From b5bb8da7d5cd64ed37773552cd7d03b849cc2640 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 20 Apr 2017 13:54:01 +0200 Subject: [PATCH 01/62] Added possibility to run script before test --- regtest/scripts/run | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/regtest/scripts/run b/regtest/scripts/run index 2a9c1f8a86..331b6d8e46 100755 --- a/regtest/scripts/run +++ b/regtest/scripts/run @@ -103,6 +103,10 @@ do fi done +if type -t plumed_regtest_before 1>/dev/null ; then + plumed_regtest_before +fi + case "$type" in (simplemd) test -f in || { From 8c21ee3c8c4202d59bab9b24d42e62bd2f733764 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Wed, 19 Apr 2017 18:15:38 +0200 Subject: [PATCH 02/62] Plumedcheck checks for astyle Travis-ci job doing cppcheck also checks whether astyle has been enforced. See #215 --- .travis.yml | 2 ++ src/maketools/codecheck | 4 ++-- src/maketools/plumedcheck | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9f6fc47e26..f4f1a4cd53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -90,6 +90,8 @@ install: - if test "$CPPCHECK" == yes ; then ./.travis/install.cppcheck $CPPCHECK_VERSION ; fi # for plumedcheck I need latest gawk - if test "$CPPCHECK" == yes ; then ./.travis/install.gawk 4.1.4 ; fi +# for plumedcheck I need astyle + - if test "$CPPCHECK" == yes ; then make -j 4 -C astyle ; fi # installation of these packages takes a lot of time # we do it only when needed - if test "$PLUMED_CXX" == "mpic++" -a "$TRAVIS_OS_NAME" == "linux" ; then sudo apt-get install -y libopenmpi-dev openmpi-bin ; fi diff --git a/src/maketools/codecheck b/src/maketools/codecheck index 15b6bd2f21..7f6a67e8a7 100755 --- a/src/maketools/codecheck +++ b/src/maketools/codecheck @@ -22,9 +22,9 @@ done if [ $do_plumedcheck == true ] ; then if [ $do_local == true ] ; then - ../maketools/plumedcheck *.{h,cpp} ../../configure.ac + ../maketools/plumedcheck *.{h,cpp} ../../configure.ac --astyle=../../astyle/astyle --astyle-options=../../.astyle.options else - maketools/plumedcheck --global-check */*.{h,cpp} ../configure.ac + maketools/plumedcheck --global-check */*.{h,cpp} ../configure.ac --astyle=../astyle/astyle --astyle-options=../.astyle.options fi fi diff --git a/src/maketools/plumedcheck b/src/maketools/plumedcheck index 751a07db36..120808decb 100755 --- a/src/maketools/plumedcheck +++ b/src/maketools/plumedcheck @@ -66,6 +66,7 @@ BEGIN{ newargv[0]=ARGV[0] pre="" opt_global_check=0 + astyle="astyle" for(i=1;i " tempfile) + s=system("diff -q " FILENAME " " tempfile ">/dev/null 2>/dev/null") + if(s!=0) error("astyle","astyle not satisfied") + system("rm " tempfile) + } + } # line by line analysis @@ -526,6 +546,9 @@ END{ error("unused_has","has " has " at " plumed_definehas[has] " is not used") } } + +# remove temporary directory + system("rmdir " tmpdir); } EOF From 37fe511caa912831e45f5a90d3db607cadebdb79 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 21 Apr 2017 11:08:59 +0200 Subject: [PATCH 03/62] changelog [makedoc] --- CHANGES/v2.3.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES/v2.3.txt b/CHANGES/v2.3.txt index b8b36e4341..3ca2505ba2 100644 --- a/CHANGES/v2.3.txt +++ b/CHANGES/v2.3.txt @@ -162,5 +162,7 @@ See branch \branch{v2.3} on git repository. For developers: - plumedcheck validation has been made stricter. All the checks are now described in the developer manual. +- IMPORTANT: we started to enforce code formatting using astyle. Check the developer documentation to learn how to + take care of not-yet-formatted branches. */ From ea10126a04ec49122ffad4c1a39b9d955f8d9f87 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 21 Apr 2017 17:24:56 +0200 Subject: [PATCH 04/62] Better formatting output For a few actions that typically write long lists, I fixed the format to write only 25 fields per line. --- src/colvar/Gyration.cpp | 7 +++++-- src/generic/Group.cpp | 10 ++++++++-- src/vatom/COM.cpp | 5 ++++- src/vatom/Center.cpp | 21 +++++++++++++++------ 4 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/colvar/Gyration.cpp b/src/colvar/Gyration.cpp index 5cf35aea06..791f6a3ed8 100644 --- a/src/colvar/Gyration.cpp +++ b/src/colvar/Gyration.cpp @@ -149,10 +149,13 @@ Gyration::Gyration(const ActionOptions&ao): if(rg_type>TRACE) log<<" Bibliography "<0) { std::vector notfound; + unsigned k=0; log<<" removing these atoms from the list:"; for(unsigned i=0; iatoms.insertGroup(getLabel(),atoms); - log.printf(" list of atoms "); - for(unsigned i=0; i Date: Sat, 22 Apr 2017 18:45:05 +0200 Subject: [PATCH 05/62] Added comment on chi torsion in MOLINFO --- src/setup/MolInfo.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/setup/MolInfo.cpp b/src/setup/MolInfo.cpp index ed2ca421c0..c16a52207f 100644 --- a/src/setup/MolInfo.cpp +++ b/src/setup/MolInfo.cpp @@ -80,6 +80,9 @@ For DNA or RNA residues, the following groups are available: @v3-# @v4-# +# quadruplet corresponding to the chi torsional angle +@chi-# + # backbone, sugar, and base heavy atoms @back-# @sugar-# From d261d70d3c4709038ef8c73f3ce83e24930ac067 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Sat, 22 Apr 2017 18:53:16 +0200 Subject: [PATCH 06/62] Added comment on temporary branches --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 00d71211a1..e9033a99d9 100644 --- a/README.md +++ b/README.md @@ -110,9 +110,18 @@ To report problems found on `master` branch, use the `plumed2-git@googlegroups.c This is also the correct place for discussions about new features etc. When reporting please provide the git hash (you can obtain it with `git rev-parse HEAD`). +In addition, the repository contains a number of other branches related to specific features. +Please contact the developers that are committing on those branches before basing your work +there, since they might contain temporary work and might be rebased laster. + +For instance, branch `testdoc` is setup so as to push a test copy of the manual +and is often force pushed. + Status ------ +Below you find the status on Travis-CI for the release branches. + | Branch | Status | Supported | |:--------:|:-------------:|:--------:| | master | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=master)](https://travis-ci.org/plumed/plumed2) | yes | From f03965915d45269fcb1709884e09b3a0c4a40dfb Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Sun, 23 Apr 2017 08:28:14 +0200 Subject: [PATCH 07/62] Forgot astyle --- src/vatom/Center.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vatom/Center.cpp b/src/vatom/Center.cpp index 3f044c3a40..7e4cdd4402 100644 --- a/src/vatom/Center.cpp +++ b/src/vatom/Center.cpp @@ -110,8 +110,8 @@ Center::Center(const ActionOptions&ao): checkRead(); log.printf(" of atoms:"); for(unsigned i=0; i Date: Mon, 24 Apr 2017 11:11:12 +0200 Subject: [PATCH 08/62] Small additions in doc [makedoc] --- src/generic/Group.cpp | 1 + user-doc/Functions.txt | 38 +++++++++++++++++++++++++++++++++++++- user-doc/Misc.txt | 9 +++++---- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index 8c77fde1b7..ecd562e8ff 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -56,6 +56,7 @@ The flow is the following: - If UNIQUE is present the resuling list is sorted and duplicate elements are removed. Notice that this command just creates a shortcut, and does not imply any real calculation. +So, having a huge group defined does not slow down your calculation in any way. It is just convenient to better organize input files. Might be used in combination with the \ref INCLUDE command so as to store long group definitions in a separate file. diff --git a/user-doc/Functions.txt b/user-doc/Functions.txt index dc6aafd01b..8bf37c42db 100644 --- a/user-doc/Functions.txt +++ b/user-doc/Functions.txt @@ -3,7 +3,43 @@ When performing biased dynamics or analysing a trajectory you may wish to analyse/bias the value of some function of a set of collective variables rather than the values of the collective variables -directly. You can do this with PLUMED by using any one of the following list of functions: +directly. You can do this with PLUMED by using any one of the following list of functions. + +Notice that in many functions you should explicitly say to PLUMED whether the result +is a periodic variable or not using the keyword `PERIODIC`. +This is crucial to allow a variable to be properly based. +To know if a function is periodic +of not you should answer to the following question: + +- Can my function change with a discontinuity when I move my atoms in a continuous manner? + +In case the answer is no, than you should use `PERIODIC=NO`. In case the answer is yes, then you should +consider the following question: + +- Are the values of the function at the discontinuity always the same or do they change? + +In case the answer is that they are the same, you should use `PERIODIC=A,B` where `A` +is the smallest value and `B` is the largest value. In case the answer is that the +values at the discontinuity are not always the same, then you cannot construct a variable that +can be biased with PLUMED. Consider the following examples: + +\verbatim +t: TORSION ATOMS=1,2,3,4 +# When atoms are moved, t could jump suddenly from -pi to +pi + +c: MATHEVAL ARG=t FUNC=x*x*x PERIODIC=-31.0062766802998,31.0062766802998 +# When atoms are moved, c could jump suddenly from -pi**3 to +pi**3 + +# equivalently, we could have used: +# c: COMBINE ARG=t POWERS=3 PERIODIC=-31.0062766802998,31.0062766802998 + +# compute x/y/z components of the distance between atoms 1 and 10 +d: DISTANCE ATOMS=1,10 COMPONENTS + +# make a new variable equal to d.z but with the correct periodicity +dz: COMBINE ARG=d.z PERIODIC=-10,10 +# here we assumed the system is in a orthorhombic box with z side = 20 +\endverbatim @FUNCTION@ diff --git a/user-doc/Misc.txt b/user-doc/Misc.txt index 0ee019d269..284a2a6e9b 100644 --- a/user-doc/Misc.txt +++ b/user-doc/Misc.txt @@ -281,12 +281,13 @@ With these settings, in the first example (`DU Date: Mon, 24 Apr 2017 12:20:30 +0200 Subject: [PATCH 09/62] Update README.md [no ci] --- README.md | 117 +++++++++++++++++++++++++++--------------------------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index e9033a99d9..4a619ac319 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,57 @@ +Branches and releases +--------------------- + +Several branches and tags are stored on the git repository. + +Branches named `v2.X` correspond to release branches. + +Master branch may contain non tested features and is not expected to be used by non-developers. +It typically contains features that will be available on the next release. + +Tags named `v2.XbY` correspond to beta releases, use it with care. +Tags named `v2.X.Y` correspond to official releases, use the latest available. + +In addition, the repository contains a number of other branches related to specific features. +Please contact the developers that are committing on those branches before basing your work +there, since they might contain temporary work and might be rebased later. +For instance, branch `testdoc` is setup so as to push a test copy of the manual +and is often force pushed. + +To report problems found on beta or official releases, use the normal +[plumed-users@googlegroups.com](mailto:plumed-users@googlegroups.com) +mailing list. Please state exactly which version you are using. +To report problems found on `master` branch, use the +[plumed2-git@googlegroups.com](plumed2-git@googlegroups.com) mailing list. +This is also the correct place for discussions about new features etc. +When reporting please provide the git hash (you can obtain it with `git rev-parse HEAD`). + +Status +------ + +Below you find the status on [Travis-CI](http://travis-ci.org/plumed/plumed2) for the release branches. + +| Branch | Status | First stable release | Still supported | +|:--------:|:-------------:|:--------:|:------:| +| master | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=master)](https://travis-ci.org/plumed/plumed2) | v2.4 is expected late 2017 | / | +| v2.3 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.3)](https://travis-ci.org/plumed/plumed2) | Dec 12, 2016 | yes | +| v2.2 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.3)](https://travis-ci.org/plumed/plumed2) | Oct 13, 2015 |no | +| v2.1 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.2)](https://travis-ci.org/plumed/plumed2) | Sep 9, 2014 | no | +| v2.0 | Not available | Sep 27, 2013 | no | Content ------- - CHANGES/ : change log +Here's a description of the content of each file and directory in the root PLUMED directory. + + CHANGES : change log COPYING.LESSER : license Makefile : makefile Makefile.conf.in : template configuration makefile PEOPLE : list of authors README : this file VERSION : version file - configurations/ : template configuration files + astyle : a local version of astyle, used to format code + configurations : template configuration files configure : configuration script configure.ac : configuration script (autoconf) developer-doc : developer documentation @@ -20,30 +62,27 @@ Content regtest : regression tests, including reference results scripts : shell tools src : source code - sourceme.sh : template configuration script + sourceme.sh.in : template configuration script test : examples user-doc : user documentation vim : directory where vim syntax is generated -Install -------- - -Extensive installation instructions are in the user documentation. -Links to precompiled versions of the documentation can be found [here](http://www.plumed.org/documentation). +Required software +----------------- Required software: -* GNU make +* GNU make. * C/c++ compiler (c++11 support is required as of version 2.4). -* A modern version of the `patch` command line tool -* Support for POSIX library `dirent.h` -* `xxd` (present in most unix distributions) +* A modern version of the `patch` command line tool. +* Support for POSIX library `dirent.h`. +* `xxd` (present in most UNIX distributions). Suggested software (libraries are checked by `./configure` and enabled if available): -* Optimized blas and lapack libraries. Can be replaced by an internal version if not available. * MPI library to run parallel simulations. It should be the same library used by your MD code. -* [VMD molfile plugins](http://www.ks.uiuc.edu/Research/vmd/plugins) to read arbitrary file formats. Can be replaced by an internal version supporting a few formats if not available. +* Optimized blas and lapack libraries. They are automatically replaced by an internal version if not available. +* [VMD molfile plugins](http://www.ks.uiuc.edu/Research/vmd/plugins) to read arbitrary file formats. They are automatically replaced by an internal version supporting a few formats if not available. * [Matheval library](http://www.gnu.org/software/libmatheval) to use algebraic collective variables. * [Zlib library](http://zlib.net/) to use compressed data files. * [Xdrfile library](http://www.gromacs.org/Developer_Zone/Programming_Guide/XTC_Library) to have read/write access to gromacs @@ -56,6 +95,7 @@ Suggested software (libraries are checked by `./configure` and enabled if availa Quick compilation instructions ------------------------------ +Extensive installation instructions are in the [user documentation](http://www.plumed.org/documentation). Configure for your system ./configure --prefix=$HOME/opt @@ -74,12 +114,14 @@ The `plumed` executable should be now in your execution path plumed help -Compile the manuals (pre-compiled manual is available online): +Compile the manuals. make doc User documentation can be found at `user-doc/html/index.html`. Developer documentation can be found at `developer-doc/html/index.html`. +[Pre-compiled documentation](http://www.plumed.org/documentation) is available online, so this is only required +if you are working with a modified version of the code! Install PLUMED in `$HOME/opt` (directory should be set during `./configure`): @@ -87,47 +129,4 @@ Install PLUMED in `$HOME/opt` (directory should be set during `./configure`): make install A sample modulefile with environment variable will be placed in -`$HOME/opt/lib/plumed/src/lib/modulefile`. Path to the installed documentation can be found with command `plumed info --user-doc`. - - -Branches and releases ---------------------- - -Several branches and tags are stored on the git repository. - -Branches named `v2.X` correspond to release branches. - -Master branch may contain non tested features and is not expected to be used by non-developers. -It typically contains features that will be available on the next release. - -Tags named `v2.XbY` correspond to beta releases, use it with care. -Tags named `v2.X.Y` correspond to official releases, use the latest available. - -To report problems found on beta or official releases, use the normal `plumed-users@googlegroups.com` -mailing list. Just state exactly which version you are using. - -To report problems found on `master` branch, use the `plumed2-git@googlegroups.com` mailing list. -This is also the correct place for discussions about new features etc. -When reporting please provide the git hash (you can obtain it with `git rev-parse HEAD`). - -In addition, the repository contains a number of other branches related to specific features. -Please contact the developers that are committing on those branches before basing your work -there, since they might contain temporary work and might be rebased laster. - -For instance, branch `testdoc` is setup so as to push a test copy of the manual -and is often force pushed. - -Status ------- - -Below you find the status on Travis-CI for the release branches. - -| Branch | Status | Supported | -|:--------:|:-------------:|:--------:| -| master | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=master)](https://travis-ci.org/plumed/plumed2) | yes | -| v2.3 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.3)](https://travis-ci.org/plumed/plumed2) | yes | -| v2.2 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.3)](https://travis-ci.org/plumed/plumed2) | no | -| v2.1 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.2)](https://travis-ci.org/plumed/plumed2) | no | -| v2.0 | Not available | no | - - +`$HOME/opt/lib/plumed/src/lib/modulefile`. If you compiled your own documentation, paths to the installed documentation can be found with command `plumed info --user-doc`. From 8d7b893b4d94029911986328b635be7478200dca Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Mon, 24 Apr 2017 14:03:49 +0200 Subject: [PATCH 10/62] Better doc molinfo MOLTYPE is actually not needed in practice. --- src/core/SetupMolInfo.cpp | 2 +- src/setup/MolInfo.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/SetupMolInfo.cpp b/src/core/SetupMolInfo.cpp index 662ddfb1c4..ece94a7f09 100644 --- a/src/core/SetupMolInfo.cpp +++ b/src/core/SetupMolInfo.cpp @@ -43,7 +43,7 @@ void SetupMolInfo::registerKeywords( Keywords& keys ) { keys.add("compulsory","STRUCTURE","a file in pdb format containing a reference structure. " "This is used to defines the atoms in the various residues, chains, etc . " "For more details on the PDB file format visit http://www.wwpdb.org/docs.html"); - keys.add("compulsory","MOLTYPE","protein","what kind of molecule is contained in the pdb file"); + keys.add("compulsory","MOLTYPE","protein","what kind of molecule is contained in the pdb file - usually not needed since protein/RNA/DNA are compatible"); keys.add("atoms","CHAIN","(for masochists ( mostly Davide Branduardi ) ) The atoms involved in each of the chains of interest in the structure."); } diff --git a/src/setup/MolInfo.cpp b/src/setup/MolInfo.cpp index c16a52207f..03a0012f97 100644 --- a/src/setup/MolInfo.cpp +++ b/src/setup/MolInfo.cpp @@ -44,12 +44,13 @@ If you are using gromacs, the safest way is to use reference pdb file generated with `gmx editconf -f topol.tpr -o reference.pdb`. -Using MOLINFO with a protein's pdb extend the possibility of atoms selection using the @ special +Using MOLINFO with a protein's or nucleic acid's pdb extends the possibility of atoms selection using the @ special symbol. Providing `MOLTYPE=protein`, `MOLTYPE=rna`, or `MOLTYPE=dna` will instruct plumed to look -for known residues from these three types of molecule (so that any of these three choice -can be safely used in a RNA/protein complex). +for known residues from these three types of molecule. In other words, this is available for +historical reasons and to allow future extensions where alternative lists will be provided. +As of now, you can just ignore this keyoword. For protein residues, the following groups are available: From 0965b152e40e8829cd1a5e1037f143c698f9d653 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Mon, 24 Apr 2017 14:32:11 +0200 Subject: [PATCH 11/62] Fix in doc [makedoc] --- src/function/Target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/function/Target.cpp b/src/function/Target.cpp index 12630e43bc..5ce9124956 100644 --- a/src/function/Target.cpp +++ b/src/function/Target.cpp @@ -45,7 +45,7 @@ d(X,X') = \vert X - X' \vert where \f$ X \f$ is the instaneous values for a set of collective variables for the system and \f$ X' \f$ is the values that these self-same set of collective variables take in some reference structure provided as input. -If we call our set of collective variables \f$\{s_i\}f\$ then this CV computes: +If we call our set of collective variables \f$\{s_i\}\f$ then this CV computes: \f[ d = \sqrt{ \sum_{i=1}^N (s_i - s_i^{(ref)})^2 } From 260b7ee47d3851fe0631db6f07906311b4684584 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Mon, 24 Apr 2017 14:46:38 +0200 Subject: [PATCH 12/62] fix doc [makedoc] --- src/generic/UpdateIf.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/generic/UpdateIf.cpp b/src/generic/UpdateIf.cpp index 1db2b6cb19..2d067fcf3d 100644 --- a/src/generic/UpdateIf.cpp +++ b/src/generic/UpdateIf.cpp @@ -66,7 +66,10 @@ the solute. solute: GROUP ATOMS=1-124 coord: COORDINATION GROUPA=solute GROUPB=500 R_0=0.5 -UPDATE_IF ARG=coord LESS_THAN=0.5 +# A coordination number higher than 0.5 indicate that there is at least one +# atom of group `solute` at less than 5 A from atom number 500 + +UPDATE_IF ARG=coord MORE_THAN=0.5 DUMPATOMS ATOMS=solute,500 FILE=output.xyz UPDATE_IF ARG=coord END \endverbatim From f34c36a163997589ca836ab71e22a99a2aa5d1e6 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Mon, 24 Apr 2017 20:57:23 +0200 Subject: [PATCH 13/62] Update README.md [ci no] --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a619ac319..0ea2a1c501 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ Below you find the status on [Travis-CI](http://travis-ci.org/plumed/plumed2) fo |:--------:|:-------------:|:--------:|:------:| | master | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=master)](https://travis-ci.org/plumed/plumed2) | v2.4 is expected late 2017 | / | | v2.3 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.3)](https://travis-ci.org/plumed/plumed2) | Dec 12, 2016 | yes | -| v2.2 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.3)](https://travis-ci.org/plumed/plumed2) | Oct 13, 2015 |no | -| v2.1 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.2)](https://travis-ci.org/plumed/plumed2) | Sep 9, 2014 | no | +| v2.2 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.2)](https://travis-ci.org/plumed/plumed2) | Oct 13, 2015 |no | +| v2.1 | [![Build Status](https://travis-ci.org/plumed/plumed2.svg?branch=v2.1)](https://travis-ci.org/plumed/plumed2) | Sep 9, 2014 | no | | v2.0 | Not available | Sep 27, 2013 | no | Content From 0b42847dd3f2056f9be0e98947808bc3f0fbe0dc Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 20 Apr 2017 13:53:49 +0200 Subject: [PATCH 14/62] Added hybrid36 to pdb Addresses #226 --- src/tools/PDB.cpp | 323 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 323 insertions(+) diff --git a/src/tools/PDB.cpp b/src/tools/PDB.cpp index ba50805c22..f4e0d398a9 100644 --- a/src/tools/PDB.cpp +++ b/src/tools/PDB.cpp @@ -29,6 +29,318 @@ using namespace std; namespace PLMD{ +/// Tiny namespace for hybrid36 format. +/// This namespace includes freely available tools for h36 format. +/// I place them here for usage within PDB class. In case we need them +/// in other places they might be better encapsulated in a c++ class +/// and placed in a separate file. +namespace h36{ + + +/*! C port of the hy36encode() and hy36decode() functions in the + hybrid_36.py Python prototype/reference implementation. + See the Python script for more information. + + This file has no external dependencies, NOT even standard C headers. + Optionally, use hybrid_36_c.h, or simply copy the declarations + into your code. + + This file is unrestricted Open Source (cctbx.sf.net). + Please send corrections and enhancements to cctbx@cci.lbl.gov . + + See also: http://cci.lbl.gov/hybrid_36/ + + Ralf W. Grosse-Kunstleve, Feb 2007. + */ + +/* The following #include may be commented out. + It is here only to enforce consistency of the declarations + and the definitions. + */ +// #include + +/* All static functions below are implementation details + (and not accessible from other translation units). + */ + +static +const char* +digits_upper() { return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } + +static +const char* +digits_lower() { return "0123456789abcdefghijklmnopqrstuvwxyz"; } + +static +const char* +value_out_of_range() { return "value out of range."; } + +static +const char* invalid_number_literal() { return "invalid number literal."; } + +static +const char* unsupported_width() { return "unsupported width."; } + +static +void +fill_with_stars(unsigned width, char* result) +{ + while (width) { + *result++ = '*'; + width--; + } + *result = '\0'; +} + +static +void +encode_pure( + const char* digits, + unsigned digits_size, + unsigned width, + int value, + char* result) +{ + char buf[16]; + int rest; + unsigned i, j; + i = 0; + j = 0; + if (value < 0) { + j = 1; + value = -value; + } + while (1) { + rest = value / digits_size; + buf[i++] = digits[value - rest * digits_size]; + if (rest == 0) break; + value = rest; + } + if (j) buf[i++] = '-'; + for(j=i;j 127) { + *result = 0; + return invalid_number_literal(); + } + if (si == ' ') { + if (!have_non_blank) continue; + value *= digits_size; + } + else if (si == '-') { + if (have_non_blank) { + *result = 0; + return invalid_number_literal(); + } + have_non_blank = 1; + have_minus = 1; + continue; + } + else { + have_non_blank = 1; + dv = digits_values[si]; + if (dv < 0 || dv >= digits_size) { + *result = 0; + return invalid_number_literal(); + } + value *= digits_size; + value += dv; + } + } + if (have_minus) value = -value; + *result = value; + return 0; +} + +/*! hybrid-36 encoder: converts integer value to string result + + width: must be 4 (e.g. for residue sequence numbers) + or 5 (e.g. for atom serial numbers) + + value: integer value to be converted + + result: pointer to char array of size width+1 or greater + on return result is null-terminated + + return value: pointer to error message, if any, + or 0 on success + + Example usage (from C++): + char result[4+1]; + const char* errmsg = hy36encode(4, 12345, result); + if (errmsg) throw std::runtime_error(errmsg); + */ +const char* +hy36encode(unsigned width, int value, char* result) +{ + int i = value; + if (width == 4U) { + if (i >= -999) { + if (i < 10000) { + encode_pure(digits_upper(), 10U, 4U, i, result); + return 0; + } + i -= 10000; + if (i < 1213056 /* 26*36**3 */) { + i += 466560 /* 10*36**3 */; + encode_pure(digits_upper(), 36U, 0U, i, result); + return 0; + } + i -= 1213056; + if (i < 1213056) { + i += 466560; + encode_pure(digits_lower(), 36U, 0U, i, result); + return 0; + } + } + } + else if (width == 5U) { + if (i >= -9999) { + if (i < 100000) { + encode_pure(digits_upper(), 10U, 5U, i, result); + return 0; + } + i -= 100000; + if (i < 43670016 /* 26*36**4 */) { + i += 16796160 /* 10*36**4 */; + encode_pure(digits_upper(), 36U, 0U, i, result); + return 0; + } + i -= 43670016; + if (i < 43670016) { + i += 16796160; + encode_pure(digits_lower(), 36U, 0U, i, result); + return 0; + } + } + } + else { + fill_with_stars(width, result); + return unsupported_width(); + } + fill_with_stars(width, result); + return value_out_of_range(); +} + +/*! hybrid-36 decoder: converts string s to integer result + + width: must be 4 (e.g. for residue sequence numbers) + or 5 (e.g. for atom serial numbers) + + s: string to be converted + does not have to be null-terminated + + s_size: size of s + must be equal to width, or an error message is + returned otherwise + + result: integer holding the conversion result + + return value: pointer to error message, if any, + or 0 on success + + Example usage (from C++): + int result; + const char* errmsg = hy36decode(width, "A1T5", 4, &result); + if (errmsg) throw std::runtime_error(errmsg); + */ +const char* +hy36decode(unsigned width, const char* s, unsigned s_size, int* result) +{ + static int first_call = 1; + static int digits_values_upper[128U]; + static int digits_values_lower[128U]; + static const char* + ie_range = "internal error hy36decode: integer value out of range."; + unsigned i; + int di; + const char* errmsg; + if (first_call) { + first_call = 0; + for(i=0;i<128U;i++) digits_values_upper[i] = -1; + for(i=0;i<128U;i++) digits_values_lower[i] = -1; + for(i=0;i<36U;i++) { + di = digits_upper()[i]; + if (di < 0 || di > 127) { + *result = 0; + return ie_range; + } + digits_values_upper[di] = i; + } + for(i=0;i<36U;i++) { + di = digits_lower()[i]; + if (di < 0 || di > 127) { + *result = 0; + return ie_range; + } + digits_values_lower[di] = i; + } + } + if (s_size == width) { + di = s[0]; + if (di >= 0 && di <= 127) { + if (digits_values_upper[di] >= 10) { + errmsg = decode_pure(digits_values_upper, 36U, s, s_size, result); + if (errmsg == 0) { + /* result - 10*36**(width-1) + 10**width */ + if (width == 4U) (*result) -= 456560; + else if (width == 5U) (*result) -= 16696160; + else { + *result = 0; + return unsupported_width(); + } + return 0; + } + } + else if (digits_values_lower[di] >= 10) { + errmsg = decode_pure(digits_values_lower, 36U, s, s_size, result); + if (errmsg == 0) { + /* result + 16*36**(width-1) + 10**width */ + if (width == 4U) (*result) += 756496; + else if (width == 5U) (*result) += 26973856; + else { + *result = 0; + return unsupported_width(); + } + return 0; + } + } + else { + errmsg = decode_pure(digits_values_upper, 10U, s, s_size, result); + if (errmsg) return errmsg; + if (!(width == 4U || width == 5U)) { + *result = 0; + return unsupported_width(); + } + return 0; + } + } + } + *result = 0; + return invalid_number_literal(); +} + +} + unsigned PDB::getNumberOfAtomBlocks()const{ return block_ends.size(); } @@ -123,6 +435,17 @@ bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale){ double o,b; Vector p; Tools::convert(serial,a); + + { + int result; + const char* errmsg = h36::hy36decode(5, serial.c_str(),5, &result); + if(errmsg){ + std::string msg(errmsg); + plumed_merror(msg); + } + a.setSerial(result); + } + Tools::convert(resnum,resno); Tools::convert(occ,o); Tools::convert(bet,b); From e7c9e02d8aaf9ca21b317fd95b70f369aae3afef Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 20 Apr 2017 13:54:29 +0200 Subject: [PATCH 15/62] Regtest Addresses #226 --- regtest/basic/rt-fix-226/Makefile | 1 + regtest/basic/rt-fix-226/config | 14 ++++++++++++++ regtest/basic/rt-fix-226/plumed.dat | 2 ++ regtest/basic/rt-fix-226/ref.pdb | 3 +++ regtest/basic/rt-fix-226/rmsd.reference | 2 ++ 5 files changed, 22 insertions(+) create mode 100644 regtest/basic/rt-fix-226/Makefile create mode 100644 regtest/basic/rt-fix-226/config create mode 100644 regtest/basic/rt-fix-226/plumed.dat create mode 100644 regtest/basic/rt-fix-226/ref.pdb create mode 100644 regtest/basic/rt-fix-226/rmsd.reference diff --git a/regtest/basic/rt-fix-226/Makefile b/regtest/basic/rt-fix-226/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/basic/rt-fix-226/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/basic/rt-fix-226/config b/regtest/basic/rt-fix-226/config new file mode 100644 index 0000000000..8ea8b40f56 --- /dev/null +++ b/regtest/basic/rt-fix-226/config @@ -0,0 +1,14 @@ +type=driver +arg="--plumed plumed.dat --ixyz traj.xyz --length-units=A" + +# this is to avoid storing a huge traj file +# just to have >100k atoms +function plumed_regtest_before(){ + awk 'BEGIN{ + n=100010; + print n + print 0,0,0 + for(i=1;i<=n;i++) print "Ar",i*0.001,i*0.001,i*0.001 + }' > traj.xyz +} + diff --git a/regtest/basic/rt-fix-226/plumed.dat b/regtest/basic/rt-fix-226/plumed.dat new file mode 100644 index 0000000000..92f54ad8e9 --- /dev/null +++ b/regtest/basic/rt-fix-226/plumed.dat @@ -0,0 +1,2 @@ +r: RMSD REFERENCE=ref.pdb TYPE=SIMPLE +PRINT ARG=r FILE=rmsd diff --git a/regtest/basic/rt-fix-226/ref.pdb b/regtest/basic/rt-fix-226/ref.pdb new file mode 100644 index 0000000000..e34b6c36ca --- /dev/null +++ b/regtest/basic/rt-fix-226/ref.pdb @@ -0,0 +1,3 @@ +ATOM 1 A XXX 2 0.001 0.001 0.001 1.00 1.00 +ATOM A0000 A XXX 2 100.000 100.000 100.000 1.00 1.00 +ATOM A0001 A XXX 2 100.001 100.001 100.001 1.00 1.00 diff --git a/regtest/basic/rt-fix-226/rmsd.reference b/regtest/basic/rt-fix-226/rmsd.reference new file mode 100644 index 0000000000..9752c803a8 --- /dev/null +++ b/regtest/basic/rt-fix-226/rmsd.reference @@ -0,0 +1,2 @@ +#! FIELDS time r + 0.000000 0.000000 From 9ac5e191b8ee00979e13443050b756fcec566b25 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Tue, 25 Apr 2017 20:23:23 +0200 Subject: [PATCH 16/62] astyle --- src/adjmat/ActionWithInputMatrix.cpp | 116 +- src/adjmat/ActionWithInputMatrix.h | 2 +- src/adjmat/AdjacencyMatrixBase.cpp | 190 +- src/adjmat/AdjacencyMatrixBase.h | 24 +- src/adjmat/AdjacencyMatrixVessel.cpp | 86 +- src/adjmat/AdjacencyMatrixVessel.h | 10 +- src/adjmat/AlignedMatrixBase.cpp | 80 +- src/adjmat/ClusterAnalysisBase.cpp | 24 +- src/adjmat/ClusterAnalysisBase.h | 2 +- src/adjmat/ClusterDiameter.cpp | 66 +- src/adjmat/ClusterDistribution.cpp | 116 +- src/adjmat/ClusterProperties.cpp | 72 +- src/adjmat/ClusterSize.cpp | 44 +- src/adjmat/ClusterWithSurface.cpp | 80 +- src/adjmat/ClusteringBase.cpp | 62 +- src/adjmat/ClusteringBase.h | 8 +- src/adjmat/ContactAlignedMatrix.cpp | 86 +- src/adjmat/ContactMatrix.cpp | 48 +- src/adjmat/DFSClustering.cpp | 104 +- src/adjmat/DumpGraph.cpp | 72 +- src/adjmat/HbondMatrix.cpp | 142 +- src/adjmat/MatrixColumnSums.cpp | 64 +- src/adjmat/MatrixRowSums.cpp | 46 +- src/adjmat/OutputCluster.cpp | 172 +- src/adjmat/SMACMatrix.cpp | 102 +- src/adjmat/Sprint.cpp | 226 +- src/adjmat/TopologyMatrix.cpp | 254 +- src/analysis/Analysis.cpp | 310 +-- src/analysis/Analysis.h | 28 +- src/analysis/AnalysisWithLandmarks.cpp | 32 +- src/analysis/AnalysisWithLandmarks.h | 8 +- src/analysis/Average.cpp | 78 +- src/analysis/AverageVessel.cpp | 20 +- src/analysis/AverageVessel.h | 16 +- .../ClassicalMultiDimensionalScaling.cpp | 122 +- src/analysis/ClassicalScaling.cpp | 50 +- src/analysis/Commit.cpp | 80 +- src/analysis/Histogram.cpp | 520 ++-- src/analysis/LandmarkRegister.cpp | 28 +- src/analysis/LandmarkRegister.h | 6 +- src/analysis/LandmarkSelectionBase.cpp | 82 +- src/analysis/LandmarkSelectionBase.h | 24 +- src/analysis/PCA.cpp | 156 +- src/analysis/SelectAllFrames.cpp | 6 +- src/bias/ABMD.cpp | 60 +- src/bias/Bias.cpp | 44 +- src/bias/Bias.h | 14 +- src/bias/BiasValue.cpp | 40 +- src/bias/ExtendedLagrangian.cpp | 88 +- src/bias/External.cpp | 50 +- src/bias/LWalls.cpp | 52 +- src/bias/MetaD.cpp | 754 +++--- src/bias/Metainference.cpp | 234 +- src/bias/MovingRestraint.cpp | 106 +- src/bias/PBMetaD.cpp | 1038 ++++---- src/bias/Restraint.cpp | 44 +- src/bias/ReweightBase.cpp | 22 +- src/bias/ReweightBase.h | 12 +- src/bias/ReweightBias.cpp | 24 +- src/bias/ReweightMetad.cpp | 22 +- src/bias/ReweightTemperature.cpp | 64 +- src/bias/UWalls.cpp | 48 +- src/cltools/CLTool.h | 6 +- src/cltools/Driver.cpp | 948 ++++---- src/cltools/DriverDouble.cpp | 2 +- src/cltools/DriverFloat.cpp | 4 +- src/cltools/GenTemplate.cpp | 44 +- src/cltools/Info.cpp | 50 +- src/cltools/Manual.cpp | 44 +- src/cltools/SimpleMD.cpp | 774 +++--- src/cltools/SumHills.cpp | 633 ++--- src/cltools/kT.cpp | 28 +- src/colvar/Angle.cpp | 22 +- src/colvar/CS2Backbone.cpp | 773 +++--- src/colvar/Cell.cpp | 20 +- src/colvar/Colvar.h | 6 +- src/colvar/Constant.cpp | 26 +- src/colvar/ContactMap.cpp | 292 +-- src/colvar/Coordination.cpp | 28 +- src/colvar/CoordinationBase.cpp | 188 +- src/colvar/CoordinationBase.h | 6 +- src/colvar/DHEnergy.cpp | 68 +- src/colvar/DRMSD.cpp | 76 +- src/colvar/Dimer.cpp | 375 +-- src/colvar/Dipole.cpp | 104 +- src/colvar/Distance.cpp | 30 +- src/colvar/ERMSD.cpp | 82 +- src/colvar/Energy.cpp | 18 +- src/colvar/Fake.cpp | 92 +- src/colvar/FretEfficiency.cpp | 22 +- src/colvar/Gyration.cpp | 254 +- src/colvar/Implicit.cpp | 2130 ++++++++--------- src/colvar/Jcoupling.cpp | 474 ++-- src/colvar/MultiRMSD.cpp | 42 +- src/colvar/NOE.cpp | 86 +- src/colvar/PCARMSD.cpp | 186 +- src/colvar/PRE.cpp | 92 +- src/colvar/PathMSD.cpp | 30 +- src/colvar/PathMSDBase.cpp | 174 +- src/colvar/PathMSDBase.h | 44 +- src/colvar/Position.cpp | 26 +- src/colvar/PropertyMap.cpp | 84 +- src/colvar/Puckering.cpp | 330 +-- src/colvar/RDC.cpp | 108 +- src/colvar/RMSD.cpp | 80 +- src/colvar/Template.cpp | 18 +- src/colvar/Torsion.cpp | 50 +- src/colvar/Volume.cpp | 10 +- src/config/Config.h | 4 +- src/config/Config.inc.in | 81 +- src/core/Action.cpp | 136 +- src/core/Action.h | 134 +- src/core/ActionAtomistic.cpp | 208 +- src/core/ActionAtomistic.h | 60 +- src/core/ActionPilot.cpp | 22 +- src/core/ActionPilot.h | 6 +- src/core/ActionRegister.cpp | 82 +- src/core/ActionRegister.h | 8 +- src/core/ActionSet.cpp | 18 +- src/core/ActionSet.h | 14 +- src/core/ActionSetup.cpp | 6 +- src/core/ActionSetup.h | 8 +- src/core/ActionWithArguments.cpp | 390 +-- src/core/ActionWithArguments.h | 28 +- src/core/ActionWithValue.cpp | 136 +- src/core/ActionWithValue.h | 54 +- src/core/ActionWithVirtualAtom.cpp | 52 +- src/core/ActionWithVirtualAtom.h | 14 +- src/core/Atoms.cpp | 246 +- src/core/Atoms.h | 50 +- src/core/CLTool.cpp | 216 +- src/core/CLTool.h | 74 +- src/core/CLToolMain.cpp | 176 +- src/core/CLToolMain.h | 12 +- src/core/CLToolRegister.cpp | 50 +- src/core/CLToolRegister.h | 6 +- src/core/Colvar.cpp | 46 +- src/core/Colvar.h | 24 +- src/core/ExchangePatterns.cpp | 32 +- src/core/ExchangePatterns.h | 8 +- src/core/FlexibleBin.cpp | 566 ++--- src/core/FlexibleBin.h | 56 +- src/core/GREX.cpp | 24 +- src/core/GREX.h | 2 +- src/core/MDAtoms.cpp | 76 +- src/core/MDAtoms.h | 2 +- src/core/PlumedMain.cpp | 838 +++---- src/core/PlumedMain.h | 190 +- src/core/PlumedMainInitializer.cpp | 16 +- src/core/SetupMolInfo.cpp | 192 +- src/core/SetupMolInfo.h | 6 +- src/core/TargetDist.cpp | 36 +- src/core/TargetDist.h | 6 +- src/core/Value.cpp | 88 +- src/core/Value.h | 92 +- src/core/WithCmd.h | 8 +- src/crystallization/BondOrientation.cpp | 50 +- src/crystallization/CubicHarmonicBase.cpp | 140 +- src/crystallization/CubicHarmonicBase.h | 6 +- src/crystallization/Fccubic.cpp | 34 +- src/crystallization/Gradient.cpp | 108 +- src/crystallization/Gradient.h | 4 +- src/crystallization/GradientVessel.cpp | 200 +- .../InterMolecularTorsions.cpp | 126 +- src/crystallization/LocalSteinhardt.h | 36 +- src/crystallization/MoleculeOrientation.cpp | 102 +- src/crystallization/MoleculePlane.cpp | 70 +- src/crystallization/OrientationSphere.cpp | 138 +- src/crystallization/OrientationSphere.h | 4 +- src/crystallization/Q3.cpp | 44 +- src/crystallization/Q4.cpp | 42 +- src/crystallization/Q6.cpp | 42 +- src/crystallization/SMAC.cpp | 122 +- src/crystallization/SimpleCubic.cpp | 30 +- src/crystallization/Steinhardt.cpp | 182 +- src/crystallization/Tetrahedral.cpp | 76 +- src/crystallization/VectorMean.cpp | 54 +- src/crystallization/VectorMultiColvar.cpp | 62 +- src/crystallization/VectorMultiColvar.h | 14 +- src/crystallization/VectorSum.cpp | 54 +- src/eds/EDS.cpp | 1051 ++++---- src/function/Combine.cpp | 38 +- src/function/Ensemble.cpp | 104 +- src/function/FuncPathMSD.cpp | 266 +- src/function/FuncSumHills.cpp | 782 +++--- src/function/Function.cpp | 46 +- src/function/Function.h | 16 +- src/function/LocalEnsemble.cpp | 34 +- src/function/Matheval.cpp | 44 +- src/function/Piecewise.cpp | 54 +- src/function/Sort.cpp | 24 +- src/function/Stats.cpp | 54 +- src/function/Target.cpp | 52 +- src/generic/Debug.cpp | 34 +- src/generic/DumpAtoms.cpp | 88 +- src/generic/DumpDerivatives.cpp | 40 +- src/generic/DumpForces.cpp | 32 +- src/generic/DumpMassCharge.cpp | 26 +- src/generic/DumpProjections.cpp | 36 +- src/generic/EffectiveEnergyDrift.cpp | 78 +- src/generic/FitToTemplate.cpp | 166 +- src/generic/Flush.cpp | 16 +- src/generic/Group.cpp | 46 +- src/generic/Include.cpp | 12 +- src/generic/Print.cpp | 62 +- src/generic/RandomExchanges.cpp | 12 +- src/generic/Read.cpp | 178 +- src/generic/ResetCell.cpp | 80 +- src/generic/Time.cpp | 18 +- src/generic/UpdateIf.cpp | 34 +- src/generic/WholeMolecules.cpp | 70 +- src/generic/WrapAround.cpp | 32 +- src/gridtools/ActionWithGrid.cpp | 58 +- src/gridtools/ActionWithGrid.h | 2 +- src/gridtools/ActionWithInputGrid.cpp | 38 +- src/gridtools/ActionWithInputGrid.h | 8 +- src/gridtools/ActionWithIntegral.cpp | 22 +- src/gridtools/ActionWithIntegral.h | 4 +- src/gridtools/AverageOnGrid.cpp | 26 +- src/gridtools/AverageOnGrid.h | 2 +- src/gridtools/ContourFindingBase.cpp | 10 +- src/gridtools/ContourFindingBase.h | 4 +- src/gridtools/ConvertToFES.cpp | 40 +- src/gridtools/DumpCube.cpp | 50 +- src/gridtools/DumpGrid.cpp | 108 +- src/gridtools/FindContour.cpp | 158 +- src/gridtools/FindContourSurface.cpp | 234 +- src/gridtools/FindSphericalContour.cpp | 78 +- src/gridtools/FourierTransform.cpp | 254 +- src/gridtools/GridPrintingBase.cpp | 28 +- src/gridtools/GridPrintingBase.h | 4 +- src/gridtools/GridToXYZ.cpp | 52 +- src/gridtools/GridVessel.cpp | 366 +-- src/gridtools/GridVessel.h | 168 +- src/gridtools/HistogramOnGrid.cpp | 252 +- src/gridtools/HistogramOnGrid.h | 2 +- src/gridtools/IntegrateGrid.cpp | 6 +- src/gridtools/InterpolateGrid.cpp | 44 +- src/main/main.cpp | 6 +- src/manyrestraints/LWalls.cpp | 26 +- src/manyrestraints/ManyRestraintsBase.cpp | 34 +- src/manyrestraints/ManyRestraintsBase.h | 26 +- src/manyrestraints/UWalls.cpp | 28 +- src/mapping/Mapping.cpp | 204 +- src/mapping/Mapping.h | 32 +- src/mapping/PCAVars.cpp | 316 +-- src/mapping/Path.cpp | 68 +- src/mapping/PathBase.cpp | 30 +- src/mapping/PathBase.h | 4 +- src/mapping/PathReparameterization.cpp | 148 +- src/mapping/PathReparameterization.h | 2 +- src/mapping/PathTools.cpp | 292 +-- src/mapping/PropertyMap.cpp | 32 +- src/mapping/SpathVessel.cpp | 28 +- src/mapping/TrigonometricPathVessel.cpp | 210 +- src/mapping/TrigonometricPathVessel.h | 4 +- src/mapping/ZpathVessel.cpp | 16 +- src/multicolvar/ActionVolume.cpp | 38 +- src/multicolvar/ActionVolume.h | 10 +- src/multicolvar/AlphaBeta.cpp | 70 +- src/multicolvar/Angles.cpp | 116 +- src/multicolvar/AtomValuePack.cpp | 76 +- src/multicolvar/AtomValuePack.h | 56 +- src/multicolvar/Bridge.cpp | 90 +- .../BridgedMultiColvarFunction.cpp | 62 +- src/multicolvar/BridgedMultiColvarFunction.h | 38 +- src/multicolvar/CatomPack.cpp | 6 +- src/multicolvar/CatomPack.h | 14 +- src/multicolvar/CenterOfMultiColvar.cpp | 166 +- src/multicolvar/CoordinationNumbers.cpp | 70 +- src/multicolvar/Density.cpp | 34 +- src/multicolvar/DihedralCorrelation.cpp | 36 +- src/multicolvar/DistanceFromContour.cpp | 240 +- src/multicolvar/Distances.cpp | 124 +- src/multicolvar/DumpMultiColvar.cpp | 52 +- src/multicolvar/FilterBetween.cpp | 78 +- src/multicolvar/FilterLessThan.cpp | 58 +- src/multicolvar/FilterMoreThan.cpp | 62 +- src/multicolvar/InPlaneDistances.cpp | 74 +- src/multicolvar/LocalAverage.cpp | 238 +- src/multicolvar/MultiColvarBase.cpp | 1388 +++++------ src/multicolvar/MultiColvarBase.h | 62 +- src/multicolvar/MultiColvarCombine.cpp | 40 +- src/multicolvar/MultiColvarDensity.cpp | 216 +- src/multicolvar/MultiColvarFilter.cpp | 58 +- src/multicolvar/MultiColvarFilter.h | 2 +- src/multicolvar/MultiColvarProduct.cpp | 38 +- src/multicolvar/NumberOfLinks.cpp | 88 +- src/multicolvar/Torsions.cpp | 36 +- src/multicolvar/VolumeAround.cpp | 60 +- src/multicolvar/VolumeCavity.cpp | 218 +- src/multicolvar/VolumeGradientBase.cpp | 164 +- src/multicolvar/VolumeGradientBase.h | 36 +- src/multicolvar/VolumeInCylinder.cpp | 66 +- src/multicolvar/VolumeInSphere.cpp | 38 +- src/multicolvar/VolumeTetrapore.cpp | 226 +- src/multicolvar/XAngle.cpp | 76 +- src/multicolvar/XDistances.cpp | 110 +- src/multicolvar/XYDistances.cpp | 98 +- src/multicolvar/XYTorsion.cpp | 118 +- src/reference/ArgumentOnlyDistance.cpp | 10 +- src/reference/ArgumentOnlyDistance.h | 4 +- src/reference/DRMSD.cpp | 90 +- src/reference/DRMSD.h | 4 +- src/reference/Direction.cpp | 30 +- src/reference/Direction.h | 10 +- src/reference/DotProductDistance.cpp | 12 +- src/reference/EuclideanDistance.cpp | 4 +- src/reference/FakeFrame.h | 8 +- src/reference/IntermolecularDRMSD.cpp | 30 +- src/reference/IntramolecularDRMSD.cpp | 26 +- src/reference/MahalanobisDistance.cpp | 4 +- src/reference/MetricRegister.cpp | 18 +- src/reference/MetricRegister.h | 34 +- src/reference/MultiDomainRMSD.cpp | 242 +- src/reference/MultiDomainRMSD.h | 4 +- src/reference/MultiReferenceBase.cpp | 52 +- src/reference/MultiReferenceBase.h | 34 +- src/reference/NormalizedEuclideanDistance.cpp | 4 +- src/reference/OptimalRMSD.cpp | 74 +- src/reference/PointWiseMapping.cpp | 66 +- src/reference/PointWiseMapping.h | 18 +- src/reference/RMSDBase.cpp | 10 +- src/reference/RMSDBase.h | 2 +- src/reference/ReferenceArguments.cpp | 268 +-- src/reference/ReferenceArguments.h | 20 +- src/reference/ReferenceAtoms.cpp | 112 +- src/reference/ReferenceAtoms.h | 28 +- src/reference/ReferenceConfiguration.cpp | 128 +- src/reference/ReferenceConfiguration.h | 66 +- src/reference/ReferenceValuePack.cpp | 74 +- src/reference/ReferenceValuePack.h | 36 +- src/reference/SimpleRMSD.cpp | 36 +- src/reference/SingleDomainRMSD.cpp | 40 +- src/reference/SingleDomainRMSD.h | 6 +- src/secondarystructure/AlphaRMSD.cpp | 50 +- src/secondarystructure/AntibetaRMSD.cpp | 136 +- src/secondarystructure/ParabetaRMSD.cpp | 134 +- .../SecondaryStructureRMSD.cpp | 182 +- .../SecondaryStructureRMSD.h | 10 +- src/setup/Load.cpp | 12 +- src/setup/MolInfo.cpp | 14 +- src/setup/Restart.cpp | 12 +- src/setup/Units.cpp | 14 +- src/tools/Angle.cpp | 62 +- src/tools/Angle.h | 4 +- src/tools/AtomNumber.h | 32 +- src/tools/BiasRepresentation.cpp | 440 ++-- src/tools/BiasRepresentation.h | 122 +- src/tools/Brent1DRootSearch.h | 92 +- src/tools/Citations.cpp | 14 +- src/tools/Citations.h | 4 +- src/tools/Communicator.cpp | 88 +- src/tools/Communicator.h | 88 +- src/tools/CubicInterpolation.cpp | 251 +- src/tools/CubicInterpolation.h | 4 +- src/tools/DLLoader.cpp | 16 +- src/tools/DLLoader.h | 4 +- src/tools/DynamicList.h | 124 +- src/tools/ERMSD.cpp | 546 ++--- src/tools/ERMSD.h | 34 +- src/tools/Exception.cpp | 12 +- src/tools/Exception.h | 10 +- src/tools/FileBase.cpp | 34 +- src/tools/FileBase.h | 14 +- src/tools/Grid.cpp | 1370 +++++------ src/tools/Grid.h | 290 +-- src/tools/HistogramBead.cpp | 200 +- src/tools/HistogramBead.h | 74 +- src/tools/IFile.cpp | 126 +- src/tools/IFile.h | 26 +- src/tools/KernelFunctions.cpp | 304 +-- src/tools/KernelFunctions.h | 22 +- src/tools/Keywords.cpp | 766 +++--- src/tools/Keywords.h | 22 +- src/tools/LatticeReduction.cpp | 74 +- src/tools/LatticeReduction.h | 6 +- src/tools/LinkCells.cpp | 104 +- src/tools/LinkCells.h | 4 +- src/tools/Log.h | 2 +- src/tools/LoopUnroller.h | 32 +- src/tools/Matrix.h | 520 ++-- src/tools/MatrixSquareBracketsAccess.h | 28 +- src/tools/Minimise1DBrent.h | 212 +- src/tools/MinimiseBase.h | 34 +- src/tools/MolDataClass.cpp | 300 +-- src/tools/MolDataClass.h | 6 +- src/tools/MultiValue.cpp | 86 +- src/tools/MultiValue.h | 46 +- src/tools/NeighborList.cpp | 176 +- src/tools/NeighborList.h | 16 +- src/tools/OFile.cpp | 210 +- src/tools/OFile.h | 38 +- src/tools/OpenMP.cpp | 6 +- src/tools/OpenMP.h | 20 +- src/tools/PDB.cpp | 194 +- src/tools/PDB.h | 16 +- src/tools/Pbc.cpp | 160 +- src/tools/Pbc.h | 8 +- src/tools/RMSD.cpp | 1226 +++++----- src/tools/RMSD.h | 406 ++-- src/tools/Random.cpp | 162 +- src/tools/Random.h | 66 +- src/tools/RootFindingBase.h | 8 +- src/tools/Stopwatch.cpp | 28 +- src/tools/Stopwatch.h | 12 +- src/tools/SwitchingFunction.cpp | 218 +- src/tools/SwitchingFunction.h | 6 +- src/tools/Tensor.cpp | 6 +- src/tools/Tensor.h | 176 +- src/tools/Tools.cpp | 186 +- src/tools/Tools.h | 62 +- src/tools/Torsion.cpp | 20 +- src/tools/Torsion.h | 4 +- src/tools/Units.cpp | 46 +- src/tools/Units.h | 24 +- src/tools/Vector.cpp | 10 +- src/tools/Vector.h | 72 +- src/vatom/ActionWithVirtualAtom.h | 6 +- src/vatom/COM.cpp | 30 +- src/vatom/Center.cpp | 38 +- src/vatom/FixedAtom.cpp | 10 +- src/vatom/Ghost.cpp | 84 +- src/vesselbase/ActionWithAveraging.cpp | 102 +- src/vesselbase/ActionWithAveraging.h | 18 +- src/vesselbase/ActionWithInputVessel.cpp | 48 +- src/vesselbase/ActionWithInputVessel.h | 8 +- src/vesselbase/ActionWithVessel.cpp | 286 +-- src/vesselbase/ActionWithVessel.h | 40 +- src/vesselbase/AltMin.cpp | 22 +- src/vesselbase/AveragingVessel.cpp | 20 +- src/vesselbase/AveragingVessel.h | 54 +- src/vesselbase/Between.cpp | 34 +- src/vesselbase/BridgeVessel.cpp | 148 +- src/vesselbase/BridgeVessel.h | 10 +- src/vesselbase/FunctionVessel.cpp | 74 +- src/vesselbase/FunctionVessel.h | 4 +- src/vesselbase/Highest.cpp | 14 +- src/vesselbase/Histogram.cpp | 16 +- src/vesselbase/LessThan.cpp | 28 +- src/vesselbase/LessThan.h | 4 +- src/vesselbase/Lowest.cpp | 14 +- src/vesselbase/Max.cpp | 20 +- src/vesselbase/Mean.cpp | 10 +- src/vesselbase/Min.cpp | 22 +- src/vesselbase/Moments.cpp | 156 +- src/vesselbase/MoreThan.cpp | 22 +- src/vesselbase/OrderingVessel.cpp | 40 +- src/vesselbase/OrderingVessel.h | 4 +- src/vesselbase/ShortcutVessel.cpp | 14 +- src/vesselbase/ShortcutVessel.h | 12 +- src/vesselbase/StoreDataVessel.cpp | 144 +- src/vesselbase/StoreDataVessel.h | 66 +- src/vesselbase/Sum.cpp | 12 +- src/vesselbase/ValueVessel.cpp | 44 +- src/vesselbase/ValueVessel.h | 8 +- src/vesselbase/Vessel.cpp | 114 +- src/vesselbase/Vessel.h | 80 +- src/vesselbase/VesselRegister.cpp | 34 +- src/vesselbase/VesselRegister.h | 6 +- src/wrapper/Plumed.c | 158 +- src/wrapper/Plumed.h | 250 +- 462 files changed, 24372 insertions(+), 24348 deletions(-) diff --git a/src/adjmat/ActionWithInputMatrix.cpp b/src/adjmat/ActionWithInputMatrix.cpp index c0acb31959..5aed42c85b 100644 --- a/src/adjmat/ActionWithInputMatrix.cpp +++ b/src/adjmat/ActionWithInputMatrix.cpp @@ -29,43 +29,43 @@ namespace PLMD { namespace adjmat { -void ActionWithInputMatrix::registerKeywords( Keywords& keys ){ - MultiColvarBase::registerKeywords( keys ); - keys.add("compulsory","MATRIX","the action that calcualtes the adjacency matrix vessel we would like to analyse"); +void ActionWithInputMatrix::registerKeywords( Keywords& keys ) { + MultiColvarBase::registerKeywords( keys ); + keys.add("compulsory","MATRIX","the action that calcualtes the adjacency matrix vessel we would like to analyse"); } ActionWithInputMatrix::ActionWithInputMatrix(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao), -mymatrix(NULL) + Action(ao), + MultiColvarBase(ao), + mymatrix(NULL) { - matsums=true; - if( keywords.exists("MATRIX") ){ - std::vector fake_atoms; - if( !parseMultiColvarAtomList("MATRIX",-1,fake_atoms ) ) error("unable to interpret input matrix"); - if( mybasemulticolvars.size()!=1 ) error("should be exactly one matrix input"); - - // Retrieve the adjacency matrix of interest - for(unsigned i=0;igetNumberOfVessels();++i){ - mymatrix = dynamic_cast( mybasemulticolvars[0]->getPntrToVessel(i) ); - if( mymatrix ) break ; - } - if( !mymatrix ) error( mybasemulticolvars[0]->getLabel() + " does not calculate an adjacency matrix"); - - atom_lab.resize(0); unsigned nnodes; // Delete all the atom labels that have been created - if( mymatrix->undirectedGraph() ) nnodes = (mymatrix->function)->ablocks[0].size(); - else nnodes = (mymatrix->function)->ablocks[0].size() + (mymatrix->function)->ablocks[1].size(); - for(unsigned i=0;i( 1, i ) ); + matsums=true; + if( keywords.exists("MATRIX") ) { + std::vector fake_atoms; + if( !parseMultiColvarAtomList("MATRIX",-1,fake_atoms ) ) error("unable to interpret input matrix"); + if( mybasemulticolvars.size()!=1 ) error("should be exactly one matrix input"); + + // Retrieve the adjacency matrix of interest + for(unsigned i=0; igetNumberOfVessels(); ++i) { + mymatrix = dynamic_cast( mybasemulticolvars[0]->getPntrToVessel(i) ); + if( mymatrix ) break ; + } + if( !mymatrix ) error( mybasemulticolvars[0]->getLabel() + " does not calculate an adjacency matrix"); + + atom_lab.resize(0); unsigned nnodes; // Delete all the atom labels that have been created + if( mymatrix->undirectedGraph() ) nnodes = (mymatrix->function)->ablocks[0].size(); + else nnodes = (mymatrix->function)->ablocks[0].size() + (mymatrix->function)->ablocks[1].size(); + for(unsigned i=0; i( 1, i ) ); } } unsigned ActionWithInputMatrix::getNumberOfDerivatives() { - return (mymatrix->function)->getNumberOfDerivatives(); + return (mymatrix->function)->getNumberOfDerivatives(); } unsigned ActionWithInputMatrix::getNumberOfNodes() const { - return (mymatrix->function)->ablocks[0].size(); + return (mymatrix->function)->ablocks[0].size(); } AdjacencyMatrixVessel* ActionWithInputMatrix::getAdjacencyVessel() const { @@ -73,27 +73,27 @@ AdjacencyMatrixVessel* ActionWithInputMatrix::getAdjacencyVessel() const { } AtomNumber ActionWithInputMatrix::getAbsoluteIndexOfCentralAtom(const unsigned& i) const { - return (mymatrix->function)->getAbsoluteIndexOfCentralAtom(i); + return (mymatrix->function)->getAbsoluteIndexOfCentralAtom(i); } double ActionWithInputMatrix::retrieveConnectionValue( const unsigned& i, const unsigned& j, std::vector& vals ) const { if( !mymatrix->matrixElementIsActive( i, j ) ) return 0; unsigned myelem = mymatrix->getStoreIndexFromMatrixIndices( i, j ); - + unsigned vi; double df; - mymatrix->retrieveValueWithIndex( myelem, false, vals ); + mymatrix->retrieveValueWithIndex( myelem, false, vals ); return vals[0]*vals[1]; // (mymatrix->function)->transformStoredValues( vals, vi, df ); } void ActionWithInputMatrix::getInputData( const unsigned& ind, const bool& normed, const multicolvar::AtomValuePack& myatoms, std::vector& orient0 ) const { - if( (mymatrix->function)->mybasemulticolvars.size()==0 ){ - std::vector tvals( mymatrix->getNumberOfComponents() ); orient0.assign(orient0.size(),0); - for(unsigned i=0;igetNumberOfColumns();++i){ - if( mymatrix->undirectedGraph() && ind==i ) continue; - orient0[1]+=retrieveConnectionValue( ind, i, tvals ); - } - orient0[0]=1.0; return; - } + if( (mymatrix->function)->mybasemulticolvars.size()==0 ) { + std::vector tvals( mymatrix->getNumberOfComponents() ); orient0.assign(orient0.size(),0); + for(unsigned i=0; igetNumberOfColumns(); ++i) { + if( mymatrix->undirectedGraph() && ind==i ) continue; + orient0[1]+=retrieveConnectionValue( ind, i, tvals ); + } + orient0[0]=1.0; return; + } (mymatrix->function)->getInputData( ind, normed, myatoms, orient0 ); } @@ -102,33 +102,33 @@ void ActionWithInputMatrix::addConnectionDerivatives( const unsigned& i, const u unsigned myelem = mymatrix->getStoreIndexFromMatrixIndices( i, j ); // Get derivatives and add mymatrix->retrieveDerivatives( myelem, false, myvals ); - for(unsigned jd=0;jdfunction)->mybasemulticolvars.size()==0 ){ - MultiValue& myder=mymatrix->getTemporyMultiValue(0); - if( myder.getNumberOfValues()!=2 || myder.getNumberOfDerivatives()!=(mymatrix->function)->getNumberOfDerivatives() ){ - myder.resize( 2, (mymatrix->function)->getNumberOfDerivatives() ); - } - myder.clearAll(); - MultiValue myvals( (mymatrix->function)->getNumberOfQuantities(), (mymatrix->function)->getNumberOfDerivatives() ); - for(unsigned i=0;igetNumberOfColumns();++i){ - if( mymatrix->undirectedGraph() && ind==i ) continue; - addConnectionDerivatives( ind, i, myvals, myder ); - } - myder.updateDynamicList(); return myder; - } - return (mymatrix->function)->getInputDerivatives( ind, normed, myatoms ); + if( (mymatrix->function)->mybasemulticolvars.size()==0 ) { + MultiValue& myder=mymatrix->getTemporyMultiValue(0); + if( myder.getNumberOfValues()!=2 || myder.getNumberOfDerivatives()!=(mymatrix->function)->getNumberOfDerivatives() ) { + myder.resize( 2, (mymatrix->function)->getNumberOfDerivatives() ); + } + myder.clearAll(); + MultiValue myvals( (mymatrix->function)->getNumberOfQuantities(), (mymatrix->function)->getNumberOfDerivatives() ); + for(unsigned i=0; igetNumberOfColumns(); ++i) { + if( mymatrix->undirectedGraph() && ind==i ) continue; + addConnectionDerivatives( ind, i, myvals, myder ); + } + myder.updateDynamicList(); return myder; + } + return (mymatrix->function)->getInputDerivatives( ind, normed, myatoms ); } unsigned ActionWithInputMatrix::getNumberOfNodeTypes() const { unsigned size = (mymatrix->function)->mybasemulticolvars.size(); if( size==0 ) return 1; - return size; + return size; } unsigned ActionWithInputMatrix::getNumberOfQuantities() const { @@ -137,13 +137,13 @@ unsigned ActionWithInputMatrix::getNumberOfQuantities() const { } unsigned ActionWithInputMatrix::getNumberOfAtomsInGroup( const unsigned& igrp ) const { - plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); - return (mymatrix->function)->mybasemulticolvars[igrp]->getFullNumberOfTasks(); + plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); + return (mymatrix->function)->mybasemulticolvars[igrp]->getFullNumberOfTasks(); } multicolvar::MultiColvarBase* ActionWithInputMatrix::getBaseMultiColvar( const unsigned& igrp ) const { - plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); - return (mymatrix->function)->mybasemulticolvars[igrp]; + plumed_dbg_assert( igrp<(mymatrix->function)->mybasemulticolvars.size() ); + return (mymatrix->function)->mybasemulticolvars[igrp]; } Vector ActionWithInputMatrix::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { diff --git a/src/adjmat/ActionWithInputMatrix.h b/src/adjmat/ActionWithInputMatrix.h index 55c2567eaa..994f5ff240 100644 --- a/src/adjmat/ActionWithInputMatrix.h +++ b/src/adjmat/ActionWithInputMatrix.h @@ -57,7 +57,7 @@ class ActionWithInputMatrix : public multicolvar::MultiColvarBase { virtual unsigned getNumberOfDerivatives(); /// Get the number of rows/cols in the adjacency matrix vessel virtual unsigned getNumberOfNodes() const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } virtual unsigned getNumberOfQuantities() const ; /// virtual AtomNumber getAbsoluteIndexOfCentralAtom(const unsigned& i) const ; diff --git a/src/adjmat/AdjacencyMatrixBase.cpp b/src/adjmat/AdjacencyMatrixBase.cpp index 4f9844f9bc..9f6cc8de7d 100644 --- a/src/adjmat/AdjacencyMatrixBase.cpp +++ b/src/adjmat/AdjacencyMatrixBase.cpp @@ -29,73 +29,73 @@ namespace PLMD { namespace adjmat { -void AdjacencyMatrixBase::registerKeywords( Keywords& keys ){ +void AdjacencyMatrixBase::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); keys.remove("LOWMEM"); keys.use("HIGHMEM"); } AdjacencyMatrixBase::AdjacencyMatrixBase(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao), -connect_id(0), -no_third_dim_accum(true), -mat(NULL) + Action(ao), + MultiColvarBase(ao), + connect_id(0), + no_third_dim_accum(true), + mat(NULL) { log<<" Bibliography "< sw; - if( !multiple ){ - sw.resize(1); parse(key,sw[0]); - if(sw[0].length()==0) error("could not find " + key + " keyword"); - } else { - std::string input; - for(int i=1;;i++){ - if( !parseNumbered(key, i, input ) ) break; - sw.push_back( input ); - } +void AdjacencyMatrixBase::parseConnectionDescriptions( const std::string& key, const bool& multiple, const unsigned& nrow_t ) { + if( getNumberOfNodeTypes()==1 || (getNumberOfNodeTypes()==2 && nrow_t==1) ) { + std::vector sw; + if( !multiple ) { + sw.resize(1); parse(key,sw[0]); + if(sw[0].length()==0) error("could not find " + key + " keyword"); + } else { + std::string input; + for(int i=1;; i++) { + if( !parseNumbered(key, i, input ) ) break; + sw.push_back( input ); } - setupConnector( connect_id, 0, 0, sw ); + } + setupConnector( connect_id, 0, 0, sw ); } else { - if( multiple ) error("keyword " + key + " does not work with multiple input strings"); - unsigned nr, nc; - if( nrow_t==0 ){ - nr=nc=getNumberOfNodeTypes(); - } else{ - nr=nrow_t; nc = getNumberOfNodeTypes() - nr; + if( multiple ) error("keyword " + key + " does not work with multiple input strings"); + unsigned nr, nc; + if( nrow_t==0 ) { + nr=nc=getNumberOfNodeTypes(); + } else { + nr=nrow_t; nc = getNumberOfNodeTypes() - nr; + } + for(unsigned i=0; i sw(1); parseNumbered(key,ibase+j+1,sw[0]); - if(sw[0].length()==0){ - std::string num; Tools::convert(ibase+j+1,num); - error("could not find " + key + num + " keyword. Need one " + key + " keyword for each distinct base-multicolvar-pair type"); - } - setupConnector( connect_id, i, j, sw ); - } + + for(unsigned j=i; j sw(1); parseNumbered(key,ibase+j+1,sw[0]); + if(sw[0].length()==0) { + std::string num; Tools::convert(ibase+j+1,num); + error("could not find " + key + num + " keyword. Need one " + key + " keyword for each distinct base-multicolvar-pair type"); + } + setupConnector( connect_id, i, j, sw ); } + } } connect_id++; } unsigned AdjacencyMatrixBase::getSizeOfInputVectors() const { - if( mybasemulticolvars.size()==0 ) return 2; + if( mybasemulticolvars.size()==0 ) return 2; unsigned nq = mybasemulticolvars[0]->getNumberOfQuantities(); - for(unsigned i=1;igetNumberOfQuantities()!=nq ) error("mismatch between vectors in base colvars"); + for(unsigned i=1; igetNumberOfQuantities()!=nq ) error("mismatch between vectors in base colvars"); } return nq; } @@ -108,69 +108,69 @@ unsigned AdjacencyMatrixBase::getNumberOfNodeTypes() const { void AdjacencyMatrixBase::retrieveTypeDimensions( unsigned& nrows, unsigned& ncols, unsigned& ntype ) const { bool allsame=(ablocks[0].size()==ablocks[1].size()); - if( allsame ){ - for(unsigned i=0;i types(1); types[0]=atom_lab[ablocks[0][0]].first; - for(unsigned i=1;i types(1); types[0]=atom_lab[ablocks[0][0]].first; + for(unsigned i=1; i types(1); types[0]=atom_lab[ablocks[0][0]].first; - for(unsigned i=1;i types(1); types[0]=atom_lab[ablocks[0][0]].first; + for(unsigned i=1; i& all_atoms ){ +void AdjacencyMatrixBase::finishMatrixSetup( const bool& symmetric, const std::vector& all_atoms ) { std::string param; if( symmetric && ablocks[0].size()==ablocks[1].size() ) param="SYMMETRIC"; - if( !symmetric ){ - bool usehbonds=( ablocks[0].size()==ablocks[1].size() ); - if( usehbonds ){ - for(unsigned i=0;i all_atoms; readTwoGroups( key0, key1, key2, all_atoms ); finishMatrixSetup( symmetric, all_atoms ); } -void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& keym, const bool& symmetric ){ +void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& keym, const bool& symmetric ) { std::vector all_atoms; readGroupKeywords( key0, key1, key2, keym, true, symmetric, all_atoms ); finishMatrixSetup( symmetric, all_atoms ); } @@ -180,14 +180,14 @@ void AdjacencyMatrixBase::readMaxThreeSpeciesMatrix( const std::string& key0, co // AtomNumber AdjacencyMatrixBase::getAbsoluteIndexOfCentralAtom(const unsigned& i) const { // plumed_dbg_assert( i myatoms; decodeIndexToAtoms( getTaskCode( myelem ), myatoms ); unsigned i=myatoms[0], j=myatoms[1]; - for(unsigned k=bookeeping(i,j).first;k& desc ) = 0; /// None of these things are allowed - bool isPeriodic(){ return false; } - Vector getCentralAtom(){ plumed_merror("cannot find central atoms for adjacency matrix actions"); Vector dum; return dum; } + bool isPeriodic() { return false; } + Vector getCentralAtom() { plumed_merror("cannot find central atoms for adjacency matrix actions"); Vector dum; return dum; } /// Get the atom number - AtomNumber getAbsoluteIndexOfCentralAtom( const unsigned& i ) const ; + AtomNumber getAbsoluteIndexOfCentralAtom( const unsigned& i ) const ; }; inline -AdjacencyMatrixVessel* AdjacencyMatrixBase::getAdjacencyVessel(){ +AdjacencyMatrixVessel* AdjacencyMatrixBase::getAdjacencyVessel() { return mat; } inline unsigned AdjacencyMatrixBase::getBaseColvarNumber( const unsigned& inum ) const { - if( atom_lab[inum].first>0 ) return atom_lab[inum].first-1; + if( atom_lab[inum].first>0 ) return atom_lab[inum].first-1; return 0; } inline AtomNumber AdjacencyMatrixBase::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const { - if( atom_lab[iatom].first>0 ){ - unsigned mmc=atom_lab[ iatom ].first - 1; - return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); + if( atom_lab[iatom].first>0 ) { + unsigned mmc=atom_lab[ iatom ].first - 1; + return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); } return ActionAtomistic::getAbsoluteIndex( atom_lab[iatom].second ); } diff --git a/src/adjmat/AdjacencyMatrixVessel.cpp b/src/adjmat/AdjacencyMatrixVessel.cpp index 6d07fc40e1..f4a62bb6db 100644 --- a/src/adjmat/AdjacencyMatrixVessel.cpp +++ b/src/adjmat/AdjacencyMatrixVessel.cpp @@ -20,20 +20,20 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "AdjacencyMatrixVessel.h" -#include "AdjacencyMatrixBase.h" +#include "AdjacencyMatrixBase.h" #include "vesselbase/ActionWithVessel.h" namespace PLMD { namespace adjmat { -void AdjacencyMatrixVessel::registerKeywords( Keywords& keys ){ +void AdjacencyMatrixVessel::registerKeywords( Keywords& keys ) { StoreDataVessel::registerKeywords(keys); keys.addFlag("SYMMETRIC",false,"is the matrix symmetric"); keys.addFlag("HBONDS",false,"can we think of the matrix as a undirected graph"); } AdjacencyMatrixVessel::AdjacencyMatrixVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da) + StoreDataVessel(da) { function=dynamic_cast( getAction() ); plumed_assert( function ); @@ -65,13 +65,13 @@ bool AdjacencyMatrixVessel::matrixElementIsActive( const unsigned& ielem, const unsigned AdjacencyMatrixVessel::getStoreIndexFromMatrixIndices( const unsigned& ielem, const unsigned& jelem ) const { if( !symmetric && !hbonds ) return (function->ablocks[1].size())*ielem + jelem; - if( !symmetric ){ - plumed_dbg_assert( ielem!=jelem ); - if( jelemablocks[1].size()-1)*ielem + jelem; - return (function->ablocks[1].size()-1)*ielem + jelem - 1; + if( !symmetric ) { + plumed_dbg_assert( ielem!=jelem ); + if( jelemablocks[1].size()-1)*ielem + jelem; + return (function->ablocks[1].size()-1)*ielem + jelem - 1; } if( ielem>jelem ) return 0.5*ielem*(ielem-1)+jelem; - return 0.5*jelem*(jelem-1) + ielem; + return 0.5*jelem*(jelem-1) + ielem; } AdjacencyMatrixBase* AdjacencyMatrixVessel::getMatrixAction() { @@ -79,61 +79,61 @@ AdjacencyMatrixBase* AdjacencyMatrixVessel::getMatrixAction() { } void AdjacencyMatrixVessel::getMatrixIndices( const unsigned& code, unsigned& i, unsigned& j ) const { - std::vector myatoms; function->decodeIndexToAtoms( function->getTaskCode(code), myatoms ); - i=myatoms[0]; j=myatoms[1]; - if( !undirectedGraph() ) j -= function->ablocks[0].size(); // Have to remove number of columns as returns number in ablocks[1] + std::vector myatoms; function->decodeIndexToAtoms( function->getTaskCode(code), myatoms ); + i=myatoms[0]; j=myatoms[1]; + if( !undirectedGraph() ) j -= function->ablocks[0].size(); // Have to remove number of columns as returns number in ablocks[1] } -void AdjacencyMatrixVessel::retrieveMatrix( DynamicList& myactive_elements, Matrix& mymatrix ){ +void AdjacencyMatrixVessel::retrieveMatrix( DynamicList& myactive_elements, Matrix& mymatrix ) { unsigned vin; double df; - myactive_elements.deactivateAll(); std::vector vals( getNumberOfComponents() ); - for(unsigned i=0;i vals( getNumberOfComponents() ); + for(unsigned i=0; igetPositionInFullTaskList(i), k, j ); + myactive_elements.activate(i); + unsigned j, k; getMatrixIndices( function->getPositionInFullTaskList(i), k, j ); - if( symmetric ) mymatrix(k,j)=mymatrix(j,k)=vals[0]*vals[1]; - else mymatrix(k,j)=vals[0]*vals[1]; + if( symmetric ) mymatrix(k,j)=mymatrix(j,k)=vals[0]*vals[1]; + else mymatrix(k,j)=vals[0]*vals[1]; } - myactive_elements.updateActiveMembers(); + myactive_elements.updateActiveMembers(); } -void AdjacencyMatrixVessel::retrieveAdjacencyLists( std::vector& nneigh, Matrix& adj_list ){ +void AdjacencyMatrixVessel::retrieveAdjacencyLists( std::vector& nneigh, Matrix& adj_list ) { plumed_dbg_assert( undirectedGraph() ); // Currently everything has zero neighbors - for(unsigned i=0;i myvals( getNumberOfComponents() ); - for(unsigned i=0;igetPositionInFullTaskList(i), k, j ); - - if( nneigh[j]>=adj_list.ncols() || nneigh[k]>=adj_list.ncols() ) error("adjacency lists are not large enough, increase maxconnections"); - // Store if atoms are connected - // unsigned j, k; getMatrixIndices( i, k, j ); - adj_list(k,nneigh[k])=j; nneigh[k]++; - adj_list(j,nneigh[j])=k; nneigh[j]++; + for(unsigned i=0; igetPositionInFullTaskList(i), k, j ); + + if( nneigh[j]>=adj_list.ncols() || nneigh[k]>=adj_list.ncols() ) error("adjacency lists are not large enough, increase maxconnections"); + // Store if atoms are connected + // unsigned j, k; getMatrixIndices( i, k, j ); + adj_list(k,nneigh[k])=j; nneigh[k]++; + adj_list(j,nneigh[j])=k; nneigh[j]++; } } -void AdjacencyMatrixVessel::retrieveEdgeList( unsigned& nedge, std::vector >& edge_list ){ +void AdjacencyMatrixVessel::retrieveEdgeList( unsigned& nedge, std::vector >& edge_list ) { plumed_dbg_assert( undirectedGraph() ); nedge=0; std::vector myvals( getNumberOfComponents() ); if( getNumberOfStoredValues()>edge_list.size() ) error("adjacency lists are not large enough, increase maxconnections"); - for(unsigned i=0;igetPositionInFullTaskList(i), edge_list[nedge].first, edge_list[nedge].second ); - nedge++; + getMatrixIndices( function->getPositionInFullTaskList(i), edge_list[nedge].first, edge_list[nedge].second ); + nedge++; } } @@ -141,7 +141,7 @@ bool AdjacencyMatrixVessel::nodesAreConnected( const unsigned& iatom, const unsi if( !matrixElementIsActive( iatom, jatom ) ) return false; unsigned ind=getStoreIndexFromMatrixIndices( iatom, jatom ); - std::vector myvals( getNumberOfComponents() ); + std::vector myvals( getNumberOfComponents() ); retrieveValueWithIndex( ind, false, myvals ); return ( myvals[0]>epsilon && myvals[1]>epsilon ); } diff --git a/src/adjmat/AdjacencyMatrixVessel.h b/src/adjmat/AdjacencyMatrixVessel.h index 637208bd4e..7e1ef1586c 100644 --- a/src/adjmat/AdjacencyMatrixVessel.h +++ b/src/adjmat/AdjacencyMatrixVessel.h @@ -22,7 +22,7 @@ #ifndef __PLUMED_adjmat_AdjacencyMatrixVessel_h #define __PLUMED_adjmat_AdjacencyMatrixVessel_h -#include "vesselbase/StoreDataVessel.h" +#include "vesselbase/StoreDataVessel.h" #include "multicolvar/MultiColvarBase.h" namespace PLMD { @@ -30,15 +30,15 @@ namespace adjmat { class AdjacencyMatrixBase; -// One school of thought would have it that it makes more sense to +// One school of thought would have it that it makes more sense to // have the functionality contained within this class in AdjacencyMatrixBase // I have not done this as I can inherit many useful things from StoreDataVessel // If I put this functionality within AdjacencyMatrixBase I would have to reimplement // these features. class AdjacencyMatrixVessel : public vesselbase::StoreDataVessel { -friend class AdjacencyMatrixBase; -friend class ActionWithInputMatrix; + friend class AdjacencyMatrixBase; + friend class ActionWithInputMatrix; private: /// Pointer to underlying action AdjacencyMatrixBase* function; @@ -63,7 +63,7 @@ friend class ActionWithInputMatrix; /// void getMatrixIndices( const unsigned& code, unsigned& i, unsigned& j ) const ; /// Can we think of the matrix as an undirected graph - bool undirectedGraph() const ; + bool undirectedGraph() const ; /// Is the matrix symmetric bool isSymmetric() const ; /// Get the number of rows diff --git a/src/adjmat/AlignedMatrixBase.cpp b/src/adjmat/AlignedMatrixBase.cpp index 28fd47c936..408cf8c736 100644 --- a/src/adjmat/AlignedMatrixBase.cpp +++ b/src/adjmat/AlignedMatrixBase.cpp @@ -27,59 +27,59 @@ namespace PLMD { namespace adjmat { -void AlignedMatrixBase::registerKeywords( Keywords& keys ){ +void AlignedMatrixBase::registerKeywords( Keywords& keys ) { AdjacencyMatrixBase::registerKeywords( keys ); keys.add("atoms","ATOMS","The list of molecules for which you would like to calculate the contact matrix. The molecules involved must " - "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " - "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " - "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); + "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " + "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " + "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); keys.add("atoms-1","ATOMSA","The list of molecules that you would like to use for the rows of the contact matrix. The molecules involved must " - "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " - "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " - "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); + "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " + "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " + "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); keys.add("atoms-1","ATOMSB","The list of molecules that you would like to use for the columns of the contact matrix. The molecules involved must " - "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " - "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " - "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); + "have an orientation so your list will be a list of the labels of \\ref mcolv or \\ref multicolvarfunction " + "as PLUMED calculates the orientations of molecules within these operations. Please note also that the majority " + "of \\ref mcolv and \\ref multicolvarfunction do not calculate a molecular orientation."); keys.add("numbered","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); } AlignedMatrixBase::AlignedMatrixBase( const ActionOptions& ao ): -Action(ao), -AdjacencyMatrixBase(ao) + Action(ao), + AdjacencyMatrixBase(ao) { // Read in the atomic positions readMaxTwoSpeciesMatrix( "ATOMS", "ATOMSA", "ATOMSB", true ); - unsigned nrows, ncols; retrieveTypeDimensions( nrows, ncols, ncol_t ); + unsigned nrows, ncols; retrieveTypeDimensions( nrows, ncols, ncol_t ); if( mybasemulticolvars.size()==0 ) error("cannot use atom indices as input to this variable / input was not specified"); if( getSizeOfInputVectors()<3 ) error("base multicolvars do not calculate an orientation"); // Read in the switching function switchingFunction.resize( nrows, ncols ); - parseConnectionDescriptions("SWITCH",false,ncol_t); + parseConnectionDescriptions("SWITCH",false,ncol_t); // Find the largest sf cutoff double sfmax=switchingFunction(0,0).get_dmax(); - for(unsigned i=0;isfmax ) sfmax=tsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + } } // And set the link cell cutoff setLinkCellCutoff( sfmax ); } -void AlignedMatrixBase::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ - plumed_assert( id<2 ); - if( id==0 ){ - plumed_assert( desc.size()==1 ); std::string errors; switchingFunction(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function in SWITCH keywrd description " + errors); - if( j!=i) switchingFunction(i,j).set(desc[0],errors); - log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); - } else if( id==1 ){ - readOrientationConnector( i, j, desc ); +void AlignedMatrixBase::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { + plumed_assert( id<2 ); + if( id==0 ) { + plumed_assert( desc.size()==1 ); std::string errors; switchingFunction(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function in SWITCH keywrd description " + errors); + if( j!=i) switchingFunction(i,j).set(desc[0],errors); + log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); + } else if( id==1 ) { + readOrientationConnector( i, j, desc ); } } @@ -94,21 +94,21 @@ double AlignedMatrixBase::compute( const unsigned& tindex, multicolvar::AtomValu std::vector orient0(ncomp), orient1(ncomp), dorient0(ncomp), dorient1(ncomp); Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); getInputData( 0, true, myatoms, orient0 ); getInputData( 1, true, myatoms, orient1 ); - double f_dot = computeVectorFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t, + double f_dot = computeVectorFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t, distance, orient0, orient1, ddistance, dorient0, dorient1 ); // Retrieve the weight of the connection - double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t ).calculate( distance.modulo(), dfunc ); + double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) )-ncol_t ).calculate( distance.modulo(), dfunc ); - if( !doNotCalculateDerivatives() ){ - addAtomDerivatives( 1, 0, (-dfunc)*f_dot*distance - sw*ddistance, myatoms ); - addAtomDerivatives( 1, 1, (+dfunc)*f_dot*distance + sw*ddistance, myatoms ); - myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) - sw*extProduct( distance, ddistance ) ); + if( !doNotCalculateDerivatives() ) { + addAtomDerivatives( 1, 0, (-dfunc)*f_dot*distance - sw*ddistance, myatoms ); + addAtomDerivatives( 1, 1, (+dfunc)*f_dot*distance + sw*ddistance, myatoms ); + myatoms.addBoxDerivatives( 1, (-dfunc)*f_dot*Tensor(distance,distance) - sw*extProduct( distance, ddistance ) ); - // Add derivatives of orientation - for(unsigned k=2;k fake_atoms; @@ -46,14 +46,14 @@ myclusters(NULL) // Setup the atom pack myfatoms.setNumberOfAtoms( myclusters->getNumberOfNodes() ); myfvals.getIndices().resize( myclusters->getNumberOfNodes() ); - for(unsigned i=0;igetNumberOfNodes();++i) myfatoms.setAtomIndex( i, i ); + for(unsigned i=0; igetNumberOfNodes(); ++i) myfatoms.setAtomIndex( i, i ); } -void ClusterAnalysisBase::turnOnDerivatives(){ +void ClusterAnalysisBase::turnOnDerivatives() { // Check for dubious vessels - for(unsigned i=0;igetName()=="MEAN" ) error("MEAN of cluster is not differentiable"); - if( getPntrToVessel(i)->getName()=="VMEAN" ) error("VMEAN of cluster is not differentiable"); + for(unsigned i=0; igetName()=="MEAN" ) error("MEAN of cluster is not differentiable"); + if( getPntrToVessel(i)->getName()=="VMEAN" ) error("VMEAN of cluster is not differentiable"); } MultiColvarBase::turnOnDerivatives(); } @@ -70,7 +70,7 @@ unsigned ClusterAnalysisBase::getNumberOfClusters() const { return myclusters->getNumberOfClusters(); } -bool ClusterAnalysisBase::isPeriodic(){ +bool ClusterAnalysisBase::isPeriodic() { return mybasemulticolvars[0]->isPeriodic(); } diff --git a/src/adjmat/ClusterAnalysisBase.h b/src/adjmat/ClusterAnalysisBase.h index 58d4b91e73..24a1b80aee 100644 --- a/src/adjmat/ClusterAnalysisBase.h +++ b/src/adjmat/ClusterAnalysisBase.h @@ -48,7 +48,7 @@ class ClusterAnalysisBase : public multicolvar::MultiColvarBase { unsigned getNumberOfQuantities() const ; bool isPeriodic(); void turnOnDerivatives(); - void setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ){} + void setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ) {} Vector getPositionOfAtomForLinkCells( const unsigned& ) const ; double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { plumed_error(); } }; diff --git a/src/adjmat/ClusterDiameter.cpp b/src/adjmat/ClusterDiameter.cpp index c1a6fa54ab..ec26f2eeb9 100644 --- a/src/adjmat/ClusterDiameter.cpp +++ b/src/adjmat/ClusterDiameter.cpp @@ -26,11 +26,11 @@ /* Print out the diameter of one of the connected components -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. When analysing these matrix we can treat them as a graph and find connected components using some clustering algorithm. This action is used in tandem with this form of analysis -to output the largest of the distances between the paris of atoms that are connected together in a particular connected component. It is important to +to output the largest of the distances between the paris of atoms that are connected together in a particular connected component. It is important to note that the quantity that is output by this action is not differentiable. As such it cannot be used as a collective variable in a biased simulation. \par Examples @@ -79,51 +79,51 @@ class ClusterDiameter : public ClusterAnalysisBase { PLUMED_REGISTER_ACTION(ClusterDiameter,"CLUSTER_DIAMETER") -void ClusterDiameter::registerKeywords( Keywords& keys ){ +void ClusterDiameter::registerKeywords( Keywords& keys ) { ClusterAnalysisBase::registerKeywords( keys ); keys.add("compulsory","CLUSTER","1","which cluster would you like to look at 1 is the largest cluster, 2 is the second largest, 3 is the the third largest and so on."); } ClusterDiameter::ClusterDiameter(const ActionOptions&ao): -Action(ao), -ClusterAnalysisBase(ao) + Action(ao), + ClusterAnalysisBase(ao) { - // Find out which cluster we want - parse("CLUSTER",clustr); - - if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); - if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); - - // Create the task list - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); + // Find out which cluster we want + parse("CLUSTER",clustr); + + if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); + if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); + + // Create the task list + for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); } -void ClusterDiameter::turnOnDerivatives(){ - error("cannot calculate derivatives of cluster radius. This quantity is not differentiable"); +void ClusterDiameter::turnOnDerivatives() { + error("cannot calculate derivatives of cluster radius. This quantity is not differentiable"); } -void ClusterDiameter::calculate(){ - // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); - // Activate the relevant tasks - deactivateAllTasks(); - for(unsigned i=1;i myatoms; retrieveAtomsInCluster( clustr, myatoms ); + // Activate the relevant tasks + deactivateAllTasks(); + for(unsigned i=1; i fake_atoms; setupMultiColvarBase( fake_atoms ); + use_switch=false; + std::string input, errors; parse("TRANSFORM",input); + if( input!="none" ) { + use_switch=true; sf.set( input, errors ); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } + parseFlag("INVERSE_TRANSFORM",inverse); + if( inverse && !use_switch ) error("INVERSE_TRANSFORM option was specified but no TRANSOFRM switching function was given"); + + // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) + for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); } -void ClusterDistribution::calculate(){ - // Activate the relevant tasks - nderivatives = getNumberOfDerivatives(); - deactivateAllTasks(); - for(unsigned i=0;i vals( getNumberOfQuantities() ); + std::vector vals( getNumberOfQuantities() ); MultiValue tvals( getNumberOfQuantities(), nderivatives ); // And this builds everything for this particular atom - double vv, df, tval=0; - for(unsigned j=0;jgetNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); + if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); + if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); - // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); + // And now finish the setup of everything in the base + std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); } -void ClusterProperties::calculate(){ - // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); - // Activate the relevant tasks - deactivateAllTasks(); - for(unsigned i=0;i myatoms; retrieveAtomsInCluster( clustr, myatoms ); + // Activate the relevant tasks + deactivateAllTasks(); + for(unsigned i=0; i vals( myvals.getNumberOfValues() ); getPropertiesOfNode( current, vals ); - if( !doNotCalculateDerivatives() ) getNodePropertyDerivatives( current, myvals ); - for(unsigned k=0;k vals( myvals.getNumberOfValues() ); getPropertiesOfNode( current, vals ); + if( !doNotCalculateDerivatives() ) getNodePropertyDerivatives( current, myvals ); + for(unsigned k=0; kgetNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); + if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); + if( clustr>getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); - // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); - addValue(); setNotPeriodic(); + // Create all tasks by copying those from underlying DFS object (which is actually MultiColvar) + for(unsigned i=0; i fake_atoms; setupMultiColvarBase( fake_atoms ); + addValue(); setNotPeriodic(); } -void ClusterSize::turnOnDerivatives(){ - error("cannot calculate derivatives of number of atoms in cluster. This quantity is not differentiable"); +void ClusterSize::turnOnDerivatives() { + error("cannot calculate derivatives of number of atoms in cluster. This quantity is not differentiable"); } -void ClusterSize::calculate(){ - // Retrieve the atoms in the largest cluster - std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); setValue( myatoms.size() ); +void ClusterSize::calculate() { + // Retrieve the atoms in the largest cluster + std::vector myatoms; retrieveAtomsInCluster( clustr, myatoms ); setValue( myatoms.size() ); } } diff --git a/src/adjmat/ClusterWithSurface.cpp b/src/adjmat/ClusterWithSurface.cpp index 21c2e3a5cd..ab472eee50 100644 --- a/src/adjmat/ClusterWithSurface.cpp +++ b/src/adjmat/ClusterWithSurface.cpp @@ -24,24 +24,24 @@ #include "AdjacencyMatrixBase.h" #include "core/ActionRegister.h" -//+PLUMEDOC MATRIXF CLUSTER_WITHSURFACE +//+PLUMEDOC MATRIXF CLUSTER_WITHSURFACE /* Take a connected component that was found using a clustering algorithm and create a new cluster that contains those atoms that are in the cluster together with those atoms that are within a certain cutoff of the cluster. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. When analysing these matrix we can treat them as a graph and find connected components using some clustering algorithm. This action is used in tandem with this form of analysis -and takes one of the connected components that was found during this analysis and creates a new cluster that includes all the atoms within the +and takes one of the connected components that was found during this analysis and creates a new cluster that includes all the atoms within the connected component that was found together that were within a certain cutoff distance of the atoms in the connected component. This form of analysis has been used sucessfully in the forward flux sampling simulations described in this paper \cite gab-ice-kaolinite \par Examples -The following input uses PLUMED to calculate a adjacency matrix that connects a pair of atoms if they both have a coordination number that is less +The following input uses PLUMED to calculate a adjacency matrix that connects a pair of atoms if they both have a coordination number that is less than 13.5 and if they are within 0.38 nm of each other. Depth first search clustering is used to find the connected components in this matrix. The -number of atoms with indices that are between 1 and 1996 and that are either in the second largest cluster or that are within within 0.3 nm of one of the -atoms within the the second largest cluster are then counted and this number of atoms is output to a file called size. In addition the indices of the atoms +number of atoms with indices that are between 1 and 1996 and that are either in the second largest cluster or that are within within 0.3 nm of one of the +atoms within the the second largest cluster are then counted and this number of atoms is output to a file called size. In addition the indices of the atoms that were counted are output to a file called dfs2.dat. \verbatim @@ -88,45 +88,45 @@ class ClusterWithSurface : public ClusteringBase { /// unsigned getNumberOfQuantities() const ; /// Do the calculation - void performClustering(){}; + void performClustering() {}; /// - double getCutoffForConnection() const ; + double getCutoffForConnection() const ; /// Vector getPositionOfAtomForLinkCells( const unsigned& taskIndex ) const ; }; PLUMED_REGISTER_ACTION(ClusterWithSurface,"CLUSTER_WITHSURFACE") -void ClusterWithSurface::registerKeywords( Keywords& keys ){ +void ClusterWithSurface::registerKeywords( Keywords& keys ) { ClusteringBase::registerKeywords( keys ); keys.remove("MATRIX"); keys.add("compulsory","CLUSTERS","the label of the action that does the clustering"); keys.add("compulsory","RCUT_SURF","you also have the option to find the atoms on the surface of the cluster. An atom must be within this distance of one of the atoms " - "of the cluster in order to be considered a surface atom"); + "of the cluster in order to be considered a surface atom"); } ClusterWithSurface::ClusterWithSurface(const ActionOptions&ao): -Action(ao), -ClusteringBase(ao) + Action(ao), + ClusteringBase(ao) { - std::vector fake_atoms; - if( !parseMultiColvarAtomList("CLUSTERS",-1,fake_atoms ) ) error("unable to find CLUSTERS input"); - if( mybasemulticolvars.size()!=1 ) error("should be exactly one multicolvar input"); + std::vector fake_atoms; + if( !parseMultiColvarAtomList("CLUSTERS",-1,fake_atoms ) ) error("unable to find CLUSTERS input"); + if( mybasemulticolvars.size()!=1 ) error("should be exactly one multicolvar input"); - // Retrieve the adjacency matrix of interest - atom_lab.resize(0); myclusters = dynamic_cast( mybasemulticolvars[0] ); - if( !myclusters ) error( mybasemulticolvars[0]->getLabel() + " does not calculate clusters"); + // Retrieve the adjacency matrix of interest + atom_lab.resize(0); myclusters = dynamic_cast( mybasemulticolvars[0] ); + if( !myclusters ) error( mybasemulticolvars[0]->getLabel() + " does not calculate clusters"); - // Setup switching function for surface atoms - double rcut_surf; parse("RCUT_SURF",rcut_surf); - if( rcut_surf>0 ) log.printf(" counting surface atoms that are within %f of the cluster atoms \n",rcut_surf); - rcut_surf2=rcut_surf*rcut_surf; + // Setup switching function for surface atoms + double rcut_surf; parse("RCUT_SURF",rcut_surf); + if( rcut_surf>0 ) log.printf(" counting surface atoms that are within %f of the cluster atoms \n",rcut_surf); + rcut_surf2=rcut_surf*rcut_surf; - // And now finish the setup of everything in the base - setupMultiColvarBase( fake_atoms ); + // And now finish the setup of everything in the base + setupMultiColvarBase( fake_atoms ); } -unsigned ClusterWithSurface::getNumberOfDerivatives(){ +unsigned ClusterWithSurface::getNumberOfDerivatives() { return myclusters->getNumberOfDerivatives(); } @@ -161,26 +161,26 @@ void ClusterWithSurface::retrieveAtomsInCluster( const unsigned& clust, std::vec // Prevent double counting std::vector incluster( getNumberOfNodes(), false ); - for(unsigned i=0;i surface_atom( getNumberOfNodes(), false ); - for(unsigned i=0;i surface_atom( getNumberOfNodes(), false ); + for(unsigned i=0; iundirectedGraph() ) error("input contact matrix is incompatible with clustering"); - } - if( keywords.exists("MATRIX") ){ - std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); - } + if( getAdjacencyVessel() ) { + cluster_sizes.resize(getNumberOfNodes()); which_cluster.resize(getNumberOfNodes()); + if( getNumberOfNodeTypes()!=1 ) error("should only be running clustering with one base multicolvar in function"); + if( !getAdjacencyVessel()->undirectedGraph() ) error("input contact matrix is incompatible with clustering"); + } + if( keywords.exists("MATRIX") ) { + std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); + } } -void ClusteringBase::turnOnDerivatives(){ - // Check base multicolvar isn't density probably other things shouldn't be allowed here as well - if( (getAdjacencyVessel()->getMatrixAction())->getNumberOfBaseMultiColvars()>0 ){ - if( getBaseMultiColvar(0)->isDensity() ) error("DFS clustering cannot be differentiated if base multicolvar is DENSITY"); - } +void ClusteringBase::turnOnDerivatives() { + // Check base multicolvar isn't density probably other things shouldn't be allowed here as well + if( (getAdjacencyVessel()->getMatrixAction())->getNumberOfBaseMultiColvars()>0 ) { + if( getBaseMultiColvar(0)->isDensity() ) error("DFS clustering cannot be differentiated if base multicolvar is DENSITY"); + } - // Ensure that derivatives are turned on in base classes - ActionWithInputMatrix::turnOnDerivatives(); + // Ensure that derivatives are turned on in base classes + ActionWithInputMatrix::turnOnDerivatives(); } -void ClusteringBase::calculate(){ - // All the clusters have zero size initially - for(unsigned i=0;i& myatoms ) const { - unsigned n=0; myatoms.resize( cluster_sizes[cluster_sizes.size() - clust].first ); - for(unsigned i=0;inodesAreConnected( iatom, jatom ); + return getAdjacencyVessel()->nodesAreConnected( iatom, jatom ); } double ClusteringBase::getCutoffForConnection() const { diff --git a/src/adjmat/ClusteringBase.h b/src/adjmat/ClusteringBase.h index 11c0bc14cc..741ac9046e 100644 --- a/src/adjmat/ClusteringBase.h +++ b/src/adjmat/ClusteringBase.h @@ -32,7 +32,7 @@ class ClusteringBase : public ActionWithInputMatrix { protected: /// Vector that stores the sizes of the current set of clusters std::vector< std::pair > cluster_sizes; -/// Used to identify the cluster we are working on +/// Used to identify the cluster we are working on int number_of_cluster; /// Vector that identifies the cluster each atom belongs to std::vector which_cluster; @@ -47,15 +47,15 @@ class ClusteringBase : public ActionWithInputMatrix { bool areConnected( const unsigned& iatom, const unsigned& jatom ) const ; /// Do the calculation void calculate(); -/// Do the clustering +/// Do the clustering virtual void performClustering()=0; /// Get the number of clusters that have been found unsigned getNumberOfClusters() const ; /// Get the atoms in one of the clusters virtual void retrieveAtomsInCluster( const unsigned& clust, std::vector& myatoms ) const ; /// Do nothing for apply here - void apply(){} -/// Get the cutoff + void apply() {} +/// Get the cutoff virtual double getCutoffForConnection() const ; }; diff --git a/src/adjmat/ContactAlignedMatrix.cpp b/src/adjmat/ContactAlignedMatrix.cpp index e1343f5a35..e1bdfcdba0 100644 --- a/src/adjmat/ContactAlignedMatrix.cpp +++ b/src/adjmat/ContactAlignedMatrix.cpp @@ -23,12 +23,12 @@ #include "core/ActionRegister.h" #include "tools/Matrix.h" -//+PLUMEDOC MATRIX ALIGNED_MATRIX +//+PLUMEDOC MATRIX ALIGNED_MATRIX /* Adjacency matrix in which two molecule are adjacent if they are within a certain cutoff and if they have the same orientation. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. These matrices can then be further analysed using a number of other algorithms as is detailed in \cite tribello-clustering. @@ -38,29 +38,29 @@ For this action the elements of the adjacency matrix are calculated using: a_{ij} = \sigma_1( |\mathbf{r}_{ij}| ) \sigma_2( \mathbf{v}_i . \mathbf{v}_j ) \f] -This form of adjacency matrix can only be used if the input species are objects that lie at a point in space and that have an orientation, \f$\mathbf{v}\f$. -These orientations might represent the -orientation of a molecule, which could be calculated using \ref MOLECULES or \ref PLANES, or it might be the complex vectors calculated using the +This form of adjacency matrix can only be used if the input species are objects that lie at a point in space and that have an orientation, \f$\mathbf{v}\f$. +These orientations might represent the +orientation of a molecule, which could be calculated using \ref MOLECULES or \ref PLANES, or it might be the complex vectors calculated using the Steinhardt parameters \ref Q3, \ref Q4 or \ref Q6. In the expression above \f$\mathbf{r}_{ij}\f$ is the vector connecting the points in space where objects \f$i\f$ and \f$j\f$ find themselves and \f$\sigma_1\f$ is a \ref switchingfunction that acts upon the magnitude of this vector. -\f$\sigma_2\f$ is a second \ref switchingfunction that acts on the dot product of the directors of the vectors that define the orientations of -objects \f$i\f$ and \f$j\f$. +\f$\sigma_2\f$ is a second \ref switchingfunction that acts on the dot product of the directors of the vectors that define the orientations of +objects \f$i\f$ and \f$j\f$. \par Examples The example input below is necessarily but gives you an idea of what can be achieved using this action. -The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the +The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the centeres of mass of the two atoms specified and the direction of the vector connecting the two atoms that were specified. -A \f$4 \times 4\f$ matrix is then computed using the formula above. The \f$ij\f$-element of this matrix tells us whether +A \f$4 \times 4\f$ matrix is then computed using the formula above. The \f$ij\f$-element of this matrix tells us whether or not atoms \f$i\f$ and \f$j\f$ are within 0.1 nm of each other and whether or not the dot-product of their orientation vectors -is greater than 0.5. The sum of the rows of this matrix are then computed. The sums of the \f$i\f$th row of this matrix tells us how -many of the molecules that are within the first coordination sphere of molecule \f$i\f$ have an orientation that is similar to that of -molecule \f$i\f$. We thus calculate the number of these "coordination numbers" that are greater than 1.0 and output this quantity to a file. +is greater than 0.5. The sum of the rows of this matrix are then computed. The sums of the \f$i\f$th row of this matrix tells us how +many of the molecules that are within the first coordination sphere of molecule \f$i\f$ have an orientation that is similar to that of +molecule \f$i\f$. We thus calculate the number of these "coordination numbers" that are greater than 1.0 and output this quantity to a file. \verbatim m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 mat: ALIGNED_MATRIX ATOMS=m1 SWITCH={RATIONAL R_0=0.1} ORIENTATION_SWITCH={RATIONAL R_0=0.1 D_MAX=0.5} -rr: ROWSUMS MATRIX=mat MORE_THAN={RATIONAL D_0=1.0 R_0=0.1} +rr: ROWSUMS MATRIX=mat MORE_THAN={RATIONAL D_0=1.0 R_0=0.1} PRINT ARG=rr.* FILE=colvar \endverbatim @@ -72,48 +72,48 @@ namespace adjmat { class ContactAlignedMatrix : public AlignedMatrixBase { private: - Matrix sf; + Matrix sf; public: - /// - static void registerKeywords( Keywords& keys ); - /// - explicit ContactAlignedMatrix(const ActionOptions&); - void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); - double computeVectorFunction( const unsigned& iv, const unsigned& jv, - const Vector& conn, const std::vector& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; + /// + static void registerKeywords( Keywords& keys ); + /// + explicit ContactAlignedMatrix(const ActionOptions&); + void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); + double computeVectorFunction( const unsigned& iv, const unsigned& jv, + const Vector& conn, const std::vector& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; }; PLUMED_REGISTER_ACTION(ContactAlignedMatrix,"ALIGNED_MATRIX") -void ContactAlignedMatrix::registerKeywords( Keywords& keys ){ - AlignedMatrixBase::registerKeywords( keys ); - keys.add("numbered","ORIENTATION_SWITCH","A switching function that transforms the dot product of the input vectors."); +void ContactAlignedMatrix::registerKeywords( Keywords& keys ) { + AlignedMatrixBase::registerKeywords( keys ); + keys.add("numbered","ORIENTATION_SWITCH","A switching function that transforms the dot product of the input vectors."); } ContactAlignedMatrix::ContactAlignedMatrix( const ActionOptions& ao ): -Action(ao), -AlignedMatrixBase(ao) + Action(ao), + AlignedMatrixBase(ao) { - unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); - sf.resize( nrows, ncols ); - parseConnectionDescriptions("ORIENTATION_SWITCH",false,0); + unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); + sf.resize( nrows, ncols ); + parseConnectionDescriptions("ORIENTATION_SWITCH",false,0); } -void ContactAlignedMatrix::readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ){ - plumed_assert( desc.size()==1 ); std::string errors; sf(j,i).set(desc[0],errors); - if( j!=i ) sf(i,j).set(desc[0],errors); - log.printf(" vectors in %u th and %u th groups must have a dot product that is greater than %s \n",i+1,j+1,(sf(i,j).description()).c_str() ); +void ContactAlignedMatrix::readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ) { + plumed_assert( desc.size()==1 ); std::string errors; sf(j,i).set(desc[0],errors); + if( j!=i ) sf(i,j).set(desc[0],errors); + log.printf(" vectors in %u th and %u th groups must have a dot product that is greater than %s \n",i+1,j+1,(sf(i,j).description()).c_str() ); } -double ContactAlignedMatrix::computeVectorFunction( const unsigned& iv, const unsigned& jv, - const Vector& conn, const std::vector& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { - double dot_df, dot=0; dconn.zero(); - for(unsigned k=2;k& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { + double dot_df, dot=0; dconn.zero(); + for(unsigned k=2; ksfmax ) sfmax=tsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + } } // And set the link cell cutoff setLinkCellCutoff( sfmax ); } -void ContactMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ +void ContactMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { plumed_assert( id==0 && desc.size()==1 ); std::string errors; switchingFunction(j,i).set(desc[0],errors); if( errors.length()!=0 ) error("problem reading switching function description " + errors); if( j!=i) switchingFunction(i,j).set(desc[0],errors); @@ -137,12 +137,12 @@ double ContactMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePac Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); - if( !doNotCalculateDerivatives() ){ - Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); - addAtomDerivatives( 1, 0, (-dfunc)*distance, myatoms ); - addAtomDerivatives( 1, 1, (+dfunc)*distance, myatoms ); - myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); + if( !doNotCalculateDerivatives() ) { + Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + double dfunc, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) - ncol_t ).calculate( distance.modulo(), dfunc ); + addAtomDerivatives( 1, 0, (-dfunc)*distance, myatoms ); + addAtomDerivatives( 1, 1, (+dfunc)*distance, myatoms ); + myatoms.addBoxDerivatives( 1, (-dfunc)*Tensor(distance,distance) ); } return sw; } diff --git a/src/adjmat/DFSClustering.cpp b/src/adjmat/DFSClustering.cpp index 596641849f..af0dc327e8 100644 --- a/src/adjmat/DFSClustering.cpp +++ b/src/adjmat/DFSClustering.cpp @@ -24,8 +24,8 @@ #include "core/ActionRegister.h" #ifdef __PLUMED_HAS_BOOST_GRAPH -#include -#include +#include +#include #include #endif @@ -33,8 +33,8 @@ /* Find the connected components of the matrix using the depth first search clustering algorithm. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. As detailed in \cite tribello-clustering these matrices provide a representation of a graph and can thus can be analysed using tools from graph theory. This particular action performs a depth first search clustering to find the connected components of this graph. You can read more about depth first search here: @@ -44,7 +44,7 @@ a depth first search clustering to find the connected components of this graph. This action is useful if you are looking at a phenomenon such as nucleation where the aim is to detect the sizes of the crystalline nuclei that have formed in your simulation cell. -\par Examples +\par Examples The input below calculates the coordination numbers of atoms 1-100 and then computes the an adjacency matrix whose elements measures whether atoms \f$i\f$ and \f$j\f$ are within 0.55 nm of each other. The action @@ -54,15 +54,15 @@ numbers for the atoms in this largest connected component are then computed and file. The way this input can be used is described in detail in \cite tribello-clustering. \verbatim -lq: COORDINATIONNUMBER SPECIES=1-100 SWITCH={CUBIC D_0=0.45 D_MAX=0.55} LOWMEM -cm: CONTACT_MATRIX ATOMS=lq SWITCH={CUBIC D_0=0.45 D_MAX=0.55} -dfs: DFSCLUSTERING MATRIX=cm -clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM +lq: COORDINATIONNUMBER SPECIES=1-100 SWITCH={CUBIC D_0=0.45 D_MAX=0.55} LOWMEM +cm: CONTACT_MATRIX ATOMS=lq SWITCH={CUBIC D_0=0.45 D_MAX=0.55} +dfs: DFSCLUSTERING MATRIX=cm +clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM PRINT ARG=clust1.* FILE=colvar \endverbatim */ -//+ENDPLUMEDOC +//+ENDPLUMEDOC namespace PLMD { namespace adjmat { @@ -93,67 +93,67 @@ class DFSClustering : public ClusteringBase { PLUMED_REGISTER_ACTION(DFSClustering,"DFSCLUSTERING") -void DFSClustering::registerKeywords( Keywords& keys ){ +void DFSClustering::registerKeywords( Keywords& keys ) { ClusteringBase::registerKeywords( keys ); keys.add("compulsory","MAXCONNECT","0","maximum number of connections that can be formed by any given node in the graph. " - "By default this is set equal to zero and the number of connections is set equal to the number " - "of nodes. You only really need to set this if you are working with a very large system and " - "memory is at a premium"); + "By default this is set equal to zero and the number of connections is set equal to the number " + "of nodes. You only really need to set this if you are working with a very large system and " + "memory is at a premium"); } DFSClustering::DFSClustering(const ActionOptions&ao): -Action(ao), -ClusteringBase(ao) + Action(ao), + ClusteringBase(ao) { - unsigned maxconnections; parse("MAXCONNECT",maxconnections); -#ifdef __PLUMED_HAS_BOOST_GRAPH - if( maxconnections>0 ) edge_list.resize( getNumberOfNodes()*maxconnections ); - else edge_list.resize(0.5*getNumberOfNodes()*(getNumberOfNodes()-1)); + unsigned maxconnections; parse("MAXCONNECT",maxconnections); +#ifdef __PLUMED_HAS_BOOST_GRAPH + if( maxconnections>0 ) edge_list.resize( getNumberOfNodes()*maxconnections ); + else edge_list.resize(0.5*getNumberOfNodes()*(getNumberOfNodes()-1)); #else - nneigh.resize( getNumberOfNodes() ); color.resize(getNumberOfNodes()); - if( maxconnections>0 ) adj_list.resize(getNumberOfNodes(),maxconnections); - else adj_list.resize(getNumberOfNodes(),getNumberOfNodes()); + nneigh.resize( getNumberOfNodes() ); color.resize(getNumberOfNodes()); + if( maxconnections>0 ) adj_list.resize(getNumberOfNodes(),maxconnections); + else adj_list.resize(getNumberOfNodes(),getNumberOfNodes()); #endif } -void DFSClustering::performClustering(){ +void DFSClustering::performClustering() { #ifdef __PLUMED_HAS_BOOST_GRAPH - // Get the list of edges - unsigned nedges=0; getAdjacencyVessel()->retrieveEdgeList( nedges, edge_list ); + // Get the list of edges + unsigned nedges=0; getAdjacencyVessel()->retrieveEdgeList( nedges, edge_list ); - // Build the graph using boost - boost::adjacency_list sg(&edge_list[0],&edge_list[nedges],getNumberOfNodes()); + // Build the graph using boost + boost::adjacency_list sg(&edge_list[0],&edge_list[nedges],getNumberOfNodes()); - // Find the connected components using boost (-1 here for compatibility with non-boost version) - number_of_cluster=boost::connected_components(sg,&which_cluster[0]) - 1; + // Find the connected components using boost (-1 here for compatibility with non-boost version) + number_of_cluster=boost::connected_components(sg,&which_cluster[0]) - 1; - // And work out the size of each cluster - for(unsigned i=0;iretrieveAdjacencyLists( nneigh, adj_list ); - - // Perform clustering - number_of_cluster=-1; color.assign(color.size(),0); - for(unsigned i=0;iretrieveAdjacencyLists( nneigh, adj_list ); + + // Perform clustering + number_of_cluster=-1; color.assign(color.size(),0); + for(unsigned i=0; i( mstring ); - if( !mm ) error("found no action in set with label " + mstring + " that calculates matrix"); - log.printf(" printing graph for matrix calculated by action %s\n", mm->getLabel().c_str() ); - - // Retrieve the adjacency matrix of interest - for(unsigned i=0;igetNumberOfVessels();++i){ - mymatrix = dynamic_cast( mm->getPntrToVessel(i) ); - if( mymatrix ) break ; - } - if( !mymatrix ) error( mm->getLabel() + " does not calculate an adjacency matrix"); - if( !mymatrix->isSymmetric() ) error("input contact matrix must be symmetric"); - if( maxconnections==0 ) maxconnections=mymatrix->getNumberOfRows(); - parse("FILE",filename); - log.printf(" printing graph to file named %s \n",filename.c_str() ); - checkRead(); + parse("MAXCONNECT",maxconnections); std::string mstring; parse("MATRIX",mstring); + AdjacencyMatrixBase* mm = plumed.getActionSet().selectWithLabel( mstring ); + if( !mm ) error("found no action in set with label " + mstring + " that calculates matrix"); + log.printf(" printing graph for matrix calculated by action %s\n", mm->getLabel().c_str() ); + + // Retrieve the adjacency matrix of interest + for(unsigned i=0; igetNumberOfVessels(); ++i) { + mymatrix = dynamic_cast( mm->getPntrToVessel(i) ); + if( mymatrix ) break ; + } + if( !mymatrix ) error( mm->getLabel() + " does not calculate an adjacency matrix"); + if( !mymatrix->isSymmetric() ) error("input contact matrix must be symmetric"); + if( maxconnections==0 ) maxconnections=mymatrix->getNumberOfRows(); + parse("FILE",filename); + log.printf(" printing graph to file named %s \n",filename.c_str() ); + checkRead(); } -void DumpGraph::update(){ - OFile ofile; ofile.link(*this); ofile.setBackupString("graph"); - ofile.open( filename ); ofile.printf("graph G { \n"); - // Print all nodes - for(unsigned i=0;igetNumberOfRows();++i) ofile.printf("%u [label=\"%u\"];\n",i,i); - // Now retrieve connectivitives - unsigned nedge; std::vector > edge_list( mymatrix->getNumberOfRows()*maxconnections ); - mymatrix->retrieveEdgeList( nedge, edge_list ); - for(unsigned i=0;igetNumberOfRows(); ++i) ofile.printf("%u [label=\"%u\"];\n",i,i); + // Now retrieve connectivitives + unsigned nedge; std::vector > edge_list( mymatrix->getNumberOfRows()*maxconnections ); + mymatrix->retrieveEdgeList( nedge, edge_list ); + for(unsigned i=0; isfmax ) sfmax=tsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + } } // Set the link cell cutoff setLinkCellCutoff( sfmax ); } -void HBondMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ +void HBondMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { plumed_assert( id<3 && desc.size()==1 ); - if( id==0 ){ - std::string errors; distanceOOSwitch(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) distanceOOSwitch(i,j).set(desc[0],errors); - log.printf(" atoms of type %u and %u must be within %s\n",i+1,j+1,(distanceOOSwitch(i,j).description()).c_str() ); - } else if( id==1 ){ - std::string errors; distanceOHSwitch(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) distanceOHSwitch(i,j).set(desc[0],errors); - log.printf(" for atoms of type %u and %u the OH distance must be less than %s \n",i+1,j+1,(distanceOHSwitch(i,j).description()).c_str() ); - } else if( id==2 ){ - std::string errors; angleSwitch(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) angleSwitch(i,j).set(desc[0],errors); - log.printf(" for atoms of type %u and %u the OOH angle must be less than %s \n",i+1,j+1,(angleSwitch(i,j).description()).c_str() ); - } + if( id==0 ) { + std::string errors; distanceOOSwitch(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) distanceOOSwitch(i,j).set(desc[0],errors); + log.printf(" atoms of type %u and %u must be within %s\n",i+1,j+1,(distanceOOSwitch(i,j).description()).c_str() ); + } else if( id==1 ) { + std::string errors; distanceOHSwitch(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) distanceOHSwitch(i,j).set(desc[0],errors); + log.printf(" for atoms of type %u and %u the OH distance must be less than %s \n",i+1,j+1,(distanceOHSwitch(i,j).description()).c_str() ); + } else if( id==2 ) { + std::string errors; angleSwitch(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) angleSwitch(i,j).set(desc[0],errors); + log.printf(" for atoms of type %u and %u the OOH angle must be less than %s \n",i+1,j+1,(angleSwitch(i,j).description()).c_str() ); + } } double HBondMatrix::calculateWeight( const unsigned& taskCode, const double& weight, multicolvar::AtomValuePack& myatoms ) const { // Ensure we skip diagonal elements of square matrix - if( myatoms.getIndex(0)==myatoms.getIndex(1) ) return 0.0; + if( myatoms.getIndex(0)==myatoms.getIndex(1) ) return 0.0; Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); if( distance.modulo2()3 ){ - for(unsigned i=2;i3 ) { + for(unsigned i=2; igetMatrixAction())->mybasemulticolvars.size()>0 ) error("matrix row sums should only be calculated when inputs are atoms"); // Setup the tasks - unsigned ncols = mymatrix->getNumberOfColumns(); + unsigned ncols = mymatrix->getNumberOfColumns(); ablocks.resize(1); ablocks[0].resize( ncols ); - for(unsigned i=0;iundirectedGraph() ){ - for(unsigned i=0;iundirectedGraph() ) { + for(unsigned i=0; igetNumberOfRows() + i; + for(unsigned i=0; igetNumberOfRows() + i; } std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); } double MatrixColumnSums::compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const { double sum=0.0; std::vector tvals( mymatrix->getNumberOfComponents() ); - unsigned nrows = mymatrix->getNumberOfRows(); - for(unsigned i=0;iundirectedGraph() && tinded==i ) continue; - sum+=retrieveConnectionValue( i, tinded, tvals ); + unsigned nrows = mymatrix->getNumberOfRows(); + for(unsigned i=0; iundirectedGraph() && tinded==i ) continue; + sum+=retrieveConnectionValue( i, tinded, tvals ); } - if( !doNotCalculateDerivatives() ){ - MultiValue myvals( mymatrix->getNumberOfComponents(), myatoms.getNumberOfDerivatives() ); - MultiValue& myvout=myatoms.getUnderlyingMultiValue(); - for(unsigned i=0;iisSymmetric() && tinded==i ) continue ; - addConnectionDerivatives( i, tinded, myvals, myvout ); - } + if( !doNotCalculateDerivatives() ) { + MultiValue myvals( mymatrix->getNumberOfComponents(), myatoms.getNumberOfDerivatives() ); + MultiValue& myvout=myatoms.getUnderlyingMultiValue(); + for(unsigned i=0; iisSymmetric() && tinded==i ) continue ; + addConnectionDerivatives( i, tinded, myvals, myvout ); + } } return sum; } diff --git a/src/adjmat/MatrixRowSums.cpp b/src/adjmat/MatrixRowSums.cpp index 1b7da9cf09..038aa89a71 100644 --- a/src/adjmat/MatrixRowSums.cpp +++ b/src/adjmat/MatrixRowSums.cpp @@ -27,36 +27,36 @@ #include "core/PlumedMain.h" #include "core/ActionSet.h" -//+PLUMEDOC MATRIXF ROWSUMS +//+PLUMEDOC MATRIXF ROWSUMS /* Sum the rows of a adjacency matrix. -As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the -so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether -or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. This action allows you to calculate +As discussed in the section of the manual on \ref contactmatrix a useful tool for developing complex collective variables is the notion of the +so called adjacency matrix. An adjacency matrix is an \f$N \times N\f$ matrix in which the \f$i\f$th, \f$j\f$th element tells you whether +or not the \f$i\f$th and \f$j\f$th atoms/molecules from a set of \f$N\f$ atoms/molecules are adjacent or not. This action allows you to calculate the sum of the rows in this adjacency matrix and to then calculate further functions of these quantities. \par Examples The first instruction in the following input file tells PLUMED to compute a \f$10 \times 10\f$ matrix in which the \f$ij\f$-element tells you whether atoms \f$i\f$ and \f$j\f$ are within 1.0 nm of each other. The numbers in each of this rows are then added together -and the average value is computed. As such the following input provides an alternative method for calculating the coordination numbers -of atoms 1 to 10. +and the average value is computed. As such the following input provides an alternative method for calculating the coordination numbers +of atoms 1 to 10. \verbatim -mat: CONTACT_MATRIX ATOMS=1-10 SWITCH={RATIONAL R_0=1.0} -rsums: ROWSUMS MATRIX=mat MEAN -PRINT ARG=rsums.* FILE=colvar +mat: CONTACT_MATRIX ATOMS=1-10 SWITCH={RATIONAL R_0=1.0} +rsums: ROWSUMS MATRIX=mat MEAN +PRINT ARG=rsums.* FILE=colvar \endverbatim -The following input demonstrates another way that an average coordination number can be computed. This input calculates the number of atoms +The following input demonstrates another way that an average coordination number can be computed. This input calculates the number of atoms with indices between 6 and 15 that are within the first coordination spheres of each of the atoms within indices between 1 and 5. The average coordination number is then calculated from these five coordination numbers and this quantity is output to a file. \verbatim -mat2: CONTACT_MATRIX ATOMSA=1-5 ATOMSB=6-15 SWITCH={RATIONAL R_0=1.0} -rsums: ROWSUMS MATRIX=mat2 MEAN -PRINT ARG=rsums.* FILE=colvar +mat2: CONTACT_MATRIX ATOMSA=1-5 ATOMSB=6-15 SWITCH={RATIONAL R_0=1.0} +rsums: ROWSUMS MATRIX=mat2 MEAN +PRINT ARG=rsums.* FILE=colvar \endverbatim */ @@ -69,12 +69,12 @@ class MatrixRowSums : public ActionWithInputMatrix { public: static void registerKeywords( Keywords& keys ); explicit MatrixRowSums(const ActionOptions&); - double compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const ; + double compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const ; }; PLUMED_REGISTER_ACTION(MatrixRowSums,"ROWSUMS") -void MatrixRowSums::registerKeywords( Keywords& keys ){ +void MatrixRowSums::registerKeywords( Keywords& keys ) { ActionWithInputMatrix::registerKeywords( keys ); keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MEAN"); keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); @@ -82,24 +82,24 @@ void MatrixRowSums::registerKeywords( Keywords& keys ){ } MatrixRowSums::MatrixRowSums(const ActionOptions& ao): -Action(ao), -ActionWithInputMatrix(ao) + Action(ao), + ActionWithInputMatrix(ao) { if( (mymatrix->getMatrixAction())->mybasemulticolvars.size()>0 ) error("matrix row sums should only be calculated when inputs are atoms"); // Setup the tasks - unsigned nrows = mymatrix->getNumberOfRows(); + unsigned nrows = mymatrix->getNumberOfRows(); ablocks.resize(1); ablocks[0].resize( nrows ); - for(unsigned i=0;i fake_atoms; setupMultiColvarBase( fake_atoms ); } double MatrixRowSums::compute( const unsigned& tinded, multicolvar::AtomValuePack& myatoms ) const { - std::vector tvals( mymatrix->getNumberOfComponents() ); + std::vector tvals( mymatrix->getNumberOfComponents() ); getInputData( tinded, false, myatoms, tvals ); double fval=tvals[1]; - if( !doNotCalculateDerivatives() ){ - tvals.assign( tvals.size(), 0 ); tvals[1]=1.0; - mergeInputDerivatives( 1, 1, 2, tinded, tvals, getInputDerivatives( tinded, false, myatoms ), myatoms ); + if( !doNotCalculateDerivatives() ) { + tvals.assign( tvals.size(), 0 ); tvals[1]=1.0; + mergeInputDerivatives( 1, 1, 2, tinded, tvals, getInputDerivatives( tinded, false, myatoms ), myatoms ); } return fval; } diff --git a/src/adjmat/OutputCluster.cpp b/src/adjmat/OutputCluster.cpp index d4bba925ba..c2b752f0d0 100644 --- a/src/adjmat/OutputCluster.cpp +++ b/src/adjmat/OutputCluster.cpp @@ -36,16 +36,16 @@ The output in question here is either - a file that contains a list of the atom indices that form part of one of the clusters that was identified using \ref DFSCLUSTERING - an xyz file containing the positions of the atoms in one of the the clusters that was identified using \ref DFSCLUSTERING -Notice also that if you choose to output an xyz file you can ask PLUMED to try to reconstruct the cluster +Notice also that if you choose to output an xyz file you can ask PLUMED to try to reconstruct the cluster taking the periodic boundary conditions into account by using the MAKE_WHOLE flag. \par Examples -The input shown below identifies those atoms with a coordination number less than 13 +The input shown below identifies those atoms with a coordination number less than 13 and then constructs a contact matrix that describes the connectivity between the atoms -that satisfy this criteria. The DFS algorithm is then used to find the connected components +that satisfy this criteria. The DFS algorithm is then used to find the connected components in this matrix and the indices of the atoms in the largest connected component are then output -to a file. +to a file. \verbatim c1: COORDINATIONNUMBER SPECIES=1-1996 SWITCH={CUBIC D_0=0.34 D_MAX=0.38} @@ -81,14 +81,14 @@ class OutputCluster : public ActionPilot { public: static void registerKeywords( Keywords& keys ); explicit OutputCluster(const ActionOptions&); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void update(); }; PLUMED_REGISTER_ACTION(OutputCluster,"OUTPUT_CLUSTER") -void OutputCluster::registerKeywords( Keywords& keys ){ +void OutputCluster::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); keys.add("compulsory","CLUSTERS","the action that performed the clustering"); @@ -101,125 +101,125 @@ void OutputCluster::registerKeywords( Keywords& keys ){ } OutputCluster::OutputCluster(const ActionOptions& ao): -Action(ao), -ActionPilot(ao), -myclusters(NULL) + Action(ao), + ActionPilot(ao), + myclusters(NULL) { // Setup output file ofile.link(*this); std::string file; parse("FILE",file); if( file.length()==0 ) error("output file name was not specified"); // Search for xyz extension output_xyz=false; - if( file.find(".")!=std::string::npos ){ - std::size_t dot=file.find_first_of('.'); - if( file.substr(dot+1)=="xyz" ) output_xyz=true; + if( file.find(".")!=std::string::npos ) { + std::size_t dot=file.find_first_of('.'); + if( file.substr(dot+1)=="xyz" ) output_xyz=true; } - ofile.open(file); log.printf(" on file %s \n",file.c_str()); + ofile.open(file); log.printf(" on file %s \n",file.c_str()); parseFlag("MAKE_WHOLE",makewhole); parse("MAXDEPTH",maxdepth); parse("MAXGOES",maxgoes); if( makewhole && !output_xyz) error("MAKE_WHOLE flag is not compatible with output of non-xyz files"); // Find what action we are taking the clusters from std::vector matname(1); parse("CLUSTERS",matname[0]); myclusters = plumed.getActionSet().selectWithLabel( matname[0] ); - if( !myclusters ) error( matname[0] + " does not calculate perform a clustering of the atomic positions"); + if( !myclusters ) error( matname[0] + " does not calculate perform a clustering of the atomic positions"); // N.B. the +0.3 is a fudge factor. Reconstrucing PBC doesnt work without this GAT addDependency( myclusters ); double rcut=myclusters->getCutoffForConnection() + 0.3; rcut2=rcut*rcut; // Read in the cluster we are calculating - parse("CLUSTER",clustr); + parse("CLUSTER",clustr); if( clustr<1 ) error("cannot look for a cluster larger than the largest cluster"); if( clustr>myclusters->getNumberOfNodes() ) error("cluster selected is invalid - too few atoms in system"); log.printf(" outputting atoms in %u th largest cluster found by %s \n",clustr,matname[0].c_str() ); } -void OutputCluster::update(){ +void OutputCluster::update() { myclusters->retrieveAtomsInCluster( clustr, myatoms ); - if( output_xyz ){ - ofile.printf("%u \n",static_cast(myatoms.size())); - ofile.printf("atoms in %u th largest cluster \n",clustr ); - if( makewhole ){ - // Retrieve the atom positions - atomsin.resize( myatoms.size() ); - for(unsigned i=0;igetPositionOfAtomForLinkCells( myatoms[i] ); - // Build a connectivity matrix neglecting the pbc - nneigh.resize( myatoms.size(), 0 ); adj_list.resize( myatoms.size(), myatoms.size() ); - for(unsigned i=1;i(myatoms.size())); + ofile.printf("atoms in %u th largest cluster \n",clustr ); + if( makewhole ) { + // Retrieve the atom positions + atomsin.resize( myatoms.size() ); + for(unsigned i=0; igetPositionOfAtomForLinkCells( myatoms[i] ); + // Build a connectivity matrix neglecting the pbc + nneigh.resize( myatoms.size(), 0 ); adj_list.resize( myatoms.size(), myatoms.size() ); + for(unsigned i=1; iareConnected( myatoms[i], myatoms[j] ) ) { adj_list(i,nneigh[i])=j; adj_list(j,nneigh[j])=i; nneigh[i]++; nneigh[j]++; } } - std::sort( cluster_sizes.begin(), cluster_sizes.end() ); + } - // Now set visited so that only those atoms in largest cluster will be start points for PBCing - visited.assign( visited.size(), false ); - for(unsigned i=0;iareConnected( myatoms[i], myatoms[j] ) ){ adj_list(i,nneigh[i])=j; adj_list(j,nneigh[j])=i; nneigh[i]++; nneigh[j]++; } - } - } + // Now find broken bonds and run iterative deepening depth first search to reconstruct + for(unsigned jj=0; jjrcut2 ){ - visited[j]=true; - for(unsigned depth=0;depth<=maxdepth;++depth) explore( j, depth ); - } - } + for(unsigned k=0; krcut2 ) { + visited[j]=true; + for(unsigned depth=0; depth<=maxdepth; ++depth) explore( j, depth ); } + } } - // And print final positions - for(unsigned i=0;igetPositionOfAtomForLinkCells( myatoms[i] ); - ofile.printf( "X %f %f %f \n", pos[0], pos[1], pos[2] ); - } - } + } + // And print final positions + for(unsigned i=0; igetPositionOfAtomForLinkCells( myatoms[i] ); + ofile.printf( "X %f %f %f \n", pos[0], pos[1], pos[2] ); + } + } } else { - ofile.printf("CLUSTERING RESULTS AT TIME %f : NUMBER OF ATOMS IN %u TH LARGEST CLUSTER EQUALS %u \n",getTime(),clustr,static_cast(myatoms.size()) ); - ofile.printf("INDICES OF ATOMS : "); - for(unsigned i=0;igetAbsoluteIndexOfCentralAtom(myatoms[i])).index()); - ofile.printf("\n"); + ofile.printf("CLUSTERING RESULTS AT TIME %f : NUMBER OF ATOMS IN %u TH LARGEST CLUSTER EQUALS %u \n",getTime(),clustr,static_cast(myatoms.size()) ); + ofile.printf("INDICES OF ATOMS : "); + for(unsigned i=0; igetAbsoluteIndexOfCentralAtom(myatoms[i])).index()); + ofile.printf("\n"); } } -void OutputCluster::explore( const unsigned& index, const unsigned& depth ){ +void OutputCluster::explore( const unsigned& index, const unsigned& depth ) { if( depth==0 ) return ; - for(unsigned i=0;ipbcDistance( atomsin[index], atomsin[j] ); - atomsin[j] = atomsin[index] + svec; - explore( j, depth-1 ); - } + for(unsigned i=0; ipbcDistance( atomsin[index], atomsin[j] ); + atomsin[j] = atomsin[index] + svec; + explore( j, depth-1 ); + } } -bool OutputCluster::explore_dfs( const unsigned& index ){ +bool OutputCluster::explore_dfs( const unsigned& index ) { visited[index]=true; - for(unsigned i=0;i > kernels; + Matrix > kernels; public: - /// - static void registerKeywords( Keywords& keys ); - /// - explicit SMACMatrix(const ActionOptions&); - void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); - double computeVectorFunction( const unsigned& iv, const unsigned& jv, - const Vector& conn, const std::vector& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; + /// + static void registerKeywords( Keywords& keys ); + /// + explicit SMACMatrix(const ActionOptions&); + void readOrientationConnector( const unsigned& i, const unsigned& j, const std::vector& desc ); + double computeVectorFunction( const unsigned& iv, const unsigned& jv, + const Vector& conn, const std::vector& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; }; PLUMED_REGISTER_ACTION(SMACMatrix,"SMAC_MATRIX") -void SMACMatrix::registerKeywords( Keywords& keys ){ - AlignedMatrixBase::registerKeywords( keys ); - keys.add("numbered","KERNEL","The various kernels that are used to determine whether or not the molecules are aligned"); +void SMACMatrix::registerKeywords( Keywords& keys ) { + AlignedMatrixBase::registerKeywords( keys ); + keys.add("numbered","KERNEL","The various kernels that are used to determine whether or not the molecules are aligned"); } SMACMatrix::SMACMatrix( const ActionOptions& ao ): -Action(ao), -AlignedMatrixBase(ao) + Action(ao), + AlignedMatrixBase(ao) { - unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); - kernels.resize( nrows, ncols ); parseConnectionDescriptions("KERNEL",true,0); + unsigned nrows, ncols, ig; retrieveTypeDimensions( nrows, ncols, ig ); + kernels.resize( nrows, ncols ); parseConnectionDescriptions("KERNEL",true,0); } -void SMACMatrix::readOrientationConnector( const unsigned& iv, const unsigned& jv, const std::vector& desc ){ - for(int i=0;i& desc ) { + for(int i=0; i& vec1, const std::vector& vec2, - Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { + const Vector& conn, const std::vector& vec1, const std::vector& vec2, + Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { unsigned nvectors = ( vec1.size() - 2 ) / 3; plumed_assert( (vec1.size()-2)%3==0 ); std::vector dv1(nvectors), dv2(nvectors), tdconn(nvectors); Torsion t; std::vector v1(nvectors), v2(nvectors); - std::vector pos; for(unsigned i=0;isetDomain( "-pi", "pi" ); } - - for(unsigned j=0;jset( angle ); + std::vector pos; for(unsigned i=0; isetDomain( "-pi", "pi" ); } + + for(unsigned j=0; jset( angle ); } - - double ans=0; std::vector deriv( nvectors ), df( nvectors, 0 ); - for(unsigned i=0;i deriv( nvectors ), df( nvectors, 0 ); + for(unsigned i=0; ilabel.coord-1, " - "the second smallest will be labelleled label.coord-1 and so on"); + "the smallest sprint coordinate will be labelled label.coord-1, " + "the second smallest will be labelleled label.coord-1 and so on"); } Sprint::Sprint(const ActionOptions&ao): -Action(ao), -ActionWithInputMatrix(ao), -eigvals( getNumberOfNodes() ), -maxeig( getNumberOfNodes() ), -thematrix( getNumberOfNodes(), getNumberOfNodes() ), -eigenvecs( getNumberOfNodes(), getNumberOfNodes() ) + Action(ao), + ActionWithInputMatrix(ao), + eigvals( getNumberOfNodes() ), + maxeig( getNumberOfNodes() ), + thematrix( getNumberOfNodes(), getNumberOfNodes() ), + eigenvecs( getNumberOfNodes(), getNumberOfNodes() ) { - // Check on setup - // if( getNumberOfVessels()!=1 ) error("there should be no vessel keywords"); - // Check for bad colvar input ( we are going to get rid of this because we are going to have input adjacency matrix in future ) - // for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); - // } - - if( !getAdjacencyVessel()->isSymmetric() ) error("input contact matrix is not symmetric"); - std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); - - // Create all the values - sqrtn = sqrt( static_cast( getNumberOfNodes() ) ); - for(unsigned i=0;iresizeDerivatives( getNumberOfDerivatives() ); - } - - // Setup the dynamic list to hold all the tasks - unsigned ntriangle = 0.5*getNumberOfNodes()*(getNumberOfNodes()-1); - for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); + // } + + if( !getAdjacencyVessel()->isSymmetric() ) error("input contact matrix is not symmetric"); + std::vector fake_atoms; setupMultiColvarBase( fake_atoms ); + + // Create all the values + sqrtn = sqrt( static_cast( getNumberOfNodes() ) ); + for(unsigned i=0; iresizeDerivatives( getNumberOfDerivatives() ); + } + + // Setup the dynamic list to hold all the tasks + unsigned ntriangle = 0.5*getNumberOfNodes()*(getNumberOfNodes()-1); + for(unsigned i=0; iretrieveMatrix( active_elements, thematrix ); - // Diagonalize it - diagMat( thematrix, eigvals, eigenvecs ); - // Get the maximum eigevalue - double lambda = eigvals[ getNumberOfNodes()-1 ]; - // Get the corresponding eigenvector - for(unsigned j=0;jset( sqrtn*lambda*maxeig[icomp].first ); - } - - // Parallelism - unsigned rank, stride; - if( serialCalculation() ){ stride=1; rank=0; } - else { rank=comm.Get_rank(); stride=comm.Get_size(); } - - // Derivatives - MultiValue myvals( 2, getNumberOfDerivatives() ); - Matrix mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); - // std::vector catoms(2); - unsigned nval = getNumberOfNodes(); mymat_ders=0; - for(unsigned i=rank;igetMatrixIndices( active_elements[i], j, k ); - double tmp1 = 2 * eigenvecs(nval-1,j)*eigenvecs(nval-1,k); - for(unsigned icomp=0;icompretrieveDerivatives( active_elements[i], false, myvals ); - for(unsigned jd=0;jdretrieveMatrix( active_elements, thematrix ); + // Diagonalize it + diagMat( thematrix, eigvals, eigenvecs ); + // Get the maximum eigevalue + double lambda = eigvals[ getNumberOfNodes()-1 ]; + // Get the corresponding eigenvector + for(unsigned j=0; jset( sqrtn*lambda*maxeig[icomp].first ); + } + + // Parallelism + unsigned rank, stride; + if( serialCalculation() ) { stride=1; rank=0; } + else { rank=comm.Get_rank(); stride=comm.Get_size(); } + + // Derivatives + MultiValue myvals( 2, getNumberOfDerivatives() ); + Matrix mymat_ders( getNumberOfComponents(), getNumberOfDerivatives() ); + // std::vector catoms(2); + unsigned nval = getNumberOfNodes(); mymat_ders=0; + for(unsigned i=rank; igetMatrixIndices( active_elements[i], j, k ); + double tmp1 = 2 * eigenvecs(nval-1,j)*eigenvecs(nval-1,k); + for(unsigned icomp=0; icompretrieveDerivatives( active_elements[i], false, myvals ); + for(unsigned jd=0; jdaddDerivative( i, mymat_ders(j,i) ); - } + for(unsigned j=0; jaddDerivative( i, mymat_ders(j,i) ); + } } -void Sprint::apply(){ +void Sprint::apply() { std::vector& f(modifyForces()); Tensor& v(modifyVirial()); unsigned nat=getNumberOfAtoms(); std::vector forces( 3*getNumberOfAtoms() + 9 ); - for(unsigned i=0;iapplyForce( forces ) ){ - for(unsigned j=0;japplyForce( forces ) ) { + for(unsigned j=0; j0 ) error("errors in DENSITY_THRESHOLD switching function : " + errors ); + if( errors.length()>0 ) error("errors in DENSITY_THRESHOLD switching function : " + errors ); log.printf(" threshold on density of atoms in cylinder equals %s\n",threshold_switch.description().c_str() ); - for(unsigned i=0;isfmax ) sfmax=tsf; - double rsf=cylinder_sw(i,j).get_dmax(); - if( rsf>rfmax ) rfmax=rsf; - } + for(unsigned i=0; isfmax ) sfmax=tsf; + double rsf=cylinder_sw(i,j).get_dmax(); + if( rsf>rfmax ) rfmax=rsf; + } } // Get the width of the bead - HistogramBead bead; bead.isNotPeriodic(); + HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype ); bead.set( 0.0, 1.0, sigma ); double radmax = sfmax/2.0 + bead.getCutoff(); radmax2=radmax*radmax; @@ -144,13 +144,13 @@ AdjacencyMatrixBase(ao) setLinkCellCutoff( sfmax, sqrt( radmax*radmax + rfmax*rfmax ) ); double maxsize=0; - for(unsigned i=0;imaxsize ) maxsize=binw_mat(i,j); - } + for(unsigned i=0; imaxsize ) maxsize=binw_mat(i,j); + } } // Set the maximum number of bins that we will need to compute - maxbins = std::floor( sfmax / maxsize ) + 1; + maxbins = std::floor( sfmax / maxsize ) + 1; // Need to resize functions again here to ensure that vector sizes // are set correctly in AdjacencyMatrixVessel resizeFunctions(); @@ -160,27 +160,27 @@ unsigned TopologyMatrix::getNumberOfQuantities() const { return maxbins+3; } -void TopologyMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ){ +void TopologyMatrix::setupConnector( const unsigned& id, const unsigned& i, const unsigned& j, const std::vector& desc ) { plumed_assert( id<4 ); - if( id==0 ){ - std::string errors; switchingFunction(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) switchingFunction(i,j).set(desc[0],errors); - log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); - } else if( id==1 ){ - std::string errors; cylinder_sw(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i) cylinder_sw(i,j).set(desc[0],errors); - log.printf(" there must be not atoms within the cylinder connections atoms of multicolvar groups %u th and %u th. This cylinder has radius %s \n",i+1,j+1,(cylinder_sw(i,j).description()).c_str() ); - } else if( id==2 ){ - std::string errors; low_sf(j,i).set(desc[0],errors); - if( errors.length()!=0 ) error("problem reading switching function description " + errors); - if( j!=i ) low_sf(i,j).set(desc[0],errors); - log.printf(" %u th and %u th multicolvar groups must be further apart than %s\n",i+1,j+1,(low_sf(j,i).description()).c_str() ); - } else if( id==3 ){ - Tools::convert( desc[0], binw_mat(j,i) ); - if( i!=j ) binw_mat(i,j)=binw_mat(j,i); - log.printf(" cylinder for %u th and %u th multicolvar groups is split into bins of length %f \n",i,j,binw_mat(i,j) ); + if( id==0 ) { + std::string errors; switchingFunction(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) switchingFunction(i,j).set(desc[0],errors); + log.printf(" %u th and %u th multicolvar groups must be within %s\n",i+1,j+1,(switchingFunction(i,j).description()).c_str() ); + } else if( id==1 ) { + std::string errors; cylinder_sw(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i) cylinder_sw(i,j).set(desc[0],errors); + log.printf(" there must be not atoms within the cylinder connections atoms of multicolvar groups %u th and %u th. This cylinder has radius %s \n",i+1,j+1,(cylinder_sw(i,j).description()).c_str() ); + } else if( id==2 ) { + std::string errors; low_sf(j,i).set(desc[0],errors); + if( errors.length()!=0 ) error("problem reading switching function description " + errors); + if( j!=i ) low_sf(i,j).set(desc[0],errors); + log.printf(" %u th and %u th multicolvar groups must be further apart than %s\n",i+1,j+1,(low_sf(j,i).description()).c_str() ); + } else if( id==3 ) { + Tools::convert( desc[0], binw_mat(j,i) ); + if( i!=j ) binw_mat(i,j)=binw_mat(j,i); + log.printf(" cylinder for %u th and %u th multicolvar groups is split into bins of length %f \n",i,j,binw_mat(i,j) ); } } @@ -199,48 +199,48 @@ double TopologyMatrix::compute( const unsigned& tindex, multicolvar::AtomValuePa HistogramBead bead; bead.isNotPeriodic(); bead.setKernelType( kerneltype ); // Initialise to zero density on all bins - for(unsigned bin=0;bin binvals( 1+maxbins ); for(unsigned i=1;imax ){ max=myatoms.getValue(i); vout=i; } + for(unsigned i=3; imax ) { max=myatoms.getValue(i); vout=i; } } // Calculate value and derivative of switching function between atoms 1 and 2 double dfuncl, sw = switchingFunction( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( d1_len, dfuncl ); // Transform the density double df, tsw = threshold_switch.calculate( max, df ); - if( !doNotCalculateDerivatives() ){ - // Factor of d1_len is required here because d1 is normalized - d1 *= d1_len; - addAtomDerivatives( 2+maxbins, 0, -dfuncl*d1, myatoms ); - addAtomDerivatives( 2+maxbins, 1, dfuncl*d1, myatoms ); - myatoms.addBoxDerivatives( 2+maxbins, (-dfuncl)*Tensor(d1,d1) ); - // Update active atoms so that next bit works - updateActiveAtoms( myatoms ); - // Now finish caclulation of derivatives - MultiValue& myvals=myatoms.getUnderlyingMultiValue(); - for(unsigned jd=0;jdradmax2 ) return; + if ( d2.modulo2()>radmax2 ) return; // Now calculate projection of d2 on d1 double proj=dotProduct(d2,d1); // This tells us if we are outside the end of the cylinder @@ -253,66 +253,66 @@ void TopologyMatrix::calculateForThreeAtoms( const unsigned& iat, const Vector& // Return if the projection is outside the length of interest if( proj<-bead.getCutoff() || proj>(lcylinder+bead.getCutoff()) ) return; - // Calculate the excess swiching function + // Calculate the excess swiching function double edf, eval = low_sf( getBaseColvarNumber( myatoms.getIndex(0) ), getBaseColvarNumber( myatoms.getIndex(1) ) ).calculate( excess, edf ); // Calculate the projection on the perpendicular distance from the center of the tube double cm = d2.modulo2() - proj*proj; // Now calculate the density in the cylinder - if( cmbinw*(bin+1)+bead.getCutoff() ) continue; - double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; der /= cellv; - myatoms.addValue( 2+bin, contr*val*eval ); - - if( !doNotCalculateDerivatives() ){ - g1derivf=contr*eval*dc1 + val*eval*der*dd1 + contr*val*de1; - addAtomDerivatives( 2+bin, 0, g1derivf, myatoms ); - g2derivf=contr*eval*dc2 + val*eval*der*dd2 + contr*val*de2; - addAtomDerivatives( 2+bin, 1, g2derivf, myatoms ); - lderivf=contr*eval*dc3 + val*eval*der*dd3 + contr*val*de3; - addAtomDerivatives( 2+bin, iat, lderivf, myatoms ); - // Virial - vir = -Tensor( myatoms.getPosition(0), g1derivf ) - Tensor( myatoms.getPosition(1), g2derivf ) - Tensor( myatoms.getPosition(iat), lderivf ); - myatoms.addBoxDerivatives( 2+bin, vir ); - } + if( cmbinw*(bin+1)+bead.getCutoff() ) continue; + double der, contr=bead.calculateWithCutoff( proj, der ) / cellv; der /= cellv; + myatoms.addValue( 2+bin, contr*val*eval ); + + if( !doNotCalculateDerivatives() ) { + g1derivf=contr*eval*dc1 + val*eval*der*dd1 + contr*val*de1; + addAtomDerivatives( 2+bin, 0, g1derivf, myatoms ); + g2derivf=contr*eval*dc2 + val*eval*der*dd2 + contr*val*de2; + addAtomDerivatives( 2+bin, 1, g2derivf, myatoms ); + lderivf=contr*eval*dc3 + val*eval*der*dd3 + contr*val*de3; + addAtomDerivatives( 2+bin, iat, lderivf, myatoms ); + // Virial + vir = -Tensor( myatoms.getPosition(0), g1derivf ) - Tensor( myatoms.getPosition(1), g2derivf ) - Tensor( myatoms.getPosition(iat), lderivf ); + myatoms.addBoxDerivatives( 2+bin, vir ); } + } } } diff --git a/src/analysis/Analysis.cpp b/src/analysis/Analysis.cpp index 4d76df935a..989981ab6b 100644 --- a/src/analysis/Analysis.cpp +++ b/src/analysis/Analysis.cpp @@ -34,7 +34,7 @@ namespace PLMD { namespace analysis { -void Analysis::registerKeywords( Keywords& keys ){ +void Analysis::registerKeywords( Keywords& keys ) { vesselbase::ActionWithAveraging::registerKeywords( keys ); keys.use("ARG"); keys.reset_style("ARG","optional"); keys.add("atoms","ATOMS","the atoms whose positions we are tracking for the purpose of analysing the data"); @@ -44,36 +44,36 @@ void Analysis::registerKeywords( Keywords& keys ){ keys.addFlag("WRITE_CHECKPOINT",false,"write out a checkpoint so that the analysis can be restarted in a later run"); keys.add("hidden","REUSE_DATA_FROM","eventually this will allow you to analyse the same set of data multiple times"); keys.add("hidden","IGNORE_REWEIGHTING","this allows you to ignore any reweighting factors"); - keys.use("RESTART"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); keys.remove("TOL"); + keys.use("RESTART"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); keys.remove("TOL"); } Analysis::Analysis(const ActionOptions&ao): -Action(ao), -ActionWithAveraging(ao), -nomemory(true), -write_chq(false), -reusing_data(false), -ignore_reweight(false), -idata(0), + Action(ao), + ActionWithAveraging(ao), + nomemory(true), + write_chq(false), + reusing_data(false), + ignore_reweight(false), + idata(0), //firstAnalysisDone(false), //old_norm(0.0), -ofmt("%f"), -current_args(getNumberOfArguments()), -argument_names(getNumberOfArguments()) + ofmt("%f"), + current_args(getNumberOfArguments()), + argument_names(getNumberOfArguments()) { parse("FMT",ofmt); // Read the format for output files // Make a vector containing all the argument names - for(unsigned i=0;igetName(); + for(unsigned i=0; igetName(); // Read in the metric style parse("METRIC",metricname); std::vector atom_numbers; ReferenceConfiguration* checkref=metricRegister().create( metricname ); // Check if we should read atoms ReferenceAtoms* hasatoms=dynamic_cast( checkref ); - if( hasatoms ){ - parseAtomList("ATOMS",atom_numbers); requestAtoms(atom_numbers); - log.printf(" monitoring positions of atoms "); - for(unsigned i=0;i( checkref ); @@ -83,174 +83,174 @@ argument_names(getNumberOfArguments()) delete checkref; std::string prev_analysis; parse("REUSE_DATA_FROM",prev_analysis); - if( prev_analysis.length()>0 ){ - reusing_data=true; - mydatastash=plumed.getActionSet().selectWithLabel( prev_analysis ); - if( !mydatastash ) error("could not find analysis action named " + prev_analysis ); - parseFlag("IGNORE_REWEIGHTING",ignore_reweight); - if( ignore_reweight ) log.printf(" reusing data stored by %s but ignoring all reweighting\n",prev_analysis.c_str() ); - else log.printf(" reusing data stored by %s\n",prev_analysis.c_str() ); - } else { - parse("RUN",freq); - if( freq==0 ){ - log.printf(" analyzing all data in trajectory\n"); - } else { - if( freq%getStride()!=0 ) error("frequncy of running is not a multiple of the stride"); - log.printf(" running analysis every %u steps\n",freq); - ndata=freq/getStride(); data.resize( ndata ); logweights.resize( ndata ); - for(unsigned i=0;i( metricname ); - data[i]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); - } - } - parseFlag("WRITE_CHECKPOINT",write_chq); - if( write_chq ){ - write_chq=false; - warning("ignoring WRITE_CHECKPOINT flag because we are analyzing all data"); - } - - // We need no restart file if we are just collecting data and analyzing all of it - std::string filename = getName() + "_" + getLabel() + ".chkpnt"; - if( write_chq ) rfile.link(*this); - if( getRestart() ){ - if( !write_chq ) warning("restarting without writing a checkpoint file is somewhat strange"); - // Read in data from input file - readDataFromFile( filename ); - // Setup the restart file (append mode) - if( write_chq ) rfile.open( filename.c_str() ); // In append mode automatically because of restart - // Run the analysis if we stoped in the middle of it last time - log.printf(" restarting analysis with %u points read from restart file\n",idata); - } else if( write_chq ){ - // Setup the restart file (delete any old one) - rfile.open( filename.c_str() ); // In overwrite mode automatically because there is no restart - } - if( write_chq ){ - //rfile.addConstantField("old_normalization"); - for(unsigned i=0;i0 ) { + reusing_data=true; + mydatastash=plumed.getActionSet().selectWithLabel( prev_analysis ); + if( !mydatastash ) error("could not find analysis action named " + prev_analysis ); + parseFlag("IGNORE_REWEIGHTING",ignore_reweight); + if( ignore_reweight ) log.printf(" reusing data stored by %s but ignoring all reweighting\n",prev_analysis.c_str() ); + else log.printf(" reusing data stored by %s\n",prev_analysis.c_str() ); + } else { + parse("RUN",freq); + if( freq==0 ) { + log.printf(" analyzing all data in trajectory\n"); + } else { + if( freq%getStride()!=0 ) error("frequncy of running is not a multiple of the stride"); + log.printf(" running analysis every %u steps\n",freq); + ndata=freq/getStride(); data.resize( ndata ); logweights.resize( ndata ); + for(unsigned i=0; i( metricname ); + data[i]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); } + } + parseFlag("WRITE_CHECKPOINT",write_chq); + if( write_chq ) { + write_chq=false; + warning("ignoring WRITE_CHECKPOINT flag because we are analyzing all data"); + } + + // We need no restart file if we are just collecting data and analyzing all of it + std::string filename = getName() + "_" + getLabel() + ".chkpnt"; + if( write_chq ) rfile.link(*this); + if( getRestart() ) { + if( !write_chq ) warning("restarting without writing a checkpoint file is somewhat strange"); + // Read in data from input file + readDataFromFile( filename ); + // Setup the restart file (append mode) + if( write_chq ) rfile.open( filename.c_str() ); // In append mode automatically because of restart + // Run the analysis if we stoped in the middle of it last time + log.printf(" restarting analysis with %u points read from restart file\n",idata); + } else if( write_chq ) { + // Setup the restart file (delete any old one) + rfile.open( filename.c_str() ); // In overwrite mode automatically because there is no restart + } + if( write_chq ) { + //rfile.addConstantField("old_normalization"); + for(unsigned i=0; iset( mypdb ); - data[idata]->parse("TIME",tstep); - if( !first && ((tstep-oldtstep) - getStride()*plumed.getAtoms().getTimeStep())>plumed.getAtoms().getTimeStep() ){ - error("frequency of data storage in " + filename + " is not equal to frequency of data storage plumed.dat file"); - } - data[idata]->parse("LOG_WEIGHT",logweights[idata]); - //data[idata]->parse("OLD_NORM",old_norm); - data[idata]->checkRead(); - idata++; first=false; oldtstep=tstep; - } else{ - break; - } - } + if(fp!=NULL) { + double tstep, oldtstep; + bool do_read=true, first=true; + while (do_read) { + PDB mypdb; + do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); + if(do_read) { + data[idata]->set( mypdb ); + data[idata]->parse("TIME",tstep); + if( !first && ((tstep-oldtstep) - getStride()*plumed.getAtoms().getTimeStep())>plumed.getAtoms().getTimeStep() ) { + error("frequency of data storage in " + filename + " is not equal to frequency of data storage plumed.dat file"); + } + data[idata]->parse("LOG_WEIGHT",logweights[idata]); + //data[idata]->parse("OLD_NORM",old_norm); + data[idata]->checkRead(); + idata++; first=false; oldtstep=tstep; + } else { + break; + } + } fclose(fp); } // if(old_norm>0) firstAnalysisDone=true; } -void Analysis::parseOutputFile( const std::string& key, std::string& filename ){ +void Analysis::parseOutputFile( const std::string& key, std::string& filename ) { parse(key,filename); if(filename=="dont output") return; - if( !getRestart() ){ - OFile ofile; ofile.link(*this); - ofile.setBackupString("analysis"); - ofile.backupAllFiles(filename); - } + if( !getRestart() ) { + OFile ofile; ofile.link(*this); + ofile.setBackupString("analysis"); + ofile.backupAllFiles(filename); + } } -void Analysis::accumulate(){ +void Analysis::accumulate() { // Don't store the first step (also don't store if we are getting data from elsewhere) if( getStep()==0 || reusing_data ) return; // This is used when we have a full quota of data from the first run - if( freq>0 && idata==logweights.size() ) return; + if( freq>0 && idata==logweights.size() ) return; // Get the arguments ready to transfer to reference configuration - for(unsigned i=0;i0){ - // Get the arguments and store them in a vector of vectors - data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); - logweights[idata] = lweight; + if( freq>0) { + // Get the arguments and store them in a vector of vectors + data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); + logweights[idata] = lweight; } else { - data.push_back( metricRegister().create( metricname ) ); - plumed_dbg_assert( data.size()==idata+1 ); - data[idata]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); - data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); - logweights.push_back(lweight); - } + data.push_back( metricRegister().create( metricname ) ); + plumed_dbg_assert( data.size()==idata+1 ); + data[idata]->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); + data[idata]->setReferenceConfig( getPositions(), current_args, getMetric() ); + logweights.push_back(lweight); + } // Write data to checkpoint file - if( write_chq ){ - rfile.rewind(); - data[idata]->print( rfile, getTime(), logweights[idata], atoms.getUnits().getLength()/0.1, 1.0 ); //old_norm ); - rfile.flush(); + if( write_chq ) { + rfile.rewind(); + data[idata]->print( rfile, getTime(), logweights[idata], atoms.getUnits().getLength()/0.1, 1.0 ); //old_norm ); + rfile.flush(); } // Increment data counter idata++; } -Analysis::~Analysis(){ - for(unsigned i=0;i Analysis::getMetric() const { // Add more exotic metrics in here -- FlexibleHill for instance std::vector empty; - if( metricname=="EUCLIDEAN" ){ - empty.resize( getNumberOfArguments(), 1.0 ); + if( metricname=="EUCLIDEAN" ) { + empty.resize( getNumberOfArguments(), 1.0 ); } return empty; } double Analysis::getWeight( const unsigned& idata ) const { - if( !reusing_data ){ - plumed_dbg_assert( idatagetWeight(); + if( !reusing_data ) { + plumed_dbg_assert( idatagetWeight(); } else { - return mydatastash->getWeight(idata); + return mydatastash->getWeight(idata); } } -void Analysis::finalizeWeights( const bool& ignore_weights ){ +void Analysis::finalizeWeights( const bool& ignore_weights ) { // Check that we have the correct ammount of data if( !reusing_data && idata!=logweights.size() ) error("something has gone wrong. Am trying to run analysis but I don't have sufficient data"); double norm=0; // Reset normalization constant - if( ignore_weights ){ - for(unsigned i=0;isetWeight(1.0); norm+=1.0; - } - } else if( nomemory ){ - // Find the maximum weight - double maxweight=logweights[0]; - for(unsigned i=1;imaxweight) maxweight=logweights[i]; - } - // Calculate normalization constant - for(unsigned i=0;isetWeight( exp( logweights[i]-maxweight ) ); - } - // Calculate normalized weights (with memory) + if( ignore_weights ) { + for(unsigned i=0; isetWeight(1.0); norm+=1.0; + } + } else if( nomemory ) { + // Find the maximum weight + double maxweight=logweights[0]; + for(unsigned i=1; imaxweight) maxweight=logweights[i]; + } + // Calculate normalization constant + for(unsigned i=0; isetWeight( exp( logweights[i]-maxweight ) ); + } + // Calculate normalized weights (with memory) } else { - plumed_merror("analysis can now only support block averages"); - // if( !firstAnalysisDone ) - // finalizeWeightsNoLogSums( 1.0 ); - // else finalizeWeightsNoLogSums( old_norm ); + plumed_merror("analysis can now only support block averages"); + // if( !firstAnalysisDone ) + // finalizeWeightsNoLogSums( 1.0 ); + // else finalizeWeightsNoLogSums( old_norm ); } } @@ -264,26 +264,26 @@ void Analysis::finalizeWeights( const bool& ignore_weights ){ void Analysis::getDataPoint( const unsigned& idata, std::vector& point, double& weight ) const { plumed_dbg_assert( getNumberOfAtoms()==0 ); - if( !reusing_data ){ - plumed_dbg_assert( idatagetReferenceArgument(i); - weight=data[idata]->getWeight(); + if( !reusing_data ) { + plumed_dbg_assert( idatagetReferenceArgument(i); + weight=data[idata]->getWeight(); } else { - return mydatastash->getDataPoint( idata, point, weight ); + return mydatastash->getDataPoint( idata, point, weight ); } } -void Analysis::runAnalysis(){ +void Analysis::runAnalysis() { // Note : could add multiple walkers here - simply read in the data from all // other walkers here if we are writing the check points. - // Calculate the final weights from the log weights - if( !reusing_data ){ - finalizeWeights( ignore_reweight ); + // Calculate the final weights from the log weights + if( !reusing_data ) { + finalizeWeights( ignore_reweight ); } else { - mydatastash->finalizeWeights( ignore_reweight ); - // norm=mydatastash->retrieveNorm(); + mydatastash->finalizeWeights( ignore_reweight ); + // norm=mydatastash->retrieveNorm(); } // This ensures everything is set up to run the calculation // if( single_run ) setAnalysisStride( single_run, freq ); @@ -294,15 +294,15 @@ void Analysis::runAnalysis(){ } -void Analysis::performOperations( const bool& from_update ){ +void Analysis::performOperations( const bool& from_update ) { accumulate(); - if( freq>0 ){ - if( getStep()>0 && getStep()%freq==0 ) runAnalysis(); - else if( idata==logweights.size() ) error("something has gone wrong. Probably a wrong initial time on restart"); + if( freq>0 ) { + if( getStep()>0 && getStep()%freq==0 ) runAnalysis(); + else if( idata==logweights.size() ) error("something has gone wrong. Probably a wrong initial time on restart"); } } -bool Analysis::getPeriodicityInformation(const unsigned& i, std::string& dmin, std::string& dmax){ +bool Analysis::getPeriodicityInformation(const unsigned& i, std::string& dmin, std::string& dmax) { bool isperiodic=getPntrToArgument(i)->isPeriodic(); if(isperiodic) getPntrToArgument(i)->getDomain(dmin,dmax); return isperiodic; @@ -311,7 +311,7 @@ bool Analysis::getPeriodicityInformation(const unsigned& i, std::string& dmin, s void Analysis::runFinalJobs() { if( freq>0 ) return; if( getNumberOfDataPoints()==0 ) error("no data is available for analysis"); - runAnalysis(); + runAnalysis(); } } diff --git a/src/analysis/Analysis.h b/src/analysis/Analysis.h index 2a6c371afb..44b6082777 100644 --- a/src/analysis/Analysis.h +++ b/src/analysis/Analysis.h @@ -34,7 +34,7 @@ namespace analysis { /** \ingroup INHERIT -This is the abstract base class to use for implementing new methods for analyzing the trajectory, within it there +This is the abstract base class to use for implementing new methods for analyzing the trajectory, within it there is information as to how to go about implementing a new analysis method. */ @@ -82,7 +82,7 @@ class Analysis : public vesselbase::ActionWithAveraging { /// Get the metric if we are using malonobius distance and flexible hill std::vector getMetric() const ; protected: -/// List of argument names +/// List of argument names std::vector argument_names; /// This is used to read in output file names for analysis methods. When /// this method is used and the calculation is not restarted old analysis @@ -98,10 +98,10 @@ class Analysis : public vesselbase::ActionWithAveraging { double getWeight( const unsigned& idata ) const ; /// Retrieve the ith point void getDataPoint( const unsigned& idata, std::vector& point, double& weight ) const ; -/// Returns true if argument i is periodic together with the domain +/// Returns true if argument i is periodic together with the domain bool getPeriodicityInformation(const unsigned& i, std::string& dmin, std::string& dmax); /// Are we analyzing each data block separately (if we are not this also returns the old normalization ) - bool usingMemory() const; + bool usingMemory() const; /// Return the format to use for numbers in output files std::string getOutputFormat() const ; /// Finalize the weights without using the log sums @@ -110,14 +110,14 @@ class Analysis : public vesselbase::ActionWithAveraging { static void registerKeywords( Keywords& keys ); explicit Analysis(const ActionOptions&); ~Analysis(); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void accumulate(); void performOperations( const bool& from_update ); virtual void performAnalysis()=0; void runFinalJobs(); void runAnalysis(); - bool isPeriodic(){ plumed_error(); return false; } + bool isPeriodic() { plumed_error(); return false; } /// Convert the stored log weights to proper weights virtual void finalizeWeights( const bool& ignore_weights ); }; @@ -129,20 +129,20 @@ std::string Analysis::getMetricName() const { inline unsigned Analysis::getNumberOfDataPoints() const { - if( !reusing_data ){ - plumed_dbg_assert( data.size()==logweights.size() ); - return data.size(); + if( !reusing_data ) { + plumed_dbg_assert( data.size()==logweights.size() ); + return data.size(); } else { - return mydatastash->getNumberOfDataPoints(); + return mydatastash->getNumberOfDataPoints(); } } inline bool Analysis::usingMemory() const { - if( !reusing_data ){ - return !nomemory; + if( !reusing_data ) { + return !nomemory; } else { - return mydatastash->usingMemory(); + return mydatastash->usingMemory(); } } diff --git a/src/analysis/AnalysisWithLandmarks.cpp b/src/analysis/AnalysisWithLandmarks.cpp index 4ff419e922..9cd67c52f4 100644 --- a/src/analysis/AnalysisWithLandmarks.cpp +++ b/src/analysis/AnalysisWithLandmarks.cpp @@ -25,7 +25,7 @@ //+PLUMEDOC INTERNAL landmarkselection /* -This is currently a filler page. +This is currently a filler page. Just use LANDMARKS=ALL. More complex versions will appear in later versions. @@ -35,37 +35,37 @@ Just use LANDMARKS=ALL. More complex versions will appear in later versions. namespace PLMD { namespace analysis { -void AnalysisWithLandmarks::registerKeywords( Keywords& keys ){ +void AnalysisWithLandmarks::registerKeywords( Keywords& keys ) { Analysis::registerKeywords( keys ); keys.add("compulsory","LANDMARKS","ALL","only use a subset of the data that was collected. " - "For more information on the landmark selection algorithms that are available in " - "plumed see \\ref landmarkselection."); + "For more information on the landmark selection algorithms that are available in " + "plumed see \\ref landmarkselection."); } AnalysisWithLandmarks::AnalysisWithLandmarks( const ActionOptions& ao): -Action(ao), -Analysis(ao), -data_to_analyze(NULL) + Action(ao), + Analysis(ao), + data_to_analyze(NULL) { - std::string linput; parse("LANDMARKS",linput); - std::vector words=Tools::getWords(linput); - landmarkSelector=landmarkRegister().create( LandmarkSelectionOptions(words,this) ); - log.printf(" %s\n", landmarkSelector->description().c_str() ); + std::string linput; parse("LANDMARKS",linput); + std::vector words=Tools::getWords(linput); + landmarkSelector=landmarkRegister().create( LandmarkSelectionOptions(words,this) ); + log.printf(" %s\n", landmarkSelector->description().c_str() ); } -AnalysisWithLandmarks::~AnalysisWithLandmarks(){ - delete landmarkSelector; +AnalysisWithLandmarks::~AnalysisWithLandmarks() { + delete landmarkSelector; } -void AnalysisWithLandmarks::setDataToAnalyze( MultiReferenceBase* mydata ){ - data_to_analyze=mydata; +void AnalysisWithLandmarks::setDataToAnalyze( MultiReferenceBase* mydata ) { + data_to_analyze=mydata; } unsigned AnalysisWithLandmarks::getNumberOfLandmarks() const { return landmarkSelector->getNumberOfLandmarks(); } -void AnalysisWithLandmarks::performAnalysis(){ +void AnalysisWithLandmarks::performAnalysis() { plumed_assert( data_to_analyze ); landmarkSelector->selectLandmarks( data_to_analyze ); analyzeLandmarks(); diff --git a/src/analysis/AnalysisWithLandmarks.h b/src/analysis/AnalysisWithLandmarks.h index 3eb2c6a023..b129a4d01e 100644 --- a/src/analysis/AnalysisWithLandmarks.h +++ b/src/analysis/AnalysisWithLandmarks.h @@ -33,12 +33,12 @@ namespace analysis { class LandmarkSelectionBase; class AnalysisWithLandmarks : public Analysis { -friend class LandmarkSelectionBase; -friend class CopyAllFrames; + friend class LandmarkSelectionBase; + friend class CopyAllFrames; private: /// This object selects landmarks from the data LandmarkSelectionBase* landmarkSelector; -/// A pointer to the data we are analyzing +/// A pointer to the data we are analyzing MultiReferenceBase* data_to_analyze; protected: /// Set the data that needs to be analyzed @@ -53,7 +53,7 @@ friend class CopyAllFrames; void performAnalysis(); virtual void analyzeLandmarks()=0; /// This does nothing - void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; + void performTask( const unsigned&, const unsigned&, MultiValue& ) const ; }; } diff --git a/src/analysis/Average.cpp b/src/analysis/Average.cpp index ec2da2ad28..c96b2556bb 100644 --- a/src/analysis/Average.cpp +++ b/src/analysis/Average.cpp @@ -23,8 +23,8 @@ #include "core/ActionRegister.h" #include "AverageVessel.h" -//+PLUMEDOC GRIDCALC AVERAGE -/* +//+PLUMEDOC GRIDCALC AVERAGE +/* Calculate the ensemble average of a collective variable The ensemble average for a non-periodic, collective variable, \f$s\f$ is given by the following expression: @@ -34,8 +34,8 @@ The ensemble average for a non-periodic, collective variable, \f$s\f$ is given b \f] Here the sum runs over a the trajectory and \f$s(t')\f$ is used to denote the value of the collective variable -at time \f$t'\f$. The final quantity evalulated is a weighted -average as the weights, \f$w(t')\f$, allow us to negate the effect any bias might have on the region of phase space +at time \f$t'\f$. The final quantity evalulated is a weighted +average as the weights, \f$w(t')\f$, allow us to negate the effect any bias might have on the region of phase space sampled by the system. This is discussed in the section of the manual on \ref Analysis. When the variable is periodic (e.g. \ref TORSION) and has a value, \f$s\f$, in \f$a \le s \le b\f$ the ensemble average is evaluated using: @@ -47,12 +47,12 @@ When the variable is periodic (e.g. \ref TORSION) and has a value, \f$s\f$, in \ \par Examples The following example calculates the ensemble average for the distance between atoms 1 and 2 -and output this to a file called COLVAR. In this example it is assumed that no bias is acting -on the system and that the weights, \f$w(t')\f$ in the formulae above can thus all be set equal -to one. +and output this to a file called COLVAR. In this example it is assumed that no bias is acting +on the system and that the weights, \f$w(t')\f$ in the formulae above can thus all be set equal +to one. \verbatim -d1: DISTANCE ATOMS=1,2 +d1: DISTANCE ATOMS=1,2 d1a: AVERAGE ARG=d1 PRINT ARG=d1a FILE=colvar STRIDE=100 \endverbatim @@ -60,23 +60,23 @@ PRINT ARG=d1a FILE=colvar STRIDE=100 The following example calculates the ensemble average for the torsional angle involving atoms 1, 2, 3 and 4. At variance with the previous example this quantity is periodic so the second formula in the above introduction is used to calculate the average. Furthermore, by using the CLEAR keyword we have specified that block averages -are to be calculated. Consequently, after 100 steps all the information aquired thus far in the simulation is -forgotten and the process of averaging is begun again. The quantities output in the colvar file are thus the +are to be calculated. Consequently, after 100 steps all the information aquired thus far in the simulation is +forgotten and the process of averaging is begun again. The quantities output in the colvar file are thus the block averages taken over the first 100 frames of the trajectory, the block average over the second 100 frames of trajectory and so on. \verbatim -t1: TORSION ATOMS=1,2,3,4 +t1: TORSION ATOMS=1,2,3,4 t1a: AVERAGE ARG=t1 CLEAR=100 PRINT ARG=t1a FILE=colvar STRIDE=100 \endverbatim This third example incorporates a bias. Notice that the effect the bias has on the ensemble average is removed by taking advantage of the \ref REWEIGHT_BIAS method. The final ensemble averages output to the file are thus block ensemble averages for the -unbiased canononical ensemble at a temperature of 300 K. +unbiased canononical ensemble at a temperature of 300 K. \verbatim -t1: TORSION ATOMS=1,2,3,4 +t1: TORSION ATOMS=1,2,3,4 RESTRAINT ARG=t1 AT=pi KAPPA=100. ww: REWEIGHT_BIAS TEMP=300 t1a: AVERAGE ARG=t1 LOGWEIGHTS=ww CLEAR=100 @@ -95,47 +95,47 @@ class Average : public vesselbase::ActionWithAveraging { public: static void registerKeywords( Keywords& keys ); explicit Average( const ActionOptions& ); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void performOperations( const bool& from_update ); void finishAveraging(); - bool isPeriodic(){ return false; } - void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); } + bool isPeriodic() { return false; } + void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); } }; PLUMED_REGISTER_ACTION(Average,"AVERAGE") -void Average::registerKeywords( Keywords& keys ){ +void Average::registerKeywords( Keywords& keys ) { vesselbase::ActionWithAveraging::registerKeywords( keys ); keys.use("ARG"); - keys.remove("SERIAL"); keys.remove("LOWMEM"); + keys.remove("SERIAL"); keys.remove("LOWMEM"); } Average::Average( const ActionOptions& ao ): -Action(ao), -ActionWithAveraging(ao) + Action(ao), + ActionWithAveraging(ao) { - addValue(); // Create a value so that we can output the average - if( getNumberOfArguments()!=1 ) error("only one quantity can be averaged at a time"); - std::string instring; - if( getPntrToArgument(0)->isPeriodic() ){ - std::string min, max; getPntrToArgument(0)->getDomain(min,max); - instring = "PERIODIC=" + min + "," + max; setPeriodic( min, max ); - } else { - setNotPeriodic(); - } - // Create a vessel to hold the average - vesselbase::VesselOptions da("myaverage","",-1,instring,this); - Keywords keys; AverageVessel::registerKeywords( keys ); - vesselbase::VesselOptions dar( da, keys ); - myaverage = new AverageVessel(dar); setAveragingAction( myaverage, false ); + addValue(); // Create a value so that we can output the average + if( getNumberOfArguments()!=1 ) error("only one quantity can be averaged at a time"); + std::string instring; + if( getPntrToArgument(0)->isPeriodic() ) { + std::string min, max; getPntrToArgument(0)->getDomain(min,max); + instring = "PERIODIC=" + min + "," + max; setPeriodic( min, max ); + } else { + setNotPeriodic(); + } + // Create a vessel to hold the average + vesselbase::VesselOptions da("myaverage","",-1,instring,this); + Keywords keys; AverageVessel::registerKeywords( keys ); + vesselbase::VesselOptions dar( da, keys ); + myaverage = new AverageVessel(dar); setAveragingAction( myaverage, false ); } -void Average::performOperations( const bool& from_update ){ - myaverage->accumulate( cweight, getArgument(0) ); +void Average::performOperations( const bool& from_update ) { + myaverage->accumulate( cweight, getArgument(0) ); } -void Average::finishAveraging(){ - setValue( myaverage->getAverage() ); +void Average::finishAveraging() { + setValue( myaverage->getAverage() ); } } diff --git a/src/analysis/AverageVessel.cpp b/src/analysis/AverageVessel.cpp index 1361696539..96e4a72fe0 100644 --- a/src/analysis/AverageVessel.cpp +++ b/src/analysis/AverageVessel.cpp @@ -24,30 +24,30 @@ namespace PLMD { namespace analysis { -void AverageVessel::registerKeywords( Keywords& keys ){ +void AverageVessel::registerKeywords( Keywords& keys ) { vesselbase::AveragingVessel::registerKeywords( keys ); keys.add("optional","PERIODIC","is the quantity being averaged periodic and what is its domain"); } AverageVessel::AverageVessel( const vesselbase::VesselOptions& da): -AveragingVessel(da) + AveragingVessel(da) { parseVector("PERIODIC",domain); plumed_assert( domain.size()==2 || domain.size()==0 ); } -void AverageVessel::resize(){ - resizeBuffer(0); +void AverageVessel::resize() { + resizeBuffer(0); if( domain.size()==2 ) setDataSize(2); else setDataSize(1); } -void AverageVessel::accumulate( const double& weight, const double& val ){ - if( domain.size()==2 ){ - // Average with Berry Phase - double tval = 2*pi*( val - domain[0] ) / ( domain[1] - domain[0] ); - addDataElement( 0, weight*sin(tval) ); addDataElement( 1, weight*cos(tval) ); - } else addDataElement( 0, weight*val ); +void AverageVessel::accumulate( const double& weight, const double& val ) { + if( domain.size()==2 ) { + // Average with Berry Phase + double tval = 2*pi*( val - domain[0] ) / ( domain[1] - domain[0] ); + addDataElement( 0, weight*sin(tval) ); addDataElement( 1, weight*cos(tval) ); + } else addDataElement( 0, weight*val ); } double AverageVessel::getAverage() const { diff --git a/src/analysis/AverageVessel.h b/src/analysis/AverageVessel.h index 6b1f239712..3b056b8c48 100644 --- a/src/analysis/AverageVessel.h +++ b/src/analysis/AverageVessel.h @@ -29,21 +29,21 @@ namespace analysis { class AverageVessel : public vesselbase::AveragingVessel { private: - std::vector domain; + std::vector domain; public: /// keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Constructor - explicit AverageVessel( const vesselbase::VesselOptions& ); + explicit AverageVessel( const vesselbase::VesselOptions& ); /// Set the size of the data vessel - void resize(); + void resize(); /// This does nothing - void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; - std::string description(){ return ""; } + void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; + std::string description() { return ""; } /// Accumulate the average - void accumulate( const double& weight, const double& val ); + void accumulate( const double& weight, const double& val ); /// Get the average value - double getAverage() const ; + double getAverage() const ; }; } diff --git a/src/analysis/ClassicalMultiDimensionalScaling.cpp b/src/analysis/ClassicalMultiDimensionalScaling.cpp index 6326dab170..93bb25f1d4 100644 --- a/src/analysis/ClassicalMultiDimensionalScaling.cpp +++ b/src/analysis/ClassicalMultiDimensionalScaling.cpp @@ -29,26 +29,26 @@ namespace analysis { //+PLUMEDOC DIMRED CLASSICAL_MDS /* -Create a low-dimensional projection of a trajectory using the classical multidimensional +Create a low-dimensional projection of a trajectory using the classical multidimensional scaling algorithm. -Multidimensional scaling (MDS) is similar to what is done when you make a map. You start with distances -between London, Belfast, Paris and Dublin and then you try to arrange points on a piece of paper so that the (suitably scaled) -distances between the points in your map representing each of those cities are related to the true distances between the cities. -Stating this more mathematically MDS endeavors to find an isometry -between points distributed in a high-dimensional space and a set of points distributed in a low-dimensional plane. -In other words, if we have \f$M\f$ \f$D\f$-dimensional points, \f$\mathbf{X}\f$, -and we can calculate dissimilarities between pairs them, \f$D_{ij}\f$, we can, with an MDS calculation, try to create \f$M\f$ projections, -\f$\mathbf{x}\f$, of the high dimensionality points in a \f$d\f$-dimensional linear space by trying to arrange the projections so that the +Multidimensional scaling (MDS) is similar to what is done when you make a map. You start with distances +between London, Belfast, Paris and Dublin and then you try to arrange points on a piece of paper so that the (suitably scaled) +distances between the points in your map representing each of those cities are related to the true distances between the cities. +Stating this more mathematically MDS endeavors to find an isometry +between points distributed in a high-dimensional space and a set of points distributed in a low-dimensional plane. +In other words, if we have \f$M\f$ \f$D\f$-dimensional points, \f$\mathbf{X}\f$, +and we can calculate dissimilarities between pairs them, \f$D_{ij}\f$, we can, with an MDS calculation, try to create \f$M\f$ projections, +\f$\mathbf{x}\f$, of the high dimensionality points in a \f$d\f$-dimensional linear space by trying to arrange the projections so that the Euclidean distances between pairs of them, \f$d_{ij}\f$, resemble the dissimilarities between the high dimensional points. In short we minimize: \f[ \chi^2 = \sum_{i \ne j} \left( D_{ij} - d_{ij} \right)^2 \f] -where \f$D_{ij}\f$ is the distance between point \f$X^{i}\f$ and point \f$X^{j}\f$ and \f$d_{ij}\f$ is the distance between the projection -of \f$X^{i}\f$, \f$x^i\f$, and the projection of \f$X^{j}\f$, \f$x^j\f$. A tutorial on this approach can be used to analyse simulations -can be found in the tutorial \ref belfast-3 and in the following short video. +where \f$D_{ij}\f$ is the distance between point \f$X^{i}\f$ and point \f$X^{j}\f$ and \f$d_{ij}\f$ is the distance between the projection +of \f$X^{i}\f$, \f$x^i\f$, and the projection of \f$X^{j}\f$, \f$x^j\f$. A tutorial on this approach can be used to analyse simulations +can be found in the tutorial \ref belfast-3 and in the following short video. \par Examples @@ -58,34 +58,34 @@ The RMSD distance between atoms 1-256 have moved is used to measure the distance \verbatim CLASSICAL_MDS ... ATOMS=1-256 - METRIC=OPTIMAL-FAST + METRIC=OPTIMAL-FAST USE_ALL_DATA NLOW_DIM=2 OUTPUT_FILE=rmsd-embed ... CLASSICAL_MDS \endverbatim -The following section is for people who are interested in how this method works in detail. A solid understanding of this material is -not necessary to use MDS. +The following section is for people who are interested in how this method works in detail. A solid understanding of this material is +not necessary to use MDS. \section dim-sec Method of optimisation -The stress function can be minimized using a standard optimization algorithm such as conjugate gradients or steepest descent. -However, it is more common to do this minimization using a technique known as classical scaling. Classical scaling works by +The stress function can be minimized using a standard optimization algorithm such as conjugate gradients or steepest descent. +However, it is more common to do this minimization using a technique known as classical scaling. Classical scaling works by recognizing that each of the distances $D_{ij}$ in the above sum can be written as: \f[ -D_{ij}^2 = \sum_{\alpha} (X^i_\alpha - X^j_\alpha)^2 = \sum_\alpha (X^i_\alpha)^2 + (X^j_\alpha)^2 - 2X^i_\alpha X^j_\alpha +D_{ij}^2 = \sum_{\alpha} (X^i_\alpha - X^j_\alpha)^2 = \sum_\alpha (X^i_\alpha)^2 + (X^j_\alpha)^2 - 2X^i_\alpha X^j_\alpha \f] -We can use this expression and matrix algebra to calculate multiple distances at once. For instance if we have three points, +We can use this expression and matrix algebra to calculate multiple distances at once. For instance if we have three points, \f$\mathbf{X}\f$, we can write distances between them as: \f{eqnarray*}{ D^2(\mathbf{X}) &=& \left[ \begin{array}{ccc} 0 & d_{12}^2 & d_{13}^2 \\ d_{12}^2 & 0 & d_{23}^2 \\ -d_{13}^2 & d_{23}^2 & 0 +d_{13}^2 & d_{23}^2 & 0 \end{array}\right] \\ &=& \sum_\alpha \left[ \begin{array}{ccc} @@ -103,19 +103,19 @@ X^1_\alpha X^1_\alpha & X^1_\alpha X^2_\alpha & X^1_\alpha X^3_\alpha \\ X^2_\alpha X^1_\alpha & X^2_\alpha X^2_\alpha & X^2_\alpha X^3_\alpha \\ X^1_\alpha X^3_\alpha & X^3_\alpha X^2_\alpha & X^3_\alpha X^3_\alpha \end{array}\right] \nonumber \\ -&=& \mathbf{c 1^T} + \mathbf{1 c^T} - 2 \sum_\alpha \mathbf{x}_a \mathbf{x}^T_a = \mathbf{c 1^T} + \mathbf{1 c^T} - 2\mathbf{X X^T} +&=& \mathbf{c 1^T} + \mathbf{1 c^T} - 2 \sum_\alpha \mathbf{x}_a \mathbf{x}^T_a = \mathbf{c 1^T} + \mathbf{1 c^T} - 2\mathbf{X X^T} \f} -This last equation can be extended to situations when we have more than three points. In it \f$\mathbf{X}\f$ is a matrix that has -one high-dimensional point on each of its rows and \f$\mathbf{X^T}\f$ is its transpose. \f$\mathbf{1}\f$ is an \f$M \times 1\f$ vector +This last equation can be extended to situations when we have more than three points. In it \f$\mathbf{X}\f$ is a matrix that has +one high-dimensional point on each of its rows and \f$\mathbf{X^T}\f$ is its transpose. \f$\mathbf{1}\f$ is an \f$M \times 1\f$ vector of ones and \f$\mathbf{c}\f$ is a vector with components given by: \f[ c_i = \sum_\alpha (x_\alpha^i)^2 \f] -These quantities are the diagonal elements of \f$\mathbf{X X^T}\f$, which is a dot product or Gram Matrix that contains the -dot product of the vector \f$X_i\f$ with the vector \f$X_j\f$ in element \f$i,j\f$. +These quantities are the diagonal elements of \f$\mathbf{X X^T}\f$, which is a dot product or Gram Matrix that contains the +dot product of the vector \f$X_i\f$ with the vector \f$X_j\f$ in element \f$i,j\f$. In classical scaling we introduce a centering matrix \f$\mathbf{J}\f$ that is given by: @@ -130,36 +130,36 @@ where \f$\mathbf{I}\f$ is the identity. Multiplying the equations above from th &=& -\frac{1}{2}\mathbf{J c 1^T J} - \frac{1}{2} \mathbf{J 1 c^T J} + \frac{1}{2} \mathbf{J}(2\mathbf{X X^T})\mathbf{J} \\ &=& \mathbf{ J X X^T J } = \mathbf{X X^T } \label{eqn:scaling} \f} - -The fist two terms in this expression disappear because \f$\mathbf{1^T J}=\mathbf{J 1} =\mathbf{0}\f$, where \f$\mathbf{0}\f$ -is a matrix containing all zeros. In the final step meanwhile we use the fact that the matrix of squared distances will not + +The fist two terms in this expression disappear because \f$\mathbf{1^T J}=\mathbf{J 1} =\mathbf{0}\f$, where \f$\mathbf{0}\f$ +is a matrix containing all zeros. In the final step meanwhile we use the fact that the matrix of squared distances will not change when we translate all the points. We can thus assume that the mean value, \f$\mu\f$, for each of the components, \f$\alpha\f$: \f[ \mu_\alpha = \frac{1}{M} \sum_{i=1}^N \mathbf{X}^i_\alpha \f] -is equal to 0 so the columns of \f$\mathbf{X}\f$ add up to 0. This in turn means that each of the columns of -\f$\mathbf{X X^T}\f$ adds up to zero, which is what allows us to write \f$\mathbf{ J X X^T J } = \mathbf{X X^T }\f$. +is equal to 0 so the columns of \f$\mathbf{X}\f$ add up to 0. This in turn means that each of the columns of +\f$\mathbf{X X^T}\f$ adds up to zero, which is what allows us to write \f$\mathbf{ J X X^T J } = \mathbf{X X^T }\f$. -The matrix of squared distances is symmetric and positive-definite we can thus use the spectral decomposition to decompose it as: +The matrix of squared distances is symmetric and positive-definite we can thus use the spectral decomposition to decompose it as: \f[ \Phi= \mathbf{V} \Lambda \mathbf{V}^T \f] -Furthermore, because the matrix we are diagonalizing, \f$\mathbf{X X^T}\f$, is the product of a matrix and its transpose +Furthermore, because the matrix we are diagonalizing, \f$\mathbf{X X^T}\f$, is the product of a matrix and its transpose we can use this decomposition to write: \f[ -\mathbf{X} =\mathbf{V} \Lambda^\frac{1}{2} +\mathbf{X} =\mathbf{V} \Lambda^\frac{1}{2} \f] -Much as in PCA there are generally a small number of large eigenvalues in \f$\Lambda\f$ and many small eigenvalues. -We can safely use only the large eigenvalues and their corresponding eigenvectors to express the relationship between -the coordinates \f$\mathbf{X}\f$. This gives us our set of low-dimensional projections. +Much as in PCA there are generally a small number of large eigenvalues in \f$\Lambda\f$ and many small eigenvalues. +We can safely use only the large eigenvalues and their corresponding eigenvectors to express the relationship between +the coordinates \f$\mathbf{X}\f$. This gives us our set of low-dimensional projections. This derivation makes a number of assumptions about the how the low dimensional points should best be arranged to minimise -the stress. If you use an interative optimization algorithm such as SMACOF you may thus be able to find a better -(lower-stress) projection of the points. For more details on the assumptions made +the stress. If you use an interative optimization algorithm such as SMACOF you may thus be able to find a better +(lower-stress) projection of the points. For more details on the assumptions made see this website. */ //+ENDPLUMEDOC @@ -179,7 +179,7 @@ class ClassicalMultiDimensionalScaling : public AnalysisWithLandmarks { PLUMED_REGISTER_ACTION(ClassicalMultiDimensionalScaling,"CLASSICAL_MDS") -void ClassicalMultiDimensionalScaling::registerKeywords( Keywords& keys ){ +void ClassicalMultiDimensionalScaling::registerKeywords( Keywords& keys ) { AnalysisWithLandmarks::registerKeywords( keys ); keys.add("compulsory","NLOW_DIM","number of low-dimensional coordinates required"); keys.add("compulsory","OUTPUT_FILE","file on which to output the final embedding coordinates"); @@ -187,8 +187,8 @@ void ClassicalMultiDimensionalScaling::registerKeywords( Keywords& keys ){ } ClassicalMultiDimensionalScaling::ClassicalMultiDimensionalScaling( const ActionOptions& ao ): -Action(ao), -AnalysisWithLandmarks(ao) + Action(ao), + AnalysisWithLandmarks(ao) { myembedding = new PointWiseMapping( getMetricName(), false ); setDataToAnalyze( dynamic_cast(myembedding) ); @@ -196,10 +196,10 @@ AnalysisWithLandmarks(ao) parse("NLOW_DIM",nlow); if( nlow<1 ) error("dimensionality of low dimensional space must be at least one"); std::vector propnames( nlow ); std::string num; - for(unsigned i=0;isetPropertyNames( propnames, false ); @@ -207,11 +207,11 @@ AnalysisWithLandmarks(ao) parseOutputFile("OUTPUT_FILE",ofilename); } -ClassicalMultiDimensionalScaling::~ClassicalMultiDimensionalScaling(){ +ClassicalMultiDimensionalScaling::~ClassicalMultiDimensionalScaling() { delete myembedding; } -void ClassicalMultiDimensionalScaling::analyzeLandmarks(){ +void ClassicalMultiDimensionalScaling::analyzeLandmarks() { // Calculate all pairwise diatances myembedding->calculateAllDistances( getPbc(), getArguments(), comm, myembedding->modifyDmat(), true ); @@ -220,27 +220,27 @@ void ClassicalMultiDimensionalScaling::analyzeLandmarks(){ // Output the embedding as long lists of data // std::string gfname=saveResultsFromPreviousAnalyses( ofilename ); - OFile gfile; gfile.link(*this); + OFile gfile; gfile.link(*this); gfile.setBackupString("analysis"); gfile.fmtField(getOutputFormat()+" "); gfile.open( ofilename.c_str() ); - + // Print embedding coordinates - for(unsigned i=0;igetNumberOfReferenceFrames();++i){ - for(unsigned j=0;jgetProjectionCoordinate(i,j) ); - } - gfile.printField(); - } + for(unsigned i=0; igetNumberOfReferenceFrames(); ++i) { + for(unsigned j=0; jgetProjectionCoordinate(i,j) ); + } + gfile.printField(); + } gfile.close(); // Output the embedding in plumed format - if( efilename!="dont output"){ - OFile afile; afile.link(*this); afile.setBackupString("analysis"); - afile.open( efilename.c_str() ); - myembedding->print( "classical mds", getTime(), afile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); - afile.close(); + if( efilename!="dont output") { + OFile afile; afile.link(*this); afile.setBackupString("analysis"); + afile.open( efilename.c_str() ); + myembedding->print( "classical mds", getTime(), afile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); + afile.close(); } } diff --git a/src/analysis/ClassicalScaling.cpp b/src/analysis/ClassicalScaling.cpp index f7e9890c9c..e7c911eeef 100644 --- a/src/analysis/ClassicalScaling.cpp +++ b/src/analysis/ClassicalScaling.cpp @@ -25,31 +25,31 @@ namespace PLMD { namespace analysis { -void ClassicalScaling::run( PointWiseMapping* mymap ){ - // Retrieve the distances from the dimensionality reduction object - double half=(-0.5); Matrix distances( half*mymap->modifyDmat() ); - - // Apply centering transtion - unsigned n=distances.nrows(); double sum; - // First HM - for(unsigned i=0;i eigval(n); Matrix eigvec(n,n); - diagMat( distances, eigval, eigvec ); - - // Pass final projections to map object - for(unsigned i=0;igetNumberOfProperties();++j) mymap->setProjectionCoordinate( i, j, sqrt(eigval[n-1-j])*eigvec(n-1-j,i) ); - } +void ClassicalScaling::run( PointWiseMapping* mymap ) { + // Retrieve the distances from the dimensionality reduction object + double half=(-0.5); Matrix distances( half*mymap->modifyDmat() ); + + // Apply centering transtion + unsigned n=distances.nrows(); double sum; + // First HM + for(unsigned i=0; i eigval(n); Matrix eigvec(n,n); + diagMat( distances, eigval, eigvec ); + + // Pass final projections to map object + for(unsigned i=0; igetNumberOfProperties(); ++j) mymap->setProjectionCoordinate( i, j, sqrt(eigval[n-1-j])*eigvec(n-1-j,i) ); + } } } diff --git a/src/analysis/Commit.cpp b/src/analysis/Commit.cpp index 6c9bf69c85..5cbacf4db1 100644 --- a/src/analysis/Commit.cpp +++ b/src/analysis/Commit.cpp @@ -28,52 +28,52 @@ namespace PLMD { namespace analysis { -//+PLUMEDOC PRINTANALYSIS COMMITTOR +//+PLUMEDOC PRINTANALYSIS COMMITTOR /* Does a committor analysis. \par Examples The following input monitors two torsional angles during a simulation, -defines two basins (A and B) as a function of the two torsions and +defines two basins (A and B) as a function of the two torsions and stops the simulation when it falls in one of the two. In the log -file will be shown the latest values for the CVs and the basin reached. +file will be shown the latest values for the CVs and the basin reached. \verbatim TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 COMMITTOR ... - ARG=r1,r2 + ARG=r1,r2 STRIDE=10 - BASIN_LL1=0.15,0.20 - BASIN_UL1=0.25,0.40 - BASIN_LL2=-0.15,-0.20 - BASIN_UL2=-0.25,-0.40 -... COMMITTOR + BASIN_LL1=0.15,0.20 + BASIN_UL1=0.25,0.40 + BASIN_LL2=-0.15,-0.20 + BASIN_UL2=-0.25,-0.40 +... COMMITTOR \endverbatim */ //+ENDPLUMEDOC -class Committor : -public ActionPilot, -public ActionWithArguments +class Committor : + public ActionPilot, + public ActionWithArguments { private: std::string file; OFile ofile; std::string fmt; - std::vector< std::vector > lowerlimits; + std::vector< std::vector > lowerlimits; std::vector< std::vector > upperlimits; unsigned nbasins; public: static void registerKeywords( Keywords& keys ); explicit Committor(const ActionOptions&ao); void calculate(); - void apply(){} + void apply() {} }; PLUMED_REGISTER_ACTION(Committor,"COMMITTOR") -void Committor::registerKeywords( Keywords& keys ){ +void Committor::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -87,14 +87,14 @@ void Committor::registerKeywords( Keywords& keys ){ } Committor::Committor(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -fmt("%f") + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + fmt("%f") { ofile.link(*this); parse("FILE",file); - if(file.length()>0){ + if(file.length()>0) { ofile.open(file); log.printf(" on file %s\n",file.c_str()); } else { @@ -105,53 +105,53 @@ fmt("%f") fmt=" "+fmt; log.printf(" with format %s\n",fmt.c_str()); - for(unsigned i=0;i tmpl, tmpu; - parseNumberedVector("BASIN_LL", b, tmpl ); - parseNumberedVector("BASIN_UL", b, tmpu ); - if( tmpl.empty() && tmpu.empty() ) break; - if( tmpl.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_LL: they should be equal to the number of arguments"); - if( tmpu.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_UL: they should be equal to the number of arguments"); - lowerlimits.push_back(tmpl); - upperlimits.push_back(tmpu); - nbasins=b; + std::vector tmpl, tmpu; + parseNumberedVector("BASIN_LL", b, tmpl ); + parseNumberedVector("BASIN_UL", b, tmpu ); + if( tmpl.empty() && tmpu.empty() ) break; + if( tmpl.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_LL: they should be equal to the number of arguments"); + if( tmpu.size()!=getNumberOfArguments()) error("Wrong number of values for BASIN_UL: they should be equal to the number of arguments"); + lowerlimits.push_back(tmpl); + upperlimits.push_back(tmpu); + nbasins=b; } checkRead(); - for(unsigned b=0;bupperlimits[b][i]) error("COMMITTOR: UPPER bounds must always be greater than LOWER bounds"); log.printf(" %f - %f\n", lowerlimits[b][i], upperlimits[b][i]); } } } -void Committor::calculate(){ +void Committor::calculate() { std::vector inbasin; inbasin.assign (nbasins,1); - for(unsigned b=0;blowerlimits[b][i]&&getArgument(i)lowerlimits[b][i]&&getArgument(i) forcesToApply, finalForces; std::vector myvessels; std::vector stashes; - gridtools::HistogramOnGrid* myhist; + gridtools::HistogramOnGrid* myhist; public: static void registerKeywords( Keywords& keys ); explicit Histogram(const ActionOptions&ao); @@ -174,16 +174,16 @@ class Histogram : public gridtools::ActionWithGrid { void prepareForAveraging(); void performOperations( const bool& from_update ); void finishAveraging(); - bool isPeriodic(){ return false; } - unsigned getNumberOfDerivatives(); + bool isPeriodic() { return false; } + unsigned getNumberOfDerivatives(); void turnOnDerivatives(); - void compute( const unsigned& , MultiValue& ) const ; + void compute( const unsigned&, MultiValue& ) const ; void apply(); }; PLUMED_REGISTER_ACTION(Histogram,"HISTOGRAM") -void Histogram::registerKeywords( Keywords& keys ){ +void Histogram::registerKeywords( Keywords& keys ) { gridtools::ActionWithGrid::registerKeywords( keys ); keys.use("ARG"); keys.add("optional","DATA","input data from action with vessel and compute histogram"); keys.add("optional","VECTORS","input three dimsnional vectors for computing histogram"); @@ -195,137 +195,137 @@ void Histogram::registerKeywords( Keywords& keys ){ } Histogram::Histogram(const ActionOptions&ao): -Action(ao), -ActionWithGrid(ao), -ww(0.0), -in_apply(false), -mvectors(false), -kernel(NULL) + Action(ao), + ActionWithGrid(ao), + ww(0.0), + in_apply(false), + mvectors(false), + kernel(NULL) { - // Read in arguments + // Read in arguments std::string vlab; parse("VECTORS",vlab); - if( vlab.length()>0 ){ - ActionWithVessel* myv = plumed.getActionSet().selectWithLabel( vlab ); - if( !myv ) error("action labelled " + vlab + " does not exist or is not an ActionWithVessel"); - myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); - addDependency( myv ); mvectors=true; - if( myv->getNumberOfQuantities()!=5 ) error("can only compute histograms for three dimensional vectors"); - log.printf(" for vector quantities calculated by %s \n", vlab.c_str() ); + if( vlab.length()>0 ) { + ActionWithVessel* myv = plumed.getActionSet().selectWithLabel( vlab ); + if( !myv ) error("action labelled " + vlab + " does not exist or is not an ActionWithVessel"); + myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); + addDependency( myv ); mvectors=true; + if( myv->getNumberOfQuantities()!=5 ) error("can only compute histograms for three dimensional vectors"); + log.printf(" for vector quantities calculated by %s \n", vlab.c_str() ); } else { - std::vector mlab; parseVector("DATA",mlab); - if( mlab.size()>0 ){ - for(unsigned i=0;i( mlab[i] ); - if( !myv ) error("action labelled " + mlab[i] + " does not exist or is not an ActionWithVessel"); - myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); - // log.printf(" for all base quantities calculated by %s \n",myvessel->getLabel().c_str() ); - // Add the dependency - addDependency( myv ); - } - unsigned nvals = myvessels[0]->getFullNumberOfTasks(); - for(unsigned i=1;igetFullNumberOfTasks() ) error("mismatched number of quantities calculated by actions input to histogram"); - } - log.printf(" for all base quantities calculated by %s ", myvessels[0]->getLabel().c_str() ); - for(unsigned i=1;igetLabel().c_str() ); + std::vector mlab; parseVector("DATA",mlab); + if( mlab.size()>0 ) { + for(unsigned i=0; i( mlab[i] ); + if( !myv ) error("action labelled " + mlab[i] + " does not exist or is not an ActionWithVessel"); + myvessels.push_back( myv ); stashes.push_back( myv->buildDataStashes( NULL ) ); + // log.printf(" for all base quantities calculated by %s \n",myvessel->getLabel().c_str() ); + // Add the dependency + addDependency( myv ); + } + unsigned nvals = myvessels[0]->getFullNumberOfTasks(); + for(unsigned i=1; igetFullNumberOfTasks() ) error("mismatched number of quantities calculated by actions input to histogram"); + } + log.printf(" for all base quantities calculated by %s ", myvessels[0]->getLabel().c_str() ); + for(unsigned i=1; igetLabel().c_str() ); + log.printf("\n"); + } else { + std::vector arg; parseArgumentList("ARG",arg); + if(!arg.empty()) { + log.printf(" with arguments"); + for(unsigned i=0; igetName().c_str()); log.printf("\n"); - } else { - std::vector arg; parseArgumentList("ARG",arg); - if(!arg.empty()){ - log.printf(" with arguments"); - for(unsigned i=0;igetName().c_str()); - log.printf("\n"); - // Retrieve the bias acting and make sure we request this also - std::vector bias( ActionWithArguments::getArguments() ); - for(unsigned i=0;i bias( ActionWithArguments::getArguments() ); + for(unsigned i=0; i0 ) narg=myvessels.size(); // Input of name and labels std::string vstring="COMPONENTS=" + getLabel(); - if( mvectors ){ - vstring += " COORDINATES=x,y,z PBC=F,F,F"; - } else if( myvessels.size()>0 ){ - vstring += " COORDINATES=" + myvessels[0]->getLabel(); - for(unsigned i=1;igetLabel(); - // Input for PBC - if( myvessels[0]->isPeriodic() ) vstring+=" PBC=T"; - else vstring+=" PBC=F"; - for(unsigned i=1;iisPeriodic() ) vstring+=",T"; - else vstring+=",F"; - } + if( mvectors ) { + vstring += " COORDINATES=x,y,z PBC=F,F,F"; + } else if( myvessels.size()>0 ) { + vstring += " COORDINATES=" + myvessels[0]->getLabel(); + for(unsigned i=1; igetLabel(); + // Input for PBC + if( myvessels[0]->isPeriodic() ) vstring+=" PBC=T"; + else vstring+=" PBC=F"; + for(unsigned i=1; iisPeriodic() ) vstring+=",T"; + else vstring+=",F"; + } } else { - vstring += " COORDINATES=" + getPntrToArgument(0)->getName(); - for(unsigned i=1;igetName(); - // Input for PBC - if( getPntrToArgument(0)->isPeriodic() ) vstring+=" PBC=T"; - else vstring+=" PBC=F"; - for(unsigned i=1;iisPeriodic() ) vstring+=",T"; - else vstring+=",F"; - } + vstring += " COORDINATES=" + getPntrToArgument(0)->getName(); + for(unsigned i=1; igetName(); + // Input for PBC + if( getPntrToArgument(0)->isPeriodic() ) vstring+=" PBC=T"; + else vstring+=" PBC=F"; + for(unsigned i=1; iisPeriodic() ) vstring+=",T"; + else vstring+=",F"; + } } // And create the grid - createGrid( "histogram", vstring ); - if( mygrid->getType()=="flat" ){ - if( mvectors ) error("computing histogram for three dimensional vectors but grid is not of fibonacci type - use CONCENTRATION"); - std::vector gmin( narg ), gmax( narg ); - parseVector("GRID_MIN",gmin); parseVector("GRID_MAX",gmax); - std::vector nbin; parseVector("GRID_BIN",nbin); - std::vector gspacing; parseVector("GRID_SPACING",gspacing); - if( nbin.size()!=narg && gspacing.size()!=narg ){ - error("GRID_BIN or GRID_SPACING must be set"); - } - mygrid->setBounds( gmin, gmax, nbin, gspacing ); + createGrid( "histogram", vstring ); + if( mygrid->getType()=="flat" ) { + if( mvectors ) error("computing histogram for three dimensional vectors but grid is not of fibonacci type - use CONCENTRATION"); + std::vector gmin( narg ), gmax( narg ); + parseVector("GRID_MIN",gmin); parseVector("GRID_MAX",gmax); + std::vector nbin; parseVector("GRID_BIN",nbin); + std::vector gspacing; parseVector("GRID_SPACING",gspacing); + if( nbin.size()!=narg && gspacing.size()!=narg ) { + error("GRID_BIN or GRID_SPACING must be set"); + } + mygrid->setBounds( gmin, gmax, nbin, gspacing ); } else { - std::vector nbin; parseVector("GRID_BIN",nbin); - if( nbin.size()!=1 ) error("should only be one index for number of bins with spherical grid"); - if( mygrid->getType()=="fibonacci" ) mygrid->setupFibonacciGrid( nbin[0] ); + std::vector nbin; parseVector("GRID_BIN",nbin); + if( nbin.size()!=1 ) error("should only be one index for number of bins with spherical grid"); + if( mygrid->getType()=="fibonacci" ) mygrid->setupFibonacciGrid( nbin[0] ); } - myhist = dynamic_cast( mygrid ); - plumed_assert( myhist ); - if( myvessels.size()>0 ){ - // Create a task list - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList(i); - setAveragingAction( mygrid, true ); + myhist = dynamic_cast( mygrid ); + plumed_assert( myhist ); + if( myvessels.size()>0 ) { + // Create a task list + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList(i); + setAveragingAction( mygrid, true ); } else { - // Create a task list - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); - myhist->addOneKernelEachTimeOnly(); - setAveragingAction( mygrid, myhist->noDiscreteKernels() ); + // Create a task list + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); + myhist->addOneKernelEachTimeOnly(); + setAveragingAction( mygrid, myhist->noDiscreteKernels() ); } checkRead(); } -void Histogram::turnOnDerivatives(){ +void Histogram::turnOnDerivatives() { ActionWithGrid::turnOnDerivatives(); std::vector all_atoms, tmp_atoms; - for(unsigned i=0;i( myvessels[i] ); - if( !mbase ) error("do not know how to get histogram derivatives for actions of type " + myvessels[i]->getName() ); - tmp_atoms = mbase->getAbsoluteIndexes(); - for(unsigned j=0;j( myvessels[i] ); + if( !mbase ) error("do not know how to get histogram derivatives for actions of type " + myvessels[i]->getName() ); + tmp_atoms = mbase->getAbsoluteIndexes(); + for(unsigned j=0; jresize(); in_apply=false; } -unsigned Histogram::getNumberOfDerivatives(){ - if( in_apply ){ - unsigned nder=0; - for(unsigned i=0;igetNumberOfDerivatives(); - return nder; +unsigned Histogram::getNumberOfDerivatives() { + if( in_apply ) { + unsigned nder=0; + for(unsigned i=0; igetNumberOfDerivatives(); + return nder; } return getNumberOfArguments(); } @@ -336,152 +336,152 @@ unsigned Histogram::getNumberOfQuantities() const { return 2; } -void Histogram::prepareForAveraging(){ - if( myvessels.size()>0 ){ - deactivateAllTasks(); double norm=0; - for(unsigned i=0;igetNumberOfStoredValues();++i){ - std::vector cvals( myvessels[0]->getNumberOfQuantities() ); - stashes[0]->retrieveSequentialValue( i, false, cvals ); - unsigned itask=myvessels[0]->getActiveTask(i); double tnorm = cvals[0]; - for(unsigned j=1;jgetActiveTask(i)!=itask ) error("mismatched task identities in histogram suggests histogram is meaningless"); - if( cvals.size()!=myvessels[j]->getNumberOfQuantities() ) cvals.resize( myvessels[j]->getNumberOfQuantities() ); - stashes[j]->retrieveSequentialValue( i, false, cvals ); tnorm *= cvals[0]; - } - norm += tnorm; taskFlags[i]=1; +void Histogram::prepareForAveraging() { + if( myvessels.size()>0 ) { + deactivateAllTasks(); double norm=0; + for(unsigned i=0; igetNumberOfStoredValues(); ++i) { + std::vector cvals( myvessels[0]->getNumberOfQuantities() ); + stashes[0]->retrieveSequentialValue( i, false, cvals ); + unsigned itask=myvessels[0]->getActiveTask(i); double tnorm = cvals[0]; + for(unsigned j=1; jgetActiveTask(i)!=itask ) error("mismatched task identities in histogram suggests histogram is meaningless"); + if( cvals.size()!=myvessels[j]->getNumberOfQuantities() ) cvals.resize( myvessels[j]->getNumberOfQuantities() ); + stashes[j]->retrieveSequentialValue( i, false, cvals ); tnorm *= cvals[0]; } - lockContributors(); - // Sort out normalization of histogram - if( !noNormalization() ) ww = cweight / norm; - else ww = cweight; + norm += tnorm; taskFlags[i]=1; + } + lockContributors(); + // Sort out normalization of histogram + if( !noNormalization() ) ww = cweight / norm; + else ww = cweight; } else { - // Now fetch the kernel and the active points - std::vector point( getNumberOfArguments() ); - for(unsigned i=0;i neighbors(1); - kernel = myhist->getKernelAndNeighbors( point, num_neigh, neighbors ); - - if( num_neigh>1 ){ - // Activate relevant tasks - deactivateAllTasks(); - for(unsigned i=0;iaddToGridElement( neighbors[0], 0, cweight ); - } + // Now fetch the kernel and the active points + std::vector point( getNumberOfArguments() ); + for(unsigned i=0; i neighbors(1); + kernel = myhist->getKernelAndNeighbors( point, num_neigh, neighbors ); + + if( num_neigh>1 ) { + // Activate relevant tasks + deactivateAllTasks(); + for(unsigned i=0; iaddToGridElement( neighbors[0], 0, cweight ); + } } } -void Histogram::performOperations( const bool& from_update ){ if( myvessels.size()==0 ) plumed_dbg_assert( !myhist->noDiscreteKernels() ); } +void Histogram::performOperations( const bool& from_update ) { if( myvessels.size()==0 ) plumed_dbg_assert( !myhist->noDiscreteKernels() ); } -void Histogram::finishAveraging(){ +void Histogram::finishAveraging() { if( myvessels.size()==0 ) delete kernel; } -void Histogram::compute( const unsigned& current, MultiValue& myvals ) const { - if( mvectors ){ - std::vector cvals( myvessels[0]->getNumberOfQuantities() ); - stashes[0]->retrieveSequentialValue( current, true, cvals ); - for(unsigned i=2;igetNumberOfQuantities();++i) myvals.setValue( i-1, cvals[i] ); - myvals.setValue( 0, cvals[0] ); myvals.setValue( myvessels[0]->getNumberOfQuantities() - 1, ww ); - if( in_apply ){ - MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); - stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), true, tmpval ); - for(unsigned j=0;jgetNumberOfQuantities();++i) myvals.addDerivative( i-1, jder, tmpval.getDerivative(i, jder) ); - } - myvals.updateDynamicList(); +void Histogram::compute( const unsigned& current, MultiValue& myvals ) const { + if( mvectors ) { + std::vector cvals( myvessels[0]->getNumberOfQuantities() ); + stashes[0]->retrieveSequentialValue( current, true, cvals ); + for(unsigned i=2; igetNumberOfQuantities(); ++i) myvals.setValue( i-1, cvals[i] ); + myvals.setValue( 0, cvals[0] ); myvals.setValue( myvessels[0]->getNumberOfQuantities() - 1, ww ); + if( in_apply ) { + MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); + stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), true, tmpval ); + for(unsigned j=0; jgetNumberOfQuantities(); ++i) myvals.addDerivative( i-1, jder, tmpval.getDerivative(i, jder) ); } - } else if( myvessels.size()>0 ){ - std::vector cvals( myvessels[0]->getNumberOfQuantities() ); - stashes[0]->retrieveSequentialValue( current, false, cvals ); - unsigned derbase; double totweight=cvals[0], tnorm = cvals[0]; myvals.setValue( 1, cvals[1] ); - // Get the derivatives as well if we are in apply - if( in_apply ){ - // This bit gets the total weight - double weight0 = cvals[0]; // Store the current weight - for(unsigned j=1;jretrieveSequentialValue( current, false, cvals ); totweight *= cvals[0]; - } - // And this bit the derivatives - MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); - stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), false, tmpval ); - for(unsigned j=0;jgetNumberOfDerivatives(); + myvals.updateDynamicList(); + } + } else if( myvessels.size()>0 ) { + std::vector cvals( myvessels[0]->getNumberOfQuantities() ); + stashes[0]->retrieveSequentialValue( current, false, cvals ); + unsigned derbase; double totweight=cvals[0], tnorm = cvals[0]; myvals.setValue( 1, cvals[1] ); + // Get the derivatives as well if we are in apply + if( in_apply ) { + // This bit gets the total weight + double weight0 = cvals[0]; // Store the current weight + for(unsigned j=1; jretrieveSequentialValue( current, false, cvals ); totweight *= cvals[0]; } - for(unsigned i=1;igetNumberOfQuantities() ) cvals.resize( myvessels[i]->getNumberOfQuantities() ); - stashes[i]->retrieveSequentialValue( current, false, cvals ); - tnorm *= cvals[0]; myvals.setValue( 1+i, cvals[1] ); - // Get the derivatives as well if we are in apply - if( in_apply ){ - MultiValue tmpval( myvessels[i]->getNumberOfQuantities(), myvessels[i]->getNumberOfDerivatives() ); - stashes[i]->retrieveDerivatives( stashes[i]->getTrueIndex(current), false, tmpval ); - for(unsigned j=0;jgetNumberOfDerivatives(); - } + // And this bit the derivatives + MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); + stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), false, tmpval ); + for(unsigned j=0; j vv( myhist->getVectorOfValues() ); - std::vector val( getNumberOfArguments() ), der( getNumberOfArguments() ); - // Retrieve the location of the grid point at which we are evaluating the kernel - mygrid->getGridPointCoordinates( current, val ); - if( kernel ){ - for(unsigned i=0;iset( val[i] ); - // Evaluate the histogram at the relevant grid point and set the values - double vvh = kernel->evaluate( vv, der ,true); myvals.setValue( 1, vvh ); - } else { - plumed_merror("normalisation of vectors does not work with arguments and spherical grids"); - // Evalulate dot product - double dot=0; for(unsigned j=0;jvon_misses_norm)*exp( (myhist->von_misses_concentration)*dot ); myvals.setValue( 1, newval ); - // And final derivatives - for(unsigned j=0;jvon_misses_concentration)*newval; + derbase = myvessels[0]->getNumberOfDerivatives(); + } + for(unsigned i=1; igetNumberOfQuantities() ) cvals.resize( myvessels[i]->getNumberOfQuantities() ); + stashes[i]->retrieveSequentialValue( current, false, cvals ); + tnorm *= cvals[0]; myvals.setValue( 1+i, cvals[1] ); + // Get the derivatives as well if we are in apply + if( in_apply ) { + MultiValue tmpval( myvessels[i]->getNumberOfQuantities(), myvessels[i]->getNumberOfDerivatives() ); + stashes[i]->retrieveDerivatives( stashes[i]->getTrueIndex(current), false, tmpval ); + for(unsigned j=0; jgetNumberOfDerivatives(); } - // Set the derivatives and delete the vector of values - for(unsigned i=0;i vv( myhist->getVectorOfValues() ); + std::vector val( getNumberOfArguments() ), der( getNumberOfArguments() ); + // Retrieve the location of the grid point at which we are evaluating the kernel + mygrid->getGridPointCoordinates( current, val ); + if( kernel ) { + for(unsigned i=0; iset( val[i] ); + // Evaluate the histogram at the relevant grid point and set the values + double vvh = kernel->evaluate( vv, der,true); myvals.setValue( 1, vvh ); + } else { + plumed_merror("normalisation of vectors does not work with arguments and spherical grids"); + // Evalulate dot product + double dot=0; for(unsigned j=0; jvon_misses_norm)*exp( (myhist->von_misses_concentration)*dot ); myvals.setValue( 1, newval ); + // And final derivatives + for(unsigned j=0; jvon_misses_concentration)*newval; + } + // Set the derivatives and delete the vector of values + for(unsigned i=0; iwasForced() ) return ; - in_apply=true; + in_apply=true; // Run the loop to calculate the forces - runAllTasks(); finishAveraging(); + runAllTasks(); finishAveraging(); // We now need to retrieve the buffer and set the forces on the atoms - myhist->applyForce( forcesToApply ); + myhist->applyForce( forcesToApply ); // Now make the forces make sense for the virial unsigned fbase=0, tbase=0, vbase = getNumberOfDerivatives() - myvessels.size()*9; - for(unsigned i=vbase;igetNumberOfDerivatives()-9;++j){ - finalForces[fbase + j] = forcesToApply[tbase + j]; - } - unsigned k=0; - for(unsigned j=myvessels[i]->getNumberOfDerivatives()-9;jgetNumberOfDerivatives();++j){ - finalForces[vbase + k] += forcesToApply[tbase + j]; k++; - } - fbase += myvessels[i]->getNumberOfDerivatives() - 9; - tbase += myvessels[i]->getNumberOfDerivatives(); + for(unsigned i=vbase; igetNumberOfDerivatives()-9; ++j) { + finalForces[fbase + j] = forcesToApply[tbase + j]; + } + unsigned k=0; + for(unsigned j=myvessels[i]->getNumberOfDerivatives()-9; jgetNumberOfDerivatives(); ++j) { + finalForces[vbase + k] += forcesToApply[tbase + j]; k++; + } + fbase += myvessels[i]->getNumberOfDerivatives() - 9; + tbase += myvessels[i]->getNumberOfDerivatives(); } // And set the final forces on the atoms setForcesOnAtoms( finalForces ); // Reset everything for next regular loop - in_apply=false; + in_apply=false; } } diff --git a/src/analysis/LandmarkRegister.cpp b/src/analysis/LandmarkRegister.cpp index 32cc946d5d..0b3a6e4f7a 100644 --- a/src/analysis/LandmarkRegister.cpp +++ b/src/analysis/LandmarkRegister.cpp @@ -22,45 +22,45 @@ #include "LandmarkRegister.h" #include -namespace PLMD{ -namespace analysis{ +namespace PLMD { +namespace analysis { -LandmarkRegister::~LandmarkRegister(){ - if(m.size()>0){ +LandmarkRegister::~LandmarkRegister() { + if(m.size()>0) { std::string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: ReferenceConfiguration "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -LandmarkRegister& landmarkRegister(){ +LandmarkRegister& landmarkRegister() { static LandmarkRegister ans; return ans; } -void LandmarkRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void LandmarkRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void LandmarkRegister::add( std::string type, creator_pointer f ){ +void LandmarkRegister::add( std::string type, creator_pointer f ) { plumed_massert(m.count(type)==0,"type has already been registered"); m.insert(std::pair(type,f)); } -bool LandmarkRegister::check(std::string type){ +bool LandmarkRegister::check(std::string type) { if( m.count(type)>0 ) return true; return false; } -LandmarkSelectionBase* LandmarkRegister::create( const LandmarkSelectionOptions& lo ){ +LandmarkSelectionBase* LandmarkRegister::create( const LandmarkSelectionOptions& lo ) { LandmarkSelectionBase* lselect; - if( check(lo.words[0]) ){ - lselect=m[lo.words[0]](lo); - lselect->checkRead(); + if( check(lo.words[0]) ) { + lselect=m[lo.words[0]](lo); + lselect->checkRead(); } else lselect=NULL; return lselect; } diff --git a/src/analysis/LandmarkRegister.h b/src/analysis/LandmarkRegister.h index e17c9b2abd..dd4c5d38d9 100644 --- a/src/analysis/LandmarkRegister.h +++ b/src/analysis/LandmarkRegister.h @@ -28,13 +28,13 @@ #include #include "LandmarkSelectionBase.h" -namespace PLMD{ +namespace PLMD { class PDB; -namespace analysis{ +namespace analysis { -class LandmarkRegister{ +class LandmarkRegister { private: /// Pointer to a function which, given the type for a ReferenceConfiguration, creates it typedef LandmarkSelectionBase*(*creator_pointer)(const LandmarkSelectionOptions&); diff --git a/src/analysis/LandmarkSelectionBase.cpp b/src/analysis/LandmarkSelectionBase.cpp index 24df3c1d1e..5bd8f7e60f 100644 --- a/src/analysis/LandmarkSelectionBase.cpp +++ b/src/analysis/LandmarkSelectionBase.cpp @@ -26,88 +26,88 @@ namespace PLMD { namespace analysis { LandmarkSelectionOptions::LandmarkSelectionOptions( const std::vector& input, AnalysisWithLandmarks* myanalysis ): -words(input), -action(myanalysis) + words(input), + action(myanalysis) { } LandmarkSelectionBase::LandmarkSelectionBase( const LandmarkSelectionOptions& lo ): -style(lo.words[0]), -input(lo.words), -action(lo.action) + style(lo.words[0]), + input(lo.words), + action(lo.action) { input.erase( input.begin() ); - if( style=="ALL" ){ - novoronoi=true; + if( style=="ALL" ) { + novoronoi=true; } else { - parse("N",nlandmarks); - parseFlag("NOVORONOI",novoronoi); + parse("N",nlandmarks); + parseFlag("NOVORONOI",novoronoi); } parseFlag("IGNORE_WEIGHTS",noweights); } -LandmarkSelectionBase::~LandmarkSelectionBase(){ +LandmarkSelectionBase::~LandmarkSelectionBase() { } -void LandmarkSelectionBase::parseFlag(const std::string& key, bool& t){ +void LandmarkSelectionBase::parseFlag(const std::string& key, bool& t) { Tools::parseFlag(input,key,t); } void LandmarkSelectionBase::checkRead() const { - if(!input.empty()){ - std::string msg="cannot understand the following words from landmark selection input : "; - for(unsigned i=0;igetWeight(iframe); } -double LandmarkSelectionBase::getDistanceBetweenFrames( const unsigned& iframe, const unsigned& jframe ){ +double LandmarkSelectionBase::getDistanceBetweenFrames( const unsigned& iframe, const unsigned& jframe ) { return distance( action->getPbc(), action->getArguments(), action->data[iframe], action->data[jframe], false ); } -void LandmarkSelectionBase::selectFrame( const unsigned& iframe, MultiReferenceBase* myframes){ +void LandmarkSelectionBase::selectFrame( const unsigned& iframe, MultiReferenceBase* myframes) { plumed_assert( myframes->getNumberOfReferenceFrames()copyFrame( action->data[iframe] ); } -void LandmarkSelectionBase::selectLandmarks( MultiReferenceBase* myframes ){ +void LandmarkSelectionBase::selectLandmarks( MultiReferenceBase* myframes ) { // Select landmarks myframes->clearFrames(); select( myframes ); plumed_assert( myframes->getNumberOfReferenceFrames()==nlandmarks ); - // Now calculate voronoi weights - if( !novoronoi ){ - unsigned rank=action->comm.Get_rank(); - unsigned size=action->comm.Get_size(); - std::vector weights( nlandmarks, 0.0 ); - for(unsigned i=rank;idata.size();i+=size){ - unsigned closest=0; - double mindist=distance( action->getPbc(), action->getArguments(), action->data[i], myframes->getFrame(0), false ); - for(unsigned j=1;jgetPbc(), action->getArguments(), action->data[i], myframes->getFrame(j), false ); - if( distcomm.Get_rank(); + unsigned size=action->comm.Get_size(); + std::vector weights( nlandmarks, 0.0 ); + for(unsigned i=rank; idata.size(); i+=size) { + unsigned closest=0; + double mindist=distance( action->getPbc(), action->getArguments(), action->data[i], myframes->getFrame(0), false ); + for(unsigned j=1; jgetPbc(), action->getArguments(), action->data[i], myframes->getFrame(j), false ); + if( distcomm.Sum( &weights[0], weights.size() ); - myframes->setWeights( weights ); + weights[closest] += getWeightOfFrame(i); + } + action->comm.Sum( &weights[0], weights.size() ); + myframes->setWeights( weights ); } } diff --git a/src/analysis/LandmarkSelectionBase.h b/src/analysis/LandmarkSelectionBase.h index b2deb5c578..a8300ff107 100644 --- a/src/analysis/LandmarkSelectionBase.h +++ b/src/analysis/LandmarkSelectionBase.h @@ -28,9 +28,9 @@ namespace PLMD { namespace analysis { -class LandmarkSelectionOptions{ -friend class LandmarkRegister; -friend class LandmarkSelectionBase; +class LandmarkSelectionOptions { + friend class LandmarkRegister; + friend class LandmarkSelectionBase; private: std::vector words; AnalysisWithLandmarks* action; @@ -39,8 +39,8 @@ friend class LandmarkSelectionBase; }; class LandmarkSelectionBase { -friend class AnalysisWithLandmarks; -friend class CopyAllFrames; + friend class AnalysisWithLandmarks; + friend class CopyAllFrames; private: /// Name of the method we are using for landmark selection std::string style; @@ -57,9 +57,9 @@ friend class CopyAllFrames; unsigned getNumberOfLandmarks() const ; /// Return the communicator Communicator& getCommunicator(); -/// Read a keywords from the input +/// Read a keywords from the input template - void parse(const std::string& ,T& ); + void parse(const std::string&,T& ); /// Read a flag from the input void parseFlag(const std::string& key, bool& t); /// Get the number of frames in the underlying action @@ -67,9 +67,9 @@ friend class CopyAllFrames; /// Get the weight of the ith frame double getWeightOfFrame( const unsigned& ); /// Calculate the distance between the ith and jth frames - double getDistanceBetweenFrames( const unsigned& , const unsigned& ); + double getDistanceBetweenFrames( const unsigned&, const unsigned& ); /// Transfer frame i in the underlying action to the object we are going to analyze - void selectFrame( const unsigned& , MultiReferenceBase* ); + void selectFrame( const unsigned&, MultiReferenceBase* ); public: explicit LandmarkSelectionBase( const LandmarkSelectionOptions& lo ); virtual ~LandmarkSelectionBase(); @@ -78,7 +78,7 @@ friend class CopyAllFrames; /// Return a description of the landmark selection protocol std::string description(); /// Overwrite this to have a more descriptive output - virtual std::string rest_of_description(){ return ""; }; + virtual std::string rest_of_description() { return ""; }; /// Actually do landmark selection void selectLandmarks( MultiReferenceBase* ); virtual void select( MultiReferenceBase* )=0; @@ -90,7 +90,7 @@ unsigned LandmarkSelectionBase::getNumberOfLandmarks() const { } inline -Communicator& LandmarkSelectionBase::getCommunicator(){ +Communicator& LandmarkSelectionBase::getCommunicator() { return action->comm; } @@ -100,7 +100,7 @@ unsigned LandmarkSelectionBase::getNumberOfFrames() const { } template -void LandmarkSelectionBase::parse( const std::string& key, T& t ){ +void LandmarkSelectionBase::parse( const std::string& key, T& t ) { bool found=Tools::parse(input,key,t); if(!found) plumed_merror("landmark seleciton style " + style + " requires " + key + " keyword"); } diff --git a/src/analysis/PCA.cpp b/src/analysis/PCA.cpp index d338b5b8a9..5b31a04faa 100644 --- a/src/analysis/PCA.cpp +++ b/src/analysis/PCA.cpp @@ -28,32 +28,32 @@ #include "core/ActionRegister.h" //+PLUMEDOC DIMRED PCA -/* +/* Perform principal component analysis (PCA) using either the positions of the atoms a large number of collective variables as input. -Principal component analysis is a statistical technique that uses an orthogonal transformation to convert a set of observations of +Principal component analysis is a statistical technique that uses an orthogonal transformation to convert a set of observations of poorly correlated variables into a set of linearly uncorrelated variables. You can read more about the specifics of this technique here: https://en.wikipedia.org/wiki/Principal_component_analysis -When used with molecular dynamics simulations a set of frames taken from the trajectory, \f$\{X_i\}\f$, or the values of -a number of collective variables which are calculated from the trajectory frames are used as input. In this second instance your +When used with molecular dynamics simulations a set of frames taken from the trajectory, \f$\{X_i\}\f$, or the values of +a number of collective variables which are calculated from the trajectory frames are used as input. In this second instance your input to the PCA analysis algorithm is thus a set of high-dimensional vectors of collective variables. However, if -collective variables are calculated from the positions of the atoms or if the positions are used directly the assumption is that -this input trajectory is a set of poorly correlated (high-dimensional) vectors. After principal component analysis has been -performed the output is a set of orthogonal vectors that describe the directions in which the largest motions have been seen. +collective variables are calculated from the positions of the atoms or if the positions are used directly the assumption is that +this input trajectory is a set of poorly correlated (high-dimensional) vectors. After principal component analysis has been +performed the output is a set of orthogonal vectors that describe the directions in which the largest motions have been seen. In other words, principal component analysis provides a method for lowering the dimensionality of the data contained in a trajectory. -These output directions are some linear combination of the \f$x\f$, \f$y\f$ and \f$z\f$ positions if the positions were used as input +These output directions are some linear combination of the \f$x\f$, \f$y\f$ and \f$z\f$ positions if the positions were used as input or some linear combination of the input collective variables if a high-dimensional vector of collective variables was used as input. -As explained on the Wikipedia page you must calculate the average and covariance for each of the input coordinates. In other words, you must -calculate the average structure and the amount the system fluctuates around this average structure. The problem in doing so when the -\f$x\f$, \f$y\f$ and \f$z\f$ coordinates of a molecule are used as input is that the majority of the changes in the positions of the +As explained on the Wikipedia page you must calculate the average and covariance for each of the input coordinates. In other words, you must +calculate the average structure and the amount the system fluctuates around this average structure. The problem in doing so when the +\f$x\f$, \f$y\f$ and \f$z\f$ coordinates of a molecule are used as input is that the majority of the changes in the positions of the atoms comes from the translational and rotational degrees of freedom of the molecule. The first six principal components will thus, most likely, -be uninteresting. Consequently, to remedy this problem PLUMED provides the functionality to perform an RMSD alignment of the all the structures -to be analysed to the first frame in the trajectory. This can be used to effectively remove translational and/or rotational motions from -consideration. The resulting principal components thus describe vibrational motions of the molecule. +be uninteresting. Consequently, to remedy this problem PLUMED provides the functionality to perform an RMSD alignment of the all the structures +to be analysed to the first frame in the trajectory. This can be used to effectively remove translational and/or rotational motions from +consideration. The resulting principal components thus describe vibrational motions of the molecule. -If you wish to calculate the projection of a trajectory on a set of principal components calculated from this PCA action then the output can be +If you wish to calculate the projection of a trajectory on a set of principal components calculated from this PCA action then the output can be used as input for the \ref PCAVARS action. \par Examples @@ -70,10 +70,10 @@ PCA METRIC=OPTIMAL ATOMS=1-22 STRIDE=1 USE_ALL_DATA NLOW_DIM=2 OFILE=pca-comp.pd The following input instructs PLUMED to perform a principal component analysis in which the covariance matrix is calculated from chnages in the six distances seen in the previous lines. Notice that here the TYPE=EUCLIDEAN keyword is used to indicate that no alighment has to be done when calculating the various elements of the covariance matrix from the input vectors. In this calculation the first two principal components will be output to a file called pca-comp.pdb. -Trajectory frames will be collected every five steps and the PCA calculation is performed every 1000 steps. Consequently, if you run a 2000 step simulation the +Trajectory frames will be collected every five steps and the PCA calculation is performed every 1000 steps. Consequently, if you run a 2000 step simulation the PCA analysis will be performed twice. The REWEIGHT_BIAS keyword in this input tells PLUMED that rather that ascribing a weight of one to each of the frames -when calculating averages and covariances a reweighting should be performed based and each frames' weight in these calculations should be determined based on -the current value of the instantaneous bias (see \ref REWEIGHT_BIAS). +when calculating averages and covariances a reweighting should be performed based and each frames' weight in these calculations should be determined based on +the current value of the instantaneous bias (see \ref REWEIGHT_BIAS). \verbatim d1: DISTANCE ATOMS=1,2 @@ -107,27 +107,27 @@ class PCA : public Analysis { explicit PCA(const ActionOptions&ao); ~PCA(); void performAnalysis(); - void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); } + void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); } }; PLUMED_REGISTER_ACTION(PCA,"PCA") -void PCA::registerKeywords( Keywords& keys ){ +void PCA::registerKeywords( Keywords& keys ) { Analysis::registerKeywords( keys ); keys.add("compulsory","NLOW_DIM","number of PCA coordinates required"); keys.add("compulsory","OFILE","the file on which to output the eigenvectors"); } PCA::PCA(const ActionOptions&ao): -PLUMED_ANALYSIS_INIT(ao) + PLUMED_ANALYSIS_INIT(ao) { // Setup reference configuration log.printf(" performing PCA analysis using %s metric \n", getMetricName().c_str() ); myref = metricRegister().create( getMetricName() ); std::vector argnames( getNumberOfArguments() ); - for(unsigned i=0;iisPeriodic() ) error("cannot run PCA with periodic variables"); - argnames[i] = getArguments()[i]->getName(); + for(unsigned i=0; iisPeriodic() ) error("cannot run PCA with periodic variables"); + argnames[i] = getArguments()[i]->getName(); } myref->setNamesAndAtomNumbers( getAbsoluteIndexes(), argnames ); @@ -136,74 +136,74 @@ PLUMED_ANALYSIS_INIT(ao) if( getNumberOfArguments()>0 ) arg_eigv.resize( ndim, getNumberOfArguments() ); // Read stuff for output file - parseOutputFile("OFILE",ofilename); + parseOutputFile("OFILE",ofilename); checkRead(); } -PCA::~PCA(){ +PCA::~PCA() { delete myref; } -void PCA::performAnalysis(){ +void PCA::performAnalysis() { // Align everything to the first frame MultiValue myval( 1, getNumberOfArguments() + 3*getNumberOfAtoms() + 9 ); ReferenceValuePack mypack( getNumberOfArguments(), getNumberOfAtoms(), myval ); - for(unsigned i=0;isetupPCAStorage ( mypack ); // Create some arrays to store the average position std::vector sarg( getNumberOfArguments(), 0 ); std::vector spos( getNumberOfAtoms() ); - for(unsigned i=0;icalc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); - // Accumulate average displacement of arguments (Here PBC could do fucked up things - really needs Berry Phase ) GAT - for(unsigned j=0;jcalc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); + // Accumulate average displacement of arguments (Here PBC could do fucked up things - really needs Berry Phase ) GAT + for(unsigned j=0; jgetReferenceArguments()[j]; - for(unsigned j=0;jgetReferencePositions()[j]; + double inorm = 1.0 / norm ; + for(unsigned j=0; jgetReferenceArguments()[j]; + for(unsigned j=0; jgetReferencePositions()[j]; // And set the reference configuration - std::vector empty( getNumberOfArguments(), 1.0 ); myref->setReferenceConfig( spos, sarg, empty ); + std::vector empty( getNumberOfArguments(), 1.0 ); myref->setReferenceConfig( spos, sarg, empty ); // Now accumulate the covariance unsigned narg=getNumberOfArguments(); Matrix covar( getNumberOfArguments()+3*getNumberOfAtoms(), getNumberOfArguments()+3*getNumberOfAtoms() ); covar=0; - for(unsigned i=0;icalc( spos, getPbc(), getArguments(), sarg, mypack, true ); - double d = data[0]->calc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); - for(unsigned jarg=0;jarggetReferenceArguments()[jarg] - sarg[jarg]; - for(unsigned karg=0;karggetReferenceArguments()[karg] - sarg[karg]; - covar( jarg, karg ) += 0.25*getWeight(i)*jarg_d*karg_d; // mypack.getArgumentDerivative(jarg)*mypack.getArgumentDerivative(karg); - } + for(unsigned i=0; icalc( spos, getPbc(), getArguments(), sarg, mypack, true ); + double d = data[0]->calc( data[i]->getReferencePositions(), getPbc(), getArguments(), data[i]->getReferenceArguments(), mypack, true ); + for(unsigned jarg=0; jarggetReferenceArguments()[jarg] - sarg[jarg]; + for(unsigned karg=0; karggetReferenceArguments()[karg] - sarg[karg]; + covar( jarg, karg ) += 0.25*getWeight(i)*jarg_d*karg_d; // mypack.getArgumentDerivative(jarg)*mypack.getArgumentDerivative(karg); } - for(unsigned jat=0;jatgetReferencePositions()[jat][jc] - spos[jat][jc]; - for(unsigned kat=0;katgetReferencePositions()[kat][kc] - spos[kat][kc]; - covar( narg+3*jat + jc, narg+3*kat + kc ) += getWeight(i)*jdisplace*kdisplace; - } - } - } + } + for(unsigned jat=0; jatgetReferencePositions()[jat][jc] - spos[jat][jc]; + for(unsigned kat=0; katgetReferencePositions()[kat][kc] - spos[kat][kc]; + covar( narg+3*jat + jc, narg+3*kat + kc ) += getWeight(i)*jdisplace*kdisplace; + } + } } + } } // Normalise - for(unsigned i=0;iprint( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); + myref->print( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); // Store and print the eigenvectors std::vector tmp_atoms( getNumberOfAtoms() ); std::vector tmp_args( getNumberOfArguments() ); Direction* tref = metricRegister().create( "DIRECTION" ); tref->setNamesAndAtomNumbers( getAbsoluteIndexes(), argument_names ); - for(unsigned dim=0;dimsetDirection( tmp_atoms, tmp_args ); - tref->print( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); - } - // Close the output file + for(unsigned dim=0; dimsetDirection( tmp_atoms, tmp_args ); + tref->print( ofile, getOutputFormat(), atoms.getUnits().getLength()/0.1 ); + } + // Close the output file delete tref; ofile.close(); } diff --git a/src/analysis/SelectAllFrames.cpp b/src/analysis/SelectAllFrames.cpp index 56ea3751fc..8f61b7305d 100644 --- a/src/analysis/SelectAllFrames.cpp +++ b/src/analysis/SelectAllFrames.cpp @@ -34,13 +34,13 @@ class CopyAllFrames : public LandmarkSelectionBase { PLUMED_REGISTER_LANDMARKS(CopyAllFrames,"ALL") CopyAllFrames::CopyAllFrames( const LandmarkSelectionOptions& lo ): -LandmarkSelectionBase(lo) + LandmarkSelectionBase(lo) { } -void CopyAllFrames::select( MultiReferenceBase* myframes ){ +void CopyAllFrames::select( MultiReferenceBase* myframes ) { nlandmarks = action->getNumberOfDataPoints(); - for(unsigned i=0;i to; std::vector min; std::vector kappa; @@ -96,7 +96,7 @@ class ABMD : public Bias{ PLUMED_REGISTER_ACTION(ABMD,"ABMD") -void ABMD::registerKeywords(Keywords& keys){ +void ABMD::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","TO","The array of target values"); @@ -106,18 +106,18 @@ void ABMD::registerKeywords(Keywords& keys){ keys.add("optional","SEED","Array of seeds for the white noise (add a temperature to the ABMD)"); keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); keys.addOutputComponent("_min","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - " These quantities will be named with the arguments of the bias followed by " - "the character string _min. These quantities tell the user the minimum value assumed by rho_m(t)."); + " These quantities will be named with the arguments of the bias followed by " + "the character string _min. These quantities tell the user the minimum value assumed by rho_m(t)."); } ABMD::ABMD(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -to(getNumberOfArguments(),0.0), -min(getNumberOfArguments(),-1.0), -kappa(getNumberOfArguments(),0.0), -temp(getNumberOfArguments(),0.0), -seed(getNumberOfArguments(),time(0)), -random(getNumberOfArguments()) + PLUMED_BIAS_INIT(ao), + to(getNumberOfArguments(),0.0), + min(getNumberOfArguments(),-1.0), + kappa(getNumberOfArguments(),0.0), + temp(getNumberOfArguments(),0.0), + seed(getNumberOfArguments(),time(0)), + random(getNumberOfArguments()) { // Note : parseVector will check that number of arguments is correct parseVector("KAPPA",kappa); @@ -130,35 +130,35 @@ random(getNumberOfArguments()) checkRead(); log.printf(" min"); - for(unsigned i=0;igetName()+"_min"; - addComponent(str_min); componentIsNotPeriodic(str_min); - if(min[i]!=-1.0) getPntrToComponent(str_min)->set(min[i]); + for(unsigned i=0; igetName()+"_min"; + addComponent(str_min); componentIsNotPeriodic(str_min); + if(min[i]!=-1.0) getPntrToComponent(str_min)->set(min[i]); } - for(unsigned i=0;i0) { + if(diff>0) { noise = 2.*random[i].Gaussian()*diff; if(cv2<=diff) { diff=0.; temp[i]=0.; } } @@ -166,11 +166,11 @@ void ABMD::calculate(){ // min < 0 means that the variable has not been used in the input file, so the current position of the CV is used // cv2 < min means that the collective variable is nearer to the target value than at any other previous time so // min is set to the CV value - if(min[i]<0.||cv21){ + if(getStride()>1) { log<<" multiple time step "<getPntrToAction())->turnOnDerivatives(); + for(unsigned i=0; igetPntrToAction())->turnOnDerivatives(); } turnOnDerivatives(); } -void Bias::registerKeywords( Keywords& keys ){ +void Bias::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithValue::registerKeywords(keys); @@ -57,13 +57,13 @@ void Bias::registerKeywords( Keywords& keys ){ keys.addOutputComponent("bias","default","the instantaneous value of the bias potential"); } -void Bias::apply(){ +void Bias::apply() { const unsigned noa=getNumberOfArguments(); const unsigned ncp=getNumberOfComponents(); - if(onStep()) { + if(onStep()) { double gstr = static_cast(getStride()); - for(unsigned i=0;iaddForce(gstr*outputForces[i]); } } @@ -73,18 +73,18 @@ void Bias::apply(){ std::vector forces(noa); bool at_least_one_forced=false; - for(unsigned i=0;iapplyForce(forces)){ - at_least_one_forced=true; - for(unsigned j=0;japplyForce(forces)) { + at_least_one_forced=true; + for(unsigned j=0; jaddForce(f[i]); - } + if(at_least_one_forced) for(unsigned i=0; iaddForce(f[i]); + } } diff --git a/src/bias/Bias.h b/src/bias/Bias.h index 551372dec8..25776466f4 100644 --- a/src/bias/Bias.h +++ b/src/bias/Bias.h @@ -28,12 +28,12 @@ #define PLUMED_BIAS_INIT(ao) Action(ao),Bias(ao) -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { /** \ingroup INHERIT -This is the abstract base class to use for implementing new simulation biases, within it there is +This is the abstract base class to use for implementing new simulation biases, within it there is information as to how to go about implementing a new bias. */ @@ -59,18 +59,18 @@ class Bias : }; inline -void Bias::setOutputForce(int i,double f){ +void Bias::setOutputForce(int i,double f) { outputForces[i]=f; valueBias->addDerivative(i,-f); } inline -void Bias::setBias(double bias){ - valueBias->set(bias); +void Bias::setBias(double bias) { + valueBias->set(bias); } inline -unsigned Bias::getNumberOfDerivatives(){ +unsigned Bias::getNumberOfDerivatives() { return getNumberOfArguments(); } diff --git a/src/bias/BiasValue.cpp b/src/bias/BiasValue.cpp index 4d5e3e25b5..3e77621a55 100644 --- a/src/bias/BiasValue.cpp +++ b/src/bias/BiasValue.cpp @@ -26,10 +26,10 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { -//+PLUMEDOC BIAS BIASVALUE +//+PLUMEDOC BIAS BIASVALUE /* Takes the value of one variable and use it as a bias @@ -40,7 +40,7 @@ to some collective variable then using the value of this function directly as a \par Examples The following input tells plumed to use the value of the distance between atoms 3 and 5 -and the value of the distance between atoms 2 and 4 as biases. +and the value of the distance between atoms 2 and 4 as biases. It then tells plumed to print the energy of the restraint \verbatim DISTANCE ATOMS=3,5 LABEL=d1 @@ -50,13 +50,13 @@ PRINT ARG=d1,d2,b.d1,b.d2 \endverbatim (See also \ref DISTANCE and \ref PRINT). -Another thing one can do is asking one system to follow +Another thing one can do is asking one system to follow a circle in sin/cos according a time dependence \verbatim t: TIME # this just print cos and sin of time -cos: MATHEVAL ARG=t VAR=t FUNC=cos(t) PERIODIC=NO +cos: MATHEVAL ARG=t VAR=t FUNC=cos(t) PERIODIC=NO sin: MATHEVAL ARG=t VAR=t FUNC=sin(t) PERIODIC=NO c1: COM ATOMS=1,2 c2: COM ATOMS=3,4 @@ -65,11 +65,11 @@ PRINT ARG=t,cos,sin,d.x,d.y,d.z STRIDE=1 FILE=colvar FMT=%8.4f # this calculates sine and cosine of a projected component of distance mycos: MATHEVAL ARG=d.x,d.y VAR=x,y FUNC=x/sqrt(x*x+y*y) PERIODIC=NO mysin: MATHEVAL ARG=d.x,d.y VAR=x,y FUNC=y/sqrt(x*x+y*y) PERIODIC=NO -# this creates a moving spring so that the system follows a circle-like dynamics +# this creates a moving spring so that the system follows a circle-like dynamics # but it is not a bias, it is a simple value now vv1: MATHEVAL ARG=mycos,mysin,cos,sin VAR=mc,ms,c,s FUNC=100*((mc-c)^2+(ms-s)^2) PERIODIC=NO -# this takes the value calculated with matheval and uses as a bias -cc: BIASVALUE ARG=vv1 +# this takes the value calculated with matheval and uses as a bias +cc: BIASVALUE ARG=vv1 # some printout PRINT ARG=t,cos,sin,d.x,d.y,d.z,mycos,mysin,cc.bias.vv1 STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim @@ -79,7 +79,7 @@ PRINT ARG=t,cos,sin,d.x,d.y,d.z,mycos,mysin,cc.bias.vv1 STRIDE=1 FILE=colvar FMT */ //+ENDPLUMEDOC -class BiasValue : public Bias{ +class BiasValue : public Bias { public: explicit BiasValue(const ActionOptions&); void calculate(); @@ -88,31 +88,31 @@ class BiasValue : public Bias{ PLUMED_REGISTER_ACTION(BiasValue,"BIASVALUE") -void BiasValue::registerKeywords(Keywords& keys){ +void BiasValue::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); // Should be _bias below keys.addOutputComponent("_bias","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "these quantities will named with the arguments of the bias followed by " - "the character string _bias. These quantities tell the user how much the bias is " - "due to each of the colvars."); + "these quantities will named with the arguments of the bias followed by " + "the character string _bias. These quantities tell the user how much the bias is " + "due to each of the colvars."); } BiasValue::BiasValue(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao) + PLUMED_BIAS_INIT(ao) { checkRead(); - // add one bias for each argument - for(unsigned i=0;igetName()+"_bias"; addComponent(ss); componentIsNotPeriodic(ss); } } -void BiasValue::calculate(){ +void BiasValue::calculate() { double bias=0.0; - for(unsigned i=0;iset(val); setOutputForce(i,-1.); bias+=val; diff --git a/src/bias/ExtendedLagrangian.cpp b/src/bias/ExtendedLagrangian.cpp index 1b89116a20..85de570dd5 100644 --- a/src/bias/ExtendedLagrangian.cpp +++ b/src/bias/ExtendedLagrangian.cpp @@ -31,8 +31,8 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS EXTENDED_LAGRANGIAN /* @@ -114,7 +114,7 @@ PRINT STRIDE=10 ARG=phi,psi,ex.phi_fict,ex.psi_fict FILE=COLVAR */ //+ENDPLUMEDOC -class ExtendedLagrangian : public Bias{ +class ExtendedLagrangian : public Bias { bool firsttime; std::vector fict; std::vector vfict; @@ -136,35 +136,35 @@ class ExtendedLagrangian : public Bias{ PLUMED_REGISTER_ACTION(ExtendedLagrangian,"EXTENDED_LAGRANGIAN") -void ExtendedLagrangian::registerKeywords(Keywords& keys){ - Bias::registerKeywords(keys); - keys.use("ARG"); - keys.add("compulsory","KAPPA","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); - keys.add("compulsory","TAU","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); - keys.add("compulsory","FRICTION","0.0","add a friction to the variable"); - keys.add("optional","TEMP","the system temperature - needed when FRICTION is present. If not provided will be taken from MD code (if available)"); - componentsAreNotOptional(keys); - keys.addOutputComponent("_fict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _tilde. It is possible to add forces on these variable."); - keys.addOutputComponent("_vfict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _tilde. It is NOT possible to add forces on these variable."); +void ExtendedLagrangian::registerKeywords(Keywords& keys) { + Bias::registerKeywords(keys); + keys.use("ARG"); + keys.add("compulsory","KAPPA","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); + keys.add("compulsory","TAU","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); + keys.add("compulsory","FRICTION","0.0","add a friction to the variable"); + keys.add("optional","TEMP","the system temperature - needed when FRICTION is present. If not provided will be taken from MD code (if available)"); + componentsAreNotOptional(keys); + keys.addOutputComponent("_fict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " + "These quantities will named with the arguments of the bias followed by " + "the character string _tilde. It is possible to add forces on these variable."); + keys.addOutputComponent("_vfict","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " + "These quantities will named with the arguments of the bias followed by " + "the character string _tilde. It is NOT possible to add forces on these variable."); } ExtendedLagrangian::ExtendedLagrangian(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -firsttime(true), -fict(getNumberOfArguments(),0.0), -vfict(getNumberOfArguments(),0.0), -vfict_laststep(getNumberOfArguments(),0.0), -ffict(getNumberOfArguments(),0.0), -kappa(getNumberOfArguments(),0.0), -tau(getNumberOfArguments(),0.0), -friction(getNumberOfArguments(),0.0), -fictValue(getNumberOfArguments(),NULL), -vfictValue(getNumberOfArguments(),NULL), -kbt(0.0) + PLUMED_BIAS_INIT(ao), + firsttime(true), + fict(getNumberOfArguments(),0.0), + vfict(getNumberOfArguments(),0.0), + vfict_laststep(getNumberOfArguments(),0.0), + ffict(getNumberOfArguments(),0.0), + kappa(getNumberOfArguments(),0.0), + tau(getNumberOfArguments(),0.0), + friction(getNumberOfArguments(),0.0), + fictValue(getNumberOfArguments(),NULL), + vfictValue(getNumberOfArguments(),NULL), + kbt(0.0) { parseVector("TAU",tau); parseVector("FRICTION",friction); @@ -176,19 +176,19 @@ kbt(0.0) checkRead(); log.printf(" with harmonic force constant"); - for(unsigned i=0;i0.0) hasFriction=true; + for(unsigned i=0; i0.0) hasFriction=true; - if(hasFriction){ + if(hasFriction) { log.printf(" with friction"); - for(unsigned i=0;igetName()+"_fict"; addComponentWithDerivatives(comp); - if(getPntrToArgument(i)->isPeriodic()){ + if(getPntrToArgument(i)->isPeriodic()) { std::string a,b; getPntrToArgument(i)->getDomain(a,b); componentIsPeriodic(comp,a,b); @@ -212,7 +212,7 @@ kbt(0.0) } log<<" Bibliography "<bringBackInPbc(fict[i]); fictValue[i]->set(fict[i]); vfictValue[i]->set(vfict_laststep[i]); } } -void ExtendedLagrangian::update(){ +void ExtendedLagrangian::update() { double dt=getTimeStep()*getStride(); - for(unsigned i=0;igetDimension()!=getNumberOfArguments()) error("mismatch between dimensionality of input grid and number of arguments"); - for(unsigned i=0;iisPeriodic()!=BiasGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); - } + for(unsigned i=0; iisPeriodic()!=BiasGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); + } } void External::calculate() @@ -154,13 +154,13 @@ void External::calculate() unsigned ncv=getNumberOfArguments(); vector cv(ncv), der(ncv); - for(unsigned i=0;igetValueAndDerivatives(cv,der); setBias(ene); - for(unsigned i=0;i at; std::vector kappa; std::vector exp; @@ -78,7 +78,7 @@ class LWalls : public Bias{ PLUMED_REGISTER_ACTION(LWalls,"LOWER_WALLS") -void LWalls::registerKeywords(Keywords& keys){ +void LWalls::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall."); @@ -90,12 +90,12 @@ void LWalls::registerKeywords(Keywords& keys){ } LWalls::LWalls(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -at(getNumberOfArguments(),0), -kappa(getNumberOfArguments(),0.0), -exp(getNumberOfArguments(),2.0), -eps(getNumberOfArguments(),1.0), -offset(getNumberOfArguments(),0.0) + PLUMED_BIAS_INIT(ao), + at(getNumberOfArguments(),0), + kappa(getNumberOfArguments(),0.0), + exp(getNumberOfArguments(),2.0), + eps(getNumberOfArguments(),1.0), + offset(getNumberOfArguments(),0.0) { // Note sizes of these vectors are automatically checked by parseVector :-) parseVector("OFFSET",offset); @@ -106,28 +106,28 @@ offset(getNumberOfArguments(),0.0) checkRead(); log.printf(" at"); - for(unsigned i=0;iset(totf2); + getPntrToComponent("force2")->set(totf2); } } diff --git a/src/bias/MetaD.cpp b/src/bias/MetaD.cpp index 6e9923aaa1..b586185705 100644 --- a/src/bias/MetaD.cpp +++ b/src/bias/MetaD.cpp @@ -41,14 +41,14 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { -//+PLUMEDOC BIAS METAD +//+PLUMEDOC BIAS METAD /* Used to performed MetaDynamics on one or more collective variables. -In a metadynamics simulations a history dependent bias composed of +In a metadynamics simulations a history dependent bias composed of intermittently added Gaussian functions is added to the potential \cite metad. \f[ @@ -60,10 +60,10 @@ V(\vec{s},t) = \sum_{ k \tau < t} W(k \tau) This potential forces the system away from the kinetic traps in the potential energy surface and out into the unexplored parts of the energy landscape. Information on the Gaussian -functions from which this potential is composed is output to a file called HILLS, which -is used both the restart the calculation and to reconstruct the free energy as a function of the CVs. +functions from which this potential is composed is output to a file called HILLS, which +is used both the restart the calculation and to reconstruct the free energy as a function of the CVs. The free energy can be reconstructed from a metadynamics calculation because the final bias is given -by: +by: \f[ V(\vec{s}) = -F(\vec(s)) @@ -72,10 +72,10 @@ V(\vec{s}) = -F(\vec(s)) During post processing the free energy can be calculated in this way using the \ref sum_hills utility. -In the simplest possible implementation of a metadynamics calculation the expense of a metadynamics -calculation increases with the length of the simulation as one has to, at every step, evaluate +In the simplest possible implementation of a metadynamics calculation the expense of a metadynamics +calculation increases with the length of the simulation as one has to, at every step, evaluate the values of a larger and larger number of Gaussians. To avoid this issue you can -store the bias on a grid. This approach is similar to that proposed in \cite babi08jcp but has the +store the bias on a grid. This approach is similar to that proposed in \cite babi08jcp but has the advantage that the grid spacing is independent on the Gaussian width. Notice that you should provide either the number of bins for every collective variable (GRID_BIN) or @@ -112,19 +112,19 @@ gaussian potential is denoted by one value only that is a Cartesian space (ADAPT (ADAPTIVE=DIFF). Note that a specific integration technique for the deposited gaussians should be used in this case. Check the documentation for utility sum_hills. -With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero -outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only +With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero +outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only to the free energy for s > sw, the history dependent potential is still updated according to the above -equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also -if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the -force on the system in the region s > sw comes from both metadynamics and the force field, in the region -s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that -fluctuates around a stable estimator, equal to the negative of the free energy far enough from the +equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also +if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the +force on the system in the region s > sw comes from both metadynamics and the force field, in the region +s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that +fluctuates around a stable estimator, equal to the negative of the free energy far enough from the boundaries. Note that: - It works only for one-dimensional biases; - It works both with and without GRID; - The interval limit sw in a region where the free energy derivative is not large; -- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should +- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should be used together with a \ref UPPER_WALLS or \ref LOWER_WALLS at sw. As a final note, since version 2.0.2 when the system is outside of the selected interval the force @@ -134,21 +134,21 @@ for replica exchange methods to be computed correctly. Multiple walkers \cite multiplewalkers can also be used. See below the examples. -The c(t) reweighting factor can also be calculated on the fly using the equations -presented in \cite Tiwary_jp504920s. -The expression used to calculate c(t) follows directly from using Eq. 12 in -Eq. 3 in \cite Tiwary_jp504920s and gives smoother results than equivalent Eqs. 13 -and Eqs. 14 in that paper. The c(t) is given by the rct component while the bias -normalized by c(t) is given by the rbias component (rbias=bias-ct) which can be used +The c(t) reweighting factor can also be calculated on the fly using the equations +presented in \cite Tiwary_jp504920s. +The expression used to calculate c(t) follows directly from using Eq. 12 in +Eq. 3 in \cite Tiwary_jp504920s and gives smoother results than equivalent Eqs. 13 +and Eqs. 14 in that paper. The c(t) is given by the rct component while the bias +normalized by c(t) is given by the rbias component (rbias=bias-ct) which can be used to obtain a reweighted histogram. -The calculation of c(t) is enabled by using the keyword REWEIGHTING_NGRID where the grid used for the +The calculation of c(t) is enabled by using the keyword REWEIGHTING_NGRID where the grid used for the calculation is specified. This grid should have a size that is equal or larger than the grid given in GRID_BIN./ -By default c(t) is updated every 50 Gaussian hills but this -can be changed by using the REWEIGHTING_NHILLS keyword. -This option can only be employed together with Well-Tempered Metadynamics and requires that +By default c(t) is updated every 50 Gaussian hills but this +can be changed by using the REWEIGHTING_NHILLS keyword. +This option can only be employed together with Well-Tempered Metadynamics and requires that a grid is used. -Additional material and examples can be also found in the tutorials: +Additional material and examples can be also found in the tutorials: - \ref belfast-6 - \ref belfast-7 @@ -174,7 +174,7 @@ PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \par If you use adaptive Gaussians, with diffusion scheme where you use a Gaussian that should cover the space of 20 timesteps in collective variables. -Note that in this case the histogram correction is needed when summing up hills. +Note that in this case the histogram correction is needed when summing up hills. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 @@ -185,7 +185,7 @@ PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \par If you use adaptive Gaussians, with geometrical scheme where you use a Gaussian that should cover the space of 0.05 nm in Cartesian space. -Note that in this case the histogram correction is needed when summing up hills. +Note that in this case the histogram correction is needed when summing up hills. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 @@ -194,40 +194,40 @@ PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \endverbatim \par -When using adaptive Gaussians you might want to limit how the hills width can change. +When using adaptive Gaussians you might want to limit how the hills width can change. You can use SIGMA_MIN and SIGMA_MAX keywords. -The sigmas should specified in terms of CV so you should use the CV units. +The sigmas should specified in terms of CV so you should use the CV units. Note that if you use a negative number, this means that the limit is not set. -Note also that in this case the histogram correction is needed when summing up hills. +Note also that in this case the histogram correction is needed when summing up hills. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 METAD ... ARG=d1,d2 SIGMA=0.05 HEIGHT=0.3 PACE=500 LABEL=restraint ADAPTIVE=GEOM - SIGMA_MIN=0.2,0.1 SIGMA_MAX=0.5,1.0 -... METAD + SIGMA_MIN=0.2,0.1 SIGMA_MAX=0.5,1.0 +... METAD PRINT ARG=d1,d2,restraint.bias STRIDE=100 FILE=COLVAR \endverbatim \par -Multiple walkers can be also use as in \cite multiplewalkers -These are enabled by setting the number of walker used, the id of the -current walker which interprets the input file, the directory where the +Multiple walkers can be also use as in \cite multiplewalkers +These are enabled by setting the number of walker used, the id of the +current walker which interprets the input file, the directory where the hills containing files resides, and the frequency to read the other walkers. Here is an example \verbatim DISTANCE ATOMS=3,5 LABEL=d1 METAD ... - ARG=d1 SIGMA=0.05 HEIGHT=0.3 PACE=500 LABEL=restraint + ARG=d1 SIGMA=0.05 HEIGHT=0.3 PACE=500 LABEL=restraint WALKERS_N=10 WALKERS_ID=3 WALKERS_DIR=../ WALKERS_RSTRIDE=100 ... METAD \endverbatim -where WALKERS_N is the total number of walkers, WALKERS_ID is the -id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory -where all the walkers are located. WALKERS_RSTRIDE is the number of step between +where WALKERS_N is the total number of walkers, WALKERS_ID is the +id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory +where all the walkers are located. WALKERS_RSTRIDE is the number of step between one update and the other. Since version 2.2.5, hills files are automatically flushed every WALKERS_RSTRIDE steps. @@ -331,20 +331,20 @@ The number of elements in the RECT array should be equal to the number of replic */ //+ENDPLUMEDOC -class MetaD : public Bias{ +class MetaD : public Bias { private: struct Gaussian { - vector center; - vector sigma; - double height; - bool multivariate; // this is required to discriminate the one dimensional case - vector invsigma; - Gaussian(const vector & center,const vector & sigma,double height, bool multivariate ): - center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma){ - // to avoid troubles from zero element in flexible hills - for(unsigned i=0;i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; - } + vector center; + vector sigma; + double height; + bool multivariate; // this is required to discriminate the one dimensional case + vector invsigma; + Gaussian(const vector & center,const vector & sigma,double height, bool multivariate ): + center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma) { + // to avoid troubles from zero element in flexible hills + for(unsigned i=0; i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; + } }; vector sigma0_; vector sigma0min_; @@ -354,7 +354,7 @@ class MetaD : public Bias{ OFile gridfile_; Grid* BiasGrid_; bool storeOldGrids_; - int wgridstride_; + int wgridstride_; bool grid_; double height0_; double biasf_; @@ -383,11 +383,11 @@ class MetaD : public Bias{ bool doInt_; bool isFirstStep; double reweight_factor; - vector rewf_grid_; + vector rewf_grid_; unsigned rewf_ustride_; double work_; long int last_step_warn_grid; - + void readGaussians(IFile*); bool readChunkOfGaussians(IFile *ifile, unsigned n); void writeGaussian(const Gaussian&,OFile&); @@ -407,15 +407,15 @@ class MetaD : public Bias{ void calculate(); void update(); static void registerKeywords(Keywords& keys); - bool checkNeedsGradients()const{if(adaptive_==FlexibleBin::geometry){return true;}else{return false;}} + bool checkNeedsGradients()const {if(adaptive_==FlexibleBin::geometry) {return true;} else {return false;}} }; PLUMED_REGISTER_ACTION(MetaD,"METAD") -void MetaD::registerKeywords(Keywords& keys){ +void MetaD::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.addOutputComponent("rbias","REWEIGHTING_NGRID","the instantaneous value of the bias normalized using the \\f$c(t)\\f$ reweighting factor [rbias=bias-c(t)]." - "This component can be used to obtain a reweighted histogram."); + "This component can be used to obtain a reweighted histogram."); keys.addOutputComponent("rct","REWEIGHTING_NGRID","the reweighting factor \\f$c(t)\\f$."); keys.addOutputComponent("work","default","accumulator for work"); keys.addOutputComponent("acc","ACCELERATION","the metadynamics acceleration factor"); @@ -436,11 +436,11 @@ void MetaD::registerKeywords(Keywords& keys){ keys.add("optional","GRID_BIN","the number of bins for the grid"); keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); keys.add("optional","REWEIGHTING_NGRID","calculate the c(t) reweighting factor and use that to obtain the normalized bias [rbias=bias-c(t)]." - "Here you should specify the number of grid points required in each dimension." - "The number of grid points should be equal or larger to the number of grid points given in GRID_BIN." - "This method is not compatible with metadynamics not on a grid."); + "Here you should specify the number of grid points required in each dimension." + "The number of grid points should be equal or larger to the number of grid points given in GRID_BIN." + "This method is not compatible with metadynamics not on a grid."); keys.add("optional","REWEIGHTING_NHILLS","how many Gaussian hills should be deposited between calculating the c(t) reweighting factor." - "The default is to do this every 50 hills."); + "The default is to do this every 50 hills."); keys.addFlag("GRID_SPARSE",false,"use a sparse grid to store hills"); keys.addFlag("GRID_NOSPLINE",false,"don't use spline interpolation with grids"); keys.add("optional","GRID_WSTRIDE","write the grid to a file every N steps"); @@ -456,13 +456,13 @@ void MetaD::registerKeywords(Keywords& keys){ keys.add("optional","SIGMA_MAX","the upper bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds "); keys.add("optional","SIGMA_MIN","the lower bounds for the sigmas (in CV units) when using adaptive hills. Negative number means no bounds "); keys.addFlag("WALKERS_MPI",false,"Switch on MPI version of multiple walkers - not compatible with WALKERS_* options other than WALKERS_DIR"); - keys.addFlag("ACCELERATION",false,"Set to TRUE if you want to compute the metadynamics acceleration factor."); + keys.addFlag("ACCELERATION",false,"Set to TRUE if you want to compute the metadynamics acceleration factor."); keys.use("RESTART"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); } -MetaD::~MetaD(){ +MetaD::~MetaD() { if(flexbin) delete flexbin; if(BiasGrid_) delete BiasGrid_; if(TargetGrid_) delete TargetGrid_; @@ -470,86 +470,86 @@ MetaD::~MetaD(){ if(wgridstride_>0) gridfile_.close(); delete [] dp_; // close files - for(int i=0;iisOpen()) ifiles[i]->close(); - delete ifiles[i]; + for(int i=0; iisOpen()) ifiles[i]->close(); + delete ifiles[i]; } } MetaD::MetaD(const ActionOptions& ao): -PLUMED_BIAS_INIT(ao), + PLUMED_BIAS_INIT(ao), // Grid stuff initialization -BiasGrid_(NULL), wgridstride_(0), grid_(false), + BiasGrid_(NULL), wgridstride_(0), grid_(false), // Metadynamics basic parameters -height0_(std::numeric_limits::max()), biasf_(-1.0), dampfactor_(0.0), TargetGrid_(NULL), -kbt_(0.0), -stride_(0), welltemp_(false), + height0_(std::numeric_limits::max()), biasf_(-1.0), dampfactor_(0.0), TargetGrid_(NULL), + kbt_(0.0), + stride_(0), welltemp_(false), // Other stuff -dp_(NULL), adaptive_(FlexibleBin::none), -flexbin(NULL), + dp_(NULL), adaptive_(FlexibleBin::none), + flexbin(NULL), // Multiple walkers initialization -mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), -walkers_mpi(false), mpi_nw_(0), mpi_mw_(0), -acceleration(false), acc(0.0), + mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), + walkers_mpi(false), mpi_nw_(0), mpi_mw_(0), + acceleration(false), acc(0.0), // Interval initialization -uppI_(-1), lowI_(-1), doInt_(false), -isFirstStep(true), -reweight_factor(0.0), -rewf_ustride_(1), -work_(0), -last_step_warn_grid(0) + uppI_(-1), lowI_(-1), doInt_(false), + isFirstStep(true), + reweight_factor(0.0), + rewf_ustride_(1), + work_(0), + last_step_warn_grid(0) { // parse the flexible hills string adaptiveoption; adaptiveoption="NONE"; parse("ADAPTIVE",adaptiveoption); - if(adaptiveoption=="GEOM"){ + if(adaptiveoption=="GEOM") { log.printf(" Uses Geometry-based hills width: sigma must be in distance units and only one sigma is needed\n"); - adaptive_=FlexibleBin::geometry; - } else if(adaptiveoption=="DIFF"){ + adaptive_=FlexibleBin::geometry; + } else if(adaptiveoption=="DIFF") { log.printf(" Uses Diffusion-based hills width: sigma must be in timesteps and only one sigma is needed\n"); - adaptive_=FlexibleBin::diffusion; - } else if(adaptiveoption=="NONE"){ - adaptive_=FlexibleBin::none; + adaptive_=FlexibleBin::diffusion; + } else if(adaptiveoption=="NONE") { + adaptive_=FlexibleBin::none; } else { - error("I do not know this type of adaptive scheme"); + error("I do not know this type of adaptive scheme"); } parse("FMT",fmt); // parse the sigma parseVector("SIGMA",sigma0_); - if(adaptive_==FlexibleBin::none){ - // if you use normal sigma you need one sigma per argument + if(adaptive_==FlexibleBin::none) { + // if you use normal sigma you need one sigma per argument if( sigma0_.size()!=getNumberOfArguments() ) error("number of arguments does not match number of SIGMA parameters"); } else { - // if you use flexible hills you need one sigma - if(sigma0_.size()!=1){ + // if you use flexible hills you need one sigma + if(sigma0_.size()!=1) { error("If you choose ADAPTIVE you need only one sigma according to your choice of type (GEOM/DIFF)"); - } + } // if adaptive then the number must be an integer - if(adaptive_==FlexibleBin::diffusion){ - if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ){ - error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); - } - } + if(adaptive_==FlexibleBin::diffusion) { + if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ) { + error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); + } + } // here evtl parse the sigma min and max values parseVector("SIGMA_MIN",sigma0min_); if(sigma0min_.size()>0 && sigma0min_.size()!=getNumberOfArguments()) { error("the number of SIGMA_MIN values be the same of the number of the arguments"); - } else if(sigma0min_.size()==0) { + } else if(sigma0min_.size()==0) { sigma0min_.resize(getNumberOfArguments()); - for(unsigned i=0;i0 && sigma0max_.size()!=getNumberOfArguments()) { - error("the number of SIGMA_MAX values be the same of the number of the arguments"); - } else if(sigma0max_.size()==0) { + error("the number of SIGMA_MAX values be the same of the number of the arguments"); + } else if(sigma0max_.size()==0) { sigma0max_.resize(getNumberOfArguments()); - for(unsigned i=0;i rect_biasf_; parseVector("RECT",rect_biasf_); - if(rect_biasf_.size()>0){ + if(rect_biasf_.size()>0) { int r=0; if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); @@ -575,32 +575,32 @@ last_step_warn_grid(0) parse("TEMP",temp); if(temp>0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; else kbt_=plumed.getAtoms().getKbT(); - if(biasf_>=1.0){ + if(biasf_>=1.0) { if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with well-tempered metad you must specify it using TEMP"); welltemp_=true; } - if(dampfactor_>0.0){ + if(dampfactor_>0.0) { if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with damped metad you must specify it using TEMP"); } parse("TARGET",targetfilename_); if(targetfilename_.length()>0 && kbt_==0.0) error("with TARGET temperature must be specified"); double tau=0.0; parse("TAU",tau); - if(tau==0.0){ + if(tau==0.0) { if(height0_==std::numeric_limits::max()) error("At least one between HEIGHT and TAU should be specified"); // if tau is not set, we compute it here from the other input parameters if(welltemp_) tau=(kbt_*(biasf_-1.0))/height0_*getTimeStep()*stride_; else if(dampfactor_>0.0) tau=(kbt_*dampfactor_)/height0_*getTimeStep()*stride_; } else { if(height0_!=std::numeric_limits::max()) error("At most one between HEIGHT and TAU should be specified"); - if(welltemp_){ + if(welltemp_) { if(biasf_!=1.0) height0_=(kbt_*(biasf_-1.0))/tau*getTimeStep()*stride_; else height0_=kbt_/tau*getTimeStep()*stride_; // special case for gamma=1 } else if(dampfactor_>0.0) height0_=(kbt_*dampfactor_)/tau*getTimeStep()*stride_; else error("TAU only makes sense in well-tempered or damped metadynamics"); } - + // Grid Stuff vector gmin(getNumberOfArguments()); parseVector("GRID_MIN",gmin); @@ -617,71 +617,71 @@ last_step_warn_grid(0) if(gmin.size()!=gmax.size()) error("GRID_MAX and GRID_MIN should be either present or absent"); if(gspacing.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); if(gbin.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); - if(gmin.size()!=0){ - if(gbin.size()==0 && gspacing.size()==0){ - if(adaptive_==FlexibleBin::none){ + if(gmin.size()!=0) { + if(gbin.size()==0 && gspacing.size()==0) { + if(adaptive_==FlexibleBin::none) { log<<" Binsize not specified, 1/5 of sigma will be be used\n"; plumed_assert(sigma0_.size()==getNumberOfArguments()); gspacing.resize(getNumberOfArguments()); - for(unsigned i=0;i0){grid_=true;} + if(gbin.size()>0) {grid_=true;} parse("GRID_WSTRIDE",wgridstride_); string gridfilename_; - parse("GRID_WFILE",gridfilename_); + parse("GRID_WFILE",gridfilename_); parseFlag("STORE_GRIDS",storeOldGrids_); - if(grid_ && gridfilename_.length()>0){ + if(grid_ && gridfilename_.length()>0) { if(wgridstride_==0 ) error("frequency with which to output grid not specified use GRID_WSTRIDE"); } - if(grid_ && wgridstride_>0){ - if(gridfilename_.length()==0) error("grid filename not specified use GRID_WFILE"); + if(grid_ && wgridstride_>0) { + if(gridfilename_.length()==0) error("grid filename not specified use GRID_WFILE"); } string gridreadfilename_; parse("GRID_RFILE",gridreadfilename_); if(!grid_&&gridfilename_.length()> 0) error("To write a grid you need first to define it!"); if(!grid_&&gridreadfilename_.length()>0) error("To read a grid you need first to define it!"); - - if(grid_){ - parseVector("REWEIGHTING_NGRID",rewf_grid_); - if(rewf_grid_.size()>0 && rewf_grid_.size()!=getNumberOfArguments()){ + + if(grid_) { + parseVector("REWEIGHTING_NGRID",rewf_grid_); + if(rewf_grid_.size()>0 && rewf_grid_.size()!=getNumberOfArguments()) { error("size mismatch for REWEIGHTING_NGRID keyword"); - } else if(rewf_grid_.size()==getNumberOfArguments()){ - for(unsigned j=0;jisPeriodic() ) rewf_grid_[j] += 1; + } else if(rewf_grid_.size()==getNumberOfArguments()) { + for(unsigned j=0; jisPeriodic() ) rewf_grid_[j] += 1; } } if(adaptive_==FlexibleBin::diffusion || adaptive_==FlexibleBin::geometry) warning("reweighting has not been proven to work with adaptive Gaussians"); rewf_ustride_=50; parse("REWEIGHTING_NHILLS",rewf_ustride_); } - if(dampfactor_>0.0){ + if(dampfactor_>0.0) { if(!grid_) error("With DAMPFACTOR you should use grids"); } @@ -716,32 +716,32 @@ last_step_warn_grid(0) log.printf(" Gaussian width "); if (adaptive_==FlexibleBin::diffusion)log.printf(" (Note: The units of sigma are in timesteps) "); if (adaptive_==FlexibleBin::geometry)log.printf(" (Note: The units of sigma are in dist units) "); - for(unsigned i=0;i0){log.printf(" Grid is written on file %s with stride %d\n",gridfilename_.c_str(),wgridstride_);} + if(spline) {log.printf(" Grid uses spline interpolation\n");} + if(sparsegrid) {log.printf(" Grid uses sparse grid\n");} + if(wgridstride_>0) {log.printf(" Grid is written on file %s with stride %d\n",gridfilename_.c_str(),wgridstride_);} } - if(mw_n_>1){ + if(mw_n_>1) { if(walkers_mpi) error("MPI version of multiple walkers is not compatible with filesystem version of multiple walkers"); log.printf(" %d multiple walkers active\n",mw_n_); log.printf(" walker id %d\n",mw_id_); @@ -749,9 +749,9 @@ last_step_warn_grid(0) if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); } else { if(walkers_mpi) { - log.printf(" Multiple walkers active using MPI communnication\n"); + log.printf(" Multiple walkers active using MPI communnication\n"); if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { // Only root of group can communicate with other walkers mpi_nw_=multi_sim_comm.Get_size(); mpi_mw_=multi_sim_comm.Get_rank(); @@ -763,16 +763,16 @@ last_step_warn_grid(0) } } - if( rewf_grid_.size()>0 ){ + if( rewf_grid_.size()>0 ) { addComponent("rbias"); componentIsNotPeriodic("rbias"); - addComponent("rct"); componentIsNotPeriodic("rct"); + addComponent("rct"); componentIsNotPeriodic("rct"); log.printf(" the c(t) reweighting factor will be calculated every %u hills\n",rewf_ustride_); getPntrToComponent("rct")->set(reweight_factor); } addComponent("work"); componentIsNotPeriodic("work"); if(acceleration) { - if(!welltemp_) error("The calculation of the acceleration works only if Well-Tempered Metadynamics is on"); + if(!welltemp_) error("The calculation of the acceleration works only if Well-Tempered Metadynamics is on"); log.printf(" calculation on the fly of the acceleration factor"); addComponent("acc"); componentIsNotPeriodic("acc"); } @@ -781,37 +781,37 @@ last_step_warn_grid(0) dp_ = new double[getNumberOfArguments()]; // initializing and checking grid - if(grid_){ - // check for mesh and sigma size - for(unsigned i=0;i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; - } else { - if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; - } - } - std::string funcl=getLabel() + ".bias"; - if(!sparsegrid){BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} - else{BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} - std::vector actualmin=BiasGrid_->getMin(); - std::vector actualmax=BiasGrid_->getMax(); - for(unsigned i=0;i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; + } else { + if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; + } + } + std::string funcl=getLabel() + ".bias"; + if(!sparsegrid) {BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + else {BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + std::vector actualmin=BiasGrid_->getMin(); + std::vector actualmax=BiasGrid_->getMax(); + for(unsigned i=0; i0){ + if(gridreadfilename_.length()>0) { // read the grid in input, find the keys - IFile gridfile; + IFile gridfile; gridfile.link(*this); - if(gridfile.FileExist(gridreadfilename_)){ + if(gridfile.FileExist(gridreadfilename_)) { gridfile.open(gridreadfilename_); } else { error("The GRID file you want to read: " + gridreadfilename_ + ", cannot be found!"); @@ -820,7 +820,7 @@ last_step_warn_grid(0) BiasGrid_=Grid::create(funcl, getArguments(), gridfile, gmin, gmax, gbin, sparsegrid, spline, true); gridfile.close(); if(BiasGrid_->getDimension()!=getNumberOfArguments()) error("mismatch between dimensionality of input grid and number of arguments"); - for(unsigned i=0;iisPeriodic()!=BiasGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); double a, b; Tools::convert(gmin[i],a); @@ -828,16 +828,16 @@ last_step_warn_grid(0) double mesh=(b-a)/((double)gbin[i]); if(mesh>0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; } - log.printf(" Restarting from %s:",gridreadfilename_.c_str()); + log.printf(" Restarting from %s:",gridreadfilename_.c_str()); if(getRestart()) restartedFromGrid=true; } // initializing and checking grid - if(grid_&&!(gridreadfilename_.length()>0)){ + if(grid_&&!(gridreadfilename_.length()>0)) { // check for adaptive and sigma_min if(sigma0min_.size()==0&&adaptive_!=FlexibleBin::none) error("When using Adaptive Gaussians on a grid SIGMA_MIN must be specified"); // check for mesh and sigma size - for(unsigned i=0;i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; } std::string funcl=getLabel() + ".bias"; - if(!sparsegrid){BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} - else{BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + if(!sparsegrid) {BiasGrid_=new Grid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} + else {BiasGrid_=new SparseGrid(funcl,getArguments(),gmin,gmax,gbin,spline,true);} std::vector actualmin=BiasGrid_->getMin(); std::vector actualmax=BiasGrid_->getMax(); - for(unsigned i=0;i1) { @@ -878,13 +878,13 @@ last_step_warn_grid(0) } IFile *ifile = new IFile(); ifile->link(*this); - ifiles.push_back(ifile); + ifiles.push_back(ifile); ifilesnames.push_back(fname); - if(ifile->FileExist(fname)){ + if(ifile->FileExist(fname)) { ifile->open(fname); - if(getRestart()&&!restartedFromGrid){ - log.printf(" Restarting from %s:",ifilesnames[i].c_str()); - readGaussians(ifiles[i]); + if(getRestart()&&!restartedFromGrid) { + log.printf(" Restarting from %s:",ifilesnames[i].c_str()); + readGaussians(ifiles[i]); } ifiles[i]->reset(false); // close only the walker own hills file for later writing @@ -901,13 +901,13 @@ last_step_warn_grid(0) // (e.g. in bias exchange with a neutral replica) // see issue #168 on github if(comm.Get_rank()==0 && walkers_mpi) multi_sim_comm.Barrier(); - if(targetfilename_.length()>0){ + if(targetfilename_.length()>0) { IFile gridfile; gridfile.open(targetfilename_); std::string funcl=getLabel() + ".target"; TargetGrid_=Grid::create(funcl,getArguments(),gridfile,false,false,true); gridfile.close(); if(TargetGrid_->getDimension()!=getNumberOfArguments()) error("mismatch between dimensionality of input grid and number of arguments"); - for(unsigned i=0;iisPeriodic()!=TargetGrid_->getIsPeriodic()[i] ) error("periodicity mismatch between arguments and input bias"); } } @@ -916,9 +916,9 @@ last_step_warn_grid(0) if(getRestart() && rewf_grid_.size()>0 ) computeReweightingFactor(); // open grid file for writing - if(wgridstride_>0){ + if(wgridstride_>0) { gridfile_.link(*this); - if(walkers_mpi){ + if(walkers_mpi) { int r=0; if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); @@ -931,7 +931,7 @@ last_step_warn_grid(0) // open hills file for writing hillsOfile_.link(*this); - if(walkers_mpi){ + if(walkers_mpi) { int r=0; if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); @@ -948,14 +948,14 @@ last_step_warn_grid(0) } hillsOfile_.setHeavyFlush(); // output periodicities of variables - for(unsigned i=0;i(p)){ concurrent=true; break; } + for(const auto & p : actionSet) if(dynamic_cast(p)) { concurrent=true; break; } if(concurrent) log<<" You are using concurrent metadynamics\n"; - if(rect_biasf_.size()>0){ - if(walkers_mpi){ + if(rect_biasf_.size()>0) { + if(walkers_mpi) { log<<" You are using RECT in its 'altruistic' implementation\n"; }{ log<<" You are using RECT\n"; @@ -964,22 +964,22 @@ last_step_warn_grid(0) log<<" Bibliography "<1||walkers_mpi) log<0) log<0) log<0 && walkers_mpi) log<0){ + "Hosek, Toulcova, Bortolato, and Spiwok, J. Phys. Chem. B 120, 2209 (2016)"); + if(targetfilename_.length()>0) { log< center(ncv); vector sigma(ncv); double height; - int nhills=0; + int nhills=0; bool multivariate=false; - + std::vector tmpvalues; - for(unsigned j=0;jgetName(), false ) ); - - while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)){; + for(unsigned j=0; jgetName(), false ) ); + + while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)) { + ; nhills++; // note that for gamma=1 we store directly -F - if(welltemp_ && biasf_>1.0){height*=(biasf_-1.0)/biasf_;} + if(welltemp_ && biasf_>1.0) {height*=(biasf_-1.0)/biasf_;} addGaussian(Gaussian(center,sigma,height,multivariate)); - } + } log.printf(" %d Gaussians read\n",nhills); } @@ -1017,18 +1018,19 @@ bool MetaD::readChunkOfGaussians(IFile *ifile, unsigned n) unsigned nhills=0; bool multivariate=false; std::vector tmpvalues; - for(unsigned j=0;jgetName(), false ) ); - - while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)){; + for(unsigned j=0; jgetName(), false ) ); + + while(scanOneHill(ifile,tmpvalues,center,sigma,height,multivariate)) { + ; // note that for gamma=1 we store directly -F - if(welltemp_ && biasf_>1.0) height*=(biasf_-1.0)/biasf_; + if(welltemp_ && biasf_>1.0) height*=(biasf_-1.0)/biasf_; addGaussian(Gaussian(center,sigma,height,multivariate)); - if(nhills==n){ + if(nhills==n) { log.printf(" %u Gaussians read\n",nhills); return true; } nhills++; - } + } log.printf(" %u Gaussians read\n",nhills); return false; } @@ -1037,26 +1039,26 @@ void MetaD::writeGaussian(const Gaussian& hill, OFile&file) { unsigned ncv=getNumberOfArguments(); file.printField("time",getTimeStep()*getStep()); - for(unsigned i=0;i mymatrix(ncv,ncv); unsigned k=0; - for(unsigned i=0;i invmatrix(ncv,ncv); Invert(mymatrix,invmatrix); // enforce symmetry - for(unsigned i=0;i lower(ncv,ncv); cholesky(invmatrix,lower); - // loop in band form - for(unsigned i=0;igetName()+"_"+getPntrToArgument(j)->getName(),lower(j+i,j)); } } } else { hillsOfile_.printField("multivariate","false"); - for(unsigned i=0;igetName(),hill.sigma[i]); } double height=hill.height; // note that for gamma=1 we store directly -F - if(welltemp_ && biasf_>1.0) height*=biasf_/(biasf_-1.0); + if(welltemp_ && biasf_>1.0) height*=biasf_/(biasf_-1.0); file.printField("height",height).printField("biasf",biasf_); if(mw_n_>1) file.printField("clock",int(std::time(0))); file.printField(); @@ -1085,36 +1087,36 @@ void MetaD::writeGaussian(const Gaussian& hill, OFile&file) void MetaD::addGaussian(const Gaussian& hill) { - if(!grid_) hills_.push_back(hill); + if(!grid_) hills_.push_back(hill); else { unsigned ncv=getNumberOfArguments(); vector nneighb=getGaussianSupport(hill); vector neighbors=BiasGrid_->getNeighbors(hill.center,nneighb); vector der(ncv); vector xx(ncv); - if(comm.Get_size()==1){ - for(unsigned i=0;igetPoint(ineigh,xx); double bias=evaluateGaussian(xx,hill,&der[0]); BiasGrid_->addValueAndDerivatives(ineigh,bias,der); - } + } } else { unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); vector allder(ncv*neighbors.size(),0.0); vector allbias(neighbors.size(),0.0); - for(unsigned i=rank;igetPoint(ineigh,xx); allbias[i]=evaluateGaussian(xx,hill,&allder[ncv*i]); } comm.Sum(allbias); comm.Sum(allder); - for(unsigned i=0;iaddValueAndDerivatives(ineigh,allbias[i],der); } } @@ -1124,42 +1126,42 @@ void MetaD::addGaussian(const Gaussian& hill) vector MetaD::getGaussianSupport(const Gaussian& hill) { vector nneigh; - vector cutoff; + vector cutoff; unsigned ncv=getNumberOfArguments(); - // traditional or flexible hill? - if(hill.multivariate){ + // traditional or flexible hill? + if(hill.multivariate) { unsigned k=0; Matrix mymatrix(ncv,ncv); - for(unsigned i=0;i myinv(ncv,ncv); Invert(mymatrix,myinv); Matrix myautovec(ncv,ncv); - vector myautoval(ncv); //should I take this or their square root? + vector myautoval(ncv); //should I take this or their square root? diagMat(myinv,myautoval,myautovec); double maxautoval=0.; - unsigned ind_maxautoval;ind_maxautoval=ncv; - for(unsigned i=0;imaxautoval){maxautoval=myautoval[i];ind_maxautoval=i;} - } - for(unsigned i=0;imaxautoval) {maxautoval=myautoval[i]; ind_maxautoval=i;} + } + for(unsigned i=0; i uppI_ || hill.center[0]-cutoff[0] < lowI_) { + if(doInt_) { + if(hill.center[0]+cutoff[0] > uppI_ || hill.center[0]-cutoff[0] < lowI_) { // in this case, we updated the entire grid to avoid problems return BiasGrid_->getNbin(); } else { @@ -1167,19 +1169,19 @@ vector MetaD::getGaussianSupport(const Gaussian& hill) return nneigh; } } else { - for(unsigned i=0;i(ceil(cutoff[i]/BiasGrid_->getDx()[i])) ); } } - + return nneigh; } double MetaD::getBiasAndDerivatives(const vector& cv, double* der) { double bias=0.0; - if(!grid_){ - if(hills_.size()>10000 && (getStep()-last_step_warn_grid)>10000){ + if(!grid_) { + if(hills_.size()>10000 && (getStep()-last_step_warn_grid)>10000) { std::string msg; Tools::convert(hills_.size(),msg); msg="You have accumulated "+msg+" hills, you should enable GRIDs to avoid serious performance hits"; @@ -1188,19 +1190,19 @@ double MetaD::getBiasAndDerivatives(const vector& cv, double* der) } unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); - for(unsigned i=rank;i vder(getNumberOfArguments()); - bias=BiasGrid_->getValueAndDerivatives(cv,vder); - for(unsigned i=0;i vder(getNumberOfArguments()); + bias=BiasGrid_->getValueAndDerivatives(cv,vder); + for(unsigned i=0; igetValue(cv); - } + } } return bias; @@ -1208,15 +1210,15 @@ double MetaD::getBiasAndDerivatives(const vector& cv, double* der) double MetaD::getGaussianNormalization( const Gaussian& hill ) { - double norm=1; + double norm=1; unsigned ncv=hill.center.size(); - if(hill.multivariate){ - // recompose the full sigma from the upper diag cholesky - unsigned k=0; + if(hill.multivariate) { + // recompose the full sigma from the upper diag cholesky + unsigned k=0; Matrix mymatrix(ncv,ncv); - for(unsigned i=0;i(ncv)/2.0); @@ -1240,65 +1242,65 @@ double MetaD::evaluateGaussian(const vector& cv, const Gaussian& hill, d const double *pcv=NULL; // pointer to cv double tmpcv[1]; // tmp array with cv (to be used with doInt_) if(cv.size()>0) pcv=&cv[0]; - if(doInt_){ + if(doInt_) { plumed_assert(cv.size()==1); tmpcv[0]=cv[0]; if(cv[0]uppI_) tmpcv[0]=uppI_; pcv=&(tmpcv[0]); } - if(hill.multivariate){ + if(hill.multivariate) { unsigned k=0; - unsigned ncv=cv.size(); - // recompose the full sigma from the upper diag cholesky + unsigned ncv=cv.size(); + // recompose the full sigma from the upper diag cholesky Matrix mymatrix(ncv,ncv); - for(unsigned i=0;iuppI_) for(unsigned i=0;iuppI_) for(unsigned i=0; i& cv, const Gaussian& hill, d double MetaD::getHeight(const vector& cv) { double height=height0_; - if(welltemp_){ + if(welltemp_) { double vbias = getBiasAndDerivatives(cv); - if(biasf_>1.0){ + if(biasf_>1.0) { height = height0_*exp(-vbias/(kbt_*(biasf_-1.0))); } else { // notice that if gamma=1 we store directly -F height = height0_*exp(-vbias/kbt_); } - } - if(dampfactor_>0.0){ + } + if(dampfactor_>0.0) { plumed_assert(BiasGrid_); double m=BiasGrid_->getMaxValue(); height*=exp(-m/(kbt_*(dampfactor_))); } - if(TargetGrid_){ + if(TargetGrid_) { double f=TargetGrid_->getValue(cv)-TargetGrid_->getMaxValue(); height*=exp(f/kbt_); } @@ -1337,15 +1339,15 @@ void MetaD::calculate() const unsigned ncv=getNumberOfArguments(); vector cv(ncv); double* der = new double[ncv]; - for(unsigned i=0;iset(mean_acc); } getPntrToComponent("work")->set(work_); - // set Forces - for(unsigned i=0;i cv(getNumberOfArguments()); vector thissigma; bool multivariate; // adding hills criteria (could be more complex though) - bool nowAddAHill; + bool nowAddAHill; if(getStep()%stride_==0 && !isFirstStep )nowAddAHill=true; else { nowAddAHill=false; isFirstStep=false; } - for(unsigned i=0;iupdate(nowAddAHill); multivariate=true; } else { multivariate=false; } - if(nowAddAHill){ + if(nowAddAHill) { // add a Gaussian double height=getHeight(cv); - // returns upper diagonal inverse + // returns upper diagonal inverse if(adaptive_!=FlexibleBin::none) thissigma=flexbin->getInverseMatrix(); // returns normal sigma else thissigma=sigma0_; // In case we use walkers_mpi, it is now necessary to communicate with other replicas. - if(walkers_mpi){ + if(walkers_mpi) { // Allocate arrays to store all walkers hills std::vector all_cv(mpi_nw_*cv.size(),0.0); std::vector all_sigma(mpi_nw_*thissigma.size(),0.0); std::vector all_height(mpi_nw_,0.0); std::vector all_multivariate(mpi_nw_,0); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { // Communicate (only root) multi_sim_comm.Allgather(cv,all_cv); multi_sim_comm.Allgather(thissigma,all_sigma); @@ -1417,12 +1419,12 @@ void MetaD::update(){ comm.Bcast(all_sigma,0); comm.Bcast(all_height,0); comm.Bcast(all_multivariate,0); - for(unsigned i=0;i cv_now(cv.size()); std::vector sigma_now(thissigma.size()); - for(unsigned j=0;j1.0?(biasf_-1.0)/biasf_:1.0),all_multivariate[i]); addGaussian(newhill); @@ -1438,7 +1440,7 @@ void MetaD::update(){ // this should be outside of the if block in case // mw_rstride_ is not a multiple of stride_ - if(mw_n_>1 && getStep()%mw_rstride_==0){ + if(mw_n_>1 && getStep()%mw_rstride_==0) { hillsOfile_.flush(); } @@ -1446,7 +1448,7 @@ void MetaD::update(){ work_+=vbias1-vbias; // dump grid on file - if(wgridstride_>0&&(getStep()%wgridstride_==0||getCPT())){ + if(wgridstride_>0&&(getStep()%wgridstride_==0||getCPT())) { // in case old grids are stored, a sequence of grids should appear // this call results in a repetition of the header: if(storeOldGrids_) gridfile_.clearFields(); @@ -1457,10 +1459,10 @@ void MetaD::update(){ if(walkers_mpi) { if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); comm.Bcast(r,0); - } + } if(r==0) gridfile_.rewind(); } - BiasGrid_->writeToFile(gridfile_); + BiasGrid_->writeToFile(gridfile_); // if a single grid is stored, it is necessary to flush it, otherwise // the file might stay empty forever (when a single grid is not large enough to // trigger flushing from the operating system). @@ -1471,83 +1473,83 @@ void MetaD::update(){ } // if multiple walkers and time to read Gaussians - if(mw_n_>1 && getStep()%mw_rstride_==0){ - for(int i=0;i1 && getStep()%mw_rstride_==0) { + for(int i=0; iisOpen())){ + // if the file is not open yet + if(!(ifiles[i]->isOpen())) { // check if it exists now and open it! if(ifiles[i]->FileExist(ifilesnames[i])) { ifiles[i]->open(ifilesnames[i]); ifiles[i]->reset(false); } - // otherwise read the new Gaussians + // otherwise read the new Gaussians } else { log.printf(" Reading hills from %s:",ifilesnames[i].c_str()); readGaussians(ifiles[i]); ifiles[i]->reset(false); } } - } + } if(getStep()%(stride_*rewf_ustride_)==0 && nowAddAHill && rewf_grid_.size()>0 ) computeReweightingFactor(); } -/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height -bool MetaD::scanOneHill(IFile *ifile, vector &tmpvalues, vector ¢er, vector &sigma, double &height , bool &multivariate) +/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height +bool MetaD::scanOneHill(IFile *ifile, vector &tmpvalues, vector ¢er, vector &sigma, double &height, bool &multivariate) { double dummy; multivariate=false; - if(ifile->scanField("time",dummy)){ + if(ifile->scanField("time",dummy)) { unsigned ncv; ncv=tmpvalues.size(); - for(unsigned i=0;iscanField( &tmpvalues[i] ); - if( tmpvalues[i].isPeriodic() && ! getPntrToArgument(i)->isPeriodic() ){ + if( tmpvalues[i].isPeriodic() && ! getPntrToArgument(i)->isPeriodic() ) { error("in hills file periodicity for variable " + tmpvalues[i].getName() + " does not match periodicity in input"); - } else if( tmpvalues[i].isPeriodic() ){ + } else if( tmpvalues[i].isPeriodic() ) { std::string imin, imax; tmpvalues[i].getDomain( imin, imax ); std::string rmin, rmax; getPntrToArgument(i)->getDomain( rmin, rmax ); - if( imin!=rmin || imax!=rmax ){ + if( imin!=rmin || imax!=rmax ) { error("in hills file periodicity for variable " + tmpvalues[i].getName() + " does not match periodicity in input"); } } center[i]=tmpvalues[i].get(); } - // scan for multivariate label: record the actual file position so to eventually rewind + // scan for multivariate label: record the actual file position so to eventually rewind std::string sss; ifile->scanField("multivariate",sss); if(sss=="true") multivariate=true; else if(sss=="false") multivariate=false; else plumed_merror("cannot parse multivariate = "+ sss); - if(multivariate){ + if(multivariate) { sigma.resize(ncv*(ncv+1)/2); Matrix upper(ncv,ncv); Matrix lower(ncv,ncv); - for(unsigned i=0;iscanField("sigma_"+getPntrToArgument(j+i)->getName()+"_"+getPntrToArgument(j)->getName(),lower(j+i,j)); upper(j,j+i)=lower(j+i,j); } } - Matrix mymult(ncv,ncv); - Matrix invmatrix(ncv,ncv); - mult(lower,upper,mymult); + Matrix mymult(ncv,ncv); + Matrix invmatrix(ncv,ncv); + mult(lower,upper,mymult); // now invert and get the sigmas Invert(mymult,invmatrix); - // put the sigmas in the usual order: upper diagonal (this time in normal form and not in band form) + // put the sigmas in the usual order: upper diagonal (this time in normal form and not in band form) unsigned k=0; - for(unsigned i=0;iscanField("sigma_"+getPntrToArgument(i)->getName(),sigma[i]); } } - + ifile->scanField("height",height); ifile->scanField("biasf",dummy); if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy); @@ -1555,8 +1557,8 @@ bool MetaD::scanOneHill(IFile *ifile, vector &tmpvalues, vector if(ifile->FieldExist("upper_int")) ifile->scanField("upper_int",dummy); ifile->scanField(); return true; - } else { - return false; + } else { + return false; } } @@ -1564,36 +1566,36 @@ void MetaD::computeReweightingFactor() { if( !welltemp_ ) error("cannot compute the c(t) reweighting factors for non well-tempered metadynamics"); - if(biasf_==1.0){ + if(biasf_==1.0) { // in this case we have no bias, so reweight factor is 1.0 - getPntrToComponent("rct")->set(1.0); - return; + getPntrToComponent("rct")->set(1.0); + return; } // Recover the minimum values for the grid unsigned ncv=getNumberOfArguments(); unsigned ntotgrid=1; - std::vector dmin( ncv ),dmax( ncv ), grid_spacing( ncv ), vals( ncv ); - for(unsigned j=0;j dmin( ncv ),dmax( ncv ), grid_spacing( ncv ), vals( ncv ); + for(unsigned j=0; jgetMin()[j], dmin[j] ); Tools::convert( BiasGrid_->getMax()[j], dmax[j] ); grid_spacing[j] = ( dmax[j] - dmin[j] ) / static_cast( rewf_grid_[j] ); - if( !getPntrToArgument(j)->isPeriodic() ) dmax[j] += grid_spacing[j]; + if( !getPntrToArgument(j)->isPeriodic() ) dmax[j] += grid_spacing[j]; ntotgrid *= rewf_grid_[j]; } - + // Now sum over whole grid reweight_factor=0.0; double* der=new double[ncv]; std::vector t_index( ncv ); double sum1=0.0; double sum2=0.0; double afactor = biasf_ / (kbt_*(biasf_-1.0)); double afactor2 = 1.0 / (kbt_*(biasf_-1.0)); - unsigned rank=comm.Get_rank(), stride=comm.Get_size(); - for(unsigned i=rank;i=2 ) t_index[ncv-1]=((kk-t_index[ncv-1])/rewf_grid_[ncv-2]); - - for(unsigned j=0;j(getNumberOfArguments())&&!parameters.empty()) @@ -206,21 +206,21 @@ MCfirst_(-1) if(!arg2.empty()) { if(parameters.size()>0) error("It is not possible to use PARARG and PARAMETERS together"); if(arg2.size()!=getNumberOfArguments()) error("Size of PARARG array should be the same as number for arguments in ARG"); - for(unsigned i=0;iget()); + for(unsigned i=0; iget()); if(arg2[i]->hasDerivatives()==true) error("PARARG can only accept arguments without derivatives"); } } - if(parameters.size()!=getNumberOfArguments()) + if(parameters.size()!=getNumberOfArguments()) error("PARARG or PARAMETERS arrays should include the same number of elements as the arguments in ARG"); string stringa_noise; parse("NOISETYPE",stringa_noise); - if(stringa_noise=="GAUSS") noise_type_ = GAUSS; + if(stringa_noise=="GAUSS") noise_type_ = GAUSS; else if(stringa_noise=="MGAUSS") noise_type_ = MGAUSS; else if(stringa_noise=="OUTLIERS") noise_type_ = OUTLIERS; - else error("Unkwnow noise type"); + else error("Unkwnow noise type"); parseFlag("SCALEDATA", doscale_); if(doscale_) { @@ -243,7 +243,7 @@ MCfirst_(-1) sigma_.resize(getNumberOfArguments(),readsigma[0]); } else { error("SIGMA0 can accept either one single value or as many values as the number of arguments (with NOISETYPE=MGAUSS)"); - } + } } else sigma_.resize(1, readsigma[0]); parse("SIGMA_MIN",sigma_min_); @@ -279,15 +279,15 @@ MCfirst_(-1) MCstride_ *= getStride(); switch(noise_type_) { - case GAUSS: - log.printf(" with gaussian noise and a single noise parameter for all the data\n"); - break; - case MGAUSS: - log.printf(" with gaussian noise and a noise parameter for each data point\n"); - break; - case OUTLIERS: - log.printf(" with long tailed gaussian noise and a single noise parameter for all the data\n"); - break; + case GAUSS: + log.printf(" with gaussian noise and a single noise parameter for all the data\n"); + break; + case MGAUSS: + log.printf(" with gaussian noise and a noise parameter for each data point\n"); + break; + case OUTLIERS: + log.printf(" with long tailed gaussian noise and a single noise parameter for all the data\n"); + break; } if(doscale_) { @@ -301,7 +301,7 @@ MCfirst_(-1) if(readsigma.size()==1) log.printf(" initial data uncertainty %f\n",sigma_[0]); else { log.printf(" initial data uncertainties"); - for(unsigned i=0;i &sigma, const double scale){ +double Metainference::getEnergySPE(const vector &sigma, const double scale) { // calculate effective sigma const double smean2 = sigma_mean_*sigma_mean_; const double s = sqrt( sigma[0]*sigma[0] + smean2 ); // cycle on arguments double ene = 0.0; - for(unsigned i=0;i &sigma, const double sca return kbt_ * ene; } -double Metainference::getEnergyGJE(const vector &sigma, const double scale){ +double Metainference::getEnergyGJE(const vector &sigma, const double scale) { // cycle on arguments double ene = 0.0; const double smean2 = sigma_mean_*sigma_mean_; - double ss = sigma[0]*sigma[0] + smean2; - for(unsigned i=0;i &sigma, const double sca return kbt_ * ene; } -void Metainference::doMonteCarlo(){ +void Metainference::doMonteCarlo() { double old_energy; switch(noise_type_) { - case GAUSS: - case MGAUSS: - old_energy = getEnergyGJE(sigma_,scale_); - break; - case OUTLIERS: - old_energy = getEnergySPE(sigma_,scale_); - break; + case GAUSS: + case MGAUSS: + old_energy = getEnergyGJE(sigma_,scale_); + break; + case OUTLIERS: + old_energy = getEnergySPE(sigma_,scale_); + break; } - - // cycle on MC steps - for(unsigned i=0;i scale_max_){new_scale = 2.0 * scale_max_ - new_scale;} - if(new_scale < scale_min_){new_scale = 2.0 * scale_min_ - new_scale;} + if(new_scale > scale_max_) {new_scale = 2.0 * scale_max_ - new_scale;} + if(new_scale < scale_min_) {new_scale = 2.0 * scale_min_ - new_scale;} // the scaling factor should be the same for all the replicas if(comm.Get_rank()==0) multi_sim_comm.Bcast(new_scale,0); comm.Bcast(new_scale,0); } - + // propose move for sigma vector new_sigma(sigma_.size()); - for(unsigned j=0;j(rand()) / RAND_MAX; const double ds2 = -Dsigma_ + r2 * 2.0 * Dsigma_; new_sigma[j] = sigma_[j] + ds2; // check boundaries - if(new_sigma[j] > sigma_max_){new_sigma[j] = 2.0 * sigma_max_ - new_sigma[j];} - if(new_sigma[j] < sigma_min_){new_sigma[j] = 2.0 * sigma_min_ - new_sigma[j];} + if(new_sigma[j] > sigma_max_) {new_sigma[j] = 2.0 * sigma_max_ - new_sigma[j];} + if(new_sigma[j] < sigma_min_) {new_sigma[j] = 2.0 * sigma_min_ - new_sigma[j];} } - + // calculate new energy double new_energy=0; switch(noise_type_) { - case GAUSS: - case MGAUSS: - new_energy = getEnergyGJE(new_sigma,new_scale); - break; - case OUTLIERS: - new_energy = getEnergySPE(new_sigma,new_scale); - break; + case GAUSS: + case MGAUSS: + new_energy = getEnergyGJE(new_sigma,new_scale); + break; + case OUTLIERS: + new_energy = getEnergySPE(new_sigma,new_scale); + break; } // accept or reject const double delta = ( new_energy - old_energy ) / kbt_; // if delta is negative always accept move - if( delta <= 0.0 ){ + if( delta <= 0.0 ) { old_energy = new_energy; scale_ = new_scale; sigma_ = new_sigma; MCaccept_++; - // otherwise extract random number + // otherwise extract random number } else { const double s = static_cast(rand()) / RAND_MAX; - if( s < exp(-delta) ){ + if( s < exp(-delta) ) { old_energy = new_energy; scale_ = new_scale; sigma_ = new_sigma; MCaccept_++; } } - + if(doscale_) { // the scaling factor should be the same for all the replicas if(comm.Get_rank()==0) multi_sim_comm.Bcast(scale_,0); @@ -466,26 +466,26 @@ double Metainference::getEnergyForceSPE() double ene = 0.0; const unsigned narg=getNumberOfArguments(); - const double smean2 = sigma_mean_*sigma_mean_; + const double smean2 = sigma_mean_*sigma_mean_; const double s = sqrt( sigma_[0]*sigma_[0] + smean2 ); vector f(narg,0); - - if(comm.Get_rank()==0){ - for(unsigned i=0;i(ndata_)*std::log(sqrt2_div_pi*s); + + if(comm.Get_rank()==0) { + for(unsigned i=0; i(ndata_)*std::log(sqrt2_div_pi*s); } // intra-replica summation comm.Sum(&f[0],narg); @@ -504,19 +504,19 @@ double Metainference::getEnergyForceGJE() vector inv_s2(ssize, 0.); const double smean2 = sigma_mean_*sigma_mean_; - for(unsigned i=0;iset(accept); // calculate bias and forces - double ene = 0; + double ene = 0; switch(noise_type_) { - case GAUSS: - case MGAUSS: - ene = getEnergyForceGJE(); - break; - case OUTLIERS: - ene = getEnergyForceSPE(); - break; + case GAUSS: + case MGAUSS: + ene = getEnergyForceGJE(); + break; + case OUTLIERS: + ene = getEnergyForceSPE(); + break; } // set value of the bias setBias(kbt_*ene); diff --git a/src/bias/MovingRestraint.cpp b/src/bias/MovingRestraint.cpp index 02c08fb4e9..13cafce97e 100644 --- a/src/bias/MovingRestraint.cpp +++ b/src/bias/MovingRestraint.cpp @@ -26,8 +26,8 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS MOVINGRESTRAINT /* @@ -39,7 +39,7 @@ and Jarzynski sampling \cite jarzynski. The harmonic restraint on your system is given by: \f[ -V(\vec{s},t) = \frac{1}{2} \kappa(t) ( \vec{s} - \vec{s}_0(t) )^2 +V(\vec{s},t) = \frac{1}{2} \kappa(t) ( \vec{s} - \vec{s}_0(t) )^2 \f] The time dependence of \f$\kappa\f$ and \f$\vec{s}_0\f$ are specified by a list of @@ -47,7 +47,7 @@ STEP, KAPPA and AT keywords. These keywords tell plumed what values \f$\kappa\f should have at the time specified by the corresponding STEP keyword. Inbetween these times the values of \f$\kappa\f$ and \f$\vec{s}_0\f$ are linearly interpolated. -Additional material and examples can be also found in the tutorial \ref belfast-5 +Additional material and examples can be also found in the tutorial \ref belfast-5 \par Examples The following input is dragging the distance between atoms 2 and 4 @@ -71,7 +71,7 @@ static. DISTANCE ATOMS=1,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 MOVINGRESTRAINT ... - ARG=d1,d2 + ARG=d1,d2 STEP0=0 AT0=1.0,1.5 KAPPA0=0.0,0.0 STEP1=1000 AT1=1.0,1.5 KAPPA1=1.0,1.0 ... MOVINGRESTRAINT @@ -88,9 +88,9 @@ MOVINGRESTRAINT ... ... MOVINGRESTRAINT \endverbatim -By default the Action is issuing some values which are +By default the Action is issuing some values which are the work on each degree of freedom, the center of the harmonic potential, -the total bias deposited +the total bias deposited (See also \ref DISTANCE). @@ -100,7 +100,7 @@ the total bias deposited //+ENDPLUMEDOC -class MovingRestraint : public Bias{ +class MovingRestraint : public Bias { std::vector > at; std::vector > kappa; std::vector step; @@ -119,54 +119,54 @@ class MovingRestraint : public Bias{ PLUMED_REGISTER_ACTION(MovingRestraint,"MOVINGRESTRAINT") -void MovingRestraint::registerKeywords( Keywords& keys ){ +void MovingRestraint::registerKeywords( Keywords& keys ) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","VERSE","B","Tells plumed whether the restraint is only acting for CV larger (U) or smaller (L) than " - "the restraint or whether it is acting on both sides (B)"); + "the restraint or whether it is acting on both sides (B)"); keys.add("numbered","STEP","This keyword appears multiple times as STEPx with x=0,1,2,...,n. Each value given represents " - "the MD step at which the restraint parameters take the values KAPPAx and ATx."); + "the MD step at which the restraint parameters take the values KAPPAx and ATx."); keys.reset_style("STEP","compulsory"); keys.add("numbered","AT","ATx is equal to the position of the restraint at time STEPx. For intermediate times this parameter " - "is linearly interpolated. If no ATx is specified for STEPx then the values of AT are kept constant " - "during the interval of time between STEPx-1 and STEPx."); - keys.reset_style("AT","compulsory"); + "is linearly interpolated. If no ATx is specified for STEPx then the values of AT are kept constant " + "during the interval of time between STEPx-1 and STEPx."); + keys.reset_style("AT","compulsory"); keys.add("numbered","KAPPA","KAPPAx is equal to the value of the force constants at time STEPx. For intermediate times this " - "parameter is linearly interpolated. If no KAPPAx is specified for STEPx then the values of KAPPAx " - "are kept constant during the interval of time between STEPx-1 and STEPx."); + "parameter is linearly interpolated. If no KAPPAx is specified for STEPx then the values of KAPPAx " + "are kept constant during the interval of time between STEPx-1 and STEPx."); keys.reset_style("KAPPA","compulsory"); keys.addOutputComponent("work","default","the total work performed changing this restraint"); keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); keys.addOutputComponent("_cntr","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "these quantities will named with the arguments of the bias followed by " - "the character string _cntr. These quantities give the instantaneous position " - "of the center of the harmonic potential."); + "these quantities will named with the arguments of the bias followed by " + "the character string _cntr. These quantities give the instantaneous position " + "of the center of the harmonic potential."); keys.addOutputComponent("_work","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _work. These quantities tell the user how much work has " - "been done by the potential in dragging the system along the various colvar axis."); + "These quantities will named with the arguments of the bias followed by " + "the character string _work. These quantities tell the user how much work has " + "been done by the potential in dragging the system along the various colvar axis."); keys.addOutputComponent("_kappa","default","one or multiple instances of this quantity will be refereceable elsewhere in the input file. " - "These quantities will named with the arguments of the bias followed by " - "the character string _kappa. These quantities tell the user the time dependent value of kappa."); + "These quantities will named with the arguments of the bias followed by " + "the character string _kappa. These quantities tell the user the time dependent value of kappa."); } MovingRestraint::MovingRestraint(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -verse(getNumberOfArguments()) + PLUMED_BIAS_INIT(ao), + verse(getNumberOfArguments()) { parseVector("VERSE",verse); vector ss(1); ss[0]=-1; std::vector kk( getNumberOfArguments() ), aa( getNumberOfArguments() ); - for(int i=0;;i++){ - // Read in step + for(int i=0;; i++) { + // Read in step if( !parseNumberedVector("STEP",i,ss) ) break; - for(unsigned j=0;jgetName()+"_cntr"; // each spring has its own center - addComponent(comp); componentIsNotPeriodic(comp); - comp=getPntrToArgument(i)->getName()+"_work"; // each spring has its own work - addComponent(comp); componentIsNotPeriodic(comp); - comp=getPntrToArgument(i)->getName()+"_kappa"; // each spring has its own kappa - addComponent(comp); componentIsNotPeriodic(comp); - work.push_back(0.); // initialize the work value + for(unsigned i=0; i< getNumberOfArguments() ; i++) { + comp=getPntrToArgument(i)->getName()+"_cntr"; // each spring has its own center + addComponent(comp); componentIsNotPeriodic(comp); + comp=getPntrToArgument(i)->getName()+"_work"; // each spring has its own work + addComponent(comp); componentIsNotPeriodic(comp); + comp=getPntrToArgument(i)->getName()+"_kappa"; // each spring has its own kappa + addComponent(comp); componentIsNotPeriodic(comp); + work.push_back(0.); // initialize the work value } addComponent("work"); componentIsNotPeriodic("work"); tot_work=0.0; @@ -208,38 +208,38 @@ verse(getNumberOfArguments()) } -void MovingRestraint::calculate(){ +void MovingRestraint::calculate() { double ene=0.0; double totf2=0.0; unsigned narg=getNumberOfArguments(); long int now=getStep(); std::vector kk(narg),aa(narg),f(narg),dpotdk(narg); - if(now<=step[0]){ + if(now<=step[0]) { kk=kappa[0]; aa=at[0]; oldaa=at[0]; oldk=kappa[0]; - olddpotdk.resize(narg); + olddpotdk.resize(narg); oldf.resize(narg); - } else if(now>=step[step.size()-1]){ + } else if(now>=step[step.size()-1]) { kk=kappa[step.size()-1]; aa=at[step.size()-1]; } else { unsigned i=0; - for(i=1;igetName()+"_cntr")->set(aa[i]); + getPntrToComponent(getPntrToArgument(i)->getName()+"_cntr")->set(aa[i]); const double k=kk[i]; f[i]=-k*cv; if(verse[i]=="U" && cv<0) continue; @@ -247,8 +247,8 @@ void MovingRestraint::calculate(){ plumed_assert(verse[i]=="U" || verse[i]=="L" || verse[i]=="B"); dpotdk[i]=0.5*cv*cv; if(oldaa.size()==aa.size() && oldf.size()==f.size()) work[i]+=0.5*(oldf[i]+f[i])*(aa[i]-oldaa[i]) + 0.5*( dpotdk[i]+olddpotdk[i] )*(kk[i]-oldk[i]); - getPntrToComponent(getPntrToArgument(i)->getName()+"_work")->set(work[i]); - getPntrToComponent(getPntrToArgument(i)->getName()+"_kappa")->set(kk[i]); + getPntrToComponent(getPntrToArgument(i)->getName()+"_work")->set(work[i]); + getPntrToComponent(getPntrToArgument(i)->getName()+"_kappa")->set(kk[i]); tot_work+=work[i]; ene+=0.5*k*cv*cv; setOutputForce(i,f[i]); diff --git a/src/bias/PBMetaD.cpp b/src/bias/PBMetaD.cpp index a129ffb9c5..b50557f7d2 100644 --- a/src/bias/PBMetaD.cpp +++ b/src/bias/PBMetaD.cpp @@ -41,14 +41,14 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { -//+PLUMEDOC BIAS PBMETAD +//+PLUMEDOC BIAS PBMETAD /* Used to performed Parallel Bias MetaDynamics. -This action activate Parallel Bias MetaDynamics (PBMetaD) \cite pbmetad, a version of MetaDynamics \cite metad in which +This action activate Parallel Bias MetaDynamics (PBMetaD) \cite pbmetad, a version of MetaDynamics \cite metad in which multiple low-dimensional bias potentials are applied in parallel. In the current implementation, these have the form of mono-dimensional MetaDynamics bias potentials: @@ -72,7 +72,7 @@ at each deposition step the Gaussian heights are multiplied by the so-called con \f[ W_i(k \tau)=W_0 \frac{\exp\left( - \frac{V(s_i,k \tau)}{k_B T} -\right)}{\sum_{i=1}^N +\right)}{\sum_{i=1}^N \exp\left( - \frac{V(s_i,k \tau)}{k_B T} \right)} @@ -83,19 +83,19 @@ where \f$W_0\f$ is the initial Gaussian height. The PBMetaD bias potential is defined by: \f[ -V_{PB}(\vec{s},t) = -k_B T \log{\sum_{i=1}^N +V_{PB}(\vec{s},t) = -k_B T \log{\sum_{i=1}^N \exp\left( - \frac{V(s_i,t)}{k_B T} \right)}. \f] -Information on the Gaussian functions that build each bias potential are printed to -multiple HILLS files, which -are used both to restart the calculation and to reconstruct the mono-dimensional -free energies as a function of the corresponding CVs. +Information on the Gaussian functions that build each bias potential are printed to +multiple HILLS files, which +are used both to restart the calculation and to reconstruct the mono-dimensional +free energies as a function of the corresponding CVs. These can be reconstructed using the \ref sum_hills utility because the final bias is given -by: +by: \f[ V(s_i) = -F(s_i) @@ -113,7 +113,7 @@ and if Gaussian width is fixed PLUMED will use 1/5 of the Gaussian width as grid This default choice should be reasonable for most applications. Another option that is available is well-tempered metadynamics \cite Barducci:2008. In this -variant of PBMetaD the heights of the Gaussian hills are rescaled at each step by the +variant of PBMetaD the heights of the Gaussian hills are rescaled at each step by the additional well-tempered metadynamics term. This ensures that each bias converges more smoothly. It should be noted that, in the case of well-tempered metadynamics, in the output printed the Gaussian height is re-scaled using the bias factor. @@ -128,21 +128,21 @@ gaussian potential is denoted by one value only that is a Cartesian space (ADAPT (ADAPTIVE=DIFF). Note that a specific integration technique for the deposited gaussians should be used in this case. Check the documentation for utility sum_hills. -With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero -outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only +With the keyword INTERVAL one changes the metadynamics algorithm setting the bias force equal to zero +outside boundary \cite baftizadeh2012protein. If, for example, metadynamics is performed on a CV s and one is interested only to the free energy for s > sw, the history dependent potential is still updated according to the above -equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also -if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the -force on the system in the region s > sw comes from both metadynamics and the force field, in the region -s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that -fluctuates around a stable estimator, equal to the negative of the free energy far enough from the +equations but the metadynamics force is set to zero for s < sw. Notice that Gaussians are added also +if s < sw, as the tails of these Gaussians influence VG in the relevant region s > sw. In this way, the +force on the system in the region s > sw comes from both metadynamics and the force field, in the region +s < sw only from the latter. This approach allows obtaining a history-dependent bias potential VG that +fluctuates around a stable estimator, equal to the negative of the free energy far enough from the boundaries. Note that: - It works only for one-dimensional biases; - It works both with and without GRID; - The interval limit sw in a region where the free energy derivative is not large; -- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should +- If in the region outside the limit sw the system has a free energy minimum, the INTERVAL keyword should be used together with a \ref UPPER_WALLS or \ref LOWER_WALLS at sw. - + Multiple walkers \cite multiplewalkers can also be used. See below the examples. \par Examples @@ -160,26 +160,26 @@ PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \par If you use well-tempered metadynamics, you should specify a single biasfactor and initial -Gaussian height. +Gaussian height. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 PBMETAD ... -ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 -PACE=500 BIASFACTOR=8 LABEL=pb +ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 +PACE=500 BIASFACTOR=8 LABEL=pb FILE=HILLS_d1,HILLS_d2 ... PBMETAD PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \endverbatim -\par +\par The following input enables the MPI version of multiple-walkers. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 PBMETAD ... -ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 -PACE=500 BIASFACTOR=8 LABEL=pb +ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 +PACE=500 BIASFACTOR=8 LABEL=pb FILE=HILLS_d1,HILLS_d2 WALKERS_MPI ... PBMETAD @@ -187,17 +187,17 @@ PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \endverbatim \par -The disk version of multiple-walkers can be -enabled by setting the number of walker used, the id of the -current walker which interprets the input file, the directory where the +The disk version of multiple-walkers can be +enabled by setting the number of walker used, the id of the +current walker which interprets the input file, the directory where the hills containing files resides, and the frequency to read the other walkers. Here is an example \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 PBMETAD ... -ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 -PACE=500 BIASFACTOR=8 LABEL=pb +ARG=d1,d2 SIGMA=0.2,0.2 HEIGHT=0.3 +PACE=500 BIASFACTOR=8 LABEL=pb FILE=HILLS_d1,HILLS_d2 WALKERS_N=10 WALKERS_ID=3 @@ -206,28 +206,28 @@ WALKERS_RSTRIDE=100 ... PBMETAD PRINT ARG=d1,d2,pb.bias STRIDE=100 FILE=COLVAR \endverbatim -where WALKERS_N is the total number of walkers, WALKERS_ID is the -id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory -where all the walkers are located. WALKERS_RSTRIDE is the number of step between -one update and the other. +where WALKERS_N is the total number of walkers, WALKERS_ID is the +id of the present walker (starting from 0 ) and the WALKERS_DIR is the directory +where all the walkers are located. WALKERS_RSTRIDE is the number of step between +one update and the other. */ //+ENDPLUMEDOC -class PBMetaD : public Bias{ +class PBMetaD : public Bias { private: struct Gaussian { - vector center; - vector sigma; - double height; - bool multivariate; // this is required to discriminate the one dimensional case - vector invsigma; - Gaussian(const vector & center,const vector & sigma, double height, bool multivariate): - center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma){ - // to avoid troubles from zero element in flexible hills - for(unsigned i=0;i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; - } + vector center; + vector sigma; + double height; + bool multivariate; // this is required to discriminate the one dimensional case + vector invsigma; + Gaussian(const vector & center,const vector & sigma, double height, bool multivariate): + center(center),sigma(sigma),height(height),multivariate(multivariate),invsigma(sigma) { + // to avoid troubles from zero element in flexible hills + for(unsigned i=0; i1.e-20?invsigma[i]=1.0/invsigma[i]:0.; + } }; vector sigma0_; vector sigma0min_; @@ -276,12 +276,12 @@ class PBMetaD : public Bias{ void calculate(); void update(); static void registerKeywords(Keywords& keys); - bool checkNeedsGradients()const{if(adaptive_==FlexibleBin::geometry){return true;}else{return false;}} + bool checkNeedsGradients()const {if(adaptive_==FlexibleBin::geometry) {return true;} else {return false;}} }; PLUMED_REGISTER_ACTION(PBMetaD,"PBMETAD") -void PBMetaD::registerKeywords(Keywords& keys){ +void PBMetaD::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","SIGMA","the widths of the Gaussian hills"); @@ -316,102 +316,102 @@ void PBMetaD::registerKeywords(Keywords& keys){ keys.use("UPDATE_UNTIL"); } -PBMetaD::~PBMetaD(){ +PBMetaD::~PBMetaD() { for(unsigned i=0; iclose(); - delete hillsOfiles_[i]; + for(unsigned i=0; iclose(); + delete hillsOfiles_[i]; } if(wgridstride_ > 0) { - for(unsigned i=0; iclose(); - delete gridfiles_[i]; - } + for(unsigned i=0; iclose(); + delete gridfiles_[i]; + } } // close files - for(unsigned i=0;iisOpen()) ifiles[i]->close(); - delete ifiles[i]; + for(unsigned i=0; iisOpen()) ifiles[i]->close(); + delete ifiles[i]; } } PBMetaD::PBMetaD(const ActionOptions& ao): -PLUMED_BIAS_INIT(ao), -grid_(false), height0_(std::numeric_limits::max()), -biasf_(1.0), kbt_(0.0), stride_(0), wgridstride_(0), welltemp_(false), -mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), -walkers_mpi(false), mpi_nw_(0), -adaptive_(FlexibleBin::none), -isFirstStep(true) + PLUMED_BIAS_INIT(ao), + grid_(false), height0_(std::numeric_limits::max()), + biasf_(1.0), kbt_(0.0), stride_(0), wgridstride_(0), welltemp_(false), + mw_n_(1), mw_dir_(""), mw_id_(0), mw_rstride_(1), + walkers_mpi(false), mpi_nw_(0), + adaptive_(FlexibleBin::none), + isFirstStep(true) { // parse the flexible hills string adaptiveoption; adaptiveoption="NONE"; parse("ADAPTIVE",adaptiveoption); - if(adaptiveoption=="GEOM"){ + if(adaptiveoption=="GEOM") { log.printf(" Uses Geometry-based hills width: sigma must be in distance units and only one sigma is needed\n"); - adaptive_=FlexibleBin::geometry; - } else if(adaptiveoption=="DIFF"){ + adaptive_=FlexibleBin::geometry; + } else if(adaptiveoption=="DIFF") { log.printf(" Uses Diffusion-based hills width: sigma must be in timesteps and only one sigma is needed\n"); - adaptive_=FlexibleBin::diffusion; - } else if(adaptiveoption=="NONE"){ - adaptive_=FlexibleBin::none; + adaptive_=FlexibleBin::diffusion; + } else if(adaptiveoption=="NONE") { + adaptive_=FlexibleBin::none; } else { - error("I do not know this type of adaptive scheme"); + error("I do not know this type of adaptive scheme"); } parse("FMT",fmt); // parse the sigma parseVector("SIGMA",sigma0_); - if(adaptive_==FlexibleBin::none){ - // if you use normal sigma you need one sigma per argument + if(adaptive_==FlexibleBin::none) { + // if you use normal sigma you need one sigma per argument if( sigma0_.size()!=getNumberOfArguments() ) error("number of arguments does not match number of SIGMA parameters"); } else { - // if you use flexible hills you need one sigma - if(sigma0_.size()!=1){ + // if you use flexible hills you need one sigma + if(sigma0_.size()!=1) { error("If you choose ADAPTIVE you need only one sigma according to your choice of type (GEOM/DIFF)"); - } + } // if adaptive then the number must be an integer - if(adaptive_==FlexibleBin::diffusion){ - if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ){ - error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); - } - } + if(adaptive_==FlexibleBin::diffusion) { + if(int(sigma0_[0])-sigma0_[0]>1.e-9 || int(sigma0_[0])-sigma0_[0] <-1.e-9 || int(sigma0_[0])<1 ) { + error("In case of adaptive hills with diffusion, the sigma must be an integer which is the number of timesteps\n"); + } + } // here evtl parse the sigma min and max values parseVector("SIGMA_MIN",sigma0min_); if(sigma0min_.size()>0 && sigma0min_.size()!=getNumberOfArguments()) { error("the number of SIGMA_MIN values be the same of the number of the arguments"); - } else if(sigma0min_.size()==0) { + } else if(sigma0min_.size()==0) { sigma0min_.resize(getNumberOfArguments()); - for(unsigned i=0;i0 && sigma0max_.size()!=getNumberOfArguments()) { - error("the number of SIGMA_MAX values be the same of the number of the arguments"); - } else if(sigma0max_.size()==0) { + error("the number of SIGMA_MAX values be the same of the number of the arguments"); + } else if(sigma0max_.size()==0) { sigma0max_.resize(getNumberOfArguments()); - for(unsigned i=0;i tmp_smin, tmp_smax; tmp_smin.resize(1,sigma0min_[i]); tmp_smax.resize(1,sigma0max_[i]); flexbin.push_back(FlexibleBin(adaptive_,this,i,sigma0_[0],tmp_smin,tmp_smax)); } } - + // note: HEIGHT is not compulsory, since one could use the TAU keyword, see below parse("HEIGHT",height0_); parse("PACE",stride_); if(stride_<=0) error("frequency for hill addition is nonsensical"); - + parseVector("FILE",hillsfname); if(hillsfname.size()==0) { - for(unsigned i=0;igetName()); - } + for(unsigned i=0; igetName()); + } if( hillsfname.size()!=getNumberOfArguments() ) { error("number of FILE arguments does not match number of HILLS files"); } @@ -422,13 +422,13 @@ isFirstStep(true) parse("TEMP",temp); if(temp>0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; else kbt_=plumed.getAtoms().getKbT(); - if(biasf_>1.0){ + if(biasf_>1.0) { if(kbt_==0.0) error("Unless the MD engine passes the temperature to plumed, with well-tempered metad you must specify it using TEMP"); welltemp_=true; } double tau=0.0; parse("TAU",tau); - if(tau==0.0){ + if(tau==0.0) { if(height0_==std::numeric_limits::max()) error("At least one between HEIGHT and TAU should be specified"); // if tau is not set, we compute it here from the other input parameters if(welltemp_) tau=(kbt_*(biasf_-1.0))/height0_*getTimeStep()*stride_; @@ -437,7 +437,7 @@ isFirstStep(true) if(height0_!=std::numeric_limits::max()) error("At most one between HEIGHT and TAU should be specified"); height0_=(kbt_*(biasf_-1.0))/tau*getTimeStep()*stride_; } - + // Multiple walkers parse("WALKERS_N",mw_n_); parse("WALKERS_ID",mw_id_); @@ -456,15 +456,15 @@ isFirstStep(true) error("frequency with which to output grid not specified use GRID_WSTRIDE"); } if(gridfilenames_.size()==0 && wgridstride_ > 0) { - for(unsigned i=0;igetName()); - } - if(gridfilenames_.size() > 0 && hillsfname.size() > 0 && gridfilenames_.size() != hillsfname.size()) + for(unsigned i=0; igetName()); + } + if(gridfilenames_.size() > 0 && hillsfname.size() > 0 && gridfilenames_.size() != hillsfname.size()) error("number of GRID_WFILES arguments does not match number of HILLS files"); // Read grid vector gridreadfilenames_; parseVector("GRID_RFILES",gridreadfilenames_); - + // Grid Stuff vector gmin(getNumberOfArguments()); parseVector("GRID_MIN",gmin); @@ -481,45 +481,45 @@ isFirstStep(true) if(gmin.size()!=gmax.size()) error("GRID_MAX and GRID_MIN should be either present or absent"); if(gspacing.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); if(gbin.size()!=0 && gmin.size()==0) error("If GRID_SPACING is present also GRID_MIN should be present"); - if(gmin.size()!=0){ - if(gbin.size()==0 && gspacing.size()==0){ - if(adaptive_==FlexibleBin::none){ + if(gmin.size()!=0) { + if(gbin.size()==0 && gspacing.size()==0) { + if(adaptive_==FlexibleBin::none) { log<<" Binsize not specified, 1/10 of sigma will be be used\n"; plumed_assert(sigma0_.size()==getNumberOfArguments()); gspacing.resize(getNumberOfArguments()); - for(unsigned i=0;i0){grid_=true;} + if(gbin.size()>0) {grid_=true;} if(!grid_&&gridfilenames_.size() > 0) error("To write a grid you need first to define it!"); if(!grid_&&gridreadfilenames_.size() > 0) error("To read a grid you need first to define it!"); - doInt_.resize(getNumberOfArguments(),false); + doInt_.resize(getNumberOfArguments(),false); // Interval keyword parseVector("INTERVAL_MIN",lowI_); parseVector("INTERVAL_MAX",uppI_); @@ -531,26 +531,26 @@ isFirstStep(true) if(getPntrToArgument(i)->isPeriodic()) warning("INTERVAL is not used for periodic variables"); else doInt_[i]=true; } - + checkRead(); log.printf(" Gaussian width "); if (adaptive_==FlexibleBin::diffusion)log.printf(" (Note: The units of sigma are in timesteps) "); if (adaptive_==FlexibleBin::geometry)log.printf(" (Note: The units of sigma are in dist units) "); - for(unsigned i=0;i1){ + if(mw_n_>1) { if(walkers_mpi) error("MPI version of multiple walkers is not compatible with filesystem version of multiple walkers"); log.printf(" %d multiple walkers active\n",mw_n_); log.printf(" walker id %d\n",mw_id_); @@ -558,9 +558,9 @@ isFirstStep(true) if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); } else { if(walkers_mpi) { - log.printf(" Multiple walkers active using MPI communnication\n"); + log.printf(" Multiple walkers active using MPI communnication\n"); if(mw_dir_!="")log.printf(" directory with hills files %s\n",mw_dir_.c_str()); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { // Only root of group can communicate with other walkers mpi_nw_ = multi_sim_comm.Get_size(); mpi_id_ = multi_sim_comm.Get_rank(); @@ -572,31 +572,31 @@ isFirstStep(true) } } - for(unsigned i=0; i0) { - for(unsigned i=0; i0) { + for(unsigned i=0; i0) { - for(unsigned i=0; i0) { + for(unsigned i=0; i0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; - } else { - if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; - } - } - std::string funcl=getLabel() + ".bias"; - for(unsigned i=0; i args(1); - args[0] = getPntrToArgument(i); - vector gmin_t(1); - vector gmax_t(1); - vector gbin_t(1); - gmin_t[0] = gmin[i]; - gmax_t[0] = gmax[i]; - gbin_t[0] = gbin[i]; - Grid* BiasGrid_; - // Read grid from file - if(gridreadfilenames_.size()>0) { - IFile gridfile; - gridfile.link(*this); - if(gridfile.FileExist(gridreadfilenames_[i])){ - gridfile.open(gridreadfilenames_[i]); - } else { - error("The GRID file you want to read: " + gridreadfilenames_[i] + ", cannot be found!"); - } - string funcl = getLabel() + ".bias"; - BiasGrid_ = Grid::create(funcl, args, gridfile, gmin_t, gmax_t, gbin_t, sparsegrid, spline, true); - gridfile.close(); - if(BiasGrid_->getDimension() != args.size()) { - error("mismatch between dimensionality of input grid and number of arguments"); - } - if(getPntrToArgument(i)->isPeriodic() != BiasGrid_->getIsPeriodic()[0]) { - error("periodicity mismatch between arguments and input bias"); - } - log.printf(" Restarting from %s:",gridreadfilenames_[i].c_str()); - if(getRestart()) restartedFromGrid=true; - } else { - if(!sparsegrid){BiasGrid_=new Grid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} - else {BiasGrid_=new SparseGrid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} - std::vector actualmin=BiasGrid_->getMin(); - std::vector actualmax=BiasGrid_->getMax(); - if(gmin_t[0]!=actualmin[0]) log<<" WARNING: GRID_MIN["<0.5*sigma0_[i]) log<<" WARNING: Using a METAD with a Grid Spacing larger than half of the Gaussians width can produce artifacts\n"; + } else { + if(mesh>0.5*sigma0min_[i]||sigma0min_[i]<0.) log<<" WARNING: to use a METAD with a GRID and ADAPTIVE you need to set a Grid Spacing larger than half of the Gaussians \n"; + } + } + std::string funcl=getLabel() + ".bias"; + for(unsigned i=0; i args(1); + args[0] = getPntrToArgument(i); + vector gmin_t(1); + vector gmax_t(1); + vector gbin_t(1); + gmin_t[0] = gmin[i]; + gmax_t[0] = gmax[i]; + gbin_t[0] = gbin[i]; + Grid* BiasGrid_; + // Read grid from file + if(gridreadfilenames_.size()>0) { + IFile gridfile; + gridfile.link(*this); + if(gridfile.FileExist(gridreadfilenames_[i])) { + gridfile.open(gridreadfilenames_[i]); + } else { + error("The GRID file you want to read: " + gridreadfilenames_[i] + ", cannot be found!"); + } + string funcl = getLabel() + ".bias"; + BiasGrid_ = Grid::create(funcl, args, gridfile, gmin_t, gmax_t, gbin_t, sparsegrid, spline, true); + gridfile.close(); + if(BiasGrid_->getDimension() != args.size()) { + error("mismatch between dimensionality of input grid and number of arguments"); + } + if(getPntrToArgument(i)->isPeriodic() != BiasGrid_->getIsPeriodic()[0]) { + error("periodicity mismatch between arguments and input bias"); + } + log.printf(" Restarting from %s:",gridreadfilenames_[i].c_str()); + if(getRestart()) restartedFromGrid=true; + } else { + if(!sparsegrid) {BiasGrid_=new Grid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} + else {BiasGrid_=new SparseGrid(funcl,args,gmin_t,gmax_t,gbin_t,spline,true);} + std::vector actualmin=BiasGrid_->getMin(); + std::vector actualmax=BiasGrid_->getMax(); + if(gmin_t[0]!=actualmin[0]) log<<" WARNING: GRID_MIN["<link(*this); ifiles.push_back(ifile); ifilesnames.push_back(fname); - if(ifile->FileExist(fname)){ + if(ifile->FileExist(fname)) { ifile->open(fname); - if(getRestart()&&!restartedFromGrid){ + if(getRestart()&&!restartedFromGrid) { log.printf(" Restarting from %s:",ifilesnames[k].c_str()); readGaussians(i,ifiles[k]); } @@ -707,106 +707,108 @@ isFirstStep(true) if(comm.Get_rank()==0 && walkers_mpi) multi_sim_comm.Barrier(); // open hills files for writing - for(unsigned i=0;ilink(*this); - // if MPI multiple walkers, only rank 0 will write to file - if(walkers_mpi){ - int r=0; - if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); - comm.Bcast(r,0); - if(r>0) ifilesnames[mw_id_*hillsfname.size()+i]="/dev/null"; - ofile->enforceSuffix(""); - } - if(mw_n_>1) ofile->enforceSuffix(""); - ofile->open(ifilesnames[mw_id_*hillsfname.size()+i]); - if(fmt.length()>0) ofile->fmtField(fmt); - ofile->addConstantField("multivariate"); - if(doInt_[i]) { - ofile->addConstantField("lower_int").printField("lower_int",lowI_[i]); - ofile->addConstantField("upper_int").printField("upper_int",uppI_[i]); - } - ofile->setHeavyFlush(); - // output periodicities of variables - ofile->setupPrintValue( getPntrToArgument(i) ); - // push back - hillsOfiles_.push_back(ofile); - } - - // Dump grid to files - if(wgridstride_ > 0) { - for(unsigned i = 0; i < gridfilenames_.size(); ++i) { + for(unsigned i=0; ilink(*this); - string gridfname_tmp = gridfilenames_[i]; + // if MPI multiple walkers, only rank 0 will write to file if(walkers_mpi) { - int r = 0; - if(comm.Get_rank() == 0) { - r = multi_sim_comm.Get_rank(); - } - comm.Bcast(r, 0); - if(r>0) { - gridfname_tmp = "/dev/null"; - } - ofile->enforceSuffix(""); + int r=0; + if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); + comm.Bcast(r,0); + if(r>0) ifilesnames[mw_id_*hillsfname.size()+i]="/dev/null"; + ofile->enforceSuffix(""); } if(mw_n_>1) ofile->enforceSuffix(""); - ofile->open(gridfname_tmp); + ofile->open(ifilesnames[mw_id_*hillsfname.size()+i]); + if(fmt.length()>0) ofile->fmtField(fmt); + ofile->addConstantField("multivariate"); + if(doInt_[i]) { + ofile->addConstantField("lower_int").printField("lower_int",lowI_[i]); + ofile->addConstantField("upper_int").printField("upper_int",uppI_[i]); + } ofile->setHeavyFlush(); - gridfiles_.push_back(ofile); - } + // output periodicities of variables + ofile->setupPrintValue( getPntrToArgument(i) ); + // push back + hillsOfiles_.push_back(ofile); + } + + // Dump grid to files + if(wgridstride_ > 0) { + for(unsigned i = 0; i < gridfilenames_.size(); ++i) { + OFile *ofile = new OFile(); + ofile->link(*this); + string gridfname_tmp = gridfilenames_[i]; + if(walkers_mpi) { + int r = 0; + if(comm.Get_rank() == 0) { + r = multi_sim_comm.Get_rank(); + } + comm.Bcast(r, 0); + if(r>0) { + gridfname_tmp = "/dev/null"; + } + ofile->enforceSuffix(""); + } + if(mw_n_>1) ofile->enforceSuffix(""); + ofile->open(gridfname_tmp); + ofile->setHeavyFlush(); + gridfiles_.push_back(ofile); + } } log<<" Bibliography "<1||walkers_mpi) log< center(1); - vector sigma(1); - double height; - int nhills=0; - bool multivariate=false; - - std::vector tmpvalues; - tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); - - while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)){; - nhills++; - if(welltemp_){height*=(biasf_-1.0)/biasf_;} - addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); - } - log.printf(" %d Gaussians read\n",nhills); + vector center(1); + vector sigma(1); + double height; + int nhills=0; + bool multivariate=false; + + std::vector tmpvalues; + tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); + + while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)) { + ; + nhills++; + if(welltemp_) {height*=(biasf_-1.0)/biasf_;} + addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); + } + log.printf(" %d Gaussians read\n",nhills); } bool PBMetaD::readChunkOfGaussians(unsigned iarg, IFile *ifile, unsigned n) { - vector center(1); - vector sigma(1); - double height; - unsigned nhills=0; - bool multivariate=false; - std::vector tmpvalues; - tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); - - while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)){; - if(welltemp_){height*=(biasf_-1.0)/biasf_;} - addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); - if(nhills==n){ + vector center(1); + vector sigma(1); + double height; + unsigned nhills=0; + bool multivariate=false; + std::vector tmpvalues; + tmpvalues.push_back( Value( this, getPntrToArgument(iarg)->getName(), false ) ); + + while(scanOneHill(iarg,ifile,tmpvalues,center,sigma,height,multivariate)) { + ; + if(welltemp_) {height*=(biasf_-1.0)/biasf_;} + addGaussian(iarg, Gaussian(center,sigma,height,multivariate)); + if(nhills==n) { log.printf(" %u Gaussians read\n",nhills); return true; + } + nhills++; } - nhills++; - } - log.printf(" %u Gaussians read\n",nhills); - return false; + log.printf(" %u Gaussians read\n",nhills); + return false; } void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile) @@ -814,17 +816,17 @@ void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile) ofile->printField("time",getTimeStep()*getStep()); ofile->printField(getPntrToArgument(iarg),hill.center[0]); - if(hill.multivariate){ + if(hill.multivariate) { ofile->printField("multivariate","true"); double lower = sqrt(1./hill.sigma[0]); ofile->printField("sigma_"+getPntrToArgument(iarg)->getName()+"_"+ - getPntrToArgument(iarg)->getName(),lower); + getPntrToArgument(iarg)->getName(),lower); } else { ofile->printField("multivariate","false"); ofile->printField("sigma_"+getPntrToArgument(iarg)->getName(),hill.sigma[0]); } double height=hill.height; - if(welltemp_) height *= biasf_/(biasf_-1.0); + if(welltemp_) height *= biasf_/(biasf_-1.0); ofile->printField("height",height); ofile->printField("biasf",biasf_); if(mw_n_>1) ofile->printField("clock",int(std::time(0))); @@ -833,128 +835,128 @@ void PBMetaD::writeGaussian(unsigned iarg, const Gaussian& hill, OFile *ofile) void PBMetaD::addGaussian(unsigned iarg, const Gaussian& hill) { - if(!grid_){hills_[iarg].push_back(hill);} - else{ - vector nneighb=getGaussianSupport(iarg, hill); - vector neighbors=BiasGrids_[iarg]->getNeighbors(hill.center,nneighb); - vector der(1); - vector xx(1); - if(comm.Get_size()==1){ - for(unsigned i=0;igetPoint(ineigh,xx); - double bias=evaluateGaussian(iarg,xx,hill,&der[0]); - BiasGrids_[iarg]->addValueAndDerivatives(ineigh,bias,der); - } - } else { - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - vector allder(neighbors.size(),0.0); - vector allbias(neighbors.size(),0.0); - for(unsigned i=rank;igetPoint(ineigh,xx); - allbias[i]=evaluateGaussian(iarg,xx,hill,&allder[i]); - } - comm.Sum(allbias); - comm.Sum(allder); - for(unsigned i=0;iaddValueAndDerivatives(ineigh,allbias[i],der); + if(!grid_) {hills_[iarg].push_back(hill);} + else { + vector nneighb=getGaussianSupport(iarg, hill); + vector neighbors=BiasGrids_[iarg]->getNeighbors(hill.center,nneighb); + vector der(1); + vector xx(1); + if(comm.Get_size()==1) { + for(unsigned i=0; igetPoint(ineigh,xx); + double bias=evaluateGaussian(iarg,xx,hill,&der[0]); + BiasGrids_[iarg]->addValueAndDerivatives(ineigh,bias,der); + } + } else { + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + vector allder(neighbors.size(),0.0); + vector allbias(neighbors.size(),0.0); + for(unsigned i=rank; igetPoint(ineigh,xx); + allbias[i]=evaluateGaussian(iarg,xx,hill,&allder[i]); + } + comm.Sum(allbias); + comm.Sum(allder); + for(unsigned i=0; iaddValueAndDerivatives(ineigh,allbias[i],der); + } } } - } } vector PBMetaD::getGaussianSupport(unsigned iarg, const Gaussian& hill) { - vector nneigh; - double cutoff; - if(hill.multivariate){ - double maxautoval=1./hill.sigma[0]; - cutoff=sqrt(2.0*DP2CUTOFF*maxautoval); - } else { - cutoff=sqrt(2.0*DP2CUTOFF)*hill.sigma[0]; - } - - if(doInt_[iarg]){ - if(hill.center[0]+cutoff > uppI_[iarg] || hill.center[0]-cutoff < lowI_[iarg]) { - // in this case, we updated the entire grid to avoid problems - return BiasGrids_[iarg]->getNbin(); - } else { - nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0]))); - return nneigh; - } - } - - nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0])) ); - - return nneigh; + vector nneigh; + double cutoff; + if(hill.multivariate) { + double maxautoval=1./hill.sigma[0]; + cutoff=sqrt(2.0*DP2CUTOFF*maxautoval); + } else { + cutoff=sqrt(2.0*DP2CUTOFF)*hill.sigma[0]; + } + + if(doInt_[iarg]) { + if(hill.center[0]+cutoff > uppI_[iarg] || hill.center[0]-cutoff < lowI_[iarg]) { + // in this case, we updated the entire grid to avoid problems + return BiasGrids_[iarg]->getNbin(); + } else { + nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0]))); + return nneigh; + } + } + + nneigh.push_back( static_cast(ceil(cutoff/BiasGrids_[iarg]->getDx()[0])) ); + + return nneigh; } double PBMetaD::getBiasAndDerivatives(unsigned iarg, const vector& cv, double* der) { - double bias=0.0; - if(!grid_){ - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - for(unsigned i=rank;i vder(1); - bias = BiasGrids_[iarg]->getValueAndDerivatives(cv,vder); - der[0] = vder[0]; - }else{ - bias = BiasGrids_[iarg]->getValue(cv); - } - } - - return bias; + double bias=0.0; + if(!grid_) { + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + for(unsigned i=rank; i vder(1); + bias = BiasGrids_[iarg]->getValueAndDerivatives(cv,vder); + der[0] = vder[0]; + } else { + bias = BiasGrids_[iarg]->getValue(cv); + } + } + + return bias; } double PBMetaD::evaluateGaussian(unsigned iarg, const vector& cv, const Gaussian& hill, double* der) { - double bias=0.0; - // I use a pointer here because cv is const (and should be const) - // but when using doInt it is easier to locally replace cv[0] with - // the upper/lower limit in case it is out of range - const double *pcv=NULL; - double tmpcv[1]; // tmp array with cv (to be used with doInt_) - tmpcv[0]=cv[0]; - bool isOutOfInt = false; - if(doInt_[iarg]){ - if(cv[0]uppI_[iarg]) { tmpcv[0]=uppI_[iarg]; isOutOfInt = true; } - } - pcv=&(tmpcv[0]); - - if(hill.multivariate){ - double dp = difference(iarg, hill.center[0], pcv[0]); - double dp2 = 0.5 * dp * dp * hill.sigma[0]; - if(dp2uppI_[iarg]) { tmpcv[0]=uppI_[iarg]; isOutOfInt = true; } + } + pcv=&(tmpcv[0]); + + if(hill.multivariate) { + double dp = difference(iarg, hill.center[0], pcv[0]); + double dp2 = 0.5 * dp * dp * hill.sigma[0]; + if(dp2 cv(getNumberOfArguments()); - vector bias(getNumberOfArguments()); - vector thissigma(getNumberOfArguments()); - vector height(getNumberOfArguments()); - vector cv_tmp(1); - vector sigma_tmp(1); - double norm = 0.0; - double bmin = 1.0e+19; - for(unsigned i=0; i all_cv(mpi_nw_*cv.size(), 0.0); - std::vector all_sigma(mpi_nw_*getNumberOfArguments(), 0.0); - std::vector all_height(mpi_nw_*height.size(), 0.0); - if(comm.Get_rank()==0){ - // fill in value - for(unsigned i=0; i cv(getNumberOfArguments()); + vector bias(getNumberOfArguments()); + vector thissigma(getNumberOfArguments()); + vector height(getNumberOfArguments()); + vector cv_tmp(1); + vector sigma_tmp(1); + double norm = 0.0; + double bmin = 1.0e+19; + for(unsigned i=0; i all_cv(mpi_nw_*cv.size(), 0.0); + std::vector all_sigma(mpi_nw_*getNumberOfArguments(), 0.0); + std::vector all_height(mpi_nw_*height.size(), 0.0); + if(comm.Get_rank()==0) { + // fill in value + for(unsigned i=0; i0 && (getStep()%wgridstride_==0 || getCPT())) { - int r = 0; - if(walkers_mpi) { - if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); - comm.Bcast(r,0); - } - if(r==0) { - for(unsigned i=0; irewind(); - BiasGrids_[i]->writeToFile(*gridfiles_[i]); - gridfiles_[i]->flush(); - } - } - } + // write grid files + if(wgridstride_>0 && (getStep()%wgridstride_==0 || getCPT())) { + int r = 0; + if(walkers_mpi) { + if(comm.Get_rank()==0) r=multi_sim_comm.Get_rank(); + comm.Bcast(r,0); + } + if(r==0) { + for(unsigned i=0; irewind(); + BiasGrids_[i]->writeToFile(*gridfiles_[i]); + gridfiles_[i]->flush(); + } + } + } // if multiple walkers and time to read Gaussians - if(mw_n_>1 && getStep()%mw_rstride_==0){ - for(int j=0;j1 && getStep()%mw_rstride_==0) { + for(int j=0; jisOpen())){ + // if the file is not open yet + if(!(ifiles[k]->isOpen())) { // check if it exists now and open it! if(ifiles[k]->FileExist(ifilesnames[k])) { ifiles[k]->open(ifilesnames[k]); ifiles[k]->reset(false); } - // otherwise read the new Gaussians + // otherwise read the new Gaussians } else { log.printf(" Reading hills from %s:",ifilesnames[k].c_str()); readGaussians(i,ifiles[k]); @@ -1131,21 +1133,21 @@ void PBMetaD::update() } -/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height +/// takes a pointer to the file and a template string with values v and gives back the next center, sigma and height bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector &tmpvalues, vector ¢er, vector &sigma, double &height, bool &multivariate) { double dummy; multivariate=false; - if(ifile->scanField("time",dummy)){ + if(ifile->scanField("time",dummy)) { ifile->scanField( &tmpvalues[0] ); - if( tmpvalues[0].isPeriodic() && ! getPntrToArgument(iarg)->isPeriodic() ){ - error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); - } else if( tmpvalues[0].isPeriodic() ){ - std::string imin, imax; tmpvalues[0].getDomain( imin, imax ); - std::string rmin, rmax; getPntrToArgument(iarg)->getDomain( rmin, rmax ); - if( imin!=rmin || imax!=rmax ){ - error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); - } + if( tmpvalues[0].isPeriodic() && ! getPntrToArgument(iarg)->isPeriodic() ) { + error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); + } else if( tmpvalues[0].isPeriodic() ) { + std::string imin, imax; tmpvalues[0].getDomain( imin, imax ); + std::string rmin, rmax; getPntrToArgument(iarg)->getDomain( rmin, rmax ); + if( imin!=rmin || imax!=rmax ) { + error("in hills file periodicity for variable " + tmpvalues[0].getName() + " does not match periodicity in input"); + } } center[0]=tmpvalues[0].get(); std::string sss; @@ -1154,9 +1156,9 @@ bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector &tmpvalues, else if(sss=="false") multivariate=false; else plumed_merror("cannot parse multivariate = "+ sss); - if(multivariate){ + if(multivariate) { ifile->scanField("sigma_"+getPntrToArgument(iarg)->getName()+"_"+ - getPntrToArgument(iarg)->getName(),sigma[0]); + getPntrToArgument(iarg)->getName(),sigma[0]); sigma[0] = 1./(sigma[0]*sigma[0]); } else { ifile->scanField("sigma_"+getPntrToArgument(iarg)->getName(),sigma[0]); @@ -1168,9 +1170,9 @@ bool PBMetaD::scanOneHill(unsigned iarg, IFile *ifile, vector &tmpvalues, if(ifile->FieldExist("upper_int")) ifile->scanField("upper_int",dummy); ifile->scanField(); return true; - } else { - return false; - } + } else { + return false; + } } } diff --git a/src/bias/Restraint.cpp b/src/bias/Restraint.cpp index fc36068209..8bb3df2027 100644 --- a/src/bias/Restraint.cpp +++ b/src/bias/Restraint.cpp @@ -26,16 +26,16 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS RESTRAINT /* -Adds harmonic and/or linear restraints on one or more variables. +Adds harmonic and/or linear restraints on one or more variables. Either or both of SLOPE and KAPPA must be present to specify the linear and harmonic force constants -respectively. The resulting potential is given by: +respectively. The resulting potential is given by: \f[ \sum_i \frac{k_i}{2} (x_i-a_i)^2 + m_i*(x_i-a_i) \f]. @@ -43,7 +43,7 @@ respectively. The resulting potential is given by: The number of components for any vector of force constants must be equal to the number of arguments to the action. -Additional material and examples can be also found in the tutorial \ref belfast-4 +Additional material and examples can be also found in the tutorial \ref belfast-4 \par Examples The following input tells plumed to restrain the distance between atoms 3 and 5 @@ -60,7 +60,7 @@ PRINT ARG=restraint.bias */ //+ENDPLUMEDOC -class Restraint : public Bias{ +class Restraint : public Bias { std::vector at; std::vector kappa; std::vector slope; @@ -73,20 +73,20 @@ class Restraint : public Bias{ PLUMED_REGISTER_ACTION(Restraint,"RESTRAINT") -void Restraint::registerKeywords(Keywords& keys){ - Bias::registerKeywords(keys); - keys.use("ARG"); - keys.add("compulsory","SLOPE","0.0","specifies that the restraint is linear and what the values of the force constants on each of the variables are"); - keys.add("compulsory","KAPPA","0.0","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); - keys.add("compulsory","AT","the position of the restraint"); - keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); +void Restraint::registerKeywords(Keywords& keys) { + Bias::registerKeywords(keys); + keys.use("ARG"); + keys.add("compulsory","SLOPE","0.0","specifies that the restraint is linear and what the values of the force constants on each of the variables are"); + keys.add("compulsory","KAPPA","0.0","specifies that the restraint is harmonic and what the values of the force constants on each of the variables are"); + keys.add("compulsory","AT","the position of the restraint"); + keys.addOutputComponent("force2","default","the instantaneous value of the squared force due to this bias potential"); } Restraint::Restraint(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -at(getNumberOfArguments()), -kappa(getNumberOfArguments(),0.0), -slope(getNumberOfArguments(),0.0) + PLUMED_BIAS_INIT(ao), + at(getNumberOfArguments()), + kappa(getNumberOfArguments(),0.0), + slope(getNumberOfArguments(),0.0) { parseVector("SLOPE",slope); parseVector("KAPPA",kappa); @@ -94,13 +94,13 @@ slope(getNumberOfArguments(),0.0) checkRead(); log.printf(" at"); - for(unsigned i=0;i0) simtemp*=plumed.getAtoms().getKBoltzmann(); - else simtemp=plumed.getAtoms().getKbT(); - if(simtemp==0) error("The MD engine does not pass the temperature to plumed so you have to specify it using TEMP"); - // Create something to hold the weight - addValue(); setNotPeriodic(); + simtemp=0.; parse("TEMP",simtemp); + if(simtemp>0) simtemp*=plumed.getAtoms().getKBoltzmann(); + else simtemp=plumed.getAtoms().getKbT(); + if(simtemp==0) error("The MD engine does not pass the temperature to plumed so you have to specify it using TEMP"); + // Create something to hold the weight + addValue(); setNotPeriodic(); } -void ReweightBase::calculate(){ +void ReweightBase::calculate() { double weight = getLogWeight(); setValue( weight ); } diff --git a/src/bias/ReweightBase.h b/src/bias/ReweightBase.h index e3dfd35adb..f39e94d705 100644 --- a/src/bias/ReweightBase.h +++ b/src/bias/ReweightBase.h @@ -28,9 +28,9 @@ namespace PLMD { namespace bias { -class ReweightBase : -public ActionWithValue, -public ActionWithArguments +class ReweightBase : + public ActionWithValue, + public ActionWithArguments { protected: /// The temperature at which you are running the simulation @@ -38,11 +38,11 @@ public ActionWithArguments public: static void registerKeywords(Keywords&); explicit ReweightBase(const ActionOptions&ao); - unsigned getNumberOfDerivatives(){ return 0; } + unsigned getNumberOfDerivatives() { return 0; } void calculate(); virtual double getLogWeight() const = 0; - void apply(){} -}; + void apply() {} +}; } } diff --git a/src/bias/ReweightBias.cpp b/src/bias/ReweightBias.cpp index d5459df962..d0b2d90a3e 100644 --- a/src/bias/ReweightBias.cpp +++ b/src/bias/ReweightBias.cpp @@ -26,24 +26,24 @@ /* Calculate weights for ensemble averages that negate the effect the bias has on the region of phase space explored -If a static or pseudo-static bias \f$V(x,t')\f$ is acting on +If a static or pseudo-static bias \f$V(x,t')\f$ is acting on the system we can remove the bias and get the unbiased probability distribution using: \f[ -\langle P(s',t) \rangle = \frac{ \sum_{t'}^t \delta( s(x) - s' ) \exp\left( +\frac{V(x,t')}{k_B T} \right) }{ \sum_t'^t \exp\left( +\frac{V(x,t')}{k_B T} \right) } +\langle P(s',t) \rangle = \frac{ \sum_{t'}^t \delta( s(x) - s' ) \exp\left( +\frac{V(x,t')}{k_B T} \right) }{ \sum_t'^t \exp\left( +\frac{V(x,t')}{k_B T} \right) } \f] -The weights calculated by this action are equal to \f$\exp\left( +\frac{V(x,t')}{k_B T} \right)\f$ these weights can then be used in any action -that computes ensemble averages. For example this action can be used in tandem with \ref HISTOGRAM or \ref AVERAGE. +The weights calculated by this action are equal to \f$\exp\left( +\frac{V(x,t')}{k_B T} \right)\f$ these weights can then be used in any action +that computes ensemble averages. For example this action can be used in tandem with \ref HISTOGRAM or \ref AVERAGE. \par Examples -In the following example there is a fixed restraint on the distance between atoms 1 and 2. Clearly, this +In the following example there is a fixed restraint on the distance between atoms 1 and 2. Clearly, this restraint will have an effect on the region of phase space that will be sampled when an MD simulation is run using this variable. Consequently, when the histogram as a function of the distance, \f$x\f$, is accumulated, we use reweighting into order to discount the effect of the bias from our final histogram. -\verbatim +\verbatim x: DISTANCE ATOMS=1,2 RESTRAINT ARG=x SLOPE=1.0 AT=0.0 as: REWEIGHT_BIAS TEMP=300 @@ -77,21 +77,21 @@ class ReweightBias : public ReweightBase { PLUMED_REGISTER_ACTION(ReweightBias,"REWEIGHT_BIAS") -void ReweightBias::registerKeywords(Keywords& keys ){ +void ReweightBias::registerKeywords(Keywords& keys ) { ReweightBase::registerKeywords( keys ); keys.remove("ARG"); keys.add("compulsory","ARG","*.bias","the biases that must be taken into account when reweighting"); } ReweightBias::ReweightBias(const ActionOptions&ao): -Action(ao), -ReweightBase(ao) + Action(ao), + ReweightBase(ao) { } double ReweightBias::getLogWeight() const { - // Retrieve the bias - double bias=0.0; for(unsigned i=0;i all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - log.printf(" using the following biases in reweighting "); - for(unsigned j=0;jgetLabel() + ".bias"; - if( all[j]->exists(flab) ){ - biases.push_back( all[j]->copyOutput(flab) ); - log.printf(" %s", flab.c_str()); - } - } - log.printf("\n"); + parse("REWEIGHT_TEMP",rtemp); + log.printf(" reweighting simulation to probabilities at temperature %f\n",rtemp); + rtemp*=plumed.getAtoms().getKBoltzmann(); + + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + log.printf(" using the following biases in reweighting "); + for(unsigned j=0; jgetLabel() + ".bias"; + if( all[j]->exists(flab) ) { + biases.push_back( all[j]->copyOutput(flab) ); + log.printf(" %s", flab.c_str()); + } + } + log.printf("\n"); } -void ReweightTemperature::prepare(){ - plumed.getAtoms().setCollectEnergy(true); +void ReweightTemperature::prepare() { + plumed.getAtoms().setCollectEnergy(true); } double ReweightTemperature::getLogWeight() const { - // Retrieve the bias - double bias=0.0; for(unsigned i=0;iget(); - double energy=plumed.getAtoms().getEnergy()+bias; - return -( (1.0/rtemp) - (1.0/simtemp) )*(energy+bias); + // Retrieve the bias + double bias=0.0; for(unsigned i=0; iget(); + double energy=plumed.getAtoms().getEnergy()+bias; + return -( (1.0/rtemp) - (1.0/simtemp) )*(energy+bias); } } diff --git a/src/bias/UWalls.cpp b/src/bias/UWalls.cpp index 04626b5db6..0f096f11b1 100644 --- a/src/bias/UWalls.cpp +++ b/src/bias/UWalls.cpp @@ -26,16 +26,16 @@ using namespace std; -namespace PLMD{ -namespace bias{ +namespace PLMD { +namespace bias { //+PLUMEDOC BIAS UPPER_WALLS /* Defines a wall for the value of one or more collective variables, - which limits the region of the phase space accessible during the simulation. + which limits the region of the phase space accessible during the simulation. -The restraining potential starts acting on the system when the value of the CV is greater -(in the case of UPPER_WALLS) or lower (in the case of LOWER_WALLS) than a certain limit \f$a_i\f$ (AT) +The restraining potential starts acting on the system when the value of the CV is greater +(in the case of UPPER_WALLS) or lower (in the case of LOWER_WALLS) than a certain limit \f$a_i\f$ (AT) minus an offset \f$o_i\f$ (OFFSET). The expression for the bias due to the wall is given by: @@ -43,15 +43,15 @@ The expression for the bias due to the wall is given by: \sum_i {k_i}((x_i-a_i+o_i)/s_i)^e_i \f$ -\f$k_i\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s_i\f$ (EPS) a rescaling factor and +\f$k_i\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s_i\f$ (EPS) a rescaling factor and \f$e_i\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFFSET = 0. \par Examples -The following input tells plumed to add both a lower and an upper walls on the distance +The following input tells plumed to add both a lower and an upper walls on the distance between atoms 3 and 5 and the distance between atoms 2 and 4. The lower and upper limits -are defined at different values. The strength of the walls is the same for the four cases. -It also tells plumed to print the energy of the walls. +are defined at different values. The strength of the walls is the same for the four cases. +It also tells plumed to print the energy of the walls. \verbatim DISTANCE ATOMS=3,5 LABEL=d1 DISTANCE ATOMS=2,4 LABEL=d2 @@ -64,7 +64,7 @@ PRINT ARG=uwall.bias,lwall.bias */ //+ENDPLUMEDOC -class UWalls : public Bias{ +class UWalls : public Bias { std::vector at; std::vector kappa; std::vector exp; @@ -78,7 +78,7 @@ class UWalls : public Bias{ PLUMED_REGISTER_ACTION(UWalls,"UPPER_WALLS") -void UWalls::registerKeywords(Keywords& keys){ +void UWalls::registerKeywords(Keywords& keys) { Bias::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","AT","the positions of the wall. The a_i in the expression for a wall."); @@ -90,12 +90,12 @@ void UWalls::registerKeywords(Keywords& keys){ } UWalls::UWalls(const ActionOptions&ao): -PLUMED_BIAS_INIT(ao), -at(getNumberOfArguments(),0), -kappa(getNumberOfArguments(),0.0), -exp(getNumberOfArguments(),2.0), -eps(getNumberOfArguments(),1.0), -offset(getNumberOfArguments(),0.0) + PLUMED_BIAS_INIT(ao), + at(getNumberOfArguments(),0), + kappa(getNumberOfArguments(),0.0), + exp(getNumberOfArguments(),2.0), + eps(getNumberOfArguments(),1.0), + offset(getNumberOfArguments(),0.0) { // Note : the sizes of these vectors are checked automatically by parseVector parseVector("OFFSET",offset); @@ -106,28 +106,28 @@ offset(getNumberOfArguments(),0.0) checkRead(); log.printf(" at"); - for(unsigned i=0;i plugins; static map pluginmap; -static int register_cb(void *v, vmdplugin_t *p){ +static int register_cb(void *v, vmdplugin_t *p) { //const char *key = p->name; const auto ret = pluginmap.insert ( std::pair(string(p->name),plugins.size()) ); - if (ret.second==false) { - //cerr<<"MOLFILE: found duplicate plugin for "<(p)); - } + if (ret.second==false) { + //cerr<<"MOLFILE: found duplicate plugin for "<(p)); + } return VMDPLUGIN_SUCCESS; } #endif @@ -195,15 +195,15 @@ class Driver : public CLTool { }; template -void Driver::registerKeywords( Keywords& keys ){ +void Driver::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.isDriver(); keys.addFlag("--help-debug",false,"print special options that can be used to create regtests"); keys.add("compulsory","--plumed","plumed.dat","specify the name of the plumed input file"); keys.add("compulsory","--timestep","1.0","the timestep that was used in the calculation that produced this trajectory in picoseconds"); keys.add("compulsory","--trajectory-stride","1","the frequency with which frames were output to this trajectory during the simulation" #ifdef __PLUMED_HAS_XDRFILE - " (0 means that the number of the step is read from the trajectory file," - " currently working only for xtc/trr files read with --ixtc/--trr)" + " (0 means that the number of the step is read from the trajectory file," + " currently working only for xtc/trr files read with --ixtc/--trr)" #endif ); keys.add("compulsory","--multi","0","set number of replicas for multi environment (needs mpi)"); @@ -225,7 +225,7 @@ void Driver::registerKeywords( Keywords& keys ){ keys.add("optional","--box","comma-separated box dimensions (3 for orthorombic, 9 for generic)"); keys.add("optional","--natoms","provides number of atoms - only used if file format does not contain number of atoms"); keys.add("optional","--debug-forces","output a file containing the forces due to the bias evaluated using numerical derivatives " - "and using the analytical derivatives implemented in plumed"); + "and using the analytical derivatives implemented in plumed"); keys.add("hidden","--debug-float","turns on the single precision version (to check float interface)"); keys.add("hidden","--debug-dd","use a fake domain decomposition"); keys.add("hidden","--debug-pd","use a fake particle decomposition"); @@ -234,56 +234,56 @@ void Driver::registerKeywords( Keywords& keys ){ #ifdef __PLUMED_HAS_MOLFILE_PLUGINS MOLFILE_INIT_ALL MOLFILE_REGISTER_ALL(NULL, register_cb) - for(int i=0;iname); - string mm=" molfile: the trajectory in "+string(plugins[i]->name)+" format " ; - //cerr<<"REGISTERING "<name); + string mm=" molfile: the trajectory in "+string(plugins[i]->name)+" format " ; + //cerr<<"REGISTERING "< Driver::Driver(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { - inputdata=commandline; + inputdata=commandline; } template -string Driver::description()const{ return "analyze trajectories with plumed"; } +string Driver::description()const { return "analyze trajectories with plumed"; } template -int Driver::main(FILE* in,FILE*out,Communicator& pc){ +int Driver::main(FILE* in,FILE*out,Communicator& pc) { Units units; PDB pdb; // Parse everything bool printhelpdebug; parseFlag("--help-debug",printhelpdebug); - if( printhelpdebug ){ - fprintf(out,"%s", - "Additional options for debug (only to be used in regtest):\n" - " [--debug-float] : turns on the single precision version (to check float interface)\n" - " [--debug-dd] : use a fake domain decomposition\n" - " [--debug-pd] : use a fake particle decomposition\n" - ); - return 0; + if( printhelpdebug ) { + fprintf(out,"%s", + "Additional options for debug (only to be used in regtest):\n" + " [--debug-float] : turns on the single precision version (to check float interface)\n" + " [--debug-dd] : use a fake domain decomposition\n" + " [--debug-pd] : use a fake particle decomposition\n" + ); + return 0; } // Are we reading trajectory data bool noatoms; parseFlag("--noatoms",noatoms); - std::string fakein; + std::string fakein; bool debugfloat=parse("--debug-float",fakein); - if(debugfloat && sizeof(real)!=sizeof(float)){ - CLTool* cl=cltoolRegister().create(CLToolOptions("driver-float")); //new Driver(*this); - cl->setInputData(this->getInputData()); - int ret=cl->main(in,out,pc); - delete cl; - return ret; + if(debugfloat && sizeof(real)!=sizeof(float)) { + CLTool* cl=cltoolRegister().create(CLToolOptions("driver-float")); //new Driver(*this); + cl->setInputData(this->getInputData()); + int ret=cl->main(in,out,pc); + delete cl; + return ret; } bool debug_pd=parse("--debug-pd",fakein); bool debug_dd=parse("--debug-dd",fakein); - if( debug_pd || debug_dd ){ + if( debug_pd || debug_dd ) { if(noatoms) error("cannot debug without atoms"); } @@ -292,7 +292,7 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ parse("--multi",multi); Communicator intracomm; Communicator intercomm; - if(multi){ + if(multi) { int ntot=pc.Get_size(); int nintra=ntot/multi; if(multi*nintra!=ntot) error("invalid number of processes for multi environment"); @@ -306,20 +306,20 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ bool debug_grex=parse("--debug-grex",fakein); int grex_stride=0; FILE*grex_log=NULL; - if(debug_grex){ + if(debug_grex) { if(noatoms) error("must have atoms to debug_grex"); if(multi<2) error("--debug_grex needs --multi with at least two replicas"); Tools::convert(fakein,grex_stride); string n; Tools::convert(intercomm.Get_rank(),n); string file; parse("--debug-grex-log",file); - if(file.length()>0){ + if(file.length()>0) { file+="."+n; grex_log=fopen(file.c_str(),"w"); } } -// Read the plumed input file name +// Read the plumed input file name string plumedFile; parse("--plumed",plumedFile); // the timestep double t; parse("--timestep",t); @@ -327,11 +327,11 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ // the stride unsigned stride; parse("--trajectory-stride",stride); // are we writing forces - string dumpforces(""), debugforces(""), dumpforcesFmt("%f");; + string dumpforces(""), debugforces(""), dumpforcesFmt("%f");; bool dumpfullvirial=false; - if(!noatoms){ - parse("--dump-forces",dumpforces); - parse("--debug-forces",debugforces); + if(!noatoms) { + parse("--dump-forces",dumpforces); + parse("--debug-forces",debugforces); } if(dumpforces!="" || debugforces!="" ) parse("--dump-forces-fmt",dumpforcesFmt); if(dumpforces!="") parseFlag("--dump-full-virial",dumpfullvirial); @@ -340,11 +340,11 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ string trajectory_fmt; - bool use_molfile=false; + bool use_molfile=false; #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - molfile_plugin_t *api=NULL; + molfile_plugin_t *api=NULL; void *h_in=NULL; - molfile_timestep_t ts_in; // this is the structure that has the timestep + molfile_timestep_t ts_in; // this is the structure that has the timestep ts_in.coords=NULL; ts_in.A=-1; // we use this to check whether cell is provided or not #endif @@ -354,99 +354,99 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ bool pbc_cli_given=false; vector pbc_cli_box(9,0.0); int command_line_natoms=-1; - if(!noatoms){ - std::string traj_xyz; parse("--ixyz",traj_xyz); - std::string traj_gro; parse("--igro",traj_gro); - std::string traj_xtc; - std::string traj_trr; + if(!noatoms) { + std::string traj_xyz; parse("--ixyz",traj_xyz); + std::string traj_gro; parse("--igro",traj_gro); + std::string traj_xtc; + std::string traj_trr; #ifdef __PLUMED_HAS_XDRFILE - parse("--ixtc",traj_xtc); - parse("--itrr",traj_trr); + parse("--ixtc",traj_xtc); + parse("--itrr",traj_trr); #endif #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - for(int i=0;iname); - string traj_molfile; - parse(molfile_key,traj_molfile); - if(traj_molfile.length()>0){ - fprintf(out,"\nDRIVER: Found molfile format trajectory %s with name %s\n",plugins[i]->name,traj_molfile.c_str()); - trajectoryFile=traj_molfile; - trajectory_fmt=string(plugins[i]->name); - use_molfile=true; - api = plugins[i]; - } - } + for(int i=0; iname); + string traj_molfile; + parse(molfile_key,traj_molfile); + if(traj_molfile.length()>0) { + fprintf(out,"\nDRIVER: Found molfile format trajectory %s with name %s\n",plugins[i]->name,traj_molfile.c_str()); + trajectoryFile=traj_molfile; + trajectory_fmt=string(plugins[i]->name); + use_molfile=true; + api = plugins[i]; + } + } #endif - { // check that only one fmt is specified - int nn=0; - if(traj_xyz.length()>0) nn++; - if(traj_gro.length()>0) nn++; - if(traj_xtc.length()>0) nn++; - if(traj_trr.length()>0) nn++; - if(nn>1){ - fprintf(stderr,"ERROR: cannot provide more than one trajectory file\n"); - if(grex_log)fclose(grex_log); - return 1; - } - } - if(traj_xyz.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_xyz; - trajectory_fmt="xyz"; - } - if(traj_gro.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_gro; - trajectory_fmt="gro"; - } - if(traj_xtc.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_xtc; - trajectory_fmt="xdr-xtc"; - } - if(traj_trr.length()>0 && trajectoryFile.length()==0){ - trajectoryFile=traj_trr; - trajectory_fmt="xdr-trr"; - } - if(trajectoryFile.length()==0){ - fprintf(stderr,"ERROR: missing trajectory data\n"); - if(grex_log)fclose(grex_log); - return 1; - } - string lengthUnits(""); parse("--length-units",lengthUnits); - if(lengthUnits.length()>0) units.setLength(lengthUnits); - string chargeUnits(""); parse("--charge-units",chargeUnits); - if(chargeUnits.length()>0) units.setCharge(chargeUnits); - string massUnits(""); parse("--mass-units",massUnits); - if(massUnits.length()>0) units.setMass(massUnits); - - parse("--pdb",pdbfile); - if(pdbfile.length()>0){ - bool check=pdb.read(pdbfile,false,1.0); - if(!check) error("error reading pdb file"); - } - - parse("--mc",mcfile); - - string pbc_cli_list; parse("--box",pbc_cli_list); - if(pbc_cli_list.length()>0) { - pbc_cli_given=true; - vector words=Tools::getWords(pbc_cli_list,","); - if(words.size()==3){ - for(int i=0;i<3;i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[4*i])); - } else if(words.size()==9) { - for(int i=0;i<9;i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[i])); - } else { - string msg="ERROR: cannot parse command-line box "+pbc_cli_list; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } - - } - - parse("--natoms",command_line_natoms); - + { // check that only one fmt is specified + int nn=0; + if(traj_xyz.length()>0) nn++; + if(traj_gro.length()>0) nn++; + if(traj_xtc.length()>0) nn++; + if(traj_trr.length()>0) nn++; + if(nn>1) { + fprintf(stderr,"ERROR: cannot provide more than one trajectory file\n"); + if(grex_log)fclose(grex_log); + return 1; + } + } + if(traj_xyz.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_xyz; + trajectory_fmt="xyz"; + } + if(traj_gro.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_gro; + trajectory_fmt="gro"; + } + if(traj_xtc.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_xtc; + trajectory_fmt="xdr-xtc"; + } + if(traj_trr.length()>0 && trajectoryFile.length()==0) { + trajectoryFile=traj_trr; + trajectory_fmt="xdr-trr"; + } + if(trajectoryFile.length()==0) { + fprintf(stderr,"ERROR: missing trajectory data\n"); + if(grex_log)fclose(grex_log); + return 1; + } + string lengthUnits(""); parse("--length-units",lengthUnits); + if(lengthUnits.length()>0) units.setLength(lengthUnits); + string chargeUnits(""); parse("--charge-units",chargeUnits); + if(chargeUnits.length()>0) units.setCharge(chargeUnits); + string massUnits(""); parse("--mass-units",massUnits); + if(massUnits.length()>0) units.setMass(massUnits); + + parse("--pdb",pdbfile); + if(pdbfile.length()>0) { + bool check=pdb.read(pdbfile,false,1.0); + if(!check) error("error reading pdb file"); + } + + parse("--mc",mcfile); + + string pbc_cli_list; parse("--box",pbc_cli_list); + if(pbc_cli_list.length()>0) { + pbc_cli_given=true; + vector words=Tools::getWords(pbc_cli_list,","); + if(words.size()==3) { + for(int i=0; i<3; i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[4*i])); + } else if(words.size()==9) { + for(int i=0; i<9; i++) sscanf(words[i].c_str(),"%100lf",&(pbc_cli_box[i])); + } else { + string msg="ERROR: cannot parse command-line box "+pbc_cli_list; + fprintf(stderr,"%s\n",msg.c_str()); + return 1; + } + + } + + parse("--natoms",command_line_natoms); + } if( debug_dd && debug_pd ) error("cannot use debug-dd and debug-pd at the same time"); - if(debug_pd || debug_dd){ + if(debug_pd || debug_dd) { if( !Communicator::initialized() ) error("needs mpi for debug-pd"); } @@ -455,14 +455,14 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ p.cmd("setRealPrecision",&rr); int checknatoms=-1; long int step=0; - if(Communicator::initialized()){ - if(multi){ + if(Communicator::initialized()) { + if(multi) { if(intracomm.Get_rank()==0) p.cmd("GREX setMPIIntercomm",&intercomm.Get_comm()); p.cmd("GREX setMPIIntracomm",&intracomm.Get_comm()); p.cmd("GREX init"); - } + } p.cmd("setMPIComm",&intracomm.Get_comm()); - } + } p.cmd("setMDLengthUnits",&units.getLength()); p.cmd("setMDChargeUnits",&units.getCharge()); p.cmd("setMDMassUnits",&units.getMass()); @@ -471,7 +471,7 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ p.cmd("setPlumedDat",plumedFile.c_str()); p.cmd("setLog",out); - if(multi){ + if(multi) { string n; Tools::convert(intercomm.Get_rank(),n); trajectoryFile=FileBase::appendSuffix(trajectoryFile,"."+n); @@ -484,57 +484,57 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ #ifdef __PLUMED_HAS_XDRFILE XDRFILE* xd=NULL; #endif - if(!noatoms){ - if (trajectoryFile=="-") - fp=in; - else { - if(use_molfile==true){ + if(!noatoms) { + if (trajectoryFile=="-") + fp=in; + else { + if(use_molfile==true) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS h_in = api->open_file_read(trajectoryFile.c_str(), trajectory_fmt.c_str(), &natoms); - if(natoms==MOLFILE_NUMATOMS_UNKNOWN){ + if(natoms==MOLFILE_NUMATOMS_UNKNOWN) { if(command_line_natoms>=0) natoms=command_line_natoms; else error("this file format does not provide number of atoms; use --natoms on the command line"); } ts_in.coords = new float [3*natoms]; #endif - }else if(trajectory_fmt=="xdr-xtc" || trajectory_fmt=="xdr-trr"){ + } else if(trajectory_fmt=="xdr-xtc" || trajectory_fmt=="xdr-trr") { #ifdef __PLUMED_HAS_XDRFILE - xd=xdrfile_open(trajectoryFile.c_str(),"r"); - if(!xd){ - string msg="ERROR: Error opening trajectory file "+trajectoryFile; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } - if(trajectory_fmt=="xdr-xtc") read_xtc_natoms(&trajectoryFile[0],&natoms); - if(trajectory_fmt=="xdr-trr") read_trr_natoms(&trajectoryFile[0],&natoms); + xd=xdrfile_open(trajectoryFile.c_str(),"r"); + if(!xd) { + string msg="ERROR: Error opening trajectory file "+trajectoryFile; + fprintf(stderr,"%s\n",msg.c_str()); + return 1; + } + if(trajectory_fmt=="xdr-xtc") read_xtc_natoms(&trajectoryFile[0],&natoms); + if(trajectory_fmt=="xdr-trr") read_trr_natoms(&trajectoryFile[0],&natoms); #endif - }else{ - fp=fopen(trajectoryFile.c_str(),"r"); - if(!fp){ - string msg="ERROR: Error opening trajectory file "+trajectoryFile; - fprintf(stderr,"%s\n",msg.c_str()); + } else { + fp=fopen(trajectoryFile.c_str(),"r"); + if(!fp) { + string msg="ERROR: Error opening trajectory file "+trajectoryFile; + fprintf(stderr,"%s\n",msg.c_str()); // cppcheck detects a false positive here. I suppress it: // cppcheck-suppress memleak - return 1; - } - } - } - if(dumpforces.length()>0){ - if(Communicator::initialized() && pc.Get_size()>1){ - string n; - Tools::convert(pc.Get_rank(),n); - dumpforces+="."+n; - } - fp_forces=fopen(dumpforces.c_str(),"w"); - } - if(debugforces.length()>0){ - if(Communicator::initialized() && pc.Get_size()>1){ - string n; - Tools::convert(pc.Get_rank(),n); - debugforces+="."+n; - } - fp_dforces.open(debugforces); - } + return 1; + } + } + } + if(dumpforces.length()>0) { + if(Communicator::initialized() && pc.Get_size()>1) { + string n; + Tools::convert(pc.Get_rank(),n); + dumpforces+="."+n; + } + fp_forces=fopen(dumpforces.c_str(),"w"); + } + if(debugforces.length()>0) { + if(Communicator::initialized() && pc.Get_size()>1) { + string n; + Tools::convert(pc.Get_rank(),n); + debugforces+="."+n; + } + fp_dforces.open(debugforces); + } } std::string line; @@ -560,41 +560,41 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ // random stream to choose decompositions Random rnd; - while(true){ - if(!noatoms){ - if(use_molfile==true){ + while(true) { + if(!noatoms) { + if(use_molfile==true) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - int rc; - rc = api->read_next_timestep(h_in, natoms, &ts_in); - //if(rc==MOLFILE_SUCCESS){ - // printf(" read this one :success \n"); - //} - if(rc==MOLFILE_EOF){ - //printf(" read this one :eof or error \n"); - break; - } + int rc; + rc = api->read_next_timestep(h_in, natoms, &ts_in); + //if(rc==MOLFILE_SUCCESS){ + // printf(" read this one :success \n"); + //} + if(rc==MOLFILE_EOF) { + //printf(" read this one :eof or error \n"); + break; + } #endif - }else if(trajectory_fmt=="xyz" || trajectory_fmt=="gro"){ - if(!Tools::getline(fp,line)) break; - } + } else if(trajectory_fmt=="xyz" || trajectory_fmt=="gro") { + if(!Tools::getline(fp,line)) break; + } } bool first_step=false; - if(!noatoms){ - if(use_molfile==false && (trajectory_fmt=="xyz" || trajectory_fmt=="gro")){ + if(!noatoms) { + if(use_molfile==false && (trajectory_fmt=="xyz" || trajectory_fmt=="gro")) { if(trajectory_fmt=="gro") if(!Tools::getline(fp,line)) error("premature end of trajectory file"); sscanf(line.c_str(),"%100d",&natoms); } } - if(checknatoms<0 && !noatoms){ + if(checknatoms<0 && !noatoms) { pd_nlocal=natoms; pd_start=0; first_step=true; masses.assign(natoms,NAN); charges.assign(natoms,NAN); //case pdb: structure - if(pdbfile.length()>0){ - for(unsigned i=0;i0) { + for(unsigned i=0; i=unsigned(natoms) ) error("atom index in pdb exceeds the number of atoms in trajectory"); @@ -602,26 +602,26 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ charges[index]=pdb.getBeta()[i]; } } - if(mcfile.length()>0){ + if(mcfile.length()>0) { IFile ifile; ifile.open(mcfile); int index; double mass; double charge; - while(ifile.scanField("index",index).scanField("mass",mass).scanField("charge",charge).scanField()){ + while(ifile.scanField("index",index).scanField("mass",mass).scanField("charge",charge).scanField()) { masses[index]=mass; charges[index]=charge; } } - } else if( checknatoms<0 && noatoms ){ - natoms=0; + } else if( checknatoms<0 && noatoms ) { + natoms=0; } - if( checknatoms<0 ){ + if( checknatoms<0 ) { checknatoms=natoms; p.cmd("setNatoms",&natoms); p.cmd("init"); } - if(checknatoms!=natoms){ - std::string stepstr; Tools::convert(step,stepstr); - error("number of atoms in frame " + stepstr + " does not match number of atoms in first frame"); + if(checknatoms!=natoms) { + std::string stepstr; Tools::convert(step,stepstr); + error("number of atoms in frame " + stepstr + " does not match number of atoms in first frame"); } coordinates.assign(3*natoms,real(0.0)); @@ -629,12 +629,12 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ cell.assign(9,real(0.0)); virial.assign(9,real(0.0)); - if( first_step || rnd.U01()>0.5){ - if(debug_pd){ + if( first_step || rnd.U01()>0.5) { + if(debug_pd) { int npe=intracomm.Get_size(); vector loc(npe,0); vector start(npe,0); - for(int i=0;inatoms) cc=natoms-start[i]; loc[i]=cc; @@ -645,14 +645,14 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ intracomm.Bcast(start,0); pd_nlocal=loc[intracomm.Get_rank()]; pd_start=start[intracomm.Get_rank()]; - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { fprintf(out,"\nDRIVER: Reassigning particle decomposition\n"); - fprintf(out,"DRIVER: "); for(int i=0;i::main(FILE* in,FILE*out,Communicator& pc){ dd_coordinates.assign(3*natoms,0.0); dd_forces.assign(3*natoms,0.0); dd_nlocal=0; - for(int i=0;ir)break; + int n; for(n=0; nr)break; plumed_assert(n::main(FILE* in,FILE*out,Communicator& pc){ dd_nlocal++; } } - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { fprintf(out,"\nDRIVER: Reassigning particle decomposition\n"); } p.cmd("setAtomsNlocal",&dd_nlocal); @@ -683,232 +683,232 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc){ } int plumedStopCondition=0; - if(!noatoms){ - if(use_molfile){ + if(!noatoms) { + if(use_molfile) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS - if(pbc_cli_given==false) { - if(ts_in.A>0.0){ // this is negative if molfile does not provide box - // info on the cell: convert using pbcset.tcl from pbctools in vmd distribution - real cosBC=cos(ts_in.alpha*pi/180.); - //double sinBC=sin(ts_in.alpha*pi/180.); - real cosAC=cos(ts_in.beta*pi/180.); - real cosAB=cos(ts_in.gamma*pi/180.); - real sinAB=sin(ts_in.gamma*pi/180.); - real Ax=ts_in.A; - real Bx=ts_in.B*cosAB; - real By=ts_in.B*sinAB; - real Cx=ts_in.C*cosAC; - real Cy=(ts_in.C*ts_in.B*cosBC-Cx*Bx)/By; - real Cz=sqrt(ts_in.C*ts_in.C-Cx*Cx-Cy*Cy); - cell[0]=Ax/10.;cell[1]=0.;cell[2]=0.; - cell[3]=Bx/10.;cell[4]=By/10.;cell[5]=0.; - cell[6]=Cx/10.;cell[7]=Cy/10.;cell[8]=Cz/10.; - } else { - cell[0]=0.0; cell[1]=0.0; cell[2]=0.0; - cell[3]=0.0; cell[4]=0.0; cell[5]=0.0; - cell[6]=0.0; cell[7]=0.0; cell[8]=0.0; - } - }else{ - for(unsigned i=0;i<9;i++)cell[i]=pbc_cli_box[i]; - } - // info on coords - // the order is xyzxyz... - for(unsigned i=0;i<3*natoms;i++){ - coordinates[i]=real(ts_in.coords[i]/10.); //convert to nm - //cerr<<"COOR "<0.0) { // this is negative if molfile does not provide box + // info on the cell: convert using pbcset.tcl from pbctools in vmd distribution + real cosBC=cos(ts_in.alpha*pi/180.); + //double sinBC=sin(ts_in.alpha*pi/180.); + real cosAC=cos(ts_in.beta*pi/180.); + real cosAB=cos(ts_in.gamma*pi/180.); + real sinAB=sin(ts_in.gamma*pi/180.); + real Ax=ts_in.A; + real Bx=ts_in.B*cosAB; + real By=ts_in.B*sinAB; + real Cx=ts_in.C*cosAC; + real Cy=(ts_in.C*ts_in.B*cosBC-Cx*Bx)/By; + real Cz=sqrt(ts_in.C*ts_in.C-Cx*Cx-Cy*Cy); + cell[0]=Ax/10.; cell[1]=0.; cell[2]=0.; + cell[3]=Bx/10.; cell[4]=By/10.; cell[5]=0.; + cell[6]=Cx/10.; cell[7]=Cy/10.; cell[8]=Cz/10.; + } else { + cell[0]=0.0; cell[1]=0.0; cell[2]=0.0; + cell[3]=0.0; cell[4]=0.0; cell[5]=0.0; + cell[6]=0.0; cell[7]=0.0; cell[8]=0.0; + } + } else { + for(unsigned i=0; i<9; i++)cell[i]=pbc_cli_box[i]; + } + // info on coords + // the order is xyzxyz... + for(unsigned i=0; i<3*natoms; i++) { + coordinates[i]=real(ts_in.coords[i]/10.); //convert to nm + //cerr<<"COOR "< celld(9,0.0); - if(pbc_cli_given==false) { - std::vector words; - words=Tools::getWords(line); - if(words.size()==3){ - sscanf(line.c_str(),"%100lf %100lf %100lf",&celld[0],&celld[4],&celld[8]); - } else if(words.size()==9){ - sscanf(line.c_str(),"%100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf", - &celld[0], &celld[1], &celld[2], - &celld[3], &celld[4], &celld[5], - &celld[6], &celld[7], &celld[8]); - } else error("needed box in second line of xyz file"); - } else { // from command line - celld=pbc_cli_box; - } - for(unsigned i=0;i<9;i++)cell[i]=real(celld[i]); - } - int ddist=0; - // Read coordinates - for(int i=0;i=pd_start && i words=Tools::getWords(line); - if(words.size()<3) error("cannot understand box format"); - Tools::convert(words[0],cell[0]); - Tools::convert(words[1],cell[4]); - Tools::convert(words[2],cell[8]); - if(words.size()>3) Tools::convert(words[3],cell[1]); - if(words.size()>4) Tools::convert(words[4],cell[2]); - if(words.size()>5) Tools::convert(words[5],cell[3]); - if(words.size()>6) Tools::convert(words[6],cell[5]); - if(words.size()>7) Tools::convert(words[7],cell[6]); - if(words.size()>8) Tools::convert(words[8],cell[7]); - } - - } - - p.cmd("setStepLong",&step); - p.cmd("setStopFlag",&plumedStopCondition); - - if(debug_dd){ - for(int i=0;i celld(9,0.0); + if(pbc_cli_given==false) { + std::vector words; + words=Tools::getWords(line); + if(words.size()==3) { + sscanf(line.c_str(),"%100lf %100lf %100lf",&celld[0],&celld[4],&celld[8]); + } else if(words.size()==9) { + sscanf(line.c_str(),"%100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf %100lf", + &celld[0], &celld[1], &celld[2], + &celld[3], &celld[4], &celld[5], + &celld[6], &celld[7], &celld[8]); + } else error("needed box in second line of xyz file"); + } else { // from command line + celld=pbc_cli_box; + } + for(unsigned i=0; i<9; i++)cell[i]=real(celld[i]); + } + int ddist=0; + // Read coordinates + for(int i=0; i=pd_start && i words=Tools::getWords(line); + if(words.size()<3) error("cannot understand box format"); + Tools::convert(words[0],cell[0]); + Tools::convert(words[1],cell[4]); + Tools::convert(words[2],cell[8]); + if(words.size()>3) Tools::convert(words[3],cell[1]); + if(words.size()>4) Tools::convert(words[4],cell[2]); + if(words.size()>5) Tools::convert(words[5],cell[3]); + if(words.size()>6) Tools::convert(words[6],cell[5]); + if(words.size()>7) Tools::convert(words[7],cell[6]); + if(words.size()>8) Tools::convert(words[8],cell[7]); + } + + } + + p.cmd("setStepLong",&step); + p.cmd("setStopFlag",&plumedStopCondition); + + if(debug_dd) { + for(int i=0; i0){ - p.cmd("GREX prepare"); - } else { - int r=intercomm.Get_rank(); - int n=intercomm.Get_size(); - int partner=r+(2*((r+step/grex_stride)%2))-1; - if(partner<0)partner=0; - if(partner>=n) partner=n-1; - p.cmd("GREX setPartner",&partner); - p.cmd("GREX calculate"); - p.cmd("GREX shareAllDeltaBias"); - for(int i=0;i0){ + intracomm.Bcast(virial,0); + if(debug_pd) intracomm.Sum(forces); + if(debug_dd) { + for(int i=0; i0) { + p.cmd("GREX prepare"); + } else { + int r=intercomm.Get_rank(); + int n=intercomm.Get_size(); + int partner=r+(2*((r+step/grex_stride)%2))-1; + if(partner<0)partner=0; + if(partner>=n) partner=n-1; + p.cmd("GREX setPartner",&partner); + p.cmd("GREX calculate"); + p.cmd("GREX shareAllDeltaBias"); + for(int i=0; i0) { // Now call the routine to work out the derivatives numerically numder.assign(3*natoms+9,real(0.0)); real base=0; p.cmd("getBias",&base); if( fabs(base)::main(FILE* in,FILE*out,Communicator& pc){ template void Driver::evaluateNumericalDerivatives( const long int& step, Plumed& p, const std::vector& coordinates, - const std::vector& masses, const std::vector& charges, - std::vector& cell, const double& base, std::vector& numder ){ + const std::vector& masses, const std::vector& charges, + std::vector& cell, const double& base, std::vector& numder ) { int natoms = coordinates.size() / 3; real delta = sqrt(epsilon); - std::vector pos(natoms); real bias=0; + std::vector pos(natoms); real bias=0; std::vector fake_forces( 3*natoms ), fake_virial(9); - for(int i=0;i DriverFloat; /// Specialized version template<> -string Driver::description()const{ return "analyze trajectories with plumed (single precision version)"; } +string Driver::description()const { return "analyze trajectories with plumed (single precision version)"; } PLUMED_REGISTER_CLTOOL(DriverFloat,"driver-float") diff --git a/src/cltools/GenTemplate.cpp b/src/cltools/GenTemplate.cpp index 7ac49aa374..bce33af848 100644 --- a/src/cltools/GenTemplate.cpp +++ b/src/cltools/GenTemplate.cpp @@ -32,7 +32,7 @@ using namespace std; namespace PLMD { -namespace cltools{ +namespace cltools { //+PLUMEDOC TOOLS gentemplate /* @@ -48,26 +48,26 @@ The following generates template input for the action DISTANCE. \verbatim plumed gentemplate --action DISTANCE \endverbatim - + */ //+ENDPLUMEDOC class GenTemplate: -public CLTool + public CLTool { public: static void registerKeywords( Keywords& keys ); explicit GenTemplate(const CLToolOptions& co ); int main(FILE* in, FILE*out,Communicator& pc); - string description()const{ + string description()const { return "print out a template input for a particular action"; } }; PLUMED_REGISTER_CLTOOL(GenTemplate,"gentemplate") -void GenTemplate::registerKeywords( Keywords& keys ){ +void GenTemplate::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.add("optional","--action","print the template for this particular action"); keys.addFlag("--list",false,"print a list of the available actions"); @@ -75,32 +75,32 @@ void GenTemplate::registerKeywords( Keywords& keys ){ } GenTemplate::GenTemplate(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { inputdata=commandline; } -int GenTemplate::main(FILE* in, FILE*out,Communicator& pc){ +int GenTemplate::main(FILE* in, FILE*out,Communicator& pc) { - std::string action; - bool list_templates=false; - parseFlag("--list",list_templates); + std::string action; + bool list_templates=false; + parseFlag("--list",list_templates); - if(list_templates) { - std::cerr<3){ + } + parse("ndim",ndim); + if(ndim<1 || ndim>3) { fprintf(stderr,"ndim should be 1,2 or 3\n"); exit(1); + } + std::string w; + parse("wrapatoms",w); + wrapatoms=false; + if(w.length()>0 && (w[0]=='T' || w[0]=='t')) wrapatoms=true; } - std::string w; - parse("wrapatoms",w); - wrapatoms=false; - if(w.length()>0 && (w[0]=='T' || w[0]=='t')) wrapatoms=true; -} -void read_natoms(const string & inputfile,int & natoms){ + void read_natoms(const string & inputfile,int & natoms) { // read the number of atoms in file "input.xyz" - FILE* fp=fopen(inputfile.c_str(),"r"); - if(!fp){ - fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str()); - exit(1); + FILE* fp=fopen(inputfile.c_str(),"r"); + if(!fp) { + fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str()); + exit(1); + } + fscanf(fp,"%1000d",&natoms); + fclose(fp); } - fscanf(fp,"%1000d",&natoms); - fclose(fp); -} -void read_positions(const string& inputfile,int natoms,vector& positions,double cell[3]){ + void read_positions(const string& inputfile,int natoms,vector& positions,double cell[3]) { // read positions and cell from a file called inputfile // natoms (input variable) and number of atoms in the file should be consistent - FILE* fp=fopen(inputfile.c_str(),"r"); - if(!fp){ - fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str()); - exit(1); - } - char buffer[256]; - char atomname[256]; - fgets(buffer,256,fp); - fscanf(fp,"%1000lf %1000lf %1000lf",&cell[0],&cell[1],&cell[2]); - for(int i=0;i&masses,vector& velocities,Random&random){ + void randomize_velocities(const int natoms,const int ndim,const double temperature,const vector&masses,vector& velocities,Random&random) { // randomize the velocities according to the temperature - for(int iatom=0;iatom& positions,const vector&positions0,const double listcutoff, - const double forcecutoff,bool & recompute) -{ + void check_list(const int natoms,const vector& positions,const vector&positions0,const double listcutoff, + const double forcecutoff,bool & recompute) + { // check if the neighbour list have to be recomputed - Vector displacement; // displacement from positions0 to positions - double delta2; // square of the 'skin' thickness - recompute=false; - delta2=(0.5*(listcutoff-forcecutoff))*(0.5*(listcutoff-forcecutoff)); + Vector displacement; // displacement from positions0 to positions + double delta2; // square of the 'skin' thickness + recompute=false; + delta2=(0.5*(listcutoff-forcecutoff))*(0.5*(listcutoff-forcecutoff)); // if ANY atom moved more than half of the skin thickness, recompute is set to .true. - for(int iatom=0;iatomdelta2) recompute=true; + for(int iatom=0; iatomdelta2) recompute=true; + } } -} -void compute_list(const int natoms,const int listsize,const vector& positions,const double cell[3],const double listcutoff, - vector& point,vector& list){ + void compute_list(const int natoms,const int listsize,const vector& positions,const double cell[3],const double listcutoff, + vector& point,vector& list) { // see Allen-Tildesey for a definition of point and list - Vector distance; // distance of the two atoms - Vector distance_pbc; // minimum-image distance of the two atoms - double listcutoff2; // squared list cutoff - listcutoff2=listcutoff*listcutoff; - point[0]=0; - for(int iatom=0;iatomlistcutoff2)continue; - if(point[iatom+1]>listsize){ + double d2=0; for(int k=0; k<3; k++) d2+=distance_pbc[k]*distance_pbc[k]; + if(d2>listcutoff2)continue; + if(point[iatom+1]>listsize) { // too many neighbours - fprintf(stderr,"%s","Verlet list size exceeded\n"); - fprintf(stderr,"%s","Increase maxneighbours\n"); - exit(1); + fprintf(stderr,"%s","Verlet list size exceeded\n"); + fprintf(stderr,"%s","Increase maxneighbours\n"); + exit(1); + } + list[point[iatom+1]]=jatom; + point[iatom+1]++; } - list[point[iatom+1]]=jatom; - point[iatom+1]++; } } -} -void compute_forces(const int natoms,const int listsize,const vector& positions,const double cell[3], - double forcecutoff,const vector& point,const vector& list,vector& forces,double & engconf) -{ - Vector distance; // distance of the two atoms - Vector distance_pbc; // minimum-image distance of the two atoms - double distance_pbc2; // squared minimum-image distance - double forcecutoff2; // squared force cutoff - Vector f; // force - double engcorrection; // energy necessary shift the potential avoiding discontinuities - - forcecutoff2=forcecutoff*forcecutoff; - engconf=0.0; - for(int i=0;i& positions,const double cell[3], + double forcecutoff,const vector& point,const vector& list,vector& forces,double & engconf) + { + Vector distance; // distance of the two atoms + Vector distance_pbc; // minimum-image distance of the two atoms + double distance_pbc2; // squared minimum-image distance + double forcecutoff2; // squared force cutoff + Vector f; // force + double engcorrection; // energy necessary shift the potential avoiding discontinuities + + forcecutoff2=forcecutoff*forcecutoff; + engconf=0.0; + for(int i=0; iforcecutoff2) continue; - double distance_pbc6=distance_pbc2*distance_pbc2*distance_pbc2; - double distance_pbc8=distance_pbc6*distance_pbc2; - double distance_pbc12=distance_pbc6*distance_pbc6; - double distance_pbc14=distance_pbc12*distance_pbc2; - engconf+=4.0*(1.0/distance_pbc12 - 1.0/distance_pbc6) - engcorrection; - for(int k=0;k<3;k++) f[k]=2.0*distance_pbc[k]*4.0*(6.0/distance_pbc14-3.0/distance_pbc8); + if(distance_pbc2>forcecutoff2) continue; + double distance_pbc6=distance_pbc2*distance_pbc2*distance_pbc2; + double distance_pbc8=distance_pbc6*distance_pbc2; + double distance_pbc12=distance_pbc6*distance_pbc6; + double distance_pbc14=distance_pbc12*distance_pbc2; + engconf+=4.0*(1.0/distance_pbc12 - 1.0/distance_pbc6) - engcorrection; + for(int k=0; k<3; k++) f[k]=2.0*distance_pbc[k]*4.0*(6.0/distance_pbc14-3.0/distance_pbc8); // same force on the two atoms, with opposite sign: - for(int k=0;k<3;k++) forces[iatom][k]+=f[k]; - for(int k=0;k<3;k++) forces[jatom][k]-=f[k]; + for(int k=0; k<3; k++) forces[iatom][k]+=f[k]; + for(int k=0; k<3; k++) forces[jatom][k]-=f[k]; + } } } -} -void compute_engkin(const int natoms,const vector& masses,const vector& velocities,double & engkin) -{ + void compute_engkin(const int natoms,const vector& masses,const vector& velocities,double & engkin) + { // calculate the kinetic energy from the velocities - engkin=0.0; - for(int iatom=0;iatom& masses,const double dt,const double friction, - const double temperature,vector& velocities,double & engint,Random & random){ + void thermostat(const int natoms,const int ndim,const vector& masses,const double dt,const double friction, + const double temperature,vector& velocities,double & engint,Random & random) { // Langevin thermostat, implemented as decribed in Bussi and Parrinello, Phys. Rev. E (2007) // it is a linear combination of old velocities and new, randomly chosen, velocity, // with proper coefficients - double c1=exp(-friction*dt); - for(int iatom=0;iatom& positions,const double cell[3],const bool wrapatoms) -{ + void write_positions(const string& trajfile,int natoms,const vector& positions,const double cell[3],const bool wrapatoms) + { // write positions on file trajfile // positions are appended at the end of the file - Vector pos; - FILE*fp; - if(write_positions_first){ - fp=fopen(trajfile.c_str(),"w"); - write_positions_first=false; - } else { - fp=fopen(trajfile.c_str(),"a"); - } - fprintf(fp,"%d\n",natoms); - fprintf(fp,"%f %f %f\n",cell[0],cell[1],cell[2]); - for(int iatom=0;iatom& positions,const double cell[3],const bool wrapatoms) -{ + void write_final_positions(const string& outputfile,int natoms,const vector& positions,const double cell[3],const bool wrapatoms) + { // write positions on file outputfile - Vector pos; - FILE*fp; - fp=fopen(outputfile.c_str(),"w"); - fprintf(fp,"%d\n",natoms); - fprintf(fp,"%f %f %f\n",cell[0],cell[1],cell[2]); - for(int iatom=0;iatom100){ + write_statistics_fp=fopen(statfile.c_str(),"w"); + write_statistics_first=false; + } + if(istep-write_statistics_last_time_reopened>100) { // every 100 steps, reopen the file to flush the buffer - fclose(write_statistics_fp); - write_statistics_fp=fopen(statfile.c_str(),"a"); - write_statistics_last_time_reopened=istep; + fclose(write_statistics_fp); + write_statistics_fp=fopen(statfile.c_str(),"a"); + write_statistics_last_time_reopened=istep; + } + fprintf(write_statistics_fp,"%d %f %f %f %f %f\n",istep,istep*tstep,2.0*engkin/double(ndim*natoms),engconf,engkin+engconf,engkin+engconf+engint); } - fprintf(write_statistics_fp,"%d %f %f %f %f %f\n",istep,istep*tstep,2.0*engkin/double(ndim*natoms),engconf,engkin+engconf,engkin+engconf+engint); -} -virtual int main(FILE* in,FILE*out,PLMD::Communicator& pc){ - int natoms; // number of atoms - vector positions; // atomic positions - vector velocities; // velocities - vector masses; // masses - vector forces; // forces - double cell[3]; // cell size - double cell9[3][3]; // cell size + virtual int main(FILE* in,FILE*out,PLMD::Communicator& pc) { + int natoms; // number of atoms + vector positions; // atomic positions + vector velocities; // velocities + vector masses; // masses + vector forces; // forces + double cell[3]; // cell size + double cell9[3][3]; // cell size // neighbour list variables // see Allen and Tildesey book for details - int listsize; // size of the list array - vector list; // neighbour list - vector point; // pointer to neighbour list - vector positions0; // reference atomic positions, i.e. positions when the neighbour list + int listsize; // size of the list array + vector list; // neighbour list + vector point; // pointer to neighbour list + vector positions0; // reference atomic positions, i.e. positions when the neighbour list // input parameters // all of them have a reasonable default value, set in read_input() - double tstep; // simulation timestep - double temperature; // temperature - double friction; // friction for Langevin dynamics (for NVE, use 0) - double listcutoff; // cutoff for neighbour list - double forcecutoff; // cutoff for forces - int nstep; // number of steps - int nconfig; // stride for output of configurations - int nstat; // stride for output of statistics - int maxneighbour; // maximum average number of neighbours per atom - int ndim; // dimensionality of the system (1, 2, or 3) - int idum; // seed - int plumedWantsToStop; // stop flag - bool wrapatoms; // if true, atomic coordinates are written wrapped in minimal cell - string inputfile; // name of file with starting configuration (xyz) - string outputfile; // name of file with final configuration (xyz) - string trajfile; // name of the trajectory file (xyz) - string statfile; // name of the file with statistics - - double engkin; // kinetic energy - double engconf; // configurational energy - double engint; // integral for conserved energy in Langevin dynamics - - bool recompute_list; // control if the neighbour list have to be recomputed - - Random random; // random numbers stream - - PLMD::Plumed* plumed=NULL; + double tstep; // simulation timestep + double temperature; // temperature + double friction; // friction for Langevin dynamics (for NVE, use 0) + double listcutoff; // cutoff for neighbour list + double forcecutoff; // cutoff for forces + int nstep; // number of steps + int nconfig; // stride for output of configurations + int nstat; // stride for output of statistics + int maxneighbour; // maximum average number of neighbours per atom + int ndim; // dimensionality of the system (1, 2, or 3) + int idum; // seed + int plumedWantsToStop; // stop flag + bool wrapatoms; // if true, atomic coordinates are written wrapped in minimal cell + string inputfile; // name of file with starting configuration (xyz) + string outputfile; // name of file with final configuration (xyz) + string trajfile; // name of the trajectory file (xyz) + string statfile; // name of the file with statistics + + double engkin; // kinetic energy + double engconf; // configurational energy + double engint; // integral for conserved energy in Langevin dynamics + + bool recompute_list; // control if the neighbour list have to be recomputed + + Random random; // random numbers stream + + PLMD::Plumed* plumed=NULL; // Commenting the next line it is possible to switch-off plumed - plumed=new PLMD::Plumed; + plumed=new PLMD::Plumed; - if(plumed){ - int s=sizeof(double); - plumed->cmd("setRealPrecision",&s); - } + if(plumed) { + int s=sizeof(double); + plumed->cmd("setRealPrecision",&s); + } - read_input(temperature,tstep,friction,forcecutoff, - listcutoff,nstep,nconfig,nstat, - wrapatoms,inputfile,outputfile,trajfile,statfile, - maxneighbour,ndim,idum); + read_input(temperature,tstep,friction,forcecutoff, + listcutoff,nstep,nconfig,nstat, + wrapatoms,inputfile,outputfile,trajfile,statfile, + maxneighbour,ndim,idum); // number of atoms is read from file inputfile - read_natoms(inputfile,natoms); + read_natoms(inputfile,natoms); // write the parameters in output so they can be checked - fprintf(out,"%s %s\n","Starting configuration :",inputfile.c_str()); - fprintf(out,"%s %s\n","Final configuration :",outputfile.c_str()); - fprintf(out,"%s %d\n","Number of atoms :",natoms); - fprintf(out,"%s %f\n","Temperature :",temperature); - fprintf(out,"%s %f\n","Time step :",tstep); - fprintf(out,"%s %f\n","Friction :",friction); - fprintf(out,"%s %f\n","Cutoff for forces :",forcecutoff); - fprintf(out,"%s %f\n","Cutoff for neighbour list :",listcutoff); - fprintf(out,"%s %d\n","Number of steps :",nstep); - fprintf(out,"%s %d\n","Stride for trajectory :",nconfig); - fprintf(out,"%s %s\n","Trajectory file :",trajfile.c_str()); - fprintf(out,"%s %d\n","Stride for statistics :",nstat); - fprintf(out,"%s %s\n","Statistics file :",statfile.c_str()); - fprintf(out,"%s %d\n","Max average number of neighbours :",maxneighbour); - fprintf(out,"%s %d\n","Dimensionality :",ndim); - fprintf(out,"%s %d\n","Seed :",idum); - fprintf(out,"%s %s\n","Are atoms wrapped on output? :",(wrapatoms?"T":"F")); + fprintf(out,"%s %s\n","Starting configuration :",inputfile.c_str()); + fprintf(out,"%s %s\n","Final configuration :",outputfile.c_str()); + fprintf(out,"%s %d\n","Number of atoms :",natoms); + fprintf(out,"%s %f\n","Temperature :",temperature); + fprintf(out,"%s %f\n","Time step :",tstep); + fprintf(out,"%s %f\n","Friction :",friction); + fprintf(out,"%s %f\n","Cutoff for forces :",forcecutoff); + fprintf(out,"%s %f\n","Cutoff for neighbour list :",listcutoff); + fprintf(out,"%s %d\n","Number of steps :",nstep); + fprintf(out,"%s %d\n","Stride for trajectory :",nconfig); + fprintf(out,"%s %s\n","Trajectory file :",trajfile.c_str()); + fprintf(out,"%s %d\n","Stride for statistics :",nstat); + fprintf(out,"%s %s\n","Statistics file :",statfile.c_str()); + fprintf(out,"%s %d\n","Max average number of neighbours :",maxneighbour); + fprintf(out,"%s %d\n","Dimensionality :",ndim); + fprintf(out,"%s %d\n","Seed :",idum); + fprintf(out,"%s %s\n","Are atoms wrapped on output? :",(wrapatoms?"T":"F")); // Setting the seed - random.setSeed(idum); + random.setSeed(idum); // Since each atom pair is counted once, the total number of pairs // will be half of the number of neighbours times the number of atoms - listsize=maxneighbour*natoms/2; + listsize=maxneighbour*natoms/2; // allocation of dynamical arrays - positions.resize(natoms); - positions0.resize(natoms); - velocities.resize(natoms); - forces.resize(natoms); - masses.resize(natoms); - point.resize(natoms); - list.resize(listsize); + positions.resize(natoms); + positions0.resize(natoms); + velocities.resize(natoms); + forces.resize(natoms); + masses.resize(natoms); + point.resize(natoms); + list.resize(listsize); // masses are hard-coded to 1 - for(int i=0;icmd("setNoVirial"); - plumed->cmd("setNatoms",&natoms); - plumed->cmd("setMDEngine","simpleMD"); - plumed->cmd("setTimestep",&tstep); - plumed->cmd("setPlumedDat","plumed.dat"); - int pversion=0; - plumed->cmd("getApiVersion",&pversion); + randomize_velocities(natoms,ndim,temperature,masses,velocities,random); + + if(plumed) { + plumed->cmd("setNoVirial"); + plumed->cmd("setNatoms",&natoms); + plumed->cmd("setMDEngine","simpleMD"); + plumed->cmd("setTimestep",&tstep); + plumed->cmd("setPlumedDat","plumed.dat"); + int pversion=0; + plumed->cmd("getApiVersion",&pversion); // setting kbT is only implemented with api>1 // even if not necessary in principle in SimpleMD (which is part of plumed) // we leave the check here as a reference - if(pversion>1){ + if(pversion>1) { plumed->cmd("setKbT",&temperature); } - plumed->cmd("init"); - } + plumed->cmd("init"); + } // neighbour list are computed, and reference positions are saved - compute_list(natoms,listsize,positions,cell,listcutoff,point,list); + compute_list(natoms,listsize,positions,cell,listcutoff,point,list); - fprintf(out,"List size: %d\n",point[natoms-1]); - for(int iatom=0;iatomcmd("setStep",&istepplusone); - plumed->cmd("setMasses",&masses[0]); - plumed->cmd("setForces",&forces[0]); - plumed->cmd("setEnergy",&engconf); - plumed->cmd("setPositions",&positions[0]); - plumed->cmd("setBox",cell9); - plumed->cmd("setStopFlag",&plumedWantsToStop); - plumed->cmd("calc"); - if(plumedWantsToStop) nstep=istep; - } + compute_forces(natoms,listsize,positions,cell,forcecutoff,point,list,forces,engconf); + + if(plumed) { + int istepplusone=istep+1; + plumedWantsToStop=0; + for(int i=0; i<3; i++)for(int k=0; k<3; k++) cell9[i][k]=0.0; + for(int i=0; i<3; i++) cell9[i][i]=cell[i]; + plumed->cmd("setStep",&istepplusone); + plumed->cmd("setMasses",&masses[0]); + plumed->cmd("setForces",&forces[0]); + plumed->cmd("setEnergy",&engconf); + plumed->cmd("setPositions",&positions[0]); + plumed->cmd("setBox",cell9); + plumed->cmd("setStopFlag",&plumedWantsToStop); + plumed->cmd("calc"); + if(plumedWantsToStop) nstep=istep; + } // remove forces if ndim<3 - if(ndim<3) - for(int iatom=0;iatom > &cvs,std::vector &pmin,std::vector &pmax, bool &multivariate, string &lowI_, string &uppI_); }; -void CLToolSumHills::registerKeywords( Keywords& keys ){ +void CLToolSumHills::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.addFlag("--help-debug",false,"print special options that can be used to create regtests"); keys.add("optional","--hills","specify the name of the hills file"); @@ -219,21 +219,21 @@ void CLToolSumHills::registerKeywords( Keywords& keys ){ } CLToolSumHills::CLToolSumHills(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { - inputdata=commandline; + inputdata=commandline; } -string CLToolSumHills::description()const{ return "sum the hills with plumed"; } +string CLToolSumHills::description()const { return "sum the hills with plumed"; } + +int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc) { -int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ - -// Read the hills input file name - vector hillsFiles; +// Read the hills input file name + vector hillsFiles; bool dohills; dohills=parseVector("--hills",hillsFiles); // Read the histogram file - vector histoFiles; + vector histoFiles; bool dohisto; dohisto=parseVector("--histo",histoFiles); @@ -243,44 +243,44 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ vector vpmin; vector vpmax; string lowI_, uppI_; - if(dohills){ - // parse it as it was a restart - bool vmultivariate; - findCvsAndPeriodic(hillsFiles[0], vcvs, vpmin, vpmax, vmultivariate, lowI_, uppI_); + if(dohills) { + // parse it as it was a restart + bool vmultivariate; + findCvsAndPeriodic(hillsFiles[0], vcvs, vpmin, vpmax, vmultivariate, lowI_, uppI_); } vector< vector > hcvs; vector hpmin; vector hpmax; - - vector sigma; - if(dohisto){ - bool hmultivariate; - findCvsAndPeriodic(histoFiles[0], hcvs, hpmin, hpmax, hmultivariate, lowI_, uppI_); - // here need also the vector of sigmas - parseVector("--sigma",sigma); - if(sigma.size()==0)plumed_merror("you should define --sigma vector when using histogram"); - lowI_=uppI_="-1."; // Interval is not use for histograms + + vector sigma; + if(dohisto) { + bool hmultivariate; + findCvsAndPeriodic(histoFiles[0], hcvs, hpmin, hpmax, hmultivariate, lowI_, uppI_); + // here need also the vector of sigmas + parseVector("--sigma",sigma); + if(sigma.size()==0)plumed_merror("you should define --sigma vector when using histogram"); + lowI_=uppI_="-1."; // Interval is not use for histograms } - if(dohisto && dohills){ - plumed_massert(vcvs==hcvs,"variables for histogram and bias should have the same labels"); - plumed_massert(hpmin==vpmin,"variables for histogram and bias should have the same min for periodicity"); - plumed_massert(hpmax==vpmax,"variables for histogram and bias should have the same max for periodicity"); + if(dohisto && dohills) { + plumed_massert(vcvs==hcvs,"variables for histogram and bias should have the same labels"); + plumed_massert(hpmin==vpmin,"variables for histogram and bias should have the same min for periodicity"); + plumed_massert(hpmax==vpmax,"variables for histogram and bias should have the same max for periodicity"); } - // now put into a neutral vector - + // now put into a neutral vector + vector< vector > cvs; vector pmin; vector pmax; - if(dohills){ + if(dohills) { cvs=vcvs; pmin=vpmin; pmax=vpmax; } - if(dohisto){ + if(dohisto) { cvs=hcvs; pmin=hpmin; pmax=hpmax; @@ -288,32 +288,32 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ // setup grids - unsigned grid_check=0; + unsigned grid_check=0; vector gmin(cvs.size()); - if(parseVector("--min",gmin)){ - if(gmin.size()!=cvs.size() && gmin.size()!=0) plumed_merror("not enough values for --min"); - grid_check++; + if(parseVector("--min",gmin)) { + if(gmin.size()!=cvs.size() && gmin.size()!=0) plumed_merror("not enough values for --min"); + grid_check++; } vector gmax(cvs.size() ); - if(parseVector("--max",gmax)){ - if(gmax.size()!=cvs.size() && gmax.size()!=0) plumed_merror("not enough values for --max"); - grid_check++; + if(parseVector("--max",gmax)) { + if(gmax.size()!=cvs.size() && gmax.size()!=0) plumed_merror("not enough values for --max"); + grid_check++; } vector gbin(cvs.size()); - bool grid_has_bin; grid_has_bin=false; - if(parseVector("--bin",gbin)){ - if(gbin.size()!=cvs.size() && gbin.size()!=0) plumed_merror("not enough values for --bin"); - grid_has_bin=true; + bool grid_has_bin; grid_has_bin=false; + if(parseVector("--bin",gbin)) { + if(gbin.size()!=cvs.size() && gbin.size()!=0) plumed_merror("not enough values for --bin"); + grid_has_bin=true; } vector gspacing(cvs.size()); - bool grid_has_spacing; grid_has_spacing=false; - if(parseVector("--spacing",gspacing)){ - if(gspacing.size()!=cvs.size() && gspacing.size()!=0) plumed_merror("not enough values for --spacing"); - grid_has_spacing=true; + bool grid_has_spacing; grid_has_spacing=false; + if(parseVector("--spacing",gspacing)) { + if(gspacing.size()!=cvs.size() && gspacing.size()!=0) plumed_merror("not enough values for --spacing"); + grid_has_spacing=true; } // allowed: no grids only bin - // not allowed: partial grid definition - plumed_massert( gmin.size()==gmax.size() && (gmin.size()==0 || gmin.size()==cvs.size() ) ,"you should specify --min and --max together with same number of components"); + // not allowed: partial grid definition + plumed_massert( gmin.size()==gmax.size() && (gmin.size()==0 || gmin.size()==cvs.size() ),"you should specify --min and --max together with same number of components"); @@ -321,99 +321,99 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ std::string ss; unsigned nn=1; ss="setNatoms"; - plumed.cmd(ss,&nn); - if(Communicator::initialized()) plumed.cmd("setMPIComm",&pc.Get_comm()); - plumed.cmd("init",&nn); - vector isdone(cvs.size(),false); - for(unsigned i=0;i actioninput; - std::vector inds; - actioninput.push_back("FAKE"); - actioninput.push_back("ATOMS=1"); - actioninput.push_back("LABEL="+cvs[i][0]); - std::vector comps, periods; - if(cvs[i].size()>1){comps.push_back(cvs[i][1]);inds.push_back(i);} - periods.push_back(pmin[i]);periods.push_back(pmax[i]); - for(unsigned j=i+1;j1){ - comps.push_back(cvs[j][1]); - periods.push_back(pmin[j]);periods.push_back(pmax[j]); - isdone[j]=true; inds.push_back(j); - } - } - - } - // drain all the components - std::string addme; - if(comps.size()>0){ - addme="COMPONENTS="; - for(unsigned i=0;ipm ){ - plumed_merror("Periodicity issue : GRID_MAX value ( "+gmax[jj]+" ) is more than periodicity in HILLS file in "+cvs[jj][0]+ " ( "+pmax[jj]+" ) "); - } - } - } - } + plumed.cmd(ss,&nn); + if(Communicator::initialized()) plumed.cmd("setMPIComm",&pc.Get_comm()); + plumed.cmd("init",&nn); + vector isdone(cvs.size(),false); + for(unsigned i=0; i actioninput; + std::vector inds; + actioninput.push_back("FAKE"); + actioninput.push_back("ATOMS=1"); + actioninput.push_back("LABEL="+cvs[i][0]); + std::vector comps, periods; + if(cvs[i].size()>1) {comps.push_back(cvs[i][1]); inds.push_back(i);} + periods.push_back(pmin[i]); periods.push_back(pmax[i]); + for(unsigned j=i+1; j1) { + comps.push_back(cvs[j][1]); + periods.push_back(pmin[j]); periods.push_back(pmax[j]); + isdone[j]=true; inds.push_back(j); + } + } + + } + // drain all the components + std::string addme; + if(comps.size()>0) { + addme="COMPONENTS="; + for(unsigned i=0; ipm ) { + plumed_merror("Periodicity issue : GRID_MAX value ( "+gmax[jj]+" ) is more than periodicity in HILLS file in "+cvs[jj][0]+ " ( "+pmax[jj]+" ) "); + } + } + } + } // for(unsigned i=0;i< actioninput.size();i++){ -// cerr<<"AA "< actioninput; vector idw; - // check if the variables to be used are correct - if(parseVector("--idw",idw)){ - for(unsigned i=0;i1){ - if(idw[i]==cvs[j][0]+"."+cvs[j][1])found=true; - }else{ - if(idw[i]==cvs[j][0])found=true; - } - } - if(!found)plumed_merror("variable "+idw[i]+" is not found in the bunch of cvs: revise your --idw option" ); - } - plumed_massert( idw.size()<=cvs.size() ,"the number of variables to be integrated should be at most equal to the total number of cvs "); - // in this case you neeed a beta factor! - } + // check if the variables to be used are correct + if(parseVector("--idw",idw)) { + for(unsigned i=0; i1) { + if(idw[i]==cvs[j][0]+"."+cvs[j][1])found=true; + } else { + if(idw[i]==cvs[j][0])found=true; + } + } + if(!found)plumed_merror("variable "+idw[i]+" is not found in the bunch of cvs: revise your --idw option" ); + } + plumed_massert( idw.size()<=cvs.size(),"the number of variables to be integrated should be at most equal to the total number of cvs "); + // in this case you neeed a beta factor! + } - std::string kt; kt=std::string("1.");// assign an arbitrary value just in case that idw.size()==cvs.size() + std::string kt; kt=std::string("1.");// assign an arbitrary value just in case that idw.size()==cvs.size() if ( dohisto || idw.size()!=0 ) { - plumed_massert(parse("--kt",kt),"if you make a dimensionality reduction (--idw) or a histogram (--histo) then you need to define --kt "); + plumed_massert(parse("--kt",kt),"if you make a dimensionality reduction (--idw) or a histogram (--histo) then you need to define --kt "); } std::string addme; @@ -423,70 +423,70 @@ int CLToolSumHills::main(FILE* in,FILE*out,Communicator& pc){ // set names std::string outfile; - if(parse("--outfile",outfile)){ - actioninput.push_back("OUTHILLS="+outfile); - } + if(parse("--outfile",outfile)) { + actioninput.push_back("OUTHILLS="+outfile); + } std::string outhisto; - if(parse("--outhisto",outhisto)){ - actioninput.push_back("OUTHISTO="+outhisto); - } + if(parse("--outhisto",outhisto)) { + actioninput.push_back("OUTHISTO="+outhisto); + } addme="ARG="; - for(unsigned i=0;i<(ncv-1);i++){ - if(cvs[i].size()==1){ - addme+=std::string(cvs[i][0])+","; - }else{ - addme+=std::string(cvs[i][0])+"."+std::string(cvs[i][1])+","; - } + for(unsigned i=0; i<(ncv-1); i++) { + if(cvs[i].size()==1) { + addme+=std::string(cvs[i][0])+","; + } else { + addme+=std::string(cvs[i][0])+"."+std::string(cvs[i][1])+","; + } } - if(cvs[ncv-1].size()==1){ - addme+=std::string(cvs[ncv-1][0]); - }else{ - addme+=std::string(cvs[ncv-1][0])+"."+std::string(cvs[ncv-1][1]); + if(cvs[ncv-1].size()==1) { + addme+=std::string(cvs[ncv-1][0]); + } else { + addme+=std::string(cvs[ncv-1][0])+"."+std::string(cvs[ncv-1][1]); } actioninput.push_back(addme); //for(unsigned i=0;i< actioninput.size();i++){ - // cerr<<"AA "< > &cvs, std::vector &pmin,std::vector &pmax, bool &multivariate, string &lowI_, string &uppI_){ - IFile ifile; - ifile.allowIgnoredFields(); - std::vector fields; - if(ifile.FileExist(filename)){ - cvs.clear(); pmin.clear(); pmax.clear(); - ifile.open(filename); - ifile.scanFieldList(fields); - bool before_sigma=true; - for(unsigned i=0;i ss; - // this loop does not take into account repetitions - if(dot!=std::string::npos){ - std::string a=fields[i].substr(0,dot); - std::string name=fields[i].substr(dot+1); - ss.push_back(a); - ss.push_back(name); - cvs.push_back(ss); - }else{ - std::vector ss; - ss.push_back(fields[i]); - cvs.push_back(ss); - } - //std::cerr<<"found variable number "<1){mm=cvs.back()[0]+"."+cvs.back()[1];}else{mm=cvs.back()[0];} - if(ifile.FieldExist("min_"+mm)){ - std::string val; - ifile.scanField("min_"+mm,val); - pmin[pmin.size()-1]=val; - // std::cerr<<"found min : "< > &cvs, std::vector &pmin,std::vector &pmax, bool &multivariate, string &lowI_, string &uppI_) { + IFile ifile; + ifile.allowIgnoredFields(); + std::vector fields; + if(ifile.FileExist(filename)) { + cvs.clear(); pmin.clear(); pmax.clear(); + ifile.open(filename); + ifile.scanFieldList(fields); + bool before_sigma=true; + for(unsigned i=0; i ss; + // this loop does not take into account repetitions + if(dot!=std::string::npos) { + std::string a=fields[i].substr(0,dot); + std::string name=fields[i].substr(dot+1); + ss.push_back(a); + ss.push_back(name); + cvs.push_back(ss); + } else { + std::vector ss; + ss.push_back(fields[i]); + cvs.push_back(ss); + } + //std::cerr<<"found variable number "<1) {mm=cvs.back()[0]+"."+cvs.back()[1];} else {mm=cvs.back()[0];} + if(ifile.FieldExist("min_"+mm)) { + std::string val; + ifile.scanField("min_"+mm,val); + pmin[pmin.size()-1]=val; + // std::cerr<<"found min : "< atoms; parseAtomList("ATOMS",atoms); @@ -111,14 +111,14 @@ pbc(true) parseFlag("NOPBC",nopbc); pbc=!nopbc; - if(atoms.size()==3){ + if(atoms.size()==3) { log.printf(" between atoms %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial()); atoms.resize(4); atoms[3]=atoms[2]; atoms[2]=atoms[1]; - }else if(atoms.size()==4){ + } else if(atoms.size()==4) { log.printf(" between lines %d-%d and %d-%d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial()); - }else error("Number of specified atoms should be either 3 or 4"); + } else error("Number of specified atoms should be either 3 or 4"); if(pbc) log.printf(" using periodic boundary conditions\n"); else log.printf(" without periodic boundary conditions\n"); @@ -129,7 +129,7 @@ pbc(true) } // calculator -void Angle::calculate(){ +void Angle::calculate() { if(pbc) makeWhole(); diff --git a/src/colvar/CS2Backbone.cpp b/src/colvar/CS2Backbone.cpp index 617a5d621a..040e0dfad8 100644 --- a/src/colvar/CS2Backbone.cpp +++ b/src/colvar/CS2Backbone.cpp @@ -25,10 +25,10 @@ #define cutOnDist 0.32 // cut off distance for non-bonded pairwise forces #define cutOffNB2 cutOffNB*cutOffNB // squared buffer distance for neighbour-lists #define cutOffDist2 cutOffDist*cutOffDist -#define cutOnDist2 cutOnDist*cutOnDist +#define cutOnDist2 cutOnDist*cutOnDist #define invswitch 1.0/((cutOffDist2-cutOnDist2)*(cutOffDist2-cutOnDist2)*(cutOffDist2-cutOnDist2)) -#define cutOffDist4 cutOffDist2*cutOffDist2 -#define cutMixed cutOffDist2*cutOffDist2*cutOffDist2 -3.*cutOffDist2*cutOffDist2*cutOnDist2 +#define cutOffDist4 cutOffDist2*cutOffDist2 +#define cutMixed cutOffDist2*cutOffDist2*cutOffDist2 -3.*cutOffDist2*cutOffDist2*cutOnDist2 #include #include @@ -46,11 +46,11 @@ using namespace std; namespace PLMD { -namespace colvar{ +namespace colvar { -//+PLUMEDOC COLVAR CS2BACKBONE +//+PLUMEDOC COLVAR CS2BACKBONE /* -This collective variable calculates the backbone chemical shifts for a protein. +This collective variable calculates the backbone chemical shifts for a protein. The functional form is that of CamShift \cite Kohlhoff:2009us. The chemical shifts of the selected nuclei/residues are saved as components. Reference experimental values @@ -63,18 +63,18 @@ shift as in \cite Camilloni:2012je \cite Camilloni:2013hs (see \ref STATS and CamShift calculation is relatively heavy because it often uses a large number of atoms, in order to make it faster it is currently parallelised with \ref Openmp. -As a general rule, when using \ref CS2BACKBONE or other experimental restraints it is better to -increase the accuracy of the constraint algorithm due to the increased strain on the bonded structure. +As a general rule, when using \ref CS2BACKBONE or other experimental restraints it is better to +increase the accuracy of the constraint algorithm due to the increased strain on the bonded structure. In the case of GROMACS it is safer to use lincs-iter=2 and lincs-order=6. In general the system for which chemical shifts are calculated must be completly included in -ATOMS and a TEMPLATE pdb file for the same atoms should be provided as well in the folder DATA. -The atoms are made automatically whole unless NOPBC is used, in particular if the system is made of +ATOMS and a TEMPLATE pdb file for the same atoms should be provided as well in the folder DATA. +The atoms are made automatically whole unless NOPBC is used, in particular if the system is made of by multiple chains it is usually better to use NOPBC and make the molecule whole \ref WHOLEMOLECULES selecting an appropriate order. - + In addition to a pdb file one needs to provide a list of chemical shifts to be calculated using one -file per nucleus type (CAshifts.dat, CBshifts.dat, Cshifts.dat, Hshifts.dat, HAshifts.dat, Nshifts.dat), +file per nucleus type (CAshifts.dat, CBshifts.dat, Cshifts.dat, Hshifts.dat, HAshifts.dat, Nshifts.dat), all the six files should always be present. A chemical shift for a nucleus is calculated if a value greater than 0 is provided. For practical purposes the value can correspond to the experimental value. Residues numbers should go from 1 to N irrespectively of the numbers used in the pdb file. The first and @@ -97,19 +97,19 @@ CAshifts.dat: The default behaviour is to store the values for the active nuclei in components (ca_#, cb_#, co_#, ha_#, hn_#, nh_# and expca_#, expcb_#, expco_#, expha_#, exphn_#, exp_nh#) with NOEXP it is possible to only store the backcalculated values. - -A pdb file is needed to the generate a simple topology of the protein. For histidines in protonation -states different from D the HIE/HSE HIP/HSP name should be used. GLH and ASH can be used for the alternative + +A pdb file is needed to the generate a simple topology of the protein. For histidines in protonation +states different from D the HIE/HSE HIP/HSP name should be used. GLH and ASH can be used for the alternative protonation of GLU and ASP. Non-standard amino acids and other molecules are not yet supported, but in principle -they can be named UNK. If multiple chains are present the chain identifier must be in the standard PDB format, -together with the TER keyword at the end of each chain. +they can be named UNK. If multiple chains are present the chain identifier must be in the standard PDB format, +together with the TER keyword at the end of each chain. One more standard file is also needed in the folder DATA: camshift.db. This file includes all the CamShift parameters -and can be found in regtest/basic/rt45/data/ . +and can be found in regtest/basic/rt45/data/ . -All the above files must be in a single folder that must be specified with the keyword DATA. +All the above files must be in a single folder that must be specified with the keyword DATA. -Additional material and examples can be also found in the tutorial \ref belfast-9 +Additional material and examples can be also found in the tutorial \ref belfast-9 \par Examples @@ -119,15 +119,15 @@ in NMR driven Metadynamics \cite Granata:2013dk : \verbatim whole: GROUP ATOMS=2612-2514:-1,961-1:-1,2466-962:-1,2513-2467:-1 WHOLEMOLECULES ENTITY0=whole -cs: CS2BACKBONE ATOMS=1-2612 NRES=176 DATA=../data/ TEMPLATE=template.pdb CAMSHIFT NOPBC +cs: CS2BACKBONE ATOMS=1-2612 NRES=176 DATA=../data/ TEMPLATE=template.pdb CAMSHIFT NOPBC metad: METAD ARG=cs HEIGHT=0.5 SIGMA=0.1 PACE=200 BIASFACTOR=10 -PRINT ARG=cs,metad.bias FILE=COLVAR STRIDE=100 +PRINT ARG=cs,metad.bias FILE=COLVAR STRIDE=100 \endverbatim -In this second example the chemical shifts are used as replica-averaged restrained as in \cite Camilloni:2012je \cite Camilloni:2013hs. - +In this second example the chemical shifts are used as replica-averaged restrained as in \cite Camilloni:2012je \cite Camilloni:2013hs. + \verbatim -cs: CS2BACKBONE ATOMS=1-174 DATA=data/ NRES=13 +cs: CS2BACKBONE ATOMS=1-174 DATA=data/ NRES=13 encs: ENSEMBLE ARG=(cs\.hn_.*),(cs\.nh_.*) stcs: STATS ARG=encs.* SQDEVSUM PARARG=(cs\.exphn_.*),(cs\.expnh_.*) RESTRAINT ARG=stcs.sqdevsum AT=0 KAPPA=0 SLOPE=24 @@ -166,13 +166,13 @@ class CS2BackboneDB { public: - inline unsigned kind(const string &s){ + inline unsigned kind(const string &s) { if(s=="GLY") return GLY; - else if(s=="PRO") return PRO; + else if(s=="PRO") return PRO; return STD; } - inline unsigned atom_kind(const string &s){ + inline unsigned atom_kind(const string &s) { if(s=="HA")return HA_ATOM; else if(s=="H") return H_ATOM; else if(s=="N") return N_ATOM; @@ -188,17 +188,17 @@ class CS2BackboneDB { inline double * CONSTAACURR(const unsigned a_kind, const unsigned at_kind) {return c_aa[a_kind][at_kind];} inline double * CONSTAANEXT(const unsigned a_kind, const unsigned at_kind) {return c_aa_succ[a_kind][at_kind];} inline double * CONSTAAPREV(const unsigned a_kind, const unsigned at_kind) {return c_aa_prev[a_kind][at_kind];} - inline double * CONST_BB2_PREV(const unsigned a_kind, const unsigned at_kind){return co_bb[a_kind][at_kind];} - inline double * CONST_BB2_CURR(const unsigned a_kind, const unsigned at_kind){return co_bb[a_kind][at_kind]+5;} - inline double * CONST_BB2_NEXT(const unsigned a_kind, const unsigned at_kind){return co_bb[a_kind][at_kind]+11;} - inline double * CONST_SC2(const unsigned a_kind, const unsigned at_kind, unsigned res_type){ return co_sc_[a_kind][at_kind][res_type];} - inline double * CONST_XD(const unsigned a_kind, const unsigned at_kind){ return co_xd[a_kind][at_kind];} - inline double * CO_SPHERE(const unsigned a_kind, const unsigned at_kind, unsigned exp_type){ return co_sphere[a_kind][at_kind][exp_type];} - inline double * CO_RING(const unsigned a_kind, const unsigned at_kind){ return co_ring[a_kind][at_kind];} - inline double * CO_DA(const unsigned a_kind, const unsigned at_kind){ return co_da[a_kind][at_kind];} - inline double * PARS_DA(const unsigned a_kind, const unsigned at_kind, const unsigned ang_kind){ return pars_da[a_kind][at_kind][ang_kind];} - - void parse(const string &file, const double dscale){ + inline double * CONST_BB2_PREV(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind];} + inline double * CONST_BB2_CURR(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind]+5;} + inline double * CONST_BB2_NEXT(const unsigned a_kind, const unsigned at_kind) {return co_bb[a_kind][at_kind]+11;} + inline double * CONST_SC2(const unsigned a_kind, const unsigned at_kind, unsigned res_type) { return co_sc_[a_kind][at_kind][res_type];} + inline double * CONST_XD(const unsigned a_kind, const unsigned at_kind) { return co_xd[a_kind][at_kind];} + inline double * CO_SPHERE(const unsigned a_kind, const unsigned at_kind, unsigned exp_type) { return co_sphere[a_kind][at_kind][exp_type];} + inline double * CO_RING(const unsigned a_kind, const unsigned at_kind) { return co_ring[a_kind][at_kind];} + inline double * CO_DA(const unsigned a_kind, const unsigned at_kind) { return co_da[a_kind][at_kind];} + inline double * PARS_DA(const unsigned a_kind, const unsigned at_kind, const unsigned ang_kind) { return pars_da[a_kind][at_kind][ang_kind];} + + void parse(const string &file, const double dscale) { ifstream in; in.open(file.c_str()); if(!in) plumed_merror("Unable to open CS2Backbone DB file " +file); @@ -207,24 +207,24 @@ class CS2BackboneDB { unsigned c_atom = 0; unsigned nline = 0; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<6;j++) { - for(unsigned k=0;k<20;k++) { - c_aa[i][j][k]=0.; - c_aa_prev[i][j][k]=0.; - c_aa_succ[i][j][k]=0.; - for(unsigned m=0;m<20;m++) co_sc_[i][j][k][m]=0.; - } - for(unsigned k=0;k<16;k++) {co_bb[i][j][k]=0.; } - for(unsigned k=0;k<8;k++) { co_sphere[i][j][0][k]=0.; co_sphere[i][j][1][k]=0.; } - for(unsigned k=0;k<3;k++) { - co_da[i][j][k]=0.; - for(unsigned l=0;l<5;l++) pars_da[i][j][k][l]=0.; + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<6; j++) { + for(unsigned k=0; k<20; k++) { + c_aa[i][j][k]=0.; + c_aa_prev[i][j][k]=0.; + c_aa_succ[i][j][k]=0.; + for(unsigned m=0; m<20; m++) co_sc_[i][j][k][m]=0.; + } + for(unsigned k=0; k<16; k++) {co_bb[i][j][k]=0.; } + for(unsigned k=0; k<8; k++) { co_sphere[i][j][0][k]=0.; co_sphere[i][j][1][k]=0.; } + for(unsigned k=0; k<3; k++) { + co_da[i][j][k]=0.; + for(unsigned l=0; l<5; l++) pars_da[i][j][k][l]=0.; + } + for(unsigned k=0; k<5; k++) co_ring[i][j][k]=0.; + for(unsigned k=0; k tok; vector tmp; tok = split(line,' '); - for(unsigned q=0;q & v, const double scale){ - for(unsigned i=1;i & v, const double scale) { + for(unsigned i=1; i dd0, dd10, dd21, dd2; - Fragment() { + Fragment() { comp.resize(6); exp_cs.resize(6,0); res_type_prev = res_type_curr = res_type_next = 0; res_kind = 0; fd = 0; - res_name = ""; + res_name = ""; pos.resize(6,-1); prev.reserve(5); curr.reserve(6); next.reserve(5); side_chain.reserve(20); - xd1.reserve(27); - xd2.reserve(27); + xd1.reserve(27); + xd2.reserve(27); box_nb.reserve(250); phi.reserve(4); psi.reserve(4); chi1.reserve(4); t_phi = t_psi = t_chi1 = 0; - dd0.resize(3); - dd10.resize(3); - dd21.resize(3); - dd2.resize(3); + dd0.resize(3); + dd10.resize(3); + dd21.resize(3); + dd2.resize(3); } }; - struct RingInfo{ + struct RingInfo { enum {R_PHE, R_TYR, R_TRP1, R_TRP2, R_HIS}; unsigned rtype; // one out of five different types unsigned atom[6]; // up to six member per ring @@ -451,7 +453,7 @@ class CS2Backbone : public Colvar { RingInfo(): rtype(0),numAtoms(0), lengthN2(NAN),lengthNV(NAN) - {for(unsigned i=0;i<6;i++) atom[i]=0;} + {for(unsigned i=0; i<6; i++) atom[i]=0;} }; enum aa_t {ALA, ARG, ASN, ASP, CYS, GLN, GLU, GLY, HIS, ILE, LEU, LYS, MET, PHE, PRO, SER, THR, TRP, TYR, VAL, UNK}; @@ -496,7 +498,7 @@ class CS2Backbone : public Colvar { PLUMED_REGISTER_ACTION(CS2Backbone,"CS2BACKBONE") -void CS2Backbone::registerKeywords( Keywords& keys ){ +void CS2Backbone::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); useCustomisableComponents(keys); @@ -505,26 +507,26 @@ void CS2Backbone::registerKeywords( Keywords& keys ){ keys.add("compulsory","TEMPLATE","template.pdb","A PDB file of the protein system to initialise ALMOST."); keys.add("compulsory","NEIGH_FREQ","20","Period in step for neighbour list update."); keys.add("compulsory","NRES","Number of residues, corresponding to the number of chemical shifts."); - keys.addFlag("CAMSHIFT",false,"Set to TRUE if you to calculate a single CamShift score."); - keys.addFlag("NOEXP",false,"Set to TRUE if you don't want to have fixed components with the experimetnal values."); - keys.addOutputComponent("ha","default","the calculated Ha hydrogen chemical shifts"); - keys.addOutputComponent("hn","default","the calculated H hydrogen chemical shifts"); - keys.addOutputComponent("nh","default","the calculated N nitrogen chemical shifts"); - keys.addOutputComponent("ca","default","the calculated Ca carbon chemical shifts"); - keys.addOutputComponent("cb","default","the calculated Cb carbon chemical shifts"); - keys.addOutputComponent("co","default","the calculated C' carbon chemical shifts"); - keys.addOutputComponent("expha","default","the experimental Ha hydrogen chemical shifts"); - keys.addOutputComponent("exphn","default","the experimental H hydrogen chemical shifts"); - keys.addOutputComponent("expnh","default","the experimental N nitrogen chemical shifts"); - keys.addOutputComponent("expca","default","the experimental Ca carbon chemical shifts"); - keys.addOutputComponent("expcb","default","the experimental Cb carbon chemical shifts"); - keys.addOutputComponent("expco","default","the experimental C' carbon chemical shifts"); + keys.addFlag("CAMSHIFT",false,"Set to TRUE if you to calculate a single CamShift score."); + keys.addFlag("NOEXP",false,"Set to TRUE if you don't want to have fixed components with the experimetnal values."); + keys.addOutputComponent("ha","default","the calculated Ha hydrogen chemical shifts"); + keys.addOutputComponent("hn","default","the calculated H hydrogen chemical shifts"); + keys.addOutputComponent("nh","default","the calculated N nitrogen chemical shifts"); + keys.addOutputComponent("ca","default","the calculated Ca carbon chemical shifts"); + keys.addOutputComponent("cb","default","the calculated Cb carbon chemical shifts"); + keys.addOutputComponent("co","default","the calculated C' carbon chemical shifts"); + keys.addOutputComponent("expha","default","the experimental Ha hydrogen chemical shifts"); + keys.addOutputComponent("exphn","default","the experimental H hydrogen chemical shifts"); + keys.addOutputComponent("expnh","default","the experimental N nitrogen chemical shifts"); + keys.addOutputComponent("expca","default","the experimental Ca carbon chemical shifts"); + keys.addOutputComponent("expcb","default","the experimental Cb carbon chemical shifts"); + keys.addOutputComponent("expco","default","the experimental C' carbon chemical shifts"); } CS2Backbone::CS2Backbone(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -camshift(false), -pbc(true) + PLUMED_COLVAR_INIT(ao), + camshift(false), + pbc(true) { string stringadb; string stringapdb; @@ -561,7 +563,7 @@ pbc(true) } log.printf(" Initialization of the predictor ...\n"); log.flush(); - db.parse(stringadb,scale); + db.parse(stringadb,scale); PDB pdb; if( !pdb.read(stringapdb,plumed.getAtoms().usingNaturalUnits(),1./scale) ) error("missing input file " + stringapdb); init_backbone(pdb); @@ -595,18 +597,18 @@ pbc(true) /* this is a workaround for those chemical shifts that can result in too large forces */ remove_problematic("GLN", "CB"); remove_problematic("ILE", "CB"); - remove_problematic("PRO", "N"); + remove_problematic("PRO", "N"); remove_problematic("PRO", "H"); remove_problematic("PRO", "CB"); remove_problematic("GLY", "HA"); remove_problematic("GLY", "CB"); /* this is a workaround for those chemical shifts that are not parameterized */ remove_problematic("HIE", "HA"); remove_problematic("HIP", "HA"); remove_problematic("HSP", "HA"); - remove_problematic("HIE", "H"); remove_problematic("HIP", "H"); remove_problematic("HSP", "H"); - remove_problematic("HIE", "N"); remove_problematic("HIP", "N"); remove_problematic("HSP", "N"); + remove_problematic("HIE", "H"); remove_problematic("HIP", "H"); remove_problematic("HSP", "H"); + remove_problematic("HIE", "N"); remove_problematic("HIP", "N"); remove_problematic("HSP", "N"); remove_problematic("HIE", "CA"); remove_problematic("HIP", "CA"); remove_problematic("HSP", "CA"); remove_problematic("HIE", "CB"); remove_problematic("HIP", "CB"); remove_problematic("HSP", "CB"); - remove_problematic("HIE", "C"); remove_problematic("HIP", "C"); remove_problematic("HSP", "C"); + remove_problematic("HIE", "C"); remove_problematic("HIP", "C"); remove_problematic("HSP", "C"); remove_problematic("GLH", "HA"); remove_problematic("ASH", "HA"); remove_problematic("HSE", "HA"); remove_problematic("GLH", "H"); remove_problematic("ASH", "H"); remove_problematic("HSE", "H"); remove_problematic("GLH", "N"); remove_problematic("ASH", "N"); remove_problematic("HSE", "N"); @@ -646,11 +648,11 @@ pbc(true) unsigned index=0; if(camshift) noexp = true; if(!camshift) { - for(unsigned i=0;iset(atom[i][a].exp_cs[at_kind]); @@ -689,7 +691,7 @@ pbc(true) /* temporary check, the idea is that I can remove NRES completely */ if(index!=numResidues) error("NRES and the number of residues in the PDB do not match!"); - + requestAtoms(atoms); } @@ -703,8 +705,8 @@ void CS2Backbone::remove_problematic(const string &res, const string &nucl) { else if(nucl=="C") n=5; else return; - for(unsigned i=0;i camshift_sigma2(6); - camshift_sigma2[0] = 0.08; // HA + camshift_sigma2[0] = 0.08; // HA camshift_sigma2[1] = 0.30; // HN camshift_sigma2[2] = 9.00; // NH camshift_sigma2[3] = 1.30; // CA @@ -777,13 +779,13 @@ void CS2Backbone::calculate() // CYCLE OVER MULTIPLE CHAINS #pragma omp parallel num_threads(OpenMP::getNumThreads()) - for(unsigned s=0;s omp_deriv; if(camshift) omp_deriv.resize(getNumberOfAtoms(), Vector(0,0,0)); #pragma omp for reduction(+:score) // SKIP FIRST AND LAST RESIDUE OF EACH CHAIN - for(unsigned a=1;ares_kind; @@ -796,7 +798,7 @@ void CS2Backbone::calculate() const unsigned xdsize=myfrag->xd1.size(); vector ext_distances(xdsize); vector ext_d(xdsize); - for(unsigned q=0;qxd1[q]==-1||myfrag->xd2[q]==-1) continue; const Vector distance = delta(getPosition(myfrag->xd1[q]),getPosition(myfrag->xd2[q])); ext_d[q] = distance.modulo(); @@ -804,30 +806,30 @@ void CS2Backbone::calculate() } // CYCLE OVER THE SIX BACKBONE CHEMICAL SHIFTS - for(unsigned at_kind=0;at_kind<6;at_kind++){ - if(atom[s][a].exp_cs[at_kind]!=0){ + for(unsigned at_kind=0; at_kind<6; at_kind++) { + if(atom[s][a].exp_cs[at_kind]!=0) { // Common constant and AATYPE const double * CONSTAACURR = db.CONSTAACURR(aa_kind,at_kind); const double * CONSTAANEXT = db.CONSTAANEXT(aa_kind,at_kind); const double * CONSTAAPREV = db.CONSTAAPREV(aa_kind,at_kind); - double cs = CONSTAACURR[res_type_curr] + - CONSTAANEXT[res_type_next] + + double cs = CONSTAACURR[res_type_curr] + + CONSTAANEXT[res_type_next] + CONSTAAPREV[res_type_prev]; - // this is the atom for which we are calculating the chemical shift + // this is the atom for which we are calculating the chemical shift const unsigned ipos = myfrag->pos[at_kind]; vector list; list.reserve(needed_atoms); list.push_back(ipos); vector ff; - ff.reserve(needed_atoms); + ff.reserve(needed_atoms); ff.push_back(Vector(0,0,0)); //PREV const double * CONST_BB2_PREV = db.CONST_BB2_PREV(aa_kind,at_kind); const unsigned presize = myfrag->prev.size(); - for(unsigned q=0;qprev[q]; @@ -845,7 +847,7 @@ void CS2Backbone::calculate() //CURR const double * CONST_BB2_CURR = db.CONST_BB2_CURR(aa_kind,at_kind); const unsigned cursize = myfrag->curr.size(); - for(unsigned q=0;qcurr[q]; @@ -864,8 +866,8 @@ void CS2Backbone::calculate() //NEXT const double * CONST_BB2_NEXT = db.CONST_BB2_NEXT(aa_kind,at_kind); const unsigned nexsize = myfrag->next.size(); - for(unsigned q=0;qnext[q]; list.push_back(jpos); @@ -882,8 +884,8 @@ void CS2Backbone::calculate() //SIDE CHAIN const double * CONST_SC2 = db.CONST_SC2(aa_kind,at_kind,res_type_curr); const unsigned sidsize = myfrag->side_chain.size(); - for(unsigned q=0;qside_chain[q]; if(ipos==jpos) continue; @@ -897,10 +899,10 @@ void CS2Backbone::calculate() ff[0] += der; ff.push_back(-der); } - + //EXTRA DIST const double * CONST_XD = db.CONST_XD(aa_kind,at_kind); - for(unsigned q=0;qxd1[q]==-1||myfrag->xd2[q]==-1) continue; @@ -911,7 +913,7 @@ void CS2Backbone::calculate() ff.push_back( der); ff.push_back(-der); } - + //NON BOND { const double * CONST_CO_SPHERE3 = db.CO_SPHERE(aa_kind,at_kind,0); @@ -921,22 +923,22 @@ void CS2Backbone::calculate() const unsigned jpos = myfrag->box_nb[bat]; const Vector distance = delta(getPosition(jpos),getPosition(ipos)); const double d2 = distance.modulo2(); - + if(d2cutOnDist2) { const double af = cutOffDist2 - d2; const double bf = cutOffDist2 - 3.*cutOnDist2 + 2.*d2; - const double cf = invswitch*af; + const double cf = invswitch*af; const double df = cf*af*bf; - factor1 *= df; + factor1 *= df; factor3 *= df; - const double d4 = d2*d2; + const double d4 = d2*d2; const double af1 = 15.*cutOnDist2*d2; const double bf1 = -14.*d4; const double cf1 = -3.*cutOffDist2*cutOnDist2 + cutOffDist2*d2; @@ -950,14 +952,14 @@ void CS2Backbone::calculate() dfactor3 *= invswitch*(cutMixed+df3); } - const unsigned t = type[jpos]; + const unsigned t = type[jpos]; cs += factor1*CONST_CO_SPHERE[t] + factor3*CONST_CO_SPHERE3[t] ; - const double fact = dfactor1*CONST_CO_SPHERE[t]+dfactor3*CONST_CO_SPHERE3[t]; + const double fact = dfactor1*CONST_CO_SPHERE[t]+dfactor3*CONST_CO_SPHERE3[t]; const Vector der = fact*distance; list.push_back(jpos); ff[0] += der; - ff.push_back(-der); + ff.push_back(-der); } } } @@ -967,64 +969,64 @@ void CS2Backbone::calculate() { const double *rc = db.CO_RING(aa_kind,at_kind); const unsigned rsize = ringInfo.size(); - for(unsigned i=0; iphi.size()==4){ - const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,0); + if(myfrag->phi.size()==4) { + const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,0); const double val1 = 3.*myfrag->t_phi+PARS_DA[3]; const double val2 = myfrag->t_phi+PARS_DA[4]; - cs += CO_DA[0]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); + cs += CO_DA[0]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); const double fact = -CO_DA[0]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2)); ff.push_back(fact*myfrag->dd0[0]); @@ -1054,11 +1056,11 @@ void CS2Backbone::calculate() list.push_back(myfrag->phi[3]); } - if(myfrag->psi.size()==4){ - const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,1); + if(myfrag->psi.size()==4) { + const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,1); const double val1 = 3.*myfrag->t_psi+PARS_DA[3]; const double val2 = myfrag->t_psi+PARS_DA[4]; - cs += CO_DA[1]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); + cs += CO_DA[1]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); const double fact = -CO_DA[1]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2)); ff.push_back(fact*myfrag->dd0[1]); @@ -1072,11 +1074,11 @@ void CS2Backbone::calculate() } //Chi - if(myfrag->chi1.size()==4){ - const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,2); + if(myfrag->chi1.size()==4) { + const double *PARS_DA = db.PARS_DA(aa_kind,at_kind,2); const double val1 = 3.*myfrag->t_chi1+PARS_DA[3]; const double val2 = myfrag->t_chi1+PARS_DA[4]; - cs += CO_DA[2]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); + cs += CO_DA[2]*(PARS_DA[0]*cos(val1)+PARS_DA[1]*cos(val2)+PARS_DA[2]); const double fact = -CO_DA[2]*(+3.*PARS_DA[0]*sin(val1)+PARS_DA[1]*sin(val2)); ff.push_back(fact*myfrag->dd0[2]); @@ -1093,13 +1095,13 @@ void CS2Backbone::calculate() Value * comp; double fact = 1.0; - if(!camshift) { + if(!camshift) { comp = atom[s][a].comp[at_kind]; comp->set(cs); Tensor virial; - for(unsigned i=0;i(res_curr-res_num[bat])); if(res_dist<2) continue; - for(unsigned at_kind=0;at_kind<6; at_kind++) { + for(unsigned at_kind=0; at_kind<6; at_kind++) { if(atom[s][a].exp_cs[at_kind]==0.) continue; - const unsigned ipos = atom[s][a].pos[at_kind]; + const unsigned ipos = atom[s][a].pos[at_kind]; const Vector distance = delta(getPosition(bat),getPosition(ipos)); const double d2=distance.modulo2(); - if(d2phi.size()==4){ + if(myfrag->phi.size()==4) { const Vector d0 = delta(getPosition(myfrag->phi[1]), getPosition(myfrag->phi[0])); const Vector d1 = delta(getPosition(myfrag->phi[2]), getPosition(myfrag->phi[1])); const Vector d2 = delta(getPosition(myfrag->phi[3]), getPosition(myfrag->phi[2])); @@ -1223,7 +1225,7 @@ void CS2Backbone::compute_dihedrals(){ atom[s][a].dd21[0] = dd2-dd1; atom[s][a].dd2[0] = dd2; } - if(myfrag->psi.size()==4){ + if(myfrag->psi.size()==4) { const Vector d0 = delta(getPosition(myfrag->psi[1]), getPosition(myfrag->psi[0])); const Vector d1 = delta(getPosition(myfrag->psi[2]), getPosition(myfrag->psi[1])); const Vector d2 = delta(getPosition(myfrag->psi[3]), getPosition(myfrag->psi[2])); @@ -1235,7 +1237,7 @@ void CS2Backbone::compute_dihedrals(){ atom[s][a].dd21[1] = dd2-dd1; atom[s][a].dd2[1] = dd2; } - if(myfrag->chi1.size()==4){ + if(myfrag->chi1.size()==4) { const Vector d0 = delta(getPosition(myfrag->chi1[1]), getPosition(myfrag->chi1[0])); const Vector d1 = delta(getPosition(myfrag->chi1[2]), getPosition(myfrag->chi1[1])); const Vector d2 = delta(getPosition(myfrag->chi1[3]), getPosition(myfrag->chi1[2])); @@ -1251,14 +1253,14 @@ void CS2Backbone::compute_dihedrals(){ } } -void CS2Backbone::init_backbone(const PDB &pdb){ +void CS2Backbone::init_backbone(const PDB &pdb) { // number of chains vector chains; pdb.getChainNames( chains ); seg_last.resize(chains.size()); unsigned old_size=0; - for(unsigned i=0;i allatoms = pdb.getAtomsInChain(chains[i]); // cycle over all the atoms in the chain - for(unsigned a=0;a atm_; - // cycle over all residues in the chain - for(unsigned a=start;a<=end;a++){ + // cycle over all residues in the chain + for(unsigned a=start; a<=end; a++) { unsigned f_idx = a - res_offset; Fragment at; at.pos[0] = HA_[f_idx]; @@ -1319,17 +1321,17 @@ void CS2Backbone::init_backbone(const PDB &pdb){ at.pos[4] = CB_[f_idx]; at.pos[5] = C_[f_idx]; at.res_type_prev = at.res_type_curr = at.res_type_next = 0; - at.res_name = pdb.getResidueName(a, chains[i]); + at.res_name = pdb.getResidueName(a, chains[i]); at.res_kind = db.kind(at.res_name); at.fd = a; //REGISTER PREV CURR NEXT { - if(a>start){ + if(a>start) { at.prev.push_back( N_[f_idx-1]); at.prev.push_back(CA_[f_idx-1]); at.prev.push_back(HA_[f_idx-1]); at.prev.push_back( C_[f_idx-1]); - at.prev.push_back( O_[f_idx-1]); + at.prev.push_back( O_[f_idx-1]); at.res_type_prev = frag2enum(pdb.getResidueName(a-1, chains[i])); } @@ -1338,10 +1340,10 @@ void CS2Backbone::init_backbone(const PDB &pdb){ at.curr.push_back(CA_[f_idx]); at.curr.push_back(HA_[f_idx]); at.curr.push_back( C_[f_idx]); - at.curr.push_back( O_[f_idx]); + at.curr.push_back( O_[f_idx]); at.res_type_curr = frag2enum(pdb.getResidueName(a, chains[i])); - if(astart){ + if(a>start) { at.phi.push_back( C_[f_idx-1]); at.phi.push_back( N_[f_idx]); at.phi.push_back(CA_[f_idx]); at.phi.push_back( C_[f_idx]); } - - if(a chains; +void CS2Backbone::init_sidechain(const PDB &pdb) { + vector chains; pdb.getChainNames( chains ); unsigned old_size=0; // cycle over chains - for(unsigned s=0; s atm = pdb.getAtomsInResidue(atom[s][a].fd, chains[s]); vector sc_atm = side_chain_atoms(atom[s][a].res_name); - for(unsigned sc=0;sc chains; + vector chains; pdb.getChainNames( chains ); unsigned old_size=0; - for(unsigned s=0; s atm_curr = pdb.getAtomsInResidue(atom[s][a].fd,chains[s]); vector atm_prev = pdb.getAtomsInResidue(atom[s][a].fd-1,chains[s]); vector atm_next = pdb.getAtomsInResidue(atom[s][a].fd+1,chains[s]); - for(unsigned q=0;q::iterator at1, at1_end; vector::iterator at2, at2_end; @@ -1449,37 +1454,37 @@ void CS2Backbone::init_xdist(const PDB &pdb){ bool init_p2=false; AtomNumber p2; - if(resOffsetP1[q]== 0){ at1 = atm_curr.begin(); at1_end = atm_curr.end();} - if(resOffsetP1[q]==-1){ at1 = atm_prev.begin(); at1_end = atm_prev.end();} - if(resOffsetP1[q]==+1){ at1 = atm_next.begin(); at1_end = atm_next.end();} - while(at1!=at1_end){ + if(resOffsetP1[q]== 0) { at1 = atm_curr.begin(); at1_end = atm_curr.end();} + if(resOffsetP1[q]==-1) { at1 = atm_prev.begin(); at1_end = atm_prev.end();} + if(resOffsetP1[q]==+1) { at1 = atm_next.begin(); at1_end = atm_next.end();} + while(at1!=at1_end) { AtomNumber aa = *at1; ++at1; string name = pdb.getAtomName(aa); xdist_name_map(name); - if(name==atomsP1[q]){ - p1 = aa; + if(name==atomsP1[q]) { + p1 = aa; init_p1=true; - break; + break; } } - if(resOffsetP2[q]== 0){ at2 = atm_curr.begin(); at2_end = atm_curr.end();} - if(resOffsetP2[q]==-1){ at2 = atm_prev.begin(); at2_end = atm_prev.end();} - if(resOffsetP2[q]==+1){ at2 = atm_next.begin(); at2_end = atm_next.end();} - while(at2!=at2_end){ + if(resOffsetP2[q]== 0) { at2 = atm_curr.begin(); at2_end = atm_curr.end();} + if(resOffsetP2[q]==-1) { at2 = atm_prev.begin(); at2_end = atm_prev.end();} + if(resOffsetP2[q]==+1) { at2 = atm_next.begin(); at2_end = atm_next.end();} + while(at2!=at2_end) { AtomNumber aa = *at2; ++at2; string name = pdb.getAtomName(aa); xdist_name_map(name); - if(name==atomsP2[q]){ - p2 = aa; + if(name==atomsP2[q]) { + p2 = aa; init_p2=true; - break; + break; } } int add1 = -1; @@ -1490,13 +1495,13 @@ void CS2Backbone::init_xdist(const PDB &pdb){ atom[s][a].xd2.push_back(add2); } } - old_size += aend.index()+1; + old_size += aend.index()+1; } } -void CS2Backbone::init_types(const PDB &pdb){ +void CS2Backbone::init_types(const PDB &pdb) { vector aa = pdb.getAtomNumbers(); - for(unsigned i=0;i chains; + vector chains; pdb.getChainNames( chains ); vector allatoms = pdb.getAtomNumbers(); unsigned old_size=0; - for(unsigned s=0; s frg_atoms = pdb.getAtomsInResidue(atom[s][r].fd,chains[s]); - if(frg=="PHE"||frg=="TYR"){ + if(frg=="PHE"||frg=="TYR") { RingInfo ri; - for(unsigned a=0;a CS2Backbone::side_chain_atoms(const string &s){ +vector CS2Backbone::side_chain_atoms(const string &s) { vector sc; - if(s=="ALA"){ + if(s=="ALA") { sc.push_back( "CB" ); sc.push_back( "HB1" ); sc.push_back( "HB2" ); sc.push_back( "HB3" ); return sc; - } else if(s=="ARG"){ + } else if(s=="ARG") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1691,7 +1696,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "1HH2" ); sc.push_back( "2HH2" ); return sc; - } else if(s=="ASN"){ + } else if(s=="ASN") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "OD1" ); @@ -1704,7 +1709,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "1HD2" ); sc.push_back( "2HD2" ); return sc; - } else if(s=="ASP"||s=="ASH"){ + } else if(s=="ASP"||s=="ASH") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "OD1" ); @@ -1713,7 +1718,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HB2" ); sc.push_back( "HB3" ); return sc; - } else if(s=="CYS"||s=="CYM"){ + } else if(s=="CYS"||s=="CYM") { sc.push_back( "CB" ); sc.push_back( "SG" ); sc.push_back( "HB1" ); @@ -1722,7 +1727,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HG1" ); sc.push_back( "HG" ); return sc; - } else if(s=="GLN"){ + } else if(s=="GLN") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1739,7 +1744,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "1HE2" ); sc.push_back( "2HE2" ); return sc; - } else if(s=="GLU"||s=="GLH"){ + } else if(s=="GLU"||s=="GLH") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1752,10 +1757,10 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HG2" ); sc.push_back( "HG3" ); return sc; - } else if(s=="GLY"){ + } else if(s=="GLY") { sc.push_back( "HA2" ); return sc; - } else if(s=="HIS"||s=="HSE"||s=="HIE"||s=="HSD"||s=="HID"||s=="HIP"||s=="HSP"){ + } else if(s=="HIS"||s=="HSE"||s=="HIE"||s=="HSD"||s=="HID"||s=="HIP"||s=="HSP") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "ND1" ); @@ -1770,7 +1775,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE1" ); sc.push_back( "HE2" ); return sc; - } else if(s=="ILE"){ + } else if(s=="ILE") { sc.push_back( "CB" ); sc.push_back( "CG1" ); sc.push_back( "CG2" ); @@ -1790,7 +1795,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HD2" ); sc.push_back( "HD3" ); return sc; - } else if(s=="LEU"){ + } else if(s=="LEU") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1812,7 +1817,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "2HD2" ); sc.push_back( "3HD2" ); return sc; - } else if(s=="LYS"){ + } else if(s=="LYS") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1834,7 +1839,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HZ2" ); sc.push_back( "HZ3" ); return sc; - } else if(s=="MET"){ + } else if(s=="MET") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "SD" ); @@ -1849,7 +1854,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE2" ); sc.push_back( "HE3" ); return sc; - } else if(s=="PHE"){ + } else if(s=="PHE") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1868,7 +1873,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE3" ); sc.push_back( "HZ" ); return sc; - } else if(s=="PRO"){ + } else if(s=="PRO") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD" ); @@ -1882,7 +1887,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HD2" ); sc.push_back( "HD3" ); return sc; - } else if(s=="SER"){ + } else if(s=="SER") { sc.push_back( "CB" ); sc.push_back( "OG" ); sc.push_back( "HB1" ); @@ -1891,7 +1896,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HG1" ); sc.push_back( "HG" ); return sc; - } else if(s=="THR"){ + } else if(s=="THR") { sc.push_back( "CB" ); sc.push_back( "OG1" ); sc.push_back( "CG2" ); @@ -1904,7 +1909,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "2HG2" ); sc.push_back( "3HG2" ); return sc; - } else if(s=="TRP"){ + } else if(s=="TRP") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1925,7 +1930,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HZ3" ); sc.push_back( "HH2" ); return sc; - } else if(s=="TYR"){ + } else if(s=="TYR") { sc.push_back( "CB" ); sc.push_back( "CG" ); sc.push_back( "CD1" ); @@ -1945,7 +1950,7 @@ vector CS2Backbone::side_chain_atoms(const string &s){ sc.push_back( "HE3" ); sc.push_back( "HH" ); return sc; - } else if(s=="VAL"){ + } else if(s=="VAL") { sc.push_back( "CB" ); sc.push_back( "CG1" ); sc.push_back( "CG2" ); @@ -2023,7 +2028,7 @@ bool CS2Backbone::isSP2(const string & resType, const string & atomName) { else if (atomName == "CE1") sp2 = true; else if (atomName == "CE2") sp2 = true; else if (atomName == "CZ") sp2 = true; - + } else if (resType == "ASN") { if (atomName == "CG") sp2 = true; @@ -2039,7 +2044,7 @@ bool CS2Backbone::isSP2(const string & resType, const string & atomName) { return sp2; } -bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm){ +bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm) { if(atm=="CG") return true; if((frg == "CYS")&&(atm =="SG")) return true; if(((frg == "ILE")||(frg == "VAL"))&&(atm == "CG1")) return true; @@ -2049,52 +2054,52 @@ bool CS2Backbone::is_chi1_cx(const string & frg, const string & atm){ return false; } -unsigned CS2Backbone::frag_segment(const unsigned p){ +unsigned CS2Backbone::frag_segment(const unsigned p) { unsigned s = 0; - for(unsigned i=0;iseg_last[i]) s = i+1; else break; } return s; } -unsigned CS2Backbone::frag_relitive_index(const unsigned p, const unsigned s){ +unsigned CS2Backbone::frag_relitive_index(const unsigned p, const unsigned s) { if(s==0) return p; return p-seg_last[s-1]; } -void CS2Backbone::debug_report(){ +void CS2Backbone::debug_report() { printf("\t CS2Backbone Initialization report: \n"); printf("\t -------------------------------\n"); printf("\t Number of segments: %u\n", static_cast(atom.size())); printf("\t Segments size: "); - for(unsigned i=0;i(atom[i].size())); printf("\n"); + for(unsigned i=0; i(atom[i].size())); printf("\n"); printf("\t%8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s \n", - "Seg","N","AA","Prev","Curr","Next","SC","XD1","XD2","Phi","Psi","Chi1"); - for(unsigned i=0;i(ringInfo.size())); printf("\t%8s %8s %8s %8s\n", "Num","Type","RType","N.atoms"); - for(unsigned i=0;i atoms; checkRead(); @@ -80,7 +80,7 @@ PLUMED_COLVAR_INIT(ao) requestAtoms(atoms); } -void Cell::registerKeywords( Keywords& keys ){ +void Cell::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -98,13 +98,13 @@ void Cell::registerKeywords( Keywords& keys ){ // calculator -void Cell::calculate(){ +void Cell::calculate() { - for(int i=0;i<3;i++) for(int j=0;j<3;j++) components[i][j]->set(getBox()[i][j]); - for(int l=0;l<3;l++) for(int m=0;m<3;m++){ - Tensor der; for(int i=0;i<3;i++) der[i][m]=getBox()[l][i]; - setBoxDerivatives(components[l][m],-der); - } + for(int i=0; i<3; i++) for(int j=0; j<3; j++) components[i][j]->set(getBox()[i][j]); + for(int l=0; l<3; l++) for(int m=0; m<3; m++) { + Tensor der; for(int i=0; i<3; i++) der[i][m]=getBox()[l][i]; + setBoxDerivatives(components[l][m],-der); + } } } diff --git a/src/colvar/Colvar.h b/src/colvar/Colvar.h index aead24e9bd..2d8904d64d 100644 --- a/src/colvar/Colvar.h +++ b/src/colvar/Colvar.h @@ -22,11 +22,11 @@ #ifndef __PLUMED_colvar_Colvar_h #define __PLUMED_colvar_Colvar_h #include "core/Colvar.h" -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { // Ideally core/Colvar.h should be moved to this directory and Colvar should stay in namespace PLMD::colvar // With this trick, PLMD::Colvar is visible as PLMD::colvar::Colvar - using PLMD::Colvar; +using PLMD::Colvar; } } #endif diff --git a/src/colvar/Constant.cpp b/src/colvar/Constant.cpp index 15bdab0dfb..49423413df 100644 --- a/src/colvar/Constant.cpp +++ b/src/colvar/Constant.cpp @@ -27,8 +27,8 @@ #include #include -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR CONSTANT /* @@ -76,16 +76,16 @@ class Constant : public Colvar { PLUMED_REGISTER_ACTION(Constant,"CONSTANT") Constant::Constant(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { bool noderiv=false; parseFlag("NODERIV",noderiv); parseVector("VALUES",values); - if(values.size()==0){ + if(values.size()==0) { double v; parse("VALUE",v); // this checks if v is different from NAN - if(v*2!=v || v==0.0){ + if(v*2!=v || v==0.0) { values.resize(1); values[0]=v; } @@ -98,7 +98,7 @@ PLUMED_COLVAR_INIT(ao) setNotPeriodic(); setValue(values[0]); } else if(values.size()>1) { - for(unsigned i=0;iset(values[i]); } diff --git a/src/colvar/ContactMap.cpp b/src/colvar/ContactMap.cpp index 4cb1c84b93..9405f172f4 100644 --- a/src/colvar/ContactMap.cpp +++ b/src/colvar/ContactMap.cpp @@ -53,15 +53,15 @@ PRINT ARG=f1.* FILE=colvar The following example calculates the difference of the current contact map with respect to a reference provided. In this case REFERENCE is the fraction of contact that is formed (i.e. the distance between two atoms transformed with the SWITH), while R_0 is the contact -distance. WEIGHT gives the relative weight of each contact to the final distance measure. +distance. WEIGHT gives the relative weight of each contact to the final distance measure. \verbatim CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=0.1 WEIGHT1=0.5 -ATOMS2=3,4 REFERENCE2=0.5 WEIGHT2=1.0 -ATOMS3=4,5 REFERENCE3=0.25 WEIGHT3=1.0 -ATOMS4=5,6 REFERENCE4=0.0 WEIGHT4=0.5 -SWITCH={RATIONAL R_0=1.5} +ATOMS1=1,2 REFERENCE1=0.1 WEIGHT1=0.5 +ATOMS2=3,4 REFERENCE2=0.5 WEIGHT2=1.0 +ATOMS3=4,5 REFERENCE3=0.25 WEIGHT3=1.0 +ATOMS4=5,6 REFERENCE4=0.0 WEIGHT4=0.5 +SWITCH={RATIONAL R_0=1.5} LABEL=cmap CMDIST ... CONTACTMAP @@ -69,14 +69,14 @@ CMDIST PRINT ARG=cmap FILE=colvar \endverbatim -The next example calculates calculates fraction of native contacts (Q) -for Trp-cage mini-protein. R_0 is the distance at which the switch function is guaranteed to -be 1.0 – it doesn't really matter for Q and should be something very small, like 1 A. -REF is the reference distance for the contact, e.g. the distance from a crystal structure. -LAMBDA is the tolerance for the distance – if set to 1.0, the contact would have to have exactly -the reference value to be formed; instead for lambda values of 1.5–1.8 are usually used to allow some slack. -BETA is the softness of the switch function, default is 50nm. -WEIGHT is the 1/(number of contacts) giving equal weight to each contact. +The next example calculates calculates fraction of native contacts (Q) +for Trp-cage mini-protein. R_0 is the distance at which the switch function is guaranteed to +be 1.0 – it doesn't really matter for Q and should be something very small, like 1 A. +REF is the reference distance for the contact, e.g. the distance from a crystal structure. +LAMBDA is the tolerance for the distance – if set to 1.0, the contact would have to have exactly +the reference value to be formed; instead for lambda values of 1.5–1.8 are usually used to allow some slack. +BETA is the softness of the switch function, default is 50nm. +WEIGHT is the 1/(number of contacts) giving equal weight to each contact. When using native contact Q switch function, please cite \cite best2013 @@ -87,7 +87,7 @@ CONTACTMAP ... ATOMS1=1,67 SWITCH1={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.4059} WEIGHT1=0.003597 ATOMS2=1,68 SWITCH2={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.4039} WEIGHT2=0.003597 ATOMS3=1,69 SWITCH3={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.3215} WEIGHT3=0.003597 -[snip] +[snip] ATOMS275=183,213 SWITCH275={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.355} WEIGHT275=0.003597 ATOMS276=183,234 SWITCH276={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.428} WEIGHT276=0.003597 ATOMS277=183,250 SWITCH277={Q R_0=0.01 BETA=50.0 LAMBDA=1.5 REF=0.3832} WEIGHT277=0.003597 @@ -104,7 +104,7 @@ PRINT ARG=cmap FILE=colvar */ //+ENDPLUMEDOC -class ContactMap : public Colvar { +class ContactMap : public Colvar { private: bool pbc, serial, docomp, dosum, docmdist; NeighborList *nl; @@ -116,28 +116,28 @@ class ContactMap : public Colvar { ~ContactMap(); // active methods: virtual void calculate(); - void checkFieldsAllowed(){} + void checkFieldsAllowed() {} }; PLUMED_REGISTER_ACTION(ContactMap,"CONTACTMAP") -void ContactMap::registerKeywords( Keywords& keys ){ +void ContactMap::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("numbered","ATOMS","the atoms involved in each of the contacts you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one contact will be " - "calculated for each ATOM keyword you specify."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one contact will be " + "calculated for each ATOM keyword you specify."); keys.reset_style("ATOMS","atoms"); keys.add("numbered","SWITCH","The switching functions to use for each of the contacts in your map. " - "You can either specify a global switching function using SWITCH or one " - "switching function for each contact. Details of the various switching " - "functions you can use are provided on \\ref switchingfunction."); + "You can either specify a global switching function using SWITCH or one " + "switching function for each contact. Details of the various switching " + "functions you can use are provided on \\ref switchingfunction."); keys.add("numbered","REFERENCE","A reference value for a given contact, by default is 0.0 " - "You can either specify a global reference value using REFERENCE or one " - "reference value for each contact."); + "You can either specify a global reference value using REFERENCE or one " + "reference value for each contact."); keys.add("numbered","WEIGHT","A weight value for a given contact, by default is 1.0 " - "You can either specify a global weight value using WEIGHT or one " - "weight value for each contact."); - keys.reset_style("SWITCH","compulsory"); + "You can either specify a global weight value using WEIGHT or one " + "weight value for each contact."); + keys.reset_style("SWITCH","compulsory"); keys.addFlag("SUM",false,"calculate the sum of all the contacts in the input"); keys.addFlag("CMDIST",false,"calculate the distance with respect to the provided reference contant map"); keys.addFlag("SERIAL",false,"Perform the calculation in serial - for debug purpose"); @@ -145,12 +145,12 @@ void ContactMap::registerKeywords( Keywords& keys ){ } ContactMap::ContactMap(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true), -serial(false), -docomp(true), -dosum(false), -docmdist(false) + PLUMED_COLVAR_INIT(ao), + pbc(true), + serial(false), + docomp(true), + dosum(false), + docmdist(false) { parseFlag("SERIAL",serial); parseFlag("SUM",dosum); @@ -158,96 +158,96 @@ docmdist(false) if(docmdist==true&&dosum==true) error("You cannot use SUM and CMDIST together"); bool nopbc=!pbc; parseFlag("NOPBC",nopbc); - pbc=!nopbc; + pbc=!nopbc; // Read in the atoms std::vector t, ga_lista, gb_lista; - for(int i=1;;++i ){ - parseAtomList("ATOMS", i, t ); - if( t.empty() ) break; - - if( t.size()!=2 ){ - std::string ss; Tools::convert(i,ss); - error("ATOMS" + ss + " keyword has the wrong number of atoms"); - } - ga_lista.push_back(t[0]); gb_lista.push_back(t[1]); - t.resize(0); - - // Add a value for this contact - std::string num; Tools::convert(i,num); - if(!dosum&&!docmdist) {addComponentWithDerivatives("contact-"+num); componentIsNotPeriodic("contact-"+num);} + for(int i=1;; ++i ) { + parseAtomList("ATOMS", i, t ); + if( t.empty() ) break; + + if( t.size()!=2 ) { + std::string ss; Tools::convert(i,ss); + error("ATOMS" + ss + " keyword has the wrong number of atoms"); + } + ga_lista.push_back(t[0]); gb_lista.push_back(t[1]); + t.resize(0); + + // Add a value for this contact + std::string num; Tools::convert(i,num); + if(!dosum&&!docmdist) {addComponentWithDerivatives("contact-"+num); componentIsNotPeriodic("contact-"+num);} } // Create neighbour lists nl= new NeighborList(ga_lista,gb_lista,true,pbc,getPbc()); // Read in switching functions std::string errors; sfs.resize( ga_lista.size() ); unsigned nswitch=0; - for(unsigned i=0;i deriv(getNumberOfAtoms()); - - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if(serial){ - // when using components the parallelisation do not work - stride=1; - rank=0; - }else{ - stride=comm.Get_size(); - rank=comm.Get_rank(); - } - - // sum over close pairs - for(unsigned i=rank;isize();i+=stride) { +void ContactMap::calculate() { + + double ncoord=0.; + Tensor virial; + std::vector deriv(getNumberOfAtoms()); + + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if(serial) { + // when using components the parallelisation do not work + stride=1; + rank=0; + } else { + stride=comm.Get_size(); + rank=comm.Get_rank(); + } + +// sum over close pairs + for(unsigned i=rank; isize(); i+=stride) { Vector distance; unsigned i0=nl->getClosePair(i).first; unsigned i1=nl->getClosePair(i).second; - if(pbc){ + if(pbc) { distance=pbcDistance(getPosition(i0),getPosition(i1)); } else { distance=delta(getPosition(i0),getPosition(i1)); @@ -294,40 +294,40 @@ void ContactMap::calculate(){ double coord = weight[i]*(sfs[i].calculate(distance.modulo(), dfunc) - reference[i]); Vector tmpder = weight[i]*dfunc*distance; Tensor tmpvir = weight[i]*dfunc*Tensor(distance,distance); - if(!docmdist) { - deriv[i0] -= tmpder; - deriv[i1] += tmpder; - virial -= tmpvir; - ncoord += coord; + if(!docmdist) { + deriv[i0] -= tmpder; + deriv[i1] += tmpder; + virial -= tmpvir; + ncoord += coord; } else { - tmpder *= 2.*coord; - tmpvir *= 2.*coord; - deriv[i0] -= tmpder; - deriv[i1] += tmpder; - virial -= tmpvir; - ncoord += coord*coord; + tmpder *= 2.*coord; + tmpvir *= 2.*coord; + deriv[i0] -= tmpder; + deriv[i1] += tmpder; + virial -= tmpvir; + ncoord += coord*coord; } if(docomp) { - Value* val=getPntrToComponent( i ); - setAtomsDerivatives( val, i0, deriv[i0] ); - setAtomsDerivatives( val, i1, deriv[i1] ); - setBoxDerivatives( val, -tmpvir ); - val->set(coord); + Value* val=getPntrToComponent( i ); + setAtomsDerivatives( val, i0, deriv[i0] ); + setAtomsDerivatives( val, i1, deriv[i1] ); + setBoxDerivatives( val, -tmpvir ); + val->set(coord); } - } - - if(!serial){ - comm.Sum(&ncoord,1); - if(!deriv.empty()) comm.Sum(&deriv[0][0],3*deriv.size()); - comm.Sum(&virial[0][0],9); - } - - if( !docomp ){ - for(unsigned i=0;i0){ + if(sw.length()>0) { switchingFunction.set(sw,errors); if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); } else { @@ -135,13 +135,13 @@ CoordinationBase(ao) parse("MM",mm); switchingFunction.set(nn,mm,r0,d0); } - + checkRead(); log<<" contacts are counted with cutoff "<0){ + if(gb_lista.size()>0) { if(doneigh) nl= new NeighborList(ga_lista,gb_lista,dopair,pbc,getPbc(),nl_cut,nl_st); else nl= new NeighborList(ga_lista,gb_lista,dopair,pbc,getPbc()); } else { if(doneigh) nl= new NeighborList(ga_lista,pbc,getPbc(),nl_cut,nl_st); else nl= new NeighborList(ga_lista,pbc,getPbc()); } - + requestAtoms(nl->getFullAtomList()); - + log.printf(" between two groups of %u and %u atoms\n",static_cast(ga_lista.size()),static_cast(gb_lista.size())); log.printf(" first group:\n"); - for(unsigned int i=0;igetStride()>0){ - if(firsttime || (getStep()%nl->getStride()==0)){ +void CoordinationBase::prepare() { + if(nl->getStride()>0) { + if(firsttime || (getStep()%nl->getStride()==0)) { requestAtoms(nl->getFullAtomList()); invalidateList=true; firsttime=false; - }else{ + } else { requestAtoms(nl->getReducedAtomList()); invalidateList=false; if(getExchangeStep()) error("Neighbor lists should be updated on exchange steps - choose a NL_STRIDE which divides the exchange stride!"); @@ -131,84 +131,84 @@ void CoordinationBase::prepare(){ void CoordinationBase::calculate() { - double ncoord=0.; - Tensor virial; - vector deriv(getNumberOfAtoms()); + double ncoord=0.; + Tensor virial; + vector deriv(getNumberOfAtoms()); // deriv.resize(getPositions().size()); - if(nl->getStride()>0 && invalidateList){ - nl->update(getPositions()); - } + if(nl->getStride()>0 && invalidateList) { + nl->update(getPositions()); + } - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if(serial){ - stride=1; - rank=0; - }else{ - stride=comm.Get_size(); - rank=comm.Get_rank(); - } + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if(serial) { + stride=1; + rank=0; + } else { + stride=comm.Get_size(); + rank=comm.Get_rank(); + } -unsigned nt=OpenMP::getNumThreads(); + unsigned nt=OpenMP::getNumThreads(); -const unsigned nn=nl->size(); + const unsigned nn=nl->size(); -if(nt*stride*10>nn) nt=nn/stride/10; -if(nt==0)nt=1; + if(nt*stride*10>nn) nt=nn/stride/10; + if(nt==0)nt=1; -#pragma omp parallel num_threads(nt) -{ - std::vector omp_deriv(getPositions().size()); - Tensor omp_virial; + #pragma omp parallel num_threads(nt) + { + std::vector omp_deriv(getPositions().size()); + Tensor omp_virial; -#pragma omp for reduction(+:ncoord) nowait - for(unsigned int i=rank;igetClosePair(i).first; - unsigned i1=nl->getClosePair(i).second; + #pragma omp for reduction(+:ncoord) nowait + for(unsigned int i=rank; igetClosePair(i).first; + unsigned i1=nl->getClosePair(i).second; - if(pbc){ - distance=pbcDistance(getPosition(i0),getPosition(i1)); - } else { - distance=delta(getPosition(i0),getPosition(i1)); - } + if(getAbsoluteIndex(i0)==getAbsoluteIndex(i1)) continue; - double dfunc=0.; - ncoord += pairing(distance.modulo2(), dfunc,i0,i1); + if(pbc) { + distance=pbcDistance(getPosition(i0),getPosition(i1)); + } else { + distance=delta(getPosition(i0),getPosition(i1)); + } - Vector dd(dfunc*distance); - Tensor vv(dd,distance); - if(nt>1){ - omp_deriv[i0]-=dd; - omp_deriv[i1]+=dd; - omp_virial-=vv; - } else { - deriv[i0]-=dd; - deriv[i1]+=dd; - virial-=vv; - } + double dfunc=0.; + ncoord += pairing(distance.modulo2(), dfunc,i0,i1); - } -#pragma omp critical - if(nt>1){ - for(int i=0;i1) { + omp_deriv[i0]-=dd; + omp_deriv[i1]+=dd; + omp_virial-=vv; + } else { + deriv[i0]-=dd; + deriv[i1]+=dd; + virial-=vv; + } + + } + #pragma omp critical + if(nt>1) { + for(int i=0; iset( pdb ); checkRead(); - std::vector atoms; + std::vector atoms; drmsd_->getAtomRequests( atoms ); // drmsd_->setNumberOfAtoms( atoms.size() ); requestAtoms( atoms ); // Setup the derivative pack myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() ); - for(unsigned i=0;icalculate(getPositions(), getPbc(), mypack, false); + double drmsd; Tensor virial; mypack.clear(); + drmsd=drmsd_->calculate(getPositions(), getPbc(), mypack, false); - setValue(drmsd); - for(unsigned i=0;i dsigmas; - private: - void consistencyCheck(); - vector usedatoms; +public: + static void registerKeywords( Keywords& keys); + Dimer(const ActionOptions&); + virtual void calculate(); +protected: + bool trimer,useall; + int myrank, nranks, natoms; + double qexp,temperature,beta,dsigma; + vector dsigmas; +private: + void consistencyCheck(); + vector usedatoms; }; PLUMED_REGISTER_ACTION(Dimer, "DIMER") -void Dimer::registerKeywords( Keywords& keys){ - Colvar::registerKeywords(keys); - - keys.add("compulsory","DSIGMA","The interaction strength of the dimer bond."); - keys.add("compulsory", "Q", "The exponent of the dimer potential."); - keys.add("compulsory", "TEMP", "The temperature (in Kelvin) of the simulation."); - keys.add("atoms", "ATOMS", "The list of atoms being considered by this CV. Used if ALLATOMS flag is missing"); - keys.add("atoms","NATOMS","The number of dimerized atoms. Used in combination with ATOMS list"); - keys.addFlag("ALLATOMS", false, "Use EVERY atom of the system. Overrides ATOMS keyword."); - keys.addFlag("NOVSITES", false, "If present the configuration is without virtual sites at the centroids."); - +void Dimer::registerKeywords( Keywords& keys) { + Colvar::registerKeywords(keys); + + keys.add("compulsory","DSIGMA","The interaction strength of the dimer bond."); + keys.add("compulsory", "Q", "The exponent of the dimer potential."); + keys.add("compulsory", "TEMP", "The temperature (in Kelvin) of the simulation."); + keys.add("atoms", "ATOMS", "The list of atoms being considered by this CV. Used if ALLATOMS flag is missing"); + keys.add("atoms","NATOMS","The number of dimerized atoms. Used in combination with ATOMS list"); + keys.addFlag("ALLATOMS", false, "Use EVERY atom of the system. Overrides ATOMS keyword."); + keys.addFlag("NOVSITES", false, "If present the configuration is without virtual sites at the centroids."); + } Dimer::Dimer(const ActionOptions& ao): - PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { - - log<<" Bibliography "< atoms; - parseFlag("ALLATOMS",useall); - trimer=true; - bool notrim; - parseFlag("NOVSITES",notrim); - trimer=!notrim; - - nranks=multi_sim_comm.Get_size(); - myrank=multi_sim_comm.Get_rank(); - if(dsigmas.size()==1) - dsigma=dsigmas[0]; - else - dsigma=dsigmas[myrank]; - - - - - if(useall) - { - // go with every atom in the system but not the virtuals... - if(trimer) - natoms= 2*getTotAtoms()/3; - else - natoms=getTotAtoms()/2; - - for(unsigned int i=0;i<((unsigned int)natoms);i++) - { - AtomNumber ati; - ati.setIndex(i); - atoms.push_back(ati); - } - } - else // serials for the first beads of each dimer are given - { - parseVector("ATOMS",usedatoms); - double ntm; - parse("NATOMS",ntm); - natoms=ntm; - - int isz = usedatoms.size(); - - for(unsigned int i=0;inatoms) - error("The Dimer CV requires that when choosing atoms you refere only to the first beads."); - atoms.push_back(atip2); - } - - } - consistencyCheck(); - checkRead(); - beta = 1./(kBoltzmann*temperature); - - addValueWithDerivatives(); // allocate - - requestAtoms(atoms); - - setNotPeriodic(); - + + log<<" Bibliography "< atoms; + parseFlag("ALLATOMS",useall); + trimer=true; + bool notrim; + parseFlag("NOVSITES",notrim); + trimer=!notrim; + + nranks=multi_sim_comm.Get_size(); + myrank=multi_sim_comm.Get_rank(); + if(dsigmas.size()==1) + dsigma=dsigmas[0]; + else + dsigma=dsigmas[myrank]; + + + + + if(useall) + { + // go with every atom in the system but not the virtuals... + if(trimer) + natoms= 2*getTotAtoms()/3; + else + natoms=getTotAtoms()/2; + + for(unsigned int i=0; i<((unsigned int)natoms); i++) + { + AtomNumber ati; + ati.setIndex(i); + atoms.push_back(ati); + } + } + else // serials for the first beads of each dimer are given + { + parseVector("ATOMS",usedatoms); + double ntm; + parse("NATOMS",ntm); + natoms=ntm; + + int isz = usedatoms.size(); + + for(unsigned int i=0; inatoms) + error("The Dimer CV requires that when choosing atoms you refere only to the first beads."); + atoms.push_back(atip2); + } + + } + consistencyCheck(); + checkRead(); + beta = 1./(kBoltzmann*temperature); + + addValueWithDerivatives(); // allocate + + requestAtoms(atoms); + + setNotPeriodic(); + } void Dimer::calculate() { - double cv_val=0; - Tensor virial; - vector derivatives; - vector my_pos=getPositions(); - int atms = my_pos.size(); - vector der_b2; - for(int i=0;i derivatives; + vector my_pos=getPositions(); + int atms = my_pos.size(); + vector der_b2; + for(int i=0; i1) - warning("Dimer CV is meant to be used with q-exponents between 0.5 and 1. We are not responsible for any black hole. :-)"); - if(dsigma<0) - error("Please use positive sigma values for the Dimer strength constant"); - if(temperature<0) - error("Please, use a positive value for the temperature..."); - - // if dsigmas has only one element means that either - // you are using different plumed.x.dat files or a plumed.dat with a single replica - if(dsigmas.size()!=nranks && dsigmas.size()!=1) - error("Mismatch between provided sigmas and number of replicas"); + if(useall==false && natoms==0) + error("Either NATOMS or ATOMS are required to specify the number of dimerized atoms."); + + if(qexp<0.5 || qexp>1) + warning("Dimer CV is meant to be used with q-exponents between 0.5 and 1. We are not responsible for any black hole. :-)"); + if(dsigma<0) + error("Please use positive sigma values for the Dimer strength constant"); + if(temperature<0) + error("Please, use a positive value for the temperature..."); + + // if dsigmas has only one element means that either + // you are using different plumed.x.dat files or a plumed.dat with a single replica + if(dsigmas.size()!=nranks && dsigmas.size()!=1) + error("Mismatch between provided sigmas and number of replicas"); } -}} +} +} diff --git a/src/colvar/Dipole.cpp b/src/colvar/Dipole.cpp index 4f0bed0308..09a4a65800 100644 --- a/src/colvar/Dipole.cpp +++ b/src/colvar/Dipole.cpp @@ -27,10 +27,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR DIPOLE +//+PLUMEDOC COLVAR DIPOLE /* Calculate the dipole moment for a group of atoms. @@ -43,7 +43,7 @@ PRINT FILE=output STRIDE=5 ARG=5 \endverbatim (see also \ref PRINT) -\attention +\attention If the total charge Q of the group in non zero, then a charge Q/N will be subtracted to every atom, where N is the number of atoms. This implies that the dipole (which for a charged system depends on the position) is computed on the geometric center of the group. @@ -51,7 +51,7 @@ on the position) is computed on the geometric center of the group. */ //+ENDPLUMEDOC - + class Dipole : public Colvar { vector ga_lista; bool components; @@ -63,7 +63,7 @@ class Dipole : public Colvar { PLUMED_REGISTER_ACTION(Dipole,"DIPOLE") -void Dipole::registerKeywords(Keywords& keys){ +void Dipole::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("atoms","GROUP","the group of atoms we are calculating the dipole moment for"); keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the dipole separately and store them as label.x, label.y and label.z"); @@ -74,13 +74,13 @@ void Dipole::registerKeywords(Keywords& keys){ } Dipole::Dipole(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -components(false) + PLUMED_COLVAR_INIT(ao), + components(false) { parseAtomList("GROUP",ga_lista); parseFlag("COMPONENTS",components); checkRead(); - if(components){ + if(components) { addComponentWithDerivatives("x"); componentIsNotPeriodic("x"); addComponentWithDerivatives("y"); componentIsNotPeriodic("y"); addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); @@ -89,7 +89,7 @@ components(false) } log.printf(" of %u atoms\n",static_cast(ga_lista.size())); - for(unsigned int i=0;i charges(N); - Vector dipje; - - for(unsigned i=0;iset(dipje[0]); - valuey->set(dipje[1]); - valuez->set(dipje[2]); - } + double ctot=0.; + unsigned N=getNumberOfAtoms(); + vector charges(N); + Vector dipje; + + for(unsigned i=0; iset(dipje[0]); + valuey->set(dipje[1]); + valuez->set(dipje[2]); + } } } diff --git a/src/colvar/Distance.cpp b/src/colvar/Distance.cpp index 8ef7c08055..c3a9817715 100644 --- a/src/colvar/Distance.cpp +++ b/src/colvar/Distance.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR DISTANCE /* @@ -110,7 +110,7 @@ with domain (-0.5,+0.5). */ //+ENDPLUMEDOC - + class Distance : public Colvar { bool components; bool scaled_components; @@ -125,11 +125,11 @@ class Distance : public Colvar { PLUMED_REGISTER_ACTION(Distance,"DISTANCE") -void Distance::registerKeywords( Keywords& keys ){ +void Distance::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("atoms","ATOMS","the pair of atom that we are calculating the distance between"); - keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the distance separately and store them as label.x, label.y and label.z"); - keys.addFlag("SCALED_COMPONENTS",false,"calculate the a, b and c scaled components of the distance separately and store them as label.a, label.b and label.c"); + keys.addFlag("COMPONENTS",false,"calculate the x, y and z components of the distance separately and store them as label.x, label.y and label.z"); + keys.addFlag("SCALED_COMPONENTS",false,"calculate the a, b and c scaled components of the distance separately and store them as label.a, label.b and label.c"); keys.addOutputComponent("x","COMPONENTS","the x-component of the vector connecting the two atoms"); keys.addOutputComponent("y","COMPONENTS","the y-component of the vector connecting the two atoms"); keys.addOutputComponent("z","COMPONENTS","the z-component of the vector connecting the two atoms"); @@ -139,10 +139,10 @@ void Distance::registerKeywords( Keywords& keys ){ } Distance::Distance(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -components(false), -scaled_components(false), -pbc(true) + PLUMED_COLVAR_INIT(ao), + components(false), + scaled_components(false), + pbc(true) { vector atoms; parseAtomList("ATOMS",atoms); @@ -161,12 +161,12 @@ pbc(true) if(components && scaled_components) error("COMPONENTS and SCALED_COMPONENTS are not compatible"); - if(components){ + if(components) { addComponentWithDerivatives("x"); componentIsNotPeriodic("x"); addComponentWithDerivatives("y"); componentIsNotPeriodic("y"); addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); log<<" WARNING: components will not have the proper periodicity - see manual\n"; - } else if(scaled_components){ + } else if(scaled_components) { addComponentWithDerivatives("a"); componentIsPeriodic("a","-0.5","+0.5"); addComponentWithDerivatives("b"); componentIsPeriodic("b","-0.5","+0.5"); addComponentWithDerivatives("c"); componentIsPeriodic("c","-0.5","+0.5"); @@ -180,7 +180,7 @@ pbc(true) // calculator -void Distance::calculate(){ +void Distance::calculate() { if(pbc) makeWhole(); @@ -188,7 +188,7 @@ void Distance::calculate(){ const double value=distance.modulo(); const double invvalue=1.0/value; - if(components){ + if(components) { Value* valuex=getPntrToComponent("x"); Value* valuey=getPntrToComponent("y"); Value* valuez=getPntrToComponent("z"); @@ -207,7 +207,7 @@ void Distance::calculate(){ setAtomsDerivatives (valuez,1,Vector(0,0,+1)); setBoxDerivativesNoPbc(valuez); valuez->set(distance[2]); - } else if(scaled_components){ + } else if(scaled_components) { Value* valuea=getPntrToComponent("a"); Value* valueb=getPntrToComponent("b"); Value* valuec=getPntrToComponent("c"); diff --git a/src/colvar/ERMSD.cpp b/src/colvar/ERMSD.cpp index 29ce5de510..3602df0868 100644 --- a/src/colvar/ERMSD.cpp +++ b/src/colvar/ERMSD.cpp @@ -35,35 +35,35 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR ERMSD /* -Calculate eRMSD with respect to a reference structure. +Calculate eRMSD with respect to a reference structure. -eRMSD is a metric developed for measuring distances between three-dimensional RNA structures. -The standard RMSD measure is highly inaccurate when measuring distances among three-dimensional -structures of nucleic acids. -It is not unusual, for example, that two RNA structures with low RMSD (i.e. less than 0.4nm) display a completely different network of base-base interactions. +eRMSD is a metric developed for measuring distances between three-dimensional RNA structures. +The standard RMSD measure is highly inaccurate when measuring distances among three-dimensional +structures of nucleic acids. +It is not unusual, for example, that two RNA structures with low RMSD (i.e. less than 0.4nm) display a completely different network of base-base interactions. eRMSD measures the distance between structures by considering only the relative positions and orientations of nucleobases. The eRMSD can be considered as a vectorial version of contact maps and it is calculated as follows: -1. Set up a local reference system in the center of the six-membered ring of each nucleobase in a molecule. - The xy plane lies on the plane of the nucleobase, and it is oriented such that the Watson-Crick interaction is always at \f$ \theta \approx 60^{\circ} \f$. +1. Set up a local reference system in the center of the six-membered ring of each nucleobase in a molecule. + The xy plane lies on the plane of the nucleobase, and it is oriented such that the Watson-Crick interaction is always at \f$ \theta \approx 60^{\circ} \f$. -2. Calculate all pairwise distance vectors \f$ \vec{r}_{i,j} \f$ among base centers. +2. Calculate all pairwise distance vectors \f$ \vec{r}_{i,j} \f$ among base centers. 3. Rescale distance vectors as \f$ \tilde{\vec{r}}_{i,j} = (r_x/a,r_y/a,r_z/b) \f$, where \f$ a=b=5 \AA, c= 3 \AA\f$. This rescaling has the effect of weghting more deviations on the z-axis with respect to the x/y directions. -4. Calculate the G vectors +4. Calculate the G vectors \f[ \vec{G}(\tilde{\vec{r}}) = (\sin(\gamma \tilde{r}) \tilde{r}_x/\tilde{r},\sin(\gamma \tilde{r}) \tilde{r}_y/\tilde{r},\sin(\gamma \tilde{r}) \tilde{r}_z/\tilde{r}, 1+\cos(\gamma \tilde{r})) \times \Theta(\tilde{r}_{cutoff}-\tilde{r}) \f] -Here, \f$ \gamma = \pi/\tilde{r}_{cutoff}\f$ and \f$ \Theta \f$ is the Heaviside step function. The default cutoff is set to 2.4. +Here, \f$ \gamma = \pi/\tilde{r}_{cutoff}\f$ and \f$ \Theta \f$ is the Heaviside step function. The default cutoff is set to 2.4. 5. The eRMSD between two structures \f$ \alpha \f$ and \f$ \beta \f$ reads @@ -81,7 +81,7 @@ for a multi molecular system. \par Examples -Calculate the eRMSD from reference structure reference.pdb using the default cutoff (2.4). The list of residues involved in the calculation has to be specified. In this example, the eRMSD is calculated +Calculate the eRMSD from reference structure reference.pdb using the default cutoff (2.4). The list of residues involved in the calculation has to be specified. In this example, the eRMSD is calculated considering residues 1,2,3,4,5,6. \verbatim @@ -91,13 +91,13 @@ eRMSD1: ERMSD REFERENCE=reference.pdb ATOMS=@lcs-1,@lcs-2,@lcs-3,@lcs-4,@lcs-5,@ */ //+ENDPLUMEDOC - + class ERMSD : public Colvar { - - vector derivs; - PLMD::ERMSD ermsd; - bool pbc; + + vector derivs; + PLMD::ERMSD ermsd; + bool pbc; public: explicit ERMSD(const ActionOptions&); @@ -107,7 +107,7 @@ class ERMSD : public Colvar { PLUMED_REGISTER_ACTION(ERMSD,"ERMSD") -void ERMSD::registerKeywords(Keywords& keys){ +void ERMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV."); @@ -118,7 +118,7 @@ void ERMSD::registerKeywords(Keywords& keys){ } ERMSD::ERMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), pbc(true) + PLUMED_COLVAR_INIT(ao), pbc(true) { string reference; parse("REFERENCE",reference); @@ -137,13 +137,13 @@ PLUMED_COLVAR_INIT(ao), pbc(true) parseVector("PAIRS",pairs_); checkRead(); - addValueWithDerivatives(); setNotPeriodic(); + addValueWithDerivatives(); setNotPeriodic(); if(atoms_.size()<6) error("at least six atoms should be specified"); if(atoms_.size()%3!=0) error("Atoms are not multiple of 3"); if(pairs_.size()%2!=0) error("pairs are not multiple of 2"); - + //checkRead(); //log.printf(" of atoms"); //for(unsigned i=0;i reference_positions; unsigned natoms = atoms_.size(); log.printf("Read %u atoms\n",natoms); reference_positions.resize(natoms); - for(unsigned i=0;i #include -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR ENERGY /* @@ -42,7 +42,7 @@ metadynamics applied to ENERGY can be used to decrease the number of required replicas. \bug Acceptance for replica exchange when \ref ENERGY is biased -is computed correctly only of all the replicas has the same +is computed correctly only of all the replicas has the same potential energy function. This is for instance not true when using GROMACS with lambda replica exchange of with plumed-hrex branch. @@ -76,7 +76,7 @@ using namespace std; PLUMED_REGISTER_ACTION(Energy,"ENERGY") Energy::Energy(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { // if(checkNumericalDerivatives()) // error("Cannot use NUMERICAL_DERIVATIVES with ENERGY"); @@ -89,23 +89,23 @@ PLUMED_COLVAR_INIT(ao) log<<"\n"; } -void Energy::registerKeywords( Keywords& keys ){ +void Energy::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); - keys.remove("NUMERICAL_DERIVATIVES"); + keys.remove("NUMERICAL_DERIVATIVES"); } -unsigned Energy::getNumberOfDerivatives(){ +unsigned Energy::getNumberOfDerivatives() { return 1; } -void Energy::prepare(){ +void Energy::prepare() { plumed.getAtoms().setCollectEnergy(true); } // calculator -void Energy::calculate(){ +void Energy::calculate() { setValue( getEnergy() ); getPntrToComponent(0)->addDerivative(0,1.0); } diff --git a/src/colvar/Fake.cpp b/src/colvar/Fake.cpp index 4a28cbf38d..70bd7f2789 100644 --- a/src/colvar/Fake.cpp +++ b/src/colvar/Fake.cpp @@ -29,10 +29,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR FAKE +//+PLUMEDOC COLVAR FAKE /* This is a fake colvar container used by cltools or various other actions and just support input and period definition @@ -46,7 +46,7 @@ FAKE ATOMS=1 PERIODIC=-3.14,3.14 LABEL=d2 */ //+ENDPLUMEDOC - + class ColvarFake : public Colvar { public: @@ -58,7 +58,7 @@ class ColvarFake : public Colvar { PLUMED_REGISTER_ACTION(ColvarFake,"FAKE") -void ColvarFake::registerKeywords( Keywords& keys ){ +void ColvarFake::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("atoms","ATOMS","the fake atom index, a number is enough"); keys.reserve("compulsory","PERIODIC","if the output of your function is periodic then you should specify the periodicity of the function. If the output is not periodic you must state this using PERIODIC=NO,NO (one for the lower and the other for the upper boundary). For multicomponents then it is PERIODIC=mincomp1,maxcomp1,mincomp2,maxcomp2 etc "); @@ -67,61 +67,61 @@ void ColvarFake::registerKeywords( Keywords& keys ){ } ColvarFake::ColvarFake(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { vector atoms; parseAtomList("ATOMS",atoms); - vector comps; - // multiple components for this variable + vector comps; + // multiple components for this variable parseVector("COMPONENTS",comps); - if(comps.size()!=0){ - for(unsigned i=0;i period; parseVector("PERIODIC",period); - if(period.size()!=0){ - plumed_massert(getNumberOfComponents()*2==period.size(),"the periodicty should coincide with the number of components"); - if(comps.size()!=0){ - for(int i=0;igetName()); - } - } else { - setNotPeriodic(); - } + if(period.size()!=0) { + plumed_massert(getNumberOfComponents()*2==period.size(),"the periodicty should coincide with the number of components"); + if(comps.size()!=0) { + for(int i=0; igetName()); + } + } else { + setNotPeriodic(); + } } - checkRead(); - requestAtoms(atoms); + checkRead(); + requestAtoms(atoms); } // calculator -void ColvarFake::calculate(){ - plumed_merror("you should never have got here"); +void ColvarFake::calculate() { + plumed_merror("you should never have got here"); } } diff --git a/src/colvar/FretEfficiency.cpp b/src/colvar/FretEfficiency.cpp index 9840c749de..02600e1057 100644 --- a/src/colvar/FretEfficiency.cpp +++ b/src/colvar/FretEfficiency.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR FRET /* @@ -48,7 +48,7 @@ boundary conditions. This behavior can be changed with the NOPBC flag. \par Examples -The following input tells plumed to print the FRET efficiencies +The following input tells plumed to print the FRET efficiencies calculated as a function of the distance between atoms 3 and 5 and the distance between atoms 2 and 4. \verbatim @@ -73,7 +73,7 @@ to be sure that if the distance is larger than half the simulation box the distance is compute properly. Also notice that, since many MD codes break molecules across cell boundary, it might be necessary to use the \ref WHOLEMOLECULES keyword (also notice that it should be -_before_ FRET). +_before_ FRET). Just be sure that the ordered list provide to WHOLEMOLECULES has the following properties: - Consecutive atoms should be closer than half-cell throughout the entire simulation. @@ -81,7 +81,7 @@ Just be sure that the ordered list provide to WHOLEMOLECULES has the following */ //+ENDPLUMEDOC - + class FretEfficiency : public Colvar { bool pbc; double R0_; @@ -95,21 +95,21 @@ class FretEfficiency : public Colvar { PLUMED_REGISTER_ACTION(FretEfficiency,"FRET") -void FretEfficiency::registerKeywords( Keywords& keys ){ +void FretEfficiency::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); keys.add("atoms","ATOMS","the pair of atom that we are calculating the distance between"); keys.add("compulsory","R0","The value of the Forster radius."); } FretEfficiency::FretEfficiency(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true) + PLUMED_COLVAR_INIT(ao), + pbc(true) { vector atoms; parseAtomList("ATOMS",atoms); if(atoms.size()!=2) error("Number of specified atoms should be 2"); - parse("R0",R0_); + parse("R0",R0_); bool nopbc=!pbc; parseFlag("NOPBC",nopbc); pbc=!nopbc; @@ -129,14 +129,14 @@ pbc(true) // calculator -void FretEfficiency::calculate(){ +void FretEfficiency::calculate() { if(pbc) makeWhole(); Vector distance=delta(getPosition(0),getPosition(1)); const double dist_mod=distance.modulo(); const double inv_dist_mod=1.0/dist_mod; - + const double ratiosix=pow(dist_mod/R0_,6); const double fret_eff = 1.0/(1.0+ratiosix); diff --git a/src/colvar/Gyration.cpp b/src/colvar/Gyration.cpp index 9471593e9f..5cf35aea06 100644 --- a/src/colvar/Gyration.cpp +++ b/src/colvar/Gyration.cpp @@ -29,26 +29,26 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR GYRATION /* Calculate the radius of gyration, or other properties related to it. The different properties can be calculated and selected by the TYPE keyword: -the Radius of Gyration (RADIUS); the Trace of the Gyration Tensor (TRACE); +the Radius of Gyration (RADIUS); the Trace of the Gyration Tensor (TRACE); the Largest Principal Moment of the Gyration Tensor (GTPC_1); the middle Principal Moment of the Gyration Tensor (GTPC_2); the Smallest Principal Moment of the Gyration Tensor (GTPC_3); the Asphericiry (ASPHERICITY); the Acylindricity (ACYLINDRICITY); -the Relative Shape Anisotropy (KAPPA2); the Smallest Principal Radius Of Gyration (GYRATION_3); +the Relative Shape Anisotropy (KAPPA2); the Smallest Principal Radius Of Gyration (GYRATION_3); the Middle Principal Radius of Gyration (GYRATION_2); the Largest Principal Radius of Gyration (GYRATION_1). A derivation of all these different variants can be found in \cite Vymetal:2011gv The radius of gyration is calculated using: \f[ -s_{\rm Gyr}=\Big ( \frac{\sum_i^{n} - m_i \vert {r}_i -{r}_{\rm COM} \vert ^2 }{\sum_i^{n} m_i} \Big)^{1/2} +s_{\rm Gyr}=\Big ( \frac{\sum_i^{n} + m_i \vert {r}_i -{r}_{\rm COM} \vert ^2 }{\sum_i^{n} m_i} \Big)^{1/2} \f] with the position of the center of mass \f${r}_{\rm COM}\f$ given by: @@ -57,14 +57,14 @@ with the position of the center of mass \f${r}_{\rm COM}\f$ given by: {r}_{\rm COM}=\frac{\sum_i^{n} {r}_i\ m_i }{\sum_i^{n} m_i} \f] -The radius of gyration usually makes sense when atoms used for the calculation +The radius of gyration usually makes sense when atoms used for the calculation are all part of the same molecule. -When running with periodic boundary conditions, the atoms should be +When running with periodic boundary conditions, the atoms should be in the proper periodic image. This is done automatically since PLUMED 2.2, by considering the ordered list of atoms and rebuilding PBCs with a procedure that is equivalent to that done in \ref WHOLEMOLECULES . Notice that rebuilding is local to this action. This is different from \ref WHOLEMOLECULES -which actually modifies the coordinates stored in PLUMED. +which actually modifies the coordinates stored in PLUMED. In case you want to recover the old behavior you should use the NOPBC flag. In that case you need to take care that atoms are in the correct @@ -73,11 +73,11 @@ periodic image. \par Examples -The following input tells plumed to print the radius of gyration of the +The following input tells plumed to print the radius of gyration of the chain containing atoms 10 to 20. \verbatim GYRATION TYPE=RADIUS ATOMS=10-20 LABEL=rg -PRINT ARG=rg STRIDE=1 FILE=colvar +PRINT ARG=rg STRIDE=1 FILE=colvar \endverbatim (See also \ref PRINT) @@ -98,7 +98,7 @@ class Gyration : public Colvar { PLUMED_REGISTER_ACTION(Gyration,"GYRATION") -void Gyration::registerKeywords(Keywords& keys){ +void Gyration::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("atoms","ATOMS","the group of atoms that you are calculating the Gyration Tensor for"); keys.add("compulsory","TYPE","RADIUS","The type of calculation relative to the Gyration Tensor you want to perform"); @@ -106,9 +106,9 @@ void Gyration::registerKeywords(Keywords& keys){ } Gyration::Gyration(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -use_masses(false), -nopbc(false) + PLUMED_COLVAR_INIT(ao), + use_masses(false), + nopbc(false) { std::vector atoms; parseAtomList("ATOMS",atoms); @@ -134,25 +134,25 @@ nopbc(false) switch(rg_type) { - case RADIUS: log.printf(" GYRATION RADIUS (Rg);"); break; - case TRACE: log.printf(" TRACE OF THE GYRATION TENSOR;"); break; - case GTPC_1: log.printf(" THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);"); break; - case GTPC_2: log.printf(" THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);"); break; - case GTPC_3: log.printf(" THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);"); break; - case ASPHERICITY: log.printf(" THE ASPHERICITY (b');"); break; - case ACYLINDRICITY: log.printf(" THE ACYLINDRICITY (c');"); break; - case KAPPA2: log.printf(" THE RELATIVE SHAPE ANISOTROPY (kappa^2);"); break; - case GYRATION_3: log.printf(" THE SMALLEST PRINCIPAL RADIUS OF GYRATION (r_g3);"); break; - case GYRATION_2: log.printf(" THE MIDDLE PRINCIPAL RADIUS OF GYRATION (r_g2);"); break; - case GYRATION_1: log.printf(" THE LARGEST PRINCIPAL RADIUS OF GYRATION (r_g1);"); break; + case RADIUS: log.printf(" GYRATION RADIUS (Rg);"); break; + case TRACE: log.printf(" TRACE OF THE GYRATION TENSOR;"); break; + case GTPC_1: log.printf(" THE LARGEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_1);"); break; + case GTPC_2: log.printf(" THE MIDDLE PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_2);"); break; + case GTPC_3: log.printf(" THE SMALLEST PRINCIPAL MOMENT OF THE GYRATION TENSOR (S'_3);"); break; + case ASPHERICITY: log.printf(" THE ASPHERICITY (b');"); break; + case ACYLINDRICITY: log.printf(" THE ACYLINDRICITY (c');"); break; + case KAPPA2: log.printf(" THE RELATIVE SHAPE ANISOTROPY (kappa^2);"); break; + case GYRATION_3: log.printf(" THE SMALLEST PRINCIPAL RADIUS OF GYRATION (r_g3);"); break; + case GYRATION_2: log.printf(" THE MIDDLE PRINCIPAL RADIUS OF GYRATION (r_g2);"); break; + case GYRATION_1: log.printf(" THE LARGEST PRINCIPAL RADIUS OF GYRATION (r_g1);"); break; } if(rg_type>TRACE) log<<" Bibliography "<(getNumberOfAtoms()); - for(unsigned i=0;i gyr_tens(3,3); - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) gyr_tens(i,j)=0.; + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) gyr_tens(i,j)=0.; //calculate gyration tensor if( use_masses ) { - for(unsigned i=0;i0.0001) error("Plumed Error: Cannot diagonalize gyration tensor\n"); switch(rg_type) { - case GTPC_1: - case GTPC_2: - case GTPC_3: - { - int pc_index = rg_type-2; //index of principal component - rgyr=sqrt(princ_comp[pc_index]/totmass); - double rm = rgyr*totmass; - if(rm>1e-6) prefactor[pc_index]=1.0/rm; //some parts of derivate - break; - } - case GYRATION_3: //the smallest principal radius of gyration - { - rgyr=sqrt((princ_comp[1]+princ_comp[2])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[1]=1.0/rm; - prefactor[2]=1.0/rm; - } - break; + case GTPC_1: + case GTPC_2: + case GTPC_3: + { + int pc_index = rg_type-2; //index of principal component + rgyr=sqrt(princ_comp[pc_index]/totmass); + double rm = rgyr*totmass; + if(rm>1e-6) prefactor[pc_index]=1.0/rm; //some parts of derivate + break; + } + case GYRATION_3: //the smallest principal radius of gyration + { + rgyr=sqrt((princ_comp[1]+princ_comp[2])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[1]=1.0/rm; + prefactor[2]=1.0/rm; } - case GYRATION_2: //the midle principal radius of gyration - { - rgyr=sqrt((princ_comp[0]+princ_comp[2])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[0]=1.0/rm; - prefactor[2]=1.0/rm; - } - break; + break; + } + case GYRATION_2: //the midle principal radius of gyration + { + rgyr=sqrt((princ_comp[0]+princ_comp[2])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[0]=1.0/rm; + prefactor[2]=1.0/rm; } - case GYRATION_1: //the largest principal radius of gyration - { - rgyr=sqrt((princ_comp[0]+princ_comp[1])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[0]=1.0/rm; - prefactor[1]=1.0/rm; - } - break; + break; + } + case GYRATION_1: //the largest principal radius of gyration + { + rgyr=sqrt((princ_comp[0]+princ_comp[1])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[0]=1.0/rm; + prefactor[1]=1.0/rm; } - case ASPHERICITY: - { - rgyr=sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ - prefactor[0]= 1.0/rm; - prefactor[1]=-0.5/rm; - prefactor[2]=-0.5/rm; - } - break; + break; + } + case ASPHERICITY: + { + rgyr=sqrt((princ_comp[0]-0.5*(princ_comp[1]+princ_comp[2]))/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { + prefactor[0]= 1.0/rm; + prefactor[1]=-0.5/rm; + prefactor[2]=-0.5/rm; } - case ACYLINDRICITY: - { - rgyr=sqrt((princ_comp[1]-princ_comp[2])/totmass); - double rm = rgyr*totmass; - if (rm>1e-6){ //avoid division by zero - prefactor[1]= 1.0/rm; - prefactor[2]=-1.0/rm; - } - break; + break; + } + case ACYLINDRICITY: + { + rgyr=sqrt((princ_comp[1]-princ_comp[2])/totmass); + double rm = rgyr*totmass; + if (rm>1e-6) { //avoid division by zero + prefactor[1]= 1.0/rm; + prefactor[2]=-1.0/rm; } - case KAPPA2: // relative shape anisotropy - { - double trace = princ_comp[0]+princ_comp[1]+princ_comp[2]; - double tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2]; - rgyr=1.0-3*(tmp/(trace*trace)); - if (rgyr>1e-6){ - prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; - prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; - prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2; - } - break; + break; + } + case KAPPA2: // relative shape anisotropy + { + double trace = princ_comp[0]+princ_comp[1]+princ_comp[2]; + double tmp=princ_comp[0]*princ_comp[1]+ princ_comp[1]*princ_comp[2]+ princ_comp[0]*princ_comp[2]; + rgyr=1.0-3*(tmp/(trace*trace)); + if (rgyr>1e-6) { + prefactor[0]= -3*((princ_comp[1]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; + prefactor[1]= -3*((princ_comp[0]+princ_comp[2])-2*tmp/trace)/(trace*trace) *2; + prefactor[2]= -3*((princ_comp[0]+princ_comp[1])-2*tmp/trace)/(trace*trace) *2; } + break; + } } - if(use_masses) { - for(unsigned i=0;i > nl; - vector > nlexpo; - vector > parameter; - void setupConstants(const vector &atoms, vector > ¶meter, bool tcorr); - map > setupTypeMap(); - map > setupValueMap(); - void update_neighb(); +private: + bool pbc; + double buffer; + double delta_g_ref; + unsigned stride; + unsigned nl_update; + vector > nl; + vector > nlexpo; + vector > parameter; + void setupConstants(const vector &atoms, vector > ¶meter, bool tcorr); + map > setupTypeMap(); + map > setupValueMap(); + void update_neighb(); - public: - static void registerKeywords(Keywords& keys); - explicit Implicit(const ActionOptions&); - virtual void calculate(); +public: + static void registerKeywords(Keywords& keys); + explicit Implicit(const ActionOptions&); + virtual void calculate(); }; PLUMED_REGISTER_ACTION(Implicit,"IMPLICIT") void Implicit::registerKeywords(Keywords& keys) { - Colvar::registerKeywords(keys); - componentsAreNotOptional(keys); - useCustomisableComponents(keys); - keys.add("atoms", "ATOMS", "The atoms to be included in the calculation, e.g. the whole protein."); - keys.add("compulsory", "NL_BUFFER", "The buffer to the intrinsic cutoff used when calculating pairwise interactions."); - keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbourlist is updated."); - keys.addFlag("TEMP_CORRECTION", false, "Correct free energy of solvation constants for temperatures different from 298.15 K"); + Colvar::registerKeywords(keys); + componentsAreNotOptional(keys); + useCustomisableComponents(keys); + keys.add("atoms", "ATOMS", "The atoms to be included in the calculation, e.g. the whole protein."); + keys.add("compulsory", "NL_BUFFER", "The buffer to the intrinsic cutoff used when calculating pairwise interactions."); + keys.add("compulsory", "NL_STRIDE", "The frequency with which the neighbourlist is updated."); + keys.addFlag("TEMP_CORRECTION", false, "Correct free energy of solvation constants for temperatures different from 298.15 K"); } Implicit::Implicit(const ActionOptions&ao): - PLUMED_COLVAR_INIT(ao), - pbc(true), - buffer(0.1), - delta_g_ref(0.), - stride(10), - nl_update(0) + PLUMED_COLVAR_INIT(ao), + pbc(true), + buffer(0.1), + delta_g_ref(0.), + stride(10), + nl_update(0) { - vector atoms; - parseAtomList("ATOMS", atoms); - const unsigned size = atoms.size(); - bool tcorr = false; - parseFlag("TEMP_CORRECTION", tcorr); - parse("NL_BUFFER", buffer); - parse("NL_STRIDE", stride); + vector atoms; + parseAtomList("ATOMS", atoms); + const unsigned size = atoms.size(); + bool tcorr = false; + parseFlag("TEMP_CORRECTION", tcorr); + parse("NL_BUFFER", buffer); + parse("NL_STRIDE", stride); - bool nopbc = !pbc; - parseFlag("NOPBC", nopbc); - pbc = !nopbc; + bool nopbc = !pbc; + parseFlag("NOPBC", nopbc); + pbc = !nopbc; - checkRead(); + checkRead(); - log << " Bibliography " << plumed.cite("Bottaro S, Lindorff-Larsen K, Best R, J. Chem. Theory Comput. 9, 5641 (2013)") - << plumed.cite("Lazaridis T, Karplus M, Proteins Struct. Funct. Genet. 35, 133 (1999)"); log << "\n"; + log << " Bibliography " << plumed.cite("Bottaro S, Lindorff-Larsen K, Best R, J. Chem. Theory Comput. 9, 5641 (2013)") + << plumed.cite("Lazaridis T, Karplus M, Proteins Struct. Funct. Genet. 35, 133 (1999)"); log << "\n"; - nl.resize(size); - nlexpo.resize(size); - parameter.resize(size, vector(4, 0)); - setupConstants(atoms, parameter, tcorr); + nl.resize(size); + nlexpo.resize(size); + parameter.resize(size, vector(4, 0)); + setupConstants(atoms, parameter, tcorr); - addValueWithDerivatives(); - setNotPeriodic(); - requestAtoms(atoms); + addValueWithDerivatives(); + setNotPeriodic(); + requestAtoms(atoms); } void Implicit::update_neighb() { - const double lower_c2 = 0.24 * 0.24; // this is the cut-off for bonded atoms - const unsigned size = getNumberOfAtoms(); - for (unsigned i=0; i mlambda) mlambda = 1./parameter[j][2]; - const double c2 = (4. * mlambda + buffer) * (4. * mlambda + buffer); - if (d2 < c2 ) { - nl[i].push_back(j); - if(parameter[i][2] == parameter[j][2] && parameter[i][3] == parameter[j][3]) { - nlexpo[i].push_back(true); - } else nlexpo[i].push_back(false); - } - } + const double lower_c2 = 0.24 * 0.24; // this is the cut-off for bonded atoms + const unsigned size = getNumberOfAtoms(); + for (unsigned i=0; i mlambda) mlambda = 1./parameter[j][2]; + const double c2 = (4. * mlambda + buffer) * (4. * mlambda + buffer); + if (d2 < c2 ) { + nl[i].push_back(j); + if(parameter[i][2] == parameter[j][2] && parameter[i][3] == parameter[j][3]) { + nlexpo[i].push_back(true); + } else nlexpo[i].push_back(false); + } } + } } void Implicit::calculate() { - if(pbc) makeWhole(); - if(getExchangeStep()) nl_update = 0; - if (nl_update == 0) { - update_neighb(); - } + if(pbc) makeWhole(); + if(getExchangeStep()) nl_update = 0; + if (nl_update == 0) { + update_neighb(); + } - const unsigned size=getNumberOfAtoms(); - double bias = 0.0; - Tensor deriv_box; - unsigned nt=OpenMP::getNumThreads(); - const unsigned nn=nl.size(); - if(nt*10>nn) nt=nn/10; - if(nt==0)nt=1; - #pragma omp parallel num_threads(nt) - { - vector deriv_omp(size); - #pragma omp for reduction(+:bias) - for (unsigned i=0; inn) nt=nn/10; + if(nt==0)nt=1; + #pragma omp parallel num_threads(nt) + { + vector deriv_omp(size); + #pragma omp for reduction(+:bias) + for (unsigned i=0; i 0.25*inv_lambda_i) - { - const double inv_lambda2_i = inv_lambda_i * inv_lambda_i; - const double rij_vdwr_diff = rij - vdw_radius_i; - const double expo = exp(-inv_lambda2_i * rij_vdwr_diff * rij_vdwr_diff); - const double fact = expo * fact_ij; - fedensity += fact; - deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_i); - } + const Vector dist = delta(posi, getPosition(j)); + const double rij = dist.modulo(); + const double inv_rij = 1.0 / rij; + const double inv_rij2 = inv_rij * inv_rij; + const double fact_ij = inv_rij2 * delta_g_free_i * vdw_volume_j * INV_PI_SQRT_PI* inv_lambda_i; + const double fact_ji = inv_rij2 * delta_g_free_j * vdw_volume_i * INV_PI_SQRT_PI* inv_lambda_j; + double deriv = 0.; - // j-i interaction - if(inv_rij > 0.25*inv_lambda_j) - { - const double inv_lambda2_j = inv_lambda_j * inv_lambda_j; - const double rij_vdwr_diff = rij - vdw_radius_j; - const double expo = exp(-inv_lambda2_j * rij_vdwr_diff * rij_vdwr_diff); - const double fact = expo * fact_ji; - fedensity += fact; - deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_j); - } - } else { - // i-j interaction - if(inv_rij > 0.25*inv_lambda_i) - { - const double inv_lambda2 = inv_lambda_i * inv_lambda_i; - const double rij_vdwr_diff = rij - vdw_radius_i; - const double expo = exp(-inv_lambda2 * rij_vdwr_diff * rij_vdwr_diff); - const double fact = expo*(fact_ij + fact_ji); - fedensity += fact; - deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2); - } - } + // in this case we can calculate a single exponential + if(!nlexpo[i][i_nl]) { + // i-j interaction + if(inv_rij > 0.25*inv_lambda_i) + { + const double inv_lambda2_i = inv_lambda_i * inv_lambda_i; + const double rij_vdwr_diff = rij - vdw_radius_i; + const double expo = exp(-inv_lambda2_i * rij_vdwr_diff * rij_vdwr_diff); + const double fact = expo * fact_ij; + fedensity += fact; + deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_i); + } - const Vector dd = deriv*dist; - deriv_i += dd; - deriv_omp[j] -= dd; - } - deriv_omp[i] += deriv_i; - bias += - 0.5 * fedensity; - } - #pragma omp critical - for(unsigned i=0;i 0.25*inv_lambda_j) + { + const double inv_lambda2_j = inv_lambda_j * inv_lambda_j; + const double rij_vdwr_diff = rij - vdw_radius_j; + const double expo = exp(-inv_lambda2_j * rij_vdwr_diff * rij_vdwr_diff); + const double fact = expo * fact_ji; + fedensity += fact; + deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2_j); + } + } else { + // i-j interaction + if(inv_rij > 0.25*inv_lambda_i) + { + const double inv_lambda2 = inv_lambda_i * inv_lambda_i; + const double rij_vdwr_diff = rij - vdw_radius_i; + const double expo = exp(-inv_lambda2 * rij_vdwr_diff * rij_vdwr_diff); + const double fact = expo*(fact_ij + fact_ji); + fedensity += fact; + deriv += inv_rij * fact * (inv_rij + rij_vdwr_diff * inv_lambda2); + } } + + const Vector dd = deriv*dist; + deriv_i += dd; + deriv_omp[j] -= dd; + } + deriv_omp[i] += deriv_i; + bias += - 0.5 * fedensity; } + #pragma omp critical + for(unsigned i=0; i &atoms, vector > ¶meter, bool tcorr) { - vector > parameter_temp; - parameter_temp.resize(atoms.size()); - map > valuemap; - map > typemap; - valuemap = setupValueMap(); - typemap = setupTypeMap(); - vector moldat = plumed.getActionSet().select(); - if (moldat.size() == 1) { - log << " MOLINFO DATA found, using proper atom names\n"; - for(unsigned i=0; i > parameter_temp; + parameter_temp.resize(atoms.size()); + map > valuemap; + map > typemap; + valuemap = setupValueMap(); + typemap = setupTypeMap(); + vector moldat = plumed.getActionSet().select(); + if (moldat.size() == 1) { + log << " MOLINFO DATA found, using proper atom names\n"; + for(unsigned i=0; igetAtomName(atoms[i]); - string Rname = moldat[0]->getResidueName(atoms[i]); - string Atype = typemap[Rname][Aname]; + // Get atom and residue names + string Aname = moldat[0]->getAtomName(atoms[i]); + string Rname = moldat[0]->getResidueName(atoms[i]); + string Atype = typemap[Rname][Aname]; - // Check for terminal COOH or COO- (different atomtypes & parameters!) - if (moldat[0]->getAtomName(atoms[i]) == "OT1") { - // We create a temporary AtomNumber object to access future atoms - unsigned ai = atoms[i].index(); - AtomNumber tmp_an; - tmp_an.setIndex(ai + 2); - if (moldat[0]->getAtomName(tmp_an) == "HT2") { - // COOH - Atype = "OB"; - } else { - // COO- - Atype = "OC"; - } - } - if (moldat[0]->getAtomName(atoms[i]) == "OT2") { - unsigned ai = atoms[i].index(); - AtomNumber tmp_an; - tmp_an.setIndex(ai + 1); - if (moldat[0]->getAtomName(tmp_an) == "HT2") { - // COOH - Atype = "OH1"; - } else { - // COO- - Atype = "OC"; - } - } + // Check for terminal COOH or COO- (different atomtypes & parameters!) + if (moldat[0]->getAtomName(atoms[i]) == "OT1") { + // We create a temporary AtomNumber object to access future atoms + unsigned ai = atoms[i].index(); + AtomNumber tmp_an; + tmp_an.setIndex(ai + 2); + if (moldat[0]->getAtomName(tmp_an) == "HT2") { + // COOH + Atype = "OB"; + } else { + // COO- + Atype = "OC"; + } + } + if (moldat[0]->getAtomName(atoms[i]) == "OT2") { + unsigned ai = atoms[i].index(); + AtomNumber tmp_an; + tmp_an.setIndex(ai + 1); + if (moldat[0]->getAtomName(tmp_an) == "HT2") { + // COOH + Atype = "OH1"; + } else { + // COO- + Atype = "OC"; + } + } - // Check for H-atoms - char type; - char first = Aname.at(0); + // Check for H-atoms + char type; + char first = Aname.at(0); - // GOLDEN RULE: type is first letter, if not a number - if (!isdigit(first)){ - type = first; - // otherwise is the second - } else { - type = Aname.at(1); - } + // GOLDEN RULE: type is first letter, if not a number + if (!isdigit(first)) { + type = first; + // otherwise is the second + } else { + type = Aname.at(1); + } - if (type == 'H') { - error("EEF1-SB does not allow the use of hydrogen atoms!\n"); - } + if (type == 'H') { + error("EEF1-SB does not allow the use of hydrogen atoms!\n"); + } - // Lookup atomtype in table or throw exception if its not there - try { - parameter_temp[i] = valuemap.at(Atype); - } catch (exception &e) { - log << "Type: " << Atype << " Name: " << Aname << " Residue: " << Rname << "\n"; - error("Invalid atom type!\n"); - } + // Lookup atomtype in table or throw exception if its not there + try { + parameter_temp[i] = valuemap.at(Atype); + } catch (exception &e) { + log << "Type: " << Atype << " Name: " << Aname << " Residue: " << Rname << "\n"; + error("Invalid atom type!\n"); + } - // Temperature correction - if (tcorr && parameter[i][1] > 0.0) { - const double t0 = 298.15; - const double delta_g_ref_t0 = parameter_temp[i][1]; - const double delta_h_ref_t0 = parameter_temp[i][3]; - const double delta_cp = parameter_temp[i][4]; - const double delta_s_ref_t0 = (delta_h_ref_t0 - delta_g_ref_t0) / t0; - const double t = plumed.getAtoms().getKbT() / plumed.getAtoms().getKBoltzmann(); - parameter_temp[i][1] -= delta_s_ref_t0 * (t - t0) - delta_cp * t * std::log(t / t0) + delta_cp * (t - t0); - parameter_temp[i][2] *= parameter_temp[i][1] / delta_g_ref_t0; - } - parameter[i][0] = parameter_temp[i][0]; - parameter[i][1] = parameter_temp[i][2]; - parameter[i][2] = parameter_temp[i][5]; - parameter[i][3] = parameter_temp[i][6]; - } - } else { - error("MOLINFO DATA not found\n"); + // Temperature correction + if (tcorr && parameter[i][1] > 0.0) { + const double t0 = 298.15; + const double delta_g_ref_t0 = parameter_temp[i][1]; + const double delta_h_ref_t0 = parameter_temp[i][3]; + const double delta_cp = parameter_temp[i][4]; + const double delta_s_ref_t0 = (delta_h_ref_t0 - delta_g_ref_t0) / t0; + const double t = plumed.getAtoms().getKbT() / plumed.getAtoms().getKBoltzmann(); + parameter_temp[i][1] -= delta_s_ref_t0 * (t - t0) - delta_cp * t * std::log(t / t0) + delta_cp * (t - t0); + parameter_temp[i][2] *= parameter_temp[i][1] / delta_g_ref_t0; + } + parameter[i][0] = parameter_temp[i][0]; + parameter[i][1] = parameter_temp[i][2]; + parameter[i][2] = parameter_temp[i][5]; + parameter[i][3] = parameter_temp[i][6]; } - for(unsigned i=0; i > Implicit::setupTypeMap() { - map > typemap; - typemap = { - {"ALA", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT3"}, - {"HB1", "HA3"}, - {"HB2", "HA3"}, - {"HB3", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"ARG", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CT2"}, - {"HD1", "HA2"}, - {"HD2", "HA2"}, - {"NE", "NC2"}, - {"HE", "HC" }, - {"CZ", "C" }, - {"NH1", "NC2"}, - {"HH11", "HC" }, - {"HH12", "HC" }, - {"NH2", "NC2"}, - {"HH21", "HC" }, - {"HH22", "HC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"ASN", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CC" }, - {"OD1", "O" }, - {"ND2", "NH2"}, - {"HD21", "H" }, - {"HD22", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"ASPP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CD" }, - {"OD1", "OB" }, - {"OD2", "OH1"}, - {"HD2", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"ASP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CC" }, - {"OD1", "OC" }, - {"OD2", "OC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"CYS", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"SG", "S" }, - {"HG1", "HS" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLN", { - {"N", "NH1" }, - {"HN", "H" }, - {"CA", "CT1" }, - {"HA", "HB1" }, - {"CB", "CT2" }, - {"HB1", "HA2" }, - {"HB2", "HA2" }, - {"CG", "CT2" }, - {"HG1", "HA2" }, - {"HG2", "HA2" }, - {"CD", "CC" }, - {"OE1", "O" }, - {"NE2", "NH2" }, - {"HE21", "H" }, - {"HE22", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLUP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CD" }, - {"OE1", "OB" }, - {"OE2", "OH1"}, - {"HE2", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLU", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CC" }, - {"OE1", "OC" }, - {"OE2", "OC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"GLY", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT2"}, - {"HA1", "HB2"}, - {"HA2", "HB2"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HSD", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"ND1", "NR1"}, - {"HD1", "H" }, - {"CG", "CPH1"}, - {"CE1", "CPH2"}, - {"HE1", "HR1"}, - {"NE2", "NR2"}, - {"CD2", "CPH1"}, - {"HD2", "HR3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HIS", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"ND1", "NR2"}, - {"CG", "CPH1"}, - {"CE1", "CPH2"}, - {"HE1", "HR1"}, - {"NE2", "NR1"}, - {"HE2", "H" }, - {"CD2", "CPH1"}, - {"HD2", "HR3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HSE", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"ND1", "NR2"}, - {"CG", "CPH1"}, - {"CE1", "CPH2"}, - {"HE1", "HR1"}, - {"NE2", "NR1"}, - {"HE2", "H" }, - {"CD2", "CPH1"}, - {"HD2", "HR3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"HSP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CD2", "CPH1"}, - {"HD2", "HR1"}, - {"CG", "CPH1"}, - {"NE2", "NR3"}, - {"HE2", "H" }, - {"ND1", "NR3"}, - {"HD1", "H" }, - {"CE1", "CPH2"}, - {"HE1", "HR2"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"ILE", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT1"}, - {"HB", "HA1"}, - {"CG2", "CT3"}, - {"HG21", "HA3"}, - {"HG22", "HA3"}, - {"HG23", "HA3"}, - {"CG1", "CT2"}, - {"HG11", "HA2"}, - {"HG12", "HA2"}, - {"CD", "CT3"}, - {"HD1", "HA3"}, - {"HD2", "HA3"}, - {"HD3", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"LEU", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT1"}, - {"HG", "HA1"}, - {"CD1", "CT3"}, - {"HD11", "HA3"}, - {"HD12", "HA3"}, - {"HD13", "HA3"}, - {"CD2", "CT3"}, - {"HD21", "HA3"}, - {"HD22", "HA3"}, - {"HD23", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"LYS", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"CD", "CT2"}, - {"HD1", "HA2"}, - {"HD2", "HA2"}, - {"CE", "CT2"}, - {"HE1", "HA2"}, - {"HE2", "HA2"}, - {"NZ", "NH3"}, - {"HZ1", "HC" }, - {"HZ2", "HC" }, - {"HZ3", "HC" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"MET", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CT2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"SD", "S" }, - {"CE", "CT3"}, - {"HE1", "HA3"}, - {"HE2", "HA3"}, - {"HE3", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"PHE", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CA" }, - {"CD1", "CA" }, - {"HD1", "HP" }, - {"CE1", "CA" }, - {"HE1", "HP" }, - {"CZ", "CA" }, - {"HZ", "HP" }, - {"CD2", "CA" }, - {"HD2", "HP" }, - {"CE2", "CA" }, - {"HE2", "HP" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"PRO", { - {"N", "N" }, - {"CD", "CP3"}, - {"HD1", "HA2"}, - {"HD2", "HA2"}, - {"CA", "CP1"}, - {"HA", "HB1"}, - {"CB", "CP2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CP2"}, - {"HG1", "HA2"}, - {"HG2", "HA2"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"SER", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"OG", "OH1"}, - {"HG1", "H" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"THR", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT1"}, - {"HB", "HA1"}, - {"OG1", "OH1"}, - {"HG1", "H" }, - {"CG2", "CT3"}, - {"HG21", "HA3"}, - {"HG22", "HA3"}, - {"HG23", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - }, - {"TRP", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CY" }, - {"CD1", "CA" }, - {"HD1", "HP" }, - {"NE1", "NY" }, - {"HE1", "H" }, - {"CE2", "CPT"}, - {"CD2", "CPT"}, - {"CE3", "CAI"}, - {"HE3", "HP" }, - {"CZ3", "CA" }, - {"HZ3", "HP" }, - {"CZ2", "CAI"}, - {"HZ2", "HP" }, - {"CH2", "CA" }, - {"HH2", "HP" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"TYR", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT2"}, - {"HB1", "HA2"}, - {"HB2", "HA2"}, - {"CG", "CA" }, - {"CD1", "CA" }, - {"HD1", "HP" }, - {"CE1", "CA" }, - {"HE1", "HP" }, - {"CZ", "CA" }, - {"OH", "OH1"}, - {"HH", "H" }, - {"CD2", "CA" }, - {"HD2", "HP" }, - {"CE2", "CA" }, - {"HE2", "HP" }, - {"C", "C" }, - {"O", "O" } - } - }, - {"VAL", { - {"N", "NH1"}, - {"HN", "H" }, - {"CA", "CT1"}, - {"HA", "HB1"}, - {"CB", "CT1"}, - {"HB", "HA1"}, - {"CG1", "CT3"}, - {"HG11", "HA3"}, - {"HG12", "HA3"}, - {"HG13", "HA3"}, - {"CG2", "CT3"}, - {"HG21", "HA3"}, - {"HG22", "HA3"}, - {"HG23", "HA3"}, - {"C", "C" }, - {"O", "O" } - } - } - }; - return typemap; + map > typemap; + typemap = { + { "ALA", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT3"}, + {"HB1", "HA3"}, + {"HB2", "HA3"}, + {"HB3", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "ARG", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CT2"}, + {"HD1", "HA2"}, + {"HD2", "HA2"}, + {"NE", "NC2"}, + {"HE", "HC" }, + {"CZ", "C" }, + {"NH1", "NC2"}, + {"HH11", "HC" }, + {"HH12", "HC" }, + {"NH2", "NC2"}, + {"HH21", "HC" }, + {"HH22", "HC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "ASN", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CC" }, + {"OD1", "O" }, + {"ND2", "NH2"}, + {"HD21", "H" }, + {"HD22", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "ASPP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CD" }, + {"OD1", "OB" }, + {"OD2", "OH1"}, + {"HD2", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "ASP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CC" }, + {"OD1", "OC" }, + {"OD2", "OC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "CYS", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"SG", "S" }, + {"HG1", "HS" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLN", { + {"N", "NH1" }, + {"HN", "H" }, + {"CA", "CT1" }, + {"HA", "HB1" }, + {"CB", "CT2" }, + {"HB1", "HA2" }, + {"HB2", "HA2" }, + {"CG", "CT2" }, + {"HG1", "HA2" }, + {"HG2", "HA2" }, + {"CD", "CC" }, + {"OE1", "O" }, + {"NE2", "NH2" }, + {"HE21", "H" }, + {"HE22", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLUP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CD" }, + {"OE1", "OB" }, + {"OE2", "OH1"}, + {"HE2", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLU", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CC" }, + {"OE1", "OC" }, + {"OE2", "OC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "GLY", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT2"}, + {"HA1", "HB2"}, + {"HA2", "HB2"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HSD", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"ND1", "NR1"}, + {"HD1", "H" }, + {"CG", "CPH1"}, + {"CE1", "CPH2"}, + {"HE1", "HR1"}, + {"NE2", "NR2"}, + {"CD2", "CPH1"}, + {"HD2", "HR3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HIS", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"ND1", "NR2"}, + {"CG", "CPH1"}, + {"CE1", "CPH2"}, + {"HE1", "HR1"}, + {"NE2", "NR1"}, + {"HE2", "H" }, + {"CD2", "CPH1"}, + {"HD2", "HR3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HSE", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"ND1", "NR2"}, + {"CG", "CPH1"}, + {"CE1", "CPH2"}, + {"HE1", "HR1"}, + {"NE2", "NR1"}, + {"HE2", "H" }, + {"CD2", "CPH1"}, + {"HD2", "HR3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "HSP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CD2", "CPH1"}, + {"HD2", "HR1"}, + {"CG", "CPH1"}, + {"NE2", "NR3"}, + {"HE2", "H" }, + {"ND1", "NR3"}, + {"HD1", "H" }, + {"CE1", "CPH2"}, + {"HE1", "HR2"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "ILE", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT1"}, + {"HB", "HA1"}, + {"CG2", "CT3"}, + {"HG21", "HA3"}, + {"HG22", "HA3"}, + {"HG23", "HA3"}, + {"CG1", "CT2"}, + {"HG11", "HA2"}, + {"HG12", "HA2"}, + {"CD", "CT3"}, + {"HD1", "HA3"}, + {"HD2", "HA3"}, + {"HD3", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "LEU", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT1"}, + {"HG", "HA1"}, + {"CD1", "CT3"}, + {"HD11", "HA3"}, + {"HD12", "HA3"}, + {"HD13", "HA3"}, + {"CD2", "CT3"}, + {"HD21", "HA3"}, + {"HD22", "HA3"}, + {"HD23", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "LYS", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"CD", "CT2"}, + {"HD1", "HA2"}, + {"HD2", "HA2"}, + {"CE", "CT2"}, + {"HE1", "HA2"}, + {"HE2", "HA2"}, + {"NZ", "NH3"}, + {"HZ1", "HC" }, + {"HZ2", "HC" }, + {"HZ3", "HC" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "MET", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CT2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"SD", "S" }, + {"CE", "CT3"}, + {"HE1", "HA3"}, + {"HE2", "HA3"}, + {"HE3", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "PHE", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CA" }, + {"CD1", "CA" }, + {"HD1", "HP" }, + {"CE1", "CA" }, + {"HE1", "HP" }, + {"CZ", "CA" }, + {"HZ", "HP" }, + {"CD2", "CA" }, + {"HD2", "HP" }, + {"CE2", "CA" }, + {"HE2", "HP" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "PRO", { + {"N", "N" }, + {"CD", "CP3"}, + {"HD1", "HA2"}, + {"HD2", "HA2"}, + {"CA", "CP1"}, + {"HA", "HB1"}, + {"CB", "CP2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CP2"}, + {"HG1", "HA2"}, + {"HG2", "HA2"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "SER", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"OG", "OH1"}, + {"HG1", "H" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "THR", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT1"}, + {"HB", "HA1"}, + {"OG1", "OH1"}, + {"HG1", "H" }, + {"CG2", "CT3"}, + {"HG21", "HA3"}, + {"HG22", "HA3"}, + {"HG23", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + }, + { "TRP", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CY" }, + {"CD1", "CA" }, + {"HD1", "HP" }, + {"NE1", "NY" }, + {"HE1", "H" }, + {"CE2", "CPT"}, + {"CD2", "CPT"}, + {"CE3", "CAI"}, + {"HE3", "HP" }, + {"CZ3", "CA" }, + {"HZ3", "HP" }, + {"CZ2", "CAI"}, + {"HZ2", "HP" }, + {"CH2", "CA" }, + {"HH2", "HP" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "TYR", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT2"}, + {"HB1", "HA2"}, + {"HB2", "HA2"}, + {"CG", "CA" }, + {"CD1", "CA" }, + {"HD1", "HP" }, + {"CE1", "CA" }, + {"HE1", "HP" }, + {"CZ", "CA" }, + {"OH", "OH1"}, + {"HH", "H" }, + {"CD2", "CA" }, + {"HD2", "HP" }, + {"CE2", "CA" }, + {"HE2", "HP" }, + {"C", "C" }, + {"O", "O" } + } + }, + { "VAL", { + {"N", "NH1"}, + {"HN", "H" }, + {"CA", "CT1"}, + {"HA", "HB1"}, + {"CB", "CT1"}, + {"HB", "HA1"}, + {"CG1", "CT3"}, + {"HG11", "HA3"}, + {"HG12", "HA3"}, + {"HG13", "HA3"}, + {"CG2", "CT3"}, + {"HG21", "HA3"}, + {"HG22", "HA3"}, + {"HG23", "HA3"}, + {"C", "C" }, + {"O", "O" } + } + } + }; + return typemap; } map > Implicit::setupValueMap() { - // Volume ∆Gref ∆Gfree ∆H ∆Cp λ vdw_radius - map > valuemap; - valuemap = { - {"C", { - ANG3_TO_NM3 * 14.720, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CD", { - ANG3_TO_NM3 * 14.720, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT1", { - ANG3_TO_NM3 * 11.507, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * 0.876, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT2", { - ANG3_TO_NM3 * 18.850, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT2A", { - ANG3_TO_NM3 * 18.666, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CT3", { - ANG3_TO_NM3 * 27.941, - KCAL_TO_KJ * 1.089, - KCAL_TO_KJ * 1.089, - KCAL_TO_KJ * -1.779, - KCAL_TO_KJ * 35.6, - 1. / (ANG_TO_NM * 3.5), - 0.204, - } - }, - {"CPH1", { - ANG3_TO_NM3 * 5.275, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.080, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.18, - } - }, - {"CPH2", { - ANG3_TO_NM3 * 11.796, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.080, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.18, - } - }, - {"CPT", { - ANG3_TO_NM3 * 4.669, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * 2.220, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.186, - } - }, - {"CY", { - ANG3_TO_NM3 * 10.507, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * -0.890, - KCAL_TO_KJ * 2.220, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.199, - } - }, - {"CP1", { - ANG3_TO_NM3 * 25.458, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * -0.187, - KCAL_TO_KJ * 0.876, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.227, - } - }, - {"CP2", { - ANG3_TO_NM3 * 19.880, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.217, - } - }, - {"CP3", { - ANG3_TO_NM3 * 26.731, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * 0.372, - KCAL_TO_KJ * -0.610, - KCAL_TO_KJ * 18.6, - 1. / (ANG_TO_NM * 3.5), - 0.217, - } - }, - {"CC", { - ANG3_TO_NM3 * 16.539, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.000, - KCAL_TO_KJ * 0.0, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"CAI", { - ANG3_TO_NM3 * 18.249, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.199, - } - }, - {"CA", { - ANG3_TO_NM3 * 18.249, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * 0.057, - KCAL_TO_KJ * -0.973, - KCAL_TO_KJ * 6.9, - 1. / (ANG_TO_NM * 3.5), - 0.199, - } - }, - {"N", { - ANG3_TO_NM3 * 0.000, - KCAL_TO_KJ * -1.000, - KCAL_TO_KJ * -1.000, - KCAL_TO_KJ * -1.250, - KCAL_TO_KJ * 8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NR1", { - ANG3_TO_NM3 * 15.273, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NR2", { - ANG3_TO_NM3 * 15.111, - KCAL_TO_KJ * -3.820, - KCAL_TO_KJ * -3.820, - KCAL_TO_KJ * -4.654, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NR3", { - ANG3_TO_NM3 * 15.071, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NH1", { - ANG3_TO_NM3 * 10.197, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NH2", { - ANG3_TO_NM3 * 18.182, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NH3", { - ANG3_TO_NM3 * 18.817, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -25.000, - KCAL_TO_KJ * -18.0, - 1. / (ANG_TO_NM * 6.0), - 0.185, - } - }, - {"NC2", { - ANG3_TO_NM3 * 18.215, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -12.000, - KCAL_TO_KJ * -7.0, - 1. / (ANG_TO_NM * 6.0), - 0.185, - } - }, - {"NY", { - ANG3_TO_NM3 * 12.001, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -5.950, - KCAL_TO_KJ * -9.059, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.185, - } - }, - {"NP", { - ANG3_TO_NM3 * 4.993, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -20.000, - KCAL_TO_KJ * -25.000, - KCAL_TO_KJ * -18.0, - 1. / (ANG_TO_NM * 6.0), - 0.185, - } - }, - {"O", { - ANG3_TO_NM3 * 11.772, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.787, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.170, - } - }, - {"OB", { - ANG3_TO_NM3 * 11.694, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.330, - KCAL_TO_KJ * -5.787, - KCAL_TO_KJ * -8.8, - 1. / (ANG_TO_NM * 3.5), - 0.170, - } - }, - {"OC", { - ANG3_TO_NM3 * 12.003, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -10.000, - KCAL_TO_KJ * -12.000, - KCAL_TO_KJ * -9.4, - 1. / (ANG_TO_NM * 6.0), - 0.170, - } - }, - {"OH1", { - ANG3_TO_NM3 * 15.528, - KCAL_TO_KJ * -5.920, - KCAL_TO_KJ * -5.920, - KCAL_TO_KJ * -9.264, - KCAL_TO_KJ * -11.2, - 1. / (ANG_TO_NM * 3.5), - 0.177, - } - }, - {"OS", { - ANG3_TO_NM3 * 6.774, - KCAL_TO_KJ * -2.900, - KCAL_TO_KJ * -2.900, - KCAL_TO_KJ * -3.150, - KCAL_TO_KJ * -4.8, - 1. / (ANG_TO_NM * 3.5), - 0.177, - } - }, - {"S", { - ANG3_TO_NM3 * 20.703, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -4.475, - KCAL_TO_KJ * -39.9, - 1. / (ANG_TO_NM * 3.5), - 0.20, - } - }, - {"SM", { - ANG3_TO_NM3 * 21.306, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -3.240, - KCAL_TO_KJ * -4.475, - KCAL_TO_KJ * -39.9, - 1. / (ANG_TO_NM * 3.5), - 0.197, - } - } - }; - return valuemap; -} + // Volume ∆Gref ∆Gfree ∆H ∆Cp λ vdw_radius + map > valuemap; + valuemap = { + { "C", { + ANG3_TO_NM3 * 14.720, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CD", { + ANG3_TO_NM3 * 14.720, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT1", { + ANG3_TO_NM3 * 11.507, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * 0.876, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT2", { + ANG3_TO_NM3 * 18.850, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT2A", { + ANG3_TO_NM3 * 18.666, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CT3", { + ANG3_TO_NM3 * 27.941, + KCAL_TO_KJ * 1.089, + KCAL_TO_KJ * 1.089, + KCAL_TO_KJ * -1.779, + KCAL_TO_KJ * 35.6, + 1. / (ANG_TO_NM * 3.5), + 0.204, + } + }, + { "CPH1", { + ANG3_TO_NM3 * 5.275, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.080, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.18, + } + }, + { "CPH2", { + ANG3_TO_NM3 * 11.796, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.080, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.18, + } + }, + { "CPT", { + ANG3_TO_NM3 * 4.669, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * 2.220, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.186, + } + }, + { "CY", { + ANG3_TO_NM3 * 10.507, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * -0.890, + KCAL_TO_KJ * 2.220, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.199, + } + }, + { "CP1", { + ANG3_TO_NM3 * 25.458, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * -0.187, + KCAL_TO_KJ * 0.876, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.227, + } + }, + { "CP2", { + ANG3_TO_NM3 * 19.880, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.217, + } + }, + { "CP3", { + ANG3_TO_NM3 * 26.731, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * 0.372, + KCAL_TO_KJ * -0.610, + KCAL_TO_KJ * 18.6, + 1. / (ANG_TO_NM * 3.5), + 0.217, + } + }, + { "CC", { + ANG3_TO_NM3 * 16.539, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.000, + KCAL_TO_KJ * 0.0, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "CAI", { + ANG3_TO_NM3 * 18.249, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.199, + } + }, + { "CA", { + ANG3_TO_NM3 * 18.249, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * 0.057, + KCAL_TO_KJ * -0.973, + KCAL_TO_KJ * 6.9, + 1. / (ANG_TO_NM * 3.5), + 0.199, + } + }, + { "N", { + ANG3_TO_NM3 * 0.000, + KCAL_TO_KJ * -1.000, + KCAL_TO_KJ * -1.000, + KCAL_TO_KJ * -1.250, + KCAL_TO_KJ * 8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NR1", { + ANG3_TO_NM3 * 15.273, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NR2", { + ANG3_TO_NM3 * 15.111, + KCAL_TO_KJ * -3.820, + KCAL_TO_KJ * -3.820, + KCAL_TO_KJ * -4.654, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NR3", { + ANG3_TO_NM3 * 15.071, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NH1", { + ANG3_TO_NM3 * 10.197, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NH2", { + ANG3_TO_NM3 * 18.182, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NH3", { + ANG3_TO_NM3 * 18.817, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -25.000, + KCAL_TO_KJ * -18.0, + 1. / (ANG_TO_NM * 6.0), + 0.185, + } + }, + { "NC2", { + ANG3_TO_NM3 * 18.215, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -12.000, + KCAL_TO_KJ * -7.0, + 1. / (ANG_TO_NM * 6.0), + 0.185, + } + }, + { "NY", { + ANG3_TO_NM3 * 12.001, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -5.950, + KCAL_TO_KJ * -9.059, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.185, + } + }, + { "NP", { + ANG3_TO_NM3 * 4.993, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -20.000, + KCAL_TO_KJ * -25.000, + KCAL_TO_KJ * -18.0, + 1. / (ANG_TO_NM * 6.0), + 0.185, + } + }, + { "O", { + ANG3_TO_NM3 * 11.772, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.787, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.170, + } + }, + { "OB", { + ANG3_TO_NM3 * 11.694, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.330, + KCAL_TO_KJ * -5.787, + KCAL_TO_KJ * -8.8, + 1. / (ANG_TO_NM * 3.5), + 0.170, + } + }, + { "OC", { + ANG3_TO_NM3 * 12.003, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -10.000, + KCAL_TO_KJ * -12.000, + KCAL_TO_KJ * -9.4, + 1. / (ANG_TO_NM * 6.0), + 0.170, + } + }, + { "OH1", { + ANG3_TO_NM3 * 15.528, + KCAL_TO_KJ * -5.920, + KCAL_TO_KJ * -5.920, + KCAL_TO_KJ * -9.264, + KCAL_TO_KJ * -11.2, + 1. / (ANG_TO_NM * 3.5), + 0.177, + } + }, + { "OS", { + ANG3_TO_NM3 * 6.774, + KCAL_TO_KJ * -2.900, + KCAL_TO_KJ * -2.900, + KCAL_TO_KJ * -3.150, + KCAL_TO_KJ * -4.8, + 1. / (ANG_TO_NM * 3.5), + 0.177, + } + }, + { "S", { + ANG3_TO_NM3 * 20.703, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -4.475, + KCAL_TO_KJ * -39.9, + 1. / (ANG_TO_NM * 3.5), + 0.20, + } + }, + { "SM", { + ANG3_TO_NM3 * 21.306, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -3.240, + KCAL_TO_KJ * -4.475, + KCAL_TO_KJ * -39.9, + 1. / (ANG_TO_NM * 3.5), + 0.197, + } } + }; + return valuemap; +} +} } diff --git a/src/colvar/Jcoupling.cpp b/src/colvar/Jcoupling.cpp index d7fda854c0..d192b8bbd6 100644 --- a/src/colvar/Jcoupling.cpp +++ b/src/colvar/Jcoupling.cpp @@ -29,8 +29,8 @@ using namespace std; -namespace PLMD{ - namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR JCOUPLING /* @@ -90,242 +90,242 @@ ENDPLUMED */ //+ENDPLUMEDOC - class JCoupling : public Colvar { - private: - bool pbc; - vector coupl; - unsigned ndata; - unsigned jtype_; - enum { HAN, HAHN, CCG, NCG, CUSTOM }; - double ka_; - double kb_; - double kc_; - double kshift_; - - public: - explicit JCoupling(const ActionOptions&); - virtual void calculate(); - static void registerKeywords(Keywords& keys); - }; - - PLUMED_REGISTER_ACTION(JCoupling, "JCOUPLING") - - void JCoupling::registerKeywords(Keywords& keys) { - Colvar::registerKeywords(keys); - componentsAreNotOptional(keys); - useCustomisableComponents(keys); - keys.add("numbered", "ATOMS", "the 4 atoms involved in each of the bonds for which you wish to calculate the J-coupling. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one J-coupling will be " - "calculated for each ATOMS keyword you specify."); - keys.reset_style("ATOMS", "atoms"); - keys.addFlag("ADDCOUPLINGS", false, "Set this flag if you want to have fixed components with the experimental values."); - keys.add("compulsory", "TYPE", "Type of J-coupling to compute (HAN,HAHN,CCG,NCG,CUSTOM)"); - keys.add("optional", "A", "Karplus parameter A"); - keys.add("optional", "B", "Karplus parameter B"); - keys.add("optional", "C", "Karplus parameter C"); - keys.add("optional", "SHIFT", "Angle shift in radians"); - keys.add("numbered", "COUPLING", "Add an experimental value for each coupling"); - keys.addOutputComponent("j", "default", "the calculated J-coupling"); - keys.addOutputComponent("exp", "ADDCOUPLINGS", "the experimental J-coupling"); - } - - JCoupling::JCoupling(const ActionOptions&ao): - PLUMED_COLVAR_INIT(ao), - pbc(true), - ndata(0) - { - bool nopbc = !pbc; - parseFlag("NOPBC", nopbc); - pbc =! nopbc; - - // Read in the atoms - vector t, atoms; - for (int i = 1; ; ++i) { - parseAtomList("ATOMS", i, t ); - if (t.empty()) { - break; - } - - if (t.size() != 4) { - std::string ss; - Tools::convert(i, ss); - error("ATOMS" + ss + " keyword has the wrong number of atoms"); - } - - // This makes the distance calculation easier later on (see Torsion implementation) - atoms.push_back(t[0]); - atoms.push_back(t[1]); - atoms.push_back(t[1]); - atoms.push_back(t[2]); - atoms.push_back(t[2]); - atoms.push_back(t[3]); - t.resize(0); - } - - // We now have 6 atoms per datapoint - ndata = atoms.size()/6; - - // Parse J-Coupling type, this will determine the Karplus parameters - string string_type; - parse("TYPE", string_type); - if(string_type == "HAN") { - jtype_ = HAN; - } else if(string_type == "HAHN") { - jtype_ = HAHN; - } else if(string_type == "CCG") { - jtype_ = CCG; - } else if(string_type == "NCG") { - jtype_ = NCG; - } else if(string_type == "CUSTOM") { - jtype_ = CUSTOM; - } else { - error("Unknown J-coupling type!"); - } - - // Optionally add an experimental value (like with RDCs) - bool addcoupling = false; - parseFlag("ADDCOUPLINGS", addcoupling); - if (addcoupling) { - coupl.resize(ndata); - unsigned ntarget = 0; - for (unsigned i = 0; i < ndata; ++i) { - if (!parseNumbered("COUPLING", i+1, coupl[i])){ - break; - } - ntarget++; - } - if (ntarget != ndata) { - error("found wrong number of COUPLING values"); - } - } - - // For custom types we allow use of custom Karplus parameters - if (jtype_ == CUSTOM) { - parse("A", ka_); - parse("B", kb_); - parse("C", kc_); - parse("SHIFT", kshift_); - } - - checkRead(); - - // Set Karplus parameters - switch (jtype_) { - case HAN: - ka_ = -0.88; - kb_ = -0.61; - kc_ = -0.27; - kshift_ = pi / 3.0; - log.printf("J-coupling type is HAN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Wang A C, Bax A, J. Am. Chem. Soc. 117, 1810 (1995)") << "\n"; - break; - case HAHN: - ka_ = 7.09; - kb_ = -1.42; - kc_ = 1.55; - kshift_ = -pi / 3.0; - log.printf("J-coupling type is HAHN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Hu J-S, Bax A, J. Am. Chem. Soc. 119, 6360 (1997)") << "\n"; - break; - case CCG: - ka_ = 2.31; - kb_ = -0.87; - kc_ = 0.55; - kshift_ = (2.0 * pi) / 3.0; - log.printf("J-coupling type is CCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; - break; - case NCG: - ka_ = 1.29; - kb_ = -0.49; - kc_ = 0.37; - kshift_ = 0.0; - log.printf("J-coupling type is NCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - log << " Bibliography " - << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; - break; - case CUSTOM: - log.printf("J-coupling type is custom, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); - break; - } - - for (unsigned i = 0; i < ndata; ++i) { - log.printf(" The %uth J-Coupling is calculated from atoms : %d %d %d %d.", - i+1, atoms[2*i].serial(), atoms[2*i+1].serial(), atoms[2*i+2].serial(), atoms[2*i+3].serial()); - if (addcoupling) { - log.printf(" Experimental J-Coupling is %f.", coupl[i]); - } - log.printf("\n"); - } - - if (pbc) { - log.printf(" using periodic boundary conditions\n"); - } else { - log.printf(" without periodic boundary conditions\n"); - } - - for (unsigned i = 0; i < ndata; i++) { - std::string num; Tools::convert(i, num); - addComponentWithDerivatives("j_" + num); - componentIsNotPeriodic("j_" + num); - } - - if (addcoupling) { - for (unsigned i = 0; i < ndata; i++) { - std::string num; Tools::convert(i, num); - addComponent("exp_" + num); - componentIsNotPeriodic("exp_" + num); - Value* comp = getPntrToComponent("exp_" + num); - comp->set(coupl[i]); - } - } - - requestAtoms(atoms); - } - - void JCoupling::calculate() { - if (pbc) { - makeWhole(); - } - - // Loop through atoms, with steps of 6 atoms (one iteration per datapoint) - for (unsigned r = 0; r < (ndata * 6); r += 6) { - // Index is the datapoint index - const unsigned index = r / 6; - - // 6 atoms -> 3 vectors - Vector d0, d1, d2; - d0 = delta(getPosition(r + 1), getPosition(r + 0)); - d1 = delta(getPosition(r + 3), getPosition(r + 2)); - d2 = delta(getPosition(r + 5), getPosition(r + 4)); - - // Calculate dihedral with 3 vectors, get the derivatives - Vector dd0, dd1, dd2; - PLMD::Torsion t; - const double torsion = t.compute(d0, d1, d2, dd0, dd1, dd2); - - // Calculate the Karplus relation and its derivative - const double theta = torsion + kshift_; - const double cos_theta = cos(theta); - const double j = ka_ * cos_theta * cos_theta + kb_ * cos_theta + kc_; - const double derj = sin(theta) * (-1.0 * (2.0 * ka_ * cos_theta + kb_)); - - Value* val = getPntrToComponent(index); - val->set(j); - - setAtomsDerivatives(val, r + 0, derj * dd0); - setAtomsDerivatives(val, r + 1, derj * -dd0); - setAtomsDerivatives(val, r + 2, derj * dd1); - setAtomsDerivatives(val, r + 3, derj * -dd1); - setAtomsDerivatives(val, r + 4, derj * dd2); - setAtomsDerivatives(val, r + 5, derj * -dd2); - setBoxDerivativesNoPbc(val); - } - } +class JCoupling : public Colvar { +private: + bool pbc; + vector coupl; + unsigned ndata; + unsigned jtype_; + enum { HAN, HAHN, CCG, NCG, CUSTOM }; + double ka_; + double kb_; + double kc_; + double kshift_; + +public: + explicit JCoupling(const ActionOptions&); + virtual void calculate(); + static void registerKeywords(Keywords& keys); +}; + +PLUMED_REGISTER_ACTION(JCoupling, "JCOUPLING") + +void JCoupling::registerKeywords(Keywords& keys) { + Colvar::registerKeywords(keys); + componentsAreNotOptional(keys); + useCustomisableComponents(keys); + keys.add("numbered", "ATOMS", "the 4 atoms involved in each of the bonds for which you wish to calculate the J-coupling. " + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one J-coupling will be " + "calculated for each ATOMS keyword you specify."); + keys.reset_style("ATOMS", "atoms"); + keys.addFlag("ADDCOUPLINGS", false, "Set this flag if you want to have fixed components with the experimental values."); + keys.add("compulsory", "TYPE", "Type of J-coupling to compute (HAN,HAHN,CCG,NCG,CUSTOM)"); + keys.add("optional", "A", "Karplus parameter A"); + keys.add("optional", "B", "Karplus parameter B"); + keys.add("optional", "C", "Karplus parameter C"); + keys.add("optional", "SHIFT", "Angle shift in radians"); + keys.add("numbered", "COUPLING", "Add an experimental value for each coupling"); + keys.addOutputComponent("j", "default", "the calculated J-coupling"); + keys.addOutputComponent("exp", "ADDCOUPLINGS", "the experimental J-coupling"); +} + +JCoupling::JCoupling(const ActionOptions&ao): + PLUMED_COLVAR_INIT(ao), + pbc(true), + ndata(0) +{ + bool nopbc = !pbc; + parseFlag("NOPBC", nopbc); + pbc =! nopbc; + + // Read in the atoms + vector t, atoms; + for (int i = 1; ; ++i) { + parseAtomList("ATOMS", i, t ); + if (t.empty()) { + break; + } + + if (t.size() != 4) { + std::string ss; + Tools::convert(i, ss); + error("ATOMS" + ss + " keyword has the wrong number of atoms"); + } + + // This makes the distance calculation easier later on (see Torsion implementation) + atoms.push_back(t[0]); + atoms.push_back(t[1]); + atoms.push_back(t[1]); + atoms.push_back(t[2]); + atoms.push_back(t[2]); + atoms.push_back(t[3]); + t.resize(0); + } + + // We now have 6 atoms per datapoint + ndata = atoms.size()/6; + + // Parse J-Coupling type, this will determine the Karplus parameters + string string_type; + parse("TYPE", string_type); + if(string_type == "HAN") { + jtype_ = HAN; + } else if(string_type == "HAHN") { + jtype_ = HAHN; + } else if(string_type == "CCG") { + jtype_ = CCG; + } else if(string_type == "NCG") { + jtype_ = NCG; + } else if(string_type == "CUSTOM") { + jtype_ = CUSTOM; + } else { + error("Unknown J-coupling type!"); + } + + // Optionally add an experimental value (like with RDCs) + bool addcoupling = false; + parseFlag("ADDCOUPLINGS", addcoupling); + if (addcoupling) { + coupl.resize(ndata); + unsigned ntarget = 0; + for (unsigned i = 0; i < ndata; ++i) { + if (!parseNumbered("COUPLING", i+1, coupl[i])) { + break; + } + ntarget++; + } + if (ntarget != ndata) { + error("found wrong number of COUPLING values"); } + } + + // For custom types we allow use of custom Karplus parameters + if (jtype_ == CUSTOM) { + parse("A", ka_); + parse("B", kb_); + parse("C", kc_); + parse("SHIFT", kshift_); + } + + checkRead(); + + // Set Karplus parameters + switch (jtype_) { + case HAN: + ka_ = -0.88; + kb_ = -0.61; + kc_ = -0.27; + kshift_ = pi / 3.0; + log.printf("J-coupling type is HAN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Wang A C, Bax A, J. Am. Chem. Soc. 117, 1810 (1995)") << "\n"; + break; + case HAHN: + ka_ = 7.09; + kb_ = -1.42; + kc_ = 1.55; + kshift_ = -pi / 3.0; + log.printf("J-coupling type is HAHN, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Hu J-S, Bax A, J. Am. Chem. Soc. 119, 6360 (1997)") << "\n"; + break; + case CCG: + ka_ = 2.31; + kb_ = -0.87; + kc_ = 0.55; + kshift_ = (2.0 * pi) / 3.0; + log.printf("J-coupling type is CCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; + break; + case NCG: + ka_ = 1.29; + kb_ = -0.49; + kc_ = 0.37; + kshift_ = 0.0; + log.printf("J-coupling type is NCG, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + log << " Bibliography " + << plumed.cite("Perez C, Löhr F, Rüterjans H, Schmidt J, J. Am. Chem. Soc. 123, 7081 (2001)") << "\n"; + break; + case CUSTOM: + log.printf("J-coupling type is custom, with A: %f, B: %f, C: %f, angle shift: %f\n", ka_, kb_, kc_, kshift_); + break; + } + + for (unsigned i = 0; i < ndata; ++i) { + log.printf(" The %uth J-Coupling is calculated from atoms : %d %d %d %d.", + i+1, atoms[2*i].serial(), atoms[2*i+1].serial(), atoms[2*i+2].serial(), atoms[2*i+3].serial()); + if (addcoupling) { + log.printf(" Experimental J-Coupling is %f.", coupl[i]); + } + log.printf("\n"); + } + + if (pbc) { + log.printf(" using periodic boundary conditions\n"); + } else { + log.printf(" without periodic boundary conditions\n"); + } + + for (unsigned i = 0; i < ndata; i++) { + std::string num; Tools::convert(i, num); + addComponentWithDerivatives("j_" + num); + componentIsNotPeriodic("j_" + num); + } + + if (addcoupling) { + for (unsigned i = 0; i < ndata; i++) { + std::string num; Tools::convert(i, num); + addComponent("exp_" + num); + componentIsNotPeriodic("exp_" + num); + Value* comp = getPntrToComponent("exp_" + num); + comp->set(coupl[i]); + } + } + + requestAtoms(atoms); +} + +void JCoupling::calculate() { + if (pbc) { + makeWhole(); + } + + // Loop through atoms, with steps of 6 atoms (one iteration per datapoint) + for (unsigned r = 0; r < (ndata * 6); r += 6) { + // Index is the datapoint index + const unsigned index = r / 6; + + // 6 atoms -> 3 vectors + Vector d0, d1, d2; + d0 = delta(getPosition(r + 1), getPosition(r + 0)); + d1 = delta(getPosition(r + 3), getPosition(r + 2)); + d2 = delta(getPosition(r + 5), getPosition(r + 4)); + + // Calculate dihedral with 3 vectors, get the derivatives + Vector dd0, dd1, dd2; + PLMD::Torsion t; + const double torsion = t.compute(d0, d1, d2, dd0, dd1, dd2); + + // Calculate the Karplus relation and its derivative + const double theta = torsion + kshift_; + const double cos_theta = cos(theta); + const double j = ka_ * cos_theta * cos_theta + kb_ * cos_theta + kc_; + const double derj = sin(theta) * (-1.0 * (2.0 * ka_ * cos_theta + kb_)); + + Value* val = getPntrToComponent(index); + val->set(j); + + setAtomsDerivatives(val, r + 0, derj * dd0); + setAtomsDerivatives(val, r + 1, derj * -dd0); + setAtomsDerivatives(val, r + 2, derj * dd1); + setAtomsDerivatives(val, r + 3, derj * -dd1); + setAtomsDerivatives(val, r + 4, derj * dd2); + setAtomsDerivatives(val, r + 5, derj * -dd2); + setBoxDerivativesNoPbc(val); + } +} +} } diff --git a/src/colvar/MultiRMSD.cpp b/src/colvar/MultiRMSD.cpp index 72e62b9456..7656c232be 100644 --- a/src/colvar/MultiRMSD.cpp +++ b/src/colvar/MultiRMSD.cpp @@ -30,13 +30,13 @@ using namespace std; -namespace PLMD{ -namespace colvar{ - +namespace PLMD { +namespace colvar { + class MultiRMSD : public Colvar { - + PLMD::MultiDomainRMSD* rmsd; - bool squared; + bool squared; MultiValue myvals; ReferenceValuePack mypack; @@ -52,11 +52,11 @@ using namespace std; //+PLUMEDOC DCOLVAR MULTI-RMSD /* -Calculate the RMSD distance moved by a number of separated domains from their positions in a reference structure. +Calculate the RMSD distance moved by a number of separated domains from their positions in a reference structure. When you have large proteins the calculation of the root mean squared deviation between all the atoms in a reference -structure and the instantaneous configuration becomes prohibitively expensive. You may thus instead want to calculate +structure and the instantaneous configuration becomes prohibitively expensive. You may thus instead want to calculate the RMSD between the atoms in a set of domains of your protein and your reference structure. That is to say: \f[ @@ -64,7 +64,7 @@ d(X,X_r) = \sqrt{ \sum_{i} w_i\vert X_i - X_i' \vert^2 } \f] where here the sum is over the domains of the protein, \f$X_i\f$ represents the positions of the atoms in domain \f$i\f$ -in the instantaneous configuration and \f$X_i'\f$ is the positions of the atoms in domain \f$i\f$ in the reference +in the instantaneous configuration and \f$X_i'\f$ is the positions of the atoms in domain \f$i\f$ in the reference configuration. \f$w_i\f$ is an optional weight. The distances for each of the domains in the above sum can be calculated using the \ref DRMSD or \ref RMSD measures or @@ -109,7 +109,7 @@ positions. Here distances are calculated using the \ref DRMSD measure. \verbatim MULTI-RMSD REFERENCE=file.pdb TYPE=MULTI-DRMSD -\endverbatim +\endverbatim in this case it is possible to use the following DRMSD options in the pdb file using the REMARK syntax: \verbatim @@ -117,7 +117,7 @@ NOPBC to calculate distances without PBC LOWER_CUTOFF=# only pairs of atoms further than LOWER_CUTOFF are considered in the calculation UPPER_CUTOFF=# only pairs of atoms further than UPPER_CUTOFF are considered in the calculation \endverbatim -as shown in the following example +as shown in the following example \verbatim REMARK NOPBC @@ -141,14 +141,14 @@ ATOM 21 HB2 ALA 2 2.556 -1.051 -0.295 1.00 1.00 DIA H ATOM 22 HB3 ALA 2 2.070 -2.314 -1.490 1.00 1.00 DIA H END \endverbatim - + */ //+ENDPLUMEDOC PLUMED_REGISTER_ACTION(MultiRMSD,"MULTI-RMSD") -void MultiRMSD::registerKeywords(Keywords& keys){ +void MultiRMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV."); keys.add("compulsory","TYPE","MULTI-SIMPLE","the manner in which RMSD alignment is performed. Should be MULTI-OPTIMAL, MULTI-OPTIMAL-FAST, MULTI-SIMPLE or MULTI-DRMSD."); @@ -157,11 +157,11 @@ void MultiRMSD::registerKeywords(Keywords& keys){ } MultiRMSD::MultiRMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals) + PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals) { string reference; parse("REFERENCE",reference); - string type; + string type; type.assign("SIMPLE"); parse("TYPE",type); parseFlag("SQUARED",squared); @@ -174,16 +174,16 @@ PLUMED_COLVAR_INIT(ao),squared(false),myvals(1,0), mypack(0,0,myvals) // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + reference ); + error("missing input file " + reference ); rmsd = metricRegister().create(type,pdb); - + std::vector atoms; rmsd->getAtomRequests( atoms ); requestAtoms( atoms ); myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() ); - for(unsigned i=0;icalculate( getPositions(), getPbc(), mypack, squared ); - setValue(r); - for(unsigned i=0;i nga; @@ -81,49 +81,49 @@ class NOE : public Colvar { PLUMED_REGISTER_ACTION(NOE,"NOE") -void NOE::registerKeywords( Keywords& keys ){ +void NOE::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); useCustomisableComponents(keys); keys.add("numbered","GROUPA","the atoms involved in each of the contacts you wish to calculate. " - "Keywords like GROUPA1, GROUPA2, GROUPA3,... should be listed and one contact will be " - "calculated for each ATOM keyword you specify."); + "Keywords like GROUPA1, GROUPA2, GROUPA3,... should be listed and one contact will be " + "calculated for each ATOM keyword you specify."); keys.add("numbered","GROUPB","the atoms involved in each of the contacts you wish to calculate. " - "Keywords like GROUPB1, GROUPB2, GROUPB3,... should be listed and one contact will be " - "calculated for each ATOM keyword you specify."); + "Keywords like GROUPB1, GROUPB2, GROUPB3,... should be listed and one contact will be " + "calculated for each ATOM keyword you specify."); keys.reset_style("GROUPA","atoms"); keys.reset_style("GROUPB","atoms"); - keys.addFlag("ADDEXP",false,"Set to TRUE if you want to have fixed components with the experimental reference values."); + keys.addFlag("ADDEXP",false,"Set to TRUE if you want to have fixed components with the experimental reference values."); keys.add("numbered","NOEDIST","Add an experimental value for each NOE."); keys.addOutputComponent("noe","default","the # NOE"); keys.addOutputComponent("exp","ADDEXP","the # NOE experimental distance"); } NOE::NOE(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true) + PLUMED_COLVAR_INIT(ao), + pbc(true) { bool nopbc=!pbc; parseFlag("NOPBC",nopbc); - pbc=!nopbc; + pbc=!nopbc; // Read in the atoms vector t, ga_lista, gb_lista; - for(int i=1;;++i ){ - parseAtomList("GROUPA", i, t ); - if( t.empty() ) break; - for(unsigned j=0;j ngb; - for(int i=1;;++i ){ - parseAtomList("GROUPB", i, t ); - if( t.empty() ) break; - for(unsigned j=0;j noedist; if(addexp) { - noedist.resize( nga.size() ); + noedist.resize( nga.size() ); unsigned ntarget=0; - for(unsigned i=0;i(nga[i]); Value* val=getPntrToComponent(i); - // cycle over equivalent atoms - for(unsigned j=0;jgetClosePair(index+j).first; const unsigned i1=nl->getClosePair(index+j).second; diff --git a/src/colvar/PCARMSD.cpp b/src/colvar/PCARMSD.cpp index 3e1688e90f..f5d1cf6f2c 100644 --- a/src/colvar/PCARMSD.cpp +++ b/src/colvar/PCARMSD.cpp @@ -29,13 +29,13 @@ using namespace std; -namespace PLMD{ -namespace colvar{ - +namespace PLMD { +namespace colvar { + class PCARMSD : public Colvar { - + PLMD::RMSD* rmsd; - bool squared; + bool squared; std::vector< std::vector > eigenvectors; std::vector pdbv; std::vector pca_names; @@ -49,7 +49,7 @@ class PCARMSD : public Colvar { using namespace std; -//+PLUMEDOC DCOLVAR PCARMSD +//+PLUMEDOC DCOLVAR PCARMSD /* Calculate the PCA components ( see \cite Sutto:2010 and \cite spiwok ) for a number of provided eigenvectors and an average structure. Performs optimal alignment at every step and reports the rmsd so you know if you are far or close from the average structure. It takes the average structure and eigenvectors in form of a pdb. @@ -58,17 +58,17 @@ Note that beta and occupancy values in the pdb are neglected and all the weights \par Examples \verbatim -PCARMSD AVERAGE=file.pdb EIGENVECTORS=eigenvectors.pdb +PCARMSD AVERAGE=file.pdb EIGENVECTORS=eigenvectors.pdb \endverbatim -The input is taken so to be compatible with the output you get from g_covar utility of gromacs (suitably adapted to have a pdb input format). +The input is taken so to be compatible with the output you get from g_covar utility of gromacs (suitably adapted to have a pdb input format). */ //+ENDPLUMEDOC PLUMED_REGISTER_ACTION(PCARMSD,"PCARMSD") -void PCARMSD::registerKeywords(Keywords& keys){ +void PCARMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","AVERAGE","a file in pdb format containing the reference structure and the atoms involved in the CV."); keys.add("compulsory","EIGENVECTORS","a file in pdb format containing the reference structure and the atoms involved in the CV."); @@ -79,35 +79,35 @@ void PCARMSD::registerKeywords(Keywords& keys){ } PCARMSD::PCARMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao),squared(true) + PLUMED_COLVAR_INIT(ao),squared(true) { string f_average; parse("AVERAGE",f_average); - string type; + string type; type.assign("OPTIMAL"); string f_eigenvectors; parse("EIGENVECTORS",f_eigenvectors); bool sq; parseFlag("SQUARED-ROOT",sq); - if (sq){ squared=false; } + if (sq) { squared=false; } checkRead(); PDB pdb; // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(f_average,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + f_average ); + error("missing input file " + f_average ); rmsd = new RMSD(); bool remove_com=true; bool normalize_weights=true; // here align and displace are a simple vector of ones - std::vector align; align=pdb.getOccupancy();for(unsigned i=0;i displace; displace=pdb.getBeta();for(unsigned i=0;i align; align=pdb.getOccupancy(); for(unsigned i=0; i displace; displace=pdb.getBeta(); for(unsigned i=0; iset(align,displace,pdb.getPositions(),type,remove_com,normalize_weights); requestAtoms( pdb.getAtomNumbers() ); - addComponentWithDerivatives("residual"); componentIsNotPeriodic("residual"); + addComponentWithDerivatives("residual"); componentIsNotPeriodic("residual"); log.printf(" average from file %s\n",f_average.c_str()); log.printf(" which contains %d atoms\n",getNumberOfAtoms()); @@ -116,7 +116,7 @@ PLUMED_COLVAR_INIT(ao),squared(true) log<<" Bibliography "< aaa; @@ -126,94 +126,94 @@ PLUMED_COLVAR_INIT(ao),squared(true) { log<<" Opening the eigenvectors file "< > drotdpos(3,3); - std::vector alignedpos; - std::vector centeredpos; - std::vector centeredref; - std::vector ddistdpos; - double r=rmsd->calc_PCAelements( getPositions(), ddistdpos, rotation , drotdpos , alignedpos ,centeredpos, centeredref ,squared); - invrotation=rotation.transpose(); - - Value* verr=getPntrToComponent("residual"); - verr->set(r); - for(unsigned iat=0;iat der; - der.resize(getNumberOfAtoms()); - - - for(unsigned i=0;iset(val); - // here the loop is reversed to better suit the structure of the derivative of the rotation matrix - double tmp1; - for(unsigned a=0;a<3;a++){ - for(unsigned b=0;b<3;b++){ - tmp1=0.; - for(unsigned n=0;n > drotdpos(3,3); + std::vector alignedpos; + std::vector centeredpos; + std::vector centeredref; + std::vector ddistdpos; + double r=rmsd->calc_PCAelements( getPositions(), ddistdpos, rotation, drotdpos, alignedpos,centeredpos, centeredref,squared); + invrotation=rotation.transpose(); + + Value* verr=getPntrToComponent("residual"); + verr->set(r); + for(unsigned iat=0; iat der; + der.resize(getNumberOfAtoms()); + + + for(unsigned i=0; iset(val); + // here the loop is reversed to better suit the structure of the derivative of the rotation matrix + double tmp1; + for(unsigned a=0; a<3; a++) { + for(unsigned b=0; b<3; b++) { + tmp1=0.; + for(unsigned n=0; n atom; parseAtomList("SPINLABEL",atom); @@ -118,24 +118,24 @@ pbc(true) // Read in the atoms vector t, ga_lista, gb_lista; - for(int i=1;;++i ){ - parseAtomList("GROUPA", i, t ); - if( t.empty() ) break; - for(unsigned j=0;j exppre; if(addexp) { - exppre.resize( nga.size() ); + exppre.resize( nga.size() ); unsigned ntarget=0; - for(unsigned i=0;iset(exppre[i]); } } @@ -213,22 +213,22 @@ pbc(true) checkRead(); } -PRE::~PRE(){ +PRE::~PRE() { delete nl; -} +} void PRE::calculate() { // cycle over the number of PRE -#pragma omp parallel for num_threads(OpenMP::getNumThreads()) - for(unsigned i=0;i deriv; + #pragma omp parallel for num_threads(OpenMP::getNumThreads()) + for(unsigned i=0; i deriv; Tensor dervir; double pre=0; unsigned index=0; - for(unsigned k=0; kgetClosePair(index+j).first; @@ -257,7 +257,7 @@ void PRE::calculate() val->set(ratio); setBoxDerivatives(val, fact*dervir); - for(unsigned j=0;jgetClosePair(index+j).first; const unsigned i1=nl->getClosePair(index+j).second; setAtomsDerivatives(val, i0, fact*deriv[j]); diff --git a/src/colvar/PathMSD.cpp b/src/colvar/PathMSD.cpp index 7d1cca0918..cdfd96ee1d 100644 --- a/src/colvar/PathMSD.cpp +++ b/src/colvar/PathMSD.cpp @@ -24,26 +24,26 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR PATHMSD /* -This Colvar calculates path collective variables. +This Colvar calculates path collective variables. -This is the Path Collective Variables implementation +This is the Path Collective Variables implementation ( see \cite brand07 ). -This variable computes the progress along a given set of frames that is provided -in input ("sss" component) and the distance from them ("zzz" component). +This variable computes the progress along a given set of frames that is provided +in input ("sss" component) and the distance from them ("zzz" component). (see below). \par Examples -Here below is a case where you have defined three frames and you want to +Here below is a case where you have defined three frames and you want to calculate the progress along the path and the distance from it in p1 \verbatim -p1: PATHMSD REFERENCE=file.pdb LAMBDA=500.0 NEIGH_STRIDE=4 NEIGH_SIZE=8 +p1: PATHMSD REFERENCE=file.pdb LAMBDA=500.0 NEIGH_STRIDE=4 NEIGH_SIZE=8 PRINT ARG=p1.sss,p1.zzz STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim @@ -60,7 +60,7 @@ is shared, as well as most input options. */ //+ENDPLUMEDOC - + class PathMSD : public PathMSDBase { public: explicit PathMSD(const ActionOptions&); @@ -69,7 +69,7 @@ class PathMSD : public PathMSDBase { PLUMED_REGISTER_ACTION(PathMSD,"PATHMSD") -void PathMSD::registerKeywords(Keywords& keys){ +void PathMSD::registerKeywords(Keywords& keys) { PathMSDBase::registerKeywords(keys); componentsAreNotOptional(keys); keys.addOutputComponent("sss","default","the position on the path"); @@ -77,7 +77,7 @@ void PathMSD::registerKeywords(Keywords& keys){ } PathMSD::PathMSD(const ActionOptions&ao): -Action(ao),PathMSDBase(ao) + Action(ao),PathMSDBase(ao) { checkRead(); @@ -87,12 +87,12 @@ Action(ao),PathMSDBase(ao) // no need to read anything addComponentWithDerivatives("sss"); componentIsNotPeriodic("sss"); addComponentWithDerivatives("zzz"); componentIsNotPeriodic("zzz"); - requestAtoms(pdbv[0].getAtomNumbers()); + requestAtoms(pdbv[0].getAtomNumbers()); double i=1.; - for(unsigned it=0 ;it v; v.push_back(i); - indexvec.push_back(v);i+=1.; + for(unsigned it=0 ; it v; v.push_back(i); + indexvec.push_back(v); i+=1.; } } diff --git a/src/colvar/PathMSDBase.cpp b/src/colvar/PathMSDBase.cpp index 6e283b27b8..cda02bdb98 100644 --- a/src/colvar/PathMSDBase.cpp +++ b/src/colvar/PathMSDBase.cpp @@ -31,10 +31,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -void PathMSDBase::registerKeywords(Keywords& keys){ +void PathMSDBase::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.remove("NOPBC"); keys.add("compulsory","LAMBDA","the lambda parameter is needed for smoothing, is in the units of plumed"); @@ -44,10 +44,10 @@ void PathMSDBase::registerKeywords(Keywords& keys){ } PathMSDBase::PathMSDBase(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -neigh_size(-1), -neigh_stride(-1), -nframes(0) + PLUMED_COLVAR_INIT(ao), + neigh_size(-1), + neigh_stride(-1), + nframes(0) { parse("LAMBDA",lambda); parse("NEIGH_SIZE",neigh_size); @@ -61,46 +61,46 @@ nframes(0) { log<<"Opening reference file "<0 || neigh_size>0){ - if(neigh_size>int(nframes)){ - log.printf(" List size required ( %d ) is too large: resizing to the maximum number of frames required: %u \n",neigh_size,nframes); - neigh_size=nframes; - } - log.printf(" Neighbor list enabled: \n"); - log.printf(" size : %d elements\n",neigh_size); - log.printf(" stride : %d timesteps \n",neigh_stride); - }else{ - log.printf(" Neighbor list NOT enabled \n"); + } + if(neigh_stride>0 || neigh_size>0) { + if(neigh_size>int(nframes)) { + log.printf(" List size required ( %d ) is too large: resizing to the maximum number of frames required: %u \n",neigh_size,nframes); + neigh_size=nframes; + } + log.printf(" Neighbor list enabled: \n"); + log.printf(" size : %d elements\n",neigh_size); + log.printf(" stride : %d timesteps \n",neigh_stride); + } else { + log.printf(" Neighbor list NOT enabled \n"); } } -void PathMSDBase::calculate(){ +void PathMSDBase::calculate() { if(neigh_size>0 && getExchangeStep()) error("Neighbor lists for this collective variable are not compatible with replica exchange, sorry for that!"); @@ -108,12 +108,12 @@ void PathMSDBase::calculate(){ // resize the list to full - if(imgVec.empty()){ // this is the signal that means: recalculate all - imgVec.resize(nframes); - for(unsigned i=0;i tmp_derivs2(imgVec.size()*nat); // if imgVec.size() is less than nframes, it means that only some msd will be calculated - for(unsigned i=rank;i val_s_path; - if(labels.size()>0){ - for(unsigned i=0;i0) { + for(unsigned i=0; i s_path(val_s_path.size());for(unsigned i=0;i s_path(val_s_path.size()); for(unsigned i=0; iset(s_path[i]) ;} + for(unsigned i=0; iset(s_path[i]) ;} val_z_path->set(-(1./lambda)*std::log(partition)); - for(unsigned j=0;j0){ - //if( int(getStep())%int(neigh_stride/getTimeStep())==0 ){ - // enforce consistency: the stride is in time steps - if( int(getStep())%int(neigh_stride)==0 ){ - - // next round do it all:empty the vector - imgVec.clear(); - } - // time to analyze the results: - if(imgVec.size()==nframes){ - //sort by msd - sort(imgVec.begin(), imgVec.end(), imgOrderByDist()); - //resize - imgVec.resize(neigh_size); - } + if (neigh_size>0) { + //if( int(getStep())%int(neigh_stride/getTimeStep())==0 ){ + // enforce consistency: the stride is in time steps + if( int(getStep())%int(neigh_stride)==0 ) { + + // next round do it all:empty the vector + imgVec.clear(); + } + // time to analyze the results: + if(imgVec.size()==nframes) { + //sort by msd + sort(imgVec.begin(), imgVec.end(), imgOrderByDist()); + //resize + imgVec.resize(neigh_size); + } } //log.printf("CALCULATION DONE! \n"); } diff --git a/src/colvar/PathMSDBase.h b/src/colvar/PathMSDBase.h index 4451bffc75..dae1603cb5 100644 --- a/src/colvar/PathMSDBase.h +++ b/src/colvar/PathMSDBase.h @@ -29,34 +29,34 @@ #include "tools/RMSD.h" #include "tools/Tools.h" -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { class PathMSDBase : public Colvar { -/// this class is a general container for path stuff +/// this class is a general container for path stuff class ImagePath { - public: - // cardinal indexing: needed to map over msd - unsigned index; - // spiwok indexing - std::vector property; - // distance - double distance; - // similarity (exp - lambda distance) or other - double similarity; - // derivatives of the distance - std::vector distder; - // here one can add a pointer to a value (hypothetically providing a distance from a point) + public: + // cardinal indexing: needed to map over msd + unsigned index; + // spiwok indexing + std::vector property; + // distance + double distance; + // similarity (exp - lambda distance) or other + double similarity; + // derivatives of the distance + std::vector distder; + // here one can add a pointer to a value (hypothetically providing a distance from a point) }; struct imgOrderByDist { - bool operator ()(ImagePath const& a, ImagePath const& b) { - return (a).distance < (b).distance; - } + bool operator ()(ImagePath const& a, ImagePath const& b) { + return (a).distance < (b).distance; + } }; struct imgOrderBySimilarity { - bool operator ()(ImagePath const& a, ImagePath const& b) { - return (a).similarity > (b).similarity; - } + bool operator ()(ImagePath const& a, ImagePath const& b) { + return (a).similarity > (b).similarity; + } }; double lambda; @@ -66,7 +66,7 @@ class PathMSDBase : public Colvar { std::string reference; std::vector derivs_s; std::vector derivs_z; - std::vector imgVec; // this can be used for doing neighlist + std::vector imgVec; // this can be used for doing neighlist protected: std::vector pdbv; std::vector labels; diff --git a/src/colvar/Position.cpp b/src/colvar/Position.cpp index ab34c3ae11..a381e039e0 100644 --- a/src/colvar/Position.cpp +++ b/src/colvar/Position.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR POSITION /* @@ -37,7 +37,7 @@ Calculate the components of the position of an atom. Notice that single components will not have the proper periodicity! If you need the values to be consistent through PBC you should use SCALED_COMPONENTS, -which defines values that by construction are in the -0.5,0.5 domain. This is +which defines values that by construction are in the -0.5,0.5 domain. This is similar to the equivalent flag for \ref DISTANCE. Also notice that by default the minimal image distance from the origin is considered (can be changed with NOPBC). @@ -45,7 +45,7 @@ origin is considered (can be changed with NOPBC). \attention This variable should be used with extreme care since it allows to easily go into troubles. See comments below. -This variable can be safely used only if +This variable can be safely used only if Hamiltonian is not invariant for translation (i.e. there are other absolute positions which are biased, e.g. by position restraints) and cell size and shapes are fixed through the simulation. @@ -65,7 +65,7 @@ PRINT ARG=p.x,p.y,p.z */ //+ENDPLUMEDOC - + class Position : public Colvar { bool scaled_components; bool pbc; @@ -79,7 +79,7 @@ class Position : public Colvar { PLUMED_REGISTER_ACTION(Position,"POSITION") -void Position::registerKeywords( Keywords& keys ){ +void Position::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); keys.add("atoms","ATOM","the atom number"); @@ -93,9 +93,9 @@ void Position::registerKeywords( Keywords& keys ){ } Position::Position(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -scaled_components(false), -pbc(true) + PLUMED_COLVAR_INIT(ao), + scaled_components(false), + pbc(true) { vector atoms; parseAtomList("ATOM",atoms); @@ -111,7 +111,7 @@ pbc(true) if(pbc) log.printf(" using periodic boundary conditions\n"); else log.printf(" without periodic boundary conditions\n"); - if(scaled_components){ + if(scaled_components) { addComponentWithDerivatives("a"); componentIsPeriodic("a","-0.5","+0.5"); addComponentWithDerivatives("b"); componentIsPeriodic("b","-0.5","+0.5"); addComponentWithDerivatives("c"); componentIsPeriodic("c","-0.5","+0.5"); @@ -127,16 +127,16 @@ pbc(true) // calculator -void Position::calculate(){ +void Position::calculate() { Vector distance; - if(pbc){ + if(pbc) { distance=pbcDistance(Vector(0.0,0.0,0.0),getPosition(0)); } else { distance=delta(Vector(0.0,0.0,0.0),getPosition(0)); } - if(scaled_components){ + if(scaled_components) { Value* valuea=getPntrToComponent("a"); Value* valueb=getPntrToComponent("b"); Value* valuec=getPntrToComponent("c"); diff --git a/src/colvar/PropertyMap.cpp b/src/colvar/PropertyMap.cpp index 89658cfad4..a8a21fef20 100644 --- a/src/colvar/PropertyMap.cpp +++ b/src/colvar/PropertyMap.cpp @@ -24,10 +24,10 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR PROPERTYMAP +//+PLUMEDOC COLVAR PROPERTYMAP /* Calculate generic property maps. @@ -42,7 +42,7 @@ Y=\frac{\sum_i Y_i*\exp(-\lambda D_i(x))}{\sum_i \exp(-\lambda D_i(x))} \\ zzz=-\frac{1}{\lambda}\log(\sum_i \exp(-\lambda D_i(x))) \f} -where the parameters \f$X_i\f$ and \f$Y_i\f$ are provided in the input pdb (allv.pdb in this case) and +where the parameters \f$X_i\f$ and \f$Y_i\f$ are provided in the input pdb (allv.pdb in this case) and \f$D_i(x)\f$ is the MSD after optimal alignment calculated on the pdb frames you input (see Kearsley). \par Examples @@ -55,17 +55,17 @@ note that NEIGH_STRIDE=4 NEIGH_SIZE=8 control the neighborlist parameter (option recommended for performance) and states that the neighbor list will be calculated every 4 timesteps and consider only the closest 8 member to the actual md snapshots. -In this case the input line instructs plumed to look for two properties X and Y with attached values in the REMARK +In this case the input line instructs plumed to look for two properties X and Y with attached values in the REMARK line of the reference pdb (Note: No spaces from X and = and 1 !!!!). e.g. \verbatim -REMARK X=1 Y=2 +REMARK X=1 Y=2 ATOM 1 CL ALA 1 -3.171 0.295 2.045 1.00 1.00 ATOM 5 CLP ALA 1 -1.819 -0.143 1.679 1.00 1.00 ....... END -REMARK X=2 Y=3 +REMARK X=2 Y=3 ATOM 1 CL ALA 1 -3.175 0.365 2.024 1.00 1.00 ATOM 5 CLP ALA 1 -1.814 -0.106 1.685 1.00 1.00 .... @@ -78,7 +78,7 @@ is shared, as well as most input options. */ //+ENDPLUMEDOC - + class PropertyMap : public PathMSDBase { public: explicit PropertyMap(const ActionOptions&); @@ -87,7 +87,7 @@ class PropertyMap : public PathMSDBase { PLUMED_REGISTER_ACTION(PropertyMap,"PROPERTYMAP") -void PropertyMap::registerKeywords(Keywords& keys){ +void PropertyMap::registerKeywords(Keywords& keys) { PathMSDBase::registerKeywords(keys); keys.add("compulsory","PROPERTY","the property to be used in the indexing: this goes in the REMARK field of the reference"); ActionWithValue::useCustomisableComponents(keys); @@ -95,45 +95,45 @@ void PropertyMap::registerKeywords(Keywords& keys){ } PropertyMap::PropertyMap(const ActionOptions&ao): -Action(ao), -PathMSDBase(ao) + Action(ao), + PathMSDBase(ao) { - // this is the only additional keyword needed + // this is the only additional keyword needed parseVector("PROPERTY",labels); checkRead(); log<<" Bibliography " - < myv(pdbv[i].getRemark()); - // now look for X=1.34555 Y=5.6677 - vector labelvals; - for(unsigned j=0;j myv(pdbv[i].getRemark()); + // now look for X=1.34555 Y=5.6677 + vector labelvals; + for(unsigned j=0; j atoms; parseAtomList("ATOMS",atoms); if(atoms.size()!=5 && atoms.size()!=6) error("only for 5 or 6-membered rings"); checkRead(); - - if(atoms.size()==5){ + + if(atoms.size()==5) { log.printf(" between atoms %d %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial(),atoms[4].serial()); - } else if(atoms.size()==6){ + } else if(atoms.size()==6) { log.printf(" between atoms %d %d %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial(),atoms[4].serial(),atoms[5].serial()); } else error("ATOMS should specify 5 atoms"); - - if(atoms.size()==5){ + + if(atoms.size()==5) { addComponentWithDerivatives("phs"); componentIsPeriodic("phs","-pi","pi"); addComponentWithDerivatives("amp"); componentIsNotPeriodic("amp"); addComponentWithDerivatives("Zx"); componentIsNotPeriodic("Zx"); addComponentWithDerivatives("Zy"); componentIsNotPeriodic("Zy"); - } else if(atoms.size()==6){ + } else if(atoms.size()==6) { addComponentWithDerivatives("qx"); componentIsNotPeriodic("qx"); addComponentWithDerivatives("qy"); componentIsNotPeriodic("qy"); addComponentWithDerivatives("qz"); componentIsNotPeriodic("qz"); @@ -134,27 +134,27 @@ PLUMED_COLVAR_INIT(ao) } // calculator -void Puckering::calculate(){ +void Puckering::calculate() { makeWhole(); if(getNumberOfAtoms()==5) calculate5m(); else calculate6m(); } -void Puckering::calculate5m(){ +void Puckering::calculate5m() { Vector d0,d1,d2,d3,d4,d5; - + d0=delta(getPosition(2),getPosition(1)); d1=delta(getPosition(3),getPosition(2)); d2=delta(getPosition(4),getPosition(3)); d3=delta(getPosition(4),getPosition(3)); d4=delta(getPosition(0),getPosition(4)); d5=delta(getPosition(1),getPosition(0)); - + Vector dd0,dd1,dd2,dd3,dd4,dd5; - + PLMD::Torsion t; - + double v1=t.compute(d0,d1,d2,dd0,dd1,dd2); double v3=t.compute(d3,d4,d5,dd3,dd4,dd5); @@ -162,31 +162,31 @@ void Puckering::calculate5m(){ double Zy=(v1-v3)/(2.0*sin(4.0*pi/5.0)); double phase=atan2(Zy,Zx); double amplitude=sqrt(Zx*Zx+Zy*Zy); - + Vector dZx_dR[5]; Vector dZy_dR[5]; - + dZx_dR[0]=(dd5-dd4); dZx_dR[1]=(dd0-dd5); dZx_dR[2]=(dd1-dd0); dZx_dR[3]=(dd2+dd3-dd1); dZx_dR[4]=(dd4-dd3-dd2); - + dZy_dR[0]=(dd4-dd5); dZy_dR[1]=(dd0+dd5); dZy_dR[2]=(dd1-dd0); dZy_dR[3]=(dd2-dd3-dd1); dZy_dR[4]=(dd3-dd4-dd2); - - for(unsigned j=0;j<5;j++) dZx_dR[j]*=(1.0/(2.0*cos(4.0*pi/5.0))); - for(unsigned j=0;j<5;j++) dZy_dR[j]*=(1.0/(2.0*sin(4.0*pi/5.0))); - + + for(unsigned j=0; j<5; j++) dZx_dR[j]*=(1.0/(2.0*cos(4.0*pi/5.0))); + for(unsigned j=0; j<5; j++) dZy_dR[j]*=(1.0/(2.0*sin(4.0*pi/5.0))); + Vector dphase_dR[5]; - for(unsigned j=0;j<5;j++) dphase_dR[j]=(1.0/(Zx*Zx+Zy*Zy))*(-Zy*dZx_dR[j] + Zx*dZy_dR[j]); - + for(unsigned j=0; j<5; j++) dphase_dR[j]=(1.0/(Zx*Zx+Zy*Zy))*(-Zy*dZx_dR[j] + Zx*dZy_dR[j]); + Vector damplitude_dR[5]; - for(unsigned j=0;j<5;j++) damplitude_dR[j]=(1.0/amplitude)*(Zx*dZx_dR[j] + Zy*dZy_dR[j]); - + for(unsigned j=0; j<5; j++) damplitude_dR[j]=(1.0/amplitude)*(Zx*dZx_dR[j] + Zy*dZy_dR[j]); + Value* vzx=getPntrToComponent("Zx"); vzx->set(Zx); setAtomsDerivatives (vzx,0, dZx_dR[0]); @@ -195,7 +195,7 @@ void Puckering::calculate5m(){ setAtomsDerivatives (vzx,3, dZx_dR[3]); setAtomsDerivatives (vzx,4, dZx_dR[4]); setBoxDerivativesNoPbc(vzx); - + Value* vzy=getPntrToComponent("Zy"); vzy->set(Zy); setAtomsDerivatives (vzy,0, dZy_dR[0]); @@ -214,7 +214,7 @@ void Puckering::calculate5m(){ setAtomsDerivatives (vph,3, dphase_dR[3]); setAtomsDerivatives (vph,4, dphase_dR[4]); setBoxDerivativesNoPbc(vph); - + Value* vam=getPntrToComponent("amp"); vam->set(amplitude); setAtomsDerivatives (vam,0, damplitude_dR[0]); @@ -224,22 +224,22 @@ void Puckering::calculate5m(){ setAtomsDerivatives (vam,4, damplitude_dR[4]); setBoxDerivativesNoPbc(vam); - + } -void Puckering::calculate6m(){ +void Puckering::calculate6m() { vector r(6); - for(unsigned i=0;i<6;i++) r[i]=getPosition(i); + for(unsigned i=0; i<6; i++) r[i]=getPosition(i); vector R(6); Vector center; - for(unsigned j=0;j<6;j++) center+=r[j]/6.0; - for(unsigned j=0;j<6;j++) R[j]=(r[j]-center); + for(unsigned j=0; j<6; j++) center+=r[j]/6.0; + for(unsigned j=0; j<6; j++) R[j]=(r[j]-center); Vector Rp,Rpp; - for(unsigned j=0;j<6;j++) Rp +=R[j]*sin(2.0/6.0*pi*j); - for(unsigned j=0;j<6;j++) Rpp+=R[j]*cos(2.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) Rp +=R[j]*sin(2.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) Rpp+=R[j]*cos(2.0/6.0*pi*j); Vector n=crossProduct(Rp,Rpp); Vector nhat=n/modulo(n); @@ -252,165 +252,165 @@ void Puckering::calculate6m(){ Tensor dnhat_dRpp=matmul(dnhat_dn,dn_dRpp); vector z(6); - for(unsigned j=0;j<6;j++) z[j]=dotProduct(R[j],nhat); + for(unsigned j=0; j<6; j++) z[j]=dotProduct(R[j],nhat); vector > dz_dR(6); - for(unsigned j=0;j<6;j++) dz_dR[j].resize(6); + for(unsigned j=0; j<6; j++) dz_dR[j].resize(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - if(i==j) dz_dR[i][j]+=nhat; - dz_dR[i][j]+=matmul(R[i],dnhat_dRp)*sin(2.0/6.0*pi*j); - dz_dR[i][j]+=matmul(R[i],dnhat_dRpp)*cos(2.0/6.0*pi*j); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + if(i==j) dz_dR[i][j]+=nhat; + dz_dR[i][j]+=matmul(R[i],dnhat_dRp)*sin(2.0/6.0*pi*j); + dz_dR[i][j]+=matmul(R[i],dnhat_dRpp)*cos(2.0/6.0*pi*j); + } double B=0.0; - for(unsigned j=0;j<6;j++) B+=z[j]*cos(4.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) B+=z[j]*cos(4.0/6.0*pi*j); vector dB_dR(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - dB_dR[i]+=dz_dR[j][i]*cos(4.0/6.0*pi*j); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + dB_dR[i]+=dz_dR[j][i]*cos(4.0/6.0*pi*j); + } Vector Bsum; - for(unsigned j=0;j<6;j++) Bsum+=dB_dR[j]; - for(unsigned j=0;j<6;j++) dB_dR[j]-=Bsum/6.0;; + for(unsigned j=0; j<6; j++) Bsum+=dB_dR[j]; + for(unsigned j=0; j<6; j++) dB_dR[j]-=Bsum/6.0;; double A=0.0; - for(unsigned j=0;j<6;j++) A+=z[j]*sin(4.0/6.0*pi*j); + for(unsigned j=0; j<6; j++) A+=z[j]*sin(4.0/6.0*pi*j); vector dA_dR(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - dA_dR[i]+=dz_dR[j][i]*sin(4.0/6.0*pi*j); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + dA_dR[i]+=dz_dR[j][i]*sin(4.0/6.0*pi*j); + } Vector Asum; - for(unsigned j=0;j<6;j++) Asum+=dA_dR[j]; - for(unsigned j=0;j<6;j++) dA_dR[j]-=Asum/6.0;; + for(unsigned j=0; j<6; j++) Asum+=dA_dR[j]; + for(unsigned j=0; j<6; j++) dA_dR[j]-=Asum/6.0;; double C=0.0; - for(unsigned j=0;j<6;j++) C+=z[j]*Tools::fastpow(-1.0,(j)); + for(unsigned j=0; j<6; j++) C+=z[j]*Tools::fastpow(-1.0,(j)); vector dC_dR(6); - for(unsigned i=0;i<6;i++) for(unsigned j=0;j<6;j++){ - dC_dR[i]+=dz_dR[j][i]*Tools::fastpow(-1.0,(j)); - } + for(unsigned i=0; i<6; i++) for(unsigned j=0; j<6; j++) { + dC_dR[i]+=dz_dR[j][i]*Tools::fastpow(-1.0,(j)); + } Vector Csum; - for(unsigned j=0;j<6;j++) Csum+=dC_dR[j]; - for(unsigned j=0;j<6;j++) dC_dR[j]-=Csum/6.0;; + for(unsigned j=0; j<6; j++) Csum+=dC_dR[j]; + for(unsigned j=0; j<6; j++) dC_dR[j]-=Csum/6.0;; // qx - double qx = A/sqrt(3); + double qx = A/sqrt(3); // qx derivaties - vector dqx_dR(6); - for(unsigned j=0;j<6;j++){ - dqx_dR[j]=1/sqrt(3) * dA_dR[j]; - } + vector dqx_dR(6); + for(unsigned j=0; j<6; j++) { + dqx_dR[j]=1/sqrt(3) * dA_dR[j]; + } - Value* vqx=getPntrToComponent("qx"); - vqx->set(qx); - setAtomsDerivatives (vqx,0, dqx_dR[0] ); - setAtomsDerivatives (vqx,1, dqx_dR[1] ); - setAtomsDerivatives (vqx,2, dqx_dR[2] ); - setAtomsDerivatives (vqx,3, dqx_dR[3] ); - setAtomsDerivatives (vqx,4, dqx_dR[4] ); - setAtomsDerivatives (vqx,5, dqx_dR[5] ); - setBoxDerivativesNoPbc(vqx); + Value* vqx=getPntrToComponent("qx"); + vqx->set(qx); + setAtomsDerivatives (vqx,0, dqx_dR[0] ); + setAtomsDerivatives (vqx,1, dqx_dR[1] ); + setAtomsDerivatives (vqx,2, dqx_dR[2] ); + setAtomsDerivatives (vqx,3, dqx_dR[3] ); + setAtomsDerivatives (vqx,4, dqx_dR[4] ); + setAtomsDerivatives (vqx,5, dqx_dR[5] ); + setBoxDerivativesNoPbc(vqx); // qy - double qy = -B/sqrt(3); + double qy = -B/sqrt(3); // qy derivatives - vector dqy_dR(6); - for(unsigned j=0;j<6;j++){ - dqy_dR[j]=-1/sqrt(3) * dB_dR[j]; - } + vector dqy_dR(6); + for(unsigned j=0; j<6; j++) { + dqy_dR[j]=-1/sqrt(3) * dB_dR[j]; + } - Value* vqy=getPntrToComponent("qy"); - vqy->set(qy); - setAtomsDerivatives (vqy,0, dqy_dR[0] ); - setAtomsDerivatives (vqy,1, dqy_dR[1] ); - setAtomsDerivatives (vqy,2, dqy_dR[2] ); - setAtomsDerivatives (vqy,3, dqy_dR[3] ); - setAtomsDerivatives (vqy,4, dqy_dR[4] ); - setAtomsDerivatives (vqy,5, dqy_dR[5] ); - setBoxDerivativesNoPbc(vqy); + Value* vqy=getPntrToComponent("qy"); + vqy->set(qy); + setAtomsDerivatives (vqy,0, dqy_dR[0] ); + setAtomsDerivatives (vqy,1, dqy_dR[1] ); + setAtomsDerivatives (vqy,2, dqy_dR[2] ); + setAtomsDerivatives (vqy,3, dqy_dR[3] ); + setAtomsDerivatives (vqy,4, dqy_dR[4] ); + setAtomsDerivatives (vqy,5, dqy_dR[5] ); + setBoxDerivativesNoPbc(vqy); -// qz - double qz = C/sqrt(6); +// qz + double qz = C/sqrt(6); // qz derivatives - vector dqz_dR(6); - for(unsigned j=0;j<6;j++){ - dqz_dR[j]=1/sqrt(6) * dC_dR[j]; - } + vector dqz_dR(6); + for(unsigned j=0; j<6; j++) { + dqz_dR[j]=1/sqrt(6) * dC_dR[j]; + } - Value* vqz=getPntrToComponent("qz"); - vqz->set(qz); - setAtomsDerivatives (vqz,0, dqz_dR[0] ); - setAtomsDerivatives (vqz,1, dqz_dR[1] ); - setAtomsDerivatives (vqz,2, dqz_dR[2] ); - setAtomsDerivatives (vqz,3, dqz_dR[3] ); - setAtomsDerivatives (vqz,4, dqz_dR[4] ); - setAtomsDerivatives (vqz,5, dqz_dR[5] ); - setBoxDerivativesNoPbc(vqz); + Value* vqz=getPntrToComponent("qz"); + vqz->set(qz); + setAtomsDerivatives (vqz,0, dqz_dR[0] ); + setAtomsDerivatives (vqz,1, dqz_dR[1] ); + setAtomsDerivatives (vqz,2, dqz_dR[2] ); + setAtomsDerivatives (vqz,3, dqz_dR[3] ); + setAtomsDerivatives (vqz,4, dqz_dR[4] ); + setAtomsDerivatives (vqz,5, dqz_dR[5] ); + setBoxDerivativesNoPbc(vqz); // PHASE - double phi=atan2(-A,B); + double phi=atan2(-A,B); // PHASE DERIVATIVES - vector dphi_dR(6); - for(unsigned j=0;j<6;j++){ - dphi_dR[j]=1.0/(A*A+B*B) * (-B*dA_dR[j] + A*dB_dR[j]); - } + vector dphi_dR(6); + for(unsigned j=0; j<6; j++) { + dphi_dR[j]=1.0/(A*A+B*B) * (-B*dA_dR[j] + A*dB_dR[j]); + } - Value* vphi=getPntrToComponent("phi"); - vphi->set(phi); - setAtomsDerivatives (vphi,0, dphi_dR[0] ); - setAtomsDerivatives (vphi,1, dphi_dR[1] ); - setAtomsDerivatives (vphi,2, dphi_dR[2] ); - setAtomsDerivatives (vphi,3, dphi_dR[3] ); - setAtomsDerivatives (vphi,4, dphi_dR[4] ); - setAtomsDerivatives (vphi,5, dphi_dR[5] ); - setBoxDerivativesNoPbc(vphi); + Value* vphi=getPntrToComponent("phi"); + vphi->set(phi); + setAtomsDerivatives (vphi,0, dphi_dR[0] ); + setAtomsDerivatives (vphi,1, dphi_dR[1] ); + setAtomsDerivatives (vphi,2, dphi_dR[2] ); + setAtomsDerivatives (vphi,3, dphi_dR[3] ); + setAtomsDerivatives (vphi,4, dphi_dR[4] ); + setAtomsDerivatives (vphi,5, dphi_dR[5] ); + setBoxDerivativesNoPbc(vphi); // AMPLITUDE - double amplitude=sqrt((2*(A*A+B*B)+C*C)/6); + double amplitude=sqrt((2*(A*A+B*B)+C*C)/6); // AMPLITUDE DERIVATIES - vector damplitude_dR(6); - for (unsigned j=0;j<6;j++){ - damplitude_dR[j]=0.5*sqrt(2.0/6.0)/(sqrt(A*A+B*B+0.5*C*C)) * (2*A*dA_dR[j] + 2*B*dB_dR[j] + C*dC_dR[j]); - } + vector damplitude_dR(6); + for (unsigned j=0; j<6; j++) { + damplitude_dR[j]=0.5*sqrt(2.0/6.0)/(sqrt(A*A+B*B+0.5*C*C)) * (2*A*dA_dR[j] + 2*B*dB_dR[j] + C*dC_dR[j]); + } - Value* vamplitude=getPntrToComponent("amplitude"); - vamplitude->set(amplitude); - setAtomsDerivatives (vamplitude,0, damplitude_dR[0] ); - setAtomsDerivatives (vamplitude,1, damplitude_dR[1] ); - setAtomsDerivatives (vamplitude,2, damplitude_dR[2] ); - setAtomsDerivatives (vamplitude,3, damplitude_dR[3] ); - setAtomsDerivatives (vamplitude,4, damplitude_dR[4] ); - setAtomsDerivatives (vamplitude,5, damplitude_dR[5] ); - setBoxDerivativesNoPbc(vamplitude); + Value* vamplitude=getPntrToComponent("amplitude"); + vamplitude->set(amplitude); + setAtomsDerivatives (vamplitude,0, damplitude_dR[0] ); + setAtomsDerivatives (vamplitude,1, damplitude_dR[1] ); + setAtomsDerivatives (vamplitude,2, damplitude_dR[2] ); + setAtomsDerivatives (vamplitude,3, damplitude_dR[3] ); + setAtomsDerivatives (vamplitude,4, damplitude_dR[4] ); + setAtomsDerivatives (vamplitude,5, damplitude_dR[5] ); + setBoxDerivativesNoPbc(vamplitude); // THETA - double theta=acos( C / sqrt(2.*(A*A+B*B) +C*C ) ); + double theta=acos( C / sqrt(2.*(A*A+B*B) +C*C ) ); // THETA DERIVATIVES - vector dtheta_dR(6); - for(unsigned j=0;j<6;j++){ - dtheta_dR[j]=1.0/(3.0*sqrt(2)*amplitude*amplitude) * (C/(sqrt(A*A+B*B)) * (A*dA_dR[j] + B*dB_dR[j]) - sqrt(A*A+B*B)*dC_dR[j]); - } - Value* vtheta=getPntrToComponent("theta"); - vtheta->set(theta); - setAtomsDerivatives (vtheta,0, dtheta_dR[0] ); - setAtomsDerivatives (vtheta,1, dtheta_dR[1] ); - setAtomsDerivatives (vtheta,2, dtheta_dR[2] ); - setAtomsDerivatives (vtheta,3, dtheta_dR[3] ); - setAtomsDerivatives (vtheta,4, dtheta_dR[4] ); - setAtomsDerivatives (vtheta,5, dtheta_dR[5] ); - setBoxDerivativesNoPbc(vtheta); + vector dtheta_dR(6); + for(unsigned j=0; j<6; j++) { + dtheta_dR[j]=1.0/(3.0*sqrt(2)*amplitude*amplitude) * (C/(sqrt(A*A+B*B)) * (A*dA_dR[j] + B*dB_dR[j]) - sqrt(A*A+B*B)*dC_dR[j]); + } + Value* vtheta=getPntrToComponent("theta"); + vtheta->set(theta); + setAtomsDerivatives (vtheta,0, dtheta_dR[0] ); + setAtomsDerivatives (vtheta,1, dtheta_dR[1] ); + setAtomsDerivatives (vtheta,2, dtheta_dR[2] ); + setAtomsDerivatives (vtheta,3, dtheta_dR[3] ); + setAtomsDerivatives (vtheta,4, dtheta_dR[4] ); + setAtomsDerivatives (vtheta,5, dtheta_dR[5] ); + setBoxDerivativesNoPbc(vtheta); } diff --git a/src/colvar/RDC.cpp b/src/colvar/RDC.cpp index 124101b558..18db380141 100644 --- a/src/colvar/RDC.cpp +++ b/src/colvar/RDC.cpp @@ -33,16 +33,16 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { -//+PLUMEDOC COLVAR RDC +//+PLUMEDOC COLVAR RDC /* -Calculates the (Residual) Dipolar Coupling between two atoms. +Calculates the (Residual) Dipolar Coupling between two atoms. -The RDC between two atomic nuclei depends on the \f$\theta\f$ angle between -the inter-nuclear vector and the external magnetic field. In isotropic media RDCs average to zero because of the orientational -averaging, but when the rotational symmetry is broken, either through the introduction of an alignment medium or for molecules +The RDC between two atomic nuclei depends on the \f$\theta\f$ angle between +the inter-nuclear vector and the external magnetic field. In isotropic media RDCs average to zero because of the orientational +averaging, but when the rotational symmetry is broken, either through the introduction of an alignment medium or for molecules with highly anisotropic paramagnetic susceptibility, RDCs become measurable. \f[ @@ -55,8 +55,8 @@ where D_{max}=-\mu_0\gamma_1\gamma_2h/(8\pi^3r^3) \f] -that is the maximal value of the dipolar coupling for the two nuclear spins with gyromagnetic ratio \f$\gamma\f$. -\f$\mu\f$ is the magnetic constant and h is the Planck constant. +that is the maximal value of the dipolar coupling for the two nuclear spins with gyromagnetic ratio \f$\gamma\f$. +\f$\mu\f$ is the magnetic constant and h is the Planck constant. Common Gyromagnetic Ratios (C.G.S) - H(1) 26.7513 @@ -67,8 +67,8 @@ Common Gyromagnetic Ratios (C.G.S) - CN -18.2385 - CC 45.2404 -This collective variable calculates the Residual Dipolar Coupling for a set of couple of atoms using the above definition. -From the calculated RDCs and a set of experimental values it calculates either their correlation or the squared quality factor +This collective variable calculates the Residual Dipolar Coupling for a set of couple of atoms using the above definition. +From the calculated RDCs and a set of experimental values it calculates either their correlation or the squared quality factor \f[ Q^2=\frac{\sum_i(D_i-D^{exp}_i)^2}{\sum_i(D^{exp}_i)^2} @@ -76,7 +76,7 @@ Q^2=\frac{\sum_i(D_i-D^{exp}_i)^2}{\sum_i(D^{exp}_i)^2} RDCs report only on the fraction of molecules that is aligned, this means that comparing the RDCs from a single structure in a MD simulation to the experimental values is not particularly meaningfull, from this point of view it is better to compare -their correlation. The fraction of aligned molecules can be obtained by maximising the correlation between the calculated and +their correlation. The fraction of aligned molecules can be obtained by maximising the correlation between the calculated and the experimental RDCs. This fraction can be used as a scaling factor in the calculation of the RDCs in order to compare their values. The averaging of the RDCs calculated with the above definition from a standard MD should result to 0 because of the rotational diffusion, but this variable can be used to break the rotational symmetry. @@ -92,12 +92,12 @@ Additional material and examples can be also found in the tutorial \ref belfast- In the following example five N-H RDCs are defined and their correlation with respect to a set of experimental data is calculated and restrained. In addition, and only for analysis purposes, the same RDCs are calculated using a Single Value -Decomposition algorithm. +Decomposition algorithm. \verbatim RDC ... GYROM=-72.5388 -SCALE=1.0 +SCALE=1.0 ATOMS1=20,21 ATOMS2=37,38 ATOMS3=56,57 @@ -113,7 +113,7 @@ rdce: RESTRAINT ARG=nh.corr KAPPA=0. SLOPE=-25000.0 AT=1. RDC ... GYROM=-72.5388 SCALE=1.0 -SVD +SVD ATOMS1=20,21 COUPLING1=8.17 ATOMS2=37,38 COUPLING2=-8.271 ATOMS3=56,57 COUPLING3=-10.489 @@ -125,7 +125,7 @@ LABEL=svd PRINT ARG=nh.corr,rdce.bias FILE=colvar PRINT ARG=svd.* FILE=svd \endverbatim -(See also \ref PRINT, \ref RESTRAINT) +(See also \ref PRINT, \ref RESTRAINT) */ //+ENDPLUMEDOC @@ -146,55 +146,55 @@ class RDC : public Colvar { PLUMED_REGISTER_ACTION(RDC,"RDC") -void RDC::registerKeywords( Keywords& keys ){ +void RDC::registerKeywords( Keywords& keys ) { Colvar::registerKeywords( keys ); componentsAreNotOptional(keys); useCustomisableComponents(keys); keys.add("numbered","ATOMS","the couple of atoms involved in each of the bonds for which you wish to calculate the RDC. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dipolar coupling will be " - "calculated for each ATOMS keyword you specify."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dipolar coupling will be " + "calculated for each ATOMS keyword you specify."); keys.reset_style("ATOMS","atoms"); keys.add("compulsory","GYROM","Add the product of the gyromagnetic constants for the bond. "); keys.add("compulsory","SCALE","Add the scaling factor to take into account concentration and other effects. "); - keys.addFlag("SVD",false,"Set to TRUE if you want to backcalculate using Single Value Decomposition (need GSL at compilation time)."); - keys.addFlag("ADDCOUPLINGS",false,"Set to TRUE if you want to have fixed components with the experimetnal values."); + keys.addFlag("SVD",false,"Set to TRUE if you want to backcalculate using Single Value Decomposition (need GSL at compilation time)."); + keys.addFlag("ADDCOUPLINGS",false,"Set to TRUE if you want to have fixed components with the experimetnal values."); keys.add("numbered","COUPLING","Add an experimental value for each coupling (needed by SVD and usefull for \ref STATS)."); keys.addOutputComponent("rdc","default","the calculated # RDC"); keys.addOutputComponent("exp","SVD/ADDCOUPLINGS","the experimental # RDC"); } RDC::RDC(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -Const(0.3356806), -mu_s(0), -scale(1), -pbc(true) + PLUMED_COLVAR_INIT(ao), + Const(0.3356806), + mu_s(0), + scale(1), + pbc(true) { bool nopbc=!pbc; parseFlag("NOPBC",nopbc); - pbc=!nopbc; + pbc=!nopbc; // Read in the atoms vector t, atoms; - for(int i=1;;++i ){ - parseAtomList("ATOMS", i, t ); - if( t.empty() ) break; - if( t.size()!=2 ){ - std::string ss; Tools::convert(i,ss); - error("ATOMS" + ss + " keyword has the wrong number of atoms"); - } - atoms.push_back(t[0]); - atoms.push_back(t[1]); - t.resize(0); + for(int i=1;; ++i ) { + parseAtomList("ATOMS", i, t ); + if( t.empty() ) break; + if( t.size()!=2 ) { + std::string ss; Tools::convert(i,ss); + error("ATOMS" + ss + " keyword has the wrong number of atoms"); + } + atoms.push_back(t[0]); + atoms.push_back(t[1]); + t.resize(0); } const unsigned ndata = atoms.size()/2; - + // Read in GYROMAGNETIC constants parse("GYROM", mu_s); if(mu_s==0.) error("GYROM must be set"); - // Read in SCALING factors + // Read in SCALING factors parse("SCALE", scale); if(scale==0.) error("SCALE must be different from 0"); @@ -208,19 +208,19 @@ pbc(true) parseFlag("ADDCOUPLINGS",addcoupling); if(svd||addcoupling) { - coupl.resize( ndata ); + coupl.resize( ndata ); unsigned ntarget=0; - for(unsigned i=0;iset(rdc); setBoxDerivatives(val, Tensor(distance,dRDC)); - setAtomsDerivatives(val, r , dRDC); - setAtomsDerivatives(val, r+1, -dRDC); + setAtomsDerivatives(val, r, dRDC); + setAtomsDerivatives(val, r+1, -dRDC); } } else { @@ -317,7 +317,7 @@ void RDC::calculate() double d = distance.modulo(); double d2 = d*d; double d3 = d2*d; - double id3 = 1./d3; + double id3 = 1./d3; double max = -Const*mu_s*scale; dmax[index] = id3*max; double mu_x = distance[0]/d; @@ -334,7 +334,7 @@ void RDC::calculate() gsl_matrix_memcpy(A,coef_mat); gsl_linalg_SV_decomp(A, V, Stmp, work); gsl_linalg_SV_solve(A, V, Stmp, rdc_vec, S); - /* tensor + /* tensor double Sxx = gsl_vector_get(S,0); double Syy = gsl_vector_get(S,1); double Szz = -Sxx-Syy; diff --git a/src/colvar/RMSD.cpp b/src/colvar/RMSD.cpp index 642433452b..8801dfeed2 100644 --- a/src/colvar/RMSD.cpp +++ b/src/colvar/RMSD.cpp @@ -30,15 +30,15 @@ using namespace std; -namespace PLMD{ -namespace colvar{ - +namespace PLMD { +namespace colvar { + class RMSD : public Colvar { - + MultiValue myvals; ReferenceValuePack mypack; PLMD::RMSDBase* rmsd; - bool squared; + bool squared; public: explicit RMSD(const ActionOptions&); @@ -52,30 +52,30 @@ using namespace std; //+PLUMEDOC DCOLVAR RMSD /* -Calculate the RMSD with respect to a reference structure. +Calculate the RMSD with respect to a reference structure. The aim with this colvar it to calculate something like: \f[ -d(X,X') = \vert X-X' \vert +d(X,X') = \vert X-X' \vert \f] -where \f$ X \f$ is the instantaneous position of all the atoms in the system and +where \f$ X \f$ is the instantaneous position of all the atoms in the system and \f$ X' \f$ is the positions of the atoms in some reference structure provided as input. \f$ d(X,X') \f$ thus measures the distance all the atoms have moved away from this reference configuration. -Oftentimes, it is only the internal motions of the structure - i.e. not the translations of the center of +Oftentimes, it is only the internal motions of the structure - i.e. not the translations of the center of mass or the rotations of the reference frame - that are interesting. Hence, when calculating the the root-mean-square deviation between the atoms in two configurations you must first superimpose the two structures in some way. At present PLUMED provides two distinct ways -of performing this superposition. The first method is applied when you use TYPE=SIMPLE in the input +of performing this superposition. The first method is applied when you use TYPE=SIMPLE in the input line. This instruction tells PLUMED that the root mean square deviation is to be calculated after the positions of the geometric centers in the reference and instantaneous configurations are aligned. In -other words \f$d(X,x')\f$ is to be calculated using: +other words \f$d(X,x')\f$ is to be calculated using: \f[ - d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}( X_{i,\alpha}-com_\alpha(X)-{X'}_{i,\alpha}+com_\alpha(X') )^2 } + d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}( X_{i,\alpha}-com_\alpha(X)-{X'}_{i,\alpha}+com_\alpha(X') )^2 } \f] -with +with \f[ com_\alpha(X)= \sum_i \frac{w'_{i}}{\sum_j w'_j}X_{i,\alpha} \f] @@ -86,42 +86,42 @@ com_\alpha(X')= \sum_i \frac{w'_{i}}{\sum_j w'_j}X'_{i,\alpha} Obviously, \f$ com_\alpha(X) \f$ and \f$ com_\alpha(X') \f$ represent the positions of the center of mass in the reference and instantaneous configurations if the weights $w'$ are set equal to the atomic masses. If the weights are all set equal to one, however, \f$com_\alpha(X) \f$ and \f$ com_\alpha(X') \f$ are the positions of the geometric centers. -Notice that there are sets of weights: \f$ w' \f$ and \f$ w \f$. The first is used to calculate the position of the center of mass +Notice that there are sets of weights: \f$ w' \f$ and \f$ w \f$. The first is used to calculate the position of the center of mass (so it determines how the atoms are \e aligned). Meanwhile, the second is used when calculating how far the atoms have actually been \e displaced. These weights are assigned in the reference configuration that you provide as input (i.e. the appear in the input file -to this action that you set using REFERENCE=whatever.pdb). This input reference configuration consists of a simple pdb file -containing the set of atoms for which you want to calculate the RMSD displacement and their positions in the reference configuration. -It is important to note that the indices in this pdb need to be set correctly. The indices in this file determine the indices of the +to this action that you set using REFERENCE=whatever.pdb). This input reference configuration consists of a simple pdb file +containing the set of atoms for which you want to calculate the RMSD displacement and their positions in the reference configuration. +It is important to note that the indices in this pdb need to be set correctly. The indices in this file determine the indices of the instantaneous atomic positions that are used by PLUMED when calculating this colvar. As such if you want to calculate the RMSD distance moved by the 1st, 4th, 6th and 28th atoms in the MD codes input file then the indices of the corresponding refernece positions in this pdb -file should be set equal to 1, 4, 6 and 28. +file should be set equal to 1, 4, 6 and 28. -The pdb input file should also contain the values of \f$w\f$ and \f$w'\f$. In particular, the OCCUPANCY column (the first column after the coordinates) +The pdb input file should also contain the values of \f$w\f$ and \f$w'\f$. In particular, the OCCUPANCY column (the first column after the coordinates) is used provides the values of \f$ w'\f$ that are used to calculate the position of the centre of mass. The BETA column (the second column -after the Cartesian coordinates) is used to provide the \f$ w \f$ values which are used in the the calculation of the displacement. -Please note that it is possible to use fractional values for beta and for the occupancy. However, we recommend you only do this when -you really know what you are doing however as the results can be rather strange. +after the Cartesian coordinates) is used to provide the \f$ w \f$ values which are used in the the calculation of the displacement. +Please note that it is possible to use fractional values for beta and for the occupancy. However, we recommend you only do this when +you really know what you are doing however as the results can be rather strange. -In PDB files the atomic coordinates and box lengths should be in Angstroms unless -you are working with natural units. If you are working with natural units then the coordinates +In PDB files the atomic coordinates and box lengths should be in Angstroms unless +you are working with natural units. If you are working with natural units then the coordinates should be in your natural length unit. For more details on the PDB file format visit http://www.wwpdb.org/docs.html. -A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line. In this case the root mean square +A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line. In this case the root mean square deviation is calculated after the positions of geometric centers in the reference and instantaneous configurations are aligned AND after an optimal alignment of the two frames is performed so that motion due to rotation of the reference frame between the two structures is removed. The equation for \f$d(X,X')\f$ in this case reads: \f[ -d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}[ X_{i,\alpha}-com_\alpha(X)- \sum_\beta M(X,X',w')_{\alpha,\beta}({X'}_{i,\beta}-com_\beta(X')) ]^2 } +d(X,X') = \sqrt{ \sum_i \sum_\alpha^{x,y,z} \frac{w_i}{\sum_j w_j}[ X_{i,\alpha}-com_\alpha(X)- \sum_\beta M(X,X',w')_{\alpha,\beta}({X'}_{i,\beta}-com_\beta(X')) ]^2 } \f] -where \f$ M(X,X',w') \f$ is the optimal alignment matrix which is calculated using the Kearsley \cite kearsley algorithm. Again different sets of +where \f$ M(X,X',w') \f$ is the optimal alignment matrix which is calculated using the Kearsley \cite kearsley algorithm. Again different sets of weights are used for the alignment (\f$w'\f$) and for the displacement calcuations (\f$w\f$). -This gives a great deal of flexibility as it allows you to use a different sets of atoms (which may or may not overlap) for the alignment and displacement +This gives a great deal of flexibility as it allows you to use a different sets of atoms (which may or may not overlap) for the alignment and displacement parts of the calculation. This may be very useful when you want to calculate how a ligand moves about in a protein cavity as you can use the protein as a reference -system and do no alignment of the ligand. +system and do no alignment of the ligand. -(Note: when this form of RMSD is used to calculate the secondary structure variables (\ref ALPHARMSD, \ref ANTIBETARMSD and \ref PARABETARMSD +(Note: when this form of RMSD is used to calculate the secondary structure variables (\ref ALPHARMSD, \ref ANTIBETARMSD and \ref PARABETARMSD all the atoms in the segment are assumed to be part of both the alignment and displacement sets and all weights are set equal to one) Please note that there are a number of other methods for calculating the distance between the instantaneous configuration and a reference configuration @@ -144,7 +144,7 @@ RMSD REFERENCE=file.pdb TYPE=OPTIMAL PLUMED_REGISTER_ACTION(RMSD,"RMSD") -void RMSD::registerKeywords(Keywords& keys){ +void RMSD::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.add("compulsory","REFERENCE","a file in pdb format containing the reference structure and the atoms involved in the CV."); keys.add("compulsory","TYPE","SIMPLE","the manner in which RMSD alignment is performed. Should be OPTIMAL or SIMPLE."); @@ -153,11 +153,11 @@ void RMSD::registerKeywords(Keywords& keys){ } RMSD::RMSD(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) + PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) { string reference; parse("REFERENCE",reference); - string type; + string type; type.assign("SIMPLE"); parse("TYPE",type); parseFlag("SQUARED",squared); @@ -170,10 +170,10 @@ PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + reference ); + error("missing input file " + reference ); rmsd = metricRegister().create(type,pdb); - + std::vector atoms; rmsd->getAtomRequests( atoms ); // rmsd->setNumberOfAtoms( atoms.size() ); @@ -181,7 +181,7 @@ PLUMED_COLVAR_INIT(ao),myvals(1,0), mypack(0,0,myvals),squared(false) // Setup the derivative pack myvals.resize( 1, 3*atoms.size()+9 ); mypack.resize( 0, atoms.size() ); - for(unsigned i=0;icalculate( getPositions(), mypack, squared ); - setValue(r); - for(unsigned i=0;i \verbatim -# This should be a sample input. +# This should be a sample input. t: TEMPLATE ATOMS=1,2 PRINT ARG=t STRIDE=100 FILE=COLVAR \endverbatim @@ -50,7 +50,7 @@ PRINT ARG=t STRIDE=100 FILE=COLVAR */ //+ENDPLUMEDOC - + class Template : public Colvar { bool pbc; @@ -63,7 +63,7 @@ class Template : public Colvar { PLUMED_REGISTER_ACTION(Template,"TEMPLATE") -void Template::registerKeywords(Keywords& keys){ +void Template::registerKeywords(Keywords& keys) { Colvar::registerKeywords(keys); keys.addFlag("TEMPLATE_DEFAULT_OFF_FLAG",false,"flags that are by default not performed should be specified like this"); keys.addFlag("TEMPLATE_DEFAULT_ON_FLAG",true,"flags that are by default performed should be specified like this"); @@ -73,8 +73,8 @@ void Template::registerKeywords(Keywords& keys){ } Template::Template(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true) + PLUMED_COLVAR_INIT(ao), + pbc(true) { vector atoms; parseAtomList("ATOMS",atoms); @@ -96,10 +96,10 @@ pbc(true) // calculator -void Template::calculate(){ +void Template::calculate() { Vector distance; - if(pbc){ + if(pbc) { distance=pbcDistance(getPosition(0),getPosition(1)); } else { distance=delta(getPosition(0),getPosition(1)); diff --git a/src/colvar/Torsion.cpp b/src/colvar/Torsion.cpp index 7d885295f3..274d0565a4 100644 --- a/src/colvar/Torsion.cpp +++ b/src/colvar/Torsion.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR TORSION /* @@ -37,7 +37,7 @@ Calculate a torsional angle. This command can be used to compute the torsion between four atoms or alternatively to calculate the angle between two vectors projected on the plane -orthogonal to an axis. +orthogonal to an axis. \par Examples @@ -51,7 +51,7 @@ PRINT ARG=t FILE=COLVAR \endverbatim If you are working with a protein you can specify the special named torsion angles \f$\phi\f$, \f$\psi\f$, \f$\omega\f$ and \f$\chi_1\f$ -by using TORSION in combination with the \ref MOLINFO command. This can be done by using the following +by using TORSION in combination with the \ref MOLINFO command. This can be done by using the following syntax. \verbatim @@ -65,7 +65,7 @@ Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the 4th residue of the protein. */ //+ENDPLUMEDOC - + class Torsion : public Colvar { bool pbc; bool do_cosine; @@ -79,19 +79,19 @@ class Torsion : public Colvar { PLUMED_REGISTER_ACTION(Torsion,"TORSION") -void Torsion::registerKeywords(Keywords& keys){ - Colvar::registerKeywords( keys ); - keys.add("atoms-1","ATOMS","the four atoms involved in the torsional angle"); - keys.add("atoms-2","AXIS","two atoms that define an axis. You can use this to find the angle in the plane perpendicular to the axis between the vectors specified using the VECTOR1 and VECTOR2 keywords."); - keys.add("atoms-2","VECTOR1","two atoms that define a vector. You can use this in combination with VECTOR2 and AXIS"); - keys.add("atoms-2","VECTOR2","two atoms that define a vector. You can use this in combination with VECTOR1 and AXIS"); - keys.addFlag("COSINE",false,"calculate cosine instead of dihedral"); +void Torsion::registerKeywords(Keywords& keys) { + Colvar::registerKeywords( keys ); + keys.add("atoms-1","ATOMS","the four atoms involved in the torsional angle"); + keys.add("atoms-2","AXIS","two atoms that define an axis. You can use this to find the angle in the plane perpendicular to the axis between the vectors specified using the VECTOR1 and VECTOR2 keywords."); + keys.add("atoms-2","VECTOR1","two atoms that define a vector. You can use this in combination with VECTOR2 and AXIS"); + keys.add("atoms-2","VECTOR2","two atoms that define a vector. You can use this in combination with VECTOR1 and AXIS"); + keys.addFlag("COSINE",false,"calculate cosine instead of dihedral"); } Torsion::Torsion(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao), -pbc(true), -do_cosine(false) + PLUMED_COLVAR_INIT(ao), + pbc(true), + do_cosine(false) { vector atoms,v1,v2,axis; parseAtomList("ATOMS",atoms); @@ -106,7 +106,7 @@ do_cosine(false) pbc=!nopbc; checkRead(); - if(atoms.size()==4){ + if(atoms.size()==4) { if(!(v1.empty() && v2.empty() && axis.empty())) error("ATOMS keyword is not compatible with VECTOR1, VECTOR2 and AXIS keywords"); log.printf(" between atoms %d %d %d %d\n",atoms[0].serial(),atoms[1].serial(),atoms[2].serial(),atoms[3].serial()); @@ -115,11 +115,11 @@ do_cosine(false) atoms[4]=atoms[2]; atoms[3]=atoms[2]; atoms[2]=atoms[1]; - }else if(atoms.empty()){ + } else if(atoms.empty()) { if(!(v1.size()==2 && v2.size()==2 && axis.size()==2)) error("VECTOR1, VECTOR2 and AXIS should specify 2 atoms each"); log.printf(" between lines %d-%d and %d-%d, projected on the plane orthogonal to line %d-%d\n", - v1[0].serial(),v1[1].serial(),v2[0].serial(),v2[1].serial(),axis[0].serial(),axis[1].serial()); + v1[0].serial(),v1[1].serial(),v2[0].serial(),v2[1].serial(),axis[0].serial(),axis[1].serial()); atoms.resize(6); atoms[0]=v1[1]; atoms[1]=v1[0]; @@ -127,7 +127,7 @@ do_cosine(false) atoms[3]=axis[1]; atoms[4]=v2[0]; atoms[5]=v2[1]; - }else error("ATOMS should specify 4 atoms"); + } else error("ATOMS should specify 4 atoms"); if(pbc) log.printf(" using periodic boundary conditions\n"); else log.printf(" without periodic boundary conditions\n"); @@ -141,7 +141,7 @@ do_cosine(false) } // calculator -void Torsion::calculate(){ +void Torsion::calculate() { Vector d0,d1,d2; if(pbc) makeWhole(); @@ -151,11 +151,11 @@ void Torsion::calculate(){ Vector dd0,dd1,dd2; PLMD::Torsion t; double torsion=t.compute(d0,d1,d2,dd0,dd1,dd2); - if(do_cosine){ - dd0 *= -sin(torsion); - dd1 *= -sin(torsion); - dd2 *= -sin(torsion); - torsion = cos(torsion); + if(do_cosine) { + dd0 *= -sin(torsion); + dd1 *= -sin(torsion); + dd2 *= -sin(torsion); + torsion = cos(torsion); } setAtomsDerivatives(0,dd0); setAtomsDerivatives(1,-dd0); diff --git a/src/colvar/Volume.cpp b/src/colvar/Volume.cpp index b33652d663..7b4fb9aacf 100644 --- a/src/colvar/Volume.cpp +++ b/src/colvar/Volume.cpp @@ -27,8 +27,8 @@ using namespace std; -namespace PLMD{ -namespace colvar{ +namespace PLMD { +namespace colvar { //+PLUMEDOC COLVAR VOLUME /* @@ -59,7 +59,7 @@ class Volume : public Colvar { PLUMED_REGISTER_ACTION(Volume,"VOLUME") Volume::Volume(const ActionOptions&ao): -PLUMED_COLVAR_INIT(ao) + PLUMED_COLVAR_INIT(ao) { std::vector atoms; checkRead(); @@ -68,7 +68,7 @@ PLUMED_COLVAR_INIT(ao) requestAtoms(atoms); } -void Volume::registerKeywords( Keywords& keys ){ +void Volume::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -76,7 +76,7 @@ void Volume::registerKeywords( Keywords& keys ){ // calculator -void Volume::calculate(){ +void Volume::calculate() { double v=getBox().determinant(); setBoxDerivatives(-v*Tensor::identity()); diff --git a/src/config/Config.h b/src/config/Config.h index 95501d9ef7..39c441e98d 100644 --- a/src/config/Config.h +++ b/src/config/Config.h @@ -24,8 +24,8 @@ #include -namespace PLMD{ -namespace config{ +namespace PLMD { +namespace config { /// Return the extension of shared libraries on this system. /// It is either "so" or "dylib". In case shared libraries are disabled, it returns an empty string. diff --git a/src/config/Config.inc.in b/src/config/Config.inc.in index 03eb4af418..6596895588 100644 --- a/src/config/Config.inc.in +++ b/src/config/Config.inc.in @@ -25,18 +25,18 @@ #include #include -namespace PLMD{ -namespace config{ +namespace PLMD { +namespace config { -std::string getSoExt(){ +std::string getSoExt() { return "@SOEXT@"; } -bool isInstalled(){ +bool isInstalled() { return @ISINSTALLED@; } -std::string getPlumedRoot(){ +std::string getPlumedRoot() { char *env = std::getenv("PLUMED_ROOT"); std::string ss; if( env == NULL) { @@ -47,7 +47,7 @@ std::string getPlumedRoot(){ return ss; } -std::string getPlumedHtmldir(){ +std::string getPlumedHtmldir() { if(!isInstalled()) return getPlumedRoot(); char *env = std::getenv("PLUMED_HTMLDIR"); std::string ss; @@ -59,7 +59,7 @@ std::string getPlumedHtmldir(){ return ss; } -std::string getPlumedIncludedir(){ +std::string getPlumedIncludedir() { if(!isInstalled()) return getPlumedRoot()+"/include"; char *env = std::getenv("PLUMED_INCLUDEDIR"); std::string ss; @@ -71,7 +71,7 @@ std::string getPlumedIncludedir(){ return ss; } -std::string getPlumedProgramName(){ +std::string getPlumedProgramName() { if(!isInstalled()) return "plumed"; char *env = std::getenv("PLUMED_PROGRAM_NAME"); std::string ss; @@ -83,86 +83,87 @@ std::string getPlumedProgramName(){ return ss; } -std::string getEnvCommand(){ +std::string getEnvCommand() { return "env PLUMED_ROOT=\""+getPlumedRoot()+"\""+ - " env PLUMED_HTMLDIR=\""+getPlumedHtmldir()+"\""+ - " env PLUMED_INCLUDEDIR=\""+getPlumedIncludedir()+"\""+ - " env PLUMED_PROGRAM_NAME=\""+getPlumedProgramName()+"\""+ - " env PLUMED_IS_INSTALLED=\""+(@ISINSTALLED@?"yes":"no")+"\""; + " env PLUMED_HTMLDIR=\""+getPlumedHtmldir()+"\""+ + " env PLUMED_INCLUDEDIR=\""+getPlumedIncludedir()+"\""+ + " env PLUMED_PROGRAM_NAME=\""+getPlumedProgramName()+"\""+ + " env PLUMED_IS_INSTALLED=\""+(@ISINSTALLED@?"yes":"no")+"\""; } -std::string getVersion(){ +std::string getVersion() { return PLUMED_VERSION_SHORT; } -std::string getVersionLong(){ +std::string getVersionLong() { return PLUMED_VERSION_LONG; } -std::string getVersionGit(){ +std::string getVersionGit() { return PLUMED_VERSION_GIT; } -std::string getMakefile(){ - static const char conf [] ={ +std::string getMakefile() { + static const char conf [] = { #include "Makefile.conf.xxd" - , 0x00 }; + , 0x00 + }; return std::string(conf,conf+std::strlen(conf)); } -bool hasMatheval(){ +bool hasMatheval() { #if __PLUMED_HAS_MATHEVAL - return true; + return true; #else - return false; + return false; #endif } -bool hasDlopen(){ +bool hasDlopen() { #if __PLUMED_HAS_DLOPEN - return true; + return true; #else - return false; + return false; #endif } -bool hasCregex(){ +bool hasCregex() { #if __PLUMED_HAS_CREGEX - return true; + return true; #else - return false; + return false; #endif } -bool hasMolfile(){ +bool hasMolfile() { #if __PLUMED_HAS_MOLFILE_PLUGINS - return true; + return true; #else - return false; + return false; #endif } -bool hasExternalMolfile(){ +bool hasExternalMolfile() { #if __PLUMED_HAS_EXTERNAL_MOLFILE_PLUGINS - return true; + return true; #else - return false; + return false; #endif } -bool hasZlib(){ +bool hasZlib() { #if __PLUMED_HAS_ZLIB - return true; + return true; #else - return false; + return false; #endif } -bool hasXdrfile(){ +bool hasXdrfile() { #if __PLUMED_HAS_XDRFILE - return true; + return true; #else - return false; + return false; #endif } diff --git a/src/core/Action.cpp b/src/core/Action.cpp index 1c47820095..a78c7c7300 100644 --- a/src/core/Action.cpp +++ b/src/core/Action.cpp @@ -28,25 +28,25 @@ #include "ActionSet.h" #include -namespace PLMD{ +namespace PLMD { Keywords ActionOptions::emptyKeys; ActionOptions::ActionOptions(PlumedMain&p,const std::vector&l): -plumed(p), -line(l), -keys(emptyKeys) + plumed(p), + line(l), + keys(emptyKeys) { } ActionOptions::ActionOptions(const ActionOptions&ao,const Keywords&keys): -plumed(ao.plumed), -line(ao.line), -keys(keys) + plumed(ao.plumed), + line(ao.line), + keys(keys) { } -void Action::registerKeywords( Keywords& keys ){ +void Action::registerKeywords( Keywords& keys ) { plumed_assert( keys.size()==0 ); keys.add( "hidden", "LABEL", "a label for the action so that its output can be referenced in the input to other actions. Actions with scalar output are referenced using their label only. Actions with vector output must have a separate label for every component. Individual componets are then refered to using label.component" ); keys.reserve("optional","UPDATE_FROM","Only update this action from this time"); @@ -71,14 +71,14 @@ Action::Action(const ActionOptions&ao): line.erase(line.begin()); log.printf("Action %s\n",name.c_str()); - if(comm.Get_rank()==0){ + if(comm.Get_rank()==0) { replica_index=multi_sim_comm.Get_rank(); } comm.Bcast(replica_index,0); - if ( keywords.exists("LABEL") ){ parse("LABEL",label); } + if ( keywords.exists("LABEL") ) { parse("LABEL",label); } - if(label.length()==0){ + if(label.length()==0) { std::string s; Tools::convert(plumed.getActionSet().size(),s); label="@"+s; } @@ -88,7 +88,7 @@ Action::Action(const ActionOptions&ao): if(update_from!=std::numeric_limits::max()) log.printf(" only update from time %f\n",update_from); if ( keywords.exists("UPDATE_UNTIL") ) parse("UPDATE_UNTIL",update_until); if(update_until!=std::numeric_limits::max()) log.printf(" only update until time %f\n",update_until); - if ( keywords.exists("RESTART") ){ + if ( keywords.exists("RESTART") ) { std::string srestart="AUTO"; parse("RESTART",srestart); if(srestart=="YES") restart=true; @@ -98,15 +98,15 @@ Action::Action(const ActionOptions&ao): } } -Action::~Action(){ - if(files.size()!=0){ +Action::~Action() { + if(files.size()!=0) { std::cerr<<"WARNING: some files open in action "+getLabel()+" where not properly closed. This could lead to data loss!!\n"; } } -FILE* Action::fopen(const char *path, const char *mode){ +FILE* Action::fopen(const char *path, const char *mode) { bool write(false); - for(const char*p=mode;*p;p++) if(*p=='w' || *p=='a' || *p=='+') write=true; + for(const char*p=mode; *p; p++) if(*p=='w' || *p=='a' || *p=='+') write=true; FILE* fp; if(write && comm.Get_rank()!=0) fp=plumed.fopen("/dev/null",mode); else fp=plumed.fopen(path,mode); @@ -114,64 +114,64 @@ FILE* Action::fopen(const char *path, const char *mode){ return fp; } -int Action::fclose(FILE*fp){ +int Action::fclose(FILE*fp) { files.erase(fp); return plumed.fclose(fp); } -void Action::fflush(){ - for(const auto & p : files){ +void Action::fflush() { + for(const auto & p : files) { std::fflush(p); } } -std::string Action::getKeyword(const std::string& key){ - // Check keyword has been registered +std::string Action::getKeyword(const std::string& key) { + // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); std::string outkey; if( Tools::getKey(line,key,outkey ) ) return key + outkey; - if( keywords.style(key,"compulsory") ){ - if( keywords.getDefaultValue(key,outkey) ){ - if( outkey.length()==0 ) error("keyword " + key + " has weird default value"); - return key + "=" + outkey; - } else { - error("keyword " + key + " is compulsory for this action"); - } - } + if( keywords.style(key,"compulsory") ) { + if( keywords.getDefaultValue(key,outkey) ) { + if( outkey.length()==0 ) error("keyword " + key + " has weird default value"); + return key + "=" + outkey; + } else { + error("keyword " + key + " is compulsory for this action"); + } + } return ""; } -void Action::parseFlag(const std::string&key,bool & t){ +void Action::parseFlag(const std::string&key,bool & t) { // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); // Check keyword is a flag - if(!keywords.style(key,"nohtml")){ - plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag"); + if(!keywords.style(key,"nohtml")) { + plumed_massert( keywords.style(key,"vessel") || keywords.style(key,"flag") || keywords.style(key,"hidden"), "keyword " + key + " is not a flag"); } // Read in the flag otherwise get the default value from the keywords object - if(!Tools::parseFlag(line,key,t)){ - if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ){ - t=false; - } else if ( !keywords.getLogicalDefault(key,t) ){ - log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() ); - plumed_error(); - } + if(!Tools::parseFlag(line,key,t)) { + if( keywords.style(key,"nohtml") || keywords.style(key,"vessel") ) { + t=false; + } else if ( !keywords.getLogicalDefault(key,t) ) { + log.printf("ERROR in action %s with label %s : flag %s has no default",name.c_str(),label.c_str(),key.c_str() ); + plumed_error(); + } } } -void Action::addDependency(Action*action){ +void Action::addDependency(Action*action) { after.push_back(action); } -void Action::activate(){ +void Action::activate() { // preparation step is called only the first time an Action is activated. // since it could change its dependences (e.g. in an ActionAtomistic which is // accessing to a virtual atom), this is done just before dependencies are // activated - if(!active){ + if(!active) { this->unlockRequests(); prepare(); this->lockRequests(); @@ -180,57 +180,57 @@ void Action::activate(){ active=true; } -void Action::setOption(const std::string &s){ -// This overloads the action and activate some options +void Action::setOption(const std::string &s) { +// This overloads the action and activate some options options.insert(s); for(const auto & p : after) p->setOption(s); } -void Action::clearOptions(){ -// This overloads the action and activate some options +void Action::clearOptions() { +// This overloads the action and activate some options options.clear(); } -void Action::clearDependencies(){ +void Action::clearDependencies() { after.clear(); } -std::string Action::getDocumentation()const{ +std::string Action::getDocumentation()const { return std::string("UNDOCUMENTED ACTION"); } -void Action::checkRead(){ - if(!line.empty()){ +void Action::checkRead() { + if(!line.empty()) { std::string msg="cannot understand the following words from the input line : "; - for(unsigned i=0;i(p); - if(av){ av->clearInputForces(); av->clearDerivatives(); } - p->readAtomsFromPDB( pdb ); - p->calculate(); + for(const auto & p : after) { + ActionWithValue*av=dynamic_cast(p); + if(av) { av->clearInputForces(); av->clearDerivatives(); } + p->readAtomsFromPDB( pdb ); + p->calculate(); } readAtomsFromPDB( pdb ); calculate(); } -bool Action::getExchangeStep()const{ +bool Action::getExchangeStep()const { return plumed.getExchangeStep(); } -std::string Action::cite(const std::string&s){ +std::string Action::cite(const std::string&s) { return plumed.cite(s); } /// Check if action should be updated. -bool Action::checkUpdate()const{ +bool Action::checkUpdate()const { double t=getTime(); if(t::max() || t>=update_from)) return true; else return false; diff --git a/src/core/Action.h b/src/core/Action.h index 43cd5d15ea..d65208bbcb 100644 --- a/src/core/Action.h +++ b/src/core/Action.h @@ -29,16 +29,16 @@ #include "tools/Tools.h" #include "tools/Log.h" -namespace PLMD{ +namespace PLMD { class PDB; class PlumedMain; class Communicator; /// This class is used to bring the relevant information to the Action constructor. -/// Only Action and ActionRegister class can access to its content, which is +/// Only Action and ActionRegister class can access to its content, which is /// kept private to other classes, and may change in the future. -class ActionOptions{ +class ActionOptions { friend class Action; friend class ActionRegister; /// Reference to main PlumedMain object @@ -88,12 +88,12 @@ class Action private: /// Actions on which this Action depends. Dependencies after; - + /// Switch to activate Action on this step. bool active; -/// Option that you might have enabled - std::set options; +/// Option that you might have enabled + std::set options; bool restart; @@ -114,7 +114,7 @@ class Action void clearDependencies(); /// Return the present timestep - long int getStep()const; + long int getStep()const; /// Return the present time double getTime()const; @@ -125,7 +125,7 @@ class Action /// Return true if we are doing a restart bool getRestart()const; -/// Return true if we are doing at a checkpoint step +/// Return true if we are doing at a checkpoint step bool getCPT()const; /// Just read one of the keywords and return the whole thing as a string @@ -151,8 +151,8 @@ class Action void parseFlag(const std::string&key,bool&t); /// Crash calculation and print documentation - void error( const std::string & msg ) const; - + void error( const std::string & msg ) const; + /// Issue a warning void warning( const std::string & msg ); @@ -190,11 +190,11 @@ class Action /// By default (if not overridden) does nothing. virtual void prepare(); -/// Register all the relevant keywords for the action +/// Register all the relevant keywords for the action static void registerKeywords( Keywords& keys ); - virtual void lockRequests(){} - virtual void unlockRequests(){} + virtual void lockRequests() {} + virtual void unlockRequests() {} /// Calculate an Action. /// This method is called one or more times per step. @@ -213,17 +213,17 @@ class Action /// of the fact that update() is active or not. /// In other words, this is *always* called, even when action /// is not active. - virtual void beforeUpdate(){} + virtual void beforeUpdate() {} /// Update. /// This method is called one time per step. /// The set of all Actions is updated in forward order. - virtual void update(){} + virtual void update() {} /// RunFinalJobs /// This method is called once at the very end of the calculation. /// The set of all Actions in run for the final time in forward order. - virtual void runFinalJobs(){} + virtual void runFinalJobs() {} /// Tell to the Action to flush open files void fflush(); @@ -254,16 +254,16 @@ class Action bool isOptionOn(const std::string &s)const; /// Return dependencies - const Dependencies & getDependencies()const{return after;} + const Dependencies & getDependencies()const {return after;} /// Check if numerical derivatives should be performed - virtual bool checkNumericalDerivatives()const{return false;} + virtual bool checkNumericalDerivatives()const {return false;} /// Check if the action needs gradient - virtual bool checkNeedsGradients()const{return false;} + virtual bool checkNeedsGradients()const {return false;} /// Perform calculation using numerical derivatives -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); @@ -278,10 +278,10 @@ class Action /// Calculate the action given a pdb file as input. This is used to initialize /// things like distance from a point in CV map space given a pdb as an input file void calculateFromPDB( const PDB& ); -/// This is overwritten in ActionAtomistic so that we can read -/// the atoms from the pdb input file rather than taking them from the +/// This is overwritten in ActionAtomistic so that we can read +/// the atoms from the pdb input file rather than taking them from the /// MD code - virtual void readAtomsFromPDB( const PDB& ){} + virtual void readAtomsFromPDB( const PDB& ) {} /// Check if we are on an exchange step bool getExchangeStep()const; @@ -293,17 +293,17 @@ class Action // FAST INLINE METHODS inline -const std::string & Action::getLabel()const{ +const std::string & Action::getLabel()const { return label; } inline -const std::string & Action::getName()const{ +const std::string & Action::getName()const { return name; } template -void Action::parse(const std::string&key,T&t){ +void Action::parse(const std::string&key,T&t) { // if(!Tools::parse(line,key,t)){ // log.printf("ERROR parsing keyword %s\n",key.c_str()); // log.printf("%s\n",getDocumentation().c_str()); @@ -313,26 +313,26 @@ void Action::parse(const std::string&key,T&t){ plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); // Now try to read the keyword - std::string def; + std::string def; bool present=Tools::findKeyword(line,key); bool found=Tools::parse(line,key,t,replica_index); if(present && !found) error("keyword " + key +" could not be read correctly"); - - // If it isn't read and it is compulsory see if a default value was specified - if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ){ - if( keywords.getDefaultValue(key,def) ){ - if( def.length()==0 || !Tools::convert(def,t) ){ - log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() ); - this->exit(1); - } - } else if( keywords.style(key,"compulsory") ){ - error("keyword " + key + " is compulsory for this action"); - } - } + + // If it isn't read and it is compulsory see if a default value was specified + if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) { + if( keywords.getDefaultValue(key,def) ) { + if( def.length()==0 || !Tools::convert(def,t) ) { + log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() ); + this->exit(1); + } + } else if( keywords.style(key,"compulsory") ) { + error("keyword " + key + " is compulsory for this action"); + } + } } template -bool Action::parseNumbered(const std::string&key, const int no, T&t){ +bool Action::parseNumbered(const std::string&key, const int no, T&t) { // Check keyword has been registered plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key ); @@ -343,7 +343,7 @@ bool Action::parseNumbered(const std::string&key, const int no, T&t){ } template -void Action::parseVector(const std::string&key,std::vector&t){ +void Action::parseVector(const std::string&key,std::vector&t) { // if(!Tools::parseVector(line,key,t)){ // log.printf("ERROR parsing keyword %s\n",key.c_str()); // log.printf("%s\n",getDocumentation().c_str()); @@ -362,31 +362,31 @@ void Action::parseVector(const std::string&key,std::vector&t){ if(present && !found) error("keyword " + key +" could not be read correctly"); // Check vectors size is correct (not if this is atoms or ARG) - if( !keywords.style(key,"atoms") && found ){ + if( !keywords.style(key,"atoms") && found ) { // bool skipcheck=false; // if( keywords.style(key,"compulsory") ){ keywords.getDefaultValue(key,def); skipcheck=(def=="nosize"); } - if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); + if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); } - // If it isn't read and it is compulsory see if a default value was specified - if ( !found && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ){ - if( keywords.getDefaultValue(key,def) ){ - if( def.length()==0 || !Tools::convert(def,val) ){ - log.printf("ERROR in action %s with label %s : keyword %s has weird default value",name.c_str(),label.c_str(),key.c_str() ); - this->exit(1); - } else { - for(unsigned i=0;iexit(1); + } else { + for(unsigned i=0; i -bool Action::parseNumberedVector(const std::string&key, const int no, std::vector&t){ +bool Action::parseNumberedVector(const std::string&key, const int no, std::vector&t) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); if( !keywords.numbered(key) ) error("numbered keywords are not allowed for " + key ); @@ -397,37 +397,37 @@ bool Action::parseNumberedVector(const std::string&key, const int no, std::vecto bool found=Tools::parseVector(line,key+num,t,replica_index); if(present && !found) error("keyword " + key +" could not be read correctly"); - if( keywords.style(key,"compulsory") ){ - if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size"); - } else if ( !found ){ + if( keywords.style(key,"compulsory") ) { + if (!skipcheck && found && t.size()!=size ) error("vector read in for keyword " + key + num + " has the wrong size"); + } else if ( !found ) { t.resize(0); } return found; } inline -void Action::deactivate(){ +void Action::deactivate() { options.clear(); active=false; } inline -bool Action::isActive()const{ +bool Action::isActive()const { return active; } inline -bool Action::isOptionOn(const std::string &s)const{ +bool Action::isOptionOn(const std::string &s)const { return options.count(s); } inline -bool Action::getRestart()const{ +bool Action::getRestart()const { return restart; } inline -bool Action::getCPT()const{ +bool Action::getCPT()const { return doCheckPoint; } diff --git a/src/core/ActionAtomistic.cpp b/src/core/ActionAtomistic.cpp index 288216266f..29ed09e3da 100644 --- a/src/core/ActionAtomistic.cpp +++ b/src/core/ActionAtomistic.cpp @@ -37,30 +37,30 @@ using namespace std; namespace PLMD { -ActionAtomistic::~ActionAtomistic(){ +ActionAtomistic::~ActionAtomistic() { // forget the pending request atoms.remove(this); delete(&pbc); } ActionAtomistic::ActionAtomistic(const ActionOptions&ao): -Action(ao), -pbc(*new(Pbc)), -lockRequestAtoms(false), -donotretrieve(false), -donotforce(false), -atoms(plumed.getAtoms()) + Action(ao), + pbc(*new(Pbc)), + lockRequestAtoms(false), + donotretrieve(false), + donotforce(false), + atoms(plumed.getAtoms()) { atoms.add(this); // if(atoms.getNatoms()==0) error("Cannot perform calculations involving atoms without atoms"); } -void ActionAtomistic::registerKeywords( Keywords& keys ){ +void ActionAtomistic::registerKeywords( Keywords& keys ) { (void) keys; // avoid warning } -void ActionAtomistic::requestAtoms(const vector & a){ +void ActionAtomistic::requestAtoms(const vector & a) { plumed_massert(!lockRequestAtoms,"requested atom list can only be changed in the prepare() method"); int nat=a.size(); indexes=a; @@ -71,7 +71,7 @@ void ActionAtomistic::requestAtoms(const vector & a){ int n=atoms.positions.size(); clearDependencies(); unique.clear(); - for(unsigned i=0;i=n) error("atom out of range"); if(atoms.isVirtualAtom(indexes[i])) addDependency(atoms.getVirtualAtomsAction(indexes[i])); // only real atoms are requested to lower level Atoms class @@ -80,24 +80,24 @@ void ActionAtomistic::requestAtoms(const vector & a){ } -Vector ActionAtomistic::pbcDistance(const Vector &v1,const Vector &v2)const{ +Vector ActionAtomistic::pbcDistance(const Vector &v1,const Vector &v2)const { return pbc.distance(v1,v2); } -void ActionAtomistic::pbcApply(std::vector& dlist, unsigned max_index)const{ +void ActionAtomistic::pbcApply(std::vector& dlist, unsigned max_index)const { pbc.apply(dlist, max_index); } -void ActionAtomistic::calculateNumericalDerivatives( ActionWithValue* a ){ +void ActionAtomistic::calculateNumericalDerivatives( ActionWithValue* a ) { calculateAtomicNumericalDerivatives( a, 0 ); } -void ActionAtomistic::changeBox( const Tensor& newbox ){ +void ActionAtomistic::changeBox( const Tensor& newbox ) { pbc.setBox( newbox ); } -void ActionAtomistic::calculateAtomicNumericalDerivatives( ActionWithValue* a, const unsigned& startnum ){ - if(!a){ +void ActionAtomistic::calculateAtomicNumericalDerivatives( ActionWithValue* a, const unsigned& startnum ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"only Actions with a value can be differentiated"); } @@ -109,109 +109,109 @@ void ActionAtomistic::calculateAtomicNumericalDerivatives( ActionWithValue* a, c std::vector savedPositions(natoms); const double delta=sqrt(epsilon); - for(int i=0;icalculate(); - positions[i][k]=savedPositions[i][k]; - for(int j=0;jgetOutputQuantity(j); + for(int i=0; icalculate(); + positions[i][k]=savedPositions[i][k]; + for(int j=0; jgetOutputQuantity(j); + } + } + Tensor box(pbc.getBox()); + for(int i=0; i<3; i++) for(int k=0; k<3; k++) { + double arg0=box(i,k); + for(int j=0; jcalculate(); + box(i,k)=arg0; + pbc.setBox(box); + for(int j=0; jgetOutputQuantity(j); } - } - Tensor box(pbc.getBox()); - for(int i=0;i<3;i++) for(int k=0;k<3;k++){ - double arg0=box(i,k); - for(int j=0;jcalculate(); - box(i,k)=arg0; - pbc.setBox(box); - for(int j=0;jgetOutputQuantity(j); - } a->calculate(); a->clearDerivatives(); - for(int j=0;jcopyOutput(j); double ref=v->get(); - if(v->hasDerivatives()){ - for(int i=0;iaddDerivative(startnum+3*i+k,d); - } + if(v->hasDerivatives()) { + for(int i=0; iaddDerivative(startnum+3*i+k,d); + } Tensor virial; - for(int i=0;i<3;i++) for(int k=0;k<3;k++)virial(i,k)= (valuebox[j](i,k)-ref)/delta; + for(int i=0; i<3; i++) for(int k=0; k<3; k++)virial(i,k)= (valuebox[j](i,k)-ref)/delta; // BE CAREFUL WITH NON ORTHOROMBIC CELL virial=-matmul(box.transpose(),virial); - for(int i=0;i<3;i++) for(int k=0;k<3;k++) v->addDerivative(startnum+3*natoms+3*k+i,virial(k,i)); + for(int i=0; i<3; i++) for(int k=0; k<3; k++) v->addDerivative(startnum+3*natoms+3*k+i,virial(k,i)); } } } -void ActionAtomistic::parseAtomList(const std::string&key, std::vector &t){ +void ActionAtomistic::parseAtomList(const std::string&key, std::vector &t) { parseAtomList(key,-1,t); } -void ActionAtomistic::parseAtomList(const std::string&key,const int num, std::vector &t){ +void ActionAtomistic::parseAtomList(const std::string&key,const int num, std::vector &t) { plumed_massert( keywords.style(key,"atoms") || keywords.style(key,"hidden"), "keyword " + key + " should be registered as atoms"); vector strings; - if( num<0 ){ - parseVector(key,strings); - if(strings.empty()) return; + if( num<0 ) { + parseVector(key,strings); + if(strings.empty()) return; } else { - if ( !parseNumberedVector(key,num,strings) ) return; + if ( !parseNumberedVector(key,num,strings) ) return; } interpretAtomList( strings, t ); } -void ActionAtomistic::interpretAtomList( std::vector& strings, std::vector &t){ +void ActionAtomistic::interpretAtomList( std::vector& strings, std::vector &t) { Tools::interpretRanges(strings); t.resize(0); - for(unsigned i=0;i moldat=plumed.getActionSet().select(); - if( moldat.size()>0 ){ - vector atom_list; moldat[0]->interpretSymbol( symbol, atom_list ); - if( atom_list.size()>0 ){ ok=true; t.insert(t.end(),atom_list.begin(),atom_list.end()); } - else { error(strings[i] + " is not a label plumed knows"); } + if( moldat.size()>0 ) { + vector atom_list; moldat[0]->interpretSymbol( symbol, atom_list ); + if( atom_list.size()>0 ) { ok=true; t.insert(t.end(),atom_list.begin(),atom_list.end()); } + else { error(strings[i] + " is not a label plumed knows"); } } else { - error("atoms specified using @ symbol but no MOLINFO was available"); + error("atoms specified using @ symbol but no MOLINFO was available"); } - } + } // here we check if the atom name is the name of a group - if(!ok){ - if(atoms.groups.count(strings[i])){ - const auto m=atoms.groups.find(strings[i]); - t.insert(t.end(),m->second.begin(),m->second.end()); - ok=true; - } - } + if(!ok) { + if(atoms.groups.count(strings[i])) { + const auto m=atoms.groups.find(strings[i]); + t.insert(t.end(),m->second.begin(),m->second.end()); + ok=true; + } + } // here we check if the atom name is the name of an added virtual atom - if(!ok){ - const ActionSet&actionSet(plumed.getActionSet()); - for(const auto & a : actionSet){ - ActionWithVirtualAtom* c=dynamic_cast(a); - if(c) if(c->getLabel()==strings[i]){ - ok=true; - t.push_back(c->getIndex()); - break; - } - } - } - if(!ok) error("it was not possible to interpret atom name " + strings[i]); - // plumed_massert(ok,"it was not possible to interpret atom name " + strings[i]); + if(!ok) { + const ActionSet&actionSet(plumed.getActionSet()); + for(const auto & a : actionSet) { + ActionWithVirtualAtom* c=dynamic_cast(a); + if(c) if(c->getLabel()==strings[i]) { + ok=true; + t.push_back(c->getIndex()); + break; + } + } + } + if(!ok) error("it was not possible to interpret atom name " + strings[i]); + // plumed_massert(ok,"it was not possible to interpret atom name " + strings[i]); } -} +} -void ActionAtomistic::retrieveAtoms(){ +void ActionAtomistic::retrieveAtoms() { pbc=atoms.pbc; Colvar*cc=dynamic_cast(this); if(cc && cc->checkIsEnergy()) energy=atoms.getEnergy(); @@ -220,15 +220,15 @@ void ActionAtomistic::retrieveAtoms(){ const vector & p(atoms.positions); const vector & c(atoms.charges); const vector & m(atoms.masses); - for(unsigned j=0;j& forcesToApply, unsigned ind ){ +void ActionAtomistic::setForcesOnAtoms( const std::vector& forcesToApply, unsigned ind ) { if(donotforce) return; - for(unsigned i=0;i& forcesToApply plumed_dbg_assert( ind+1==forcesToApply.size()); } -void ActionAtomistic::applyForces(){ +void ActionAtomistic::applyForces() { if(donotforce) return; vector & f(atoms.forces); Tensor & v(atoms.virial); - for(unsigned j=0;j(this); if(cc && cc->checkIsEnergy()) error("can't read energies from pdb files"); - for(unsigned j=0;jpdb.size() ) error("there are not enough atoms in the input pdb file"); - if( pdb.getAtomNumbers()[j].index()!=indexes[j].index() ) error("there are atoms missing in the pdb file"); - positions[j]=pdb.getPositions()[indexes[j].index()]; + for(unsigned j=0; jpdb.size() ) error("there are not enough atoms in the input pdb file"); + if( pdb.getAtomNumbers()[j].index()!=indexes[j].index() ) error("there are atoms missing in the pdb file"); + positions[j]=pdb.getPositions()[indexes[j].index()]; } - for(unsigned j=0;j indexes; // the set of needed atoms std::set unique; @@ -111,7 +111,7 @@ class ActionAtomistic : /// Get a reference to force on energy double & modifyForceOnEnergy(); /// Get number of available atoms - unsigned getNumberOfAtoms()const{return indexes.size();} + unsigned getNumberOfAtoms()const {return indexes.size();} /// Compute the pbc distance between two positions Vector pbcDistance(const Vector&,const Vector&)const; /// Applies PBCs to a seriens of positions or distances @@ -126,7 +126,7 @@ class ActionAtomistic : void parseAtomList(const std::string&key,const int num, std::vector &t); /// Convert a set of read in strings into an atom list (this is used in parseAtomList) void interpretAtomList( std::vector& strings, std::vector &t); -/// Change the box shape +/// Change the box shape void changeBox( const Tensor& newbox ); /// Get reference to Pbc const Pbc & getPbc() const; @@ -137,15 +137,15 @@ class ActionAtomistic : /// not going to be retrieved. Can be used for optimization. Notice that /// calling getPosition(int) in an Action where DoNotRetrieve() was called might /// lead to undefined behavior. - void doNotRetrieve(){donotretrieve=true;} + void doNotRetrieve() {donotretrieve=true;} /// Skip atom forces - use with care. /// If this function is called during initialization, then forces are /// not going to be propagated. Can be used for optimization. - void doNotForce(){donotforce=true;} + void doNotForce() {donotforce=true;} /// Make atoms whole, assuming they are in the proper order void makeWhole(); /// Allow calls to modifyGlobalForce() - void allowToAccessGlobalForces(){atoms.zeroallforces=true;} + void allowToAccessGlobalForces() {atoms.zeroallforces=true;} public: // virtual functions: @@ -157,10 +157,10 @@ class ActionAtomistic : void clearOutputForces(); -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. The default will be correct for the vast majority of cases virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); -/// Numerical derivative routine to use when using Actions that inherit from BOTH +/// Numerical derivative routine to use when using Actions that inherit from BOTH /// ActionWithArguments and ActionAtomistic void calculateAtomicNumericalDerivatives( ActionWithValue* a, const unsigned& startnum ); @@ -169,38 +169,38 @@ class ActionAtomistic : void lockRequests(); void unlockRequests(); const std::set & getUnique()const; -/// Read in an input file containing atom positions and calculate the action for the atomic +/// Read in an input file containing atom positions and calculate the action for the atomic /// configuration therin void readAtomsFromPDB( const PDB& pdb ); }; inline -const Vector & ActionAtomistic::getPosition(int i)const{ +const Vector & ActionAtomistic::getPosition(int i)const { return positions[i]; } inline -const Vector & ActionAtomistic::getPosition(AtomNumber i)const{ +const Vector & ActionAtomistic::getPosition(AtomNumber i)const { return atoms.positions[i.index()]; } inline -Vector & ActionAtomistic::modifyPosition(AtomNumber i){ +Vector & ActionAtomistic::modifyPosition(AtomNumber i) { return atoms.positions[i.index()]; } inline -Vector & ActionAtomistic::modifyGlobalForce(AtomNumber i){ +Vector & ActionAtomistic::modifyGlobalForce(AtomNumber i) { return atoms.forces[i.index()]; } inline -Tensor & ActionAtomistic::modifyGlobalVirial(){ +Tensor & ActionAtomistic::modifyGlobalVirial() { return atoms.virial; } inline -double ActionAtomistic::getMass(int i)const{ +double ActionAtomistic::getMass(int i)const { return masses[i]; } @@ -211,72 +211,72 @@ double ActionAtomistic::getCharge(int i) const { } inline -const std::vector & ActionAtomistic::getAbsoluteIndexes()const{ +const std::vector & ActionAtomistic::getAbsoluteIndexes()const { return indexes; } inline -AtomNumber ActionAtomistic::getAbsoluteIndex(int i)const{ +AtomNumber ActionAtomistic::getAbsoluteIndex(int i)const { return indexes[i]; } inline -const std::vector & ActionAtomistic::getPositions()const{ +const std::vector & ActionAtomistic::getPositions()const { return positions; } inline -const double & ActionAtomistic::getEnergy()const{ +const double & ActionAtomistic::getEnergy()const { return energy; } inline -const Tensor & ActionAtomistic::getBox()const{ +const Tensor & ActionAtomistic::getBox()const { return pbc.getBox(); } inline -std::vector & ActionAtomistic::modifyForces(){ +std::vector & ActionAtomistic::modifyForces() { return forces; } inline -Tensor & ActionAtomistic::modifyVirial(){ +Tensor & ActionAtomistic::modifyVirial() { return virial; } inline -double & ActionAtomistic::modifyForceOnEnergy(){ +double & ActionAtomistic::modifyForceOnEnergy() { return forceOnEnergy; } inline -const Pbc & ActionAtomistic::getPbc() const{ - return pbc; +const Pbc & ActionAtomistic::getPbc() const { + return pbc; } inline -void ActionAtomistic::lockRequests(){ +void ActionAtomistic::lockRequests() { lockRequestAtoms=true; } inline -void ActionAtomistic::unlockRequests(){ +void ActionAtomistic::unlockRequests() { lockRequestAtoms=false; } inline -const std::set & ActionAtomistic::getUnique()const{ +const std::set & ActionAtomistic::getUnique()const { return unique; } inline -unsigned ActionAtomistic::getTotAtoms()const{ +unsigned ActionAtomistic::getTotAtoms()const { return atoms.positions.size(); } inline -Pbc & ActionAtomistic::modifyGlobalPbc(){ +Pbc & ActionAtomistic::modifyGlobalPbc() { return atoms.pbc; } diff --git a/src/core/ActionPilot.cpp b/src/core/ActionPilot.cpp index 10007dedcb..fbd6d3bb2f 100644 --- a/src/core/ActionPilot.cpp +++ b/src/core/ActionPilot.cpp @@ -22,33 +22,33 @@ #include "ActionPilot.h" using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionPilot::registerKeywords(Keywords& keys){ +void ActionPilot::registerKeywords(Keywords& keys) { } ActionPilot::ActionPilot(const ActionOptions&ao): -Action(ao), -stride(1) + Action(ao), + stride(1) { - if( keywords.exists("STRIDE") ){ - parse("STRIDE",stride); - if( !keywords.style("STRIDE","hidden") ) log.printf(" with stride %d\n",stride); + if( keywords.exists("STRIDE") ) { + parse("STRIDE",stride); + if( !keywords.style("STRIDE","hidden") ) log.printf(" with stride %d\n",stride); } else { - stride=0; + stride=0; } } -bool ActionPilot::onStep()const{ +bool ActionPilot::onStep()const { if( stride>0 ) return getStep()%stride==0; return false; } -int ActionPilot::getStride()const{ +int ActionPilot::getStride()const { return stride; } -void ActionPilot::setStride( const int& n ){ +void ActionPilot::setStride( const int& n ) { stride=n; } diff --git a/src/core/ActionPilot.h b/src/core/ActionPilot.h index 007508ca64..bf3e024463 100644 --- a/src/core/ActionPilot.h +++ b/src/core/ActionPilot.h @@ -24,13 +24,13 @@ #include "Action.h" -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT This is used to create PLMD::Action objects that are run with some set frequency. -Any PLMD::Action -that does not inherit from PLMD::Action is only run when some other Action requires the output from +Any PLMD::Action +that does not inherit from PLMD::Action is only run when some other Action requires the output from it in order to run. This class is used in PLMD::Bias Action which drives the execution of other Action's. Action's of this kind are executed with a fixed stride diff --git a/src/core/ActionRegister.cpp b/src/core/ActionRegister.cpp index b948e69a54..e064392c39 100644 --- a/src/core/ActionRegister.cpp +++ b/src/core/ActionRegister.cpp @@ -27,34 +27,34 @@ using namespace std; -namespace PLMD{ +namespace PLMD { -ActionRegister::~ActionRegister(){ - if(m.size()>0){ +ActionRegister::~ActionRegister() { + if(m.size()>0) { string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: Directive "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -ActionRegister& actionRegister(){ +ActionRegister& actionRegister() { static ActionRegister ans; return ans; } -void ActionRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void ActionRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void ActionRegister::add(string key,creator_pointer f,keywords_pointer k){ - if(m.count(key)){ +void ActionRegister::add(string key,creator_pointer f,keywords_pointer k) { + if(m.count(key)) { m.erase(key); disabled.insert(key); - }else{ + } else { m.insert(pair(key,f)); // Store a pointer to the function that creates keywords // A pointer is stored and not the keywords because all @@ -63,66 +63,66 @@ void ActionRegister::add(string key,creator_pointer f,keywords_pointer k){ }; } -bool ActionRegister::check(string key){ +bool ActionRegister::check(string key) { if(m.count(key)>0 && mk.count(key)>0) return true; return false; } -Action* ActionRegister::create(const ActionOptions&ao){ +Action* ActionRegister::create(const ActionOptions&ao) { if(ao.line.size()<1)return NULL; - // Create a copy of the manual locally. The manual is - // then added to the ActionOptions. This allows us to + // Create a copy of the manual locally. The manual is + // then added to the ActionOptions. This allows us to // ensure during construction that all the keywords for // the action have been documented. In addition, we can // generate the documentation when the user makes an error // in the input. Action* action; - if( check(ao.line[0]) ){ - Keywords keys; mk[ao.line[0]](keys); - ActionOptions nao( ao,keys ); - action=m[ao.line[0]](nao); - keys.destroyData(); + if( check(ao.line[0]) ) { + Keywords keys; mk[ao.line[0]](keys); + ActionOptions nao( ao,keys ); + action=m[ao.line[0]](nao); + keys.destroyData(); } else action=NULL; return action; } -bool ActionRegister::printManual( const std::string& action, const bool& vimout ){ - if ( check(action) ){ - Keywords keys; mk[action](keys); - if( vimout ){ - printf("%s",action.c_str()); keys.print_vim(); printf("\n"); - } else { - keys.print_html(); - } - keys.destroyData(); - return true; +bool ActionRegister::printManual( const std::string& action, const bool& vimout ) { + if ( check(action) ) { + Keywords keys; mk[action](keys); + if( vimout ) { + printf("%s",action.c_str()); keys.print_vim(); printf("\n"); + } else { + keys.print_html(); + } + keys.destroyData(); + return true; } else { - return false; - } + return false; + } } -bool ActionRegister::printTemplate( const std::string& action, bool include_optional ){ - if( check(action) ){ - Keywords keys; mk[action](keys); - keys.print_template(action, include_optional); keys.destroyData(); - return true; +bool ActionRegister::printTemplate( const std::string& action, bool include_optional ) { + if( check(action) ) { + Keywords keys; mk[action](keys); + keys.print_template(action, include_optional); keys.destroyData(); + return true; } else { - return false; + return false; } } -std::ostream & operator<<(std::ostream &log,const ActionRegister&ar){ +std::ostream & operator<<(std::ostream &log,const ActionRegister&ar) { vector s; for(const auto & it : ar.m) s.push_back(it.first); sort(s.begin(),s.end()); - for(unsigned i=0;i #include "tools/Keywords.h" -namespace PLMD{ +namespace PLMD { class Action; class ActionOptions; @@ -42,7 +42,7 @@ class ActionOptions; /// If the same directive is used for different classes, it is automatically disabled /// to avoid random results. /// -class ActionRegister{ +class ActionRegister { /// Write on a stream the list of registered directives friend std::ostream &operator<<(std::ostream &,const ActionRegister&); /// Pointer to a function which, given the options, create an Action @@ -67,8 +67,8 @@ class ActionRegister{ /// \param ao object containing information for initialization, such as the full input line, a pointer to PlumedMain, etc Action* create(const ActionOptions&ao); /// Print out the keywords for an action in html/vim ready for input into the manual - bool printManual(const std::string& action, const bool& vimout); -/// Print out a template command for an action + bool printManual(const std::string& action, const bool& vimout); +/// Print out a template command for an action bool printTemplate(const std::string& action, bool include_optional); void remove(creator_pointer); ~ActionRegister(); diff --git a/src/core/ActionSet.cpp b/src/core/ActionSet.cpp index 9a1735dc20..35334eca21 100644 --- a/src/core/ActionSet.cpp +++ b/src/core/ActionSet.cpp @@ -22,35 +22,35 @@ #include "ActionSet.h" using namespace std; -namespace PLMD{ +namespace PLMD { ActionSet::ActionSet(PlumedMain&p): -plumed(p){ + plumed(p) { (void) plumed; // to suppress warning about "unused plumed" } ActionSet::~ActionSet() { - for(int i=size()-1;i>=0;i--) delete (*this)[i]; + for(int i=size()-1; i>=0; i--) delete (*this)[i]; } -void ActionSet::clearDelete(){ - for(int i=size()-1;i>=0;i--) delete (*this)[i]; +void ActionSet::clearDelete() { + for(int i=size()-1; i>=0; i--) delete (*this)[i]; clear(); } -std::string ActionSet::getLabelList() const{ +std::string ActionSet::getLabelList() const { std::string outlist; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { outlist+=dynamic_cast(p)->getLabel()+" "; }; return outlist; } -std::vector ActionSet::getLabelVector() const{ +std::vector ActionSet::getLabelVector() const { std::vector outlist; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { outlist.push_back(dynamic_cast(p)->getLabel()); }; return outlist; diff --git a/src/core/ActionSet.h b/src/core/ActionSet.h index 17b605dbf7..c2d48a2690 100644 --- a/src/core/ActionSet.h +++ b/src/core/ActionSet.h @@ -62,7 +62,7 @@ class ActionSet: T selectWithLabel(const std::string&s)const; /// get the labels in the list of actions in form of a string (useful to debug) std::string getLabelList() const; -/// get the labels in the form of a vector of strings +/// get the labels in the form of a vector of strings std::vector getLabelVector() const; }; @@ -70,9 +70,9 @@ class ActionSet: // INLINE IMPLEMENTATIONS: template -std::vector ActionSet::select()const{ +std::vector ActionSet::select()const { std::vector ret; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { T t=dynamic_cast(p); if(t) ret.push_back(t); }; @@ -80,8 +80,8 @@ std::vector ActionSet::select()const{ } template -T ActionSet::selectWithLabel(const std::string&s)const{ - for(const auto & p : (*this)){ +T ActionSet::selectWithLabel(const std::string&s)const { + for(const auto & p : (*this)) { T t=dynamic_cast(p); if(t && dynamic_cast(t)->getLabel()==s) return t; }; @@ -89,9 +89,9 @@ T ActionSet::selectWithLabel(const std::string&s)const{ } template -std::vector ActionSet::selectNot()const{ +std::vector ActionSet::selectNot()const { std::vector ret; - for(const auto & p : (*this)){ + for(const auto & p : (*this)) { T t=dynamic_cast(p); if(!t) ret.push_back(p); }; diff --git a/src/core/ActionSetup.cpp b/src/core/ActionSetup.cpp index 9bc9e527b0..1a0216a7b5 100644 --- a/src/core/ActionSetup.cpp +++ b/src/core/ActionSetup.cpp @@ -24,19 +24,19 @@ #include "ActionSet.h" #include "tools/Exception.h" -namespace PLMD{ +namespace PLMD { ActionSetup::ActionSetup(const ActionOptions&ao): Action(ao) { const ActionSet& actionset(plumed.getActionSet()); - for(const auto & p : actionset){ + for(const auto & p : actionset) { // check that all the preceeding actions are ActionSetup if( !dynamic_cast(p) ) error("Action " + getLabel() + " is a setup action, and should be only preceeded by other setup actions"); } } -void ActionSetup::registerKeywords( Keywords& keys ){ +void ActionSetup::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); keys.remove("LABEL"); } diff --git a/src/core/ActionSetup.h b/src/core/ActionSetup.h index bb9dfc5dc2..d76a0bea1a 100644 --- a/src/core/ActionSetup.h +++ b/src/core/ActionSetup.h @@ -24,7 +24,7 @@ #include "Action.h" -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT @@ -36,11 +36,11 @@ class ActionSetup : /// Constructor explicit ActionSetup(const ActionOptions&ao); /// Creator of keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Do nothing. - void calculate(){} + void calculate() {} /// Do nothing. - void apply(){} + void apply() {} }; } diff --git a/src/core/ActionWithArguments.cpp b/src/core/ActionWithArguments.cpp index b492410ca7..23b7729389 100644 --- a/src/core/ActionWithArguments.cpp +++ b/src/core/ActionWithArguments.cpp @@ -25,217 +25,217 @@ #include "PlumedMain.h" #include "ActionSet.h" #include -#ifdef __PLUMED_HAS_CREGEX +#ifdef __PLUMED_HAS_CREGEX #include -#include "regex.h" +#include "regex.h" #endif using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionWithArguments::registerKeywords(Keywords& keys){ +void ActionWithArguments::registerKeywords(Keywords& keys) { keys.reserve("numbered","ARG","the input for this action is the scalar output from one or more other actions. The particular scalars that you will use " - "are referenced using the label of the action. If the label appears on its own then it is assumed that the Action calculates " - "a single scalar value. The value of this scalar is thus used as the input to this new action. If * or *.* appears the " - "scalars calculated by all the proceding actions in the input file are taken. Some actions have multi-component outputs and " - "each component of the output has a specific label. For example a \\ref DISTANCE action labelled dist may have three componets " - "x, y and z. To take just the x component you should use dist.x, if you wish to take all three components then use dist.*." - "More information on the referencing of Actions can be found in the section of the manual on the PLUMED \\ref Syntax. " - "Scalar values can also be " - "referenced using POSIX regular expressions as detailed in the section on \\ref Regex. To use this feature you you must compile " - "PLUMED with the appropriate flag."); + "are referenced using the label of the action. If the label appears on its own then it is assumed that the Action calculates " + "a single scalar value. The value of this scalar is thus used as the input to this new action. If * or *.* appears the " + "scalars calculated by all the proceding actions in the input file are taken. Some actions have multi-component outputs and " + "each component of the output has a specific label. For example a \\ref DISTANCE action labelled dist may have three componets " + "x, y and z. To take just the x component you should use dist.x, if you wish to take all three components then use dist.*." + "More information on the referencing of Actions can be found in the section of the manual on the PLUMED \\ref Syntax. " + "Scalar values can also be " + "referenced using POSIX regular expressions as detailed in the section on \\ref Regex. To use this feature you you must compile " + "PLUMED with the appropriate flag."); } -void ActionWithArguments::parseArgumentList(const std::string&key,std::vector&arg){ - vector c; arg.clear(); parseVector(key,c); - if( c.size()==0 && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ){ +void ActionWithArguments::parseArgumentList(const std::string&key,std::vector&arg) { + vector c; arg.clear(); parseVector(key,c); + if( c.size()==0 && (keywords.style(key,"compulsory") || keywords.style(key,"hidden")) ) { std::string def; if( keywords.getDefaultValue(key,def) ) c.push_back( def ); } interpretArgumentList(c,arg); } -bool ActionWithArguments::parseArgumentList(const std::string&key,int i,std::vector&arg){ - vector c; - arg.clear(); +bool ActionWithArguments::parseArgumentList(const std::string&key,int i,std::vector&arg) { + vector c; + arg.clear(); if(parseNumberedVector(key,i,c)) { interpretArgumentList(c,arg); return true; } else return false; } -void ActionWithArguments::interpretArgumentList(const std::vector& c, std::vector&arg){ - for(unsigned i=0;ire_nsub==1,"I can parse with only one subexpression"); - pmatch = (regmatch_t*)malloc(sizeof(regmatch_t)*preg->re_nsub); - // select all the actions that have a value - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - for(unsigned j=0;j ss=all[j]->getComponentsVector(); - for(unsigned k=0;k str(ll); - strcpy(&str[0],ss[k].c_str()); - const char *ppstr=&str[0]; - if(!regexec(preg, ppstr , preg->re_nsub, pmatch, 0)) { - log.printf(" Something matched with \"%s\" : ",ss[k].c_str()); - do { - if (pmatch[0].rm_so != -1) { /* The regex is matching part of a string */ - char *submatch; - size_t matchlen = pmatch[0].rm_eo - pmatch[0].rm_so; - submatch = (char*)malloc(matchlen+1); - strncpy(submatch, ppstr+pmatch[0].rm_so, matchlen+1); - submatch[matchlen]='\0'; - log.printf(" subpattern %s\n", submatch); - // this is the match: try to see if it is a valid action - std::string putativeVal(submatch); - if( all[j]->exists(putativeVal) ){ - arg.push_back(all[j]->copyOutput(putativeVal)); - log.printf(" Action %s added! \n",putativeVal.c_str()); - } - free(submatch); - }; - ppstr += pmatch[0].rm_eo; /* Restart from last match */ - } while(!regexec(preg,ppstr,preg->re_nsub,pmatch,0)); - } - } - }; - regfree(preg); - free(preg); - free(pmatch); +void ActionWithArguments::interpretArgumentList(const std::vector& c, std::vector&arg) { + for(unsigned i=0; ire_nsub==1,"I can parse with only one subexpression"); + pmatch = (regmatch_t*)malloc(sizeof(regmatch_t)*preg->re_nsub); + // select all the actions that have a value + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + for(unsigned j=0; j ss=all[j]->getComponentsVector(); + for(unsigned k=0; k str(ll); + strcpy(&str[0],ss[k].c_str()); + const char *ppstr=&str[0]; + if(!regexec(preg, ppstr, preg->re_nsub, pmatch, 0)) { + log.printf(" Something matched with \"%s\" : ",ss[k].c_str()); + do { + if (pmatch[0].rm_so != -1) { /* The regex is matching part of a string */ + char *submatch; + size_t matchlen = pmatch[0].rm_eo - pmatch[0].rm_so; + submatch = (char*)malloc(matchlen+1); + strncpy(submatch, ppstr+pmatch[0].rm_so, matchlen+1); + submatch[matchlen]='\0'; + log.printf(" subpattern %s\n", submatch); + // this is the match: try to see if it is a valid action + std::string putativeVal(submatch); + if( all[j]->exists(putativeVal) ) { + arg.push_back(all[j]->copyOutput(putativeVal)); + log.printf(" Action %s added! \n",putativeVal.c_str()); + } + free(submatch); + }; + ppstr += pmatch[0].rm_eo; /* Restart from last match */ + } while(!regexec(preg,ppstr,preg->re_nsub,pmatch,0)); + } + } + }; + regfree(preg); + free(preg); + free(pmatch); #else - plumed_merror("Regexp support not compiled!"); + plumed_merror("Regexp support not compiled!"); #endif - }else{ - plumed_merror("did you want to use regexp to input arguments? enclose it between two round braces (...) with no spaces!"); - } - }else{ - std::size_t dot=c[i].find_first_of('.'); - string a=c[i].substr(0,dot); - string name=c[i].substr(dot+1); - if(c[i].find(".")!=string::npos){ // if it contains a dot: - if(a=="*" && name=="*"){ - // Take all values from all actions - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - for(unsigned j=0;jgetNumberOfComponents();++k) arg.push_back(all[j]->copyOutput(k)); - } - } else if ( name=="*"){ - // Take all the values from an action with a specific name - ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); - if(!action){ - std::string str=" (hint! the actions in this ActionSet are: "; - str+=plumed.getActionSet().getLabelList()+")"; - error("cannot find action named " + a + str); - } - if( action->getNumberOfComponents()==0 ) error("found " + a +".* indicating use all components calculated by action with label " + a + " but this action has no components"); - for(int k=0;kgetNumberOfComponents();++k) arg.push_back(action->copyOutput(k)); - } else if ( a=="*" ){ - // Take components from all actions with a specific name - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - unsigned nval=0; - for(unsigned j=0;jgetLabel() + "." + name; - if( all[j]->exists(flab) ){ arg.push_back(all[j]->copyOutput(flab)); nval++; } - } - if(nval==0) error("found no actions with a component called " + name ); - } else { - // Take values with a specific name - ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); - if(!action){ - std::string str=" (hint! the actions in this ActionSet are: "; - str+=plumed.getActionSet().getLabelList()+")"; - error("cannot find action named " + a +str); - } - if( !(action->exists(c[i])) ){ - std::string str=" (hint! the components in this actions are: "; - str+=action->getComponentsList()+")"; - error("action " + a + " has no component named " + name + str); - } ; - arg.push_back(action->copyOutput(c[i])); - } - } else { // if it doesn't contain a dot - if(c[i]=="*"){ - // Take all values from all actions - std::vector all=plumed.getActionSet().select(); - if( all.empty() ) error("your input file is not telling plumed to calculate anything"); - for(unsigned j=0;jgetNumberOfComponents();++k) arg.push_back(all[j]->copyOutput(k)); - } - } else { - ActionWithValue* action=plumed.getActionSet().selectWithLabel(c[i]); - if(!action){ - std::string str=" (hint! the actions in this ActionSet are: "; - str+=plumed.getActionSet().getLabelList()+")"; - error("cannot find action named " + c[i] + str ); - } - if( !(action->exists(c[i])) ){ - std::string str=" (hint! the components in this actions are: "; - str+=action->getComponentsList()+")"; - error("action " + c[i] + " has no component named " + c[i] +str); - }; - arg.push_back(action->copyOutput(c[i])); - } - } - } + } else { + plumed_merror("did you want to use regexp to input arguments? enclose it between two round braces (...) with no spaces!"); + } + } else { + std::size_t dot=c[i].find_first_of('.'); + string a=c[i].substr(0,dot); + string name=c[i].substr(dot+1); + if(c[i].find(".")!=string::npos) { // if it contains a dot: + if(a=="*" && name=="*") { + // Take all values from all actions + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + for(unsigned j=0; jgetNumberOfComponents(); ++k) arg.push_back(all[j]->copyOutput(k)); + } + } else if ( name=="*") { + // Take all the values from an action with a specific name + ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); + if(!action) { + std::string str=" (hint! the actions in this ActionSet are: "; + str+=plumed.getActionSet().getLabelList()+")"; + error("cannot find action named " + a + str); + } + if( action->getNumberOfComponents()==0 ) error("found " + a +".* indicating use all components calculated by action with label " + a + " but this action has no components"); + for(int k=0; kgetNumberOfComponents(); ++k) arg.push_back(action->copyOutput(k)); + } else if ( a=="*" ) { + // Take components from all actions with a specific name + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + unsigned nval=0; + for(unsigned j=0; jgetLabel() + "." + name; + if( all[j]->exists(flab) ) { arg.push_back(all[j]->copyOutput(flab)); nval++; } + } + if(nval==0) error("found no actions with a component called " + name ); + } else { + // Take values with a specific name + ActionWithValue* action=plumed.getActionSet().selectWithLabel(a); + if(!action) { + std::string str=" (hint! the actions in this ActionSet are: "; + str+=plumed.getActionSet().getLabelList()+")"; + error("cannot find action named " + a +str); + } + if( !(action->exists(c[i])) ) { + std::string str=" (hint! the components in this actions are: "; + str+=action->getComponentsList()+")"; + error("action " + a + " has no component named " + name + str); + } ; + arg.push_back(action->copyOutput(c[i])); + } + } else { // if it doesn't contain a dot + if(c[i]=="*") { + // Take all values from all actions + std::vector all=plumed.getActionSet().select(); + if( all.empty() ) error("your input file is not telling plumed to calculate anything"); + for(unsigned j=0; jgetNumberOfComponents(); ++k) arg.push_back(all[j]->copyOutput(k)); + } + } else { + ActionWithValue* action=plumed.getActionSet().selectWithLabel(c[i]); + if(!action) { + std::string str=" (hint! the actions in this ActionSet are: "; + str+=plumed.getActionSet().getLabelList()+")"; + error("cannot find action named " + c[i] + str ); + } + if( !(action->exists(c[i])) ) { + std::string str=" (hint! the components in this actions are: "; + str+=action->getComponentsList()+")"; + error("action " + c[i] + " has no component named " + c[i] +str); + }; + arg.push_back(action->copyOutput(c[i])); + } + } + } } } -void ActionWithArguments::expandArgKeywordInPDB( PDB& pdb ){ +void ActionWithArguments::expandArgKeywordInPDB( PDB& pdb ) { std::vector pdb_remark=pdb.getRemark(); std::vector arg_names; bool found=Tools::parseVector(pdb_remark,"ARG",arg_names); - if( found ){ - std::vector arg_vals; - interpretArgumentList( arg_names, arg_vals ); - std::string new_args="ARG=" + arg_vals[0]->getName(); - for(unsigned i=1;igetName(); - pdb.setArgKeyword( new_args ); + if( found ) { + std::vector arg_vals; + interpretArgumentList( arg_names, arg_vals ); + std::string new_args="ARG=" + arg_vals[0]->getName(); + for(unsigned i=1; igetName(); + pdb.setArgKeyword( new_args ); } } -void ActionWithArguments::requestArguments(const vector &arg){ +void ActionWithArguments::requestArguments(const vector &arg) { plumed_massert(!lockRequestArguments,"requested argument list can only be changed in the prepare() method"); arguments=arg; clearDependencies(); std::string fullname,name; - for(unsigned i=0;igetName(); - if(fullname.find(".")!=string::npos){ - std::size_t dot=fullname.find_first_of('.'); - name=fullname.substr(0,dot); - } else { - name=fullname; - } - ActionWithValue* action=plumed.getActionSet().selectWithLabel(name); - plumed_massert(action,"cannot find action named (in requestArguments - this is weird)" + name); - addDependency(action); + for(unsigned i=0; igetName(); + if(fullname.find(".")!=string::npos) { + std::size_t dot=fullname.find_first_of('.'); + name=fullname.substr(0,dot); + } else { + name=fullname; + } + ActionWithValue* action=plumed.getActionSet().selectWithLabel(name); + plumed_massert(action,"cannot find action named (in requestArguments - this is weird)" + name); + addDependency(action); } } @@ -243,21 +243,21 @@ ActionWithArguments::ActionWithArguments(const ActionOptions&ao): Action(ao), lockRequestArguments(false) { - if( keywords.exists("ARG") && !keywords.exists("DATA") ){ - vector arg; - parseArgumentList("ARG",arg); + if( keywords.exists("ARG") && !keywords.exists("DATA") ) { + vector arg; + parseArgumentList("ARG",arg); - if(!arg.empty()){ - log.printf(" with arguments"); - for(unsigned i=0;igetName().c_str()); - log.printf("\n"); - } - requestArguments(arg); + if(!arg.empty()) { + log.printf(" with arguments"); + for(unsigned i=0; igetName().c_str()); + log.printf("\n"); + } + requestArguments(arg); } } -void ActionWithArguments::calculateNumericalDerivatives( ActionWithValue* a ){ - if(!a){ +void ActionWithArguments::calculateNumericalDerivatives( ActionWithValue* a ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"cannot compute numerical derivatives for an action without values"); } @@ -265,24 +265,24 @@ void ActionWithArguments::calculateNumericalDerivatives( ActionWithValue* a ){ const int nval=a->getNumberOfComponents(); const int npar=arguments.size(); std::vector value (nval*npar); - for(int i=0;iget(); arguments[i]->set(arg0+sqrt(epsilon)); a->calculate(); arguments[i]->set(arg0); - for(int j=0;jgetOutputQuantity(j); } } a->calculate(); a->clearDerivatives(); - for(int j=0;jcopyOutput(j); - if( v->hasDerivatives() ) for(int i=0;iaddDerivative(i,(value[i*nval+j]-a->getOutputQuantity(j))/sqrt(epsilon)); + if( v->hasDerivatives() ) for(int i=0; iaddDerivative(i,(value[i*nval+j]-a->getOutputQuantity(j))/sqrt(epsilon)); } } -double ActionWithArguments::getProjection(unsigned i,unsigned j)const{ +double ActionWithArguments::getProjection(unsigned i,unsigned j)const { plumed_massert(i& forces ){ - for(unsigned i=0;iaddForce( forces[i] ); +void ActionWithArguments::addForcesOnArguments( const std::vector& forces ) { + for(unsigned i=0; iaddForce( forces[i] ); } } diff --git a/src/core/ActionWithArguments.h b/src/core/ActionWithArguments.h index a4036f99c9..47a14b7607 100644 --- a/src/core/ActionWithArguments.h +++ b/src/core/ActionWithArguments.h @@ -26,16 +26,16 @@ #include "Value.h" #include -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT -This is used to create PLMD::Action objects that take the output from some other Action as input. +This is used to create PLMD::Action objects that take the output from some other Action as input. This is used in PLMD::Function and PLMD::Bias - PLMD::Action objects that inherit from PLMD::ActionWithArguments take + PLMD::Action objects that inherit from PLMD::ActionWithArguments take values and components calculated in other PLMD::Action objects and - use this information to calculate some new function. If you have - only one list of arguments you should use the reserved keyword ARG + use this information to calculate some new function. If you have + only one list of arguments you should use the reserved keyword ARG when you use parseArgumentList. */ @@ -60,7 +60,7 @@ class ActionWithArguments: virtual unsigned getNumberOfArguments() const ; /// Takes the difference taking into account pbc for arg i double difference(int, double, double) const; -/// Takes one value and brings it back into the pbc of argument i +/// Takes one value and brings it back into the pbc of argument i double bringBackInPbc(int i,double d1)const; /// Parse a list of arguments void parseArgumentList(const std::string&key,std::vector&args); @@ -72,9 +72,9 @@ class ActionWithArguments: void addForcesOnArguments( const std::vector& forces ); public: explicit ActionWithArguments(const ActionOptions&); - virtual ~ActionWithArguments(){} + virtual ~ActionWithArguments() {} /// Calculate the numerical derivatives -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. The default will be correct for the vast majority of cases virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); void lockRequests(); @@ -87,7 +87,7 @@ class ActionWithArguments: inline -Value* ActionWithArguments::getPntrToArgument( const unsigned n ){ +Value* ActionWithArguments::getPntrToArgument( const unsigned n ) { return arguments[n]; } @@ -97,27 +97,27 @@ double ActionWithArguments::getArgument(const unsigned n) const { } inline -unsigned ActionWithArguments::getNumberOfArguments()const{ +unsigned ActionWithArguments::getNumberOfArguments()const { return arguments.size(); } inline -double ActionWithArguments::difference(int i,double d1,double d2)const{ +double ActionWithArguments::difference(int i,double d1,double d2)const { return arguments[i]->difference(d1,d2); } inline -double ActionWithArguments::bringBackInPbc(int i,double d1)const{ +double ActionWithArguments::bringBackInPbc(int i,double d1)const { return arguments[i]->bringBackInPbc(d1); } inline -void ActionWithArguments::lockRequests(){ +void ActionWithArguments::lockRequests() { lockRequestArguments=true; } inline -void ActionWithArguments::unlockRequests(){ +void ActionWithArguments::unlockRequests() { lockRequestArguments=false; } diff --git a/src/core/ActionWithValue.cpp b/src/core/ActionWithValue.cpp index 1a8d821116..bc92a9410d 100644 --- a/src/core/ActionWithValue.cpp +++ b/src/core/ActionWithValue.cpp @@ -24,32 +24,32 @@ #include "tools/OpenMP.h" using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionWithValue::registerKeywords(Keywords& keys){ +void ActionWithValue::registerKeywords(Keywords& keys) { keys.setComponentsIntroduction("By default the value of the calculated quantity can be referenced elsewhere in the " "input file by using the label of the action. Alternatively this Action can be used " "to be used to calculate the following quantities by employing the keywords listed " - "below. These quanties can be referenced elsewhere in the input by using this Action's " + "below. These quanties can be referenced elsewhere in the input by using this Action's " "label followed by a dot and the name of the quantity required from the list below."); keys.addFlag("NUMERICAL_DERIVATIVES", false, "calculate the derivatives for these quantities numerically"); } -void ActionWithValue::noAnalyticalDerivatives(Keywords& keys){ - keys.remove("NUMERICAL_DERIVATIVES"); - keys.addFlag("NUMERICAL_DERIVATIVES",true,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used"); +void ActionWithValue::noAnalyticalDerivatives(Keywords& keys) { + keys.remove("NUMERICAL_DERIVATIVES"); + keys.addFlag("NUMERICAL_DERIVATIVES",true,"analytical derivatives are not implemented for this keyword so numerical derivatives are always used"); } -void ActionWithValue::componentsAreNotOptional(Keywords& keys){ - keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quanties can " - "be referenced elsewhere in the input by using this Action's label followed by a " - "dot and the name of the quantity required from the list below."); +void ActionWithValue::componentsAreNotOptional(Keywords& keys) { + keys.setComponentsIntroduction("By default this Action calculates the following quantities. These quanties can " + "be referenced elsewhere in the input by using this Action's label followed by a " + "dot and the name of the quantity required from the list below."); } -void ActionWithValue::useCustomisableComponents(Keywords& keys){ - keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the " - "actions input file. However, in addition to these customizable components the " - "following quantities will always be output"); +void ActionWithValue::useCustomisableComponents(Keywords& keys) { + keys.setComponentsIntroduction("The names of the components in this action can be customized by the user in the " + "actions input file. However, in addition to these customizable components the " + "following quantities will always be output"); } ActionWithValue::ActionWithValue(const ActionOptions&ao): @@ -61,35 +61,35 @@ ActionWithValue::ActionWithValue(const ActionOptions&ao): if(numericalDerivatives) log.printf(" using numerical derivatives\n"); } -ActionWithValue::~ActionWithValue(){ - for(unsigned i=0;iclearInputForce(); +void ActionWithValue::clearInputForces() { + for(unsigned i=0; iclearInputForce(); } -void ActionWithValue::clearDerivatives(){ +void ActionWithValue::clearDerivatives() { unsigned nt = OpenMP::getGoodNumThreads(values); #pragma omp parallel num_threads(nt) - { + { #pragma omp for - for(unsigned i=0;iclearDerivatives(); + for(unsigned i=0; iclearDerivatives(); } -} +} // -- These are the routine for copying the value pointers to other classes -- // bool ActionWithValue::exists( const std::string& name ) const { - for(unsigned i=0;iname==name) return true; + for(unsigned i=0; iname==name) return true; } return false; } Value* ActionWithValue::copyOutput( const std::string& name ) const { - for(unsigned i=0;iname==name) return values[i]; + for(unsigned i=0; iname==name) return values[i]; } plumed_merror("there is no pointer with name " + name); return NULL; @@ -102,30 +102,30 @@ Value* ActionWithValue::copyOutput( const unsigned& n ) const { // -- HERE WE HAVE THE STUFF FOR THE DEFAULT VALUE -- // -void ActionWithValue::addValue(){ +void ActionWithValue::addValue() { plumed_massert(values.empty(),"You have already added the default value for this action"); values.push_back(new Value(this,getLabel(), false ) ); } -void ActionWithValue::addValueWithDerivatives(){ +void ActionWithValue::addValueWithDerivatives() { plumed_massert(values.empty(),"You have already added the default value for this action"); values.push_back(new Value(this,getLabel(), true ) ); } -void ActionWithValue::setNotPeriodic(){ +void ActionWithValue::setNotPeriodic() { plumed_massert(values.size()==1,"The number of components is not equal to one"); plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); values[0]->min=0; values[0]->max=0; values[0]->setupPeriodicity(); } -void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ){ +void ActionWithValue::setPeriodic( const std::string& min, const std::string& max ) { plumed_massert(values.size()==1,"The number of components is not equal to one"); plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); values[0]->setDomain( min, max ); } -Value* ActionWithValue::getPntrToValue(){ +Value* ActionWithValue::getPntrToValue() { plumed_dbg_massert(values.size()==1,"The number of components is not equal to one"); plumed_dbg_massert(values[0]->name==getLabel(), "The value you are trying to retrieve is not the default"); return values[0]; @@ -133,34 +133,34 @@ Value* ActionWithValue::getPntrToValue(){ // -- HERE WE HAVE THE STUFF FOR NAMED VALUES / COMPONENTS -- // -void ActionWithValue::addComponent( const std::string& name ){ - if( !keywords.outputComponentExists(name,true) ){ - warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " - "registerKeywords as described in the developer docs."); +void ActionWithValue::addComponent( const std::string& name ) { + if( !keywords.outputComponentExists(name,true) ) { + warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " + "registerKeywords as described in the developer docs."); } std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname!=getLabel(),"Cannot mix single values with components"); - plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" - "Remove the line addComponent(\"bias\") from your bias."); - plumed_massert(values[i]->name!=thename,"there is already a value with this name"); + for(unsigned i=0; iname!=getLabel(),"Cannot mix single values with components"); + plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" + "Remove the line addComponent(\"bias\") from your bias."); + plumed_massert(values[i]->name!=thename,"there is already a value with this name"); } values.push_back(new Value(this,thename, false ) ); std::string msg=" added component to this action: "+thename+" \n"; log.printf(msg.c_str()); } -void ActionWithValue::addComponentWithDerivatives( const std::string& name ){ - if( !keywords.outputComponentExists(name,true) ){ - warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " - "registerKeywords as described in the developer doc."); +void ActionWithValue::addComponentWithDerivatives( const std::string& name ) { + if( !keywords.outputComponentExists(name,true) ) { + warning("a description of component " + name + " has not been added to the manual. Components should be registered like keywords in " + "registerKeywords as described in the developer doc."); } std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname!=getLabel(),"Cannot mix single values with components"); - plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" - "Remove the line addComponentWithDerivatives(\"bias\") from your bias."); - plumed_massert(values[i]->name!=thename,"there is already a value with this name"); + for(unsigned i=0; iname!=getLabel(),"Cannot mix single values with components"); + plumed_massert(values[i]->name!=thename&&name!="bias","Since PLUMED 2.3 the component 'bias' is automatically added to all biases by the general constructor!\n" + "Remove the line addComponentWithDerivatives(\"bias\") from your bias."); + plumed_massert(values[i]->name!=thename,"there is already a value with this name"); } values.push_back(new Value(this,thename, true ) ); std::string msg=" added component to this action: "+thename+" \n"; @@ -170,8 +170,8 @@ void ActionWithValue::addComponentWithDerivatives( const std::string& name ){ int ActionWithValue::getComponent( const std::string& name ) const { plumed_massert( !exists( getLabel() ), "You should not be calling this routine if you are using a value"); std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname==thename) return i; + for(unsigned i=0; iname==thename) return i; } plumed_merror("there is no component with name " + name); return -1; @@ -179,55 +179,55 @@ int ActionWithValue::getComponent( const std::string& name ) const { std::string ActionWithValue::getComponentsList( ) const { std::string complist; - for(unsigned i=0;iname+" "; + for(unsigned i=0; iname+" "; } return complist; } std::vector ActionWithValue::getComponentsVector( ) const { std::vector complist; - for(unsigned i=0;iname); + for(unsigned i=0; iname); } return complist; } -void ActionWithValue::componentIsNotPeriodic( const std::string& name ){ +void ActionWithValue::componentIsNotPeriodic( const std::string& name ) { int kk=getComponent(name); values[kk]->min=0; values[kk]->max=0; values[kk]->setupPeriodicity(); } -void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ){ +void ActionWithValue::componentIsPeriodic( const std::string& name, const std::string& min, const std::string& max ) { int kk=getComponent(name); values[kk]->setDomain(min,max); } -void ActionWithValue::setGradientsIfNeeded(){ +void ActionWithValue::setGradientsIfNeeded() { if(isOptionOn("GRADIENTS")) { - for(unsigned i=0;isetGradients(); + for(unsigned i=0; isetGradients(); } } -void ActionWithValue::turnOnDerivatives(){ +void ActionWithValue::turnOnDerivatives() { // Turn on the derivatives noderiv=false; - // Resize the derivatives - for(unsigned i=0;iresizeDerivatives( getNumberOfDerivatives() ); + // Resize the derivatives + for(unsigned i=0; iresizeDerivatives( getNumberOfDerivatives() ); // And turn on the derivatives in all actions on which we are dependent - for(unsigned i=0;i( getDependencies()[i] ); - if(vv) vv->turnOnDerivatives(); + for(unsigned i=0; i( getDependencies()[i] ); + if(vv) vv->turnOnDerivatives(); } } -Value* ActionWithValue::getPntrToComponent( const std::string& name ){ +Value* ActionWithValue::getPntrToComponent( const std::string& name ) { int kk=getComponent(name); - return values[kk]; + return values[kk]; } -Value* ActionWithValue::getPntrToComponent( int n ){ +Value* ActionWithValue::getPntrToComponent( int n ) { plumed_dbg_massert(n -namespace PLMD{ +namespace PLMD { /** \ingroup MULTIINHERIT -Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some derivatives. -This is used for PLMD::Bias, PLMD::Colvar and PLMD::Function +Used to create a PLMD::Action that has some scalar or vectorial output that may or may not have some derivatives. +This is used for PLMD::Bias, PLMD::Colvar and PLMD::Function The vast majority of the PLMD::Action objects that are implemented in plumed calculate some quantity or a set of quantities. This could be @@ -43,26 +43,26 @@ quantities between PLMD::Actions. When you are deciding what quantities your new PLMD::Action will need to store using PLMD::ActionWithValue you must ask yourself the following two questions: -- Do I need to differentiate my output quantities -- Is my PLMD::Action calculating a single thing or does the output have multiple components +- Do I need to differentiate my output quantities +- Is my PLMD::Action calculating a single thing or does the output have multiple components If the answer to the first of these questions is yes then you must setup your values -you using either PLMD::ActionWithValue::addValueWithDerivatives() or -PLMD::ActionWithValue::addComponentWithDerivatives. If the answer is no you +you using either PLMD::ActionWithValue::addValueWithDerivatives() or +PLMD::ActionWithValue::addComponentWithDerivatives. If the answer is no you can set up values using PLMD::ActionWithValue::addValue() or PLMD::ActionWithValue::addComponent(). The precise routine you use to setup your values will depend on your answer to the -second question. As you are probably aware if the output of your PLMD::Action is a -single quantity you can reference that quantity in the input file using the label of the -PLMD::Action it was calculated in. If your action outputs only one quantity -we call that quantity the value of the Action. To set the value and get pointers to it -you should use the set of routines that have the word value in the name . If, by contrast, +second question. As you are probably aware if the output of your PLMD::Action is a +single quantity you can reference that quantity in the input file using the label of the +PLMD::Action it was calculated in. If your action outputs only one quantity +we call that quantity the value of the Action. To set the value and get pointers to it +you should use the set of routines that have the word value in the name . If, by contrast, your PLMD::Action calculates multiple quantities then these quantities are referenced in input using the -label.component syntax. We refer to these multiple quantities the components +label.component syntax. We refer to these multiple quantities the components of the PLMD::Action. Perhaps unsurprisingly, when you manipulate the components of an PLMD::Action you should use the routines with the word component in the name. */ -class ActionWithValue : +class ActionWithValue : public virtual Action { private: @@ -112,7 +112,7 @@ class ActionWithValue : explicit ActionWithValue(const ActionOptions&ao); ~ActionWithValue(); -/// Register all the relevant keywords for the action +/// Register all the relevant keywords for the action static void registerKeywords( Keywords& keys ); /// Insist that numerical derivatives should always be used for an action and make this fact appear in the manual static void noAnalyticalDerivatives(Keywords& keys); @@ -125,7 +125,7 @@ class ActionWithValue : /// Get the value of one of the components of the PLMD::Action double getOutputQuantity( const unsigned j ) const ; /// Get the value with a specific name (N.B. if there is no such value this returns zero) - double getOutputQuantity( const std::string& name ) const ; + double getOutputQuantity( const std::string& name ) const ; // --- Routines for passing stuff to ActionWithArguments -- // @@ -133,14 +133,14 @@ class ActionWithValue : /// You should not use it when manipulating components. bool exists( const std::string& name ) const; /// Return a pointer to the value with name (this is used to retrieve values in other PLMD::Actions) -/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use +/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use /// getPntrToComponent instead. Value* copyOutput( const std::string&name ) const; /// Return a pointer to the value with this number (this is used to retrieve values in other PLMD::Actions) -/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use +/// You should NEVER use this routine to refer to the components of your PLMD::Action. Use /// getPntrToComponent instead. Value* copyOutput( const unsigned& n ) const; -/// get a string that contains all the available components +/// get a string that contains all the available components std::string getComponentsList( ) const ; /// get a vector that contains the label for all the components std::vector getComponentsVector( ) const ; @@ -154,17 +154,17 @@ class ActionWithValue : void clearInputForces(); /// Clear the derivatives of values wrt parameters virtual void clearDerivatives(); -/// Calculate the gradients and store them for all the values (need for projections) +/// Calculate the gradients and store them for all the values (need for projections) void setGradientsIfNeeded(); /// Set the value void setValue(Value*,double); /// Check if numerical derivatives should be used bool checkNumericalDerivatives() const ; -/// This forces the class to use numerical derivatives +/// This forces the class to use numerical derivatives void useNumericalDerivatives(); // These are things for using vectors of values as fields - virtual void checkFieldsAllowed(){ error("cannot use this action as a field"); } - virtual unsigned getNumberOfDerivatives()=0; + virtual void checkFieldsAllowed() { error("cannot use this action as a field"); } + virtual unsigned getNumberOfDerivatives()=0; /// Activate the calculation of derivatives virtual void turnOnDerivatives(); }; @@ -178,14 +178,14 @@ double ActionWithValue::getOutputQuantity(const unsigned j) const { inline double ActionWithValue::getOutputQuantity( const std::string& name ) const { std::string thename; thename=getLabel() + "." + name; - for(unsigned i=0;iname==thename ) return values[i]->value; } return 0.0; } inline -void ActionWithValue::setValue(const double& d){ +void ActionWithValue::setValue(const double& d) { plumed_massert(values.size()==1, "cannot use setValue in multi-component actions"); plumed_massert(values[0]->name==getLabel(), "The value you are trying to set is not the default"); values[0]->set(d); @@ -197,7 +197,7 @@ int ActionWithValue::getNumberOfComponents() const { } inline -void ActionWithValue::useNumericalDerivatives(){ +void ActionWithValue::useNumericalDerivatives() { plumed_massert( keywords.exists("NUMERICAL_DERIVATIVES"), "numerical derivatives are not permitted for this action" ); numericalDerivatives=true; } @@ -210,7 +210,7 @@ bool ActionWithValue::checkNumericalDerivatives() const { inline bool ActionWithValue::doNotCalculateDerivatives() const { return noderiv; -} +} diff --git a/src/core/ActionWithVirtualAtom.cpp b/src/core/ActionWithVirtualAtom.cpp index da6d8a6afe..668ea7e795 100644 --- a/src/core/ActionWithVirtualAtom.cpp +++ b/src/core/ActionWithVirtualAtom.cpp @@ -24,9 +24,9 @@ using namespace std; -namespace PLMD{ +namespace PLMD { -void ActionWithVirtualAtom::registerKeywords(Keywords& keys){ +void ActionWithVirtualAtom::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionAtomistic::registerKeywords(keys); keys.add("atoms","ATOMS","the list of atoms which are involved the virtual atom's definition"); @@ -41,71 +41,71 @@ ActionWithVirtualAtom::ActionWithVirtualAtom(const ActionOptions&ao): log.printf(" serial associated to this virtual atom is %u\n",index.serial()); } -ActionWithVirtualAtom::~ActionWithVirtualAtom(){ +ActionWithVirtualAtom::~ActionWithVirtualAtom() { atoms.removeVirtualAtom(this); } -void ActionWithVirtualAtom::apply(){ +void ActionWithVirtualAtom::apply() { Vector & f(atoms.forces[index.index()]); - for(unsigned i=0;i & a){ +void ActionWithVirtualAtom::requestAtoms(const std::vector & a) { ActionAtomistic::requestAtoms(a); derivatives.resize(a.size()); } -void ActionWithVirtualAtom::setGradients(){ +void ActionWithVirtualAtom::setGradients() { gradients.clear(); - for(unsigned i=0;igradients){ + for(const auto & p : a->gradients) { gradients[p.first]+=matmul(derivatives[i],p.second); } - // this case if the atom is a normal one + // this case if the atom is a normal one } else { gradients[an]+=derivatives[i]; } } } -void ActionWithVirtualAtom::setBoxDerivatives(const std::vector &d){ +void ActionWithVirtualAtom::setBoxDerivatives(const std::vector &d) { boxDerivatives=d; plumed_assert(d.size()==3); // Subtract the trivial part coming from a distorsion applied to the ghost atom first. // Notice that this part alone should exactly cancel the already accumulated virial // due to forces on this atom. Vector pos=atoms.positions[index.index()]; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) boxDerivatives[j][i][j]+=pos[i]; + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) boxDerivatives[j][i][j]+=pos[i]; } -void ActionWithVirtualAtom::setBoxDerivativesNoPbc(){ +void ActionWithVirtualAtom::setBoxDerivativesNoPbc() { std::vector bd(3); - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) for(unsigned k=0;k<3;k++){ + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) for(unsigned k=0; k<3; k++) { // Notice that this expression is very similar to the one used in Colvar::setBoxDerivativesNoPbc(). // Indeed, we have the negative of a sum over dependent atoms (l) of the external product between positions // and derivatives. Notice that this only works only when Pbc have not been used to compute // derivatives. - for(unsigned l=0;l &d){ +void ActionWithVirtualAtom::setAtomsDerivatives(const std::vector &d) { derivatives=d; } inline -const std::map & ActionWithVirtualAtom::getGradients()const{ +const std::map & ActionWithVirtualAtom::getGradients()const { return gradients; } diff --git a/src/core/Atoms.cpp b/src/core/Atoms.cpp index ec0ba9c58f..8841bbefeb 100644 --- a/src/core/Atoms.cpp +++ b/src/core/Atoms.cpp @@ -67,111 +67,111 @@ Atoms::Atoms(PlumedMain&plumed): mdatoms=MDAtomsBase::create(sizeof(double)); } -Atoms::~Atoms(){ - if(actions.size()>0){ +Atoms::~Atoms() { + if(actions.size()>0) { std::cerr<<"WARNING: there is some inconsistency in action added to atoms, as some of them were not properly destroyed. This might indicate an internal bug!!\n"; } delete mdatoms; delete &pbc; } -void Atoms::startStep(){ +void Atoms::startStep() { collectEnergy=false; energyHasBeenSet=false; positionsHaveBeenSet=0; massesHaveBeenSet=false; chargesHaveBeenSet=false; boxHasBeenSet=false; forcesHaveBeenSet=0; virialHasBeenSet=false; dataCanBeSet=true; } -void Atoms::setBox(void*p){ +void Atoms::setBox(void*p) { mdatoms->setBox(p); Tensor b; mdatoms->getBox(b); boxHasBeenSet=true; } -void Atoms::setPositions(void*p){ - plumed_massert( dataCanBeSet ,"setPositions must be called after setStep in MD code interface"); +void Atoms::setPositions(void*p) { + plumed_massert( dataCanBeSet,"setPositions must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL position pointer with non-zero local atoms"); mdatoms->setp(p); positionsHaveBeenSet=3; } -void Atoms::setMasses(void*p){ - plumed_massert( dataCanBeSet ,"setMasses must be called after setStep in MD code interface"); +void Atoms::setMasses(void*p) { + plumed_massert( dataCanBeSet,"setMasses must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL mass pointer with non-zero local atoms"); mdatoms->setm(p); massesHaveBeenSet=true; } -void Atoms::setCharges(void*p){ +void Atoms::setCharges(void*p) { plumed_massert( dataCanBeSet, "setCharges must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL charges pointer with non-zero local atoms"); mdatoms->setc(p); chargesHaveBeenSet=true; } -void Atoms::setVirial(void*p){ - plumed_massert( dataCanBeSet ,"setVirial must be called after setStep in MD code interface"); +void Atoms::setVirial(void*p) { + plumed_massert( dataCanBeSet,"setVirial must be called after setStep in MD code interface"); mdatoms->setVirial(p); virialHasBeenSet=true; - + } -void Atoms::setEnergy(void*p){ - plumed_massert( dataCanBeSet ,"setEnergy must be called after setStep in MD code interface"); +void Atoms::setEnergy(void*p) { + plumed_massert( dataCanBeSet,"setEnergy must be called after setStep in MD code interface"); MD2double(p,md_energy); md_energy*=MDUnits.getEnergy()/units.getEnergy(); energyHasBeenSet=true; } -void Atoms::setForces(void*p){ - plumed_massert( dataCanBeSet ,"setForces must be called after setStep in MD code interface"); +void Atoms::setForces(void*p) { + plumed_massert( dataCanBeSet,"setForces must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL force pointer with non-zero local atoms"); forcesHaveBeenSet=3; mdatoms->setf(p); } -void Atoms::setPositions(void*p,int i){ - plumed_massert( dataCanBeSet ,"setPositions must be called after setStep in MD code interface"); +void Atoms::setPositions(void*p,int i) { + plumed_massert( dataCanBeSet,"setPositions must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL positions pointer with non-zero local atoms"); mdatoms->setp(p,i); positionsHaveBeenSet++; } -void Atoms::setForces(void*p,int i){ - plumed_massert( dataCanBeSet ,"setForces must be called after setStep in MD code interface"); +void Atoms::setForces(void*p,int i) { + plumed_massert( dataCanBeSet,"setForces must be called after setStep in MD code interface"); plumed_massert( p || gatindex.size()==0, "NULL force pointer with non-zero local atoms"); mdatoms->setf(p,i); forcesHaveBeenSet++; } -void Atoms::share(){ +void Atoms::share() { std::set unique; // At first step I scatter all the atoms so as to store their mass and charge // Notice that this works with the assumption that charges and masses are // not changing during the simulation! - if(!massAndChargeOK && shareMassAndChargeOnlyAtFirstStep){ + if(!massAndChargeOK && shareMassAndChargeOnlyAtFirstStep) { shareAll(); return; } - for(unsigned i=0;iisActive()) { - if(dd && shuffledAtoms>0){ - unique.insert(actions[i]->getUnique().begin(),actions[i]->getUnique().end()); + for(unsigned i=0; iisActive()) { + if(dd && shuffledAtoms>0) { + unique.insert(actions[i]->getUnique().begin(),actions[i]->getUnique().end()); + } + if(!actions[i]->getUnique().empty()) atomsNeeded=true; } - if(!actions[i]->getUnique().empty()) atomsNeeded=true; - } share(unique); } -void Atoms::shareAll(){ +void Atoms::shareAll() { std::set unique; if(dd && shuffledAtoms>0) - for(int i=0;i& unique){ +void Atoms::share(const std::set& unique) { plumed_assert( positionsHaveBeenSet==3 && massesHaveBeenSet ); virial.zero(); - if(zeroallforces || int(gatindex.size())==natoms){ - for(int i=0;igetBox(box); @@ -179,7 +179,7 @@ void Atoms::share(const std::set& unique){ atomsNeeded=false; - if(int(gatindex.size())==natoms && shuffledAtoms==0){ + if(int(gatindex.size())==natoms && shuffledAtoms==0) { // faster version, which retrieves all atoms mdatoms->getPositions(0,natoms,positions); } else { @@ -188,7 +188,7 @@ void Atoms::share(const std::set& unique){ } // how many double per atom should be scattered: int ndata=3; - if(!massAndChargeOK){ + if(!massAndChargeOK) { ndata=5; masses.assign(masses.size(),NAN); charges.assign(charges.size(),NAN); @@ -196,34 +196,34 @@ void Atoms::share(const std::set& unique){ mdatoms->getMasses(gatindex,masses); } - if(dd && shuffledAtoms>0){ - if(dd.async){ - for(unsigned i=0;i0) { + if(dd.async) { + for(unsigned i=0; i=0){ + for(const auto & p : unique) { + if(dd.g2l[p.index()]>=0) { dd.indexToBeSent[count]=p.index(); dd.positionsToBeSent[ndata*count+0]=positions[p.index()][0]; dd.positionsToBeSent[ndata*count+1]=positions[p.index()][1]; dd.positionsToBeSent[ndata*count+2]=positions[p.index()][2]; - if(!massAndChargeOK){ + if(!massAndChargeOK) { dd.positionsToBeSent[ndata*count+3]=masses[p.index()]; dd.positionsToBeSent[ndata*count+4]=charges[p.index()]; } count++; } } - if(dd.async){ + if(dd.async) { asyncSent=true; dd.mpi_request_positions.resize(dd.Get_size()); dd.mpi_request_index.resize(dd.Get_size()); - for(int i=0;i counts(n); vector displ(n); @@ -231,17 +231,17 @@ void Atoms::share(const std::set& unique){ vector displ5(n); dd.Allgather(count,counts); displ[0]=0; - for(int i=1;i& unique){ } } -void Atoms::wait(){ +void Atoms::wait() { dataCanBeSet=false; // Everything should be set by this stage // How many double per atom should be scattered int ndata=3; if(!massAndChargeOK)ndata=5; - if(dd){ + if(dd) { dd.Bcast(box,0); } pbc.setBox(box); if(collectEnergy) energy=md_energy; - if(dd && shuffledAtoms>0){ + if(dd && shuffledAtoms>0) { // receive toBeReceived - if(asyncSent){ + if(asyncSent) { Communicator::Status status; int count=0; - for(int i=0;i(); dd.Recv(&dd.positionsToBeReceived[ndata*count],dd.positionsToBeReceived.size()-ndata*count,i,667); count+=c; } - for(int i=0;iepsilon){ - double alpha=1.0-forceOnEnergy; - mdatoms->rescaleForces(gatindex,alpha); + if(forceOnEnergy*forceOnEnergy>epsilon) { + double alpha=1.0-forceOnEnergy; + mdatoms->rescaleForces(gatindex,alpha); } mdatoms->updateForces(gatindex,forces); - if( !plumed.novirial && dd.Get_rank()==0 ){ - plumed_assert( virialHasBeenSet ); - mdatoms->updateVirial(virial); + if( !plumed.novirial && dd.Get_rank()==0 ) { + plumed_assert( virialHasBeenSet ); + mdatoms->updateVirial(virial); } } -void Atoms::setNatoms(int n){ +void Atoms::setNatoms(int n) { natoms=n; positions.resize(n); forces.resize(n); masses.resize(n); charges.resize(n); gatindex.resize(n); - for(unsigned i=0;igetRealPrecision(); } -void Atoms::MD2double(const void*m,double&d)const{ +void Atoms::MD2double(const void*m,double&d)const { plumed_assert(mdatoms); mdatoms->MD2double(m,d); } -void Atoms::double2MD(const double&d,void*m)const{ +void Atoms::double2MD(const double&d,void*m)const { plumed_assert(mdatoms); mdatoms->double2MD(d,m); } -void Atoms::updateUnits(){ +void Atoms::updateUnits() { mdatoms->setUnits(units,MDUnits); } -void Atoms::setTimeStep(void*p){ +void Atoms::setTimeStep(void*p) { MD2double(p,timestep); } -double Atoms::getTimeStep()const{ +double Atoms::getTimeStep()const { return timestep/units.getTime()*MDUnits.getTime(); } -void Atoms::setKbT(void*p){ +void Atoms::setKbT(void*p) { MD2double(p,kbT); } -double Atoms::getKbT()const{ +double Atoms::getKbT()const { return kbT/units.getEnergy()*MDUnits.getEnergy(); } -void Atoms::createFullList(int*n){ +void Atoms::createFullList(int*n) { vector fullListTmp; - for(unsigned i=0;iisActive()) - fullListTmp.insert(fullListTmp.end(),actions[i]->getUnique().begin(),actions[i]->getUnique().end()); + for(unsigned i=0; iisActive()) + fullListTmp.insert(fullListTmp.end(),actions[i]->getUnique().begin(),actions[i]->getUnique().end()); std::sort(fullListTmp.begin(),fullListTmp.end()); int nn=std::unique(fullListTmp.begin(),fullListTmp.end())-fullListTmp.begin(); fullList.resize(nn); - for(int i=0;i&a){ +void Atoms::insertGroup(const std::string&name,const std::vector&a) { plumed_massert(groups.count(name)==0,"group named "+name+" already exists"); groups[name]=a; } -void Atoms::removeGroup(const std::string&name){ +void Atoms::removeGroup(const std::string&name) { plumed_massert(groups.count(name)==1,"cannot remove group named "+name); groups.erase(name); } -void Atoms::writeBinary(std::ostream&o)const{ +void Atoms::writeBinary(std::ostream&o)const { o.write(reinterpret_cast(&positions[0][0]),natoms*3*sizeof(double)); o.write(reinterpret_cast(&box(0,0)),9*sizeof(double)); o.write(reinterpret_cast(&energy),sizeof(double)); } -void Atoms::readBinary(std::istream&i){ +void Atoms::readBinary(std::istream&i) { i.read(reinterpret_cast(&positions[0][0]),natoms*3*sizeof(double)); i.read(reinterpret_cast(&box(0,0)),9*sizeof(double)); i.read(reinterpret_cast(&energy),sizeof(double)); pbc.setBox(box); } -double Atoms::getKBoltzmann()const{ +double Atoms::getKBoltzmann()const { if(naturalUnits) return 1.0; else return kBoltzmann/units.getEnergy(); } -double Atoms::getMDKBoltzmann()const{ +double Atoms::getMDKBoltzmann()const { if(naturalUnits) return 1.0; else return kBoltzmann/MDUnits.getEnergy(); } -void Atoms::getLocalMasses(std::vector& localMasses){ - localMasses.resize(gatindex.size()); - for(unsigned i=0; i& localMasses) { + localMasses.resize(gatindex.size()); + for(unsigned i=0; i& localPositions){ +void Atoms::getLocalPositions(std::vector& localPositions) { localPositions.resize(gatindex.size()); mdatoms->getLocalPositions(localPositions); } -void Atoms::getLocalForces(std::vector& localForces){ +void Atoms::getLocalForces(std::vector& localForces) { localForces.resize(gatindex.size()); for(unsigned i=0; i& localForces){ +void Atoms::getLocalMDForces(std::vector& localForces) { localForces.resize(gatindex.size()); for(unsigned i=0; igetMDforces(i); diff --git a/src/core/Atoms.h b/src/core/Atoms.h index 4e7ed103d5..e9cccf399f 100644 --- a/src/core/Atoms.h +++ b/src/core/Atoms.h @@ -32,7 +32,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class MDAtomsBase; class PlumedMain; @@ -77,7 +77,7 @@ class Atoms void resizeVectors(unsigned); std::vector fullList; - + MDAtomsBase* mdatoms; PlumedMain & plumed; @@ -114,15 +114,15 @@ class Atoms std::vector mpi_request_positions; std::vector mpi_request_index; - + std::vector positionsToBeSent; std::vector positionsToBeReceived; std::vector indexToBeSent; std::vector indexToBeReceived; - operator bool() const{return on;} + operator bool() const {return on;} DomainDecomposition(): on(false), async(false) - {} + {} void enable(Communicator& c); }; @@ -164,7 +164,7 @@ class Atoms void getLocalMDForces(std::vector&); const Tensor& getVirial()const; - void setCollectEnergy(bool b){ collectEnergy=b; } + void setCollectEnergy(bool b) { collectEnergy=b; } void setDomainDecomposition(Communicator&); void setAtomsGatindex(int*,bool); @@ -194,18 +194,18 @@ class Atoms void add(const ActionAtomistic*); void remove(const ActionAtomistic*); - double getEnergy()const{plumed_assert(collectEnergy && energyHasBeenSet); return energy;} + double getEnergy()const {plumed_assert(collectEnergy && energyHasBeenSet); return energy;} - bool isEnergyNeeded()const{return collectEnergy;} + bool isEnergyNeeded()const {return collectEnergy;} - void setMDEnergyUnits(double d){MDUnits.setEnergy(d);} - void setMDLengthUnits(double d){MDUnits.setLength(d);} - void setMDTimeUnits(double d){MDUnits.setTime(d);} - void setMDChargeUnits(double d){MDUnits.setCharge(d);} - void setMDMassUnits(double d){MDUnits.setMass(d);} - const Units& getMDUnits(){return MDUnits;} - void setUnits(const Units&u){units=u;} - const Units& getUnits(){return units;} + void setMDEnergyUnits(double d) {MDUnits.setEnergy(d);} + void setMDLengthUnits(double d) {MDUnits.setLength(d);} + void setMDTimeUnits(double d) {MDUnits.setTime(d);} + void setMDChargeUnits(double d) {MDUnits.setCharge(d);} + void setMDMassUnits(double d) {MDUnits.setMass(d);} + const Units& getMDUnits() {return MDUnits;} + void setUnits(const Units&u) {units=u;} + const Units& getUnits() {return units;} void updateUnits(); AtomNumber addVirtualAtom(ActionWithVirtualAtom*); @@ -219,37 +219,37 @@ class Atoms double getKBoltzmann()const; double getMDKBoltzmann()const; bool usingNaturalUnits()const; - void setNaturalUnits(bool n){naturalUnits=n;} - void setMDNaturalUnits(bool n){MDnaturalUnits=n;} + void setNaturalUnits(bool n) {naturalUnits=n;} + void setMDNaturalUnits(bool n) {MDnaturalUnits=n;} }; inline -const int & Atoms::getNatoms()const{ +const int & Atoms::getNatoms()const { return natoms; } inline -const long int& Atoms::getDdStep()const{ +const long int& Atoms::getDdStep()const { return ddStep; } inline -const std::vector& Atoms::getGatindex()const{ +const std::vector& Atoms::getGatindex()const { return gatindex; } inline -const Pbc& Atoms::getPbc()const{ +const Pbc& Atoms::getPbc()const { return pbc; } inline -bool Atoms::isVirtualAtom(AtomNumber i)const{ +bool Atoms::isVirtualAtom(AtomNumber i)const { return i.index()>=(unsigned) getNatoms(); } inline -ActionWithVirtualAtom* Atoms::getVirtualAtomsAction(AtomNumber i)const{ +ActionWithVirtualAtom* Atoms::getVirtualAtomsAction(AtomNumber i)const { return virtualAtomsActions[i.index()-getNatoms()]; } @@ -269,7 +269,7 @@ bool Atoms::boxWasSet() const { } inline -const Tensor& Atoms::getVirial()const{ +const Tensor& Atoms::getVirial()const { return virial; } diff --git a/src/core/CLTool.cpp b/src/core/CLTool.cpp index 527e5b6cbe..c7441d41ed 100644 --- a/src/core/CLTool.cpp +++ b/src/core/CLTool.cpp @@ -21,148 +21,148 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "CLTool.h" -namespace PLMD{ +namespace PLMD { Keywords CLToolOptions::emptyKeys; -CLToolOptions::CLToolOptions(const std::string &name): -line(1,name), -keys(emptyKeys) +CLToolOptions::CLToolOptions(const std::string &name): + line(1,name), + keys(emptyKeys) { } CLToolOptions::CLToolOptions(const CLToolOptions& co, const Keywords& k): -line(co.line), -keys(k) + line(co.line), + keys(k) { } -void CLTool::registerKeywords( Keywords& keys ){ +void CLTool::registerKeywords( Keywords& keys ) { keys.addFlag("--help/-h",false,"print this help"); } -CLTool::CLTool(const CLToolOptions& co ): -name(co.line[0]), -keywords(co.keys), -inputdata(unset) +CLTool::CLTool(const CLToolOptions& co ): + name(co.line[0]), + keywords(co.keys), + inputdata(unset) { } -void CLTool::parseFlag( const std::string&key, bool&t ){ +void CLTool::parseFlag( const std::string&key, bool&t ) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); plumed_massert(keywords.style(key,"flag"),"keyword " + key + " has not been registered as a flag"); - plumed_assert(inputData.count(key)>0); + plumed_assert(inputData.count(key)>0); if( inputData[key]=="true") t=true; else if( inputData[key]=="false") t=false; else plumed_error(); } -bool CLTool::readInput( int argc, char**argv, FILE* in, FILE*out ){ +bool CLTool::readInput( int argc, char**argv, FILE* in, FILE*out ) { plumed_massert( inputdata!=unset,"You have not specified where your tool reads its input. " - "If it is from the command line (like driver) add inputdata=commandline to the " - "tools constructor. If it reads everything from an input file (like simplemd) " - "add inputdata=ifile to the tools constructor"); + "If it is from the command line (like driver) add inputdata=commandline to the " + "tools constructor. If it reads everything from an input file (like simplemd) " + "add inputdata=ifile to the tools constructor"); if(inputdata==commandline) return readCommandLineArgs( argc, argv, out ); if(inputdata==ifile) return readInputFile( argc, argv, in, out ); return true; } -bool CLTool::readCommandLineArgs( int argc, char**argv, FILE*out ){ +bool CLTool::readCommandLineArgs( int argc, char**argv, FILE*out ) { plumed_assert(inputdata==commandline); std::string prefix(""), a(""), thiskey; // Set all flags to default false - for(unsigned k=0;k(thiskey,"false")); + for(unsigned k=0; k(thiskey,"false")); } // Read command line arguments bool printhelp=false; - for(int i=1;i(thiskey,"")); - } else if(Tools::startWith(a,thiskey+"=")){ - a.erase(0,a.find("=")+1); prefix=""; found=true; - if(inputData.count(thiskey)==0){ - inputData.insert(std::pair(thiskey,a)); - } else { - inputData[thiskey]=a; - } - } - } - } - if(!found){ - fprintf(stderr,"ERROR in input for command line tool %s : %s option is unknown \n\n", name.c_str(), a.c_str() ); - fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); - fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); - keywords.print( out ); - printhelp=true; - } + for(int i=1; i(thiskey,"")); + } else if(Tools::startWith(a,thiskey+"=")) { + a.erase(0,a.find("=")+1); prefix=""; found=true; + if(inputData.count(thiskey)==0) { + inputData.insert(std::pair(thiskey,a)); + } else { + inputData[thiskey]=a; + } + } + } + } + if(!found) { + fprintf(stderr,"ERROR in input for command line tool %s : %s option is unknown \n\n", name.c_str(), a.c_str() ); + fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); + fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); + keywords.print( out ); + printhelp=true; } - if(printhelp) break; + } + if(printhelp) break; } if(!printhelp) setRemainingToDefault(out); - if(printhelp){ - fprintf(out,"Usage: %s [options] \n\n", name.c_str() ); - keywords.print( out ); + if(printhelp) { + fprintf(out,"Usage: %s [options] \n\n", name.c_str() ); + keywords.print( out ); } return !printhelp; } -void CLTool::setRemainingToDefault(FILE* out){ +void CLTool::setRemainingToDefault(FILE* out) { std::string def, thiskey; - for(unsigned k=0;k0 ); - inputData.insert(std::pair(thiskey,def)); - } else { - fprintf(out,"ERROR : argument %s is compulsory. Use --help option for help\n",thiskey.c_str() ); - plumed_error(); - } - } + for(unsigned k=0; k0 ); + inputData.insert(std::pair(thiskey,def)); + } else { + fprintf(out,"ERROR : argument %s is compulsory. Use --help option for help\n",thiskey.c_str() ); + plumed_error(); + } } + } } } -bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ){ +bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ) { plumed_assert(inputdata==ifile); // Check if use is just asking for help std::string a; - for(int i=1;i(thiskey,line.substr(keypos))); - Tools::stripLeadingAndTrailingBlanks( inputData[thiskey] ); - } - } - if(!found){ - fprintf(stderr,"ERROR in input for command line tool %s : unknown keyword %s found in input file\n\n",name.c_str(),keyword.c_str()); - fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); - fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); - keywords.print( out ); - fclose(mystdin); - return false; - } + while(fgets(buffer,256,mystdin)) { + line=buffer; + for(unsigned i=0; i(thiskey,line.substr(keypos))); + Tools::stripLeadingAndTrailingBlanks( inputData[thiskey] ); + } + } + if(!found) { + fprintf(stderr,"ERROR in input for command line tool %s : unknown keyword %s found in input file\n\n",name.c_str(),keyword.c_str()); + fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); + fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); + keywords.print( out ); + fclose(mystdin); + return false; + } } if(argc==2) fclose(mystdin); @@ -205,9 +205,9 @@ bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ){ return true; } -void CLTool::error( const std::string& msg ){ +void CLTool::error( const std::string& msg ) { fprintf(stderr,"ERROR : in input for command line tool %s : %s\n",name.c_str(),msg.c_str()); - plumed_error(); + plumed_error(); } } diff --git a/src/core/CLTool.h b/src/core/CLTool.h index 9385c93d82..c9ab30778e 100644 --- a/src/core/CLTool.h +++ b/src/core/CLTool.h @@ -28,11 +28,11 @@ #include "tools/Tools.h" #include "tools/Keywords.h" -namespace PLMD{ +namespace PLMD { class Communicator; -class CLToolOptions{ +class CLToolOptions { friend class CLTool; friend class CLToolRegister; private: @@ -67,92 +67,92 @@ class CLTool { void setRemainingToDefault(FILE* out); public: /// Set the input data: - void setInputData(const std::map&inputData){ + void setInputData(const std::map&inputData) { this->inputData=inputData; } - const std::map&getInputData(){ + const std::map&getInputData() { return this->inputData; } protected: -/// Get the value of one of the command line arguments +/// Get the value of one of the command line arguments template bool parse(const std::string&key,T&t); /// Find out whether one of the command line flags is present or not - void parseFlag(const std::string&key,bool&t); + void parseFlag(const std::string&key,bool&t); /// Crash the command line tool with an error void error(const std::string& msg); template - bool parseVector(const std::string&key,std::vector&t); + bool parseVector(const std::string&key,std::vector&t); public: /// How is the input specified on the command line or in an input file enum {unset,commandline,ifile} inputdata; -/// Create the help keywords +/// Create the help keywords static void registerKeywords( Keywords& keys ); - explicit CLTool(const CLToolOptions& co ); + explicit CLTool(const CLToolOptions& co ); /// Read the arguments from the command line bool readInput( int argc, char**argv, FILE* in, FILE*out ); /// virtual function mapping to the specific main for each tool virtual int main( FILE* in, FILE*out, Communicator&pc )=0; /// virtual function returning a one-line descriptor for the tool - virtual std::string description()const{return "(no description available)";} + virtual std::string description()const {return "(no description available)";} /// virtual destructor to allow inheritance - virtual ~CLTool(){} + virtual ~CLTool() {} }; template -bool CLTool::parse(const std::string&key,T&t){ +bool CLTool::parse(const std::string&key,T&t) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); - if(keywords.style(key,"compulsory") ){ - if(inputData.count(key)==0) error("missing data for keyword " + key); - bool check=Tools::convert(inputData[key],t); - if(!check) error("data input for keyword " + key + " has wrong type"); - return true; + if(keywords.style(key,"compulsory") ) { + if(inputData.count(key)==0) error("missing data for keyword " + key); + bool check=Tools::convert(inputData[key],t); + if(!check) error("data input for keyword " + key + " has wrong type"); + return true; } - if( inputData.count(key)==0 ) return false; + if( inputData.count(key)==0 ) return false; Tools::convert(inputData[key],t); return true; } -// very limited support and check: take more from core/Action.h parseVector +// very limited support and check: take more from core/Action.h parseVector template -bool CLTool::parseVector(const std::string&key,std::vector&t){ +bool CLTool::parseVector(const std::string&key,std::vector&t) { // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); // initial size - unsigned size=t.size(); + unsigned size=t.size(); bool skipcheck=false; - if(size==0) skipcheck=true; // if the vector in input has size zero, skip the check if size of input vector is the same of argument read + if(size==0) skipcheck=true; // if the vector in input has size zero, skip the check if size of input vector is the same of argument read // check if there is some value plumed_massert(inputData[key]!="false","compulsory keyword "+std::string(key)+"has no data"); std::vector words=Tools::getWords(inputData[key],"\t\n ,"); - t.resize(0); + t.resize(0); if(words.size()==0)return false; - for(unsigned i=0;i using namespace std; -namespace PLMD{ +namespace PLMD { CLToolMain::CLToolMain(): -argc(0), -in(stdin), -out(stdout), -comm(*new Communicator) + argc(0), + in(stdin), + out(stdout), + comm(*new Communicator) { } -CLToolMain::~CLToolMain(){ +CLToolMain::~CLToolMain() { delete &comm; } #define CHECK_NULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"CLTool " + word + "\")"); -void CLToolMain::cmd(const std::string& word,void*val){ - if(false){ - } else if(word=="setArgc"){ - CHECK_NULL(val,word); - argc=*static_cast(val); - } else if(word=="setArgv"){ - CHECK_NULL(val,word); - char**v=static_cast(val); - for(int i=0;i(val); - argv=Tools::getWords(v); - } else if(word=="setIn"){ - CHECK_NULL(val,word); - in=static_cast(val); - } else if(word=="setOut"){ - CHECK_NULL(val,word); - out=static_cast(val); - } else if(word=="setMPIComm"){ - comm.Set_comm(val); - } else if(word=="setMPIFComm"){ - comm.Set_fcomm(val); - } else if(word=="run"){ - CHECK_NULL(val,word); - argc=argv.size(); - int n=0; for(int i=0;i args(n); - std::vector v(argc); - char* ptr=&args[0]; - for(int i=0;i(val)=ret; +void CLToolMain::cmd(const std::string& word,void*val) { + if(false) { + } else if(word=="setArgc") { + CHECK_NULL(val,word); + argc=*static_cast(val); + } else if(word=="setArgv") { + CHECK_NULL(val,word); + char**v=static_cast(val); + for(int i=0; i(val); + argv=Tools::getWords(v); + } else if(word=="setIn") { + CHECK_NULL(val,word); + in=static_cast(val); + } else if(word=="setOut") { + CHECK_NULL(val,word); + out=static_cast(val); + } else if(word=="setMPIComm") { + comm.Set_comm(val); + } else if(word=="setMPIFComm") { + comm.Set_fcomm(val); + } else if(word=="run") { + CHECK_NULL(val,word); + argc=argv.size(); + int n=0; for(int i=0; i args(n); + std::vector v(argc); + char* ptr=&args[0]; + for(int i=0; i(val)=ret; } else { plumed_merror("cannot interpret cmd(\"CLTool " + word + "\"). check plumed developers manual to see the available commands."); } @@ -99,7 +99,7 @@ This is the entry point to the command line tools included in the plumed library. */ -int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ +int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc) { int i; bool printhelp=false; @@ -112,55 +112,55 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ // Start parsing options string prefix(""); string a(""); - for(i=1;i1){ + if(i>1) { fprintf(stderr,"--no-mpi option can only be used as the first option"); return 1; } - } else if(a=="--mpi"){ + } else if(a=="--mpi") { // this is ignored, as it is parsed in main - if(i>1){ + if(i>1) { fprintf(stderr,"--mpi option can only be used as the first option"); return 1; } - } else if(a=="--standalone-executable"){ + } else if(a=="--standalone-executable") { standalone_executable=true; - } else if(Tools::startWith(a,"--load=")){ + } else if(Tools::startWith(a,"--load=")) { a.erase(0,a.find("=")+1); prefix=""; void *p=dlloader.load(a); - if(!p){ + if(!p) { fprintf(stderr,"ERROR: cannot load library %s\n",a.c_str()); fprintf(stderr,"ERROR: %s\n",dlloader.error().c_str()); return 1; } - } else if(a=="--load"){ + } else if(a=="--load") { prefix="--load="; } else if(a[0]=='-') { string msg="ERROR: Unknown option " +a; @@ -170,11 +170,11 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ } // Check if plumedRoot/patches/ directory exists (as a further check) - if(!standalone_executable){ + if(!standalone_executable) { vector files=Tools::ls(root); if(find(files.begin(),files.end(),"patches")==files.end()) { string msg= - "WARNING: I cannot find "+root+"/patches/ directory. Set PLUMED_ROOT or reinstall PLUMED\n\n"; + "WARNING: I cannot find "+root+"/patches/ directory. Set PLUMED_ROOT or reinstall PLUMED\n\n"; fprintf(stderr,"%s",msg.c_str()); } } @@ -186,36 +186,36 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){ if(!standalone_executable) { vector tmp; tmp=Tools::ls(string(root+"/scripts")); - for(unsigned j=0;j0) availableShell.push_back(tmp[j]); + for(unsigned j=0; j0) availableShell.push_back(tmp[j]); } - if(printhelp){ + if(printhelp) { string msg= - "Usage: plumed [options] [command] [command options]\n" - " plumed [command] -h|--help: to print help for a specific command\n" - "Options:\n" - " [help|-h|--help] : to print this help\n" - " [--is-installed] : fails if plumed is not installed\n" - " [--has-mpi] : fails if plumed is running without MPI\n" - " [--has-matheval] : fails if plumed is compiled without matheval\n" - " [--has-dlopen] : fails if plumed is compiled without dlopen\n" - " [--load LIB] : loads a shared object (typically a plugin library)\n" - " [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n" - "Commands:\n"; + "Usage: plumed [options] [command] [command options]\n" + " plumed [command] -h|--help: to print help for a specific command\n" + "Options:\n" + " [help|-h|--help] : to print this help\n" + " [--is-installed] : fails if plumed is not installed\n" + " [--has-mpi] : fails if plumed is running without MPI\n" + " [--has-matheval] : fails if plumed is compiled without matheval\n" + " [--has-dlopen] : fails if plumed is compiled without dlopen\n" + " [--load LIB] : loads a shared object (typically a plugin library)\n" + " [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n" + "Commands:\n"; fprintf(out,"%s",msg.c_str()); - for(unsigned j=0;jdescription(); delete cl; fprintf(out," plumed %s\n", manual.c_str()); } - for(unsigned j=0;jreadInput( argc-i,&argv[i],in,out ) ){ delete cl; return 0; } + if( !cl->readInput( argc-i,&argv[i],in,out ) ) { delete cl; return 0; } int ret=cl->main(in,out,pc); delete cl; return ret; } - if(find(availableShell.begin(),availableShell.end(),command)!=availableShell.end()){ + if(find(availableShell.begin(),availableShell.end(),command)!=availableShell.end()) { plumed_massert(in==stdin,"shell tools can only work on stdin"); plumed_massert(out==stdout,"shell tools can only work on stdin"); string cmd=config::getEnvCommand()+" \""+root+"/scripts/"+command+".sh\""; - for(int j=i+1;j0){ +CLToolRegister::~CLToolRegister() { + if(m.size()>0) { string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: CLTools "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -CLToolRegister& cltoolRegister(){ +CLToolRegister& cltoolRegister() { static CLToolRegister ans; return ans; } -void CLToolRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void CLToolRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void CLToolRegister::add(string key,creator_pointer f,keywords_pointer kf){ - if(m.count(key)){ +void CLToolRegister::add(string key,creator_pointer f,keywords_pointer kf) { + if(m.count(key)) { m.erase(key); disabled.insert(key); - }else{ + } else { m.insert(pair(key,f)); Keywords keys; kf(keys); mk.insert(pair(key,keys)); }; } -bool CLToolRegister::check(string key){ +bool CLToolRegister::check(string key) { if(m.count(key)>0) return true; return false; } -CLTool* CLToolRegister::create(const CLToolOptions&ao){ +CLTool* CLToolRegister::create(const CLToolOptions&ao) { if(ao.line.size()<1)return NULL; CLTool* cltool; - if(check(ao.line[0])){ - CLToolOptions nao( ao,mk[ao.line[0]] ); - cltool=m[ao.line[0]](nao); + if(check(ao.line[0])) { + CLToolOptions nao( ao,mk[ao.line[0]] ); + cltool=m[ao.line[0]](nao); } else cltool=NULL; return cltool; } -std::ostream & operator<<(std::ostream &log,const CLToolRegister&ar){ +std::ostream & operator<<(std::ostream &log,const CLToolRegister&ar) { vector s(ar.list()); - for(unsigned i=0;i CLToolRegister::list()const{ +vector CLToolRegister::list()const { vector s; for(const auto & it : m) s.push_back(it.first); sort(s.begin(),s.end()); diff --git a/src/core/CLToolRegister.h b/src/core/CLToolRegister.h index 1d91bfe145..f7b14a561f 100644 --- a/src/core/CLToolRegister.h +++ b/src/core/CLToolRegister.h @@ -29,13 +29,13 @@ #include #include "tools/Keywords.h" -namespace PLMD{ +namespace PLMD { class CLTool; class CLToolOptions; /// Same as ActionRegister, but for CLTools -class CLToolRegister{ +class CLToolRegister { /// Write on a stream the list of registered directives friend std::ostream &operator<<(std::ostream &,const CLToolRegister&); /// Pointer to a function which, given the options, create an CLTool @@ -64,7 +64,7 @@ class CLToolRegister{ /// Returns a list of the allowed CLTools std::vector list()const; /// Print out the instructions for using the tool in html ready for input into the manual - bool printManual(const std::string& cltool); + bool printManual(const std::string& cltool); }; /// Function returning a reference to the CLToolRegister. diff --git a/src/core/Colvar.cpp b/src/core/Colvar.cpp index bdd6b048ea..239afdc8d3 100644 --- a/src/core/Colvar.cpp +++ b/src/core/Colvar.cpp @@ -25,32 +25,32 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { Colvar::Colvar(const ActionOptions&ao): -Action(ao), -ActionAtomistic(ao), -ActionWithValue(ao), -isEnergy(false) + Action(ao), + ActionAtomistic(ao), + ActionWithValue(ao), + isEnergy(false) { } -void Colvar::registerKeywords( Keywords& keys ){ +void Colvar::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); keys.addFlag("NOPBC",false,"ignore the periodic boundary conditions when calculating distances"); -} +} -void Colvar::requestAtoms(const vector & a){ +void Colvar::requestAtoms(const vector & a) { plumed_massert(!isEnergy,"request atoms should not be called if this is energy"); // Tell actionAtomistic what atoms we are getting ActionAtomistic::requestAtoms(a); // Resize the derivatives of all atoms - for(int i=0;iresizeDerivatives(3*a.size()+9); + for(int i=0; iresizeDerivatives(3*a.size()+9); } -void Colvar::apply(){ +void Colvar::apply() { vector& f(modifyForces()); Tensor& v(modifyVirial()); const unsigned nat=getNumberOfAtoms(); @@ -67,16 +67,16 @@ void Colvar::apply(){ unsigned nt=OpenMP::getNumThreads(); if(nt>ncp/(2.*stride)) nt=1; - if(!isEnergy){ - #pragma omp parallel num_threads(nt) + if(!isEnergy) { + #pragma omp parallel num_threads(nt) { vector omp_f(fsz); Tensor omp_v; vector forces(3*nat+9); - #pragma omp for - for(unsigned i=rank;iapplyForce(forces)){ - for(unsigned j=0;japplyForce(forces)) { + for(unsigned j=0; j forces(1); if(getPntrToComponent(0)->applyForce(forces)) modifyForceOnEnergy()+=forces[0]; } } -void Colvar::setBoxDerivativesNoPbc(Value* v){ +void Colvar::setBoxDerivativesNoPbc(Value* v) { Tensor virial; unsigned nat=getNumberOfAtoms(); - for(unsigned i=0;igetDerivative(3*i+0), - v->getDerivative(3*i+1), - v->getDerivative(3*i+2))); + for(unsigned i=0; igetDerivative(3*i+0), + v->getDerivative(3*i+1), + v->getDerivative(3*i+2))); setBoxDerivatives(v,virial); } } diff --git a/src/core/Colvar.h b/src/core/Colvar.h index 08e962aa5f..4a7ef6a08b 100644 --- a/src/core/Colvar.h +++ b/src/core/Colvar.h @@ -32,14 +32,14 @@ namespace PLMD { /** \ingroup INHERIT -This is the abstract base class to use for implementing new collective variables, within it there is -\ref AddingAColvar "information" as to how to go about implementing a new CV. +This is the abstract base class to use for implementing new collective variables, within it there is +\ref AddingAColvar "information" as to how to go about implementing a new CV. */ class Colvar : public ActionAtomistic, public ActionWithValue - { +{ private: protected: bool isEnergy; @@ -47,7 +47,7 @@ class Colvar : // Set the derivatives for a particular atom equal to the input Vector // This routine is called setAtomsDerivatives because not because you // are setting the derivative of many atoms but because you are setting -// the derivatives of a particular atom. The s is an apostrophe s +// the derivatives of a particular atom. The s is an apostrophe s // but you can't put apostrophes in function names void setAtomsDerivatives(int,const Vector&); void setAtomsDerivatives(Value*,int,const Vector&); @@ -63,15 +63,15 @@ class Colvar : void setBoxDerivativesNoPbc(); void setBoxDerivativesNoPbc(Value*); public: - bool checkIsEnergy(){return isEnergy;} + bool checkIsEnergy() {return isEnergy;} explicit Colvar(const ActionOptions&); - ~Colvar(){} + ~Colvar() {} static void registerKeywords( Keywords& keys ); virtual unsigned getNumberOfDerivatives(); }; inline -void Colvar::setAtomsDerivatives(Value*v,int i,const Vector&d){ +void Colvar::setAtomsDerivatives(Value*v,int i,const Vector&d) { v->addDerivative(3*i+0,d[0]); v->addDerivative(3*i+1,d[1]); v->addDerivative(3*i+2,d[2]); @@ -79,7 +79,7 @@ void Colvar::setAtomsDerivatives(Value*v,int i,const Vector&d){ inline -void Colvar::setBoxDerivatives(Value* v,const Tensor&d){ +void Colvar::setBoxDerivatives(Value* v,const Tensor&d) { unsigned nat=getNumberOfAtoms(); v->addDerivative(3*nat+0,d(0,0)); v->addDerivative(3*nat+1,d(0,1)); @@ -93,22 +93,22 @@ void Colvar::setBoxDerivatives(Value* v,const Tensor&d){ } inline -void Colvar::setAtomsDerivatives(int i,const Vector&d){ +void Colvar::setAtomsDerivatives(int i,const Vector&d) { setAtomsDerivatives(getPntrToValue(),i,d); } inline -void Colvar::setBoxDerivatives(const Tensor&d){ +void Colvar::setBoxDerivatives(const Tensor&d) { setBoxDerivatives(getPntrToValue(),d); } inline -void Colvar::setBoxDerivativesNoPbc(){ +void Colvar::setBoxDerivativesNoPbc() { setBoxDerivativesNoPbc(getPntrToValue()); } inline -unsigned Colvar::getNumberOfDerivatives(){ +unsigned Colvar::getNumberOfDerivatives() { return 3*getNumberOfAtoms() + 9; } diff --git a/src/core/ExchangePatterns.cpp b/src/core/ExchangePatterns.cpp index a3b4d338c3..fdd22e74ec 100644 --- a/src/core/ExchangePatterns.cpp +++ b/src/core/ExchangePatterns.cpp @@ -24,7 +24,7 @@ using namespace std; -namespace PLMD{ +namespace PLMD { ExchangePatterns::ExchangePatterns(): PatternFlag(NONE), @@ -37,15 +37,15 @@ ExchangePatterns::~ExchangePatterns() delete &random; } -void ExchangePatterns::setNofR(const int nrepl){ +void ExchangePatterns::setNofR(const int nrepl) { NumberOfReplicas=nrepl; } -void ExchangePatterns::setFlag(const int flag){ +void ExchangePatterns::setFlag(const int flag) { PatternFlag=flag; } -void ExchangePatterns::getFlag(int &flag){ +void ExchangePatterns::getFlag(int &flag) { flag=PatternFlag; } @@ -58,19 +58,19 @@ void ExchangePatterns::getList(int *ind) { switch(PatternFlag) { - case RANDOM: - for(int i=0;i &smin, vector &smax):type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax){ - // initialize the averages and the variance matrices - if(type==diffusion){ - unsigned ncv=paction->getNumberOfArguments(); - vector average(ncv*(ncv+1)/2); - vector variance(ncv*(ncv+1)/2); - } - paction->log<<" Limits for sigmas using adaptive hills: \n"; - for(unsigned i=0;igetNumberOfArguments();++i){ - paction->log<<" CV "<getPntrToArgument(i)->getName()<<":\n"; - if(sigmamin[i]>0.){ - limitmin.push_back(true); - paction->log<<" Min "<log<<" Min No "; - } - if(sigmamax[i]>0.){ - limitmax.push_back(true); - paction->log<<" Max "<log<<" Max No "; - } - paction->log<<" \n"; - } +FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, double const &d, vector &smin, vector &smax):type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax) { + // initialize the averages and the variance matrices + if(type==diffusion) { + unsigned ncv=paction->getNumberOfArguments(); + vector average(ncv*(ncv+1)/2); + vector variance(ncv*(ncv+1)/2); + } + paction->log<<" Limits for sigmas using adaptive hills: \n"; + for(unsigned i=0; igetNumberOfArguments(); ++i) { + paction->log<<" CV "<getPntrToArgument(i)->getName()<<":\n"; + if(sigmamin[i]>0.) { + limitmin.push_back(true); + paction->log<<" Min "<log<<" Min No "; + } + if(sigmamax[i]>0.) { + limitmax.push_back(true); + paction->log<<" Max "<log<<" Max No "; + } + paction->log<<" \n"; + } } /// Constructure for 1D FB for PBMETAD -FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, +FlexibleBin::FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, double const &d, vector &smin, vector &smax): - type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax) + type(type),paction(paction),sigma(d),sigmamin(smin),sigmamax(smax) { - // initialize the averages and the variance matrices - if(type==diffusion){ - vector average(1); - vector variance(1); - } - paction->log<<" Limits for sigmas using adaptive hills: \n"; - paction->log<<" CV "<getPntrToArgument(iarg)->getName()<<":\n"; - if(sigmamin[0]>0.){ - limitmin.push_back(true); - paction->log<<" Min "<log<<" Min No "; - } - if(sigmamax[0]>0.){ - limitmax.push_back(true); - paction->log<<" Max "<log<<" Max No "; - } - paction->log<<" \n"; + // initialize the averages and the variance matrices + if(type==diffusion) { + vector average(1); + vector variance(1); + } + paction->log<<" Limits for sigmas using adaptive hills: \n"; + paction->log<<" CV "<getPntrToArgument(iarg)->getName()<<":\n"; + if(sigmamin[0]>0.) { + limitmin.push_back(true); + paction->log<<" Min "<log<<" Min No "; + } + if(sigmamax[0]>0.) { + limitmax.push_back(true); + paction->log<<" Max "<log<<" Max No "; + } + paction->log<<" \n"; } -/// Update the flexible bin +/// Update the flexible bin /// in case of diffusion based: update at every step -/// in case of gradient based: update only when you add the hill -void FlexibleBin::update(bool nowAddAHill){ - unsigned ncv=paction->getNumberOfArguments(); - unsigned dimension=ncv*(ncv+1)/2; - // this is done all the times from scratch. It is not an accumulator - unsigned k=0; - unsigned i; - vector cv; - vector delta; - // if you use this below then the decay is in time units - //double decay=paction->getTimeStep()/sigma; - // to be consistent with the rest of the program: everything is better to be in timesteps - double decay=1./sigma; - // here update the flexible bin according to the needs - switch (type){ - // This should be called every time - case diffusion: - // - // THE AVERAGE VALUE - // - // beware: the pbc - delta.resize(ncv); - for(i=0;igetArgument(i)); - if(average.size()==0){ // initial time: just set the initial vector - average.resize(ncv); - for(i=0;idifference(i,average[i],cv[i]); - average[i]+=decay*delta[i]; - average[i]=paction->bringBackInPbc(i,average[i]); // equation 8 of "Metadynamics with adaptive Gaussians" - } +/// in case of gradient based: update only when you add the hill +void FlexibleBin::update(bool nowAddAHill) { + unsigned ncv=paction->getNumberOfArguments(); + unsigned dimension=ncv*(ncv+1)/2; + // this is done all the times from scratch. It is not an accumulator + unsigned k=0; + unsigned i; + vector cv; + vector delta; + // if you use this below then the decay is in time units + //double decay=paction->getTimeStep()/sigma; + // to be consistent with the rest of the program: everything is better to be in timesteps + double decay=1./sigma; + // here update the flexible bin according to the needs + switch (type) { + // This should be called every time + case diffusion: + // + // THE AVERAGE VALUE + // + // beware: the pbc + delta.resize(ncv); + for(i=0; igetArgument(i)); + if(average.size()==0) { // initial time: just set the initial vector + average.resize(ncv); + for(i=0; idifference(i,average[i],cv[i]); + average[i]+=decay*delta[i]; + average[i]=paction->bringBackInPbc(i,average[i]); // equation 8 of "Metadynamics with adaptive Gaussians" + } - } - // - // THE VARIANCE - // - if(variance.size()==0){ - variance.resize(dimension,0.); // nonredundant members dimension=ncv*(ncv+1)/2; - }else{ - k=0; - for(i=0;igetProjection(i,j)); - k++; - } - }; - }; - break; - default: - cerr<< "This flexible bin is not recognized "<getProjection(i,j)); + k++; + } + }; + }; + break; + default: + cerr<< "This flexible bin is not recognized "< FlexibleBin::getMatrix() const{ - return variance; +vector FlexibleBin::getMatrix() const { + return variance; } /// Update the flexible bin for PBMetaD like FlexBin /// in case of diffusion based: update at every step -/// in case of gradient based: update only when you add the hill -void FlexibleBin::update(bool nowAddAHill, unsigned iarg){ - // this is done all the times from scratch. It is not an accumulator - vector cv; - vector delta; - // if you use this below then the decay is in time units - // to be consistent with the rest of the program: everything is better to be in timesteps - double decay=1./sigma; - // here update the flexible bin according to the needs - switch (type){ - // This should be called every time - case diffusion: - // - // THE AVERAGE VALUE - // - delta.resize(1); - cv.push_back(paction->getArgument(iarg)); - if(average.size()==0){ // initial time: just set the initial vector - average.resize(1); - average[0]=cv[0]; - }else{ // accumulate - delta[0]=paction->difference(iarg,average[0],cv[0]); - average[0]+=decay*delta[0]; - average[0]=paction->bringBackInPbc(iarg,average[0]); // equation 8 of "Metadynamics with adaptive Gaussians" - } - // - // THE VARIANCE - // - if(variance.size()==0){ - variance.resize(1,0.); // nonredundant members dimension=ncv*(ncv+1)/2; - }else{ - variance[0]+=decay*(delta[0]*delta[0]-variance[0]); - } - break; - case geometry: - // - //this calculates in variance the \nabla CV_i \dot \nabla CV_j - // - variance.resize(1); - // now the signal for retrieving the gradients should be already given by checkNeedsGradients. - // here just do the projections - // note that the call checkNeedsGradients() in BiasMetaD takes care of switching on the call to gradients - if (nowAddAHill){// geometry is sync with hill deposition - // eq 12 of "Metadynamics with adaptive Gaussians" - variance[0]=sigma*sigma*(paction->getProjection(iarg,iarg)); - } - break; - default: - cerr<< "This flexible bin is not recognized "< cv; + vector delta; + // if you use this below then the decay is in time units + // to be consistent with the rest of the program: everything is better to be in timesteps + double decay=1./sigma; + // here update the flexible bin according to the needs + switch (type) { + // This should be called every time + case diffusion: + // + // THE AVERAGE VALUE + // + delta.resize(1); + cv.push_back(paction->getArgument(iarg)); + if(average.size()==0) { // initial time: just set the initial vector + average.resize(1); + average[0]=cv[0]; + } else { // accumulate + delta[0]=paction->difference(iarg,average[0],cv[0]); + average[0]+=decay*delta[0]; + average[0]=paction->bringBackInPbc(iarg,average[0]); // equation 8 of "Metadynamics with adaptive Gaussians" + } + // + // THE VARIANCE + // + if(variance.size()==0) { + variance.resize(1,0.); // nonredundant members dimension=ncv*(ncv+1)/2; + } else { + variance[0]+=decay*(delta[0]*delta[0]-variance[0]); + } + break; + case geometry: + // + //this calculates in variance the \nabla CV_i \dot \nabla CV_j + // + variance.resize(1); + // now the signal for retrieving the gradients should be already given by checkNeedsGradients. + // here just do the projections + // note that the call checkNeedsGradients() in BiasMetaD takes care of switching on the call to gradients + if (nowAddAHill) { // geometry is sync with hill deposition + // eq 12 of "Metadynamics with adaptive Gaussians" + variance[0]=sigma*sigma*(paction->getProjection(iarg,iarg)); + } + break; + default: + cerr<< "This flexible bin is not recognized "< FlexibleBin::getInverseMatrix() const{ - unsigned ncv=paction->getNumberOfArguments(); - Matrix matrix(ncv,ncv); - unsigned i,j,k; - k=0; - //paction->log<<"------------ GET INVERSE MATRIX ---------------\n"; - // place the matrix in a complete matrix for compatibility - for (i=0;i FlexibleBin::getInverseMatrix() const { + unsigned ncv=paction->getNumberOfArguments(); + Matrix matrix(ncv,ncv); + unsigned i,j,k; + k=0; + //paction->log<<"------------ GET INVERSE MATRIX ---------------\n"; + // place the matrix in a complete matrix for compatibility + for (i=0; i eigenvecs(ncv,ncv); - vector eigenvals(ncv); + // diagonalize to impose boundaries (only if boundaries are set) + Matrix eigenvecs(ncv,ncv); + vector eigenvals(ncv); - //eigenvecs: first is eigenvec number, second is eigenvec component - if(diagMat( matrix , eigenvals , eigenvecs )!=0){plumed_merror("diagonalization in FlexibleBin failed! This matrix is weird\n");}; - - for (i=0;ipow(sigmamax[i],2) ){ - eigenvals[j]=sqrt(pow(sigmamax[i]/(eigenvecs[j][i]),2))*copysign(1.,eigenvals[j]); - } - } - } - } - for (i=0;ifmax){ - fmax=fact;imax=j; - } - } - if(fmax newinvmatrix(ncv,ncv); - for (i=0;ipow(sigmamax[i],2) ) { + eigenvals[j]=sqrt(pow(sigmamax[i]/(eigenvecs[j][i]),2))*copysign(1.,eigenvals[j]); + } + } + } + } + for (i=0; ifmax) { + fmax=fact; imax=j; + } + } + if(fmax uppervec(ncv*(ncv+1)/2); - k=0; - for (i=0;i invmatrix(ncv,ncv); - Invert(matrix,invmatrix); - vector uppervec(ncv*(ncv+1)/2); - // upper diagonal of the inverted matrix (that is symmetric) - k=0; - for (i=0;ilog<<"VV "< newinvmatrix(ncv,ncv); + for (i=0; i uppervec(ncv*(ncv+1)/2); + k=0; + for (i=0; i invmatrix(ncv,ncv); + Invert(matrix,invmatrix); + vector uppervec(ncv*(ncv+1)/2); + // upper diagonal of the inverted matrix (that is symmetric) + k=0; + for (i=0; ilog<<"VV "< FlexibleBin::getInverseMatrix(unsigned iarg) const{ - // diagonalize to impose boundaries (only if boundaries are set) - vector eigenvals(1, variance[0]); - if( limitmax[0] ){ - if(eigenvals[0]>sigmamax[0]){ - eigenvals[0]=sigmamax[0]; - } - } - // find the largest one: if it is smaller than min then rescale - if( limitmin[0] ){ - double fmax=-1.e10; - double fact=eigenvals[0]; - if(fact>fmax){ - fmax=fact; - } - if(fmax uppervec(1,1./eigenvals[0]); +vector FlexibleBin::getInverseMatrix(unsigned iarg) const { + // diagonalize to impose boundaries (only if boundaries are set) + vector eigenvals(1, variance[0]); + if( limitmax[0] ) { + if(eigenvals[0]>sigmamax[0]) { + eigenvals[0]=sigmamax[0]; + } + } + // find the largest one: if it is smaller than min then rescale + if( limitmin[0] ) { + double fmax=-1.e10; + double fact=eigenvals[0]; + if(fact>fmax) { + fmax=fact; + } + if(fmax uppervec(1,1./eigenvals[0]); - return uppervec; + return uppervec; } } diff --git a/src/core/FlexibleBin.h b/src/core/FlexibleBin.h index 4bd942a07e..3bcbd16f08 100644 --- a/src/core/FlexibleBin.h +++ b/src/core/FlexibleBin.h @@ -24,37 +24,37 @@ #include -namespace PLMD{ +namespace PLMD { class ActionWithArguments; -class FlexibleBin{ - private: - int type; - // this contains all the infos about the CVs including periodicity - ActionWithArguments *paction; - double sigma; - // variance is the matrix that really matters - std::vector variance; - // this is only there - std::vector average; - // minimum and maximum values - std::vector sigmamin; - std::vector sigmamax; - std::vector limitmax; - std::vector limitmin; - public: - /// a constructor that takes the pointer of the action that contains it - FlexibleBin(int type,ActionWithArguments *paction, double const &d, std::vector &sigmamin, std::vector &sigmamax ); - /// a constructor for 1D FlexBin (for PBMETAD) - FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, double const &d, std::vector &sigmamin, std::vector &sigmamax); - /// update the average (always for diffusion) or calculate the geom covariance ( only when do_when_zero is zero) - void update(bool nowAddAHill); - void update(bool nowAddAHill, unsigned iarg); - std::vector getMatrix() const; - std::vector getInverseMatrix() const; - std::vector getInverseMatrix(unsigned iarg) const; - enum AdaptiveHillsType { none, diffusion, geometry }; +class FlexibleBin { +private: + int type; + // this contains all the infos about the CVs including periodicity + ActionWithArguments *paction; + double sigma; + // variance is the matrix that really matters + std::vector variance; + // this is only there + std::vector average; + // minimum and maximum values + std::vector sigmamin; + std::vector sigmamax; + std::vector limitmax; + std::vector limitmin; +public: + /// a constructor that takes the pointer of the action that contains it + FlexibleBin(int type,ActionWithArguments *paction, double const &d, std::vector &sigmamin, std::vector &sigmamax ); + /// a constructor for 1D FlexBin (for PBMETAD) + FlexibleBin(int type, ActionWithArguments *paction, unsigned iarg, double const &d, std::vector &sigmamin, std::vector &sigmamax); + /// update the average (always for diffusion) or calculate the geom covariance ( only when do_when_zero is zero) + void update(bool nowAddAHill); + void update(bool nowAddAHill, unsigned iarg); + std::vector getMatrix() const; + std::vector getInverseMatrix() const; + std::vector getInverseMatrix(unsigned iarg) const; + enum AdaptiveHillsType { none, diffusion, geometry }; }; diff --git a/src/core/GREX.cpp b/src/core/GREX.cpp index 9e355ece1d..fb30166a3a 100644 --- a/src/core/GREX.cpp +++ b/src/core/GREX.cpp @@ -30,12 +30,12 @@ #include "GREXEnum.inc" using namespace std; -namespace PLMD{ +namespace PLMD { -const std::unordered_map & GREXWordMap(){ +const std::unordered_map & GREXWordMap() { static std::unordered_map word_map; static bool init=false; - if(!init){ + if(!init) { #include "GREXMap.inc" } init=true; @@ -58,7 +58,7 @@ GREX::GREX(PlumedMain&p): p.setSuffix(".NA"); } -GREX::~GREX(){ +GREX::~GREX() { delete &intercomm; delete &intracomm; } @@ -67,16 +67,16 @@ GREX::~GREX(){ #define CHECK_NOTINIT(ini,word) plumed_massert(!(ini),"cmd(\"" + word +"\") should be only used before GREX initialization") #define CHECK_NOTNULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"GREX " + word + "\")"); -void GREX::cmd(const string&key,void*val){ +void GREX::cmd(const string&key,void*val) { std::vector words=Tools::getWords(key); unsigned nw=words.size(); - if(nw==0){ + if(nw==0) { // do nothing } else { int iword=-1; const auto it=GREXWordMap().find(words[0]); if(it!=GREXWordMap().end()) iword=it->second; - switch(iword){ + switch(iword) { case cmd_initialized: CHECK_NOTNULL(val,key); *static_cast(val)=initialized; @@ -173,7 +173,7 @@ void GREX::cmd(const string&key,void*val){ CHECK_NOTNULL(val,key); plumed_assert(nw==2); plumed_massert(allDeltaBias.size()==static_cast(intercomm.Get_size()), - "to retrieve bias with cmd(\"GREX getDeltaBias\"), first share it with cmd(\"GREX shareAllDeltaBias\")"); + "to retrieve bias with cmd(\"GREX getDeltaBias\"), first share it with cmd(\"GREX shareAllDeltaBias\")"); { unsigned rep; Tools::convert(words[1],rep); @@ -189,7 +189,7 @@ void GREX::cmd(const string&key,void*val){ } } -void GREX::savePositions(){ +void GREX::savePositions() { plumedMain.prepareDependencies(); plumedMain.resetActive(true); atoms.shareAll(); @@ -199,12 +199,12 @@ void GREX::savePositions(){ buffer=o.str(); } -void GREX::calculate(){ +void GREX::calculate() { //fprintf(stderr,"CALCULATE %d %d\n",intercomm.Get_rank(),partner); unsigned nn=buffer.size(); vector rbuf(nn); localDeltaBias=-plumedMain.getBias(); - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { Communicator::Request req=intercomm.Isend(buffer,partner,1066); intercomm.Recv(rbuf,partner,1066); req.wait(); @@ -218,7 +218,7 @@ void GREX::calculate(){ plumedMain.setExchangeStep(false); localDeltaBias+=plumedMain.getBias(); localDeltaBias+=localUSwap-localUNow; - if(intracomm.Get_rank()==0){ + if(intracomm.Get_rank()==0) { Communicator::Request req=intercomm.Isend(localDeltaBias,partner,1067); intercomm.Recv(foreignDeltaBias,partner,1067); req.wait(); diff --git a/src/core/GREX.h b/src/core/GREX.h index 3a2553e4cf..2266d1581f 100644 --- a/src/core/GREX.h +++ b/src/core/GREX.h @@ -26,7 +26,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class PlumedMain; class Atoms; diff --git a/src/core/MDAtoms.cpp b/src/core/MDAtoms.cpp index ba95c8facd..1f11ad9cd4 100644 --- a/src/core/MDAtoms.cpp +++ b/src/core/MDAtoms.cpp @@ -35,7 +35,7 @@ namespace PLMD { /// IT IS STILL UNDOCUMENTED. IT PROBABLY NEEDS A STRONG CLEANUP template class MDAtomsTyped: -public MDAtomsBase + public MDAtomsBase { T scalep,scalef; T scaleb,scalev; @@ -58,13 +58,13 @@ public MDAtomsBase void setp(void*p,int i); void setf(void*f,int i); void setUnits(const Units&,const Units&); - void MD2double(const void*m,double&d)const{ + void MD2double(const void*m,double&d)const { d=double(*(static_cast(m))); } - void double2MD(const double&d,void*m)const{ + void double2MD(const double&d,void*m)const { *(static_cast(m))=T(d); } - Vector getMDforces(const unsigned index)const{ + Vector getMDforces(const unsigned index)const { Vector force(fx[stride*index],fy[stride*index],fz[stride*index]); return force/scalef; } @@ -81,7 +81,7 @@ public MDAtomsBase }; template -void MDAtomsTyped::setUnits(const Units& units,const Units& MDUnits){ +void MDAtomsTyped::setUnits(const Units& units,const Units& MDUnits) { double lscale=units.getLength()/MDUnits.getLength(); double escale=units.getEnergy()/MDUnits.getEnergy(); double cscale=units.getCharge()/MDUnits.getCharge(); @@ -97,15 +97,15 @@ void MDAtomsTyped::setUnits(const Units& units,const Units& MDUnits){ } template -void MDAtomsTyped::getBox(Tensor&box)const{ - if(this->box) for(int i=0;i<3;i++)for(int j=0;j<3;j++) box(i,j)=this->box[3*i+j]*scaleb; +void MDAtomsTyped::getBox(Tensor&box)const { + if(this->box) for(int i=0; i<3; i++)for(int j=0; j<3; j++) box(i,j)=this->box[3*i+j]*scaleb; else box.zero(); } template -void MDAtomsTyped::getPositions(const vector&index,vector&positions)const{ +void MDAtomsTyped::getPositions(const vector&index,vector&positions)const { // cannot be parallelized with omp because access to positions is not ordered - for(unsigned i=0;i::getPositions(const vector&index,vector&positi } template -void MDAtomsTyped::getPositions(unsigned j,unsigned k,vector&positions)const{ +void MDAtomsTyped::getPositions(unsigned j,unsigned k,vector&positions)const { #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(&positions[j],(k-j))) - for(unsigned i=j;i::getPositions(unsigned j,unsigned k,vector&position template -void MDAtomsTyped::getLocalPositions(vector&positions)const{ +void MDAtomsTyped::getLocalPositions(vector&positions)const { #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(positions)) - for(unsigned i=0;i::getLocalPositions(vector&positions)const{ template -void MDAtomsTyped::getMasses(const vector&index,vector&masses)const{ - if(m) for(unsigned i=0;i::getMasses(const vector&index,vector&masses)const { + if(m) for(unsigned i=0; i -void MDAtomsTyped::getCharges(const vector&index,vector&charges)const{ - if(c) for(unsigned i=0;i::getCharges(const vector&index,vector&charges)const { + if(c) for(unsigned i=0; i -void MDAtomsTyped::updateVirial(const Tensor&virial)const{ - if(this->virial) for(int i=0;i<3;i++)for(int j=0;j<3;j++) this->virial[3*i+j]+=T(virial(i,j)*scalev); +void MDAtomsTyped::updateVirial(const Tensor&virial)const { + if(this->virial) for(int i=0; i<3; i++)for(int j=0; j<3; j++) this->virial[3*i+j]+=T(virial(i,j)*scalev); } template -void MDAtomsTyped::updateForces(const vector&index,const vector&forces){ +void MDAtomsTyped::updateForces(const vector&index,const vector&forces) { #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(fx,stride*index.size())) - for(unsigned i=0;i::updateForces(const vector&index,const vector& } template -void MDAtomsTyped::rescaleForces(const vector&index,double factor){ - if(virial) for(unsigned i=0;i<3;i++)for(unsigned j=0;j<3;j++) virial[3*i+j]*=T(factor); +void MDAtomsTyped::rescaleForces(const vector&index,double factor) { + if(virial) for(unsigned i=0; i<3; i++)for(unsigned j=0; j<3; j++) virial[3*i+j]*=T(factor); #pragma omp parallel for num_threads(OpenMP::getGoodNumThreads(fx,stride*index.size())) - for(unsigned i=0;i::rescaleForces(const vector&index,double factor){ } template -unsigned MDAtomsTyped::getRealPrecision()const{ +unsigned MDAtomsTyped::getRealPrecision()const { return sizeof(T); } template -void MDAtomsTyped::setp(void*pp){ +void MDAtomsTyped::setp(void*pp) { T*p=static_cast(pp); plumed_assert(stride==0 || stride==3); px=p; @@ -188,13 +188,13 @@ void MDAtomsTyped::setp(void*pp){ } template -void MDAtomsTyped::setBox(void*pp){ +void MDAtomsTyped::setBox(void*pp) { box=static_cast(pp); } template -void MDAtomsTyped::setf(void*ff){ +void MDAtomsTyped::setf(void*ff) { T*f=static_cast(ff); plumed_assert(stride==0 || stride==3); fx=f; @@ -204,7 +204,7 @@ void MDAtomsTyped::setf(void*ff){ } template -void MDAtomsTyped::setp(void*pp,int i){ +void MDAtomsTyped::setp(void*pp,int i) { T*p=static_cast(pp); plumed_assert(stride==0 || stride==1); if(i==0)px=p; @@ -214,13 +214,13 @@ void MDAtomsTyped::setp(void*pp,int i){ } template -void MDAtomsTyped::setVirial(void*pp){ +void MDAtomsTyped::setVirial(void*pp) { virial=static_cast(pp); } template -void MDAtomsTyped::setf(void*ff,int i){ +void MDAtomsTyped::setf(void*ff,int i) { T*f=static_cast(ff); plumed_assert(stride==0 || stride==1); if(i==0)fx=f; @@ -230,12 +230,12 @@ void MDAtomsTyped::setf(void*ff,int i){ } template -void MDAtomsTyped::setm(void*m){ +void MDAtomsTyped::setm(void*m) { this->m=static_cast(m); } template -void MDAtomsTyped::setc(void*c){ +void MDAtomsTyped::setc(void*c) { this->c=static_cast(c); } @@ -260,10 +260,10 @@ MDAtomsTyped::MDAtomsTyped(): virial(NULL) {} -MDAtomsBase* MDAtomsBase::create(unsigned p){ - if(p==sizeof(double)){ +MDAtomsBase* MDAtomsBase::create(unsigned p) { + if(p==sizeof(double)) { return new MDAtomsTyped; - } else if (p==sizeof(float)){ + } else if (p==sizeof(float)) { return new MDAtomsTyped; } std::string pp; diff --git a/src/core/MDAtoms.h b/src/core/MDAtoms.h index 04932a21f7..3926d47f13 100644 --- a/src/core/MDAtoms.h +++ b/src/core/MDAtoms.h @@ -51,7 +51,7 @@ class MDAtomsBase /// Creates an MDAtomsTyped object such that sizeof(T)==n static MDAtomsBase* create(unsigned n); /// Virtual destructor, just to allow inheritance. - virtual ~MDAtomsBase(){} + virtual ~MDAtomsBase() {} /// Get the size of MD-real virtual unsigned getRealPrecision()const=0; /// Set a pointer to the mass array in the MD code diff --git a/src/core/PlumedMain.cpp b/src/core/PlumedMain.cpp index ff4e9b79f3..dd96581db4 100644 --- a/src/core/PlumedMain.cpp +++ b/src/core/PlumedMain.cpp @@ -49,12 +49,12 @@ using namespace std; #include "PlumedMainEnum.inc" -namespace PLMD{ +namespace PLMD { -const std::unordered_map & plumedMainWordMap(){ +const std::unordered_map & plumedMainWordMap() { static std::unordered_map word_map; static bool init=false; - if(!init){ + if(!init) { #include "PlumedMainMap.inc" } init=true; @@ -92,7 +92,7 @@ PlumedMain::PlumedMain(): stopwatch.pause(); } -PlumedMain::~PlumedMain(){ +PlumedMain::~PlumedMain() { stopwatch.start(); stopwatch.stop(); if(initialized) log< words=Tools::getWords(word); unsigned nw=words.size(); - if(nw==0){ + if(nw==0) { // do nothing } else { int iword=-1; @@ -131,333 +131,333 @@ void PlumedMain::cmd(const std::string & word,void*val){ const auto it=plumedMainWordMap().find(words[0]); if(it!=plumedMainWordMap().end()) iword=it->second; switch(iword) { - case cmd_setBox: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setBox(val); - break; - case cmd_setPositions: - CHECK_INIT(initialized,word); - atoms.setPositions(val); - break; - case cmd_setMasses: - CHECK_INIT(initialized,word); - atoms.setMasses(val); - break; - case cmd_setCharges: - CHECK_INIT(initialized,word); - atoms.setCharges(val); - break; - case cmd_setPositionsX: - CHECK_INIT(initialized,word); - atoms.setPositions(val,0); - break; - case cmd_setPositionsY: - CHECK_INIT(initialized,word); - atoms.setPositions(val,1); - break; - case cmd_setPositionsZ: - CHECK_INIT(initialized,word); - atoms.setPositions(val,2); - break; - case cmd_setVirial: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setVirial(val); - break; - case cmd_setEnergy: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setEnergy(val); - break; - case cmd_setForces: - CHECK_INIT(initialized,word); - atoms.setForces(val); - break; - case cmd_setForcesX: - CHECK_INIT(initialized,word); - atoms.setForces(val,0); - break; - case cmd_setForcesY: - CHECK_INIT(initialized,word); - atoms.setForces(val,1); - break; - case cmd_setForcesZ: - CHECK_INIT(initialized,word); - atoms.setForces(val,2); - break; - case cmd_calc: - CHECK_INIT(initialized,word); - calc(); - break; - case cmd_prepareDependencies: - CHECK_INIT(initialized,word); - prepareDependencies(); - break; - case cmd_shareData: - CHECK_INIT(initialized,word); - shareData(); - break; - case cmd_prepareCalc: - CHECK_INIT(initialized,word); - prepareCalc(); - break; - case cmd_performCalc: - CHECK_INIT(initialized,word); - performCalc(); - break; - case cmd_performCalcNoUpdate: - CHECK_INIT(initialized,word); - performCalcNoUpdate(); - break; - case cmd_update: - CHECK_INIT(initialized,word); - update(); - break; - case cmd_setStep: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - step=(*static_cast(val)); - atoms.startStep(); - break; - case cmd_setStepLong: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - step=(*static_cast(val)); - atoms.startStep(); - break; - // words used less frequently: - case cmd_setAtomsNlocal: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setAtomsNlocal(*static_cast(val)); - break; - case cmd_setAtomsGatindex: - CHECK_INIT(initialized,word); - atoms.setAtomsGatindex(static_cast(val),false); - break; - case cmd_setAtomsFGatindex: - CHECK_INIT(initialized,word); - atoms.setAtomsGatindex(static_cast(val),true); - break; - case cmd_setAtomsContiguous: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setAtomsContiguous(*static_cast(val)); - break; - case cmd_createFullList: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.createFullList(static_cast(val)); - break; - case cmd_getFullList: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.getFullList(static_cast(val)); - break; - case cmd_clearFullList: - CHECK_INIT(initialized,word); - atoms.clearFullList(); - break; - case cmd_read: - CHECK_INIT(initialized,word); - if(val)readInputFile(static_cast(val)); - else readInputFile("plumed.dat"); - break; - case cmd_readInputLine: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - readInputLine(static_cast(val)); - break; - case cmd_clear: - CHECK_INIT(initialized,word); - actionSet.clearDelete(); - break; - case cmd_getApiVersion: - CHECK_NOTNULL(val,word); - *(static_cast(val))=4; - break; - // commands which can be used only before initialization: - case cmd_init: - CHECK_NOTINIT(initialized,word); - init(); - break; - case cmd_setRealPrecision: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setRealPrecision(*static_cast(val)); - break; - case cmd_setMDLengthUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDLengthUnits(d); - break; - case cmd_setMDChargeUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDChargeUnits(d); - break; - case cmd_setMDMassUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDMassUnits(d); - break; - case cmd_setMDEnergyUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDEnergyUnits(d); - break; - case cmd_setMDTimeUnits: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.MD2double(val,d); - atoms.setMDTimeUnits(d); - break; - case cmd_setNaturalUnits: + case cmd_setBox: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setBox(val); + break; + case cmd_setPositions: + CHECK_INIT(initialized,word); + atoms.setPositions(val); + break; + case cmd_setMasses: + CHECK_INIT(initialized,word); + atoms.setMasses(val); + break; + case cmd_setCharges: + CHECK_INIT(initialized,word); + atoms.setCharges(val); + break; + case cmd_setPositionsX: + CHECK_INIT(initialized,word); + atoms.setPositions(val,0); + break; + case cmd_setPositionsY: + CHECK_INIT(initialized,word); + atoms.setPositions(val,1); + break; + case cmd_setPositionsZ: + CHECK_INIT(initialized,word); + atoms.setPositions(val,2); + break; + case cmd_setVirial: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setVirial(val); + break; + case cmd_setEnergy: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setEnergy(val); + break; + case cmd_setForces: + CHECK_INIT(initialized,word); + atoms.setForces(val); + break; + case cmd_setForcesX: + CHECK_INIT(initialized,word); + atoms.setForces(val,0); + break; + case cmd_setForcesY: + CHECK_INIT(initialized,word); + atoms.setForces(val,1); + break; + case cmd_setForcesZ: + CHECK_INIT(initialized,word); + atoms.setForces(val,2); + break; + case cmd_calc: + CHECK_INIT(initialized,word); + calc(); + break; + case cmd_prepareDependencies: + CHECK_INIT(initialized,word); + prepareDependencies(); + break; + case cmd_shareData: + CHECK_INIT(initialized,word); + shareData(); + break; + case cmd_prepareCalc: + CHECK_INIT(initialized,word); + prepareCalc(); + break; + case cmd_performCalc: + CHECK_INIT(initialized,word); + performCalc(); + break; + case cmd_performCalcNoUpdate: + CHECK_INIT(initialized,word); + performCalcNoUpdate(); + break; + case cmd_update: + CHECK_INIT(initialized,word); + update(); + break; + case cmd_setStep: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + step=(*static_cast(val)); + atoms.startStep(); + break; + case cmd_setStepLong: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + step=(*static_cast(val)); + atoms.startStep(); + break; + // words used less frequently: + case cmd_setAtomsNlocal: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setAtomsNlocal(*static_cast(val)); + break; + case cmd_setAtomsGatindex: + CHECK_INIT(initialized,word); + atoms.setAtomsGatindex(static_cast(val),false); + break; + case cmd_setAtomsFGatindex: + CHECK_INIT(initialized,word); + atoms.setAtomsGatindex(static_cast(val),true); + break; + case cmd_setAtomsContiguous: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setAtomsContiguous(*static_cast(val)); + break; + case cmd_createFullList: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.createFullList(static_cast(val)); + break; + case cmd_getFullList: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.getFullList(static_cast(val)); + break; + case cmd_clearFullList: + CHECK_INIT(initialized,word); + atoms.clearFullList(); + break; + case cmd_read: + CHECK_INIT(initialized,word); + if(val)readInputFile(static_cast(val)); + else readInputFile("plumed.dat"); + break; + case cmd_readInputLine: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + readInputLine(static_cast(val)); + break; + case cmd_clear: + CHECK_INIT(initialized,word); + actionSet.clearDelete(); + break; + case cmd_getApiVersion: + CHECK_NOTNULL(val,word); + *(static_cast(val))=4; + break; + // commands which can be used only before initialization: + case cmd_init: + CHECK_NOTINIT(initialized,word); + init(); + break; + case cmd_setRealPrecision: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setRealPrecision(*static_cast(val)); + break; + case cmd_setMDLengthUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDLengthUnits(d); + break; + case cmd_setMDChargeUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDChargeUnits(d); + break; + case cmd_setMDMassUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDMassUnits(d); + break; + case cmd_setMDEnergyUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDEnergyUnits(d); + break; + case cmd_setMDTimeUnits: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.MD2double(val,d); + atoms.setMDTimeUnits(d); + break; + case cmd_setNaturalUnits: // set the boltzman constant for MD in natural units (kb=1) // only needed in LJ codes if the MD is passing temperatures to plumed (so, not yet...) // use as cmd("setNaturalUnits") - CHECK_NOTINIT(initialized,word); - atoms.setMDNaturalUnits(true); - break; - case cmd_setNoVirial: - CHECK_NOTINIT(initialized,word); - novirial=true; - break; - case cmd_setPlumedDat: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - plumedDat=static_cast(val); - break; - case cmd_setMPIComm: - CHECK_NOTINIT(initialized,word); - comm.Set_comm(val); - atoms.setDomainDecomposition(comm); - break; - case cmd_setMPIFComm: - CHECK_NOTINIT(initialized,word); - comm.Set_fcomm(val); - atoms.setDomainDecomposition(comm); - break; - case cmd_setMPImultiSimComm: - CHECK_NOTINIT(initialized,word); - multi_sim_comm.Set_comm(val); - break; - case cmd_setNatoms: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setNatoms(*static_cast(val)); - break; - case cmd_setTimestep: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setTimeStep(val); - break; - /* ADDED WITH API==2 */ - case cmd_setKbT: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.setKbT(val); - break; - /* ADDED WITH API==3 */ - case cmd_setRestart: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - if(*static_cast(val)!=0) restart=true; - break; - /* ADDED WITH API==4 */ - case cmd_doCheckPoint: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - doCheckPoint = false; - if(*static_cast(val)!=0) doCheckPoint = true; - break; - /* STOP API */ - case cmd_setMDEngine: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - MDEngine=static_cast(val); - break; - case cmd_setLog: - CHECK_NOTINIT(initialized,word); - log.link(static_cast(val)); - break; - case cmd_setLogFile: - CHECK_NOTINIT(initialized,word); - CHECK_NOTNULL(val,word); - log.open(static_cast(val)); - break; - // other commands that should be used after initialization: - case cmd_setStopFlag: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - stopFlag=static_cast(val); - break; - case cmd_getExchangesFlag: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.getFlag((*static_cast(val))); - break; - case cmd_setExchangesSeed: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.setSeed((*static_cast(val))); - break; - case cmd_setNumberOfReplicas: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.setNofR((*static_cast(val))); - break; - case cmd_getExchangesList: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - exchangePatterns.getList((static_cast(val))); - break; - case cmd_runFinalJobs: - CHECK_INIT(initialized,word); - runJobsAtEndOfCalculation(); - break; - case cmd_isEnergyNeeded: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - if(atoms.isEnergyNeeded()) *(static_cast(val))=1; - else *(static_cast(val))=0; - break; - case cmd_getBias: - CHECK_INIT(initialized,word); - CHECK_NOTNULL(val,word); - atoms.double2MD(getBias()/(atoms.getMDUnits().getEnergy()/atoms.getUnits().getEnergy()),val); - break; - case cmd_checkAction: - CHECK_NOTNULL(val,word); - plumed_assert(nw==2); - *(static_cast(val))=(actionRegister().check(words[1]) ? 1:0); - break; - case cmd_GREX: - if(!grex) grex=new GREX(*this); - plumed_massert(grex,"error allocating grex"); - { - std::string kk=words[1]; - for(unsigned i=2;icmd(kk.c_str(),val); - } - break; - case cmd_CLTool: - CHECK_NOTINIT(initialized,word); - if(!cltool) cltool=new CLToolMain; - { - std::string kk=words[1]; - for(unsigned i=2;icmd(kk.c_str(),val); - } - break; - default: - plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands."); - break; + CHECK_NOTINIT(initialized,word); + atoms.setMDNaturalUnits(true); + break; + case cmd_setNoVirial: + CHECK_NOTINIT(initialized,word); + novirial=true; + break; + case cmd_setPlumedDat: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + plumedDat=static_cast(val); + break; + case cmd_setMPIComm: + CHECK_NOTINIT(initialized,word); + comm.Set_comm(val); + atoms.setDomainDecomposition(comm); + break; + case cmd_setMPIFComm: + CHECK_NOTINIT(initialized,word); + comm.Set_fcomm(val); + atoms.setDomainDecomposition(comm); + break; + case cmd_setMPImultiSimComm: + CHECK_NOTINIT(initialized,word); + multi_sim_comm.Set_comm(val); + break; + case cmd_setNatoms: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setNatoms(*static_cast(val)); + break; + case cmd_setTimestep: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setTimeStep(val); + break; + /* ADDED WITH API==2 */ + case cmd_setKbT: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.setKbT(val); + break; + /* ADDED WITH API==3 */ + case cmd_setRestart: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + if(*static_cast(val)!=0) restart=true; + break; + /* ADDED WITH API==4 */ + case cmd_doCheckPoint: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + doCheckPoint = false; + if(*static_cast(val)!=0) doCheckPoint = true; + break; + /* STOP API */ + case cmd_setMDEngine: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + MDEngine=static_cast(val); + break; + case cmd_setLog: + CHECK_NOTINIT(initialized,word); + log.link(static_cast(val)); + break; + case cmd_setLogFile: + CHECK_NOTINIT(initialized,word); + CHECK_NOTNULL(val,word); + log.open(static_cast(val)); + break; + // other commands that should be used after initialization: + case cmd_setStopFlag: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + stopFlag=static_cast(val); + break; + case cmd_getExchangesFlag: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.getFlag((*static_cast(val))); + break; + case cmd_setExchangesSeed: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.setSeed((*static_cast(val))); + break; + case cmd_setNumberOfReplicas: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.setNofR((*static_cast(val))); + break; + case cmd_getExchangesList: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + exchangePatterns.getList((static_cast(val))); + break; + case cmd_runFinalJobs: + CHECK_INIT(initialized,word); + runJobsAtEndOfCalculation(); + break; + case cmd_isEnergyNeeded: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + if(atoms.isEnergyNeeded()) *(static_cast(val))=1; + else *(static_cast(val))=0; + break; + case cmd_getBias: + CHECK_INIT(initialized,word); + CHECK_NOTNULL(val,word); + atoms.double2MD(getBias()/(atoms.getMDUnits().getEnergy()/atoms.getUnits().getEnergy()),val); + break; + case cmd_checkAction: + CHECK_NOTNULL(val,word); + plumed_assert(nw==2); + *(static_cast(val))=(actionRegister().check(words[1]) ? 1:0); + break; + case cmd_GREX: + if(!grex) grex=new GREX(*this); + plumed_massert(grex,"error allocating grex"); + { + std::string kk=words[1]; + for(unsigned i=2; icmd(kk.c_str(),val); + } + break; + case cmd_CLTool: + CHECK_NOTINIT(initialized,word); + if(!cltool) cltool=new CLToolMain; + { + std::string kk=words[1]; + for(unsigned i=2; icmd(kk.c_str(),val); + } + break; + default: + plumed_merror("cannot interpret cmd(\"" + word + "\"). check plumed developers manual to see the available commands."); + break; } } stopwatch.pause(); @@ -465,7 +465,7 @@ void PlumedMain::cmd(const std::string & word,void*val){ //////////////////////////////////////////////////////////////////////// -void PlumedMain::init(){ +void PlumedMain::init() { // check that initialization just happens once initialized=true; atoms.init(); @@ -486,7 +486,7 @@ void PlumedMain::init(){ log.printf("Number of atoms: %d\n",atoms.getNatoms()); if(grex) log.printf("GROMACS-like replica exchange is on\n"); log.printf("File suffix: %s\n",getSuffix().c_str()); - if(plumedDat.length()>0){ + if(plumedDat.length()>0) { readInputFile(plumedDat); plumedDat=""; } @@ -504,7 +504,7 @@ void PlumedMain::init(){ log<<"Finished setup\n"; } -void PlumedMain::readInputFile(std::string str){ +void PlumedMain::readInputFile(std::string str) { plumed_assert(initialized); log.printf("FILE: %s\n",str.c_str()); IFile ifile; @@ -519,34 +519,34 @@ void PlumedMain::readInputFile(std::string str){ pilots=actionSet.select(); } -void PlumedMain::readInputLine(const std::string & str){ +void PlumedMain::readInputLine(const std::string & str) { plumed_assert(initialized); if(str.empty()) return; std::vector words=Tools::getWords(str); citations.clear(); readInputWords(words); - if(!citations.empty()){ + if(!citations.empty()) { log<<"Relevant bibliography:\n"; log< & words){ +void PlumedMain::readInputWords(const std::vector & words) { plumed_assert(initialized); if(words.empty())return; else if(words[0]=="ENDPLUMED") return; - else if(words[0]=="_SET_SUFFIX"){ + else if(words[0]=="_SET_SUFFIX") { plumed_assert(words.size()==2); setSuffix(words[1]); } else { std::vector interpreted(words); Tools::interpretLabel(interpreted); Action* action=actionRegister().create(ActionOptions(*this,interpreted)); - if(!action){ + if(!action) { log<<"ERROR\n"; log<<"I cannot understand line:"; - for(unsigned i=0;i & words){ //////////////////////////////////////////////////////////////////////// -void PlumedMain::exit(int c){ +void PlumedMain::exit(int c) { comm.Abort(c); } -Log& PlumedMain::getLog(){ +Log& PlumedMain::getLog() { return log; } -void PlumedMain::calc(){ +void PlumedMain::calc() { prepareCalc(); performCalc(); } -void PlumedMain::prepareCalc(){ +void PlumedMain::prepareCalc() { prepareDependencies(); shareData(); } @@ -582,7 +582,7 @@ void PlumedMain::prepareCalc(){ // here we have the main steps in "calc()" // they can be called individually, but the standard thing is to // traverse them in this order: -void PlumedMain::prepareDependencies(){ +void PlumedMain::prepareDependencies() { stopwatch.start("1 Prepare dependencies"); @@ -593,24 +593,24 @@ void PlumedMain::prepareDependencies(){ // which can be dynamically changed). // First switch off all actions - for(const auto & p : actionSet){ - p->deactivate(); - //I think this is already done inside deactivate - //(*p)->clearOptions(); + for(const auto & p : actionSet) { + p->deactivate(); + //I think this is already done inside deactivate + //(*p)->clearOptions(); } // for optimization, an "active" flag remains false if no action at all is active active=false; - for(unsigned i=0;ionStep()){ + for(unsigned i=0; ionStep()) { pilots[i]->activate(); active=true; - } + } }; // also, if one of them is the total energy, tell to atoms that energy should be collected - for(const auto & p : actionSet){ - if(p->isActive()){ + for(const auto & p : actionSet) { + if(p->isActive()) { if(p->checkNeedsGradients()) p->setOption("GRADIENTS"); } } @@ -618,7 +618,7 @@ void PlumedMain::prepareDependencies(){ stopwatch.stop("1 Prepare dependencies"); } -void PlumedMain::shareData(){ +void PlumedMain::shareData() { // atom positions are shared (but only if there is something to do) if(!active)return; stopwatch.start("2 Sharing data"); @@ -626,27 +626,27 @@ void PlumedMain::shareData(){ stopwatch.stop("2 Sharing data"); } -void PlumedMain::performCalcNoUpdate(){ +void PlumedMain::performCalcNoUpdate() { waitData(); justCalculate(); backwardPropagate(); } -void PlumedMain::performCalc(){ +void PlumedMain::performCalc() { waitData(); justCalculate(); backwardPropagate(); update(); } -void PlumedMain::waitData(){ +void PlumedMain::waitData() { if(!active)return; stopwatch.start("3 Waiting for data"); if(atoms.getNatoms()>0) atoms.wait(); stopwatch.stop("3 Waiting for data"); } -void PlumedMain::justCalculate(){ +void PlumedMain::justCalculate() { if(!active)return; stopwatch.start("4 Calculating (forward loop)"); bias=0.0; @@ -654,10 +654,10 @@ void PlumedMain::justCalculate(){ int iaction=0; // calculate the active actions in order (assuming *backward* dependence) - for(const auto & p : actionSet){ - if(p->isActive()){ + for(const auto & p : actionSet) { + if(p->isActive()) { std::string actionNumberLabel; - if(detailedTimers){ + if(detailedTimers) { Tools::convert(iaction,actionNumberLabel); actionNumberLabel="4A "+actionNumberLabel+" "+p->getLabel(); stopwatch.start(actionNumberLabel); @@ -674,12 +674,12 @@ void PlumedMain::justCalculate(){ } if(p->checkNumericalDerivatives()) p->calculateNumericalDerivatives(); else p->calculate(); - // This retrieves components called bias + // This retrieves components called bias if(av) bias+=av->getOutputQuantity("bias"); if(av) work+=av->getOutputQuantity("work"); - if(av)av->setGradientsIfNeeded(); + if(av)av->setGradientsIfNeeded(); ActionWithVirtualAtom*avv=dynamic_cast(p); - if(avv)avv->setGradientsIfNeeded(); + if(avv)avv->setGradientsIfNeeded(); if(detailedTimers) stopwatch.stop(actionNumberLabel); } iaction++; @@ -687,22 +687,22 @@ void PlumedMain::justCalculate(){ stopwatch.stop("4 Calculating (forward loop)"); } -void PlumedMain::justApply(){ +void PlumedMain::justApply() { backwardPropagate(); update(); } - -void PlumedMain::backwardPropagate(){ + +void PlumedMain::backwardPropagate() { if(!active)return; int iaction=0; stopwatch.start("5 Applying (backward loop)"); // apply them in reverse order - for(auto pp=actionSet.rbegin();pp!=actionSet.rend();++pp){ + for(auto pp=actionSet.rbegin(); pp!=actionSet.rend(); ++pp) { const auto & p(*pp); - if(p->isActive()){ + if(p->isActive()) { std::string actionNumberLabel; - if(detailedTimers){ + if(detailedTimers) { Tools::convert(iaction,actionNumberLabel); actionNumberLabel="5A "+actionNumberLabel+" "+p->getLabel(); stopwatch.start(actionNumberLabel); @@ -725,28 +725,28 @@ void PlumedMain::backwardPropagate(){ stopwatch.stop("5 Applying (backward loop)"); } -void PlumedMain::update(){ +void PlumedMain::update() { if(!active)return; stopwatch.start("6 Update"); // update step (for statistics, etc) updateFlags.push(true); - for(const auto & p : actionSet){ + for(const auto & p : actionSet) { p->beforeUpdate(); if(p->isActive() && p->checkUpdate() && updateFlagsTop()) p->update(); } while(!updateFlags.empty()) updateFlags.pop(); if(!updateFlags.empty()) plumed_merror("non matching changes in the update flags"); // Check that no action has told the calculation to stop - if(stopNow){ - if(stopFlag) (*stopFlag)=1; - else plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)"); - } + if(stopNow) { + if(stopFlag) (*stopFlag)=1; + else plumed_merror("your md code cannot handle plumed stop events - add a call to plumed.comm(stopFlag,stopCondition)"); + } // flush by default every 10000 steps // hopefully will not affect performance // also if receive checkpointing signal - if(step%10000==0||doCheckPoint){ + if(step%10000==0||doCheckPoint) { fflush(); log.flush(); for(const auto & p : actionSet) p->fflush(); @@ -754,49 +754,49 @@ void PlumedMain::update(){ stopwatch.stop("6 Update"); } -void PlumedMain::load(const std::string& ss){ - if(DLLoader::installed()){ - string s=ss; - size_t n=s.find_last_of("."); - string extension=""; - string base=s; - if(n!=std::string::npos && n0) log<<" (only on master node)"; - log<<"\n"; - if(comm.Get_rank()==0) system(cmd.c_str()); - comm.Barrier(); - base="./"+base; - } - s=base+"."+config::getSoExt(); - void *p=dlloader.load(s); - if(!p){ - const std::string error_msg="I cannot load library " + ss + " " + dlloader.error(); - log<<"ERROR\n"; - log<0) log<<" (only on master node)"; + log<<"\n"; + if(comm.Get_rank()==0) system(cmd.c_str()); + comm.Barrier(); + base="./"+base; + } + s=base+"."+config::getSoExt(); + void *p=dlloader.load(s); + if(!p) { + const std::string error_msg="I cannot load library " + ss + " " + dlloader.error(); + log<<"ERROR\n"; + log<flush(); } } -void PlumedMain::insertFile(FileBase&f){ +void PlumedMain::insertFile(FileBase&f) { files.insert(&f); } -void PlumedMain::eraseFile(FileBase&f){ +void PlumedMain::eraseFile(FileBase&f) { files.erase(&f); } -void PlumedMain::stop(){ +void PlumedMain::stop() { stopNow=true; } -void PlumedMain::runJobsAtEndOfCalculation(){ - for(const auto & p : actionSet){ - p->runFinalJobs(); +void PlumedMain::runJobsAtEndOfCalculation() { + for(const auto & p : actionSet) { + p->runFinalJobs(); } -} +} } diff --git a/src/core/PlumedMain.h b/src/core/PlumedMain.h index ced8d15c9a..ad26628444 100644 --- a/src/core/PlumedMain.h +++ b/src/core/PlumedMain.h @@ -171,104 +171,104 @@ class PlumedMain: PlumedMain(); // this is to access to WithCmd versions of cmd (allowing overloading of a virtual method) using WithCmd::cmd; -/** - cmd method, accessible with standard Plumed.h interface. - \param key The name of the command to be executed. - \param val The argument of the command to be executed. - It is called as plumed_cmd() or as PLMD::Plumed::cmd() - It is the interpreter for plumed commands. It basically contains the definition of the plumed interface. - If you want to add a new functionality to the interface between plumed - and an MD engine, this is the right place - Notice that this interface should always keep retro-compatibility -*/ + /** + cmd method, accessible with standard Plumed.h interface. + \param key The name of the command to be executed. + \param val The argument of the command to be executed. + It is called as plumed_cmd() or as PLMD::Plumed::cmd() + It is the interpreter for plumed commands. It basically contains the definition of the plumed interface. + If you want to add a new functionality to the interface between plumed + and an MD engine, this is the right place + Notice that this interface should always keep retro-compatibility + */ void cmd(const std::string&key,void*val=NULL); ~PlumedMain(); -/** - Read an input file. - \param str name of the file -*/ + /** + Read an input file. + \param str name of the file + */ void readInputFile(std::string str); -/** - Read an input string. - \param str name of the string -*/ + /** + Read an input string. + \param str name of the string + */ void readInputWords(const std::vector & str); -/** - Read an input string. - \param str name of the string - At variance with readInputWords(), this is splitting the string into words -*/ + /** + Read an input string. + \param str name of the string + At variance with readInputWords(), this is splitting the string into words + */ void readInputLine(const std::string & str); -/** - Initialize the object. - Should be called once. -*/ + /** + Initialize the object. + Should be called once. + */ void init(); -/** - Prepare the calculation. - Here it is checked which are the active Actions and communication of the relevant atoms is initiated. - Shortcut for prepareDependencies() + shareData() -*/ + /** + Prepare the calculation. + Here it is checked which are the active Actions and communication of the relevant atoms is initiated. + Shortcut for prepareDependencies() + shareData() + */ void prepareCalc(); -/** - Prepare the list of active Actions and needed atoms. - Scan the Actions to see which are active and which are not, so as to prepare a list of - the atoms needed at this step. -*/ + /** + Prepare the list of active Actions and needed atoms. + Scan the Actions to see which are active and which are not, so as to prepare a list of + the atoms needed at this step. + */ void prepareDependencies(); -/** - Share the needed atoms. - In asynchronous implementations, this method sends the required atoms to all the plumed processes, - without waiting for the communication to complete. -*/ + /** + Share the needed atoms. + In asynchronous implementations, this method sends the required atoms to all the plumed processes, + without waiting for the communication to complete. + */ void shareData(); -/** - Perform the calculation. - Shortcut for waitData() + justCalculate() + justApply(). - Equivalently: waitData() + justCalculate() + backwardPropagate() + update(). -*/ + /** + Perform the calculation. + Shortcut for waitData() + justCalculate() + justApply(). + Equivalently: waitData() + justCalculate() + backwardPropagate() + update(). + */ void performCalc(); -/** - Perform the calculation without update() - Shortcut for: waitData() + justCalculate() + backwardPropagate() -*/ + /** + Perform the calculation without update() + Shortcut for: waitData() + justCalculate() + backwardPropagate() + */ void performCalcNoUpdate(); -/** - Complete PLUMED calculation. - Shortcut for prepareCalc() + performCalc() -*/ + /** + Complete PLUMED calculation. + Shortcut for prepareCalc() + performCalc() + */ void calc(); -/** - Scatters the needed atoms. - In asynchronous implementations, this method waits for the communications started in shareData() - to be completed. Otherwise, just send around needed atoms. -*/ + /** + Scatters the needed atoms. + In asynchronous implementations, this method waits for the communications started in shareData() + to be completed. Otherwise, just send around needed atoms. + */ void waitData(); -/** - Perform the forward loop on active actions. -*/ + /** + Perform the forward loop on active actions. + */ void justCalculate(); -/** - Backward propagate and update. - Shortcut for backwardPropagate() + update() - I leave it here for backward compatibility -*/ + /** + Backward propagate and update. + Shortcut for backwardPropagate() + update() + I leave it here for backward compatibility + */ void justApply(); -/** - Perform the backward loop on active actions. - Needed to apply the forces back. -*/ + /** + Perform the backward loop on active actions. + Needed to apply the forces back. + */ void backwardPropagate(); -/** - Call the update() method. -*/ + /** + Call the update() method. + */ void update(); -/** - If there are calculations that need to be done at the very end of the calculations this - makes sures they are done -*/ + /** + If there are calculations that need to be done at the very end of the calculations this + makes sures they are done + */ void runJobsAtEndOfCalculation(); /// Reference to atoms object Atoms& getAtoms(); @@ -277,7 +277,7 @@ class PlumedMain: /// Referenge to the log stream Log & getLog(); /// Return the number of the step - long int getStep()const{return step;} + long int getStep()const {return step;} /// Stop the run void exit(int c=0); /// Load a shared library @@ -305,8 +305,8 @@ class PlumedMain: /// Check if restarting bool getRestart()const; /// Set restart flag - void setRestart(bool f){restart=f;} -/// Check if checkpointing + void setRestart(bool f) {restart=f;} +/// Check if checkpointing bool getCPT()const; /// Set exchangeStep flag void setExchangeStep(bool f); @@ -322,7 +322,7 @@ class PlumedMain: void resetActive(bool active); /// Access to exchange patterns - ExchangePatterns& getExchangePatterns(){return exchangePatterns;} + ExchangePatterns& getExchangePatterns() {return exchangePatterns;} /// Push a state to update flags void updateFlagsPush(bool); @@ -336,62 +336,62 @@ class PlumedMain: // FAST INLINE METHODS: inline -const ActionSet & PlumedMain::getActionSet()const{ +const ActionSet & PlumedMain::getActionSet()const { return actionSet; } inline -Atoms& PlumedMain::getAtoms(){ +Atoms& PlumedMain::getAtoms() { return atoms; } inline -const std::string & PlumedMain::getSuffix()const{ +const std::string & PlumedMain::getSuffix()const { return suffix; } inline -void PlumedMain::setSuffix(const std::string&s){ +void PlumedMain::setSuffix(const std::string&s) { suffix=s; } inline -bool PlumedMain::getRestart()const{ +bool PlumedMain::getRestart()const { return restart; } inline -bool PlumedMain::getCPT()const{ +bool PlumedMain::getCPT()const { return doCheckPoint; } inline -void PlumedMain::setExchangeStep(bool s){ +void PlumedMain::setExchangeStep(bool s) { exchangeStep=s; } inline -bool PlumedMain::getExchangeStep()const{ +bool PlumedMain::getExchangeStep()const { return exchangeStep; } inline -void PlumedMain::resetActive(bool active){ +void PlumedMain::resetActive(bool active) { this->active=active; } inline -void PlumedMain::updateFlagsPush(bool on){ +void PlumedMain::updateFlagsPush(bool on) { updateFlags.push(on); } inline -void PlumedMain::updateFlagsPop(){ +void PlumedMain::updateFlagsPop() { updateFlags.pop(); } inline -bool PlumedMain::updateFlagsTop(){ +bool PlumedMain::updateFlagsTop() { return updateFlags.top(); } diff --git a/src/core/PlumedMainInitializer.cpp b/src/core/PlumedMainInitializer.cpp index 20244e257c..b7fc8e3e45 100644 --- a/src/core/PlumedMainInitializer.cpp +++ b/src/core/PlumedMainInitializer.cpp @@ -43,16 +43,16 @@ typedef struct { /* These functions should be accessible from C, since they might be statically used from Plumed.c (for static binding) */ -extern "C" void*plumedmain_create(){ +extern "C" void*plumedmain_create() { return new PLMD::PlumedMain; } -extern "C" void plumedmain_cmd(void*plumed,const char*key,const void*val){ +extern "C" void plumedmain_cmd(void*plumed,const char*key,const void*val) { plumed_massert(plumed,"trying to use a plumed object which is not initialized"); static_cast(plumed)->cmd(key,val); } -extern "C" void plumedmain_finalize(void*plumed){ +extern "C" void plumedmain_finalize(void*plumed) { plumed_massert(plumed,"trying to deallocate a plumed object which is not initialized"); delete static_cast(plumed); } @@ -60,16 +60,16 @@ extern "C" void plumedmain_finalize(void*plumed){ /* This refers to a function implemented in Plumed.c */ extern "C" plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder*); -namespace PLMD{ +namespace PLMD { /// Static object which registers Plumed. /// This is a static object which, during its construction at startup, /// registers the pointers to plumedmain_create, plumedmain_cmd and plumedmain_finalize /// to the plumed_kernel_register function -static class PlumedMainInitializer{ - public: - PlumedMainInitializer(){ - plumed_plumedmain_function_holder fh={plumedmain_create,plumedmain_cmd,plumedmain_finalize}; +static class PlumedMainInitializer { +public: + PlumedMainInitializer() { + plumed_plumedmain_function_holder fh= {plumedmain_create,plumedmain_cmd,plumedmain_finalize}; plumed_kernel_register(&fh); } } RegisterMe; diff --git a/src/core/SetupMolInfo.cpp b/src/core/SetupMolInfo.cpp index af6a4d5138..662ddfb1c4 100644 --- a/src/core/SetupMolInfo.cpp +++ b/src/core/SetupMolInfo.cpp @@ -38,24 +38,24 @@ compilation will exclude it from plumed. */ -void SetupMolInfo::registerKeywords( Keywords& keys ){ +void SetupMolInfo::registerKeywords( Keywords& keys ) { ActionSetup::registerKeywords(keys); keys.add("compulsory","STRUCTURE","a file in pdb format containing a reference structure. " - "This is used to defines the atoms in the various residues, chains, etc . " - "For more details on the PDB file format visit http://www.wwpdb.org/docs.html"); + "This is used to defines the atoms in the various residues, chains, etc . " + "For more details on the PDB file format visit http://www.wwpdb.org/docs.html"); keys.add("compulsory","MOLTYPE","protein","what kind of molecule is contained in the pdb file"); keys.add("atoms","CHAIN","(for masochists ( mostly Davide Branduardi ) ) The atoms involved in each of the chains of interest in the structure."); } -SetupMolInfo::~SetupMolInfo(){ +SetupMolInfo::~SetupMolInfo() { delete &pdb; } SetupMolInfo::SetupMolInfo( const ActionOptions&ao ): -Action(ao), -ActionSetup(ao), -ActionAtomistic(ao), -pdb(*new(PDB)) + Action(ao), + ActionSetup(ao), + ActionAtomistic(ao), + pdb(*new(PDB)) { // Read what is contained in the pdb file parse("MOLTYPE",mytype); @@ -65,126 +65,126 @@ pdb(*new(PDB)) std::vector backbone; parseAtomList("CHAIN",backbone); - if( read_backbone.size()==0 ){ - for(unsigned i=1;;++i){ - parseAtomList("CHAIN",i,backbone); - if( backbone.size()==0 ) break; - read_backbone.push_back(backbone); - backbone.resize(0); - } - } else { + if( read_backbone.size()==0 ) { + for(unsigned i=1;; ++i) { + parseAtomList("CHAIN",i,backbone); + if( backbone.size()==0 ) break; read_backbone.push_back(backbone); + backbone.resize(0); + } + } else { + read_backbone.push_back(backbone); } - if( read_backbone.size()==0 ){ + if( read_backbone.size()==0 ) { std::string reference; parse("STRUCTURE",reference); if( ! pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/plumed.getAtoms().getUnits().getLength()))plumed_merror("missing input file " + reference ); std::vector chains; pdb.getChainNames( chains ); log.printf(" pdb file named %s contains %u chains \n",reference.c_str(), static_cast(chains.size())); - for(unsigned i=0;i& restrings, const std::string& fortype, std::vector< std::vector >& backbone ){ +void SetupMolInfo::getBackbone( std::vector& restrings, const std::string& fortype, std::vector< std::vector >& backbone ) { if( fortype!=mytype ) error("cannot calculate a variable designed for " + fortype + " molecules for molecule type " + mytype ); if( MolDataClass::numberOfAtomsPerResidueInBackbone( mytype )==0 ) error("backbone is not defined for molecule type " + mytype ); - if( read_backbone.size()!=0 ){ - if( restrings.size()!=1 ) error("cannot interpret anything other than all for residues when using CHAIN keywords"); - if( restrings[0]!="all" ) error("cannot interpret anything other than all for residues when using CHAIN keywords"); - backbone.resize( read_backbone.size() ); - for(unsigned i=0;i chains; pdb.getChainNames( chains ); - for(unsigned i=0;i chains; pdb.getChainNames( chains ); + for(unsigned i=0; i > segments; - std::vector thissegment; - Tools::convert(restrings[0],nk); thissegment.push_back(nk); - for(unsigned i=1;i > segments; + std::vector thissegment; + Tools::convert(restrings[0],nk); thissegment.push_back(nk); + for(unsigned i=1; i atomnumbers; - for(unsigned i=0;i atomnumbers; + for(unsigned i=0; i& atoms )const{ +void SetupMolInfo::interpretSymbol( const std::string& symbol, std::vector& atoms )const { MolDataClass::specialSymbol( mytype, symbol, pdb, atoms ); } -std::string SetupMolInfo::getAtomName(AtomNumber a)const{ +std::string SetupMolInfo::getAtomName(AtomNumber a)const { return pdb.getAtomName(a); } -unsigned SetupMolInfo::getResidueNumber(AtomNumber a)const{ +unsigned SetupMolInfo::getResidueNumber(AtomNumber a)const { return pdb.getResidueNumber(a); } -std::string SetupMolInfo::getResidueName(AtomNumber a)const{ +std::string SetupMolInfo::getResidueName(AtomNumber a)const { return pdb.getResidueName(a); } diff --git a/src/core/SetupMolInfo.h b/src/core/SetupMolInfo.h index f347f616f5..362073b8bd 100644 --- a/src/core/SetupMolInfo.h +++ b/src/core/SetupMolInfo.h @@ -30,9 +30,9 @@ namespace PLMD { class PDB; -class SetupMolInfo : -public ActionSetup, -public ActionAtomistic { +class SetupMolInfo : + public ActionSetup, + public ActionAtomistic { private: /// A pdb file containing the topology PDB& pdb; diff --git a/src/core/TargetDist.cpp b/src/core/TargetDist.cpp index 4a666a8e0e..1bed184498 100644 --- a/src/core/TargetDist.cpp +++ b/src/core/TargetDist.cpp @@ -27,44 +27,44 @@ namespace PLMD { -void TargetDist::read( const PDB& pdb, std::vector ar ){ +void TargetDist::read( const PDB& pdb, std::vector ar ) { // Clear values in target actions - for(unsigned i=0;igetPntrToAction())->clearInputForces(); - (ar[i]->getPntrToAction())->clearDerivatives(); + for(unsigned i=0; igetPntrToAction())->clearInputForces(); + (ar[i]->getPntrToAction())->clearDerivatives(); } // Caclulate target actions from input in PDB file std::vector targ( ar.size() ); - for(unsigned i=0;ivalueHasBeenSet() ){ - targ[i]=ar[i]->get(); - } else { - (ar[i]->getPntrToAction())->calculateFromPDB( pdb ); - targ[i]=ar[i]->get(); - } + for(unsigned i=0; ivalueHasBeenSet() ) { + targ[i]=ar[i]->get(); + } else { + (ar[i]->getPntrToAction())->calculateFromPDB( pdb ); + targ[i]=ar[i]->get(); + } } read( targ, ar ); } -void TargetDist::read( const std::vector& targ, std::vector ar ){ +void TargetDist::read( const std::vector& targ, std::vector ar ) { plumed_assert( targ.size()==ar.size() ); target.resize( ar.size() ); args.resize( ar.size() ); log.printf(" distance from this point in cv space : "); - for(unsigned i=0;i& derivs ){ +double TargetDist::calculate( std::vector& derivs ) { plumed_assert( derivs.size()==args.size() ); double dist=0; - for(unsigned i=0;idifference( target[i], args[i]->get() ); - derivs[i]=tmp; dist+=tmp*tmp; + for(unsigned i=0; idifference( target[i], args[i]->get() ); + derivs[i]=tmp; dist+=tmp*tmp; } dist=sqrt(dist); - for(unsigned i=0;i #include -namespace PLMD{ +namespace PLMD { class Log; class PDB; @@ -33,12 +33,12 @@ class Value; class TargetDist { private: - std::vector args; + std::vector args; std::vector target; Log &log; public: explicit TargetDist(Log& log) : log(log) {} - void read( const PDB& pdb, std::vector args ); + void read( const PDB& pdb, std::vector args ); void read( const std::vector& targ, std::vector ar ); double calculate( std::vector& derivs ); }; diff --git a/src/core/Value.cpp b/src/core/Value.cpp index b1fd605b5a..76d43a0ac0 100644 --- a/src/core/Value.cpp +++ b/src/core/Value.cpp @@ -28,19 +28,19 @@ #include "Atoms.h" #include "PlumedMain.h" -namespace PLMD{ +namespace PLMD { Value::Value(): - action(NULL), - value_set(false), - value(0.0), + action(NULL), + value_set(false), + value(0.0), inputForce(0.0), hasForce(false), - hasDeriv(true), - periodicity(unset), - min(0.0), - max(0.0), - max_minus_min(0.0), + hasDeriv(true), + periodicity(unset), + min(0.0), + max(0.0), + max_minus_min(0.0), inv_max_minus_min(0.0) { } @@ -61,18 +61,18 @@ Value::Value(ActionWithValue* av, const std::string& name, const bool withderiv) { } -void Value::setupPeriodicity(){ - if( min==0 && max==0 ){ - periodicity=notperiodic; +void Value::setupPeriodicity() { + if( min==0 && max==0 ) { + periodicity=notperiodic; } else { - periodicity=periodic; - max_minus_min=max-min; - plumed_massert(max_minus_min>0, "your function has a very strange domain?"); - inv_max_minus_min=1.0/max_minus_min; + periodicity=periodic; + max_minus_min=max-min; + plumed_massert(max_minus_min>0, "your function has a very strange domain?"); + inv_max_minus_min=1.0/max_minus_min; } } -bool Value::isPeriodic()const{ +bool Value::isPeriodic()const { plumed_massert(periodicity!=unset,"periodicity should be set"); return periodicity==periodic; } @@ -81,18 +81,18 @@ bool Value::applyForce(std::vector& forces ) const { if( !hasForce ) return false; plumed_dbg_massert( derivatives.size()==forces.size()," forces array has wrong size" ); const unsigned N=derivatives.size(); - for(unsigned i=0;ierror("could not convert period string " + str_min + " to real"); - str_max=pmax; +void Value::setDomain(const std::string& pmin,const std::string& pmax) { + str_min=pmin; + if( !Tools::convert(str_min,min) ) action->error("could not convert period string " + str_min + " to real"); + str_max=pmax; if( !Tools::convert(str_max,max) ) action->error("could not convert period string " + str_max + " to read"); setupPeriodicity(); } @@ -109,28 +109,28 @@ void Value::getDomain(double&minout,double&maxout) const { maxout=max; } -void Value::setGradients(){ +void Value::setGradients() { gradients.clear(); ActionAtomistic*aa=dynamic_cast(action); ActionWithArguments*aw=dynamic_cast(action); - if(aa){ + if(aa) { Atoms&atoms((aa->plumed).getAtoms()); - for(unsigned j=0;jgetNumberOfAtoms();++j){ + for(unsigned j=0; jgetNumberOfAtoms(); ++j) { AtomNumber an=aa->getAbsoluteIndex(j); - if(atoms.isVirtualAtom(an)){ + if(atoms.isVirtualAtom(an)) { const ActionWithVirtualAtom* a=atoms.getVirtualAtomsAction(an); - for(const auto & p : a->getGradients()){ + for(const auto & p : a->getGradients()) { // controllare l'ordine del matmul: gradients[p.first]+=matmul(Vector(derivatives[3*j],derivatives[3*j+1],derivatives[3*j+2]),p.second); } } else { - for(unsigned i=0;i<3;i++) gradients[an][i]+=derivatives[3*j+i]; + for(unsigned i=0; i<3; i++) gradients[an][i]+=derivatives[3*j+i]; } } - } else if(aw){ + } else if(aw) { std::vector values=aw->getArguments(); - for(unsigned j=0;jgradients){ + for(unsigned j=0; jgradients) { AtomNumber iatom=p.first; gradients[iatom]+=p.second*derivatives[j]; } @@ -138,44 +138,44 @@ void Value::setGradients(){ } else plumed_error(); } -double Value::projection(const Value& v1,const Value&v2){ +double Value::projection(const Value& v1,const Value&v2) { double proj=0.0; const std::map & grad1(v1.gradients); const std::map & grad2(v2.gradients); - for(const auto & p1 : grad1){ + for(const auto & p1 : grad1) { AtomNumber a=p1.first; const auto p2=grad2.find(a); - if(p2!=grad2.end()){ + if(p2!=grad2.end()) { proj+=dotProduct(p1.second,(*p2).second); } } return proj; } -ActionWithValue* Value::getPntrToAction(){ +ActionWithValue* Value::getPntrToAction() { plumed_assert( action!=NULL ); return action; } -void copy( const Value& val1, Value& val2 ){ +void copy( const Value& val1, Value& val2 ) { unsigned nder=val1.getNumberOfDerivatives(); - if( nder!=val2.getNumberOfDerivatives() ){ val2.resizeDerivatives( nder ); } + if( nder!=val2.getNumberOfDerivatives() ) { val2.resizeDerivatives( nder ); } val2.clearDerivatives(); - for(unsigned i=0;igetNumberOfDerivatives() ){ val2->resizeDerivatives( nder ); } + if( nder!=val2->getNumberOfDerivatives() ) { val2->resizeDerivatives( nder ); } val2->clearDerivatives(); - for(unsigned i=0;iaddDerivative( i, val1.getDerivative(i) ); + for(unsigned i=0; iaddDerivative( i, val1.getDerivative(i) ); val2->set( val1.get() ); } -void add( const Value& val1, Value* val2 ){ +void add( const Value& val1, Value* val2 ) { plumed_assert( val1.getNumberOfDerivatives()==val2->getNumberOfDerivatives() ); - for(unsigned i=0;iaddDerivative( i, val1.getDerivative(i) ); + for(unsigned i=0; iaddDerivative( i, val1.getDerivative(i) ); val2->set( val1.get() + val2->get() ); } diff --git a/src/core/Value.h b/src/core/Value.h index d1a8509c7c..6bbd9b6cee 100644 --- a/src/core/Value.h +++ b/src/core/Value.h @@ -30,31 +30,31 @@ #include "tools/AtomNumber.h" #include "tools/Vector.h" -namespace PLMD{ +namespace PLMD { class ActionWithValue; /// \ingroup TOOLBOX /// A class for holding the value of a function together with its derivatives. -/// Typically, an object of type PLMD::ActionWithValue will contain one -/// object of type PLUMD::Value that will be named after the label. If the -/// PLMD::ActionWithValue is part of a class that calculates multiple components +/// Typically, an object of type PLMD::ActionWithValue will contain one +/// object of type PLUMD::Value that will be named after the label. If the +/// PLMD::ActionWithValue is part of a class that calculates multiple components /// then the class will contain multiple that will be called label.component-name -/// This class is used to pass information between different PLMD::Action +/// This class is used to pass information between different PLMD::Action /// objects. However, if you find a use for a tempory PLMD::Value in some method /// you are implementing please feel free to use it. -class Value{ -friend class ActionWithValue; +class Value { + friend class ActionWithValue; /// This copies the contents of a value into a second value (just the derivatives and value) -friend void copy( const Value& val1, Value& val2 ); + friend void copy( const Value& val1, Value& val2 ); /// This copies the contents of a value into a second value (but second value is a pointer) -friend void copy( const Value& val, Value* val2 ); + friend void copy( const Value& val, Value* val2 ); /// This adds some derivatives onto the value -friend void add( const Value& val1, Value* valout ); + friend void add( const Value& val1, Value* valout ); /// This calculates val1*val2 and sorts out the derivatives -friend void product( const Value& val1, const Value& val2, Value& valout ); + friend void product( const Value& val1, const Value& val2, Value& valout ); /// This calculates va1/val2 and sorts out the derivatives -friend void quotient( const Value& val1, const Value& val2, Value* valout ); + friend void quotient( const Value& val1, const Value& val2, Value* valout ); private: /// The action in which this quantity is calculated ActionWithValue* action; @@ -89,7 +89,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); Value(); /// A constructor that is used throughout the code to setup the value poiters Value(ActionWithValue* av, const std::string& name, const bool withderiv); -/// Set the value of the function +/// Set the value of the function void set(double); /// Add something to the value of the function void add(double); @@ -102,7 +102,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); /// Set the function not periodic void setNotPeriodic(); /// Set the domain of the function - void setDomain(const std::string&, const std::string&); + void setDomain(const std::string&, const std::string&); /// Get the domain of the quantity void getDomain(std::string&,std::string&) const; /// Get the domain of the quantity @@ -112,7 +112,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); /// Check whether or not this particular quantity has derivatives bool hasDerivatives()const; /// Get the number of derivatives that this particular value has - unsigned getNumberOfDerivatives() const; + unsigned getNumberOfDerivatives() const; /// Set the number of derivatives void resizeDerivatives(int n); /// Set all the derivatives to zero @@ -135,7 +135,7 @@ friend void quotient( const Value& val1, const Value& val2, Value* valout ); bool applyForce( std::vector& forces ) const ; /// Calculate the difference between the instantaneous value of the function and some other point: other_point-inst_val double difference(double)const; -/// Calculate the difference between two values of this function: d2 -d1 +/// Calculate the difference between two values of this function: d2 -d1 double difference(double d1,double d2)const; /// This returns the pointer to the action where this value is calculated ActionWithValue* getPntrToAction(); @@ -151,57 +151,57 @@ void copy( const Value& val1, Value* val2 ); void add( const Value& val1, Value* valout ); inline -void Value::applyPeriodicity(){ - if(periodicity==periodic){ +void Value::applyPeriodicity() { + if(periodicity==periodic) { value=min+difference(min,value); if(valuederivatives.size()!=val1.derivatives.size() ) valout->resizeDerivatives( val1.derivatives.size() ); - valout->value_set=false; + valout->value_set=false; valout->clearDerivatives(); - double u=val1.get(); + double u=val1.get(); double v=val2.get(); - for(unsigned i=0;iaddDerivative(i, v*val1.getDerivative(i) - u*val2.getDerivative(i) ); + for(unsigned i=0; iaddDerivative(i, v*val1.getDerivative(i) - u*val2.getDerivative(i) ); } valout->chainRule( 1/(v*v) ); valout->set( u / v ); } inline -void Value::set(double v){ +void Value::set(double v) { value_set=true; value=v; applyPeriodicity(); } inline -void Value::add(double v){ +void Value::add(double v) { value_set=true; value+=v; applyPeriodicity(); } inline -double Value::get()const{ +double Value::get()const { return value; } @@ -211,7 +211,7 @@ bool Value::valueHasBeenSet() const { } inline -const std::string& Value::getName()const{ +const std::string& Value::getName()const { return name; } @@ -233,41 +233,41 @@ bool Value::hasDerivatives() const { } inline -void Value::resizeDerivatives(int n){ +void Value::resizeDerivatives(int n) { if(hasDeriv) derivatives.resize(n); } inline -void Value::addDerivative(unsigned i,double d){ +void Value::addDerivative(unsigned i,double d) { plumed_dbg_massert(i -namespace PLMD{ +namespace PLMD { /// Base for classes with cmd() method. /// This is an abstract base class for classes with /// cmd() method. It takes care of "const" cast, and /// in the future it may be used to enforce some sort /// of type checking on passed arguments. -class WithCmd{ +class WithCmd { public: virtual ~WithCmd(); /// Const val version, which indeed just overrides the const and call the virtual method. @@ -41,7 +41,7 @@ class WithCmd{ }; inline -void WithCmd::cmd(const std::string& key,const void*val){ +void WithCmd::cmd(const std::string& key,const void*val) { // this is nasty trick: cmd(key,const_cast(val)); // in this manner, a const pointer can be used for val, allowing the user to pass @@ -50,7 +50,7 @@ void WithCmd::cmd(const std::string& key,const void*val){ } inline -WithCmd::~WithCmd(){ +WithCmd::~WithCmd() { // do nothing // here just to allow inheriting from this class properly } diff --git a/src/crystallization/BondOrientation.cpp b/src/crystallization/BondOrientation.cpp index 450cc3b94f..638d70bf5d 100644 --- a/src/crystallization/BondOrientation.cpp +++ b/src/crystallization/BondOrientation.cpp @@ -49,49 +49,49 @@ class BondOrientation : public VectorMultiColvar { PLUMED_REGISTER_ACTION(BondOrientation,"BOND_DIRECTIONS") -void BondOrientation::registerKeywords( Keywords& keys ){ +void BondOrientation::registerKeywords( Keywords& keys ) { VectorMultiColvar::registerKeywords( keys ); keys.add("numbered","ATOMS","the atoms involved in each of the vectors you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one vector will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one vector will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); keys.add("compulsory","NN","12","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); keys.use("VMEAN"); keys.use("VSUM"); } BondOrientation::BondOrientation( const ActionOptions& ao ): -Action(ao), -VectorMultiColvar(ao) + Action(ao), + VectorMultiColvar(ao) { // Read atoms weightHasDerivatives=true; - std::vector all_atoms; + std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); - if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 2, all_atoms ); + if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 2, all_atoms ); setupMultiColvarBase( all_atoms ); // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" orientation of those bonds with lengths are less than %s\n",( switchingFunction.description() ).c_str() ); // Set the link cell cutoff @@ -106,10 +106,10 @@ double BondOrientation::calculateWeight( const unsigned& current, const double& if( distm>rcut2 ) return 0.0; double df, ww=switchingFunction.calculateSqr( distm, df ); // Derivatives of weights - addAtomDerivatives( 0, 0, -df*weight*distance, myatoms ); + addAtomDerivatives( 0, 0, -df*weight*distance, myatoms ); addAtomDerivatives( 0, 1, df*weight*distance, myatoms ); myatoms.addBoxDerivatives( 0, (-df)*weight*Tensor(distance,distance) ); - return ww; + return ww; } void BondOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) const { @@ -125,11 +125,11 @@ void BondOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) con myatoms.addBoxDerivatives( 3, Tensor(distance,Vector(0,-1.0,0)) ); myatoms.addValue( 3, distance[1] ); - addAtomDerivatives( 4 , 0, Vector(0,0,-1.0), myatoms ); - addAtomDerivatives( 4 , 1, Vector(0,0,+1.0), myatoms ); + addAtomDerivatives( 4, 0, Vector(0,0,-1.0), myatoms ); + addAtomDerivatives( 4, 1, Vector(0,0,+1.0), myatoms ); myatoms.addBoxDerivatives( 4, Tensor(distance,Vector(0,0,-1.0)) ); myatoms.addValue( 4, distance[2] ); } } -} +} diff --git a/src/crystallization/CubicHarmonicBase.cpp b/src/crystallization/CubicHarmonicBase.cpp index 3d793a0dc5..04a07426e1 100644 --- a/src/crystallization/CubicHarmonicBase.cpp +++ b/src/crystallization/CubicHarmonicBase.cpp @@ -27,10 +27,10 @@ using namespace std; -namespace PLMD{ -namespace crystallization{ +namespace PLMD { +namespace crystallization { -void CubicHarmonicBase::registerKeywords( Keywords& keys ){ +void CubicHarmonicBase::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); keys.add("compulsory","NN","6","The n parameter of the switching function "); @@ -38,8 +38,8 @@ void CubicHarmonicBase::registerKeywords( Keywords& keys ){ keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); keys.add("compulsory","PHI","0.0","The Euler rotational angle phi"); keys.add("compulsory","THETA","0.0","The Euler rotational angle theta"); keys.add("compulsory","PSI","0.0","The Euler rotational angle psi"); @@ -47,42 +47,42 @@ void CubicHarmonicBase::registerKeywords( Keywords& keys ){ // Use actionWithDistributionKeywords keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MAX"); keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); - keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); } CubicHarmonicBase::CubicHarmonicBase(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + if(sw.length()>0) { + switchingFunction.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } else { + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } - + double phi, theta, psi; parse("PHI",phi); parse("THETA",theta); parse("PSI",psi); log.printf(" creating rotation matrix with Euler angles phi=%f, theta=%f and psi=%f\n",phi,theta,psi); // Calculate the rotation matrix http://mathworld.wolfram.com/EulerAngles.html rotationmatrix[0][0]=cos(psi)*cos(phi)-cos(theta)*sin(phi)*sin(psi); rotationmatrix[0][1]=cos(psi)*sin(phi)+cos(theta)*cos(phi)*sin(psi); rotationmatrix[0][2]=sin(psi)*sin(theta); - + rotationmatrix[1][0]=-sin(psi)*cos(phi)-cos(theta)*sin(phi)*cos(psi); rotationmatrix[1][1]=-sin(psi)*sin(phi)+cos(theta)*cos(phi)*cos(psi); rotationmatrix[1][2]=cos(psi)*sin(theta); - + rotationmatrix[2][0]=sin(theta)*sin(phi); rotationmatrix[2][1]=-sin(theta)*cos(phi); rotationmatrix[2][2]=cos(theta); - - + + log.printf(" measure crystallinity around central atom. Includes those atoms within %s\n",( switchingFunction.description() ).c_str() ); parseFlag("UNORMALIZED",unormalized); if( unormalized ) log.printf(" output sum of vector functions \n"); @@ -91,57 +91,57 @@ MultiColvarBase(ao) rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); setLinkCellCutoff( switchingFunction.get_dmax() ); // And setup the ActionWithVessel - std::vector all_atoms; setupMultiColvarBase( all_atoms ); + std::vector all_atoms; setupMultiColvarBase( all_atoms ); } double CubicHarmonicBase::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { - double dfunc; Vector rotatedis; - - // Calculate the coordination number - Vector myder, rotateder, fder; unsigned nat=myatoms.getNumberOfAtoms(); - - double d2; - for(unsigned i=1;i der of... value [0], weight[1], x coord [2], y, z... [more magic] - updateActiveAtoms( myatoms ); - if( !unormalized ) myatoms.getUnderlyingMultiValue().quotientRule( 1, 1 ); - return myatoms.getValue(1); // this is equivalent to getting an "atomic" CV + double dfunc; Vector rotatedis; + + // Calculate the coordination number + Vector myder, rotateder, fder; unsigned nat=myatoms.getNumberOfAtoms(); + + double d2; + for(unsigned i=1; i der of... value [0], weight[1], x coord [2], y, z... [more magic] + updateActiveAtoms( myatoms ); + if( !unormalized ) myatoms.getUnderlyingMultiValue().quotientRule( 1, 1 ); + return myatoms.getValue(1); // this is equivalent to getting an "atomic" CV } } diff --git a/src/crystallization/CubicHarmonicBase.h b/src/crystallization/CubicHarmonicBase.h index 8cc2408e85..7986038a4e 100644 --- a/src/crystallization/CubicHarmonicBase.h +++ b/src/crystallization/CubicHarmonicBase.h @@ -26,8 +26,8 @@ #include "multicolvar/AtomValuePack.h" #include "tools/SwitchingFunction.h" -namespace PLMD{ -namespace crystallization{ +namespace PLMD { +namespace crystallization { class CubicHarmonicBase : public multicolvar::MultiColvarBase { private: @@ -43,7 +43,7 @@ class CubicHarmonicBase : public multicolvar::MultiColvarBase { double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; virtual double calculateCubicHarmonic( const Vector& distance, const double& d2, Vector& myder ) const = 0; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; } diff --git a/src/crystallization/Fccubic.cpp b/src/crystallization/Fccubic.cpp index cf27beaf1f..fc1793ab39 100644 --- a/src/crystallization/Fccubic.cpp +++ b/src/crystallization/Fccubic.cpp @@ -28,23 +28,23 @@ using namespace std; -namespace PLMD{ -namespace crystallization{ +namespace PLMD { +namespace crystallization { -//+PLUMEDOC MCOLVAR FCCUBIC +//+PLUMEDOC MCOLVAR FCCUBIC /* Measure how similar the environment around atoms is to that found in a FCC structure. This CV was introduced in this article \cite fcc-michele-1 and again in this article \cite fcc-michele-2 -This CV essentially determines whether the environment around any given atom is similar to that found in +This CV essentially determines whether the environment around any given atom is similar to that found in the FCC structure or not. The function that is used to make this determination is as follows: \f[ -s_i = \frac{ \sum_{i \ne j} \sigma(r_{ij}) \left\{ a\left[ \frac{(x_{ij}y_{ij})^4 + (x_{ij}z_{ij})^4 + (y_{ij}z_{ij})^4}{r_{ij}^8} - \frac{\alpha (x_{ij}y_{ij}z_{ij})^4}{r_{ij}^{12}} \right] + b \right\} }{ \sum_{i \ne j} \sigma(r_{ij}) } +s_i = \frac{ \sum_{i \ne j} \sigma(r_{ij}) \left\{ a\left[ \frac{(x_{ij}y_{ij})^4 + (x_{ij}z_{ij})^4 + (y_{ij}z_{ij})^4}{r_{ij}^8} - \frac{\alpha (x_{ij}y_{ij}z_{ij})^4}{r_{ij}^{12}} \right] + b \right\} }{ \sum_{i \ne j} \sigma(r_{ij}) } \f] -In this expression \f$x_{ij}\f$, \f$y_{ij}\f$ and \f$z_{ij}\f$ are the \f$x\f$, \f$y\f$ and \f$z\f$ components of the vector connecting atom \f$i\f$ to -atom \f$j\f$ and \f$r_{ij}\f$ is the magnitude of this vector. \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that acts on the distance between +In this expression \f$x_{ij}\f$, \f$y_{ij}\f$ and \f$z_{ij}\f$ are the \f$x\f$, \f$y\f$ and \f$z\f$ components of the vector connecting atom \f$i\f$ to +atom \f$j\f$ and \f$r_{ij}\f$ is the magnitude of this vector. \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that acts on the distance between atom \f$i\f$ and atom \f$j\f$ and its inclusion in the numerator and the denominator of the above expression as well as the fact that we are summing over all of the other atoms in the system ensures that we are calculating an average of the function of \f$x_{ij}\f$, \f$y_{ij}\f$ and \f$z_{ij}\f$ for the atoms in the first coordination sphere around atom \f$i\f$. Lastly, \f$\alpha\f$ @@ -52,15 +52,15 @@ is a parameter that can be set by the user, which by default is equal to three. \f[ a = \frac{ 80080}{ 2717 + 16 \alpha} \qquad \textrm{and} \qquad b = \frac{ 16(\alpha - 143) }{2717 + 16\alpha} -\f] +\f] This quantity is once again a multicolvar so you can compute it for multiple atoms using a single PLUMED action and then compute -the average value for the atoms in your system, the number of atoms that have an \f$s_i\f$ value that is more that some target and +the average value for the atoms in your system, the number of atoms that have an \f$s_i\f$ value that is more that some target and so on. Notice also that you can rotate the reference frame if you are using a non-standard unit cell. \par Examples -The following input calculates the FCCUBIC parameter for the 64 atoms in the system +The following input calculates the FCCUBIC parameter for the 64 atoms in the system and then calculates and prints the average value for this quantity. \verbatim @@ -83,14 +83,14 @@ class Fccubic : public CubicHarmonicBase { PLUMED_REGISTER_ACTION(Fccubic,"FCCUBIC") -void Fccubic::registerKeywords( Keywords& keys ){ +void Fccubic::registerKeywords( Keywords& keys ) { CubicHarmonicBase::registerKeywords( keys ); keys.add("compulsory","ALPHA","3.0","The alpha parameter of the angular function"); } Fccubic::Fccubic(const ActionOptions&ao): -Action(ao), -CubicHarmonicBase(ao) + Action(ao), + CubicHarmonicBase(ao) { // Scaling factors such that '1' corresponds to fcc lattice // and '0' corresponds to isotropic (liquid) @@ -110,7 +110,7 @@ double Fccubic::calculateCubicHarmonic( const Vector& distance, const double& d2 double z2 = distance[2]*distance[2]; double z4 = z2*z2; - + double r8 = pow( d2, 4 ); double r12 = pow( d2, 6 ); @@ -119,12 +119,12 @@ double Fccubic::calculateCubicHarmonic( const Vector& distance, const double& d2 double t0 = (x2*y4+x2*z4)/r8-alpha*x2*y4*z4/r12; double t1 = (y2*x4+y2*z4)/r8-alpha*y2*x4*z4/r12; double t2 = (z2*x4+z2*y4)/r8-alpha*z2*x4*y4/r12; - double t3 = (2*tmp-alpha*x4*y4*z4/r12)/d2; - + double t3 = (2*tmp-alpha*x4*y4*z4/r12)/d2; + myder[0]=4*a1*distance[0]*(t0-t3); myder[1]=4*a1*distance[1]*(t1-t3); myder[2]=4*a1*distance[2]*(t2-t3); - + return a1*tmp+b1; } diff --git a/src/crystallization/Gradient.cpp b/src/crystallization/Gradient.cpp index 0c2f7c729f..173d9e5adb 100644 --- a/src/crystallization/Gradient.cpp +++ b/src/crystallization/Gradient.cpp @@ -35,24 +35,24 @@ This command allows you to calculate the collective variable discussed in \cite \par Examples -The input below calculates the gradient of the density of atoms in the manner +The input below calculates the gradient of the density of atoms in the manner described in \cite fede-grad in order to detect whether or not atoms are distributed uniformly along the x-axis of the simulation cell. \verbatim -d1: DENSITY SPECIES=1-50 -s1: GRADIENT ORIGIN=1 DATA=d1 DIR=x NBINS=4 SIGMA=1.0 +d1: DENSITY SPECIES=1-50 +s1: GRADIENT ORIGIN=1 DATA=d1 DIR=x NBINS=4 SIGMA=1.0 PRINT ARG=s1 FILE=colvar \endverbatim The input below calculates the coordination numbers of the 50 atoms in the simulation cell. The gradient of this quantity is then evaluated in the manner described using the equation above -to detect whether the average values of the coordination number are uniformly distributed along the +to detect whether the average values of the coordination number are uniformly distributed along the x-axis of the simulation cell. \verbatim -d2: COORDINATIONNUMBER SPECIES=1-50 SWITCH={RATIONAL R_0=2.0} MORE_THAN={EXP R_0=4.0} -s2: GRADIENT ORIGIN=1 DATA=d2 DIR=x NBINS=4 SIGMA=1.0 +d2: COORDINATIONNUMBER SPECIES=1-50 SWITCH={RATIONAL R_0=2.0} MORE_THAN={EXP R_0=4.0} +s2: GRADIENT ORIGIN=1 DATA=d2 DIR=x NBINS=4 SIGMA=1.0 PRINT ARG=s2 FILE=colvar \endverbatim @@ -61,7 +61,7 @@ PRINT ARG=s2 FILE=colvar PLUMED_REGISTER_ACTION(Gradient,"GRADIENT") -void Gradient::registerKeywords( Keywords& keys ){ +void Gradient::registerKeywords( Keywords& keys ) { VolumeGradientBase::registerKeywords( keys ); keys.add("atoms","ORIGIN","we will use the position of this atom as the origin in our calculation"); keys.add("compulsory","DIR","xyz","the directions in which we are calculating the graident. Should be x, y, z, xy, xz, yz or xyz"); @@ -71,9 +71,9 @@ void Gradient::registerKeywords( Keywords& keys ){ } Gradient::Gradient(const ActionOptions&ao): -Action(ao), -VolumeGradientBase(ao), -nbins(3) + Action(ao), + VolumeGradientBase(ao), + nbins(3) { std::vector atom; parseAtomList("ORIGIN",atom); @@ -82,48 +82,48 @@ nbins(3) std::string direction; parse("DIR",direction); std::vector tbins; parseVector("NBINS",tbins); - for(unsigned i=0;iisDensity() ) vend=2; else if( getPntrToMultiColvar()->getNumberOfQuantities()==2 ) vend=2; - else vend = getPntrToMultiColvar()->getNumberOfQuantities(); + else vend = getPntrToMultiColvar()->getNumberOfQuantities(); nquantities = vend + nbins[0] + nbins[1] + nbins[2]; // Output some nice information std::string functype=getPntrToMultiColvar()->getName(); std::transform( functype.begin(), functype.end(), functype.begin(), tolower ); - log.printf(" calculating gradient of %s in %s direction \n",functype.c_str(), direction.c_str() ); + log.printf(" calculating gradient of %s in %s direction \n",functype.c_str(), direction.c_str() ); log<<" Bibliography:"<getCentralAtomPos( curr ) ); // Note we use the pbc from base multicolvar so that we get numerical derivatives correct - Vector oderiv, fpos = (getPntrToMultiColvar()->getPbc()).realToScaled( cpos ); - + Vector oderiv, fpos = (getPntrToMultiColvar()->getPbc()).realToScaled( cpos ); + Vector deriv; unsigned nbase=vend; std::vector refder(1); Tensor vir; vir.zero(); - for(unsigned idir=0;idir<3;++idir){ - deriv[0]=deriv[1]=deriv[2]=0.0; - double delx = 1.0 / static_cast( nbins[idir] ); - for(unsigned jbead=0;jbeadgetPbc()).realToScaled( deriv ); - // Set and derivatives - refder[0]=-oderiv; // vir = -Tensor(cpos,oderiv); - setNumberInVolume( nbase+jbead, curr, weight, oderiv, vir, refder, outvals ); + for(unsigned idir=0; idir<3; ++idir) { + deriv[0]=deriv[1]=deriv[2]=0.0; + double delx = 1.0 / static_cast( nbins[idir] ); + for(unsigned jbead=0; jbeadgetPbc()).realToScaled( deriv ); + // Set and derivatives + refder[0]=-oderiv; // vir = -Tensor(cpos,oderiv); + setNumberInVolume( nbase+jbead, curr, weight, oderiv, vir, refder, outvals ); // addReferenceAtomDerivatives( nbase+jbead, 0, -oderiv ); // addBoxDerivatives( nbase+jbead, -Tensor(cpos,oderiv) ); - } - nbase += nbins[idir]; + } + nbase += nbins[idir]; } } diff --git a/src/crystallization/Gradient.h b/src/crystallization/Gradient.h index bb3b81bd7b..e639a84587 100644 --- a/src/crystallization/Gradient.h +++ b/src/crystallization/Gradient.h @@ -28,7 +28,7 @@ namespace PLMD { namespace crystallization { class Gradient : public multicolvar::VolumeGradientBase { -friend class GradientVessel; + friend class GradientVessel; private: /// The value of sigma double sigma; @@ -52,7 +52,7 @@ friend class GradientVessel; inline unsigned Gradient::getNumberOfQuantities() const { return nquantities; -} +} } } diff --git a/src/crystallization/GradientVessel.cpp b/src/crystallization/GradientVessel.cpp index d1ad12fe99..a266bbf019 100644 --- a/src/crystallization/GradientVessel.cpp +++ b/src/crystallization/GradientVessel.cpp @@ -46,55 +46,55 @@ class GradientVessel : public vesselbase::FunctionVessel { PLUMED_REGISTER_VESSEL(GradientVessel,"GRADIENT") -void GradientVessel::registerKeywords( Keywords& keys ){ +void GradientVessel::registerKeywords( Keywords& keys ) { vesselbase::FunctionVessel::registerKeywords(keys); } -void GradientVessel::reserveKeyword( Keywords& keys ){ +void GradientVessel::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","GRADIENT","calculate the gradient"); keys.addOutputComponent("gradient","GRADIENT","the gradient"); } GradientVessel::GradientVessel( const vesselbase::VesselOptions& da ) : -FunctionVessel(da) + FunctionVessel(da) { - Gradient* vg=dynamic_cast( getAction() ); - plumed_assert( vg ); isdens=(vg->getPntrToMultiColvar())->isDensity(); - nweights = vg->nbins[0] + vg->nbins[1] + vg->nbins[2]; - if( (vg->getPntrToMultiColvar())->getNumberOfQuantities()>2 ){ - ncomponents = (vg->getPntrToMultiColvar())->getNumberOfQuantities() - 2; - } else { - ncomponents = 1; - } - - starts.push_back(0); - if( vg->nbins[0]>0 ){ - starts.push_back( vg->nbins[0] ); - if( vg->nbins[1]>0 ){ - starts.push_back( vg->nbins[0] + vg->nbins[1] ); - if( vg->nbins[2]>0 ) starts.push_back( nweights ); - } else if( vg->nbins[2]>0 ){ - starts.push_back( nweights ); - } - } else if( vg->nbins[1]>0 ){ - starts.push_back( vg->nbins[1] ); - if( vg->nbins[2]>0 ) starts.push_back( nweights ); - } else if( vg->nbins[2]>0 ){ - starts.push_back( nweights ); - } + Gradient* vg=dynamic_cast( getAction() ); + plumed_assert( vg ); isdens=(vg->getPntrToMultiColvar())->isDensity(); + nweights = vg->nbins[0] + vg->nbins[1] + vg->nbins[2]; + if( (vg->getPntrToMultiColvar())->getNumberOfQuantities()>2 ) { + ncomponents = (vg->getPntrToMultiColvar())->getNumberOfQuantities() - 2; + } else { + ncomponents = 1; + } + + starts.push_back(0); + if( vg->nbins[0]>0 ) { + starts.push_back( vg->nbins[0] ); + if( vg->nbins[1]>0 ) { + starts.push_back( vg->nbins[0] + vg->nbins[1] ); + if( vg->nbins[2]>0 ) starts.push_back( nweights ); + } else if( vg->nbins[2]>0 ) { + starts.push_back( nweights ); + } + } else if( vg->nbins[1]>0 ) { + starts.push_back( vg->nbins[1] ); + if( vg->nbins[2]>0 ) starts.push_back( nweights ); + } else if( vg->nbins[2]>0 ) { + starts.push_back( nweights ); + } } -std::string GradientVessel::value_descriptor(){ +std::string GradientVessel::value_descriptor() { return "the gradient"; } -void GradientVessel::resize(){ - if( getAction()->derivativesAreRequired() ){ - unsigned nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*(ncomponents+1)*nweights ); - getFinalValue()->resizeDerivatives( nder ); +void GradientVessel::resize() { + if( getAction()->derivativesAreRequired() ) { + unsigned nder=getAction()->getNumberOfDerivatives(); + resizeBuffer( (1+nder)*(ncomponents+1)*nweights ); + getFinalValue()->resizeDerivatives( nder ); } else { - resizeBuffer( (ncomponents+1)*nweights ); + resizeBuffer( (ncomponents+1)*nweights ); } } @@ -102,90 +102,90 @@ void GradientVessel::calculate( const unsigned& current, MultiValue& myvals, std unsigned nder; if( getAction()->derivativesAreRequired() ) nder=getAction()->getNumberOfDerivatives(); else nder=0; - unsigned wstart, cstart; if( ncomponents==1 ){ cstart=1; wstart=2; } else { cstart=2; wstart=2+ncomponents; } - - for(unsigned iw=0;iw& buffer ){ +void GradientVessel::finish( const std::vector& buffer ) { std::vector val_interm( ncomponents*nweights ); unsigned nder; if( getAction()->derivativesAreRequired() ) nder=getAction()->getNumberOfDerivatives(); else nder=0; Matrix der_interm( ncomponents*nweights, nder ); der_interm=0; - if( isdens ){ - for(unsigned iw=0;iwderivativesAreRequired() ){ - unsigned wstart = bufstart + 2*iw*(nder+1) + 1; - for(unsigned jder=0;jderderivativesAreRequired() ) { + unsigned wstart = bufstart + 2*iw*(nder+1) + 1; + for(unsigned jder=0; jderderivativesAreRequired() ){ - unsigned wstart = bufstart + xx*(nder+1) + 1; - for(unsigned jc=0;jcderivativesAreRequired() ) { + unsigned wstart = bufstart + xx*(nder+1) + 1; + for(unsigned jc=0; jcderivativesAreRequired() ){ - Value* fval=getFinalValue(); - for(unsigned j=0;jaddDerivative( jder, +2.0*tmp*der_interm( (starts[j+1]-1)*ncomponents + jc, jder) ); - fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); - } - } else { - tmp=val_interm[(bin-1)*ncomponents + jc] - val_interm[bin*ncomponents + jc]; - for(unsigned jder=0;jderaddDerivative( jder, +2.0*tmp*der_interm( (bin-1)*ncomponents + jc, jder) ); - fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); - } - } - diff2+=tmp*tmp; - } + double tmp, diff2=0.0; + + if( getAction()->derivativesAreRequired() ) { + Value* fval=getFinalValue(); + for(unsigned j=0; jaddDerivative( jder, +2.0*tmp*der_interm( (starts[j+1]-1)*ncomponents + jc, jder) ); + fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); + } + } else { + tmp=val_interm[(bin-1)*ncomponents + jc] - val_interm[bin*ncomponents + jc]; + for(unsigned jder=0; jderaddDerivative( jder, +2.0*tmp*der_interm( (bin-1)*ncomponents + jc, jder) ); + fval->addDerivative( jder, -2.0*tmp*der_interm( bin*ncomponents + jc, jder ) ); + } + } + diff2+=tmp*tmp; } - } + } + } } else { - for(unsigned j=0;j #include @@ -43,32 +43,32 @@ Here the sums run over all pairs of molecules. \f$\sigma(r_{ij})\f$ is a \ref sw action on the distance between the centers of molecules \f$i\f$ and \f$j\f$. \f$\theta_{ij}\f$ is then the torsional angle between an orientation vector for molecule \f$i\f$ and molecule \f$j\f$. -This command can be used to calculate the intermolecular torsional angles between the orientations of nearby molecules. The orientation of a -molecule can be calculated by using either the \ref MOLECULES or the \ref PLANES commands. These two commands calculate the orientation of a -bond in the molecule or the orientation of a plane containing three of the molecule's atoms. Furthermore, when we use these commands we think of +This command can be used to calculate the intermolecular torsional angles between the orientations of nearby molecules. The orientation of a +molecule can be calculated by using either the \ref MOLECULES or the \ref PLANES commands. These two commands calculate the orientation of a +bond in the molecule or the orientation of a plane containing three of the molecule's atoms. Furthermore, when we use these commands we think of molecules as objects that lie at a point in space and that have an orientation. This command calculates the torsional angles between the orientations -of these objects. We can then calculates functions of a large number of these torsional angles that measures things such as the number of torsional -angles that are within a particular range. Because it is often useful to only consider the torsional angles between objects that are within a certain +of these objects. We can then calculates functions of a large number of these torsional angles that measures things such as the number of torsional +angles that are within a particular range. Because it is often useful to only consider the torsional angles between objects that are within a certain distance of each other we can, when calculating these sums, perform a weighted sum and use a \ref switchingfunction to ensure that we focus on molecules -that are close together. +that are close together. \par Examples The example input below is necessarily but gives you an idea of what can be achieved using this action. -The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the +The orientations and positions of four molecules are defined using the \ref MOLECULES action as the position of the centeres of mass of the two atoms specified and the direction of the vector connecting the two atoms that were specified. The torsional angles between the molecules are then calculated by the \ref INTERMOLECULARTORSIONS command labelled tt_p. We then compute a \ref HISTOGRAM that shows the distribution that these torsional angles take in the structure. The weight a given torsional angle contributes to this \ref HISTOGRAM is determined using a \ref switchingfunction that acts on the distance -between the two molecules. As such the torsional angles between molecules that are close together contribute a high weight to the -histogram while the torsional angles between molecules that are far apart does not contribute to the histogram. The histogram is +between the two molecules. As such the torsional angles between molecules that are close together contribute a high weight to the +histogram while the torsional angles between molecules that are far apart does not contribute to the histogram. The histogram is averaged over the whole trajectory and output once all the trajectory frames have been read. \verbatim m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 -tt_p: INTERMOLECULARTORSIONS MOLS=m1 SWITCH={RATIONAL R_0=0.25 D_0=2.0 D_MAX=3.0} -htt_p: HISTOGRAM DATA=tt_p GRID_MIN=-pi GRID_MAX=pi BANDWIDTH=0.1 GRID_BIN=200 STRIDE=1 -DUMPGRID GRID=htt_p FILE=myhist.out +tt_p: INTERMOLECULARTORSIONS MOLS=m1 SWITCH={RATIONAL R_0=0.25 D_0=2.0 D_MAX=3.0} +htt_p: HISTOGRAM DATA=tt_p GRID_MIN=-pi GRID_MAX=pi BANDWIDTH=0.1 GRID_BIN=200 STRIDE=1 +DUMPGRID GRID=htt_p FILE=myhist.out \endverbatim */ @@ -89,57 +89,57 @@ class InterMolecularTorsions : public multicolvar::MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return true; } - void retrieveDomain( std::string& min, std::string& max ){ min="-pi"; max="+pi"; } + bool isPeriodic() { return true; } + void retrieveDomain( std::string& min, std::string& max ) { min="-pi"; max="+pi"; } }; PLUMED_REGISTER_ACTION(InterMolecularTorsions,"INTERMOLECULARTORSIONS") -void InterMolecularTorsions::registerKeywords( Keywords& keys ){ +void InterMolecularTorsions::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("atoms","MOLS","The molecules you would like to calculate the torsional angles between. This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); - keys.add("atoms-1","MOLSA","In this version of the input the torsional angles between all pairs of atoms including one atom from MOLA one atom from MOLB will be computed. " - "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); + keys.add("atoms-1","MOLSA","In this version of the input the torsional angles between all pairs of atoms including one atom from MOLA one atom from MOLB will be computed. " + "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); keys.add("atoms-1","MOLSB","In this version of the input the torsional angles between all pairs of atoms including one atom from MOLA one atom from MOLB will be computed. " - "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); + "This should be the label/s of \\ref MOLECULES or \\ref PLANES actions"); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords - keys.remove("LOWMEM"); + keys.remove("LOWMEM"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); } InterMolecularTorsions::InterMolecularTorsions(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { - for(unsigned i=0;igetNumberOfQuantities()!=5 ) error("input multicolvar does not calculate molecular orientations"); + for(unsigned i=0; igetNumberOfQuantities()!=5 ) error("input multicolvar does not calculate molecular orientations"); } // The weight of this does have derivatives weightHasDerivatives=true; // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" calculating number of links with atoms separation of %s\n",( switchingFunction.description() ).c_str() ); std::vector all_atoms; readTwoGroups( "MOLS", "MOLSA", "MOLSB", all_atoms ); setupMultiColvarBase( all_atoms ); setLinkCellCutoff( switchingFunction.get_dmax() ); - for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); } @@ -154,39 +154,39 @@ double InterMolecularTorsions::calculateWeight( const unsigned& taskCode, const Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc ); - if( !doNotCalculateDerivatives() ){ - addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); - addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); - myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); + if( !doNotCalculateDerivatives() ) { + addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); + addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); + myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); } return sw; } double InterMolecularTorsions::compute( const unsigned& tindex, multicolvar::AtomValuePack& myatoms ) const { - Vector v1, v2, dv1, dv2, dconn, conn = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - - // Retrieve vectors - std::vector orient0( 5 ), orient1( 5 ); - getInputData( 0, true, myatoms, orient0 ); - getInputData( 1, true, myatoms, orient1 ); - for(unsigned i=0;i<3;++i){ v1[i]=orient0[2+i]; v2[i]=orient1[2+i]; } - if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; - - // Evaluate angle - Torsion t; double angle = t.compute( v1, conn, v2, dv1, dconn, dv2 ); - for(unsigned i=0;i<3;++i){ orient0[i+2]=dv1[i]; orient1[i+2]=dv2[i]; } - - // And accumulate derivatives - if( !doNotCalculateDerivatives() ){ - MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); - mergeInputDerivatives( 1, 2, orient1.size(), 0, orient0, myder0, myatoms ); - MultiValue& myder1=getInputDerivatives( 1, true, myatoms ); - mergeInputDerivatives( 1, 2, orient0.size(), 1, orient1, myder1, myatoms ); - addAtomDerivatives( 1, 0, -dconn, myatoms ); addAtomDerivatives( 1, 1, dconn, myatoms ); - myatoms.addBoxDerivatives( 1, -extProduct( conn, dconn ) ); - } - - return angle; + Vector v1, v2, dv1, dv2, dconn, conn = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + + // Retrieve vectors + std::vector orient0( 5 ), orient1( 5 ); + getInputData( 0, true, myatoms, orient0 ); + getInputData( 1, true, myatoms, orient1 ); + for(unsigned i=0; i<3; ++i) { v1[i]=orient0[2+i]; v2[i]=orient1[2+i]; } + if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; + + // Evaluate angle + Torsion t; double angle = t.compute( v1, conn, v2, dv1, dconn, dv2 ); + for(unsigned i=0; i<3; ++i) { orient0[i+2]=dv1[i]; orient1[i+2]=dv2[i]; } + + // And accumulate derivatives + if( !doNotCalculateDerivatives() ) { + MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); + mergeInputDerivatives( 1, 2, orient1.size(), 0, orient0, myder0, myatoms ); + MultiValue& myder1=getInputDerivatives( 1, true, myatoms ); + mergeInputDerivatives( 1, 2, orient0.size(), 1, orient1, myder1, myatoms ); + addAtomDerivatives( 1, 0, -dconn, myatoms ); addAtomDerivatives( 1, 1, dconn, myatoms ); + myatoms.addBoxDerivatives( 1, -extProduct( conn, dconn ) ); + } + + return angle; } } diff --git a/src/crystallization/LocalSteinhardt.h b/src/crystallization/LocalSteinhardt.h index a71c6e65ed..c7ced6ab35 100644 --- a/src/crystallization/LocalSteinhardt.h +++ b/src/crystallization/LocalSteinhardt.h @@ -29,31 +29,31 @@ namespace crystallization { template class LocalSteinhardt : public OrientationSphere { public: - static void registerKeywords( Keywords& keys ){ + static void registerKeywords( Keywords& keys ) { OrientationSphere::registerKeywords(keys); } explicit LocalSteinhardt(const ActionOptions& ao): Action(ao), OrientationSphere(ao) { - for(unsigned i=0;i( getBaseMultiColvar(i) ); - if(!mc){ - if( getBaseMultiColvar(i)->getNumberOfBaseMultiColvars()==0 ){ - error("input action is not calculating the correct vectors"); - } - for(unsigned j=0;jgetNumberOfBaseMultiColvars();++j){ - T* mmc=dynamic_cast( getBaseMultiColvar(i)->getBaseMultiColvar(j) ); - if( !mmc ) error("input action is not calculating the correct vectors"); - } - } - } + for(unsigned i=0; i( getBaseMultiColvar(i) ); + if(!mc) { + if( getBaseMultiColvar(i)->getNumberOfBaseMultiColvars()==0 ) { + error("input action is not calculating the correct vectors"); + } + for(unsigned j=0; jgetNumberOfBaseMultiColvars(); ++j) { + T* mmc=dynamic_cast( getBaseMultiColvar(i)->getBaseMultiColvar(j) ); + if( !mmc ) error("input action is not calculating the correct vectors"); + } + } + } } double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { - double dot=0; dconn.zero(); - for(unsigned k=2;k all_atoms; - readAtomsLikeKeyword("MOL",-1,all_atoms); + readAtomsLikeKeyword("MOL",-1,all_atoms); nvectors = std::floor( ablocks.size() / 2 ); if( ablocks.size()%2!=0 && 2*nvectors+1!=ablocks.size() ) error("number of atoms in molecule specification is wrong. Should be two or three."); if( all_atoms.size()==0 ) error("No atoms were specified"); setVectorDimensionality( 3*nvectors ); setupMultiColvarBase( all_atoms ); - if( ablocks.size()==2*nvectors+1 ){ + if( ablocks.size()==2*nvectors+1 ) { std::vector catom_ind(ablocks.size(), false); catom_ind[ablocks.size()-1]=true; setAtomsForCentralAtom( catom_ind ); - } + } } AtomNumber MoleculeOrientation::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const { @@ -97,55 +97,55 @@ AtomNumber MoleculeOrientation::getAbsoluteIndexOfCentralAtom( const unsigned& i } void MoleculeOrientation::calculateVector( multicolvar::AtomValuePack& myatoms ) const { - for(unsigned i=0;i& vals ) const { - for(unsigned i=0;iepsilon ) inorm = 1.0 / norm; - for(unsigned j=0;j<3;++j) vals[2+3*i+j] = inorm*vals[2+3*i+j]; +void MoleculeOrientation::normalizeVector( std::vector& vals ) const { + for(unsigned i=0; iepsilon ) inorm = 1.0 / norm; + for(unsigned j=0; j<3; ++j) vals[2+3*i+j] = inorm*vals[2+3*i+j]; } } void MoleculeOrientation::normalizeVectorDerivatives( MultiValue& myvals ) const { std::vector weight( nvectors ), wdf( nvectors ); - for(unsigned ivec=0;ivecepsilon ){ weight[ivec] = 1.0 / v; wdf[ivec] = 1.0 / ( v*v*v ); } + for(unsigned ivec=0; ivecepsilon ) { weight[ivec] = 1.0 / v; wdf[ivec] = 1.0 / ( v*v*v ); } } - for(unsigned j=0;j all_atoms; - readAtomsLikeKeyword("MOL",-1,all_atoms); + readAtomsLikeKeyword("MOL",-1,all_atoms); if( ablocks.size()!=3 && ablocks.size()!=4 ) error("number of atoms in molecule specification is wrong. Should be three or four."); if( all_atoms.size()==0 ) error("No atoms were specified"); @@ -76,56 +76,56 @@ AtomNumber MoleculePlane::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) return ActionAtomistic::getAbsoluteIndex( ablocks[0][atom_lab[iatom].second] ); } -void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ) const { - Vector d1, d2, cp; - if( myatoms.getNumberOfAtoms()==3 ){ - d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); - d2=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); +void MoleculePlane::calculateVector( multicolvar::AtomValuePack& myatoms ) const { + Vector d1, d2, cp; + if( myatoms.getNumberOfAtoms()==3 ) { + d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); + d2=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); } else { - d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); - d2=getSeparation( myatoms.getPosition(2), myatoms.getPosition(3) ); + d1=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); + d2=getSeparation( myatoms.getPosition(2), myatoms.getPosition(3) ); } cp = crossProduct( d1, d2 ); addAtomDerivatives( 2, 0, crossProduct( Vector(-1.0,0,0), d2 ), myatoms ); - if( myatoms.getNumberOfAtoms()==3 ){ - addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ) + crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); - addAtomDerivatives( 2, 2, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); + if( myatoms.getNumberOfAtoms()==3 ) { + addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ) + crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); + addAtomDerivatives( 2, 2, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); } else { - addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ), myatoms ); - addAtomDerivatives( 2, 2, crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); - addAtomDerivatives( 2, 3, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); + addAtomDerivatives( 2, 1, crossProduct( Vector(+1.0,0,0), d2 ), myatoms ); + addAtomDerivatives( 2, 2, crossProduct( Vector(-1.0,0,0), d1 ), myatoms ); + addAtomDerivatives( 2, 3, crossProduct( Vector(+1.0,0,0), d1 ), myatoms ); } myatoms.addBoxDerivatives( 2, Tensor(d1,crossProduct(Vector(+1.0,0,0), d2)) + Tensor( d2, crossProduct(Vector(-1.0,0,0), d1)) ); myatoms.addValue( 2, cp[0] ); addAtomDerivatives( 3, 0, crossProduct( Vector(0,-1.0,0), d2 ), myatoms ); - if( myatoms.getNumberOfAtoms()==3 ){ - addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ) + crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); - addAtomDerivatives( 3, 2, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); + if( myatoms.getNumberOfAtoms()==3 ) { + addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ) + crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); + addAtomDerivatives( 3, 2, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); } else { - addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ), myatoms ); - addAtomDerivatives( 3, 2, crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); - addAtomDerivatives( 3, 3, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); + addAtomDerivatives( 3, 1, crossProduct( Vector(0,+1.0,0), d2 ), myatoms ); + addAtomDerivatives( 3, 2, crossProduct( Vector(0,-1.0,0), d1 ), myatoms ); + addAtomDerivatives( 3, 3, crossProduct( Vector(0,+1.0,0), d1 ), myatoms ); } myatoms.addBoxDerivatives( 3, Tensor(d1,crossProduct(Vector(0,+1.0,0), d2)) + Tensor( d2, crossProduct(Vector(0,-1.0,0), d1)) ); myatoms.addValue( 3, cp[1] ); addAtomDerivatives( 4, 0, crossProduct( Vector(0,0,-1.0), d2 ), myatoms ); - if( myatoms.getNumberOfAtoms()==3 ){ - addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,+1.0), d2 ) + crossProduct( Vector(0,0,-1.0), d1 ), myatoms ); - addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); + if( myatoms.getNumberOfAtoms()==3 ) { + addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,+1.0), d2 ) + crossProduct( Vector(0,0,-1.0), d1 ), myatoms ); + addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); } else { - addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,-1.0), d2 ), myatoms); - addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,-1.0), d1 ), myatoms); - addAtomDerivatives( 4, 3, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); + addAtomDerivatives( 4, 1, crossProduct( Vector(0,0,-1.0), d2 ), myatoms); + addAtomDerivatives( 4, 2, crossProduct( Vector(0,0,-1.0), d1 ), myatoms); + addAtomDerivatives( 4, 3, crossProduct( Vector(0,0,+1.0), d1 ), myatoms); } myatoms.addBoxDerivatives( 4, Tensor(d1,crossProduct(Vector(0,0,+1.0), d2)) + Tensor( d2, crossProduct(Vector(0,0,-1.0), d1)) ); myatoms.addValue( 4, cp[2] ); } // Vector MoleculePlane::getCentralAtom(){ -// Vector com; com.zero(); +// Vector com; com.zero(); // if( getNAtoms()==3 ){ // com+=(1.0/3.0)*getPosition(0); // com+=(1.0/3.0)*getPosition(1); diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp index b17a2821cd..8d6fa46d12 100644 --- a/src/crystallization/OrientationSphere.cpp +++ b/src/crystallization/OrientationSphere.cpp @@ -25,40 +25,40 @@ using namespace std; -namespace PLMD{ +namespace PLMD { namespace crystallization { -void OrientationSphere::registerKeywords( Keywords& keys ){ +void OrientationSphere::registerKeywords( Keywords& keys ) { multicolvar::MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords - keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); + keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); + keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("LOWEST"); keys.use("HIGHEST"); } OrientationSphere::OrientationSphere(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { if( getNumberOfBaseMultiColvars()>1 ) warning("not sure if orientation sphere works with more than one base multicolvar - check numerical derivatives"); // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); - } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + if(sw.length()>0) { + switchingFunction.set(sw,errors); + } else { + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" degree of overlap in orientation between central molecule and those within %s\n",( switchingFunction.description() ).c_str() ); log<<" Bibliography "<getNumberOfQuantities(); - std::vector catom_orient( ncomponents ), this_orient( ncomponents ); - std::vector this_der( ncomponents ), catom_der( ncomponents ); - - getInputData( 0, true, myatoms, catom_orient ); - MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); - - for(unsigned i=1;igetNumberOfQuantities(); + std::vector catom_orient( ncomponents ), this_orient( ncomponents ); + std::vector this_der( ncomponents ), catom_der( ncomponents ); + + getInputData( 0, true, myatoms, catom_orient ); + MultiValue& myder0=getInputDerivatives( 0, true, myatoms ); + + for(unsigned i=1; iepsilon ){ rdenom = 1.0 / denom; } - else { plumed_assert(fabs(value)epsilon ) { rdenom = 1.0 / denom; } + else { plumed_assert(fabs(value)& vec1, const std::vector& vec2, + virtual double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const = 0; virtual double calculateCoordinationPrefactor( const double& coord, double& df ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; inline diff --git a/src/crystallization/Q3.cpp b/src/crystallization/Q3.cpp index 25a5b77bd1..6c3aeedc2f 100644 --- a/src/crystallization/Q3.cpp +++ b/src/crystallization/Q3.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "Steinhardt.h" -#include "LocalSteinhardt.h" +#include "LocalSteinhardt.h" #include "core/ActionRegister.h" //+PLUMEDOC MCOLVAR Q3 @@ -28,7 +28,7 @@ Calculate 3rd order Steinhardt parameters. The 3rd order Steinhardt parameters allow us to measure the degree to which the first coordination shell -around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are +around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are calculated using the following formula: \f[ @@ -36,9 +36,9 @@ q_{3m}(i) = \frac{\sum_j \sigma( r_{ij} ) Y_{3m}(\mathbf{r}_{ij}) }{\sum_j \sigm \f] where \f$Y_{3m}\f$ is one of the 3rd order spherical harmonics so \f$m\f$ is a number that runs from \f$-3\f$ to -\f$+3\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +\f$+3\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The Steinhardt parameters can be used to measure the degree of order in the system in a variety of different ways. The simplest way of measuring whether or not the coordination sphere is ordered is to simply take the norm of the above vector i.e. @@ -47,11 +47,11 @@ simplest way of measuring whether or not the coordination sphere is ordered is t Q_3(i) = \sqrt{ \sum_{m=-3}^3 q_{3m}(i)^{*} q_{3m}(i) } \f] -This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when +This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when the keywords LESS_THAN, MIN, MAX, HISTOGRAM, MEAN and so on are used with this colvar it is the distribution of these normed quantities -that is investigated. +that is investigated. -Other measures of order can be taken by averaging the components of the individual \f$q_3\f$ vectors individually or by taking dot products of +Other measures of order can be taken by averaging the components of the individual \f$q_3\f$ vectors individually or by taking dot products of the \f$q_{3}\f$ vectors on adjacent atoms. More information on these variables can be found in the documentation for \ref LOCAL_Q3, \ref LOCAL_AVERAGE and \ref NLINKS. @@ -75,7 +75,7 @@ PRINT ARG=q3.* FILE=colvar The following command could be used to measure the Q3 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input -with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q3 paramter is calculated and output to a +with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q3 paramter is calculated and output to a file called colvar \verbatim @@ -92,12 +92,12 @@ Calculate the local degree of order around an atoms by taking the average dot pr on the atoms in the first coordination sphere. The \ref Q3 command allows one to calculate one complex vectors for each of the atoms in your system that describe the degree of order in the coordination sphere -around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a -measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is +around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a +measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is examining nucleation say only the order parameters for those atoms in the nucleus will change significantly when the nucleus forms. The order parameters for the atoms in the surrounding liquid will remain pretty much the same. As such if one models a small nucleus embedded in a very large amount of solution/melt any -change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only -because the number of atoms is relatively small. +change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only +because the number of atoms is relatively small. When the average \ref Q3 parameter is used to bias the dynamics a problems can occur. These averaged coordinates cannot distinguish between the correct, @@ -116,17 +116,17 @@ biased dynamics what is really required is an order parameter that measures: - Whether or not the atoms that are ordered are clustered together in a crystalline nucleus \ref LOCAL_AVERAGE and \ref NLINKS are variables that can be combined with the Steinhardt parameteters allow to calculate variables that satisfy these requirements. -LOCAL_Q3 is another variable that can be used in these sorts of calculations. The LOCAL_Q3 parameter for a particular atom is a number that measures the extent to -which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following +LOCAL_Q3 is another variable that can be used in these sorts of calculations. The LOCAL_Q3 parameter for a particular atom is a number that measures the extent to +which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following quantity for each of the atoms in the system: \f[ s_i = \frac{ \sum_j \sigma( r_{ij} ) \sum_{m=-3}^3 q_{3m}^{*}(i)q_{3m}(j) }{ \sum_j \sigma( r_{ij} ) } \f] - + where \f$q_{3m}(i)\f$ and \f$q_{3m}(j)\f$ are the 3rd order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes complex conjugation. The function -\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set +\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The sum in the numerator of this expression is the dot product of the Steinhardt parameters for atoms \f$i\f$ and \f$j\f$ and thus measures the degree to which the orientations of these adjacent atoms is correlated. @@ -178,13 +178,13 @@ PLUMED_REGISTER_ACTION(Q3,"Q3") typedef LocalSteinhardt LOCAL_Q3; PLUMED_REGISTER_ACTION(LOCAL_Q3,"LOCAL_Q3") -void Q3::registerKeywords( Keywords& keys ){ +void Q3::registerKeywords( Keywords& keys ) { Steinhardt::registerKeywords( keys ); } Q3::Q3(const ActionOptions& ao ): -Action(ao), -Steinhardt(ao) + Action(ao), + Steinhardt(ao) { setAngularMomentum(3); @@ -200,10 +200,10 @@ Steinhardt(ao) // Legendre polynomial coefficients of order three - coeff_poly.resize( 4 ); - coeff_poly[0]=0.0; + coeff_poly.resize( 4 ); + coeff_poly[0]=0.0; coeff_poly[1]=-1.5; - coeff_poly[2]=0.0; + coeff_poly[2]=0.0; coeff_poly[3]=2.5; } diff --git a/src/crystallization/Q4.cpp b/src/crystallization/Q4.cpp index 6be9c9b470..fa76b0d10e 100644 --- a/src/crystallization/Q4.cpp +++ b/src/crystallization/Q4.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "Steinhardt.h" -#include "LocalSteinhardt.h" +#include "LocalSteinhardt.h" #include "core/ActionRegister.h" //+PLUMEDOC MCOLVAR Q4 @@ -28,7 +28,7 @@ Calculate 4th order Steinhardt parameters. The 4th order Steinhardt parameters allow us to measure the degree to which the first coordination shell -around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are +around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are calculated using the following formula: \f[ @@ -36,9 +36,9 @@ q_{4m}(i) = \frac{\sum_j \sigma( r_{ij} ) Y_{4m}(\mathbf{r}_{ij}) }{\sum_j \sigm \f] where \f$Y_{4m}\f$ is one of the 4th order spherical harmonics so \f$m\f$ is a number that runs from \f$-4\f$ to -\f$+4\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +\f$+4\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The Steinhardt parameters can be used to measure the degree of order in the system in a variety of different ways. The simplest way of measuring whether or not the coordination sphere is ordered is to simply take the norm of the above vector i.e. @@ -47,11 +47,11 @@ simplest way of measuring whether or not the coordination sphere is ordered is t Q_4(i) = \sqrt{ \sum_{m=-4}^4 q_{4m}(i)^{*} q_{4m}(i) } \f] -This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when +This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when the keywords LESS_THAN, MIN, MAX, HISTOGRAM, MEAN and so on are used with this colvar it is the distribution of these normed quantities -that is investigated. +that is investigated. -Other measures of order can be taken by averaging the components of the individual \f$q_4\f$ vectors individually or by taking dot products of +Other measures of order can be taken by averaging the components of the individual \f$q_4\f$ vectors individually or by taking dot products of the \f$q_{4}\f$ vectors on adjacent atoms. More information on these variables can be found in the documentation for \ref LOCAL_Q4, \ref LOCAL_AVERAGE and \ref NLINKS. @@ -75,7 +75,7 @@ PRINT ARG=q4.* FILE=colvar The following command could be used to measure the Q4 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input -with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q4 paramter is calculated and output to a +with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q4 paramter is calculated and output to a file called colvar \verbatim @@ -92,12 +92,12 @@ Calculate the local degree of order around an atoms by taking the average dot pr on the atoms in the first coordination sphere. The \ref Q4 command allows one to calculate one complex vectors for each of the atoms in your system that describe the degree of order in the coordination sphere -around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a -measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is +around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a +measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is examining nucleation say only the order parameters for those atoms in the nucleus will change significantly when the nucleus forms. The order parameters for the atoms in the surrounding liquid will remain pretty much the same. As such if one models a small nucleus embedded in a very large amount of solution/melt any -change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only -because the number of atoms is relatively small. +change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only +because the number of atoms is relatively small. When the average \ref Q4 parameter is used to bias the dynamics a problems can occur. These averaged coordinates cannot distinguish between the correct, @@ -116,17 +116,17 @@ biased dynamics what is really required is an order parameter that measures: - Whether or not the atoms that are ordered are clustered together in a crystalline nucleus \ref LOCAL_AVERAGE and \ref NLINKS are variables that can be combined with the Steinhardt parameteters allow to calculate variables that satisfy these requirements. -LOCAL_Q4 is another variable that can be used in these sorts of calculations. The LOCAL_Q4 parameter for a particular atom is a number that measures the extent to -which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following +LOCAL_Q4 is another variable that can be used in these sorts of calculations. The LOCAL_Q4 parameter for a particular atom is a number that measures the extent to +which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following quantity for each of the atoms in the system: \f[ s_i = \frac{ \sum_j \sigma( r_{ij} ) \sum_{m=-4}^4 q_{4m}^{*}(i)q_{4m}(j) }{ \sum_j \sigma( r_{ij} ) } \f] - + where \f$q_{4m}(i)\f$ and \f$q_{4m}(j)\f$ are the 4th order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes complex conjugation. The function -\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set +\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The sum in the numerator of this expression is the dot product of the Steinhardt parameters for atoms \f$i\f$ and \f$j\f$ and thus measures the degree to which the orientations of these adjacent atoms is correlated. @@ -177,13 +177,13 @@ PLUMED_REGISTER_ACTION(Q4,"Q4") typedef LocalSteinhardt LOCAL_Q4; PLUMED_REGISTER_ACTION(LOCAL_Q4,"LOCAL_Q4") -void Q4::registerKeywords( Keywords& keys ){ +void Q4::registerKeywords( Keywords& keys ) { Steinhardt::registerKeywords( keys ); } Q4::Q4(const ActionOptions& ao ): -Action(ao), -Steinhardt(ao) + Action(ao), + Steinhardt(ao) { setAngularMomentum(4); @@ -194,10 +194,10 @@ Steinhardt(ao) normaliz[3] = -sqrt( ( 9.0*1) / (4.0*pi*5040.0) ); normaliz[4] = sqrt( (9.0*1) / (4.0*pi*40320.0) ); - coeff_poly.resize( 5 ); + coeff_poly.resize( 5 ); coeff_poly[0]=0.375; coeff_poly[1]=0.0; coeff_poly[2]=-3.75; coeff_poly[3]=0.0; - coeff_poly[4]=4.375; + coeff_poly[4]=4.375; } } diff --git a/src/crystallization/Q6.cpp b/src/crystallization/Q6.cpp index e473d8b65f..447b0e1cb4 100644 --- a/src/crystallization/Q6.cpp +++ b/src/crystallization/Q6.cpp @@ -28,7 +28,7 @@ Calculate 6th order Steinhardt parameters. The 6th order Steinhardt parameters allow us to measure the degree to which the first coordination shell -around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are +around an atom is ordered. The Steinhardt parameter for atom, \f$i\f$ is complex vector whose components are calculated using the following formula: \f[ @@ -36,9 +36,9 @@ q_{6m}(i) = \frac{\sum_j \sigma( r_{ij} ) Y_{6m}(\mathbf{r}_{ij}) }{\sum_j \sigm \f] where \f$Y_{6m}\f$ is one of the 6th order spherical harmonics so \f$m\f$ is a number that runs from \f$-6\f$ to -\f$+6\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +\f$+6\f$. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The Steinhardt parameters can be used to measure the degree of order in the system in a variety of different ways. The simplest way of measuring whether or not the coordination sphere is ordered is to simply take the norm of the above vector i.e. @@ -47,11 +47,11 @@ simplest way of measuring whether or not the coordination sphere is ordered is t Q_6(i) = \sqrt{ \sum_{m=-6}^6 q_{6m}(i)^{*} q_{6m}(i) } \f] -This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when +This norm is small when the coordination shell is disordered and larger when the coordination shell is ordered. Furthermore, when the keywords LESS_THAN, MIN, MAX, HISTOGRAM, MEAN and so on are used with this colvar it is the distribution of these normed quantities -that is investigated. +that is investigated. -Other measures of order can be taken by averaging the components of the individual \f$q_6\f$ vectors individually or by taking dot products of +Other measures of order can be taken by averaging the components of the individual \f$q_6\f$ vectors individually or by taking dot products of the \f$q_{6}\f$ vectors on adjacent atoms. More information on these variables can be found in the documentation for \ref LOCAL_Q6, \ref LOCAL_AVERAGE and \ref NLINKS. @@ -75,7 +75,7 @@ PRINT ARG=q6.* FILE=colvar The following command could be used to measure the Q6 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input -with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q6 paramter is calculated and output to a +with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q6 paramter is calculated and output to a file called colvar \verbatim @@ -92,12 +92,12 @@ Calculate the local degree of order around an atoms by taking the average dot pr on the atoms in the first coordination sphere. The \ref Q6 command allows one to calculate one complex vectors for each of the atoms in your system that describe the degree of order in the coordination sphere -around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a -measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is +around a particular atom. The difficulty with these vectors comes when combining the order parameters from all of the individual atoms/molecules so as to get a +measure of the global degree of order for the system. The simplest way of doing this - calculating the average Steinhardt parameter - can be problematic. If one is examining nucleation say only the order parameters for those atoms in the nucleus will change significantly when the nucleus forms. The order parameters for the atoms in the surrounding liquid will remain pretty much the same. As such if one models a small nucleus embedded in a very large amount of solution/melt any -change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only -because the number of atoms is relatively small. +change in the average order parameter will be negligible. Substantial changes in the value of this average can be observed in simulations of nucleation but only +because the number of atoms is relatively small. When the average \ref Q6 parameter is used to bias the dynamics a problems can occur. These averaged coordinates cannot distinguish between the correct, @@ -116,17 +116,17 @@ biased dynamics what is really required is an order parameter that measures: - Whether or not the atoms that are ordered are clustered together in a crystalline nucleus \ref LOCAL_AVERAGE and \ref NLINKS are variables that can be combined with the Steinhardt parameteters allow to calculate variables that satisfy these requirements. -LOCAL_Q6 is another variable that can be used in these sorts of calculations. The LOCAL_Q6 parameter for a particular atom is a number that measures the extent to -which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following +LOCAL_Q6 is another variable that can be used in these sorts of calculations. The LOCAL_Q6 parameter for a particular atom is a number that measures the extent to +which the orientation of the atoms in the first coordination sphere of an atom match the orientation of the central atom. It does this by calculating the following quantity for each of the atoms in the system: \f[ s_i = \frac{ \sum_j \sigma( r_{ij} ) \sum_{m=-6}^6 q_{6m}^{*}(i)q_{6m}(j) }{ \sum_j \sigma( r_{ij} ) } \f] - -where \f$q_{6m}(i)\f$ and \f$q_{6m}(j)\f$ are the 6th order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes + +where \f$q_{6m}(i)\f$ and \f$q_{6m}(j)\f$ are the 6th order Steinhardt vectors calculated for atom \f$i\f$ and atom \f$j\f$ respectively and the asterix denotes complex conjugation. The function -\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set +\f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. The parameters of this function should be set so that it the function is equal to one when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. The sum in the numerator of this expression is the dot product of the Steinhardt parameters for atoms \f$i\f$ and \f$j\f$ and thus measures the degree to which the orientations of these adjacent atoms is correlated. @@ -177,13 +177,13 @@ PLUMED_REGISTER_ACTION(Q6,"Q6") typedef LocalSteinhardt LOCAL_Q6; PLUMED_REGISTER_ACTION(LOCAL_Q6,"LOCAL_Q6") -void Q6::registerKeywords( Keywords& keys ){ +void Q6::registerKeywords( Keywords& keys ) { Steinhardt::registerKeywords( keys ); } Q6::Q6(const ActionOptions& ao ): -Action(ao), -Steinhardt(ao) + Action(ao), + Steinhardt(ao) { setAngularMomentum(6); @@ -196,11 +196,11 @@ Steinhardt(ao) normaliz[5] = -sqrt( (13.0*1) / (4.0*pi*39916800) ); normaliz[6] = sqrt( (13.0*1) / (4.0*pi*479001600) ); - coeff_poly.resize( 7 ); + coeff_poly.resize( 7 ); coeff_poly[0]=-0.3125; coeff_poly[1]=0.0; coeff_poly[2]=6.5625; coeff_poly[3]=0.0; coeff_poly[4]=-19.6875; coeff_poly[5]=0.0; - coeff_poly[6]=14.4375; + coeff_poly[6]=14.4375; } } diff --git a/src/crystallization/SMAC.cpp b/src/crystallization/SMAC.cpp index 18e9a2ab05..ce83df7380 100644 --- a/src/crystallization/SMAC.cpp +++ b/src/crystallization/SMAC.cpp @@ -28,40 +28,40 @@ /* Calculate a variant on the SMAC collective variable discussed in \cite smac-paper -The SMAC collective variable can be used to study the formation of molecular solids -from either the melt or from solution. The idea behind this variable is that what -differentiates a molecular solid from a molecular liquid is an alignment of -internal vectors in neighboring molecules. In other words, the relative orientation +The SMAC collective variable can be used to study the formation of molecular solids +from either the melt or from solution. The idea behind this variable is that what +differentiates a molecular solid from a molecular liquid is an alignment of +internal vectors in neighboring molecules. In other words, the relative orientation of neighboring molecules is no longer random as it is in a liquid. In a solid particular torsional angles between molecules are preferred. As such this CV calculates the following average: \f[ s_i = \frac{ \left\{ 1 - \psi\left[ \sum_{j \ne i} \sigma(r_{ij}) \right] \right\} \sum_{j \ne i} \sigma(r_{ij}) \sum_n K_n(\theta_{ij}) }{ \sum_{j \ne i} \sigma(r_{ij}) } -\f] +\f] In this expression \f$r_{ij}\f$ is the distance between molecule \f$i\f$ and molecule \f$j\f$ and \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that acts on this distance. By including this switching function in the second summation in the -numerator and in the denominator we are thus ensuring that we calculate an average over the molecules in the first coordination -sphere of molecule \f$i\f$. All molecules in higher coordination sphere will essentially contribute zero to the sums in the -above expression because their \f$\sigma(r_{ij})\f$ will be very small. \f$\psi\f$ is also a switching function. The term +numerator and in the denominator we are thus ensuring that we calculate an average over the molecules in the first coordination +sphere of molecule \f$i\f$. All molecules in higher coordination sphere will essentially contribute zero to the sums in the +above expression because their \f$\sigma(r_{ij})\f$ will be very small. \f$\psi\f$ is also a switching function. The term including \f$\psi\f$ in the numerator is there to ensure that only those molecules that are attached to a reasonably large number of molecules. It is important to include this "more than" switching function when you are simulating nucleation -from solution with this CV. Lastly, the $K_n functions are \ref kernelfunctions that take the torsion angle, \f$\theta_{ij}\f$, between the +from solution with this CV. Lastly, the $K_n functions are \ref kernelfunctions that take the torsion angle, \f$\theta_{ij}\f$, between the internal orientation vectors for molecules \f$i\f$ and \f$j\f$ as input. These kernel functions should be set so that they are equal to one when the relative orientation of the moleclues are as they are in the solid and equal to zero otherwise. The final \f$s_i\f$ quantity thus measures whether (on average) the molecules in the first coordination sphere around molecule \f$i\f$ -are oriented as they would be in the solid. Furthermore, this Action is a multicolvar so you can calculate the \f$s_i\f$ values -for all the molecules in your system simultaneously and then determine the average, the number less than and so on. +are oriented as they would be in the solid. Furthermore, this Action is a multicolvar so you can calculate the \f$s_i\f$ values +for all the molecules in your system simultaneously and then determine the average, the number less than and so on. \par Examples -In the example below the orientation of the molecules in the system is determined by calculating the +In the example below the orientation of the molecules in the system is determined by calculating the vector that connects a pair of atoms. SMAC is then used to determine whether the molecules are sitting -in a solid or liquid like environment. We can determine whether the environment is solid or liquid like because in the solid the torsional angle between +in a solid or liquid like environment. We can determine whether the environment is solid or liquid like because in the solid the torsional angle between the bond vectors on adjacent molecules is close to 0 or \f$\pi\f$. The final quantity that is output to the colvar file measures the number of molecules that have a SMAC parameter that is greater than 0.7. N.B. By using -the indices of three atoms for each of the MOL keywords below we are telling PLUMED to use the first two +the indices of three atoms for each of the MOL keywords below we are telling PLUMED to use the first two numbers to determine the orientation of the molecule that will ultimately be used when calculating the \f$\theta_{ij}\f$ terms in the formula above. The atom with the third index meanwhile is used when we calculate \f$r_{ij}\f$. @@ -79,8 +79,8 @@ LABEL=m3 ... MOLECULES SMAC ... - SPECIES=m3 LOWMEM - KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} + SPECIES=m3 LOWMEM + KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} SWITCH={RATIONAL R_0=0.6} MORE_THAN={RATIONAL R_0=0.7} SWITCH_COORD={EXP R_0=4} LABEL=s2 ... SMAC @@ -89,7 +89,7 @@ PRINT ARG=s2.* FILE=colvar \endverbatim This second example works in a way that is very similar to the previous command. Now, however, -the orientation of the molecules is determined by finding the plane that contains the positions +the orientation of the molecules is determined by finding the plane that contains the positions of three atoms. \verbatim @@ -106,9 +106,9 @@ VMEAN LABEL=m3 ... PLANES -SMAC ... - SPECIES=m3 LOWMEM - KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} +SMAC ... + SPECIES=m3 LOWMEM + KERNEL1={GAUSSIAN CENTER=0 SIGMA=0.480} KERNEL2={GAUSSIAN CENTER=pi SIGMA=0.480} SWITCH={RATIONAL R_0=0.6} MORE_THAN={RATIONAL R_0=0.7} SWITCH_COORD={EXP R_0=3.0} LABEL=s2 ... SMAC @@ -127,70 +127,70 @@ class SMAC : public OrientationSphere { std::vector kernels; SwitchingFunction coord_switch; public: - static void registerKeywords( Keywords& keys ); - explicit SMAC(const ActionOptions& ao); - double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, + static void registerKeywords( Keywords& keys ); + explicit SMAC(const ActionOptions& ao); + double computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const ; double calculateCoordinationPrefactor( const double& coord, double& df ) const ; }; PLUMED_REGISTER_ACTION(SMAC,"SMAC") -void SMAC::registerKeywords( Keywords& keys ){ +void SMAC::registerKeywords( Keywords& keys ) { OrientationSphere::registerKeywords(keys); keys.add("numbered","KERNEL","The kernels used in the function of the angle"); keys.add("compulsory","SWITCH_COORD","This keyword is used to define the coordination switching function."); - keys.reset_style("KERNEL","compulsory"); + keys.reset_style("KERNEL","compulsory"); } SMAC::SMAC(const ActionOptions& ao): -Action(ao), -OrientationSphere(ao) + Action(ao), + OrientationSphere(ao) { - if( mybasemulticolvars.size()==0 ) error("SMAC must take multicolvar as input"); - for(unsigned i=0;igetNumberOfQuantities()-2)%3!=0 ) error("SMAC is only possible with three dimensional vectors"); - } - - std::string kernelinpt; - for(int i=1;;i++){ - if( !parseNumbered("KERNEL",i,kernelinpt) ) break; - KernelFunctions mykernel( kernelinpt, false ); - kernels.push_back( mykernel ); - } - if( kernels.size()==0 ) error("no kernels defined"); - - std::string sw, errors; parse("SWITCH_COORD",sw); - if(sw.length()==0) error("SWITCH_COORD keyword is missing"); - coord_switch.set(sw,errors); - if(errors.length()>0) error("the following errors were found in input to SWITCH_COORD : " + errors ); + if( mybasemulticolvars.size()==0 ) error("SMAC must take multicolvar as input"); + for(unsigned i=0; igetNumberOfQuantities()-2)%3!=0 ) error("SMAC is only possible with three dimensional vectors"); + } + + std::string kernelinpt; + for(int i=1;; i++) { + if( !parseNumbered("KERNEL",i,kernelinpt) ) break; + KernelFunctions mykernel( kernelinpt, false ); + kernels.push_back( mykernel ); + } + if( kernels.size()==0 ) error("no kernels defined"); + + std::string sw, errors; parse("SWITCH_COORD",sw); + if(sw.length()==0) error("SWITCH_COORD keyword is missing"); + coord_switch.set(sw,errors); + if(errors.length()>0) error("the following errors were found in input to SWITCH_COORD : " + errors ); } -double SMAC::computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, +double SMAC::computeVectorFunction( const Vector& conn, const std::vector& vec1, const std::vector& vec2, Vector& dconn, std::vector& dvec1, std::vector& dvec2 ) const { unsigned nvectors = ( vec1.size() - 2 ) / 3; plumed_assert( (vec1.size()-2)%3==0 ); std::vector dv1(nvectors), dv2(nvectors), tdconn(nvectors); Torsion t; std::vector v1(nvectors), v2(nvectors); - std::vector pos; for(unsigned i=0;isetDomain( "-pi", "pi" ); } - - for(unsigned j=0;jset( angle ); + std::vector pos; for(unsigned i=0; isetDomain( "-pi", "pi" ); } + + for(unsigned j=0; jset( angle ); } - double ans=0; std::vector deriv( nvectors ), df( nvectors, 0 ); - for(unsigned i=0;i deriv( nvectors ), df( nvectors, 0 ); + for(unsigned i=0; i0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" Steinhardt parameter of central atom and those within %s\n",( switchingFunction.description() ).c_str() ); log<<" Bibliography "< all_atoms; setupMultiColvarBase( all_atoms ); } -void Steinhardt::setAngularMomentum( const unsigned& ang ){ +void Steinhardt::setAngularMomentum( const unsigned& ang ) { tmom=ang; setVectorDimensionality( 2*(2*ang + 1) ); -} +} void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { - double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; + double dfunc, dpoly_ass, md, tq6, itq6, real_z, imag_z; Vector dz, myrealvec, myimagvec, real_dz, imag_dz; // The square root of -1 std::complex ii( 0.0, 1.0 ), dp_x, dp_y, dp_z; - unsigned ncomp=2*tmom+1; + unsigned ncomp=2*tmom+1; double sw, poly_ass, d2, dlen; std::complex powered; - for(unsigned i=1;i com1( distance[0]/dlen ,distance[1]/dlen ); - - // Do stuff for all other m values - for(unsigned m=1;m<=tmom;++m){ - // Calculate Legendre Polynomial - poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass ); - // Calculate powe of complex number - powered=pow(com1,m-1); md=static_cast(m); - // Real and imaginary parts of z - real_z = real(com1*powered); imag_z = imag(com1*powered ); - - // Calculate steinhardt parameter - tq6=poly_ass*real_z; // Real part of steinhardt parameter - itq6=poly_ass*imag_z; // Imaginary part of steinhardt parameter - - // Derivatives wrt ( x/r + iy )^m - dp_x = md*powered*( (1.0/dlen)-(distance[0]*distance[0])/dlen3-ii*(distance[0]*distance[1])/dlen3 ); - dp_y = md*powered*( ii*(1.0/dlen)-(distance[0]*distance[1])/dlen3-ii*(distance[1]*distance[1])/dlen3 ); - dp_z = md*powered*( -(distance[0]*distance[2])/dlen3-ii*(distance[1]*distance[2])/dlen3 ); - - // Derivatives of real and imaginary parts of above - real_dz[0] = real( dp_x ); real_dz[1] = real( dp_y ); real_dz[2] = real( dp_z ); - imag_dz[0] = imag( dp_x ); imag_dz[1] = imag( dp_y ); imag_dz[2] = imag( dp_z ); - - // Complete derivative of steinhardt parameter - myrealvec = (+sw)*dpoly_ass*real_z*dz + (+dfunc)*distance*tq6 + (+sw)*poly_ass*real_dz; - myimagvec = (+sw)*dpoly_ass*imag_z*dz + (+dfunc)*distance*itq6 + (+sw)*poly_ass*imag_dz; - - // Real part - accumulateSymmetryFunction( 2 + tmom + m, i, sw*tq6, myrealvec, Tensor( -myrealvec,distance ), myatoms ); - // Imaginary part - accumulateSymmetryFunction( 2+ncomp+tmom+m, i, sw*itq6, myimagvec, Tensor( -myimagvec,distance ), myatoms ); - // Store -m part of vector - double pref=pow(-1.0,m); - // -m part of vector is just +m part multiplied by (-1.0)**m and multiplied by complex - // conjugate of Legendre polynomial - // Real part - accumulateSymmetryFunction( 2+tmom-m, i, pref*sw*tq6, pref*myrealvec, pref*Tensor( -myrealvec,distance ), myatoms ); - // Imaginary part - accumulateSymmetryFunction( 2+ncomp+tmom-m, i, -pref*sw*itq6, -pref*myimagvec, pref*Tensor( myimagvec,distance ), myatoms ); - } - } - } - - // Normalize + for(unsigned i=1; i com1( distance[0]/dlen,distance[1]/dlen ); + + // Do stuff for all other m values + for(unsigned m=1; m<=tmom; ++m) { + // Calculate Legendre Polynomial + poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass ); + // Calculate powe of complex number + powered=pow(com1,m-1); md=static_cast(m); + // Real and imaginary parts of z + real_z = real(com1*powered); imag_z = imag(com1*powered ); + + // Calculate steinhardt parameter + tq6=poly_ass*real_z; // Real part of steinhardt parameter + itq6=poly_ass*imag_z; // Imaginary part of steinhardt parameter + + // Derivatives wrt ( x/r + iy )^m + dp_x = md*powered*( (1.0/dlen)-(distance[0]*distance[0])/dlen3-ii*(distance[0]*distance[1])/dlen3 ); + dp_y = md*powered*( ii*(1.0/dlen)-(distance[0]*distance[1])/dlen3-ii*(distance[1]*distance[1])/dlen3 ); + dp_z = md*powered*( -(distance[0]*distance[2])/dlen3-ii*(distance[1]*distance[2])/dlen3 ); + + // Derivatives of real and imaginary parts of above + real_dz[0] = real( dp_x ); real_dz[1] = real( dp_y ); real_dz[2] = real( dp_z ); + imag_dz[0] = imag( dp_x ); imag_dz[1] = imag( dp_y ); imag_dz[2] = imag( dp_z ); + + // Complete derivative of steinhardt parameter + myrealvec = (+sw)*dpoly_ass*real_z*dz + (+dfunc)*distance*tq6 + (+sw)*poly_ass*real_dz; + myimagvec = (+sw)*dpoly_ass*imag_z*dz + (+dfunc)*distance*itq6 + (+sw)*poly_ass*imag_dz; + + // Real part + accumulateSymmetryFunction( 2 + tmom + m, i, sw*tq6, myrealvec, Tensor( -myrealvec,distance ), myatoms ); + // Imaginary part + accumulateSymmetryFunction( 2+ncomp+tmom+m, i, sw*itq6, myimagvec, Tensor( -myimagvec,distance ), myatoms ); + // Store -m part of vector + double pref=pow(-1.0,m); + // -m part of vector is just +m part multiplied by (-1.0)**m and multiplied by complex + // conjugate of Legendre polynomial + // Real part + accumulateSymmetryFunction( 2+tmom-m, i, pref*sw*tq6, pref*myrealvec, pref*Tensor( -myrealvec,distance ), myatoms ); + // Imaginary part + accumulateSymmetryFunction( 2+ncomp+tmom-m, i, -pref*sw*itq6, -pref*myimagvec, pref*Tensor( myimagvec,distance ), myatoms ); + } + } + } + + // Normalize updateActiveAtoms( myatoms ); - for(unsigned i=0;igetNumberOfQuantities() - 2; - if( getAction()->derivativesAreRequired() ){ - nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*(ncomp+1) ); getFinalValue()->resizeDerivatives( nder ); + if( getAction()->derivativesAreRequired() ) { + nder=getAction()->getNumberOfDerivatives(); + resizeBuffer( (1+nder)*(ncomp+1) ); getFinalValue()->resizeDerivatives( nder ); } else { - nder=0; resizeBuffer(ncomp+1); + nder=0; resizeBuffer(ncomp+1); } } void VectorMean::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); buffer[bufstart] += weight; - for(unsigned i=0;iderivativesAreRequired() ) return; if( diffweight ) myvals.chainRule( 0, 0, 1, 0, 1.0, bufstart, buffer ); - for(unsigned i=0;i& buffer ){ +void VectorMean::finish( const std::vector& buffer ) { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double sum=0, ww=buffer[bufstart]; - for(unsigned i=0;iderivativesAreRequired() ) return; Value* fval=getFinalValue(); double tw = 1.0 / sqrt(sum); - for(unsigned icomp=0;icompaddDerivative( jder, (tw*tmp/ww)*( buffer[bstart + jder] - tmp*buffer[bufstart + 1 + jder] ) ); + for(unsigned icomp=0; icompaddDerivative( jder, (tw*tmp/ww)*( buffer[bstart + jder] - tmp*buffer[bufstart + 1 + jder] ) ); } } diff --git a/src/crystallization/VectorMultiColvar.cpp b/src/crystallization/VectorMultiColvar.cpp index e3bd4d4d59..9a070de58e 100644 --- a/src/crystallization/VectorMultiColvar.cpp +++ b/src/crystallization/VectorMultiColvar.cpp @@ -25,24 +25,24 @@ namespace PLMD { namespace crystallization { -void VectorMultiColvar::registerKeywords( Keywords& keys ){ +void VectorMultiColvar::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); } VectorMultiColvar::VectorMultiColvar(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao), -store_director(true) + Action(ao), + MultiColvarBase(ao), + store_director(true) { setLowMemOption(true); } -void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp ){ +void VectorMultiColvar::setVectorDimensionality( const unsigned& ncomp ) { ncomponents = ncomp; resizeFunctions(); // This resize needs to be here to ensure buffers are set to correct size in base } -void VectorMultiColvar::doNotCalculateDirector(){ - store_director=false; // Need a sanity check in here so that you don't use the same instance of Q4 to calcualte vectors and directors +void VectorMultiColvar::doNotCalculateDirector() { + store_director=false; // Need a sanity check in here so that you don't use the same instance of Q4 to calcualte vectors and directors } double VectorMultiColvar::compute( const unsigned& taskIndex, multicolvar::AtomValuePack& myatoms ) const { @@ -52,46 +52,46 @@ double VectorMultiColvar::compute( const unsigned& taskIndex, multicolvar::AtomV updateActiveAtoms( myatoms ); // Now calculate the norm of the vector (this is what we return here) - double norm=0; - for(unsigned i=0;i dervec( ncomponents ); - for(unsigned i=0;i dervec( ncomponents ); + for(unsigned i=0; i& vals ) const { double inorm = 1.0; if( vals[1]>epsilon ) inorm = 1.0 / vals[1]; - for(unsigned i=2;i& inforces ){ +void VectorMultiColvar::addForcesOnAtoms( const std::vector& inforces ) { plumed_dbg_assert( inforces.size()==getNumberOfDerivatives() ); - std::vector oldforces( getNumberOfDerivatives() ); - getForcesFromVessels( oldforces ); - for(unsigned i=0;i oldforces( getNumberOfDerivatives() ); + getForcesFromVessels( oldforces ); + for(unsigned i=0; i& vals ) const ; - virtual void normalizeVectorDerivatives( MultiValue& myvals ) const ; + virtual void normalizeVector( std::vector& vals ) const ; + virtual void normalizeVectorDerivatives( MultiValue& myvals ) const ; }; inline unsigned VectorMultiColvar::getNumberOfComponentsInVector() const { - return ncomponents; + return ncomponents; } inline diff --git a/src/crystallization/VectorSum.cpp b/src/crystallization/VectorSum.cpp index 2c0eb346fc..ca0eaf6529 100644 --- a/src/crystallization/VectorSum.cpp +++ b/src/crystallization/VectorSum.cpp @@ -43,70 +43,70 @@ class VectorSum : public vesselbase::FunctionVessel { PLUMED_REGISTER_VESSEL(VectorSum,"VSUM") -void VectorSum::registerKeywords( Keywords& keys ){ +void VectorSum::registerKeywords( Keywords& keys ) { vesselbase::FunctionVessel::registerKeywords(keys); } -void VectorSum::reserveKeyword( Keywords& keys ){ +void VectorSum::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","VSUM","calculate the norm of the sum of vectors."); keys.addOutputComponent("vsum","VSUM","the norm of sum of vectors. The output component can be refererred to elsewhere in the input " - "file by using the label.vsum"); + "file by using the label.vsum"); } VectorSum::VectorSum( const vesselbase::VesselOptions& da ) : -FunctionVessel(da), -nder(0) + FunctionVessel(da), + nder(0) { } -std::string VectorSum::value_descriptor(){ +std::string VectorSum::value_descriptor() { return "the norm of the mean vector"; } -void VectorSum::resize(){ +void VectorSum::resize() { unsigned ncomp=getAction()->getNumberOfQuantities() - 2; - if( getAction()->derivativesAreRequired() ){ - nder=getAction()->getNumberOfDerivatives(); - resizeBuffer( (1+nder)*ncomp ); getFinalValue()->resizeDerivatives( nder ); + if( getAction()->derivativesAreRequired() ) { + nder=getAction()->getNumberOfDerivatives(); + resizeBuffer( (1+nder)*ncomp ); getFinalValue()->resizeDerivatives( nder ); } else { - nder=0; resizeBuffer(ncomp); + nder=0; resizeBuffer(ncomp); } } void VectorSum::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double weight=myvals.get(0); + double weight=myvals.get(0); plumed_dbg_assert( weight>=getTolerance() ); - for(unsigned i=0;iderivativesAreRequired() ) return; - for(unsigned i=0;i& buffer ){ +void VectorSum::finish( const std::vector& buffer ) { unsigned ncomp=getAction()->getNumberOfQuantities()-2; - double sum=0; - for(unsigned i=0;iderivativesAreRequired() ) return; Value* fval=getFinalValue(); - for(unsigned icomp=0;icompaddDerivative( jder, tw*tmp*buffer[bstart + jder] ); + for(unsigned icomp=0; icompaddDerivative( jder, tw*tmp*buffer[bstart + jder] ); } } diff --git a/src/eds/EDS.cpp b/src/eds/EDS.cpp index 9d8187555d..e5e575abe1 100644 --- a/src/eds/EDS.cpp +++ b/src/eds/EDS.cpp @@ -104,7 +104,7 @@ eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 IN_RESTART=restart. */ //+ENDPLUMEDOC -class EDS : public Bias{ +class EDS : public Bias { private: @@ -160,7 +160,7 @@ class EDS : public Bias{ void calc_ssd_step_size(); void reset_statistics(); void update_bias(); - void apply_bias(); + void apply_bias(); public: explicit EDS(const ActionOptions&); @@ -171,616 +171,617 @@ class EDS : public Bias{ ~EDS(); }; - PLUMED_REGISTER_ACTION(EDS,"EDS") - - void EDS::registerKeywords(Keywords& keys){ - Bias::registerKeywords(keys); - keys.use("ARG"); - keys.add("optional","CENTER","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. This is for fixed values"); - keys.add("optional","CENTER_ARG","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. " - "CENTER_ARG is for calculated centers, e.g. from a CV or analysis. "); - - keys.add("compulsory","PERIOD","Steps over which to adjust bias"); - - keys.add("compulsory","RANGE","3.0","The largest magnitude of the force constant which one expects (in kBT) for each CV based"); - keys.add("compulsory","SEED","0","Seed for random order of changing bias"); - keys.add("compulsory","INIT","0","Starting value for coupling coefficients"); - keys.add("compulsory","FIXED","0","Fixed target values for bias factors (not adaptive)"); - keys.add("optional","BIAS_SCALE","A divisor to set the units of the bias. " - "If not set, this will be the experimental value by default (as is done in White and Voth 2014)."); - keys.add("optional","TEMP","The system temperature. If not provided will be taken from MD code (if available)"); - keys.add("optional","MULTI_PROP","What proportion of dimensions to update at each step. " - "Must be in interval [1,0), where 1 indicates all and any other indicates a stochastic update. " - "If not set, default is 1 / N, where N is the number of CVs. "); - keys.add("optional","RESTART_FMT","the format that should be used to output real numbers in EDS restarts"); - keys.add("optional","OUT_RESTART","Output file for all information needed to continue EDS simulation. " - "If you have the RESTART directive set (global or for EDS), this file will be appended to. " - "Note that the header will be printed again if appending."); - keys.add("optional","IN_RESTART","Read this file to continue an EDS simulation. " - "If same as OUT_RESTART and you have not set the RESTART directive, the file will be backed-up and overwritten with new output. " - "If you do have the RESTART flag set and it is the same name as OUT_RESTART, this file will be appended."); - - keys.addFlag("RAMP",false,"Slowly increase bias constant to a fixed value"); - keys.addFlag("COVAR",false,"Utilize the covariance matrix when updating the bias. Default Off, but may be enabled due to other options"); - keys.addFlag("FREEZE",false,"Fix bias at current level (only used for restarting). Can also set PERIOD=0 if not using RESTART."); - keys.addFlag("MEAN",false,"Instead of using final bias level from restart, use average. Can only be used in conjunction with FREEZE"); - - keys.use("RESTART"); - - keys.addOutputComponent("force2","default","squared value of force from the bias"); - keys.addOutputComponent("_coupling","default", "For each named CV biased, there will be a corresponding output CV_coupling storing the current linear bias prefactor."); +PLUMED_REGISTER_ACTION(EDS,"EDS") + +void EDS::registerKeywords(Keywords& keys) { + Bias::registerKeywords(keys); + keys.use("ARG"); + keys.add("optional","CENTER","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. This is for fixed values"); + keys.add("optional","CENTER_ARG","The desired centers (equilibrium values) which will be sought during the adaptive linear biasing. " + "CENTER_ARG is for calculated centers, e.g. from a CV or analysis. "); + + keys.add("compulsory","PERIOD","Steps over which to adjust bias"); + + keys.add("compulsory","RANGE","3.0","The largest magnitude of the force constant which one expects (in kBT) for each CV based"); + keys.add("compulsory","SEED","0","Seed for random order of changing bias"); + keys.add("compulsory","INIT","0","Starting value for coupling coefficients"); + keys.add("compulsory","FIXED","0","Fixed target values for bias factors (not adaptive)"); + keys.add("optional","BIAS_SCALE","A divisor to set the units of the bias. " + "If not set, this will be the experimental value by default (as is done in White and Voth 2014)."); + keys.add("optional","TEMP","The system temperature. If not provided will be taken from MD code (if available)"); + keys.add("optional","MULTI_PROP","What proportion of dimensions to update at each step. " + "Must be in interval [1,0), where 1 indicates all and any other indicates a stochastic update. " + "If not set, default is 1 / N, where N is the number of CVs. "); + keys.add("optional","RESTART_FMT","the format that should be used to output real numbers in EDS restarts"); + keys.add("optional","OUT_RESTART","Output file for all information needed to continue EDS simulation. " + "If you have the RESTART directive set (global or for EDS), this file will be appended to. " + "Note that the header will be printed again if appending."); + keys.add("optional","IN_RESTART","Read this file to continue an EDS simulation. " + "If same as OUT_RESTART and you have not set the RESTART directive, the file will be backed-up and overwritten with new output. " + "If you do have the RESTART flag set and it is the same name as OUT_RESTART, this file will be appended."); + + keys.addFlag("RAMP",false,"Slowly increase bias constant to a fixed value"); + keys.addFlag("COVAR",false,"Utilize the covariance matrix when updating the bias. Default Off, but may be enabled due to other options"); + keys.addFlag("FREEZE",false,"Fix bias at current level (only used for restarting). Can also set PERIOD=0 if not using RESTART."); + keys.addFlag("MEAN",false,"Instead of using final bias level from restart, use average. Can only be used in conjunction with FREEZE"); + + keys.use("RESTART"); + + keys.addOutputComponent("force2","default","squared value of force from the bias"); + keys.addOutputComponent("_coupling","default", "For each named CV biased, there will be a corresponding output CV_coupling storing the current linear bias prefactor."); +} + +EDS::EDS(const ActionOptions&ao): + PLUMED_BIAS_INIT(ao), + ncvs_(getNumberOfArguments()), + scale_(ncvs_,0.0), + current_coupling_(ncvs_,0.0), + set_coupling_(ncvs_,0.0), + target_coupling_(ncvs_,0.0), + max_coupling_range_(ncvs_,3.0), + max_coupling_grad_(ncvs_,0.0), + coupling_rate_(ncvs_,1.0), + coupling_accum_(ncvs_,1.0), + means_(ncvs_,0.0), + step_size_(ncvs_,0.0), + out_coupling_(ncvs_,NULL), + in_restart_name_(""), + out_restart_name_(""), + fmt_("%f"), + b_adaptive_(true), + b_freeze_(false), + b_equil_(true), + b_ramp_(false), + b_covar_(false), + b_restart_(false), + b_write_restart_(false), + b_hard_c_range_(false), + seed_(0), + update_period_(0), + avg_coupling_count_(1), + update_calls_(0), + kbt_(0.0), + c_range_increase_f_(1.25), + multi_prop_(-1.0), + value_force2_(NULL) +{ + double temp=-1.0; + bool b_mean=false; + + addComponent("force2"); + componentIsNotPeriodic("force2"); + value_force2_ = getPntrToComponent("force2"); + + for(unsigned int i = 0; igetName() + "_coupling"; + addComponent(comp); + componentIsNotPeriodic(comp); + out_coupling_[i]=getPntrToComponent(comp); } - EDS::EDS(const ActionOptions&ao): - PLUMED_BIAS_INIT(ao), - ncvs_(getNumberOfArguments()), - scale_(ncvs_,0.0), - current_coupling_(ncvs_,0.0), - set_coupling_(ncvs_,0.0), - target_coupling_(ncvs_,0.0), - max_coupling_range_(ncvs_,3.0), - max_coupling_grad_(ncvs_,0.0), - coupling_rate_(ncvs_,1.0), - coupling_accum_(ncvs_,1.0), - means_(ncvs_,0.0), - step_size_(ncvs_,0.0), - out_coupling_(ncvs_,NULL), - in_restart_name_(""), - out_restart_name_(""), - fmt_("%f"), - b_adaptive_(true), - b_freeze_(false), - b_equil_(true), - b_ramp_(false), - b_covar_(false), - b_restart_(false), - b_write_restart_(false), - b_hard_c_range_(false), - seed_(0), - update_period_(0), - avg_coupling_count_(1), - update_calls_(0), - kbt_(0.0), - c_range_increase_f_(1.25), - multi_prop_(-1.0), - value_force2_(NULL) - { - double temp=-1.0; - bool b_mean=false; - - addComponent("force2"); - componentIsNotPeriodic("force2"); - value_force2_ = getPntrToComponent("force2"); - - for(unsigned int i = 0;igetName() + "_coupling"; - addComponent(comp); - componentIsNotPeriodic(comp); - out_coupling_[i]=getPntrToComponent(comp); - } - - parseVector("CENTER",center_); - parseArgumentList("CENTER_ARG",center_values_); - parseVector("BIAS_SCALE", scale_); - parseVector("RANGE",max_coupling_range_); - parseVector("FIXED",target_coupling_); - parseVector("INIT",set_coupling_); - parse("PERIOD",update_period_); - parse("TEMP",temp); - parse("SEED",seed_); - parse("MULTI_PROP",multi_prop_); - parse("RESTART_FMT", fmt_); - fmt_ = " " + fmt_;//add space since parse strips them - parse("OUT_RESTART",out_restart_name_); - parseFlag("RAMP",b_ramp_); - parseFlag("FREEZE",b_freeze_); - parseFlag("MEAN",b_mean); - parseFlag("COVAR",b_covar_); - parse("IN_RESTART",in_restart_name_); - checkRead(); - - /* - * Things that are different when usnig changing centers: - * 1. Scale - * 2. The log file - * 3. Reading Restarts - */ - - if(center_.size() == 0) { - if(center_values_.size() == 0) - error("Must set either CENTER or CENTER_ARG"); - else if(center_values_.size() != ncvs_) - error("CENTER_ARG must contain the same number of variables as ARG"); - b_c_values_ = true; - center_.resize(ncvs_); - log.printf(" EDS will use possibly varying centers\n"); - } else { - if(center_.size() != ncvs_) - error("Must have same number of CENTER arguments as ARG arguments"); - else if(center_values_.size() != 0) - error("You can only set CENTER or CENTER_ARG. Not both"); - b_c_values_ = false; - log.printf(" EDS will use fixed centers\n"); - } - - - - log.printf(" setting scaling:"); - if(scale_.size() > 0 && scale_.size() < ncvs_) { - error("the number of BIAS_SCALE values be the same as number of CVs"); - } else if(scale_.size() == 0 && b_c_values_) { - log.printf(" Setting SCALE to be 1 for all CVs\n"); - scale_.resize(ncvs_); - for(unsigned int i = 0; i < ncvs_; ++i) - scale_[i] = 1; - } else if(scale_.size() == 0 && !b_c_values_) { - log.printf(" (default) "); - - scale_.resize(ncvs_); - for(unsigned int i = 0; i < scale_.size(); i++) { - if(center_[i]==0) - error("BIAS_SCALE parameter has been set to CENTER value of 0 (as is default). This will divide by 0, so giving up. See doc for EDS bias"); - scale_[i] = center_[i]; - } - } else { - for(unsigned int i = 0; i < scale_.size(); i++) - log.printf(" %f",scale_[i]); - } - log.printf("\n"); + parseVector("CENTER",center_); + parseArgumentList("CENTER_ARG",center_values_); + parseVector("BIAS_SCALE", scale_); + parseVector("RANGE",max_coupling_range_); + parseVector("FIXED",target_coupling_); + parseVector("INIT",set_coupling_); + parse("PERIOD",update_period_); + parse("TEMP",temp); + parse("SEED",seed_); + parse("MULTI_PROP",multi_prop_); + parse("RESTART_FMT", fmt_); + fmt_ = " " + fmt_;//add space since parse strips them + parse("OUT_RESTART",out_restart_name_); + parseFlag("RAMP",b_ramp_); + parseFlag("FREEZE",b_freeze_); + parseFlag("MEAN",b_mean); + parseFlag("COVAR",b_covar_); + parse("IN_RESTART",in_restart_name_); + checkRead(); + + /* + * Things that are different when usnig changing centers: + * 1. Scale + * 2. The log file + * 3. Reading Restarts + */ + + if(center_.size() == 0) { + if(center_values_.size() == 0) + error("Must set either CENTER or CENTER_ARG"); + else if(center_values_.size() != ncvs_) + error("CENTER_ARG must contain the same number of variables as ARG"); + b_c_values_ = true; + center_.resize(ncvs_); + log.printf(" EDS will use possibly varying centers\n"); + } else { + if(center_.size() != ncvs_) + error("Must have same number of CENTER arguments as ARG arguments"); + else if(center_values_.size() != 0) + error("You can only set CENTER or CENTER_ARG. Not both"); + b_c_values_ = false; + log.printf(" EDS will use fixed centers\n"); + } - if(b_covar_) { - log.printf(" EDS will utilize covariance matrix for update steps\n"); - covar_.resize(ncvs_, ncvs_); - } else { - log.printf(" EDS will utilize variance for update steps\n"); - ssds_.resize(ncvs_); - } + log.printf(" setting scaling:"); + if(scale_.size() > 0 && scale_.size() < ncvs_) { + error("the number of BIAS_SCALE values be the same as number of CVs"); + } else if(scale_.size() == 0 && b_c_values_) { + log.printf(" Setting SCALE to be 1 for all CVs\n"); + scale_.resize(ncvs_); + for(unsigned int i = 0; i < ncvs_; ++i) + scale_[i] = 1; + } else if(scale_.size() == 0 && !b_c_values_) { + log.printf(" (default) "); - if (b_mean == true and b_freeze_ == false) { - error("EDS keyworkd MEAN can only be used along with keyword FREEZE"); + scale_.resize(ncvs_); + for(unsigned int i = 0; i < scale_.size(); i++) { + if(center_[i]==0) + error("BIAS_SCALE parameter has been set to CENTER value of 0 (as is default). This will divide by 0, so giving up. See doc for EDS bias"); + scale_[i] = center_[i]; } + } else { + for(unsigned int i = 0; i < scale_.size(); i++) + log.printf(" %f",scale_[i]); + } + log.printf("\n"); - if(in_restart_name_ != ""){ - b_restart_ = true; - log.printf(" reading simulation information from file: %s\n",in_restart_name_.c_str()); - readInRestart(b_mean); - } else{ - - if(temp>=0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; - else kbt_ = plumed.getAtoms().getKbT(); - - //in driver, this results in kbt of 0 - if(kbt_ == 0){ - error(" Unable to determine valid kBT. " - "Could be because you are runnning from driver or MD didn't give temperature.\n" - "Consider setting temperature manually with the TEMP keyword."); - kbt_ = 1; - } - log.printf(" kBT = %f\n",kbt_); - log.printf(" Updating every %i steps\n",update_period_); - - if(!b_c_values_) { - log.printf(" with centers:"); - for(unsigned int i = 0;i< ncvs_;i++){ - log.printf(" %f ",center_[i]); - } - } else { - log.printf(" with actions centers:"); - for(unsigned int i = 0;i< ncvs_;i++){ - log.printf(" %s ",center_values_[i]->getName().c_str()); - //add dependency on these actions - addDependency(center_values_[i]->getPntrToAction()); - } - } + if(b_covar_) { + log.printf(" EDS will utilize covariance matrix for update steps\n"); + covar_.resize(ncvs_, ncvs_); + } else { + log.printf(" EDS will utilize variance for update steps\n"); + ssds_.resize(ncvs_); + } - log.printf("\n with initial ranges / rates:\n"); - for(unsigned int i = 0;i0){ - log.printf(" setting random seed = %i",seed_); - rand_.setSeed(seed_); - } + if (b_mean == true and b_freeze_ == false) { + error("EDS keyworkd MEAN can only be used along with keyword FREEZE"); + } - for(unsigned int i = 0;i=0.0) kbt_=plumed.getAtoms().getKBoltzmann()*temp; + else kbt_ = plumed.getAtoms().getKbT(); + + //in driver, this results in kbt of 0 + if(kbt_ == 0) { + error(" Unable to determine valid kBT. " + "Could be because you are runnning from driver or MD didn't give temperature.\n" + "Consider setting temperature manually with the TEMP keyword."); + kbt_ = 1; + } - if(!b_adaptive_){ - if(b_ramp_) { - log.printf(" ramping up coupling constants over %i steps\n",update_period_); - } + log.printf(" kBT = %f\n",kbt_); + log.printf(" Updating every %i steps\n",update_period_); - log.printf(" with starting coupling constants"); - for(unsigned int i = 0;i0){ - update_period_ /= 2; + } else { + log.printf(" with actions centers:"); + for(unsigned int i = 0; i< ncvs_; i++) { + log.printf(" %s ",center_values_[i]->getName().c_str()); + //add dependency on these actions + addDependency(center_values_[i]->getPntrToAction()); } - - } - if(b_freeze_){ - b_adaptive_=false; - update_period_ = 0; - if (b_mean) { - log.printf(" freezing bias at the average level from the restart file\n"); - } else{ - log.printf(" freezing bias at current level\n"); - } + log.printf("\n with initial ranges / rates:\n"); + for(unsigned int i = 0; i 0 && multi_prop_ <= 1.0) { - log.printf(" Will update each dimension stochastically with probability %f\n", multi_prop_); - } else{ - error(" MULTI_PROP must be between 0 and 1\n"); + if(seed_>0) { + log.printf(" setting random seed = %i",seed_); + rand_.setSeed(seed_); } - if(out_restart_name_.length()>0) { - log.printf(" writing restart information every %i steps to file %s with format %s\n",abs(update_period_),out_restart_name_.c_str(), fmt_.c_str()); - b_write_restart_ = true; - setupOutRestart(); - } + for(unsigned int i = 0; i fields; - in_restart_.scanFieldList(fields); - log.printf("field"); - for(unsigned int i = 0;i0) { + update_period_ /= 2; + } - if(in_restart_.FieldExist("update_period")){ - in_restart_.scanField("update_period",update_period_); - }else{ error("No field 'update_period' in restart file"); } - log.printf(" Updating every %i steps\n",update_period_); - if(in_restart_.FieldExist("adaptive")){ - //note, no version of scanField for boolean - in_restart_.scanField("adaptive",adaptive_i); - }else{ error("No field 'adaptive' in restart file"); } - b_adaptive_ = bool(adaptive_i); + } - if(in_restart_.FieldExist("seed")){ - in_restart_.scanField("seed",seed_); - }else{ error("No field 'seed' in restart file"); } - if(seed_>0){ - log.printf(" setting random seed = %i",seed_); - rand_.setSeed(seed_); + if(b_freeze_) { + b_adaptive_=false; + update_period_ = 0; + if (b_mean) { + log.printf(" freezing bias at the average level from the restart file\n"); + } else { + log.printf(" freezing bias at current level\n"); } + } - double time; - std::vector avg_bias = std::vector(center_.size()); - unsigned int N = 0; - std::string cv_name; + if(multi_prop_ == -1.0) { + log.printf(" Will update each dimension stochastically with probability 1 / number of CVs\n"); + multi_prop_ = 1.0 / ncvs_; + } else if(multi_prop_ > 0 && multi_prop_ <= 1.0) { + log.printf(" Will update each dimension stochastically with probability %f\n", multi_prop_); + } else { + error(" MULTI_PROP must be between 0 and 1\n"); + } - while(in_restart_.scanField("time",time)){ + if(out_restart_name_.length()>0) { + log.printf(" writing restart information every %i steps to file %s with format %s\n",abs(update_period_),out_restart_name_.c_str(), fmt_.c_str()); + b_write_restart_ = true; + setupOutRestart(); + } - for(unsigned int i = 0;igetName(); - in_restart_.scanField(cv_name + "_center", set_coupling_[i]); - in_restart_.scanField(cv_name + "_set", set_coupling_[i]); - in_restart_.scanField(cv_name + "_target",target_coupling_[i]); - in_restart_.scanField(cv_name + "_coupling",current_coupling_[i]); - in_restart_.scanField(cv_name + "_maxrange",max_coupling_range_[i]); - in_restart_.scanField(cv_name + "_maxgrad",max_coupling_grad_[i]); + log<<" Bibliography "< fields; + in_restart_.scanFieldList(fields); + log.printf("field"); + for(unsigned int i = 0;i0) { + log.printf(" setting random seed = %i",seed_); + rand_.setSeed(seed_); + } - log.printf(" with centers:"); - for(unsigned int i = 0;i avg_bias = std::vector(center_.size()); + unsigned int N = 0; + std::string cv_name; - log.printf("\n with initial ranges / rates:\n"); - for(unsigned int i = 0;igetName(); + in_restart_.scanField(cv_name + "_center", set_coupling_[i]); + in_restart_.scanField(cv_name + "_set", set_coupling_[i]); + in_restart_.scanField(cv_name + "_target",target_coupling_[i]); + in_restart_.scanField(cv_name + "_coupling",current_coupling_[i]); + in_restart_.scanField(cv_name + "_maxrange",max_coupling_range_[i]); + in_restart_.scanField(cv_name + "_maxgrad",max_coupling_grad_[i]); + + avg_bias[i] += current_coupling_[i]; } + N++; - if(b_mean) { - log.printf("Loaded in averages for coupling constants...\n"); - for(unsigned int i = 0;igetName(); - out_restart_.printField(cv_name + "_center",center_[i]); - out_restart_.printField(cv_name + "_set",set_coupling_[i]); - out_restart_.printField(cv_name + "_target",target_coupling_[i]); - out_restart_.printField(cv_name + "_coupling",current_coupling_[i]); - out_restart_.printField(cv_name + "_maxrange",max_coupling_range_[i]); - out_restart_.printField(cv_name + "_maxgrad",max_coupling_grad_[i]); - } - out_restart_.printField(); + log.printf(" with current coupling constants:\n "); + for(unsigned int i = 0; igetName(); + out_restart_.printField(cv_name + "_center",center_[i]); + out_restart_.printField(cv_name + "_set",set_coupling_[i]); + out_restart_.printField(cv_name + "_target",target_coupling_[i]); + out_restart_.printField(cv_name + "_coupling",current_coupling_[i]); + out_restart_.printField(cv_name + "_maxrange",max_coupling_range_[i]); + out_restart_.printField(cv_name + "_maxgrad",max_coupling_grad_[i]); } + out_restart_.printField(); +} - void EDS::calculate(){ - - //get center values from action if necessary - if(b_c_values_) - for(unsigned int i = 0; i < ncvs_; ++i) - center_[i] = center_values_[i]->get(); +void EDS::calculate() { - apply_bias(); + //get center values from action if necessary + if(b_c_values_) + for(unsigned int i = 0; i < ncvs_; ++i) + center_[i] = center_values_[i]->get(); - //adjust parameters according to EDS recipe - update_calls_++; + apply_bias(); - //check if we're ramping or doing normal updates and then restart if needed. The ramping check - //is complicated because we could be frozen, finished ramping or not ramping. - //The + 2 is so we have an extra line showing that the bias isn't changing (for my sanity and yours) - if( b_write_restart_){ - if(getStep() == 0 || - ( (update_period_ < 0 && !b_freeze_ && update_calls_ <= fabs(update_period_) + 2) || - (update_period_ > 0 && update_calls_ % update_period_ == 0 ) ) ) - writeOutRestart(); - } + //adjust parameters according to EDS recipe + update_calls_++; - int b_finished_equil_flag = 1; + //check if we're ramping or doing normal updates and then restart if needed. The ramping check + //is complicated because we could be frozen, finished ramping or not ramping. + //The + 2 is so we have an extra line showing that the bias isn't changing (for my sanity and yours) + if( b_write_restart_) { + if(getStep() == 0 || + ( (update_period_ < 0 && !b_freeze_ && update_calls_ <= fabs(update_period_) + 2) || + (update_period_ > 0 && update_calls_ % update_period_ == 0 ) ) ) + writeOutRestart(); + } - //assume forces already applied and saved + int b_finished_equil_flag = 1; + //assume forces already applied and saved - //are we ramping to a constant value and not done equilibrating? - if(update_period_ < 0){ - if(update_calls_ <= fabs(update_period_) && !b_freeze_){ - for(unsigned int i = 0;i < ncvs_; ++i) - current_coupling_[i] += (target_coupling_[i]-set_coupling_[i])/fabs(update_period_); + + //are we ramping to a constant value and not done equilibrating? + if(update_period_ < 0) { + if(update_calls_ <= fabs(update_period_) && !b_freeze_) { + for(unsigned int i = 0; i < ncvs_; ++i) + current_coupling_[i] += (target_coupling_[i]-set_coupling_[i])/fabs(update_period_); + } + //make sure we don't reset update calls + b_finished_equil_flag = 0; + } else if(update_period_ == 0) { //do we have a no-update case? + //not updating + //pass + } else if(!b_equil_) { + //if we aren't wating for the bias to equilibrate, collect data + update_statistics(); + } else { + // equilibrating + //check if we've reached the setpoint + for(unsigned int i = 0; i < ncvs_; ++i) { + if(coupling_rate_[i] == 0 || pow(current_coupling_[i] - set_coupling_[i],2) < pow(coupling_rate_[i],2)) { + b_finished_equil_flag &= 1; } - //make sure we don't reset update calls - b_finished_equil_flag = 0; - } else if(update_period_ == 0){ //do we have a no-update case? - //not updating - //pass - } else if(!b_equil_){ - //if we aren't wating for the bias to equilibrate, collect data - update_statistics(); - } else { - // equilibrating - //check if we've reached the setpoint - for(unsigned int i = 0;i < ncvs_; ++i) { - if(coupling_rate_[i] == 0 || pow(current_coupling_[i] - set_coupling_[i],2) < pow(coupling_rate_[i],2)) { - b_finished_equil_flag &= 1; - } - else{ - current_coupling_[i] += coupling_rate_[i]; - b_finished_equil_flag = 0; - } + else { + current_coupling_[i] += coupling_rate_[i]; + b_finished_equil_flag = 0; } } + } - //Update max coupling range if not hard - if(!b_hard_c_range_) { - for(unsigned int i = 0;i < ncvs_; ++i) { - if(fabs(current_coupling_[i])>max_coupling_range_[i]) { - max_coupling_range_[i]*=c_range_increase_f_; - max_coupling_grad_[i]*=c_range_increase_f_; - } + //Update max coupling range if not hard + if(!b_hard_c_range_) { + for(unsigned int i = 0; i < ncvs_; ++i) { + if(fabs(current_coupling_[i])>max_coupling_range_[i]) { + max_coupling_range_[i]*=c_range_increase_f_; + max_coupling_grad_[i]*=c_range_increase_f_; } } - - //reduce all the flags - if(b_equil_ && b_finished_equil_flag) { - b_equil_ = false; - update_calls_ = 0; - } - - //Now we update coupling constant, if necessary - if(!b_equil_ && update_period_ > 0 && update_calls_ == update_period_ && !b_freeze_) { - update_bias(); - update_calls_ = 0; - avg_coupling_count_++; - b_equil_ = true; //back to equilibration now - } //close update if - - //pass couplings out so they are accessible - for(unsigned int i = 0;iset(current_coupling_[i]); - } } - void EDS::apply_bias() { - //Compute linear force as in "restraint" - double ene = 0, totf2 = 0, cv, m , f; - - for(unsigned int i = 0; i < ncvs_; ++i) { - cv = difference(i, center_[i], getArgument(i)); - m = current_coupling_[i]; - f = -m; - ene += m*cv; - setOutputForce(i,f); - totf2 += f*f; - }; - - setBias(ene); - value_force2_->set(totf2); - + //reduce all the flags + if(b_equil_ && b_finished_equil_flag) { + b_equil_ = false; + update_calls_ = 0; } - void EDS::update_statistics() { - double s; - std::vector deltas(ncvs_); - //Welford, West, and Hanso online variance method - for(unsigned int i = 0; i < ncvs_; ++i) { - deltas[i] = difference(i,means_[i],getArgument(i)); - means_[i] += deltas[i]/update_calls_; - if(!b_covar_) - ssds_[i] += deltas[i]*difference(i,means_[i],getArgument(i)); - } - if(b_covar_) { - for(unsigned int i = 0; i < ncvs_; ++i) { - for(unsigned int j = i; j < ncvs_; ++j) { - s = (update_calls_ - 1) * deltas[i] * deltas[j] / update_calls_ / update_calls_ - covar_(i,j) / update_calls_; - covar_(i,j) += s; - //do this so we don't double count - covar_(j,i) = covar_(i,j); - } + //Now we update coupling constant, if necessary + if(!b_equil_ && update_period_ > 0 && update_calls_ == update_period_ && !b_freeze_) { + update_bias(); + update_calls_ = 0; + avg_coupling_count_++; + b_equil_ = true; //back to equilibration now + } //close update if + + //pass couplings out so they are accessible + for(unsigned int i = 0; iset(current_coupling_[i]); + } +} + +void EDS::apply_bias() { + //Compute linear force as in "restraint" + double ene = 0, totf2 = 0, cv, m, f; + + for(unsigned int i = 0; i < ncvs_; ++i) { + cv = difference(i, center_[i], getArgument(i)); + m = current_coupling_[i]; + f = -m; + ene += m*cv; + setOutputForce(i,f); + totf2 += f*f; + }; + + setBias(ene); + value_force2_->set(totf2); + +} + +void EDS::update_statistics() { + double s; + std::vector deltas(ncvs_); + //Welford, West, and Hanso online variance method + for(unsigned int i = 0; i < ncvs_; ++i) { + deltas[i] = difference(i,means_[i],getArgument(i)); + means_[i] += deltas[i]/update_calls_; + if(!b_covar_) + ssds_[i] += deltas[i]*difference(i,means_[i],getArgument(i)); + } + if(b_covar_) { + for(unsigned int i = 0; i < ncvs_; ++i) { + for(unsigned int j = i; j < ncvs_; ++j) { + s = (update_calls_ - 1) * deltas[i] * deltas[j] / update_calls_ / update_calls_ - covar_(i,j) / update_calls_; + covar_(i,j) += s; + //do this so we don't double count + covar_(j,i) = covar_(i,j); } } } +} - void EDS::reset_statistics() { - for(unsigned int i = 0; i < ncvs_; ++i) { - means_[i] = 0; - if(!b_covar_) - ssds_[i] = 0; - } - if(b_covar_) - for(unsigned int i = 0; i < ncvs_; ++i) - for(unsigned int j = 0; j < ncvs_; ++j) - covar_(i,j) = 0; +void EDS::reset_statistics() { + for(unsigned int i = 0; i < ncvs_; ++i) { + means_[i] = 0; + if(!b_covar_) + ssds_[i] = 0; } - - void EDS::calc_covar_step_size() { - //calulcate step size - //uses scale here, which by default is center - double tmp; - for(unsigned int i = 0; i< ncvs_; ++i){ - tmp = 0; + if(b_covar_) + for(unsigned int i = 0; i < ncvs_; ++i) for(unsigned int j = 0; j < ncvs_; ++j) - tmp += difference(i, means_[i], center_[i]) * covar_(i,j); - step_size_[i] = 2 * tmp / kbt_ / scale_[i] * update_calls_ / (update_calls_ - 1); - } - + covar_(i,j) = 0; +} + +void EDS::calc_covar_step_size() { + //calulcate step size + //uses scale here, which by default is center + double tmp; + for(unsigned int i = 0; i< ncvs_; ++i) { + tmp = 0; + for(unsigned int j = 0; j < ncvs_; ++j) + tmp += difference(i, means_[i], center_[i]) * covar_(i,j); + step_size_[i] = 2 * tmp / kbt_ / scale_[i] * update_calls_ / (update_calls_ - 1); } - void EDS::calc_ssd_step_size() { - double tmp; - for(unsigned int i = 0; i< ncvs_; ++i){ - tmp = 2. * difference(i, means_[i], center_[i]) * ssds_[i] / (update_calls_ - 1); - step_size_[i] = tmp / kbt_/scale_[i]; - } +} + +void EDS::calc_ssd_step_size() { + double tmp; + for(unsigned int i = 0; i< ncvs_; ++i) { + tmp = 2. * difference(i, means_[i], center_[i]) * ssds_[i] / (update_calls_ - 1); + step_size_[i] = tmp / kbt_/scale_[i]; } +} - void EDS::update_bias() - { - if(b_covar_) - calc_covar_step_size(); - else - calc_ssd_step_size(); - - for(unsigned int i = 0; i< ncvs_; ++i){ - - //check if the step_size exceeds maximum possible gradient - step_size_[i] = copysign(fmin(fabs(step_size_[i]), max_coupling_grad_[i]), step_size_[i]); - - //reset means/vars - reset_statistics(); - - //multidimesional stochastic step - if(ncvs_ == 1 || (rand_.RandU01() < (multi_prop_) ) ) { - coupling_accum_[i] += step_size_[i] * step_size_[i]; - - //equation 5 in White and Voth, JCTC 2014 - //no negative sign because it's in step_size - set_coupling_[i] += max_coupling_range_[i]/sqrt(coupling_accum_[i])*step_size_[i]; - coupling_rate_[i] = (set_coupling_[i]-current_coupling_[i])/update_period_; - - } else { - //do not change the bias - coupling_rate_[i] = 0; - } +void EDS::update_bias() +{ + if(b_covar_) + calc_covar_step_size(); + else + calc_ssd_step_size(); + + for(unsigned int i = 0; i< ncvs_; ++i) { + + //check if the step_size exceeds maximum possible gradient + step_size_[i] = copysign(fmin(fabs(step_size_[i]), max_coupling_grad_[i]), step_size_[i]); + + //reset means/vars + reset_statistics(); + + //multidimesional stochastic step + if(ncvs_ == 1 || (rand_.RandU01() < (multi_prop_) ) ) { + coupling_accum_[i] += step_size_[i] * step_size_[i]; + + //equation 5 in White and Voth, JCTC 2014 + //no negative sign because it's in step_size + set_coupling_[i] += max_coupling_range_[i]/sqrt(coupling_accum_[i])*step_size_[i]; + coupling_rate_[i] = (set_coupling_[i]-current_coupling_[i])/update_period_; + + } else { + //do not change the bias + coupling_rate_[i] = 0; } } +} - void EDS::update(){ - //pass - } +void EDS::update() { + //pass +} - EDS::~EDS(){ - out_restart_.close(); - } +EDS::~EDS() { + out_restart_.close(); +} - void EDS::turnOnDerivatives(){ - // do nothing - // this is to avoid errors triggered when a bias is used as a CV - // (This is done in ExtendedLagrangian.cpp) - } +void EDS::turnOnDerivatives() { + // do nothing + // this is to avoid errors triggered when a bias is used as a CV + // (This is done in ExtendedLagrangian.cpp) +} -}}//close the 2 namespaces +} +}//close the 2 namespaces diff --git a/src/function/Combine.cpp b/src/function/Combine.cpp index 5e3ac9b29f..e76ed7b8bb 100644 --- a/src/function/Combine.cpp +++ b/src/function/Combine.cpp @@ -26,8 +26,8 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION COMBINE /* @@ -92,7 +92,7 @@ class Combine : PLUMED_REGISTER_ACTION(Combine,"COMBINE") -void Combine::registerKeywords(Keywords& keys){ +void Combine::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.use("PERIODIC"); keys.add("compulsory","COEFFICIENTS","1.0","the coefficients of the arguments in your function"); @@ -102,12 +102,12 @@ void Combine::registerKeywords(Keywords& keys){ } Combine::Combine(const ActionOptions&ao): -Action(ao), -Function(ao), -normalize(false), -coefficients(getNumberOfArguments(),1.0), -parameters(getNumberOfArguments(),0.0), -powers(getNumberOfArguments(),1.0) + Action(ao), + Function(ao), + normalize(false), + coefficients(getNumberOfArguments(),1.0), + parameters(getNumberOfArguments(),0.0), + powers(getNumberOfArguments(),1.0) { parseVector("COEFFICIENTS",coefficients); if(coefficients.size()!=static_cast(getNumberOfArguments())) @@ -123,29 +123,29 @@ powers(getNumberOfArguments(),1.0) parseFlag("NORMALIZE",normalize); - if(normalize){ + if(normalize) { double n=0.0; - for(unsigned i=0;ilabel.cvlabel. +Each collective variable is averaged separately and stored in a component labelled label.cvlabel. \par Examples The following input tells plumed to calculate the distance between atoms 3 and 5 and the average it over the available replicas. \verbatim -dist: DISTANCE ATOMS=3,5 +dist: DISTANCE ATOMS=3,5 ens: ENSEMBLE ARG=dist PRINT ARG=dist,ens.dist \endverbatim @@ -72,11 +72,11 @@ class Ensemble : PLUMED_REGISTER_ACTION(Ensemble,"ENSEMBLE") -void Ensemble::registerKeywords(Keywords& keys){ +void Ensemble::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); - keys.addFlag("REWEIGHT",false,"simple REWEIGHT using the latest ARG as energy"); - keys.addFlag("CENTRAL",false,"calculate a central moment instead of a standard moment"); + keys.addFlag("REWEIGHT",false,"simple REWEIGHT using the latest ARG as energy"); + keys.addFlag("CENTRAL",false,"calculate a central moment instead of a standard moment"); keys.add("optional","TEMP","the system temperature - this is only needed if you are reweighting"); keys.add("optional","MOMENT","the moment you want to calculate in alternative to the mean or the variance"); keys.add("optional","POWER","the power of the mean (and moment)"); @@ -84,17 +84,17 @@ void Ensemble::registerKeywords(Keywords& keys){ } Ensemble::Ensemble(const ActionOptions&ao): -Action(ao), -Function(ao), -do_reweight(false), -do_moments(false), -do_central(false), -do_powers(false), -kbt(-1.0), -moment(0), -power(0) + Action(ao), + Function(ao), + do_reweight(false), + do_moments(false), + do_central(false), + do_powers(false), + kbt(-1.0), + moment(0), + power(0) { - parseFlag("REWEIGHT", do_reweight); + parseFlag("REWEIGHT", do_reweight); double temp=0.0; parse("TEMP",temp); if(do_reweight) { @@ -108,7 +108,7 @@ power(0) if(moment!=0) do_moments=true; parseFlag("CENTRAL", do_central); if(!do_moments&&do_central) error("To calculate a CENTRAL moment you need to define for which MOMENT"); - + parse("POWER",power); if(power==1) error("POWER can be any number but for 0 and 1"); if(power!=0) do_powers=true; @@ -116,7 +116,7 @@ power(0) checkRead(); master = (comm.Get_rank()==0); - ens_dim=0; + ens_dim=0; my_repl=0; if(master) { ens_dim=multi_sim_comm.Get_size(); @@ -125,22 +125,22 @@ power(0) comm.Bcast(ens_dim,0); comm.Bcast(my_repl,0); if(ens_dim<2) log.printf("WARNING: ENSEMBLE with one replica is not doing any averaging!\n"); - + // prepare output components, the number depending on reweighing or not narg = getNumberOfArguments(); if(do_reweight) narg--; - + // these are the averages - for(unsigned i=0;igetName(); - addComponentWithDerivatives(s); - getPntrToComponent(i)->setNotPeriodic(); + for(unsigned i=0; igetName(); + addComponentWithDerivatives(s); + getPntrToComponent(i)->setNotPeriodic(); } - // these are the moments + // these are the moments if(do_moments) { - for(unsigned i=0;igetName()+"_m"; - addComponentWithDerivatives(s); + addComponentWithDerivatives(s); getPntrToComponent(i+narg)->setNotPeriodic(); } } @@ -152,38 +152,38 @@ power(0) if(do_powers) log.printf(" calculating the %lf power of the mean (and moment)\n", power); } -void Ensemble::calculate(){ +void Ensemble::calculate() { double norm = 0.0; double fact = 0.0; - // calculate the weights either from BIAS - if(do_reweight){ + // calculate the weights either from BIAS + if(do_reweight) { vector bias; bias.resize(ens_dim); - if(master){ - bias[my_repl] = getArgument(narg); - if(ens_dim>1) multi_sim_comm.Sum(&bias[0], ens_dim); + if(master) { + bias[my_repl] = getArgument(narg); + if(ens_dim>1) multi_sim_comm.Sum(&bias[0], ens_dim); } comm.Sum(&bias[0], ens_dim); const double maxbias = *(std::max_element(bias.begin(), bias.end())); - for(unsigned i=0; i(ens_dim); - fact = 1.0/norm; + norm = static_cast(ens_dim); + fact = 1.0/norm; } const double fact_kbt = fact/kbt; vector mean(narg); vector dmean(narg,fact); - // calculate the mean + // calculate the mean if(master) { - for(unsigned i=0;i1) multi_sim_comm.Sum(&mean[0], narg); } comm.Sum(&mean[0], narg); @@ -196,29 +196,29 @@ void Ensemble::calculate(){ // standard moment if(!do_central) { if(master) { - for(unsigned i=0;i1) multi_sim_comm.Sum(&v_moment[0], narg); } else { - for(unsigned i=0;i1) multi_sim_comm.Sum(&v_moment[0], narg); } else { - for(unsigned i=0;iset(mean[i]); @@ -261,7 +261,7 @@ void Ensemble::calculate(){ setDerivative(u, narg, w_tmp); } } - } + } } } diff --git a/src/function/FuncPathMSD.cpp b/src/function/FuncPathMSD.cpp index 5aa68d1209..f4d481d733 100644 --- a/src/function/FuncPathMSD.cpp +++ b/src/function/FuncPathMSD.cpp @@ -30,30 +30,30 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION FUNCPATHMSD /* -This function calculates path collective variables. +This function calculates path collective variables. -This is the Path Collective Variables implementation +This is the Path Collective Variables implementation ( see \cite brand07 ). -This variable computes the progress along a given set of frames that is provided -in input ("s" component) and the distance from them ("z" component). -It is a function of MSD that are obtained by the joint use of MSD variable and SQUARED flag +This variable computes the progress along a given set of frames that is provided +in input ("s" component) and the distance from them ("z" component). +It is a function of MSD that are obtained by the joint use of MSD variable and SQUARED flag (see below). \par Examples -Here below is a case where you have defined three frames and you want to +Here below is a case where you have defined three frames and you want to calculate the progress alng the path and the distance from it in p1 \verbatim t1: RMSD REFERENCE=frame_1.dat TYPE=OPTIMAL SQUARED t2: RMSD REFERENCE=frame_21.dat TYPE=OPTIMAL SQUARED t3: RMSD REFERENCE=frame_42.dat TYPE=OPTIMAL SQUARED -p1: FUNCPATHMSD ARG=t1,t2,t3 LAMBDA=500.0 +p1: FUNCPATHMSD ARG=t1,t2,t3 LAMBDA=500.0 PRINT ARG=t1,t2,t3,p1.s,p1.z STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim @@ -61,83 +61,83 @@ In this second example is shown how to define a PATH in the \ref CONTACTMAP spac \verbatim CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=0.1 -ATOMS2=3,4 REFERENCE2=0.5 -ATOMS3=4,5 REFERENCE3=0.25 -ATOMS4=5,6 REFERENCE4=0.0 -SWITCH=(RATIONAL R_0=1.5) +ATOMS1=1,2 REFERENCE1=0.1 +ATOMS2=3,4 REFERENCE2=0.5 +ATOMS3=4,5 REFERENCE3=0.25 +ATOMS4=5,6 REFERENCE4=0.0 +SWITCH=(RATIONAL R_0=1.5) LABEL=c1 CMDIST ... CONTACTMAP CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=0.3 -ATOMS2=3,4 REFERENCE2=0.9 -ATOMS3=4,5 REFERENCE3=0.45 -ATOMS4=5,6 REFERENCE4=0.1 -SWITCH=(RATIONAL R_0=1.5) +ATOMS1=1,2 REFERENCE1=0.3 +ATOMS2=3,4 REFERENCE2=0.9 +ATOMS3=4,5 REFERENCE3=0.45 +ATOMS4=5,6 REFERENCE4=0.1 +SWITCH=(RATIONAL R_0=1.5) LABEL=c2 CMDIST ... CONTACTMAP CONTACTMAP ... -ATOMS1=1,2 REFERENCE1=1.0 -ATOMS2=3,4 REFERENCE2=1.0 -ATOMS3=4,5 REFERENCE3=1.0 -ATOMS4=5,6 REFERENCE4=1.0 -SWITCH=(RATIONAL R_0=1.5) +ATOMS1=1,2 REFERENCE1=1.0 +ATOMS2=3,4 REFERENCE2=1.0 +ATOMS3=4,5 REFERENCE3=1.0 +ATOMS4=5,6 REFERENCE4=1.0 +SWITCH=(RATIONAL R_0=1.5) LABEL=c3 CMDIST ... CONTACTMAP -p1: FUNCPATHMSD ARG=c1,c2,c3 LAMBDA=500.0 +p1: FUNCPATHMSD ARG=c1,c2,c3 LAMBDA=500.0 PRINT ARG=c1,c2,c3,p1.s,p1.z STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim */ //+ENDPLUMEDOC - + class FuncPathMSD : public Function { double lambda; int neigh_size; double neigh_stride; vector< pair > neighpair; map indexmap; // use double to allow isomaps - vector allArguments; + vector allArguments; // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -// this below is useful when one wants to sort a vector of double and have back the order +// this below is useful when one wants to sort a vector of double and have back the order // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // create a custom sorter -typedef vector::const_iterator myiter; -struct ordering { - bool operator ()(pair const& a, pair const& b) { - return *(a.second) < *(b.second); - } -}; + typedef vector::const_iterator myiter; + struct ordering { + bool operator ()(pair const& a, pair const& b) { + return *(a.second) < *(b.second); + } + }; // sorting utility -vector increasingOrder( vector &v){ - // make a pair - vector< pair > order(v.size()); - unsigned n = 0; - for (myiter it = v.begin(); it != v.end(); ++it, ++n){ - order[n] = make_pair(n, it); // note: heere i do not put the values but the addresses that point to the value - } - // now sort according the second value - sort(order.begin(), order.end(), ordering()); - vector vv(v.size());n=0; - for (const auto & it : order){ - vv[n]=it.first;n++; - } - return vv; -} + vector increasingOrder( vector &v) { + // make a pair + vector< pair > order(v.size()); + unsigned n = 0; + for (myiter it = v.begin(); it != v.end(); ++it, ++n) { + order[n] = make_pair(n, it); // note: heere i do not put the values but the addresses that point to the value + } + // now sort according the second value + sort(order.begin(), order.end(), ordering()); + vector vv(v.size()); n=0; + for (const auto & it : order) { + vv[n]=it.first; n++; + } + return vv; + } // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -struct pairordering { - bool operator ()(pair const& a, pair const& b) { - return (a).second > (b).second; - } -}; + struct pairordering { + bool operator ()(pair const& a, pair const& b) { + return (a).second > (b).second; + } + }; public: explicit FuncPathMSD(const ActionOptions&); @@ -149,7 +149,7 @@ struct pairordering { PLUMED_REGISTER_ACTION(FuncPathMSD,"FUNCPATHMSD") -void FuncPathMSD::registerKeywords(Keywords& keys){ +void FuncPathMSD::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","LAMBDA","the lambda parameter is needed for smoothing, is in the units of plumed"); @@ -160,10 +160,10 @@ void FuncPathMSD::registerKeywords(Keywords& keys){ keys.addOutputComponent("z","default","the distance from the path"); } FuncPathMSD::FuncPathMSD(const ActionOptions&ao): -Action(ao), -Function(ao), -neigh_size(-1), -neigh_stride(-1.) + Action(ao), + Function(ao), + neigh_size(-1), + neigh_stride(-1.) { parse("LAMBDA",lambda); @@ -171,52 +171,52 @@ neigh_stride(-1.) parse("NEIGH_STRIDE",neigh_stride); checkRead(); log.printf(" lambda is %f\n",lambda); - // list the action involved and check the type + // list the action involved and check the type std::string myname=getPntrToArgument(0)->getPntrToAction()->getName(); if(myname!="RMSD"&&myname!="CONTACTMAP"&&myname!="DISTANCE") error("One or more of your arguments is not of RMSD/CONTACTMAP/DISTANCE type!!!"); - for(unsigned i=1;igetPntrToAction()->getName()!=myname ) error("mismatch between the types of arguments"); - } - log.printf(" Consistency check completed! Your path cvs look good!\n"); + for(unsigned i=1; igetPntrToAction()->getName()!=myname ) error("mismatch between the types of arguments"); + } + log.printf(" Consistency check completed! Your path cvs look good!\n"); // do some neighbor printout - if(neigh_stride>0. || neigh_size>0){ - if(neigh_size>getNumberOfArguments()){ - log.printf(" List size required ( %d ) is too large: resizing to the maximum number of arg required: %d \n",neigh_size,getNumberOfArguments()); - neigh_size=getNumberOfArguments(); - } - log.printf(" Neighbor list enabled: \n"); - log.printf(" size : %d elements\n",neigh_size); - log.printf(" stride : %f time \n",neigh_stride); - }else{ - log.printf(" Neighbor list NOT enabled \n"); + if(neigh_stride>0. || neigh_size>0) { + if(neigh_size>getNumberOfArguments()) { + log.printf(" List size required ( %d ) is too large: resizing to the maximum number of arg required: %d \n",neigh_size,getNumberOfArguments()); + neigh_size=getNumberOfArguments(); + } + log.printf(" Neighbor list enabled: \n"); + log.printf(" size : %d elements\n",neigh_size); + log.printf(" stride : %f time \n",neigh_stride); + } else { + log.printf(" Neighbor list NOT enabled \n"); } addComponentWithDerivatives("s"); componentIsNotPeriodic("s"); addComponentWithDerivatives("z"); componentIsNotPeriodic("z"); - // now backup the arguments - for(unsigned i=0;iget())); s_path+=(indexmap[it.first])*it.second; partition+=it.second; @@ -225,7 +225,7 @@ void FuncPathMSD::calculate(){ val_s_path->set(s_path); val_z_path->set(-(1./lambda)*std::log(partition)); int n=0; - for(const auto & it : neighpair){ + for(const auto & it : neighpair) { double expval=it.second; double tmp=lambda*expval*(s_path-(indexmap[it.first]))/partition; setDerivative(val_s_path,n,tmp); @@ -238,60 +238,60 @@ void FuncPathMSD::calculate(){ /// /// this function updates the needed argument list /// -void FuncPathMSD::prepare(){ +void FuncPathMSD::prepare() { - // neighbor list: rank and activate the chain for the next step + // neighbor list: rank and activate the chain for the next step // neighbor list: if neigh_size<0 never sort and keep the full vector - // neighbor list: if neigh_size>0 - // if the size is full -> sort the vector and decide the dependencies for next step - // if the size is not full -> check if next step will need the full dependency otherwise keep this dependencies + // neighbor list: if neigh_size>0 + // if the size is full -> sort the vector and decide the dependencies for next step + // if the size is not full -> check if next step will need the full dependency otherwise keep this dependencies // here just resize the neighpair. The real resizing of reinit will be done by the prepare stage that will modify the list of arguments - if (neigh_size>0){ - if(neighpair.size()==allArguments.size()){ // I just did the complete round: need to sort, shorten and give it a go - // sort the values - sort(neighpair.begin(),neighpair.end(),pairordering()); - // resize the effective list - neighpair.resize(neigh_size); - log.printf(" NEIGH LIST NOW INCLUDE INDEXES: "); - for(int i=0;i0) { + if(neighpair.size()==allArguments.size()) { // I just did the complete round: need to sort, shorten and give it a go + // sort the values + sort(neighpair.begin(),neighpair.end(),pairordering()); + // resize the effective list + neighpair.resize(neigh_size); + log.printf(" NEIGH LIST NOW INCLUDE INDEXES: "); + for(int i=0; i argstocall; - //log.printf("PREPARING \n"); - argstocall.clear(); - if(!neighpair.empty()){ - for(const auto & it : neighpair){ - argstocall.push_back( it.first ); - // log.printf("CALLING %p %f ",(*it).first ,indexmap[(*it).first] ); + vector argstocall; +//log.printf("PREPARING \n"); + argstocall.clear(); + if(!neighpair.empty()) { + for(const auto & it : neighpair) { + argstocall.push_back( it.first ); + // log.printf("CALLING %p %f ",(*it).first ,indexmap[(*it).first] ); } - }else{ - for(unsigned i=0;iclearDerivatives(); - getPntrToComponent(i)->resizeDerivatives(getNumberOfArguments()); - } - //log.printf("PREPARING DONE! \n"); + } +// now the list of argument changes + requestArguments(argstocall); +//now resize the derivatives as well +//for each value in this action + for(int i=0; i< getNumberOfComponents(); i++) { + //resize the derivative to the number the + getPntrToComponent(i)->clearDerivatives(); + getPntrToComponent(i)->resizeDerivatives(getNumberOfArguments()); + } +//log.printf("PREPARING DONE! \n"); } } diff --git a/src/function/FuncSumHills.cpp b/src/function/FuncSumHills.cpp index 5231b0fdc9..65049b9b63 100644 --- a/src/function/FuncSumHills.cpp +++ b/src/function/FuncSumHills.cpp @@ -31,18 +31,18 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { -//+PLUMEDOC FUNCTION FUNCSUMHILLS +//+PLUMEDOC FUNCTION FUNCSUMHILLS /* This function is intended to be called by the command line tool sum_hills -and it is meant to integrate a HILLS file or an HILLS file interpreted as -a histogram i a variety of ways. Therefore it is not expected that you use this +and it is meant to integrate a HILLS file or an HILLS file interpreted as +a histogram i a variety of ways. Therefore it is not expected that you use this during your dynamics (it will crash!) -In the future one could implement periodic integration during the metadynamics +In the future one could implement periodic integration during the metadynamics or straightforward MD as a tool to check convergence \par Examples @@ -52,130 +52,131 @@ There are currently no examples for this keyword. */ //+ENDPLUMEDOC -class FilesHandler{ - vector filenames; - vector ifiles; - Action *action; - Log *log; - bool parallelread; - unsigned beingread; - bool isopen; - public: - FilesHandler(const vector &filenames, const bool ¶llelread , Action &myaction , Log &mylog); - bool readBunch(BiasRepresentation *br, int stride); - bool scanOneHill(BiasRepresentation *br, IFile *ifile ); - void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin); - void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma); - ~FilesHandler(); +class FilesHandler { + vector filenames; + vector ifiles; + Action *action; + Log *log; + bool parallelread; + unsigned beingread; + bool isopen; +public: + FilesHandler(const vector &filenames, const bool ¶llelread, Action &myaction, Log &mylog); + bool readBunch(BiasRepresentation *br, int stride); + bool scanOneHill(BiasRepresentation *br, IFile *ifile ); + void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin); + void getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma); + ~FilesHandler(); }; -FilesHandler::FilesHandler(const vector &filenames, const bool ¶llelread , Action &action , Log &mylog ):filenames(filenames),log(&mylog),parallelread(parallelread),beingread(0),isopen(false){ - this->action=&action; - for(unsigned i=0;ilink(action); - ifiles.push_back(ifile); - plumed_massert((ifile->FileExist(filenames[i])), "the file "+filenames[i]+" does not exist " ); - } - +FilesHandler::FilesHandler(const vector &filenames, const bool ¶llelread, Action &action, Log &mylog ):filenames(filenames),log(&mylog),parallelread(parallelread),beingread(0),isopen(false) { + this->action=&action; + for(unsigned i=0; ilink(action); + ifiles.push_back(ifile); + plumed_massert((ifile->FileExist(filenames[i])), "the file "+filenames[i]+" does not exist " ); + } + } -FilesHandler::~FilesHandler(){ - for(unsigned i=0;iopen(filenames[beingread]);isopen=true; - } - int n; - while(true){ - bool fileisover=true; - while(scanOneHill(br,ff)){ - // here do the dump if needed - n=br->getNumberOfKernels(); - if(stride>0 && n%stride==0 && n!=0 ){ - (*log)<<" done with this chunk: now with "<close(); - isopen=false; - (*log)<<" now total "<getNumberOfKernels()<<" kernels \n"; - beingread++; - if(beingreadopen(filenames[beingread]); - (*log)<<" opening file "<open(filenames[beingread]); isopen=true; + } + int n; + while(true) { + bool fileisover=true; + while(scanOneHill(br,ff)) { + // here do the dump if needed + n=br->getNumberOfKernels(); + if(stride>0 && n%stride==0 && n!=0 ) { + (*log)<<" done with this chunk: now with "<close(); + isopen=false; + (*log)<<" now total "<getNumberOfKernels()<<" kernels \n"; + beingread++; + if(beingreadopen(filenames[beingread]); + (*log)<<" opening file "< vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin){ - // create the representation (no grid) - BiasRepresentation br(vals,cc); - // read all the kernels - readBunch(&br); - // loop over the kernels and get the support - br.getMinMaxBin(vmin,vmax,vbin); +void FilesHandler::getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin) { + // create the representation (no grid) + BiasRepresentation br(vals,cc); + // read all the kernels + readBunch(&br); + // loop over the kernels and get the support + br.getMinMaxBin(vmin,vmax,vbin); } -void FilesHandler::getMinMaxBin(vector vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma){ - BiasRepresentation br(vals,cc,histosigma); - // read all the kernels - readBunch(&br); - // loop over the kernels and get the support - br.getMinMaxBin(vmin,vmax,vbin); - //for(unsigned i=0;i vals, Communicator &cc, vector &vmin, vector &vmax, vector &vbin, vector &histosigma) { + BiasRepresentation br(vals,cc,histosigma); + // read all the kernels + readBunch(&br); + // loop over the kernels and get the support + br.getMinMaxBin(vmin,vmax,vbin); + //for(unsigned i=0;iscanField("time",dummy)){ - //(*log)<<" scanning one hill: "<FieldExist("biasf")) ifile->scanField("biasf",dummy); - if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy); - // keep this intermediate function in case you need to parse more data in the future - br->pushKernel(ifile); - //(*log)<<" read hill\n"; - if(br->hasSigmaInInput())ifile->allowIgnoredFields(); - ifile->scanField(); - return true; - }else{ - return false; - } +bool FilesHandler::scanOneHill(BiasRepresentation *br, IFile *ifile ) { + double dummy; + if(ifile->scanField("time",dummy)) { + //(*log)<<" scanning one hill: "<FieldExist("biasf")) ifile->scanField("biasf",dummy); + if(ifile->FieldExist("clock")) ifile->scanField("clock",dummy); + // keep this intermediate function in case you need to parse more data in the future + br->pushKernel(ifile); + //(*log)<<" read hill\n"; + if(br->hasSigmaInInput())ifile->allowIgnoredFields(); + ifile->scanField(); + return true; + } else { + return false; + } } -double mylog( double v1 ){ - return log(v1); +double mylog( double v1 ) { + return log(v1); } -double mylogder( double v1 ){ - return 1./v1; +double mylogder( double v1 ) { + return 1./v1; } @@ -183,8 +184,8 @@ double mylogder( double v1 ){ class FuncSumHills : public Function { - vector hillsFiles,histoFiles; - vector proj; + vector hillsFiles,histoFiles; + vector proj; int initstride; bool iscltool,integratehills,integratehisto,parallelread; bool negativebias; @@ -201,23 +202,23 @@ class FuncSumHills : explicit FuncSumHills(const ActionOptions&); ~FuncSumHills(); void calculate(); // this probably is not needed - bool checkFilesAreExisting(const vector & hills ); + bool checkFilesAreExisting(const vector & hills ); static void registerKeywords(Keywords& keys); }; PLUMED_REGISTER_ACTION(FuncSumHills,"FUNCSUMHILLS") -void FuncSumHills::registerKeywords(Keywords& keys){ +void FuncSumHills::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); - keys.use("ARG"); - keys.add("optional","HILLSFILES"," source file for hills creation(may be the same as HILLS)"); // this can be a vector! + keys.use("ARG"); + keys.add("optional","HILLSFILES"," source file for hills creation(may be the same as HILLS)"); // this can be a vector! keys.add("optional","HISTOFILES"," source file for histogram creation(may be the same as HILLS)"); // also this can be a vector! - keys.add("optional","HISTOSIGMA"," sigmas for binning when the histogram correction is needed "); + keys.add("optional","HISTOSIGMA"," sigmas for binning when the histogram correction is needed "); keys.add("optional","PROJ"," only with sumhills: the projection on the cvs"); keys.add("optional","KT"," only with sumhills: the kt factor when projection on cvs"); keys.add("optional","GRID_MIN","the lower bounds for the grid"); keys.add("optional","GRID_MAX","the upper bounds for the grid"); - keys.add("optional","GRID_BIN","the number of bins for the grid"); + keys.add("optional","GRID_BIN","the number of bins for the grid"); keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); keys.add("optional","INTERVAL","set monodimensional INTERVAL"); keys.add("optional","OUTHILLS"," output file for hills "); @@ -233,29 +234,29 @@ void FuncSumHills::registerKeywords(Keywords& keys){ } FuncSumHills::FuncSumHills(const ActionOptions&ao): -Action(ao), -Function(ao), -initstride(-1), -iscltool(false), -integratehills(false), -integratehisto(false), -parallelread(false), -negativebias(false), -nohistory(false), -minTOzero(false), -doInt(false), -lowI_(-1.), -uppI_(-1.), -beta(-1.), -fmt("%14.9f"), -biasrep(NULL), -historep(NULL) + Action(ao), + Function(ao), + initstride(-1), + iscltool(false), + integratehills(false), + integratehisto(false), + parallelread(false), + negativebias(false), + nohistory(false), + minTOzero(false), + doInt(false), + lowI_(-1.), + uppI_(-1.), + beta(-1.), + fmt("%14.9f"), + biasrep(NULL), + historep(NULL) { // format parse("FMT",fmt); - log<<" Output format is "< gmin; parseVector("GRID_MIN",gmin); @@ -273,20 +274,20 @@ historep(NULL) parseVector("GRID_SPACING",gspacing); plumed_massert(gspacing.size()==getNumberOfArguments() || gspacing.size()==0,"need GRID_SPACING argument for this") ; if(gspacing.size()!=getNumberOfArguments() && gspacing.size()!=0) error("not enough values for GRID_SPACING"); - if(gspacing.size()!=0 && gbin.size()==0){ + if(gspacing.size()!=0 && gbin.size()==0) { log<<" The number of bins will be estimated from GRID_SPACING\n"; - } else if(gspacing.size()!=0 && gbin.size()!=0){ + } else if(gspacing.size()!=0 && gbin.size()!=0) { log<<" You specified both GRID_BIN and GRID_SPACING\n"; log<<" The more conservative (highest) number of bins will be used for each variable\n"; } - if(gspacing.size()!=0) for(unsigned i=0;i tmpI(2); @@ -309,31 +310,31 @@ historep(NULL) if(gmax.size()==0) gmax.push_back(strsmax.str()); if(gbin.size()==0) gbin.push_back(200); } - - // hills file: + + // hills file: parseVector("HILLSFILES",hillsFiles); - if(hillsFiles.size()==0){ - integratehills=false; // default behaviour - }else{ - integratehills=true; - for(unsigned i=0;i histoSigma; - if(integratehisto){ - parseVector("HISTOSIGMA",histoSigma); - for(unsigned i=0;igetName()); + for(unsigned i=0; igetName()); } - // add some automatic hills width: not in case stride is defined + // add some automatic hills width: not in case stride is defined // since when you start from zero the automatic size will be zero! - if(gmin.size()==0 || gmax.size()==0){ - log<<" \n"; - log<<" No boundaries defined: need to do a prescreening of hills \n"; - std::vector tmphillsvalues, tmphistovalues; - if(integratehills) { - for(unsigned i=0;igetName(); - for(unsigned j=0;j tmphillsvalues, tmphistovalues; + if(integratehills) { + for(unsigned i=0; igetName(); + for(unsigned j=0; j vmin,vmax; - vector vbin; - hillsHandler.getMinMaxBin(tmphillsvalues,comm,vmin,vmax,vbin); - log<<" found boundaries from hillsfile: \n"; - gmin.resize(vmin.size()); - gmax.resize(vmax.size()); - if(gbin.size()==0){ - gbin=vbin; - }else{ - log<<" found nbins in input, this overrides the automatic choice \n"; - } - for(unsigned i=0;igetName()<<" min: "< vmin,vmax; - vector vbin; - histoHandler.getMinMaxBin(tmphistovalues,comm,vmin,vmax,vbin,histoSigma); - log<<" found boundaries from histofile: \n"; - gmin.resize(vmin.size()); - gmax.resize(vmax.size()); - if(gbin.size()==0){ - gbin=vbin; - }else{ - log<<" found nbins in input, this overrides the automatic choice \n"; - } - for(unsigned i=0;i vmin,vmax; + vector vbin; + hillsHandler.getMinMaxBin(tmphillsvalues,comm,vmin,vmax,vbin); + log<<" found boundaries from hillsfile: \n"; + gmin.resize(vmin.size()); + gmax.resize(vmax.size()); + if(gbin.size()==0) { + gbin=vbin; + } else { + log<<" found nbins in input, this overrides the automatic choice \n"; + } + for(unsigned i=0; igetName()<<" min: "< vmin,vmax; + vector vbin; + histoHandler.getMinMaxBin(tmphistovalues,comm,vmin,vmax,vbin,histoSigma); + log<<" found boundaries from histofile: \n"; + gmin.resize(vmin.size()); + gmax.resize(vmax.size()); + if(gbin.size()==0) { + gbin=vbin; + } else { + log<<" found nbins in input, this overrides the automatic choice \n"; + } + for(unsigned i=0; i0.,"if you make a projection or a histogram correction then you need KT flag!"); - beta=1./beta; - log<<" beta is "<0.,"if you make a projection or a histogram correction then you need KT flag!"); + beta=1./beta; + log<<" beta is "< tmphillsvalues, tmphistovalues; + std::vector tmphillsvalues, tmphistovalues; if(integratehills) { - for(unsigned i=0;igetName(); - for(unsigned j=0;jgetName(); + for(unsigned j=0; jsetRescaledToBias(true); - log<<" required the -bias instead of the free energy \n"; - if(initstride<0){outhills="negativebias.dat";} - else{outhills="negativebias_";} - } + // check if the files exists + if(integratehills) { + checkFilesAreExisting(hillsFiles); + biasrep=new BiasRepresentation(tmphillsvalues,comm, gmin, gmax, gbin, doInt, lowI_, uppI_); + if(negativebias) { + biasrep->setRescaledToBias(true); + log<<" required the -bias instead of the free energy \n"; + if(initstride<0) {outhills="negativebias.dat";} + else {outhills="negativebias_";} + } } parse("OUTHILLS",outhills); parse("OUTHISTO",outhisto); - if(integratehills)log<<" output file for fes/bias is : "<clear();log<<" clearing history before reading a new block\n";}; - log<<" reading hills: \n"; - ibias=hillsHandler->readBunch(biasrep,initstride) ; log<<"\n"; - } - - if( integratehisto && ihisto ){ - if(nohistory){historep->clear();log<<" clearing history before reading a new block\n";}; - log<<" reading histogram: \n"; - ihisto=histoHandler->readBunch(historep,initstride) ; log<<"\n"; - } - - // dump: need to project? - if(proj.size()!=0){ - - if(integratehills){ - - log<<" Bias: Projecting on subgrid... \n"; - BiasWeight Bw(beta); - Grid biasGrid=*(biasrep->getGridPtr()); - Grid smallGrid=biasGrid.project(proj,&Bw); - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhills+ostr.str()+".dat" ;}else{myout=outhills;} - log<<" Bias: Writing subgrid on file "<getGridPtr()); - - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhisto+ostr.str()+".dat" ;}else{myout=outhisto;} - log<<" Histo: Writing subgrid on file "<getGridPtr()); - biasGrid.scaleAllValuesAndDerivatives(-1.); - - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhills+ostr.str()+".dat" ;}else{myout=outhills;} - log<<" Writing full grid on file "<getGridPtr()); - // do this if you want a free energy from a grid, otherwise do not - histoGrid.applyFunctionAllValuesAndDerivatives(&mylog,&mylogder); - histoGrid.scaleAllValuesAndDerivatives(-1./beta); - - OFile gridfile; gridfile.link(*this); - std::ostringstream ostr;ostr<0){ myout=outhisto+ostr.str()+".dat" ;}else{myout=outhisto;} - log<<" Writing full grid on file "<clear(); log<<" clearing history before reading a new block\n";}; + log<<" reading hills: \n"; + ibias=hillsHandler->readBunch(biasrep,initstride) ; log<<"\n"; + } + + if( integratehisto && ihisto ) { + if(nohistory) {historep->clear(); log<<" clearing history before reading a new block\n";}; + log<<" reading histogram: \n"; + ihisto=histoHandler->readBunch(historep,initstride) ; log<<"\n"; + } + + // dump: need to project? + if(proj.size()!=0) { + + if(integratehills) { + + log<<" Bias: Projecting on subgrid... \n"; + BiasWeight Bw(beta); + Grid biasGrid=*(biasrep->getGridPtr()); + Grid smallGrid=biasGrid.project(proj,&Bw); + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhills+ostr.str()+".dat" ;} else {myout=outhills;} + log<<" Bias: Writing subgrid on file "<getGridPtr()); + + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhisto+ostr.str()+".dat" ;} else {myout=outhisto;} + log<<" Histo: Writing subgrid on file "<getGridPtr()); + biasGrid.scaleAllValuesAndDerivatives(-1.); + + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhills+ostr.str()+".dat" ;} else {myout=outhills;} + log<<" Writing full grid on file "<getGridPtr()); + // do this if you want a free energy from a grid, otherwise do not + histoGrid.applyFunctionAllValuesAndDerivatives(&mylog,&mylogder); + histoGrid.scaleAllValuesAndDerivatives(-1./beta); + + OFile gridfile; gridfile.link(*this); + std::ostringstream ostr; ostr<0) { myout=outhisto+ostr.str()+".dat" ;} else {myout=outhisto;} + log<<" Writing full grid on file "< & hills ){ - plumed_massert(hills.size()!=0,"the number of files provided should be at least one" ); - IFile *ifile = new IFile(); - ifile->link(*this); - for(unsigned i=0; i< hills.size();i++){ - plumed_massert(ifile->FileExist(hills[i]),"missing file "+hills[i]); - } - delete ifile; - return true; +bool FuncSumHills::checkFilesAreExisting(const vector & hills ) { + plumed_massert(hills.size()!=0,"the number of files provided should be at least one" ); + IFile *ifile = new IFile(); + ifile->link(*this); + for(unsigned i=0; i< hills.size(); i++) { + plumed_massert(ifile->FileExist(hills[i]),"missing file "+hills[i]); + } + delete ifile; + return true; } diff --git a/src/function/Function.cpp b/src/function/Function.cpp index 39b5ea82be..0852d31810 100644 --- a/src/function/Function.cpp +++ b/src/function/Function.cpp @@ -23,10 +23,10 @@ #include "tools/OpenMP.h" using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { -void Function::registerKeywords(Keywords& keys){ +void Function::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionWithValue::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -34,29 +34,29 @@ void Function::registerKeywords(Keywords& keys){ } Function::Function(const ActionOptions&ao): -Action(ao), -ActionWithValue(ao), -ActionWithArguments(ao) + Action(ao), + ActionWithValue(ao), + ActionWithArguments(ao) { } -void Function::addValueWithDerivatives(){ +void Function::addValueWithDerivatives() { plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values"); - ActionWithValue::addValueWithDerivatives(); + ActionWithValue::addValueWithDerivatives(); getPntrToValue()->resizeDerivatives(getNumberOfArguments()); - if( keywords.exists("PERIODIC") ){ - std::vector period; - parseVector("PERIODIC",period); - if(period.size()==1 && period[0]=="NO"){ - setNotPeriodic(); - } else if(period.size()==2){ - setPeriodic(period[0],period[1]); - } else error("missing PERIODIC keyword"); + if( keywords.exists("PERIODIC") ) { + std::vector period; + parseVector("PERIODIC",period); + if(period.size()==1 && period[0]=="NO") { + setNotPeriodic(); + } else if(period.size()==2) { + setPeriodic(period[0],period[1]); + } else error("missing PERIODIC keyword"); } -} - -void Function::addComponentWithDerivatives( const std::string& name ){ +} + +void Function::addComponentWithDerivatives( const std::string& name ) { plumed_massert( getNumberOfArguments()!=0, "for functions you must requestArguments before adding values"); ActionWithValue::addComponentWithDerivatives(name); getPntrToComponent(name)->resizeDerivatives(getNumberOfArguments()); @@ -83,19 +83,19 @@ void Function::apply() vector omp_f(noa,0.0); vector forces(noa); #pragma omp for reduction( + : at_least_one_forced) - for(unsigned i=rank;iapplyForce(forces)) { at_least_one_forced+=1; - for(unsigned j=0;j0&&ncp>4*cgs) { comm.Sum(&f[0],noa); comm.Sum(at_least_one_forced); } - if(at_least_one_forced>0) for(unsigned i=0;iaddForce(f[i]); + if(at_least_one_forced>0) for(unsigned i=0; iaddForce(f[i]); } } diff --git a/src/function/Function.h b/src/function/Function.h index e0dfae9080..02215e1cce 100644 --- a/src/function/Function.h +++ b/src/function/Function.h @@ -26,12 +26,12 @@ #include "core/ActionWithArguments.h" #include "tools/Communicator.h" -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { /** \ingroup INHERIT -This is the abstract base class to use for implementing new CV function, within it there is +This is the abstract base class to use for implementing new CV function, within it there is \ref AddingAFunction "information" as to how to go about implementing a new function. */ @@ -43,27 +43,27 @@ class Function: void setDerivative(int,double); void setDerivative(Value*,int,double); void addValueWithDerivatives(); - void addComponentWithDerivatives( const std::string& name ); + void addComponentWithDerivatives( const std::string& name ); public: explicit Function(const ActionOptions&); - virtual ~Function(){} + virtual ~Function() {} void apply(); static void registerKeywords(Keywords&); unsigned getNumberOfDerivatives(); }; inline -void Function::setDerivative(Value*v,int i,double d){ +void Function::setDerivative(Value*v,int i,double d) { v->addDerivative(i,d); } inline -void Function::setDerivative(int i,double d){ +void Function::setDerivative(int i,double d) { setDerivative(getPntrToValue(),i,d); } inline -unsigned Function::getNumberOfDerivatives(){ +unsigned Function::getNumberOfDerivatives() { return getNumberOfArguments(); } diff --git a/src/function/LocalEnsemble.cpp b/src/function/LocalEnsemble.cpp index aee9a076fa..6e3bd96f68 100644 --- a/src/function/LocalEnsemble.cpp +++ b/src/function/LocalEnsemble.cpp @@ -25,15 +25,15 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION LOCALENSEMBLE /* Calculates the average over multiple arguments. If more than one collective variable is given for each argument then they -are averaged separately. The average is stored in a component labelled label.cvlabel. +are averaged separately. The average is stored in a component labelled label.cvlabel. \par Examples The following input tells plumed to calculate the chemical shifts for four @@ -88,7 +88,7 @@ class LocalEnsemble : PLUMED_REGISTER_ACTION(LocalEnsemble,"LOCALENSEMBLE") -void LocalEnsemble::registerKeywords(Keywords& keys){ +void LocalEnsemble::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.add("compulsory","NUM","the number of local replicas"); @@ -96,24 +96,24 @@ void LocalEnsemble::registerKeywords(Keywords& keys){ } LocalEnsemble::LocalEnsemble(const ActionOptions&ao): -Action(ao), -Function(ao), -ens_dim(0) + Action(ao), + Function(ao), + ens_dim(0) { parse("NUM",ens_dim); if(ens_dim==0) error("NUM should be greater or equal to 1"); vector arg; int oldsize=-1; - for(unsigned i=1;i<=ens_dim;++i ){ + for(unsigned i=1; i<=ens_dim; ++i ) { vector larg; if(!parseArgumentList("ARG",i,larg)) break; - for(unsigned j=0;jgetName().c_str()); + for(unsigned j=0; jgetName().c_str()); log.printf("\n"); } } @@ -121,9 +121,9 @@ ens_dim(0) narg = arg.size()/ens_dim; // these are the averages - for(unsigned i=0;igetName(); - addComponentWithDerivatives(s); + addComponentWithDerivatives(s); getPntrToComponent(i)->setNotPeriodic(); } @@ -132,18 +132,18 @@ ens_dim(0) void LocalEnsemble::calculate() { - const double fact = 1.0/static_cast(ens_dim); + const double fact = 1.0/static_cast(ens_dim); #pragma omp parallel for num_threads(OpenMP::getNumThreads()) - for(unsigned i=0;iset(mean); - } + } } } diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp index 55a7f439ee..59e6e9bf05 100644 --- a/src/function/Matheval.cpp +++ b/src/function/Matheval.cpp @@ -28,8 +28,8 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION MATHEVAL @@ -186,7 +186,7 @@ class Matheval : #ifdef __PLUMED_HAS_MATHEVAL PLUMED_REGISTER_ACTION(Matheval,"MATHEVAL") -void Matheval::registerKeywords(Keywords& keys){ +void Matheval::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); keys.use("PERIODIC"); keys.add("compulsory","FUNC","the function you wish to evaluate"); @@ -194,14 +194,14 @@ void Matheval::registerKeywords(Keywords& keys){ } Matheval::Matheval(const ActionOptions&ao): -Action(ao), -Function(ao), -evaluator_deriv(getNumberOfArguments()), -values(getNumberOfArguments()), -names(getNumberOfArguments()) + Action(ao), + Function(ao), + evaluator_deriv(getNumberOfArguments()), + values(getNumberOfArguments()), + names(getNumberOfArguments()) { parseVector("VAR",var); - if(var.size()==0){ + if(var.size()==0) { var.resize(getNumberOfArguments()); if(getNumberOfArguments()>3) error("Using more than 3 arguments you should explicitly write their names with VAR"); @@ -212,7 +212,7 @@ names(getNumberOfArguments()) if(var.size()!=getNumberOfArguments()) error("Size of VAR array should be the same as number of arguments"); parse("FUNC",func); - addValueWithDerivatives(); + addValueWithDerivatives(); checkRead(); evaluator=evaluator_create(const_cast(func.c_str())); @@ -222,46 +222,46 @@ names(getNumberOfArguments()) char **check_names; int check_count; evaluator_get_variables(evaluator,&check_names,&check_count); - if(check_count!=int(getNumberOfArguments())){ + if(check_count!=int(getNumberOfArguments())) { string sc; Tools::convert(check_count,sc); error("Your function string contains "+sc+" arguments. This should be equal to the number of ARGs"); } - for(unsigned i=0;i(var[i].c_str())); log.printf(" with function : %s\n",func.c_str()); log.printf(" with variables :"); - for(unsigned i=0;i(var[i].c_str()); +void Matheval::calculate() { + for(unsigned i=0; i(var[i].c_str()); setValue(evaluator_evaluate(evaluator,names.size(),&names[0],&values[0])); - for(unsigned i=0;ix_{N-1} +y_N ; if x>x_{N-1} \f] \f[ -y_1 ; if x pp; if(!parseNumberedVector("POINT",i,pp) ) break; - if(pp.size()!=2) error("points should be in x,y format"); - points.push_back(std::pair(pp[0],pp[1])); - if(i>0 && points[i].first<=points[i-1].first) error("points abscissas should be monotonously increasing"); + if(pp.size()!=2) error("points should be in x,y format"); + points.push_back(std::pair(pp[0],pp[1])); + if(i>0 && points[i].first<=points[i-1].first) error("points abscissas should be monotonously increasing"); } - for(unsigned i=0;iisPeriodic()) - error("Cannot use PIECEWISE on periodic arguments"); + error("Cannot use PIECEWISE on periodic arguments"); - if(getNumberOfArguments()==1){ - addValueWithDerivatives(); + if(getNumberOfArguments()==1) { + addValueWithDerivatives(); setNotPeriodic(); - }else{ - for(unsigned i=0;igetName()+"_pfunc" ); getPntrToComponent(i)->setNotPeriodic(); } @@ -123,22 +123,22 @@ Function(ao) checkRead(); log.printf(" on points:"); - for(unsigned i=0;ilabel.1, the second lowest will be labelled label.2 and so on. +This function sorts its arguments according to their magnitudes. The lowest argument will be +labelled label.1, the second lowest will be labelled label.2 and so on. \par Examples The following input tells plumed to print the distance of the closest and of @@ -69,38 +69,38 @@ class Sort : PLUMED_REGISTER_ACTION(Sort,"SORT") -void Sort::registerKeywords(Keywords& keys){ +void Sort::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); keys.use("ARG"); ActionWithValue::useCustomisableComponents(keys); } Sort::Sort(const ActionOptions&ao): -Action(ao), -Function(ao) + Action(ao), + Function(ao) { - for(unsigned i=0;iisPeriodic()) error("Cannot sort periodic values (check argument "+s+")"); - addComponentWithDerivatives(s); + addComponentWithDerivatives(s); getPntrToComponent(i)->setNotPeriodic(); } checkRead(); } -void Sort::calculate(){ +void Sort::calculate() { vector > vals(getNumberOfArguments()); - for(unsigned i=0;iset(vals[i].first); setDerivative(v,vals[i].second,1.0); diff --git a/src/function/Stats.cpp b/src/function/Stats.cpp index c9f5ef8040..429442e6d8 100644 --- a/src/function/Stats.cpp +++ b/src/function/Stats.cpp @@ -24,8 +24,8 @@ using namespace std; -namespace PLMD{ -namespace function{ +namespace PLMD { +namespace function { //+PLUMEDOC FUNCTION STATS /* @@ -38,7 +38,7 @@ from other actions using PARARG (for example using experimental values from coll \ref CS2BACKBONE, \ref RDC, \ref NOE, \ref PRE). \par Examples -The following input tells plumed to print the distance between three couple of atoms +The following input tells plumed to print the distance between three couple of atoms and compare them with three reference distances. \verbatim @@ -69,28 +69,28 @@ class Stats : PLUMED_REGISTER_ACTION(Stats,"STATS") -void Stats::registerKeywords(Keywords& keys){ +void Stats::registerKeywords(Keywords& keys) { Function::registerKeywords(keys); useCustomisableComponents(keys); keys.use("ARG"); - keys.add("optional","PARARG","the input for this action is the scalar output from one or more other actions without derivatives."); + keys.add("optional","PARARG","the input for this action is the scalar output from one or more other actions without derivatives."); keys.add("optional","PARAMETERS","the parameters of the arguments in your function"); keys.addFlag("SQDEVSUM",false,"calculates only SQDEVSUM"); keys.addFlag("SQDEV",false,"calculates and store the SQDEV as components"); keys.addFlag("UPPERDISTS",false,"calculates and store the SQDEV as components"); - keys.addOutputComponent("sqdevsum","default","the sum of the squared deviations between arguments and parameters"); - keys.addOutputComponent("corr","default","the correlation between arguments and parameters"); - keys.addOutputComponent("slope","default","the slope of a linear fit between arguments and parameters"); - keys.addOutputComponent("intercept","default","the intercept of a linear fit between arguments and parameters"); - keys.addOutputComponent("sqd","SQDEV","the squared deviations between arguments and parameters"); + keys.addOutputComponent("sqdevsum","default","the sum of the squared deviations between arguments and parameters"); + keys.addOutputComponent("corr","default","the correlation between arguments and parameters"); + keys.addOutputComponent("slope","default","the slope of a linear fit between arguments and parameters"); + keys.addOutputComponent("intercept","default","the intercept of a linear fit between arguments and parameters"); + keys.addOutputComponent("sqd","SQDEV","the squared deviations between arguments and parameters"); } Stats::Stats(const ActionOptions&ao): -Action(ao), -Function(ao), -sqdonly(false), -components(false), -upperd(false) + Action(ao), + Function(ao), + sqdonly(false), + components(false), + upperd(false) { parseVector("PARAMETERS",parameters); if(parameters.size()!=static_cast(getNumberOfArguments())&&!parameters.empty()) @@ -102,13 +102,13 @@ upperd(false) if(!arg2.empty()) { if(parameters.size()>0) error("It is not possible to use PARARG and PARAMETERS together"); if(arg2.size()!=getNumberOfArguments()) error("Size of PARARG array should be the same as number for arguments in ARG"); - for(unsigned i=0;iget()); + for(unsigned i=0; iget()); if(arg2[i]->hasDerivatives()==true) error("PARARG can only accept arguments without derivatives"); } } - if(parameters.size()!=getNumberOfArguments()) + if(parameters.size()!=getNumberOfArguments()) error("PARARG or PARAMETERS arrays should include the same number of elements as the arguments in ARG"); if(getNumberOfArguments()<2) error("STATS need at least two arguments to be used"); @@ -123,12 +123,12 @@ upperd(false) if(!arg2.empty()) log.printf(" using %zu parameters from inactive actions:", arg2.size()); else log.printf(" using %zu parameters:", arg2.size()); - for(unsigned i=0;iset(dev*dev); - } else { + } else { nsqd += dev*dev; } setDerivative(val,i,2.*dev); @@ -175,8 +175,8 @@ void Stats::calculate() } else { double scx=0., scx2=0., scy=0., scy2=0., scxy=0.; - - for(unsigned i=0;iset(inter); /* derivatives */ - for(unsigned i=0;icalculate( getArguments(), mypack, false ); setValue(r); - for(unsigned i=0;i0){ + if(file.length()>0) { ofile.open(file); log.printf(" on file %s\n",file.c_str()); } else { @@ -104,17 +104,17 @@ novirial(false){ checkRead(); } -void Debug::apply(){ - if(logActivity){ +void Debug::apply() { + if(logActivity) { const ActionSet&actionSet(plumed.getActionSet()); int a=0; - for(const auto & p : actionSet){ + for(const auto & p : actionSet) { if(dynamic_cast(p))continue; if(p->isActive()) a++; }; - if(a>0){ + if(a>0) { ofile.printf("activity at step %i: ",getStep()); - for(const auto & p : actionSet){ + for(const auto & p : actionSet) { if(dynamic_cast(p))continue; if(p->isActive()) ofile.printf("+"); else ofile.printf("-"); @@ -122,13 +122,13 @@ void Debug::apply(){ ofile.printf("\n"); }; }; - if(logRequestedAtoms){ + if(logRequestedAtoms) { ofile.printf("requested atoms at step %i: ",getStep()); int* l; int n; plumed.cmd("createFullList",&n); plumed.cmd("getFullList",&l); - for(int i=0;i0){ + if(ntype.length()>0) { if(ntype!="xyz" && ntype!="gro" #ifdef __PLUMED_HAS_XDRFILE - && ntype!="xtc" && ntype!="trr" + && ntype!="xtc" && ntype!="trr" #endif - ) error("TYPE cannot be understood"); + ) error("TYPE cannot be understood"); log<<" file type enforced to be "<0){ + if(precision.length()>0) { Tools::convert(precision,iprecision); log<<" with precision "< moldat=plumed.getActionSet().select(); - if( moldat.size()==1 ){ + if( moldat.size()==1 ) { log<<" MOLINFO DATA found, using proper atom names\n"; names.resize(atoms.size()); - for(unsigned i=0;igetAtomName(atoms[i]); + for(unsigned i=0; igetAtomName(atoms[i]); residueNumbers.resize(atoms.size()); - for(unsigned i=0;igetResidueNumber(atoms[i]); + for(unsigned i=0; igetResidueNumber(atoms[i]); residueNames.resize(atoms.size()); - for(unsigned i=0;igetResidueName(atoms[i]); + for(unsigned i=0; igetResidueName(atoms[i]); } } -void DumpAtoms::update(){ - if(type=="xyz"){ +void DumpAtoms::update() { + if(type=="xyz") { of.printf("%d\n",getNumberOfAtoms()); const Tensor & t(getPbc().getBox()); - if(getPbc().isOrthorombic()){ + if(getPbc().isOrthorombic()) { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ + } else { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(), - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); } - for(unsigned i=0;i0) if(names[i].length()>0) name=names[i].c_str(); of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),name,lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2)); } - } else if(type=="gro"){ + } else if(type=="gro") { const Tensor & t(getPbc().getBox()); of.printf("Made with PLUMED t=%f\n",getTime()/plumed.getAtoms().getUnits().getTime()); of.printf("%d\n",getNumberOfAtoms()); - for(unsigned i=0;i0) resname=residueNames[i]; of.printf(("%5u%-5s%5s%5d"+fmt_gro_pos+fmt_gro_pos+fmt_gro_pos+"\n").c_str(), - residueNumber%100000,resname.c_str(),name,getAbsoluteIndex(i).serial()%100000, - lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2)); + residueNumber%100000,resname.c_str(),name,getAbsoluteIndex(i).serial()%100000, + lenunit*getPosition(i)(0),lenunit*getPosition(i)(1),lenunit*getPosition(i)(2)); } of.printf((fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+" "+fmt_gro_box+"\n").c_str(), - lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2), - lenunit*t(0,1),lenunit*t(0,2),lenunit*t(1,0), - lenunit*t(1,2),lenunit*t(2,0),lenunit*t(2,1)); + lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2), + lenunit*t(0,1),lenunit*t(0,2),lenunit*t(1,0), + lenunit*t(1,2),lenunit*t(2,0),lenunit*t(2,1)); #if defined(__PLUMED_HAS_XDRFILE) - } else if(type=="xtc" || type=="trr"){ + } else if(type=="xtc" || type=="trr") { matrix box; const Tensor & t(getPbc().getBox()); int natoms=getNumberOfAtoms(); int step=getStep(); float time=getTime()/plumed.getAtoms().getUnits().getTime(); float precision=Tools::fastpow(10.0,iprecision); - for(int i=0;i<3;i++) for(int j=0;j<3;j++) box[i][j]=lenunit*t(i,j); + for(int i=0; i<3; i++) for(int j=0; j<3; j++) box[i][j]=lenunit*t(i,j); rvec* pos=new rvec [natoms]; // Notice that code below cannot throw any exception. // Thus, this pointer is excepton safe - for(int i=0;igetPntrToAction())->turnOnDerivatives(); unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); if( npar==0 ) error("one or more arguments has no derivatives"); - for(unsigned i=1;igetPntrToAction())->turnOnDerivatives(); - if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) error("the number of derivatives must be the same in all values being dumped"); + for(unsigned i=1; igetPntrToAction())->turnOnDerivatives(); + if( npar!=getPntrToArgument(i)->getNumberOfDerivatives() ) error("the number of derivatives must be the same in all values being dumped"); } checkRead(); } -void DumpDerivatives::update(){ +void DumpDerivatives::update() { unsigned npar=getPntrToArgument(0)->getNumberOfDerivatives(); - for(unsigned ipar=0;ipargetName(),getPntrToArgument(i)->getDerivative(ipar) ); } @@ -125,7 +125,7 @@ void DumpDerivatives::update(){ } } -DumpDerivatives::~DumpDerivatives(){ +DumpDerivatives::~DumpDerivatives() { } } diff --git a/src/generic/DumpForces.cpp b/src/generic/DumpForces.cpp index ab96bb0708..f5e204d65b 100644 --- a/src/generic/DumpForces.cpp +++ b/src/generic/DumpForces.cpp @@ -26,12 +26,12 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC PRINTANALYSIS DUMPFORCES /* -Dump the force acting on one of a values in a file. +Dump the force acting on one of a values in a file. For a CV this command will dump the force on the CV itself. Be aware that in order to have the forces on the atoms @@ -42,7 +42,7 @@ by specifying more than one argument. You can control the buffering of output us \par Examples The following input instructs plumed to write a file called forces that contains -the force acting on the distance between atoms 1 and 2. +the force acting on the distance between atoms 1 and 2. \verbatim DISTANCE ATOM=1,2 LABEL=distance DUMPFORCES ARG=distance STRIDE=1 FILE=forces @@ -54,24 +54,24 @@ DUMPFORCES ARG=distance STRIDE=1 FILE=forces //+ENDPLUMEDOC class DumpForces : -public ActionPilot, -public ActionWithArguments + public ActionPilot, + public ActionWithArguments { string file; string fmt; OFile of; public: - void calculate(){} + void calculate() {} explicit DumpForces(const ActionOptions&); static void registerKeywords(Keywords& keys); - void apply(){} + void apply() {} void update(); ~DumpForces(); }; PLUMED_REGISTER_ACTION(DumpForces,"DUMPFORCES") -void DumpForces::registerKeywords(Keywords& keys){ +void DumpForces::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -85,10 +85,10 @@ void DumpForces::registerKeywords(Keywords& keys){ } DumpForces::DumpForces(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -fmt("%15.10f") + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + fmt("%15.10f") { parse("FILE",file); if( file.length()==0 ) error("name of file was not specified"); @@ -103,17 +103,17 @@ fmt("%15.10f") } -void DumpForces::update(){ +void DumpForces::update() { of.fmtField(" %f"); of.printField("time",getTime()); - for(unsigned i=0;igetName(),getPntrToArgument(i)->getForce()); } of.printField(); } -DumpForces::~DumpForces(){ +DumpForces::~DumpForces() { } } diff --git a/src/generic/DumpMassCharge.cpp b/src/generic/DumpMassCharge.cpp index f6f4e83923..4153bc8384 100644 --- a/src/generic/DumpMassCharge.cpp +++ b/src/generic/DumpMassCharge.cpp @@ -30,7 +30,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC PRINTANALYSIS DUMPMASSCHARGE /* @@ -59,7 +59,7 @@ DUMPMASSCHARGE FILE=mcfile (see also \ref COM and \ref PRINT) In this way, you will be able to use the same masses while processing -a trajectory from the \ref driver . To do so, you need to +a trajectory from the \ref driver . To do so, you need to add the --mc flag on the driver command line, e.g. \verbatim plumed driver --mc mcfile --plumed plumed.dat --ixyz traj.xyz @@ -100,14 +100,14 @@ class DumpMassCharge: explicit DumpMassCharge(const ActionOptions&); ~DumpMassCharge(); static void registerKeywords( Keywords& keys ); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void update(); }; PLUMED_REGISTER_ACTION(DumpMassCharge,"DUMPMASSCHARGE") -void DumpMassCharge::registerKeywords( Keywords& keys ){ +void DumpMassCharge::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -128,8 +128,8 @@ DumpMassCharge::DumpMassCharge(const ActionOptions&ao): parseAtomList("ATOMS",atoms); - if(atoms.size()==0){ - for(unsigned i=0;igetPntrToAction())->turnOnDerivatives(); + for(unsigned i=0; igetPntrToAction())->turnOnDerivatives(); } } -void DumpProjections::update(){ +void DumpProjections::update() { of.fmtField(" %f").printField("time",getTime()); - for(unsigned i=0;igetName()+"-"+getPntrToArgument(j)->getName(),getProjection(i,j)); } @@ -113,7 +113,7 @@ void DumpProjections::update(){ of.printField(); } -DumpProjections::~DumpProjections(){ +DumpProjections::~DumpProjections() { } } diff --git a/src/generic/EffectiveEnergyDrift.cpp b/src/generic/EffectiveEnergyDrift.cpp index 885491e2ba..1c3961390a 100644 --- a/src/generic/EffectiveEnergyDrift.cpp +++ b/src/generic/EffectiveEnergyDrift.cpp @@ -20,7 +20,7 @@ along with plumed. If not, see . +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ -/* +/* This class was originally written by Marco Jacopo Ferrarotti (marco.ferrarotti@gmail.com) and Giovanni Bussi */ @@ -42,7 +42,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC EFFECTIVE_ENERGY_DRIFT /* @@ -57,7 +57,7 @@ simulation on the Debye-Huckel energy. Since this variable is very expensive, it could be conveniently computed every second step. \verbatim dh: DHENERGY GROUPA=1-10 GROUPB=11-20 EPSILON=80.0 I=0.1 TEMP=300.0 -METAD ARG=dh HEIGHT=0.5 SIGMA=0.1 PACE=500 STRIDE=2 +METAD ARG=dh HEIGHT=0.5 SIGMA=0.1 PACE=500 STRIDE=2 EFFECTIVE_ENERGY_DRIFT PRINT_STRIDE=100 FILE=eff \endverbatim @@ -73,7 +73,7 @@ EFFECTIVE_ENERGY_DRIFT PRINT_STRIDE=100 FILE=eff class EffectiveEnergyDrift: -public ActionPilot{ + public ActionPilot { OFile output; long int printStride; @@ -115,14 +115,14 @@ public ActionPilot{ static void registerKeywords( Keywords& keys ); - void calculate(){}; - void apply(){}; + void calculate() {}; + void apply() {}; void update(); }; PLUMED_REGISTER_ACTION(EffectiveEnergyDrift,"EFFECTIVE_ENERGY_DRIFT") -void EffectiveEnergyDrift::registerKeywords( Keywords& keys ){ +void EffectiveEnergyDrift::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); @@ -136,14 +136,14 @@ void EffectiveEnergyDrift::registerKeywords( Keywords& keys ){ } EffectiveEnergyDrift::EffectiveEnergyDrift(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -eed(0.0), -atoms(plumed.getAtoms()), -nProc(plumed.comm.Get_size()), -initialBias(0.0), -isFirstStep(true), -ensemble(false) + Action(ao), + ActionPilot(ao), + eed(0.0), + atoms(plumed.getAtoms()), + nProc(plumed.comm.Get_size()), + initialBias(0.0), + isFirstStep(true), + ensemble(false) { //stride must be == 1 if(getStride()!=1) error("EFFECTIVE_ENERGY_DRIFT must have STRIDE=1 to work properly"); @@ -163,13 +163,13 @@ ensemble(false) parseFlag("ENSEMBLE",ensemble); if(ensemble&&comm.Get_rank()==0) { if(multi_sim_comm.Get_size()<2) error("You CANNOT run Replica-Averaged simulations without running multiple replicas!\n"); - } + } log<<"Bibliography "< tmpActions=plumed.getActionSet().select(); - for(unsigned i=0;iexists(tmpActions[i]->getLabel()+".bias")) biases.push_back(tmpActions[i]); + for(unsigned i=0; iexists(tmpActions[i]->getLabel()+".bias")) biases.push_back(tmpActions[i]); //resize counters and displacements useful to communicate with MPI_Allgatherv indexCnt.resize(nProc); @@ -182,11 +182,11 @@ ensemble(false) backmap.resize(atoms.getNatoms()); } -EffectiveEnergyDrift::~EffectiveEnergyDrift(){ +EffectiveEnergyDrift::~EffectiveEnergyDrift() { } -void EffectiveEnergyDrift::update(){ +void EffectiveEnergyDrift::update() { bool pbc=atoms.getPbc().isSet(); //retrive data of local atoms @@ -194,11 +194,11 @@ void EffectiveEnergyDrift::update(){ nLocalAtoms = gatindex.size(); atoms.getLocalPositions(positions); atoms.getLocalForces(forces); - if(pbc){ + if(pbc) { Tensor B=atoms.getPbc().getBox(); Tensor IB=atoms.getPbc().getInvBox(); -#pragma omp parallel for - for(unsigned i=0;igetOutputQuantity("bias"); + for(unsigned i=0; igetOutputQuantity("bias"); plumed.comm.Sum(&eedSum,1); - + double effective = eedSum+bias-initialBias-plumed.getWork(); // this is to take into account ensemble averaging if(ensemble) { diff --git a/src/generic/FitToTemplate.cpp b/src/generic/FitToTemplate.cpp index ad35b40b73..37e38333f6 100644 --- a/src/generic/FitToTemplate.cpp +++ b/src/generic/FitToTemplate.cpp @@ -41,7 +41,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC FIT_TO_TEMPLATE /* @@ -65,7 +65,7 @@ change the result. Examples are: \attention The implementation of TYPE=OPTIMAL is available but should be considered in testing phase. Please report any -strange behavior. +strange behavior. \attention This directive modifies the stored position at the precise moment @@ -104,7 +104,7 @@ class FitToTemplate: Vector center; Vector shift; // optimal alignment related stuff - PLMD::RMSD* rmsd; + PLMD::RMSD* rmsd; Tensor rotation; Matrix< std::vector > drotdpos; std::vector positions; @@ -113,19 +113,19 @@ class FitToTemplate: std::vector centeredpositions; Vector center_positions; - + public: explicit FitToTemplate(const ActionOptions&ao); ~FitToTemplate(); static void registerKeywords( Keywords& keys ); void calculate(); void apply(); - unsigned getNumberOfDerivatives(){plumed_merror("You should not call this function");}; + unsigned getNumberOfDerivatives() {plumed_merror("You should not call this function");}; }; PLUMED_REGISTER_ACTION(FitToTemplate,"FIT_TO_TEMPLATE") -void FitToTemplate::registerKeywords( Keywords& keys ){ +void FitToTemplate::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); keys.add("compulsory","STRIDE","1","the frequency with which molecules are reassembled. Unless you are completely certain about what you are doing leave this set equal to 1!"); @@ -134,18 +134,18 @@ void FitToTemplate::registerKeywords( Keywords& keys ){ } FitToTemplate::FitToTemplate(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao), -ActionWithValue(ao), -rmsd(NULL) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao), + ActionWithValue(ao), + rmsd(NULL) { string reference; parse("REFERENCE",reference); type.assign("SIMPLE"); parse("TYPE",type); - // if(type!="SIMPLE") error("Only TYPE=SIMPLE is implemented in FIT_TO_TEMPLATE"); +// if(type!="SIMPLE") error("Only TYPE=SIMPLE is implemented in FIT_TO_TEMPLATE"); checkRead(); @@ -153,7 +153,7 @@ rmsd(NULL) // read everything in ang and transform to nm if we are not in natural units if( !pdb.read(reference,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()) ) - error("missing input file " + reference ); + error("missing input file " + reference ); requestAtoms(pdb.getAtomNumbers()); @@ -163,22 +163,22 @@ rmsd(NULL) // normalize weights - double n=0.0; for(unsigned i=0;i weights_measure=pdb.getBeta(); - n=0.0; for(unsigned i=0;iset(weights,weights_measure,positions,type,false,false);// note: the reference is shifted now with center in the origin - log<<" Method chosen for fitting: "<getMethod()<<" \n"; + if(type=="OPTIMAL" or type=="OPTIMAL-FAST" ) { + rmsd=new RMSD(); + rmsd->set(weights,weights_measure,positions,type,false,false);// note: the reference is shifted now with center in the origin + log<<" Method chosen for fitting: "<getMethod()<<" \n"; } // register the value of rmsd (might be useful sometimes) addValue(); setNotPeriodic(); @@ -191,92 +191,92 @@ rmsd(NULL) } -void FitToTemplate::calculate(){ +void FitToTemplate::calculate() { - Vector cc; + Vector cc; - for(unsigned i=0;icalc_FitElements( positions, rotation , drotdpos , centeredpositions, center_positions); - setValue(r); - for(unsigned i=0;icalc_FitElements( positions, rotation, drotdpos, centeredpositions, center_positions); + setValue(r); + for(unsigned i=0; ifflush(); + p->fflush(); } }; PLUMED_REGISTER_ACTION(Flush,"FLUSH") -void Flush::registerKeywords( Keywords& keys ){ +void Flush::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); keys.add("compulsory","STRIDE","the frequency with which all the open files should be flushed"); diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index a214aa3536..0403d6b761 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -31,19 +31,19 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC GENERIC GROUP /* Define a group of atoms so that a particular list of atoms can be referenced with a single label -in definitions of CVs or virtual atoms. +in definitions of CVs or virtual atoms. Atoms can be listed as comma separated numbers (i.e. 1,2,3,10,45,7,9,..) , simple positive ranges (i.e. 20-40), ranges with a stride either positive or negative (i.e. 20-40:2 or 80-50:-2) or as -combinations of all the former methods (1,2,4,5,10-20,21-40:2,80-50:-2). +combinations of all the former methods (1,2,4,5,10-20,21-40:2,80-50:-2). -Moreover, lists can be imported from ndx files (GROMACS format). Use NDX_FILE to set the name of +Moreover, lists can be imported from ndx files (GROMACS format). Use NDX_FILE to set the name of the index file and NDX_GROUP to set the name of the group to be imported (default is first one). It is also possible to remove atoms from a list and or sort them using keywords REMOVE, SORT, and UNIQUE. @@ -126,8 +126,8 @@ class Group: explicit Group(const ActionOptions&ao); ~Group(); static void registerKeywords( Keywords& keys ); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} }; PLUMED_REGISTER_ACTION(Group,"GROUP") @@ -144,25 +144,25 @@ Group::Group(const ActionOptions&ao): if(ndxfile.length()>0 && atoms.size()>0) error("either use explicit atom list or import from index file"); if(ndxfile.length()==0 && ndxgroup.size()>0) error("NDX_GROUP can be only used is NDX_FILE is also used"); - if(ndxfile.length()>0){ + if(ndxfile.length()>0) { if(ndxgroup.size()>0) log<<" importing group '"+ndxgroup+"'"; else log<<" importing first group"; log<<" from index file "< words=Tools::getWords(line); - if(words.size()>=3 && words[0]=="[" && words[2]=="]"){ + if(words.size()>=3 && words[0]=="[" && words[2]=="]") { if(groupname.length()>0) firstgroup=false; groupname=words[1]; if(groupname==ndxgroup || ndxgroup.length()==0) groupfound=true; - } else if(groupname==ndxgroup || (firstgroup && ndxgroup.length()==0)){ - for(unsigned i=0;i remove; parseAtomList("REMOVE",remove); - if(remove.size()>0){ + if(remove.size()>0) { std::vector notfound; log<<" removing these atoms from the list:"; - for(unsigned i=0;i0){ + if(notfound.size()>0) { log<<" the following atoms were not found:"; - for(unsigned i=0;iatoms.insertGroup(getLabel(),atoms); log.printf(" list of atoms "); - for(unsigned i=0;i rotateArguments; ///////////////////////////////////////// public: - void calculate(){} + void calculate() {} void prepare(); explicit Print(const ActionOptions&); static void registerKeywords(Keywords& keys); - void apply(){} + void apply() {} void update(); ~Print(); }; PLUMED_REGISTER_ACTION(Print,"PRINT") -void Print::registerKeywords(Keywords& keys){ +void Print::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -95,15 +95,15 @@ void Print::registerKeywords(Keywords& keys){ } Print::Print(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -fmt("%f"), -rotate(0) + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + fmt("%f"), + rotate(0) { ofile.link(*this); parse("FILE",file); - if(file.length()>0){ + if(file.length()>0) { ofile.open(file); log.printf(" on file %s\n",file.c_str()); } else { @@ -113,15 +113,15 @@ rotate(0) parse("FMT",fmt); fmt=" "+fmt; log.printf(" with format %s\n",fmt.c_str()); - for(unsigned i=0;i0){ + if(rotate>0) { rotateCountdown=rotate; - for(unsigned i=0;i a(1,rotateArguments[0]); requestArguments(vector(1,rotateArguments[0])); rotateLast=0; @@ -130,14 +130,14 @@ rotate(0) checkRead(); } -void Print::prepare(){ +void Print::prepare() { ///////////////////////////////////////// // these are crazy things just for debug: // they allow to change regularly the // printed argument - if(rotate>0){ + if(rotate>0) { rotateCountdown--; - if(rotateCountdown==0){ + if(rotateCountdown==0) { rotateCountdown=rotate; rotateLast++; rotateLast%=rotateArguments.size(); @@ -147,18 +147,18 @@ void Print::prepare(){ ///////////////////////////////////////// } -void Print::update(){ - ofile.fmtField(" %f"); - ofile.printField("time",getTime()); - for(unsigned i=0;igetName(),getArgument(i)); - } - ofile.printField(); +void Print::update() { + ofile.fmtField(" %f"); + ofile.printField("time",getTime()); + for(unsigned i=0; igetName(),getArgument(i)); + } + ofile.printField(); } -Print::~Print(){ +Print::~Print() { } } diff --git a/src/generic/RandomExchanges.cpp b/src/generic/RandomExchanges.cpp index b98889e2ff..be36873bcc 100644 --- a/src/generic/RandomExchanges.cpp +++ b/src/generic/RandomExchanges.cpp @@ -27,8 +27,8 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC GENERIC RANDOM_EXCHANGES /* @@ -78,19 +78,19 @@ class RandomExchanges: public: static void registerKeywords( Keywords& keys ); explicit RandomExchanges(const ActionOptions&ao); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} }; PLUMED_REGISTER_ACTION(RandomExchanges,"RANDOM_EXCHANGES") -void RandomExchanges::registerKeywords( Keywords& keys ){ +void RandomExchanges::registerKeywords( Keywords& keys ) { Action::registerKeywords(keys); keys.add("optional","SEED","seed for random exchanges"); } RandomExchanges::RandomExchanges(const ActionOptions&ao): -Action(ao) + Action(ao) { plumed.getExchangePatterns().setFlag(ExchangePatterns::RANDOM); // I convert the seed to -seed because I think it is more general to use a positive seed in input diff --git a/src/generic/Read.cpp b/src/generic/Read.cpp index 2b67c1685a..88c2796300 100644 --- a/src/generic/Read.cpp +++ b/src/generic/Read.cpp @@ -27,20 +27,20 @@ #include "core/Atoms.h" #include "tools/IFile.h" -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC GENERIC READ -/* +/* Read quantities from a colvar file. -This Action can be used with driver to read in a colvar file that was generated during +This Action can be used with driver to read in a colvar file that was generated during an MD simulation \par Description of components The READ command will read those fields that are labelled with the text string given to the -VALUE keyword. It will also read in any fields that are labelleled with the text string +VALUE keyword. It will also read in any fields that are labelleled with the text string given to the VALUE keyword followed by a dot and a further string. If a single Value is read in this value can be referenced using the label of the Action. Alternatively, if multiple quanties are read in, they can be referenced elsewhere in the input by using the label for the Action @@ -49,7 +49,7 @@ followed by a dot and the character string that appeared after the dot in the ti \par Examples This input reads in data from a file called input_colvar.data that was generated -in a calculation that involved PLUMED. The first command reads in the data from the +in a calculation that involved PLUMED. The first command reads in the data from the column headed phi1 while the second reads in the data from the column headed phi2. \verbatim @@ -62,8 +62,8 @@ PRINT ARG=rphi1,rphi2 STRIDE=500 FILE=output_colvar.data //+ENDPLUMEDOC class Read : -public ActionPilot, -public ActionWithValue + public ActionPilot, + public ActionWithValue { private: bool ignore_time; @@ -78,7 +78,7 @@ public ActionWithValue explicit Read(const ActionOptions&); ~Read(); void prepare(); - void apply(){} + void apply() {} void calculate(); void update(); std::string getFilename() const; @@ -89,7 +89,7 @@ public ActionWithValue PLUMED_REGISTER_ACTION(Read,"READ") -void Read::registerKeywords(Keywords& keys){ +void Read::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithValue::registerKeywords(keys); @@ -98,9 +98,9 @@ void Read::registerKeywords(Keywords& keys){ keys.add("compulsory","VALUES","the values to read from the file"); keys.add("compulsory","FILE","the name of the file from which to read these quantities"); keys.addFlag("IGNORE_TIME",false,"ignore the time in the colvar file. When this flag is not present read will be quite strict " - "about the start time of the simulation and the stride between frames"); + "about the start time of the simulation and the stride between frames"); keys.addFlag("IGNORE_FORCES",false,"use this flag if the forces added by any bias can be safely ignored. As an example forces can be " - "safely ignored if you are doing postprocessing that does not involve outputting forces"); + "safely ignored if you are doing postprocessing that does not involve outputting forces"); keys.remove("NUMERICAL_DERIVATIVES"); keys.use("UPDATE_FROM"); keys.use("UPDATE_UNTIL"); @@ -108,12 +108,12 @@ void Read::registerKeywords(Keywords& keys){ } Read::Read(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithValue(ao), -ignore_time(false), -ignore_forces(false), -nlinesPerStep(1) + Action(ao), + ActionPilot(ao), + ActionWithValue(ao), + ignore_time(false), + ignore_forces(false), + nlinesPerStep(1) { // Read the file name from the input line parse("FILE",filename); @@ -124,18 +124,18 @@ nlinesPerStep(1) // Open the file if it is not already opened cloned_file=false; std::vector other_reads=plumed.getActionSet().select(); - for(unsigned i=0;igetFilename()==filename ){ - ifile=other_reads[i]->getFile(); - cloned_file=true; - } + for(unsigned i=0; igetFilename()==filename ) { + ifile=other_reads[i]->getFile(); + cloned_file=true; + } } - if( !cloned_file ){ - ifile=new IFile(); - if( !ifile->FileExist(filename) ) error("could not find file named " + filename); - ifile->link(*this); - ifile->open(filename); - ifile->allowIgnoredFields(); + if( !cloned_file ) { + ifile=new IFile(); + if( !ifile->FileExist(filename) ) error("could not find file named " + filename); + ifile->link(*this); + ifile->open(filename); + ifile->allowIgnoredFields(); } parse("EVERY",nlinesPerStep); if(nlinesPerStep>1) log.printf(" only reading every %uth line of file %s\n",nlinesPerStep,filename.c_str() ); @@ -144,93 +144,93 @@ nlinesPerStep(1) std::vector valread; parseVector("VALUES",valread); std::size_t dot=valread[0].find_first_of('.'); - if( valread[0].find(".")!=std::string::npos ){ - std::string label=valread[0].substr(0,dot); - std::string name=valread[0].substr(dot+1); - if( name=="*" ){ - if( valread.size()>1 ) error("all values must be from the same Action when using READ"); - std::vector fieldnames; - ifile->scanFieldList( fieldnames ); - for(unsigned i=0;iFieldExist("min_" + fieldnames[i]) ) componentIsPeriodic( fieldnames[i].substr(dot+1), "-pi","pi" ); - else componentIsNotPeriodic( fieldnames[i].substr(dot+1) ); - } - } - } else { - readvals.push_back(new Value(this, valread[0], false) ); addComponentWithDerivatives( name ); - if( ifile->FieldExist("min_" + valread[0]) ) componentIsPeriodic( valread[0].substr(dot+1), "-pi", "pi" ); - else componentIsNotPeriodic( valread[0].substr(dot+1) ); - for(unsigned i=1;iFieldExist("min_" + valread[i]) ) componentIsPeriodic( valread[i].substr(dot+1), "-pi", "pi" ); - else componentIsNotPeriodic( valread[i].substr(dot+1) ); - } + if( valread[0].find(".")!=std::string::npos ) { + std::string label=valread[0].substr(0,dot); + std::string name=valread[0].substr(dot+1); + if( name=="*" ) { + if( valread.size()>1 ) error("all values must be from the same Action when using READ"); + std::vector fieldnames; + ifile->scanFieldList( fieldnames ); + for(unsigned i=0; iFieldExist("min_" + fieldnames[i]) ) componentIsPeriodic( fieldnames[i].substr(dot+1), "-pi","pi" ); + else componentIsNotPeriodic( fieldnames[i].substr(dot+1) ); + } + } + } else { + readvals.push_back(new Value(this, valread[0], false) ); addComponentWithDerivatives( name ); + if( ifile->FieldExist("min_" + valread[0]) ) componentIsPeriodic( valread[0].substr(dot+1), "-pi", "pi" ); + else componentIsNotPeriodic( valread[0].substr(dot+1) ); + for(unsigned i=1; iFieldExist("min_" + valread[i]) ) componentIsPeriodic( valread[i].substr(dot+1), "-pi", "pi" ); + else componentIsNotPeriodic( valread[i].substr(dot+1) ); } + } } else { - if( valread.size()!=1 ) error("all values must be from the same Action when using READ"); - readvals.push_back(new Value(this, valread[0], false) ); addValueWithDerivatives(); - if( ifile->FieldExist("min_" + valread[0]) ) setPeriodic( "-pi", "pi" ); - else setNotPeriodic(); - log.printf(" reading value %s and storing as %s\n",valread[0].c_str() ,getLabel().c_str() ); + if( valread.size()!=1 ) error("all values must be from the same Action when using READ"); + readvals.push_back(new Value(this, valread[0], false) ); addValueWithDerivatives(); + if( ifile->FieldExist("min_" + valread[0]) ) setPeriodic( "-pi", "pi" ); + else setNotPeriodic(); + log.printf(" reading value %s and storing as %s\n",valread[0].c_str(),getLabel().c_str() ); } checkRead(); } -Read::~Read(){ - if( !cloned_file ){ ifile->close(); delete ifile; } - for(unsigned i=0;iclose(); delete ifile; } + for(unsigned i=0; iscanField("time",du_time) ){ - error("Reached end of file " + filename + " before end of trajectory"); - } else if( fabs( du_time-getTime() )>plumed.getAtoms().getTimeStep() && !ignore_time ){ - std::string str_dutime,str_ptime; Tools::convert(du_time,str_dutime); Tools::convert(getTime(),str_ptime); - error("mismatched times in colvar files : colvar time=" + str_dutime + " plumed time=" + str_ptime + ". Add IGNORE_TIME to ignore error."); - } - } +void Read::prepare() { + if( !cloned_file ) { + double du_time; + if( !ifile->scanField("time",du_time) ) { + error("Reached end of file " + filename + " before end of trajectory"); + } else if( fabs( du_time-getTime() )>plumed.getAtoms().getTimeStep() && !ignore_time ) { + std::string str_dutime,str_ptime; Tools::convert(du_time,str_dutime); Tools::convert(getTime(),str_ptime); + error("mismatched times in colvar files : colvar time=" + str_dutime + " plumed time=" + str_ptime + ". Add IGNORE_TIME to ignore error."); + } + } } -void Read::calculate(){ +void Read::calculate() { std::string smin, smax; - for(unsigned i=0;iscanField( readvals[i] ); - getPntrToComponent(i)->set( readvals[i]->get() ); - if( readvals[i]->isPeriodic() ){ - readvals[i]->getDomain( smin, smax ); - getPntrToComponent(i)->setDomain( smin, smax ); - } + for(unsigned i=0; iscanField( readvals[i] ); + getPntrToComponent(i)->set( readvals[i]->get() ); + if( readvals[i]->isPeriodic() ) { + readvals[i]->getDomain( smin, smax ); + getPntrToComponent(i)->setDomain( smin, smax ); + } } } -void Read::update(){ - if( !cloned_file ){ - for(unsigned i=0;iscanField(); double du_time; - if( plumed.getAtoms().getNatoms()==0 && !ifile->scanField("time",du_time) ) plumed.stop(); - } +void Read::update() { + if( !cloned_file ) { + for(unsigned i=0; iscanField(); double du_time; + if( plumed.getAtoms().getNatoms()==0 && !ifile->scanField("time",du_time) ) plumed.stop(); + } } } diff --git a/src/generic/ResetCell.cpp b/src/generic/ResetCell.cpp index c595b4d9cc..fd14c1fe10 100644 --- a/src/generic/ResetCell.cpp +++ b/src/generic/ResetCell.cpp @@ -35,7 +35,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC RESET_CELL /* @@ -58,7 +58,7 @@ arbitrary. \attention The implementation of this action is available but should be considered in testing phase. Please report any -strange behavior. +strange behavior. \attention This directive modifies the stored position at the precise moment @@ -91,7 +91,7 @@ class ResetCell: { std::string type; Tensor rotation,newbox; - + public: explicit ResetCell(const ActionOptions&ao); static void registerKeywords( Keywords& keys ); @@ -101,7 +101,7 @@ class ResetCell: PLUMED_REGISTER_ACTION(ResetCell,"RESET_CELL") -void ResetCell::registerKeywords( Keywords& keys ){ +void ResetCell::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); keys.add("compulsory","STRIDE","1","the frequency with which molecules are reassembled. Unless you are completely certain about what you are doing leave this set equal to 1!"); @@ -109,66 +109,66 @@ void ResetCell::registerKeywords( Keywords& keys ){ } ResetCell::ResetCell(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao) { type.assign("TRIANGULAR"); parse("TYPE",type); log<<" type: "<resizeDerivatives(1); } -void Time::calculate(){ - setValue (getTime()); +void Time::calculate() { + setValue (getTime()); } } diff --git a/src/generic/UpdateIf.cpp b/src/generic/UpdateIf.cpp index 987cbc2c04..1db2b6cb19 100644 --- a/src/generic/UpdateIf.cpp +++ b/src/generic/UpdateIf.cpp @@ -26,8 +26,8 @@ using namespace std; -namespace PLMD{ -namespace generic{ +namespace PLMD { +namespace generic { //+PLUMEDOC PRINTANALYSIS UPDATE_IF /* @@ -76,8 +76,8 @@ UPDATE_IF ARG=coord END //+ENDPLUMEDOC class UpdateIf: -public ActionPilot, -public ActionWithArguments + public ActionPilot, + public ActionWithArguments { std::vector lower; std::vector upper; @@ -89,13 +89,13 @@ public ActionWithArguments void beforeUpdate(); explicit UpdateIf(const ActionOptions&); static void registerKeywords(Keywords& keys); - void apply(){} + void apply() {} ~UpdateIf(); }; PLUMED_REGISTER_ACTION(UpdateIf,"UPDATE_IF") -void UpdateIf::registerKeywords(Keywords& keys){ +void UpdateIf::registerKeywords(Keywords& keys) { Action::registerKeywords(keys); ActionPilot::registerKeywords(keys); ActionWithArguments::registerKeywords(keys); @@ -107,11 +107,11 @@ void UpdateIf::registerKeywords(Keywords& keys){ } UpdateIf::UpdateIf(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionWithArguments(ao), -on(false), -end(false) + Action(ao), + ActionPilot(ao), + ActionWithArguments(ao), + on(false), + end(false) { parseFlag("END",end); parseVector("LESS_THAN",upper); @@ -122,24 +122,24 @@ end(false) if(lower.size()==0) lower.assign(getNumberOfArguments(),-std::numeric_limits::max()); if(upper.size()!=getNumberOfArguments()) error("LESS_THAN should have the same size as ARG"); if(lower.size()!=getNumberOfArguments()) error("MORE_THAN should have the same size as ARG"); - for(unsigned i=0;i=upper[i] || getArgument(i)<=lower[i]) on=false; } } -void UpdateIf::beforeUpdate(){ +void UpdateIf::beforeUpdate() { if(end) plumed.updateFlagsPop(); else { if(on) plumed.updateFlagsPush(plumed.updateFlagsTop()); @@ -148,7 +148,7 @@ void UpdateIf::beforeUpdate(){ } -UpdateIf::~UpdateIf(){ +UpdateIf::~UpdateIf() { } } diff --git a/src/generic/WholeMolecules.cpp b/src/generic/WholeMolecules.cpp index 6d8551774b..12e9c82813 100644 --- a/src/generic/WholeMolecules.cpp +++ b/src/generic/WholeMolecules.cpp @@ -36,7 +36,7 @@ using namespace std; namespace PLMD { -namespace generic{ +namespace generic { //+PLUMEDOC GENERIC WHOLEMOLECULES /* @@ -47,7 +47,7 @@ It is similar to the ALIGN_ATOMS keyword of plumed1, and is needed since some MD dynamics code (e.g. GROMACS) can break molecules during the calculation. Running some CVs without this command can cause there to be discontinuities changes -in the CV value and artifacts in the calculations. This command can be applied +in the CV value and artifacts in the calculations. This command can be applied more than once. To see what effect is has use a variable without pbc or use the \ref DUMPATOMS directive to output the atomic positions. @@ -90,12 +90,12 @@ DUMPATOMS FILE=dump.xyz ATOMS=1-20,30-40 \endverbatim (see also \ref DUMPATOMS) -This command instructs plumed to reconstruct the chain of backbone atoms in a +This command instructs plumed to reconstruct the chain of backbone atoms in a protein \verbatim MOLINFO STRUCTURE=helix.pdb -WHOLEMOLECULES RESIDUES=all MOLTYPE=protein +WHOLEMOLECULES RESIDUES=all MOLTYPE=protein \endverbatim (See also \ref MOLINFO) @@ -112,12 +112,12 @@ class WholeMolecules: explicit WholeMolecules(const ActionOptions&ao); static void registerKeywords( Keywords& keys ); void calculate(); - void apply(){} + void apply() {} }; PLUMED_REGISTER_ACTION(WholeMolecules,"WHOLEMOLECULES") -void WholeMolecules::registerKeywords( Keywords& keys ){ +void WholeMolecules::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); @@ -125,24 +125,24 @@ void WholeMolecules::registerKeywords( Keywords& keys ){ keys.add("numbered","ENTITY","the atoms that make up a molecule that you wish to align. To specify multiple molecules use a list of ENTITY keywords: ENTITY0, ENTITY1,..."); keys.reset_style("ENTITY","atoms"); keys.add("residues","RESIDUES","this command specifies that the backbone atoms in a set of residues all must be aligned. It must be used in tandem with the \\ref MOLINFO " - "action and the MOLTYPE keyword. If you wish to use all the residues from all the chains in your system you can do so by " - "specifying all. Alternatively, if you wish to use a subset of the residues you can specify the particular residues " - "you are interested in as a list of numbers"); + "action and the MOLTYPE keyword. If you wish to use all the residues from all the chains in your system you can do so by " + "specifying all. Alternatively, if you wish to use a subset of the residues you can specify the particular residues " + "you are interested in as a list of numbers"); keys.add("optional","MOLTYPE","the type of molecule that is under study. This is used to define the backbone atoms"); } WholeMolecules::WholeMolecules(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao) { vector merge; - for(int i=0;;i++){ + for(int i=0;; i++) { vector group; - parseAtomList("ENTITY",i,group); + parseAtomList("ENTITY",i,group); if( group.empty() ) break; log.printf(" atoms in entity %d : ",i); - for(unsigned j=0;j resstrings; parseVector("RESIDUES",resstrings); - if( resstrings.size()>0 ){ - if( resstrings.size()==1 ){ - if( resstrings[0]=="all" ) resstrings[0]="all-ter"; // Include terminal groups in alignment - } - string moltype; parse("MOLTYPE",moltype); - if(moltype.length()==0) error("Found RESIDUES keyword without specification of the moleclue - use MOLTYPE"); - std::vector moldat=plumed.getActionSet().select(); - if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); - std::vector< std::vector > backatoms; - moldat[0]->getBackbone( resstrings, moltype, backatoms ); - for(unsigned i=0;i(groups.size()+1)); - for(unsigned j=0;j0 ) { + if( resstrings.size()==1 ) { + if( resstrings[0]=="all" ) resstrings[0]="all-ter"; // Include terminal groups in alignment + } + string moltype; parse("MOLTYPE",moltype); + if(moltype.length()==0) error("Found RESIDUES keyword without specification of the moleclue - use MOLTYPE"); + std::vector moldat=plumed.getActionSet().select(); + if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); + std::vector< std::vector > backatoms; + moldat[0]->getBackbone( resstrings, moltype, backatoms ); + for(unsigned i=0; i(groups.size()+1)); + for(unsigned j=0; j1) log<<" atoms will be grouped by "<::max(); int closest=-1; - for(unsigned j=0;j0 ){ - vstring += " TYPE=fibonacci CONCENTRATION=" + vconc; - } else { - std::string kstring; parse("KERNEL",kstring); - if( kstring=="DISCRETE" ) vstring += " KERNEL=" + kstring; - else vstring += " KERNEL=" + kstring + " " + getKeyword("BANDWIDTH"); - } + std::string vstring = inputstr; + if( keywords.exists("KERNEL") ) { + std::string vconc; parse("CONCENTRATION",vconc); + if( vconc.length()>0 ) { + vstring += " TYPE=fibonacci CONCENTRATION=" + vconc; + } else { + std::string kstring; parse("KERNEL",kstring); + if( kstring=="DISCRETE" ) vstring += " KERNEL=" + kstring; + else vstring += " KERNEL=" + kstring + " " + getKeyword("BANDWIDTH"); + } } vesselbase::VesselOptions da("mygrid","",-1,vstring,this); Keywords keys; gridtools::AverageOnGrid::registerKeywords( keys ); vesselbase::VesselOptions dar( da, keys ); - if( type=="histogram" ){ - mygrid = new HistogramOnGrid(dar); - } else if( type=="average" ){ - mygrid = new AverageOnGrid(dar); - } else if( type=="grid" ){ - mygrid = new GridVessel(dar); + if( type=="histogram" ) { + mygrid = new HistogramOnGrid(dar); + } else if( type=="average" ) { + mygrid = new AverageOnGrid(dar); + } else if( type=="grid" ) { + mygrid = new GridVessel(dar); } else { - plumed_merror("no way to create grid of type " + type ); - } + plumed_merror("no way to create grid of type " + type ); + } } -void ActionWithGrid::turnOnDerivatives(){ - needsDerivatives(); ActionWithValue::turnOnDerivatives(); +void ActionWithGrid::turnOnDerivatives() { + needsDerivatives(); ActionWithValue::turnOnDerivatives(); if( getStride()==1 ) setStride(0); else if( getStride()!=0 ) error("conflicting instructions for grid - stride was set but must be evaluated on every step for derivatives - remove STRIDE keyword"); - if( clearstride>1 ) error("conflicting instructions for grid - CLEAR was set but grid must be reset on every step for derivatives - remove CLEAR keyword" ); - if( weights.size()>0 ) error("conflicting instructions for grid - LOGWEIGHTS was set but weights are not considered when derivatives of grid are evaluated - remove LOGWEIGHTS keyword"); + if( clearstride>1 ) error("conflicting instructions for grid - CLEAR was set but grid must be reset on every step for derivatives - remove CLEAR keyword" ); + if( weights.size()>0 ) error("conflicting instructions for grid - LOGWEIGHTS was set but weights are not considered when derivatives of grid are evaluated - remove LOGWEIGHTS keyword"); } -void ActionWithGrid::calculate(){ +void ActionWithGrid::calculate() { // Do nothing if derivatives are not required if( doNotCalculateDerivatives() ) return; // Clear on every step diff --git a/src/gridtools/ActionWithGrid.h b/src/gridtools/ActionWithGrid.h index f87c5e6e61..c01a50ef10 100644 --- a/src/gridtools/ActionWithGrid.h +++ b/src/gridtools/ActionWithGrid.h @@ -43,7 +43,7 @@ class ActionWithGrid : public vesselbase::ActionWithAveraging { void createGrid( const std::string& type, const std::string& inputstr ); public: static void registerKeywords( Keywords& keys ); - explicit ActionWithGrid( const ActionOptions& ); + explicit ActionWithGrid( const ActionOptions& ); virtual void turnOnDerivatives(); void calculate(); void performTask( const unsigned& task_index, const unsigned& current, MultiValue& myvals ) const ; diff --git a/src/gridtools/ActionWithInputGrid.cpp b/src/gridtools/ActionWithInputGrid.cpp index e409d9662b..12d358115c 100644 --- a/src/gridtools/ActionWithInputGrid.cpp +++ b/src/gridtools/ActionWithInputGrid.cpp @@ -26,52 +26,52 @@ namespace PLMD { namespace gridtools { -void ActionWithInputGrid::registerKeywords( Keywords& keys ){ +void ActionWithInputGrid::registerKeywords( Keywords& keys ) { ActionWithGrid::registerKeywords( keys ); keys.add("compulsory","GRID","the action that creates the input grid you would like to use"); keys.add("optional","COMPONENT","if your input is a vector field use this to specifiy the component of the input vector field for which you wish to use"); } ActionWithInputGrid::ActionWithInputGrid(const ActionOptions&ao): -Action(ao), -ActionWithGrid(ao), -ingrid(NULL) + Action(ao), + ActionWithGrid(ao), + ingrid(NULL) { std::string mlab; parse("GRID",mlab); vesselbase::ActionWithVessel* mves= plumed.getActionSet().selectWithLabel(mlab); if(!mves) error("action labelled " + mlab + " does not exist or does not have vessels"); addDependency(mves); - for(unsigned i=0;igetNumberOfVessels();++i){ - ingrid=dynamic_cast( mves->getPntrToVessel(i) ); - if( ingrid ) break; + for(unsigned i=0; igetNumberOfVessels(); ++i) { + ingrid=dynamic_cast( mves->getPntrToVessel(i) ); + if( ingrid ) break; } if( !ingrid ) error("input action does not calculate a grid"); - if( ingrid->getNumberOfComponents()==1 ){ - mycomp=0; + if( ingrid->getNumberOfComponents()==1 ) { + mycomp=0; } else { - int tcomp=-1; parse("COMPONENT",tcomp); - if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); - mycomp=tcomp; + int tcomp=-1; parse("COMPONENT",tcomp); + if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); + mycomp=tcomp; } log.printf(" using %uth component of grid calculated by action %s \n",mycomp,mves->getLabel().c_str() ); } -void ActionWithInputGrid::clearAverage(){ +void ActionWithInputGrid::clearAverage() { if( mygrid->getType()=="flat" ) mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), mygrid->getNbin(), mygrid->getGridSpacing() ); ActionWithAveraging::clearAverage(); } -void ActionWithInputGrid::prepareForAveraging(){ - if( checkAllActive() ){ - for(unsigned i=0;igetNumberOfPoints();++i){ - if( ingrid->inactive(i) ) error("if FIND_CONTOUR is used with BUFFER option then other actions cannot be performed with grid"); - } +void ActionWithInputGrid::prepareForAveraging() { + if( checkAllActive() ) { + for(unsigned i=0; igetNumberOfPoints(); ++i) { + if( ingrid->inactive(i) ) error("if FIND_CONTOUR is used with BUFFER option then other actions cannot be performed with grid"); + } } } -void ActionWithInputGrid::performOperations( const bool& from_update ){ +void ActionWithInputGrid::performOperations( const bool& from_update ) { prepareForAveraging(); runAllTasks(); } diff --git a/src/gridtools/ActionWithInputGrid.h b/src/gridtools/ActionWithInputGrid.h index 0799f4de69..cc1ba009e5 100644 --- a/src/gridtools/ActionWithInputGrid.h +++ b/src/gridtools/ActionWithInputGrid.h @@ -29,7 +29,7 @@ namespace PLMD { namespace gridtools { class ActionWithInputGrid : public ActionWithGrid { -friend class DumpGrid; + friend class DumpGrid; private: unsigned mycomp; protected: @@ -44,12 +44,12 @@ friend class DumpGrid; virtual void prepareForAveraging(); virtual bool checkAllActive() const { return true; } virtual void performOperations( const bool& from_update ); - virtual void apply(){}; + virtual void apply() {}; }; inline double ActionWithInputGrid::getFunctionValue( const unsigned& ipoint ) const { - unsigned dim=ingrid->getDimension(); if( ingrid->noderiv ) dim=0; + unsigned dim=ingrid->getDimension(); if( ingrid->noderiv ) dim=0; return ingrid->getGridElement( ipoint, mycomp*(1+dim) ); } @@ -61,7 +61,7 @@ double ActionWithInputGrid::getFunctionValue( const std::vector& ip ) inline double ActionWithInputGrid::getFunctionValueAndDerivatives( const std::vector& x, std::vector& der ) const { return ingrid->getValueAndDerivatives( x, mycomp, der ); -} +} } } diff --git a/src/gridtools/ActionWithIntegral.cpp b/src/gridtools/ActionWithIntegral.cpp index addfb46db4..7deb7fbd39 100644 --- a/src/gridtools/ActionWithIntegral.cpp +++ b/src/gridtools/ActionWithIntegral.cpp @@ -24,37 +24,37 @@ namespace PLMD { namespace gridtools { -void ActionWithIntegral::registerKeywords( Keywords& keys ){ +void ActionWithIntegral::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); - keys.remove("KERNEL"); keys.remove("BANDWIDTH"); + keys.remove("KERNEL"); keys.remove("BANDWIDTH"); keys.remove("CLEAR"); keys.add("compulsory","CLEAR","1","the frequency with which to clear all the accumulated data."); } ActionWithIntegral::ActionWithIntegral(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao) + Action(ao), + ActionWithInputGrid(ao) { - plumed_assert( ingrid->getNumberOfComponents()==1 ); + plumed_assert( ingrid->getNumberOfComponents()==1 ); // Retrieve the volume of the grid (for integration) volume = ingrid->getCellVolume(); - // Create something that is going to calculate the sum of all the values + // Create something that is going to calculate the sum of all the values // at the various grid points - this is going to be the integral std::string fake_input; addVessel( "SUM", fake_input, -1 ); readVesselKeywords(); // Now create task list - number of tasks is equal to the number of grid points // as we have to evaluate the function at each grid points - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); // And activate all tasks - deactivateAllTasks(); - for(unsigned i=0;igetNumberOfPoints();++i) taskFlags[i]=1; + deactivateAllTasks(); + for(unsigned i=0; igetNumberOfPoints(); ++i) taskFlags[i]=1; lockContributors(); } -void ActionWithIntegral::turnOnDerivatives(){ +void ActionWithIntegral::turnOnDerivatives() { ActionWithGrid::turnOnDerivatives(); forcesToApply.resize( ingrid->getNumberOfPoints() ); } -void ActionWithIntegral::apply(){ +void ActionWithIntegral::apply() { if( getForcesFromVessels( forcesToApply ) ) ingrid->setForce( forcesToApply ); } diff --git a/src/gridtools/ActionWithIntegral.h b/src/gridtools/ActionWithIntegral.h index 635ce663b1..b4fcbf2b96 100644 --- a/src/gridtools/ActionWithIntegral.h +++ b/src/gridtools/ActionWithIntegral.h @@ -40,7 +40,7 @@ class ActionWithIntegral : public ActionWithInputGrid { unsigned getNumberOfDerivatives(); void turnOnDerivatives(); /// Unless I am mistaken an integral should never be a periodic function - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } void apply(); }; @@ -50,7 +50,7 @@ double ActionWithIntegral::getVolume() const { } inline -unsigned ActionWithIntegral::getNumberOfDerivatives(){ +unsigned ActionWithIntegral::getNumberOfDerivatives() { return ingrid->getNumberOfPoints(); } diff --git a/src/gridtools/AverageOnGrid.cpp b/src/gridtools/AverageOnGrid.cpp index 75d04579bc..0f9c5cc737 100644 --- a/src/gridtools/AverageOnGrid.cpp +++ b/src/gridtools/AverageOnGrid.cpp @@ -24,16 +24,16 @@ namespace PLMD { namespace gridtools { -void AverageOnGrid::registerKeywords( Keywords& keys ){ +void AverageOnGrid::registerKeywords( Keywords& keys ) { HistogramOnGrid::registerKeywords( keys ); } AverageOnGrid::AverageOnGrid( const vesselbase::VesselOptions& da ): -HistogramOnGrid(da) + HistogramOnGrid(da) { arg_names.push_back( "density" ); - if( !discrete ){ - for(unsigned i=0;i& der, std::vector& buffer ) const { buffer[bufstart+nper*ipoint] += weight*dens; buffer[ bufstart+nper*(ipoint+1) - (dimension+1) ] += dens; - if( der.size()>0 ){ - for(unsigned j=0;j0 ) { + for(unsigned j=0; j=(nper-(dimension+1)) ) return getDataElement( nper*ipoint + jelement ); + if( jelement>=(nper-(dimension+1)) ) return getDataElement( nper*ipoint + jelement ); if( noderiv ) return getDataElement( nper*ipoint+jelement ) / getDataElement( nper*(1+ipoint) - 1); - double rdenom = 1.0; + double rdenom = 1.0; if( fabs(getDataElement( nper*(ipoint+1) -(dimension+1) ))>epsilon ) rdenom = 1. / getDataElement( nper*(ipoint+1) - (dimension+1) ); - + unsigned jderiv = jelement%(1+dimension); - if( jderiv==0 ) return rdenom*getDataElement( nper*ipoint+jelement ); + if( jderiv==0 ) return rdenom*getDataElement( nper*ipoint+jelement ); unsigned jfloor = std::floor( jelement / (1+dimension) ); - return rdenom*getDataElement( nper*ipoint+jelement ) - rdenom*rdenom*getDataElement(nper*ipoint+jfloor)*getDataElement(nper*(ipoint+1) - (dimension+1) + jderiv); + return rdenom*getDataElement( nper*ipoint+jelement ) - rdenom*rdenom*getDataElement(nper*ipoint+jfloor)*getDataElement(nper*(ipoint+1) - (dimension+1) + jderiv); } } diff --git a/src/gridtools/AverageOnGrid.h b/src/gridtools/AverageOnGrid.h index 8b224bf056..ad38b50e71 100644 --- a/src/gridtools/AverageOnGrid.h +++ b/src/gridtools/AverageOnGrid.h @@ -35,7 +35,7 @@ class AverageOnGrid : public HistogramOnGrid { void accumulateForce( const unsigned& ipoint, const double& weight, const std::vector& der, std::vector& intforce ) const { plumed_error(); } double getGridElement( const unsigned& ipoint, const unsigned& jelement ) const ; unsigned getNumberOfComponents() const ; - void getFinalForces( const std::vector& buffer, std::vector& finalForces ){ plumed_error(); } + void getFinalForces( const std::vector& buffer, std::vector& finalForces ) { plumed_error(); } }; inline diff --git a/src/gridtools/ContourFindingBase.cpp b/src/gridtools/ContourFindingBase.cpp index cb6d374f5d..3a20dd6724 100644 --- a/src/gridtools/ContourFindingBase.cpp +++ b/src/gridtools/ContourFindingBase.cpp @@ -24,19 +24,19 @@ namespace PLMD { namespace gridtools { -void ContourFindingBase::registerKeywords( Keywords& keys ){ +void ContourFindingBase::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.add("compulsory","CONTOUR","the value we would like to draw the contour at in the space"); keys.remove("KERNEL"); keys.remove("BANDWIDTH"); } ContourFindingBase::ContourFindingBase(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao), -mymin(this) + Action(ao), + ActionWithInputGrid(ao), + mymin(this) { if( ingrid->noDerivatives() ) error("cannot find contours if input grid has no derivatives"); - parse("CONTOUR",contour); + parse("CONTOUR",contour); log.printf(" calculating dividing surface along which function equals %f \n", contour); } diff --git a/src/gridtools/ContourFindingBase.h b/src/gridtools/ContourFindingBase.h index ec6c1eee95..5a1752d5e5 100644 --- a/src/gridtools/ContourFindingBase.h +++ b/src/gridtools/ContourFindingBase.h @@ -43,9 +43,9 @@ class ContourFindingBase : public ActionWithInputGrid { /// Get the contour value double getDifferenceFromContour( const std::vector& x, std::vector& der ) const ; /// Overwrite not needed stuff - unsigned getNumberOfDerivatives(){ return 0; } + unsigned getNumberOfDerivatives() { return 0; } /// This is not periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; inline diff --git a/src/gridtools/ConvertToFES.cpp b/src/gridtools/ConvertToFES.cpp index 1edf196f04..4e3bbdf170 100644 --- a/src/gridtools/ConvertToFES.cpp +++ b/src/gridtools/ConvertToFES.cpp @@ -42,13 +42,13 @@ The free energy calculated on a grid is output by this action and can be printed This is a typical example showing how CONVERT_TO_FES might be used when postprocessing a trajectory. The input below calculates the free energy as a function of the distance between atom 1 and atom 2. This is done by accumulating a histogram as a function of this distance using kernel density estimation -and the HISTOGRAM action. All the data within this trajectory is used in the construction of this -HISTOGRAM. Finally, once all the data has been read in, the histogram is converted to a free energy +and the HISTOGRAM action. All the data within this trajectory is used in the construction of this +HISTOGRAM. Finally, once all the data has been read in, the histogram is converted to a free energy using the formula above and the free energy is output to a file called fes.dat \verbatim x: DISTANCE ATOMS=1,2 -hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 +hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 ff: CONVERT_TO_FES GRID=hA1 TEMP=300 DUMPGRID GRID=ff FILE=fes.dat \endverbatim @@ -67,35 +67,35 @@ class ConvertToFES : public ActionWithInputGrid { static void registerKeywords( Keywords& keys ); explicit ConvertToFES(const ActionOptions&ao); unsigned getNumberOfQuantities() const ; - void prepare(){ activated=true; } - void prepareForAveraging(){ ActionWithInputGrid::prepareForAveraging(); activated=false; } + void prepare() { activated=true; } + void prepareForAveraging() { ActionWithInputGrid::prepareForAveraging(); activated=false; } void compute( const unsigned& current, MultiValue& myvals ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } bool onStep() const { return activated; } void runFinalJobs(); }; PLUMED_REGISTER_ACTION(ConvertToFES,"CONVERT_TO_FES") -void ConvertToFES::registerKeywords( Keywords& keys ){ +void ConvertToFES::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.add("optional","TEMP","the temperature at which you are operating"); - keys.remove("STRIDE"); keys.remove("KERNEL"); keys.remove("BANDWIDTH"); + keys.remove("STRIDE"); keys.remove("KERNEL"); keys.remove("BANDWIDTH"); keys.remove("LOGWEIGHTS"); keys.remove("CLEAR"); keys.remove("UNORMALIZED"); } ConvertToFES::ConvertToFES(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao), -activated(false) + Action(ao), + ActionWithInputGrid(ao), + activated(false) { plumed_assert( ingrid->getNumberOfComponents()==1 ); // Create a grid - createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); - if( ingrid->noDerivatives() ) mygrid->setNoDerivatives(); + createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); + if( ingrid->noDerivatives() ) mygrid->setNoDerivatives(); std::vector fspacing; - mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), ingrid->getNbin(), fspacing); + mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), ingrid->getNbin(), fspacing); setAveragingAction( mygrid, true ); simtemp=0.; parse("TEMP",simtemp); @@ -104,10 +104,10 @@ activated(false) if( simtemp==0 ) error("TEMP not set - use keyword TEMP"); // Now create task list - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); // And activate all tasks - deactivateAllTasks(); - for(unsigned i=0;igetNumberOfPoints();++i) taskFlags[i]=1; + deactivateAllTasks(); + for(unsigned i=0; igetNumberOfPoints(); ++i) taskFlags[i]=1; lockContributors(); } @@ -118,12 +118,12 @@ unsigned ConvertToFES::getNumberOfQuantities() const { void ConvertToFES::compute( const unsigned& current, MultiValue& myvals ) const { double val=getFunctionValue( current ); myvals.setValue(1, -simtemp*std::log(val) ); - if( !mygrid->noDerivatives() && val>0 ){ - for(unsigned i=0;igetDimension();++i) myvals.setValue( 2+i, -(simtemp/val)*ingrid->getGridElement(current,i+1) ); + if( !mygrid->noDerivatives() && val>0 ) { + for(unsigned i=0; igetDimension(); ++i) myvals.setValue( 2+i, -(simtemp/val)*ingrid->getGridElement(current,i+1) ); } } -void ConvertToFES::runFinalJobs(){ +void ConvertToFES::runFinalJobs() { activated=true; update(); } diff --git a/src/gridtools/DumpCube.cpp b/src/gridtools/DumpCube.cpp index 22676175bd..0fbc47f566 100644 --- a/src/gridtools/DumpCube.cpp +++ b/src/gridtools/DumpCube.cpp @@ -28,22 +28,22 @@ Output a three dimensional grid using the Gaussian cube file format. Suppose you have calculated the value of a function on a three dimensional grid. -This function might be a \ref HISTOGRAM or it might be a free energy energy surface +This function might be a \ref HISTOGRAM or it might be a free energy energy surface that was calculated from this histogram by using \ref CONVERT_TO_FES. Alternatively, your function might be a phase-field that was calculated using \ref MULTICOLVARDENS. Whatever the function is, however, you obviously cannot show it using a typical contour -plotting program such as gnuplot as you have three input variables. +plotting program such as gnuplot as you have three input variables. Tools like VMD have nice features for plotting these types of three dimensional functions -but typically you are required to use a Gaussian cube file format to input the data. This +but typically you are required to use a Gaussian cube file format to input the data. This action thus allows you to output a function evaluated on a grid to a Gaussian cube file format. \par Examples The input below can be used to postprocess a trajectory. A histogram as a function of the distance between atoms 1 and 2, the distance between atom 1 and 3 and the angle between the vector connecting atoms 1 and -2 and 1 and 3 is computed using kernel density estimation. Once all the data contained in the trajectory has been read in and -all the kernels have been added the resulting histogram is output to a file called histoA1.cube. This file has the +2 and 1 and 3 is computed using kernel density estimation. Once all the data contained in the trajectory has been read in and +all the kernels have been added the resulting histogram is output to a file called histoA1.cube. This file has the Gaussian cube file format. The histogram can thus be visualized using tools such as VMD. \verbatim @@ -52,7 +52,7 @@ x2: DISTANCE ATOMS=1,3 x3: ANGLE ATOMS=1,2,3 hA1: HISTOGRAM ARG=x1,x2,x3 GRID_MIN=0.0,0.0,0.0 GRID_MAX=3.0,3.0,3.0 GRID_BIN=10,10,10 BANDWIDTH=1.0,1.0,1.0 -DUMPCUBE GRID=hA1 FILE=histoA1.cube +DUMPCUBE GRID=hA1 FILE=histoA1.cube \endverbatim */ @@ -66,32 +66,32 @@ class DumpCube : public GridPrintingBase { unsigned mycomp; public: static void registerKeywords( Keywords& keys ); - explicit DumpCube(const ActionOptions&ao); + explicit DumpCube(const ActionOptions&ao); void printGrid( OFile& ofile ) const ; }; PLUMED_REGISTER_ACTION(DumpCube,"DUMPCUBE") -void DumpCube::registerKeywords( Keywords& keys ){ +void DumpCube::registerKeywords( Keywords& keys ) { GridPrintingBase::registerKeywords( keys ); keys.add("optional","COMPONENT","if your input is a vector field use this to specifiy the component of the input vector field for which you wish to output"); } DumpCube::DumpCube(const ActionOptions&ao): -Action(ao), -GridPrintingBase(ao) + Action(ao), + GridPrintingBase(ao) { fmt = fmt + " "; if( ingrid->getType()!="flat" ) error("cannot dump grid of type " + ingrid->getType() + " using DUMPCUBE"); if( ingrid->getDimension()!=3 ) error("cannot print cube file if grid does not contain three dimensional data"); - if( ingrid->getNumberOfComponents()==1 ){ - mycomp=0; + if( ingrid->getNumberOfComponents()==1 ) { + mycomp=0; } else { - int tcomp=-1; parse("COMPONENT",tcomp); - if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); - mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; - log.printf(" using %dth component of grid \n",tcomp ); + int tcomp=-1; parse("COMPONENT",tcomp); + if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); + mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; + log.printf(" using %dth component of grid \n",tcomp ); } checkRead(); @@ -105,19 +105,19 @@ void DumpCube::printGrid( OFile& ofile ) const { // Number of atoms followed by position of origin (origin set so that center of grid is in center of cell) std::string ostr = "%d " + fmt + fmt + fmt + "\n"; ofile.printf(ostr.c_str(),1,-0.5*lunit*ingrid->getGridExtent(0),-0.5*lunit*ingrid->getGridExtent(1),-0.5*lunit*ingrid->getGridExtent(2)); - ofile.printf(ostr.c_str(),ingrid->getNbin()[0],lunit*ingrid->getGridSpacing()[0],0.0,0.0); // Number of bins in each direction followed by + ofile.printf(ostr.c_str(),ingrid->getNbin()[0],lunit*ingrid->getGridSpacing()[0],0.0,0.0); // Number of bins in each direction followed by ofile.printf(ostr.c_str(),ingrid->getNbin()[1],0.0,lunit*ingrid->getGridSpacing()[1],0.0); // shape of voxel ofile.printf(ostr.c_str(),ingrid->getNbin()[2],0.0,0.0,lunit*ingrid->getGridSpacing()[2]); ofile.printf(ostr.c_str(),1,0.0,0.0,0.0); // Fake atom otherwise VMD doesn't work std::vector pp(3); std::vector nbin( ingrid->getNbin() ); - for(pp[0]=0;pp[0]getGridElement( ingrid->getIndex(pp), mycomp ) ); - if(pp[2]%6==5) ofile.printf("\n"); - } - ofile.printf("\n"); - } + for(pp[0]=0; pp[0]getGridElement( ingrid->getIndex(pp), mycomp ) ); + if(pp[2]%6==5) ofile.printf("\n"); + } + ofile.printf("\n"); + } } } diff --git a/src/gridtools/DumpGrid.cpp b/src/gridtools/DumpGrid.cpp index acbcdc805e..608742a8bf 100644 --- a/src/gridtools/DumpGrid.cpp +++ b/src/gridtools/DumpGrid.cpp @@ -32,12 +32,12 @@ Output the function on the grid to a file with the PLUMED grid format. PLUMED provides a number of actions that calculate the values of functions on grids. For instance, whenver you calculate a free energy as a function of a collective variable using -\ref HISTOGRAM and \ref CONVERT_TO_FES you will generally want to output the value of the free energy at a number of points on a +\ref HISTOGRAM and \ref CONVERT_TO_FES you will generally want to output the value of the free energy at a number of points on a discrete grid that covers the CV space uniformly. Alternatively you may want to calculate -what value some symmetry function takes at different points inside your simulation cell using \ref MULTICOLVARDENS. +what value some symmetry function takes at different points inside your simulation cell using \ref MULTICOLVARDENS. -This action allows you to output these functions calculated on a grid using a format that can be read in using gnuplot -and other such plotting programs. The file output using this action will have a header that contains some essential +This action allows you to output these functions calculated on a grid using a format that can be read in using gnuplot +and other such plotting programs. The file output using this action will have a header that contains some essential information about the function plotted and that looks something like this: \verbatim @@ -51,17 +51,17 @@ information about the function plotted and that looks something like this: #! SET max_y 3.0 #! SET nbins_y 100 #! SET periodic_y false -\endverbatim +\endverbatim -The header shown here tells us that we have grid showing the values that a function with two arguments x and y -takes at various points in our cell. The lines beheath the first line then tell us a little bit about these two -input arguments. +The header shown here tells us that we have grid showing the values that a function with two arguments x and y +takes at various points in our cell. The lines beheath the first line then tell us a little bit about these two +input arguments. -The remaining lines of the file give us information on the positions of our grid points and the value the function and -its partial derivatives with respect to x and y. If the header is as above a list of values of the function that have +The remaining lines of the file give us information on the positions of our grid points and the value the function and +its partial derivatives with respect to x and y. If the header is as above a list of values of the function that have x=0 and 100 values of y between 0.0 and 3.0 will be provided. This block of data will be followed with a blank line. There will then be a second block of values which will all have been evaluated the same value of x and all possible values -for y. This block is then followed by a blank line again and this pattern continues until all points of the grid have been covered. +for y. This block is then followed by a blank line again and this pattern continues until all points of the grid have been covered. \par Examples @@ -71,11 +71,11 @@ and outputs a continuos histogram as a function of them at the end of the simula TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + ARG=r1,r2 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 - BANDWIDTH=0.05,0.05 + BANDWIDTH=0.05,0.05 LABEL=hh ... HISTOGRAM @@ -88,11 +88,11 @@ and outputs a discrete histogram as a function of them at the end of the simulat TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 + ARG=r1,r2 USE_ALL_DATA KERNEL=DISCRETE - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 LABEL=hh ... HISTOGRAM @@ -106,11 +106,11 @@ and outputs the histogram accumulated thus far every 100000 steps. TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + ARG=r1,r2 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 - BANDWIDTH=0.05,0.05 + BANDWIDTH=0.05,0.05 LABEL=hh ... HISTOGRAM @@ -119,18 +119,18 @@ DUMPGRID GRID=hh FILE=histo STRIDE=100000 The following input monitors two torsional angles during a simulation and outputs a separate histogram for each 100000 steps worth of trajectory. -Notice how the CLEAR keyword is used here and how it is not used in the +Notice how the CLEAR keyword is used here and how it is not used in the previous example. \verbatim TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... - ARG=r1,r2 CLEAR=100000 - GRID_MIN=-3.14,-3.14 - GRID_MAX=3.14,3.14 + ARG=r1,r2 CLEAR=100000 + GRID_MIN=-3.14,-3.14 + GRID_MAX=3.14,3.14 GRID_BIN=200,200 - BANDWIDTH=0.05,0.05 + BANDWIDTH=0.05,0.05 GRID_WFILE=histo LABEL=hh ... HISTOGRAM @@ -144,19 +144,19 @@ DUMPGRID GRID=hh FILE=histo STRIDE=100000 class DumpGrid : public GridPrintingBase { public: static void registerKeywords( Keywords& keys ); - explicit DumpGrid(const ActionOptions&ao); + explicit DumpGrid(const ActionOptions&ao); void printGrid( OFile& ofile ) const ; }; PLUMED_REGISTER_ACTION(DumpGrid,"DUMPGRID") -void DumpGrid::registerKeywords( Keywords& keys ){ +void DumpGrid::registerKeywords( Keywords& keys ) { GridPrintingBase::registerKeywords( keys ); } DumpGrid::DumpGrid(const ActionOptions&ao): -Action(ao), -GridPrintingBase(ao) + Action(ao), + GridPrintingBase(ao) { if( ingrid->getType()!="flat" ) error("cannot dump grid of type " + ingrid->getType() + " using DUMPGRID"); fmt = " " + fmt; checkRead(); @@ -164,33 +164,33 @@ GridPrintingBase(ao) void DumpGrid::printGrid( OFile& ofile ) const { ofile.addConstantField("normalisation"); - for(unsigned i=0;igetDimension();++i){ - ofile.addConstantField("min_" + ingrid->getComponentName(i) ); - ofile.addConstantField("max_" + ingrid->getComponentName(i) ); - ofile.addConstantField("nbins_" + ingrid->getComponentName(i) ); - ofile.addConstantField("periodic_" + ingrid->getComponentName(i) ); + for(unsigned i=0; igetDimension(); ++i) { + ofile.addConstantField("min_" + ingrid->getComponentName(i) ); + ofile.addConstantField("max_" + ingrid->getComponentName(i) ); + ofile.addConstantField("nbins_" + ingrid->getComponentName(i) ); + ofile.addConstantField("periodic_" + ingrid->getComponentName(i) ); } std::vector xx( ingrid->getDimension() ); std::vector ind( ingrid->getDimension() ); - for(unsigned i=0;igetNumberOfPoints();++i){ - ingrid->getIndices( i, ind ); - if(i>0 && ingrid->getDimension()==2 && ind[ingrid->getDimension()-2]==0) ofile.printf("\n"); - ofile.fmtField(fmt); ofile.printField("normalisation", ingrid->getNorm() ); - for(unsigned j=0;jgetDimension();++j){ - ofile.printField("min_" + ingrid->getComponentName(j), ingrid->getMin()[j] ); - ofile.printField("max_" + ingrid->getComponentName(j), ingrid->getMax()[j] ); - ofile.printField("nbins_" + ingrid->getComponentName(j), static_cast(ingrid->getNbin()[j]) ); - if( ingrid->isPeriodic(j) ) ofile.printField("periodic_" + ingrid->getComponentName(j), "true" ); - else ofile.printField("periodic_" + ingrid->getComponentName(j), "false" ); - } - // Retrieve and print the grid coordinates - ingrid->getGridPointCoordinates(i, xx ); - for(unsigned j=0;jgetDimension();++j){ ofile.fmtField(fmt); ofile.printField(ingrid->getComponentName(j),xx[j]); } - for(unsigned j=0;jgetNumberOfQuantities();++j){ - ofile.fmtField(fmt); ofile.printField(ingrid->arg_names[ingrid->dimension+j], ingrid->getGridElement( i, j ) ); - } - ofile.printField(); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + ingrid->getIndices( i, ind ); + if(i>0 && ingrid->getDimension()==2 && ind[ingrid->getDimension()-2]==0) ofile.printf("\n"); + ofile.fmtField(fmt); ofile.printField("normalisation", ingrid->getNorm() ); + for(unsigned j=0; jgetDimension(); ++j) { + ofile.printField("min_" + ingrid->getComponentName(j), ingrid->getMin()[j] ); + ofile.printField("max_" + ingrid->getComponentName(j), ingrid->getMax()[j] ); + ofile.printField("nbins_" + ingrid->getComponentName(j), static_cast(ingrid->getNbin()[j]) ); + if( ingrid->isPeriodic(j) ) ofile.printField("periodic_" + ingrid->getComponentName(j), "true" ); + else ofile.printField("periodic_" + ingrid->getComponentName(j), "false" ); + } + // Retrieve and print the grid coordinates + ingrid->getGridPointCoordinates(i, xx ); + for(unsigned j=0; jgetDimension(); ++j) { ofile.fmtField(fmt); ofile.printField(ingrid->getComponentName(j),xx[j]); } + for(unsigned j=0; jgetNumberOfQuantities(); ++j) { + ofile.fmtField(fmt); ofile.printField(ingrid->arg_names[ingrid->dimension+j], ingrid->getGridElement( i, j ) ); + } + ofile.printField(); } } diff --git a/src/gridtools/FindContour.cpp b/src/gridtools/FindContour.cpp index 1fb94949af..a58e4f650e 100644 --- a/src/gridtools/FindContour.cpp +++ b/src/gridtools/FindContour.cpp @@ -29,14 +29,14 @@ /* Find an isocontour in a smooth function. -As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate -a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables +As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate +a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables or it might be a phase field that has been calcualted using \ref MULTICOLVARDENS. If this function has one or two input arguments it is relatively straightforward to plot the function. If by contrast the data has a three or more dimensions -it can be difficult to visualize. +it can be difficult to visualize. -This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour -where the function takes a particular values. In other words, for the function \f$f(x,y)\f$ this action would find a set +This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour +where the function takes a particular values. In other words, for the function \f$f(x,y)\f$ this action would find a set of points \f$\{x_c,y_c\}\f$ that have: \f[ @@ -55,14 +55,14 @@ Furthermore, the topology of the contour will be determined by the algorithm and \par Examples The input below allows you to calculate something akin to a Willard-Chandler dividing surface \cite wcsurface. -The simulation cell in this case contains a solid phase and a liquid phase. The Willard-Chandler surface is the +The simulation cell in this case contains a solid phase and a liquid phase. The Willard-Chandler surface is the surface that separates the parts of the box containing the solid from the parts containing the liquid. To compute the position of this surface the \ref FCCUBIC symmetry function is calculated for each of the atoms in the system from on the geometry of the atoms in the first coordination sphere of each of the atoms. These quantities are then transformed using a switching function. -This procedure generates a single number for each atom in the system and this quantity has a value of one for atoms that are in +This procedure generates a single number for each atom in the system and this quantity has a value of one for atoms that are in parts of the box that resemble the solid structure and zero for atoms that are in parts of the box that resemble the liquid. The position of a virtual atom is then computed using \ref CENTER_OF_MULTICOLVAR and a phase field model is constructed using -\ref MULTICOLVARDENS. These procedure ensures that we have a continuous function that gives a measure of the average degree of +\ref MULTICOLVARDENS. These procedure ensures that we have a continuous function that gives a measure of the average degree of solidness at each point in the simulation cell. The Willard-Chandler dividing surface is calculated by finding a a set of points at which the value of this phase field is equal to 0.5. This set of points is output to file called mycontour.dat. A new contour is found on every single step for each frame that is read in. @@ -70,20 +70,20 @@ is found on every single step for each frame that is read in. \verbatim UNITS NATURAL FCCUBIC ... - SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} + SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} ALPHA=27 PHI=0.0 THETA=-1.5708 PSI=-2.35619 LABEL=fcc ... FCCUBIC tfcc: MTRANSFORM_MORE DATA=fcc SWITCH={SMAP R_0=0.5 A=8 B=8} center: CENTER_OF_MULTICOLVAR DATA=tfcc -MULTICOLVARDENS ... - DATA=tfcc ORIGIN=center DIR=xyz LABEL=dens +MULTICOLVARDENS ... + DATA=tfcc ORIGIN=center DIR=xyz LABEL=dens NBINS=80,80,80 BANDWIDTH=1.0,1.0,1.0 STRIDE=25 LABEL=dens STRIDE=1 CLEAR=1 ... MULTICOLVARDENS -FIND_CONTOUR GRID=dens CONTOUR=0.5 FILE=mycontour.dat +FIND_CONTOUR GRID=dens CONTOUR=0.5 FILE=mycontour.dat \endverbatim */ @@ -96,7 +96,7 @@ class FindContour : public ContourFindingBase { private: bool firsttime; unsigned gbuffer; -/// Stuff for output +/// Stuff for output OFile of; double lenunit; std::string fmt_xyz; @@ -107,7 +107,7 @@ class FindContour : public ContourFindingBase { explicit FindContour(const ActionOptions&ao); bool checkAllActive() const { return gbuffer==0; } void prepareForAveraging(); - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } unsigned getNumberOfQuantities() const { return 1 + ingrid->getDimension(); } void compute( const unsigned& current, MultiValue& myvals ) const ; void finishAveraging(); @@ -115,7 +115,7 @@ class FindContour : public ContourFindingBase { PLUMED_REGISTER_ACTION(FindContour,"FIND_CONTOUR") -void FindContour::registerKeywords( Keywords& keys ){ +void FindContour::registerKeywords( Keywords& keys ) { ContourFindingBase::registerKeywords( keys ); // We want a better way of doing this bit keys.add("compulsory","BUFFER","0","number of buffer grid points around location where grid was found on last step. If this is zero the full grid is calculated on each step"); @@ -125,9 +125,9 @@ void FindContour::registerKeywords( Keywords& keys ){ } FindContour::FindContour(const ActionOptions&ao): -Action(ao), -ContourFindingBase(ao), -firsttime(true) + Action(ao), + ContourFindingBase(ao), + firsttime(true) { parse("BUFFER",gbuffer); @@ -137,20 +137,20 @@ firsttime(true) if( file.length()==0 ) error("name out output file was not specified"); std::string type=Tools::extension(file); log<<" file name "<0){ - int p; Tools::convert(precision,p); - log<<" with precision "<0) { + int p; Tools::convert(precision,p); + log<<" with precision "<getDimension()*ingrid->getNumberOfPoints();++i) addTaskToList( i ); + if( firsttime ) { + for(unsigned i=0; igetDimension()*ingrid->getNumberOfPoints(); ++i) addTaskToList( i ); } firsttime=false; deactivateAllTasks(); @@ -171,34 +171,34 @@ void FindContour::prepareForAveraging(){ std::vector ind( ingrid->getDimension() ); std::vector ones( ingrid->getDimension(), 1 ); unsigned num_neighbours; std::vector neighbours; - for(unsigned i=0;igetNumberOfPoints();++i){ - // Ensure inactive grid points are ignored - if( ingrid->inactive(i) ) continue; - - // Get the index of the current grid point - ingrid->getIndices( i, ind ); - ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); - bool cycle=false; - for(unsigned j=0;jinactive( neighbours[j]) ){ cycle=true; break; } - } - if( cycle ) continue; - - // Get the value of a point on the grid - double val1=getFunctionValue( i ) - contour; - bool edge=false; - for(unsigned j=0;jgetDimension();++j){ - // Make sure we don't search at the edge of the grid - if( !ingrid->isPeriodic(j) && (ind[j]+1)==nbin[j] ) continue; - else if( (ind[j]+1)==nbin[j] ){ edge=true; ind[j]=0; } - else ind[j]+=1; - double val2=getFunctionValue( ind ) - contour; - if( val1*val2<0 ) taskFlags[ ingrid->getDimension()*i + j ] = 1; - if( ingrid->isPeriodic(j) && edge ){ edge=false; ind[j]=nbin[j]-1; } - else ind[j]-=1; - } + for(unsigned i=0; igetNumberOfPoints(); ++i) { + // Ensure inactive grid points are ignored + if( ingrid->inactive(i) ) continue; + + // Get the index of the current grid point + ingrid->getIndices( i, ind ); + ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); + bool cycle=false; + for(unsigned j=0; jinactive( neighbours[j]) ) { cycle=true; break; } + } + if( cycle ) continue; + + // Get the value of a point on the grid + double val1=getFunctionValue( i ) - contour; + bool edge=false; + for(unsigned j=0; jgetDimension(); ++j) { + // Make sure we don't search at the edge of the grid + if( !ingrid->isPeriodic(j) && (ind[j]+1)==nbin[j] ) continue; + else if( (ind[j]+1)==nbin[j] ) { edge=true; ind[j]=0; } + else ind[j]+=1; + double val2=getFunctionValue( ind ) - contour; + if( val1*val2<0 ) taskFlags[ ingrid->getDimension()*i + j ] = 1; + if( ingrid->isPeriodic(j) && edge ) { edge=false; ind[j]=nbin[j]-1; } + else ind[j]-=1; + } } - lockContributors(); + lockContributors(); } void FindContour::compute( const unsigned& current, MultiValue& myvals ) const { @@ -209,40 +209,40 @@ void FindContour::compute( const unsigned& current, MultiValue& myvals ) const { // Retrieve the direction we are searching for the contour unsigned gdir = current%(ingrid->getDimension() ); - std::vector direction( ingrid->getDimension() , 0 ); + std::vector direction( ingrid->getDimension(), 0 ); direction[gdir] = 0.999999999*ingrid->getGridSpacing()[gdir]; // Now find the contour findContour( direction, point ); // And transfer to the store data vessel - for(unsigned i=0;igetDimension();++i) myvals.setValue( 1+i, point[i] ); + for(unsigned i=0; igetDimension(); ++i) myvals.setValue( 1+i, point[i] ); } -void FindContour::finishAveraging(){ +void FindContour::finishAveraging() { // And update the list of active grid points - if( gbuffer>0 ){ - std::vector neighbours; unsigned num_neighbours; - std::vector ugrid_indices( ingrid->getDimension() ); - std::vector active( ingrid->getNumberOfPoints(), false ); - std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); - for(unsigned i=0;igetDimension() ); - // Get the indices of this point - ingrid->getIndices( ipoint, ugrid_indices ); - // Now activate buffer region - ingrid->getNeighbors( ugrid_indices , gbuffer_vec, num_neighbours, neighbours ); - for(unsigned n=0;nactivateThesePoints( active ); + if( gbuffer>0 ) { + std::vector neighbours; unsigned num_neighbours; + std::vector ugrid_indices( ingrid->getDimension() ); + std::vector active( ingrid->getNumberOfPoints(), false ); + std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); + for(unsigned i=0; igetDimension() ); + // Get the indices of this point + ingrid->getIndices( ipoint, ugrid_indices ); + // Now activate buffer region + ingrid->getNeighbors( ugrid_indices, gbuffer_vec, num_neighbours, neighbours ); + for(unsigned n=0; nactivateThesePoints( active ); } std::vector point( 1 + ingrid->getDimension() ); of.printf("%u\n",mydata->getNumberOfStoredValues()); of.printf("Points found on isocontour\n"); - for(unsigned i=0;igetNumberOfStoredValues();++i){ - mydata->retrieveSequentialValue( i, false, point ); of.printf("X"); - for(unsigned j=0;jgetDimension();++j) of.printf( (" " + fmt_xyz).c_str(), lenunit*point[1+j] ); - of.printf("\n"); + for(unsigned i=0; igetNumberOfStoredValues(); ++i) { + mydata->retrieveSequentialValue( i, false, point ); of.printf("X"); + for(unsigned j=0; jgetDimension(); ++j) of.printf( (" " + fmt_xyz).c_str(), lenunit*point[1+j] ); + of.printf("\n"); } } diff --git a/src/gridtools/FindContourSurface.cpp b/src/gridtools/FindContourSurface.cpp index 6a83c0abdc..ce24d757f1 100644 --- a/src/gridtools/FindContourSurface.cpp +++ b/src/gridtools/FindContourSurface.cpp @@ -26,14 +26,14 @@ /* Find an isocontour by searching along either the x, y or z direction. -As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate -a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables +As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate +a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables or it might be a phase field that has been calcualted using \ref MULTICOLVARDENS. If this function has one or two input -arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be +arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be difficult to visualize. -This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour -wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set +This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour +wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set of points \f$\{x_c,y_c,z_c\}\f$ that have: \f[ @@ -41,34 +41,34 @@ f(x_c,y_c,z_c) - c = 0 \f] where \f$c\f$ is some constant value that is specified by the user. The points on this contour are find by searching along lines -that run parallel to the \f$x\f$, \f$y\f$ or \f$z\f$ axis of the simulation cell. The result is, therefore, a two dimensional -function evaluated on a grid that gives us the height of the interface as a function of two coordinates. +that run parallel to the \f$x\f$, \f$y\f$ or \f$z\f$ axis of the simulation cell. The result is, therefore, a two dimensional +function evaluated on a grid that gives us the height of the interface as a function of two coordinates. -It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to -find the full set of contour points if the contour does not have the same topology as an infinite plane. If you are uncertain that the isocontours in your +It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to +find the full set of contour points if the contour does not have the same topology as an infinite plane. If you are uncertain that the isocontours in your function have the appropriate topology you should use \ref FIND_CONTOUR in place of \ref FIND_CONTOUR_SURFACE. \par Examples -The input shown below was used to analyse the results from a simulation of an interface between solid and molten Lennard Jones. The interface between -the solid and the liquid was set up in the plane perpendicular to the \f$z\f$ direction of the simulation cell. The input below calculates something -akin to a Willard-Chandler dividing surface \cite wcsurface between the solid phase and the liquid phase. There are two of these interfaces within the -simulation box because of the periodic boundary conditions but we were able to determine that one of these two surfaces lies in a particular part of the -simulation box. The input below detects the height profile of one of these two interfaces. It does so by computing a phase field average of the +The input shown below was used to analyse the results from a simulation of an interface between solid and molten Lennard Jones. The interface between +the solid and the liquid was set up in the plane perpendicular to the \f$z\f$ direction of the simulation cell. The input below calculates something +akin to a Willard-Chandler dividing surface \cite wcsurface between the solid phase and the liquid phase. There are two of these interfaces within the +simulation box because of the periodic boundary conditions but we were able to determine that one of these two surfaces lies in a particular part of the +simulation box. The input below detects the height profile of one of these two interfaces. It does so by computing a phase field average of the \ref FCCUBIC symmetry function using the \ref MULTICOLVARDENS action. Notice that we use the fact that we know roughly where the interface is when specifying -how this phase field is to be calculated and specify the region over the \f$z\f$-axis in which we are going to search for the phase field in the line defining +how this phase field is to be calculated and specify the region over the \f$z\f$-axis in which we are going to search for the phase field in the line defining the \ref MULTICOLVARDENS. Once we have calculated the phase field we search for contour points on the lines that run parallel to the \f$z\f$-direction of the cell -box using the FIND_CONTOUR_SURFACE command. The final result is a \f$14 \times 14\f$ grid of values for the height of the interface as a function of the \f$(x,y)\f$ +box using the FIND_CONTOUR_SURFACE command. The final result is a \f$14 \times 14\f$ grid of values for the height of the interface as a function of the \f$(x,y)\f$ position. This grid is then output to a file called contour2.dat. Notice that the commands below calculate the instantaneous position of the surface separating the solid and liquid and that as such the accumulated average is cleared -on every step. +on every step. \verbatim UNITS NATURAL FCCUBIC ... - SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} + SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} ALPHA=27 PHI=0.0 THETA=-1.5708 PSI=-2.35619 LABEL=fcc ... FCCUBIC @@ -105,17 +105,17 @@ class FindContourSurface : public ContourFindingBase { PLUMED_REGISTER_ACTION(FindContourSurface,"FIND_CONTOUR_SURFACE") -void FindContourSurface::registerKeywords( Keywords& keys ){ +void FindContourSurface::registerKeywords( Keywords& keys ) { ContourFindingBase::registerKeywords( keys ); keys.add("compulsory","SEARCHDIR","In which directions do you wish to search for the contour."); keys.add("compulsory","BUFFER","0","number of buffer grid points around location where grid was found on last step. If this is zero the full grid is calculated on each step"); } FindContourSurface::FindContourSurface(const ActionOptions&ao): -Action(ao), -ContourFindingBase(ao), -firsttime(true), -ones(ingrid->getDimension(),1) + Action(ao), + ContourFindingBase(ao), + firsttime(true), + ones(ingrid->getDimension(),1) { if( ingrid->getDimension()<2 ) error("cannot find dividing surface if input grid is one dimensional"); @@ -125,85 +125,85 @@ ones(ingrid->getDimension(),1) checkRead(); unsigned n=0; gdirs.resize( ingrid->getDimension()-1 ); - for(unsigned i=0;igetDimension();++i){ - if( ingrid->getComponentName(i)==dir ){ - dir_n=i; - } else { - if( n==gdirs.size() ) error("could not find " + dir + " direction in input grid"); - gdirs[n]=i; n++; - } + for(unsigned i=0; igetDimension(); ++i) { + if( ingrid->getComponentName(i)==dir ) { + dir_n=i; + } else { + if( n==gdirs.size() ) error("could not find " + dir + " direction in input grid"); + gdirs[n]=i; n++; + } } if( n!=(ingrid->getDimension()-1) ) error("output of grid is not understood"); // Create the input from the old string std::string vstring = "COMPONENTS=" + getLabel() + " COORDINATES=" + ingrid->getComponentName( gdirs[0] ); - for(unsigned i=1;igetComponentName( gdirs[i] ); + for(unsigned i=1; igetComponentName( gdirs[i] ); vstring += " PBC="; if( ingrid->isPeriodic(gdirs[0]) ) vstring+="T"; else vstring+="F"; - for(unsigned i=1;iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; + for(unsigned i=1; iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; } - createGrid( "grid", vstring ); mygrid->setNoDerivatives(); + createGrid( "grid", vstring ); mygrid->setNoDerivatives(); setAveragingAction( mygrid, true ); } -void FindContourSurface::clearAverage(){ +void FindContourSurface::clearAverage() { // Set the boundaries of the output grid std::vector fspacing; std::vector snbins( ingrid->getDimension()-1 ); std::vector smin( ingrid->getDimension()-1 ), smax( ingrid->getDimension()-1 ); - for(unsigned i=0;igetMin()[gdirs[i]]; smax[i]=ingrid->getMax()[gdirs[i]]; - snbins[i]=ingrid->getNbin()[gdirs[i]]; - } + for(unsigned i=0; igetMin()[gdirs[i]]; smax[i]=ingrid->getMax()[gdirs[i]]; + snbins[i]=ingrid->getNbin()[gdirs[i]]; + } mygrid->setBounds( smin, smax, snbins, fspacing); resizeFunctions(); ActionWithAveraging::clearAverage(); } -void FindContourSurface::prepareForAveraging(){ +void FindContourSurface::prepareForAveraging() { // Create a task list if first time - if( firsttime ){ - std::vector find( ingrid->getDimension() ); - std::vector ind( mygrid->getDimension() ); - for(unsigned i=0;igetNumberOfPoints();++i){ - find.assign( find.size(), 0 ); mygrid->getIndices( i, ind ); - for(unsigned j=0;jgetIndex(find) ); - } - // And prepare the task list - deactivateAllTasks(); - for(unsigned i=0;igetDimension(), 0 ); - direction[dir_n] = 0.999999999*ingrid->getGridSpacing()[dir_n]; + if( firsttime ) { + std::vector find( ingrid->getDimension() ); + std::vector ind( mygrid->getDimension() ); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + find.assign( find.size(), 0 ); mygrid->getIndices( i, ind ); + for(unsigned j=0; jgetIndex(find) ); + } + // And prepare the task list + deactivateAllTasks(); + for(unsigned i=0; igetDimension(), 0 ); + direction[dir_n] = 0.999999999*ingrid->getGridSpacing()[dir_n]; } } -void FindContourSurface::finishAveraging(){ +void FindContourSurface::finishAveraging() { ContourFindingBase::finishAveraging(); // And update the list of active grid points - if( gbuffer>0 ){ - std::vector dx( ingrid->getGridSpacing() ); - std::vector point( ingrid->getDimension() ); - std::vector lpoint( mygrid->getDimension() ); - std::vector neighbours; unsigned num_neighbours; - std::vector ugrid_indices( ingrid->getDimension() ); - std::vector active( ingrid->getNumberOfPoints(), false ); - std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); - for(unsigned i=0;igetNumberOfPoints();++i){ - // Retrieve the coordinates of this grid point - mygrid->getGridPointCoordinates( i, lpoint ); - point[dir_n] = mygrid->getGridElement( i, 0 ); - // 0.5*dx added here to prevent problems with flooring of grid points - for(unsigned j=0;jgetIndices( point, ugrid_indices ); - // Now activate buffer region - ingrid->getNeighbors( ugrid_indices , gbuffer_vec, num_neighbours, neighbours ); - for(unsigned n=0;nactivateThesePoints( active ); + if( gbuffer>0 ) { + std::vector dx( ingrid->getGridSpacing() ); + std::vector point( ingrid->getDimension() ); + std::vector lpoint( mygrid->getDimension() ); + std::vector neighbours; unsigned num_neighbours; + std::vector ugrid_indices( ingrid->getDimension() ); + std::vector active( ingrid->getNumberOfPoints(), false ); + std::vector gbuffer_vec( ingrid->getDimension(), gbuffer ); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + // Retrieve the coordinates of this grid point + mygrid->getGridPointCoordinates( i, lpoint ); + point[dir_n] = mygrid->getGridElement( i, 0 ); + // 0.5*dx added here to prevent problems with flooring of grid points + for(unsigned j=0; jgetIndices( point, ugrid_indices ); + // Now activate buffer region + ingrid->getNeighbors( ugrid_indices, gbuffer_vec, num_neighbours, neighbours ); + for(unsigned n=0; nactivateThesePoints( active ); } firsttime=false; } @@ -212,51 +212,51 @@ void FindContourSurface::compute( const unsigned& current, MultiValue& myvals ) std::vector neighbours; unsigned num_neighbours; unsigned nfound=0; double minv=0, minp; std::vector bins_n( ingrid->getNbin() ); unsigned shiftn=current; std::vector ind( ingrid->getDimension() ); std::vector point( ingrid->getDimension() ); -#ifndef DNDEBUG - std::vector oind( mygrid->getDimension() ); mygrid->getIndices( current, oind ); +#ifndef DNDEBUG + std::vector oind( mygrid->getDimension() ); mygrid->getIndices( current, oind ); #endif - for(unsigned i=0;i base_ind( ingrid->getDimension() ); ingrid->getIndices( shiftn, base_ind ); - for(unsigned j=0;j base_ind( ingrid->getDimension() ); ingrid->getIndices( shiftn, base_ind ); + for(unsigned j=0; jinactive( shiftn ) ){ shiftn += ingrid->getStride()[dir_n]; continue; } - // Get the index of the current grid point - ingrid->getIndices( shiftn, ind ); - // Exit if we are at the edge of the grid - if( !ingrid->isPeriodic(dir_n) && (ind[dir_n]+1)==bins_n[dir_n] ){ - shiftn += ingrid->getStride()[dir_n]; continue; - } - - // Ensure points with inactive neighbours are ignored - ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); - bool cycle=false; - for(unsigned j=0;jinactive( neighbours[j]) ){ cycle=true; break; } - } - if( cycle ){ shiftn += ingrid->getStride()[dir_n]; continue; } - - // Now get the function value at two points - double val1=getFunctionValue( shiftn ) - contour; double val2; - if( (ind[dir_n]+1)==bins_n[dir_n] ) val2 = getFunctionValue( current ) - contour; - else val2=getFunctionValue( shiftn + ingrid->getStride()[dir_n] ) - contour; - - // Check if the minimum is bracketed - if( val1*val2<0 ){ - ingrid->getGridPointCoordinates( shiftn, point ); findContour( direction, point ); - minp=point[dir_n]; nfound++; break; - } - - - // This moves us on to the next point - shiftn += ingrid->getStride()[dir_n]; + // Ensure inactive grid points are ignored + if( ingrid->inactive( shiftn ) ) { shiftn += ingrid->getStride()[dir_n]; continue; } + // Get the index of the current grid point + ingrid->getIndices( shiftn, ind ); + // Exit if we are at the edge of the grid + if( !ingrid->isPeriodic(dir_n) && (ind[dir_n]+1)==bins_n[dir_n] ) { + shiftn += ingrid->getStride()[dir_n]; continue; + } + + // Ensure points with inactive neighbours are ignored + ingrid->getNeighbors( ind, ones, num_neighbours, neighbours ); + bool cycle=false; + for(unsigned j=0; jinactive( neighbours[j]) ) { cycle=true; break; } + } + if( cycle ) { shiftn += ingrid->getStride()[dir_n]; continue; } + + // Now get the function value at two points + double val1=getFunctionValue( shiftn ) - contour; double val2; + if( (ind[dir_n]+1)==bins_n[dir_n] ) val2 = getFunctionValue( current ) - contour; + else val2=getFunctionValue( shiftn + ingrid->getStride()[dir_n] ) - contour; + + // Check if the minimum is bracketed + if( val1*val2<0 ) { + ingrid->getGridPointCoordinates( shiftn, point ); findContour( direction, point ); + minp=point[dir_n]; nfound++; break; + } + + + // This moves us on to the next point + shiftn += ingrid->getStride()[dir_n]; } - if( nfound==0 ){ - std::string num; Tools::convert( getStep(), num ); - error("On step " + num + " failed to find required grid point"); + if( nfound==0 ) { + std::string num; Tools::convert( getStep(), num ); + error("On step " + num + " failed to find required grid point"); } - myvals.setValue( 1, minp ); + myvals.setValue( 1, minp ); } } diff --git a/src/gridtools/FindSphericalContour.cpp b/src/gridtools/FindSphericalContour.cpp index 5d99abeda7..a2ee2aa862 100644 --- a/src/gridtools/FindSphericalContour.cpp +++ b/src/gridtools/FindSphericalContour.cpp @@ -27,59 +27,59 @@ /* Find an isocontour in a three dimensional grid by searching over a Fibonacci sphere. -As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate -a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables +As discussed in the part of the manual on \ref Analysis PLUMED contains a number of tools that allow you to calculate +a function on a grid. The function on this grid might be a \ref HISTOGRAM as a function of a few collective variables or it might be a phase field that has been calcualted using \ref MULTICOLVARDENS. If this function has one or two input -arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be +arguments it is relatively straightforward to plot the function. If by contrast the data has a three dimensions it can be difficult to visualize. -This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour -wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set +This action provides one tool for visualizing these functions. It can be used to search for a set of points on a contour +wher the function takes a particular value. In other words, for the function \f$f(x,y,z)\f$ this action would find a set of points \f$\{x_c,y_c,z_c\}\f$ that have: \f[ f(x_c,y_c,z_c) - c = 0 \f] -where \f$c\f$ is some constant value that is specified by the user. The points on this contour are find by searching along a -set of equally spaced radii of a sphere that centered at on particular, user-speciified atom or virtual atom. To ensure that -these search radii are equally spaced on the surface of the sphere the search directions are generated by using a fibonacci +where \f$c\f$ is some constant value that is specified by the user. The points on this contour are find by searching along a +set of equally spaced radii of a sphere that centered at on particular, user-speciified atom or virtual atom. To ensure that +these search radii are equally spaced on the surface of the sphere the search directions are generated by using a fibonacci spiral projected on a sphere. In other words, the search directions are given by: \f[ -\mathbf{r}_i = \left( +\mathbf{r}_i = \left( \begin{matrix} \sqrt{1 - y^2} \cos(\phi) \\ \frac{2i}{n} - 1 + \frac{1}{n} \\ \sqrt{1 - y^2} \sin(\phi) -\end{matrix} +\end{matrix} \right) \f] -where \f$y\f$ is the quantity second component of the vector defined above, \f$n\f$ is the number of directions to look in and \f$\phi\f$ is +where \f$y\f$ is the quantity second component of the vector defined above, \f$n\f$ is the number of directions to look in and \f$\phi\f$ is \f[ \phi = \mod(i + R, n) \pi ( 3 - \sqrt{5} ) \f] -where \f$R\f$ is a random variable between 0 and \f$n-1\f$ that is generated during the read in of the input file and that is fixed during -the whole calculation. +where \f$R\f$ is a random variable between 0 and \f$n-1\f$ that is generated during the read in of the input file and that is fixed during +the whole calculation. -It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to -find the full set of contour points if the contour does not have the same topology as a sphere. If you are uncertain that the isocontours in your -function have a spherical topology you should use \ref FIND_CONTOUR in place of \ref FIND_SPHERICAL_CONTOUR. +It is important to note that this action can only be used to detect countours in three dimensional functions. In addition, this action will fail to +find the full set of contour points if the contour does not have the same topology as a sphere. If you are uncertain that the isocontours in your +function have a spherical topology you should use \ref FIND_CONTOUR in place of \ref FIND_SPHERICAL_CONTOUR. \par Examples -The following input demonstrates how this action can be used. The input here is used to study the shape of a droplet that has been formed during the +The following input demonstrates how this action can be used. The input here is used to study the shape of a droplet that has been formed during the condensation of Lennard Jones from the vapour. The input below achieves this by calculating the coordination numbers of all the atoms within the gas. Obviously, those atoms within the droplet will have a large value for the coordination number while the isolated atoms in the gas will have a low value. As such we can detect the sizes of the droplets by constructing a \ref CONTACT_MATRIX whose \f$ij\f$ element tells us whether atom \f$i\f$ and atom \f$j\f$ -have coordination number that is greater that two. The atoms within the various droplets within the system can then be found by performing a +have coordination number that is greater that two. The atoms within the various droplets within the system can then be found by performing a \ref DFSCLUSTERING on this matrix to detect the connected components. We can take the largest of these connected components and find the center of the droplet -by exploiting the functionality within \ref CENTER_OF_MULTICOLVAR. We can then construct a phase field based on the positions of the atoms in the largest +by exploiting the functionality within \ref CENTER_OF_MULTICOLVAR. We can then construct a phase field based on the positions of the atoms in the largest cluster and the values of the coordination numbers of these atoms. The final line in the input then finds the a set of points on the dividing surface that separates -teh droplet from the surrounding gas. The value of the phase field on this isocontour is equal to 0.75. +teh droplet from the surrounding gas. The value of the phase field on this isocontour is equal to 0.75. \verbatim # Calculate coordination numbers @@ -119,7 +119,7 @@ class FindSphericalContour : public ContourFindingBase { PLUMED_REGISTER_ACTION(FindSphericalContour,"FIND_SPHERICAL_CONTOUR") -void FindSphericalContour::registerKeywords( Keywords& keys ){ +void FindSphericalContour::registerKeywords( Keywords& keys ) { ContourFindingBase::registerKeywords( keys ); keys.add("compulsory","NPOINTS","the number of points for which we are looking for the contour"); keys.add("compulsory","INNER_RADIUS","the minimum radius on which to look for the contour"); @@ -128,8 +128,8 @@ void FindSphericalContour::registerKeywords( Keywords& keys ){ } FindSphericalContour::FindSphericalContour(const ActionOptions&ao): -Action(ao), -ContourFindingBase(ao) + Action(ao), + ContourFindingBase(ao) { if( ingrid->getDimension()!=3 ) error("input grid must be three dimensional"); @@ -145,9 +145,9 @@ ContourFindingBase(ao) checkRead(); // Create a task list - for(unsigned i=0;igetGridPointCoordinates( current, direction ); // Now setup contour point on inner sphere - for(unsigned j=0;j<3;++j){ - contour_point[j] = min*direction[j]; - direction[j] = (max-min)*direction[j] / static_cast(nbins); + for(unsigned j=0; j<3; ++j) { + contour_point[j] = min*direction[j]; + direction[j] = (max-min)*direction[j] / static_cast(nbins); } bool found=false; - for(unsigned k=0;k fourier_params; public: static void registerKeywords( Keywords& keys ); - explicit FourierTransform(const ActionOptions&ao); + explicit FourierTransform(const ActionOptions&ao); #ifndef __PLUMED_HAS_FFTW - void performOperations( const bool& from_update ){} + void performOperations( const bool& from_update ) {} #else void performOperations( const bool& from_update ); #endif - void compute( const unsigned& , MultiValue& ) const {} - bool isPeriodic(){ return false; } + void compute( const unsigned&, MultiValue& ) const {} + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(FourierTransform,"FOURIER_TRANSFORM") -void FourierTransform::registerKeywords( Keywords& keys ){ +void FourierTransform::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.remove("BANDWIDTH"); keys.remove("KERNEL"); keys.add("optional","FT_TYPE","choose what kind of data you want as output on the grid. Possible values are: ABS = compute the complex modulus of Fourier coefficients (DEFAULT); NORM = compute the norm (i.e. ABS^2) of Fourier coefficients; COMPLEX = store the FFTW complex output on the grid (as a vector)."); keys.add("compulsory","FOURIER_PARAMETERS","default","what kind of normalization is applied to the output and if the Fourier transform in FORWARD or BACKWARD. This keyword takes the form FOURIER_PARAMETERS=A,B, where A and B can be 0, 1 or -1. The default values are A=1 (no normalization at all) and B=1 (forward FFT). Other possible choices for A are: " - "A=-1: normalize by the number of data, " - "A=0: normalize by the square root of the number of data (one forward and followed by backward FFT recover the original data). "); + "A=-1: normalize by the number of data, " + "A=0: normalize by the square root of the number of data (one forward and followed by backward FFT recover the original data). "); } FourierTransform::FourierTransform(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao), -real_output(true), -store_norm(false), -fourier_params(2) + Action(ao), + ActionWithInputGrid(ao), + real_output(true), + store_norm(false), + fourier_params(2) { #ifndef __PLUMED_HAS_FFTW error("this feature is only available if you compile PLUMED with FFTW"); @@ -108,58 +108,58 @@ fourier_params(2) // Get the type of FT parse("FT_TYPE",output_type); if (output_type.length()==0) { - log<<" keyword FT_TYPE unset. By default output grid will contain REAL Fourier coefficients\n"; + log<<" keyword FT_TYPE unset. By default output grid will contain REAL Fourier coefficients\n"; } else if ( output_type=="ABS" || output_type=="abs") { - log << " keyword FT_TYPE is '"<< output_type << "' : will compute the MODULUS of Fourier coefficients\n"; + log << " keyword FT_TYPE is '"<< output_type << "' : will compute the MODULUS of Fourier coefficients\n"; } else if ( output_type=="NORM" || output_type=="norm") { - log << " keyword FT_TYPE is '"<< output_type << "' : will compute the NORM of Fourier coefficients\n"; - store_norm=true; + log << " keyword FT_TYPE is '"<< output_type << "' : will compute the NORM of Fourier coefficients\n"; + store_norm=true; } else if ( output_type=="COMPLEX" || output_type=="complex" ) { - log<<" keyword FT_TYPE is '"<< output_type <<"' : output grid will contain the COMPLEX Fourier coefficients\n"; - real_output=false; + log<<" keyword FT_TYPE is '"<< output_type <<"' : output grid will contain the COMPLEX Fourier coefficients\n"; + real_output=false; } else error("keyword FT_TYPE unrecognized!"); // Normalize output? std::string params_str; parse("FOURIER_PARAMETERS",params_str); if (params_str=="default") { - fourier_params.assign( fourier_params.size(), 1 ); - log.printf(" default values of Fourier parameters A=%i, B=%i : the output will NOT be normalized and BACKWARD Fourier transform is computed \n", fourier_params[0],fourier_params[1]); + fourier_params.assign( fourier_params.size(), 1 ); + log.printf(" default values of Fourier parameters A=%i, B=%i : the output will NOT be normalized and BACKWARD Fourier transform is computed \n", fourier_params[0],fourier_params[1]); } else { - std::vector fourier_str = Tools::getWords(params_str, "\t\n ,"); - if (fourier_str.size()>2) error("FOURIER_PARAMETERS can take just two values"); - for (unsigned i=0; i1 || fourier_params[i]<-1) error("values accepted for FOURIER_PARAMETERS are only -1, 1 or 0"); - } - log.printf(" Fourier parameters are A=%i, B=%i \n", fourier_params[0],fourier_params[1]); + std::vector fourier_str = Tools::getWords(params_str, "\t\n ,"); + if (fourier_str.size()>2) error("FOURIER_PARAMETERS can take just two values"); + for (unsigned i=0; i1 || fourier_params[i]<-1) error("values accepted for FOURIER_PARAMETERS are only -1, 1 or 0"); + } + log.printf(" Fourier parameters are A=%i, B=%i \n", fourier_params[0],fourier_params[1]); } // Create the input from the old string std::string vstring; unsigned n=0; gdirs.resize( ingrid->getDimension() ); - for(unsigned i=0;igetDimension();++i){ - gdirs[n]=i; n++; + for(unsigned i=0; igetDimension(); ++i) { + gdirs[n]=i; n++; } - + plumed_assert( n==ingrid->getDimension() ); - - if (real_output) { - if (!store_norm) vstring="COMPONENTS=" + getLabel() + "_abs"; - else vstring="COMPONENTS=" + getLabel() + "_norm"; + + if (real_output) { + if (!store_norm) vstring="COMPONENTS=" + getLabel() + "_abs"; + else vstring="COMPONENTS=" + getLabel() + "_norm"; } else vstring="COMPONENTS=" + getLabel() + "_real," + getLabel() + "_imag"; - + // Set COORDINATES keyword vstring += " COORDINATES=" + ingrid->getComponentName( gdirs[0] ); for(unsigned i=1; igetComponentName( gdirs[i] ); - + // Set PBC keyword vstring += " PBC="; if( ingrid->isPeriodic(gdirs[0]) ) vstring+="T"; else vstring+="F"; - for(unsigned i=1; iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; + for(unsigned i=1; iisPeriodic(gdirs[i]) ) vstring+=",T"; else vstring+=",F"; } - + // Create a grid on which to store the fourier transform of the input grid createGrid( "grid", vstring ); @@ -171,97 +171,97 @@ fourier_params(2) } #ifdef __PLUMED_HAS_FFTW -void FourierTransform::performOperations( const bool& from_update ){ - - // Spacing of the real grid - std::vector g_spacing ( ingrid->getGridSpacing() ); - // Spacing of the k-grid - std::vector ft_spacing; - // Extents of the k-grid - std::vector ft_min( ingrid->getMin() ), ft_max( ingrid->getMax() ); - // Number of bins in the k-grid (equal to the number of bins in the real grid) - std::vector ft_bins ( ingrid->getNbin() ); - - for (unsigned i=0; igetDimension(); ++i) { - // Check PBC in current grid dimension - if( !ingrid->isPeriodic(i) ) ft_bins[i]++; - // Compute k-grid extents - double dmin, dmax; - Tools::convert(ft_min[i],dmin); Tools::convert(ft_max[i],dmax); - // We want to have the min of k-grid at point (0,0) - dmin=0.0; - dmax=2.0*pi*ft_bins[i]/( ingrid->getGridExtent(i) ); - Tools::convert(dmin,ft_min[i]); Tools::convert(dmax,ft_max[i]); - } - - // This is the actual setup of the k-grid - mygrid->setBounds( ft_min, ft_max, ft_bins, ft_spacing); resizeFunctions(); - - // *** CHECK CORRECT k-GRID BOUNDARIES *** - //log<<"Real grid boundaries: \n" - // <<" min_x: "<getMin()[0]<<" min_y: "<getMin()[1]<<"\n" - // <<" max_x: "<getMax()[0]<<" max_y: "<getMax()[1]<<"\n" - // <<"K-grid boundaries:"<<"\n" - // <<" min_x: "< N_input_data( ingrid->getNbin() ); - size_t fft_dimension=1; for(unsigned i=0; i( N_input_data[i] ); - - // FFT arrays - std::vector > input_data(fft_dimension), fft_data(fft_dimension); - - - // Fill real input with the data on the grid - std::vector ind( ingrid->getDimension() ); - for (unsigned i=0;igetNumberOfPoints();++i) { - // Get point indices - ingrid->getIndices(i, ind); - // Fill input data in row-major order - input_data[ind[0]*N_input_data[0]+ind[1]].real( getFunctionValue( i ) ); - input_data[ind[0]*N_input_data[0]+ind[1]].imag( 0.0 ); - } +void FourierTransform::performOperations( const bool& from_update ) { + + // Spacing of the real grid + std::vector g_spacing ( ingrid->getGridSpacing() ); + // Spacing of the k-grid + std::vector ft_spacing; + // Extents of the k-grid + std::vector ft_min( ingrid->getMin() ), ft_max( ingrid->getMax() ); + // Number of bins in the k-grid (equal to the number of bins in the real grid) + std::vector ft_bins ( ingrid->getNbin() ); + + for (unsigned i=0; igetDimension(); ++i) { + // Check PBC in current grid dimension + if( !ingrid->isPeriodic(i) ) ft_bins[i]++; + // Compute k-grid extents + double dmin, dmax; + Tools::convert(ft_min[i],dmin); Tools::convert(ft_max[i],dmax); + // We want to have the min of k-grid at point (0,0) + dmin=0.0; + dmax=2.0*pi*ft_bins[i]/( ingrid->getGridExtent(i) ); + Tools::convert(dmin,ft_min[i]); Tools::convert(dmax,ft_max[i]); + } + + // This is the actual setup of the k-grid + mygrid->setBounds( ft_min, ft_max, ft_bins, ft_spacing); resizeFunctions(); + + // *** CHECK CORRECT k-GRID BOUNDARIES *** + //log<<"Real grid boundaries: \n" + // <<" min_x: "<getMin()[0]<<" min_y: "<getMin()[1]<<"\n" + // <<" max_x: "<getMax()[0]<<" max_y: "<getMax()[1]<<"\n" + // <<"K-grid boundaries:"<<"\n" + // <<" min_x: "<(&input_data[0]), reinterpret_cast(&fft_data[0]), fourier_params[1], FFTW_ESTIMATE); - - // Compute FT - fftw_execute( plan_complex ); - // Compute the normalization constant - double norm=1.0; - for (unsigned i=0; i N_out_data ( mygrid->getNbin() ); - std::vector out_ind ( mygrid->getDimension() ); - for(unsigned i=0; igetNumberOfPoints(); ++i){ - mygrid->getIndices( i, out_ind ); - if (real_output) { - double ft_value; - // Compute abs/norm and fix normalization - if (!store_norm) ft_value=std::abs( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); - else ft_value=std::norm( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); - // Set the value - mygrid->setGridElement( i, 0, ft_value ); - } else { - double ft_value_real, ft_value_imag; - ft_value_real=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].real() / norm; - ft_value_imag=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].imag() / norm; - // Set values - mygrid->setGridElement( i, 0, ft_value_real); - mygrid->setGridElement( i, 1, ft_value_imag); - } + // Get the size of the input data arrays (to allocate FFT data) + std::vector N_input_data( ingrid->getNbin() ); + size_t fft_dimension=1; for(unsigned i=0; i( N_input_data[i] ); + + // FFT arrays + std::vector > input_data(fft_dimension), fft_data(fft_dimension); + + + // Fill real input with the data on the grid + std::vector ind( ingrid->getDimension() ); + for (unsigned i=0; igetNumberOfPoints(); ++i) { + // Get point indices + ingrid->getIndices(i, ind); + // Fill input data in row-major order + input_data[ind[0]*N_input_data[0]+ind[1]].real( getFunctionValue( i ) ); + input_data[ind[0]*N_input_data[0]+ind[1]].imag( 0.0 ); + } + + // *** HERE is the only clear limitation: I'm computing explicitly a 2D FT. It should not happen to deal with other than two-dimensional grid ... + fftw_plan plan_complex = fftw_plan_dft_2d(N_input_data[0], N_input_data[1], reinterpret_cast(&input_data[0]), reinterpret_cast(&fft_data[0]), fourier_params[1], FFTW_ESTIMATE); + + // Compute FT + fftw_execute( plan_complex ); + + // Compute the normalization constant + double norm=1.0; + for (unsigned i=0; i N_out_data ( mygrid->getNbin() ); + std::vector out_ind ( mygrid->getDimension() ); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + mygrid->getIndices( i, out_ind ); + if (real_output) { + double ft_value; + // Compute abs/norm and fix normalization + if (!store_norm) ft_value=std::abs( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); + else ft_value=std::norm( fft_data[out_ind[0]*N_out_data[0]+out_ind[1]] / norm ); + // Set the value + mygrid->setGridElement( i, 0, ft_value ); + } else { + double ft_value_real, ft_value_imag; + ft_value_real=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].real() / norm; + ft_value_imag=fft_data[out_ind[0]*N_out_data[0]+out_ind[1]].imag() / norm; + // Set values + mygrid->setGridElement( i, 0, ft_value_real); + mygrid->setGridElement( i, 1, ft_value_imag); } - - // Free FFTW stuff - fftw_destroy_plan(plan_complex); - + } + + // Free FFTW stuff + fftw_destroy_plan(plan_complex); + } #endif diff --git a/src/gridtools/GridPrintingBase.cpp b/src/gridtools/GridPrintingBase.cpp index 90bf949735..616284d459 100644 --- a/src/gridtools/GridPrintingBase.cpp +++ b/src/gridtools/GridPrintingBase.cpp @@ -27,42 +27,42 @@ namespace PLMD { namespace gridtools { -void GridPrintingBase::registerKeywords( Keywords& keys ){ +void GridPrintingBase::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); keys.add("compulsory","GRID","the action that creates the grid you would like to output"); keys.add("compulsory","STRIDE","0","the frequency with which the grid should be output to the file. The default " - "value of 0 ensures that the grid is only output at the end of the trajectory"); + "value of 0 ensures that the grid is only output at the end of the trajectory"); keys.add("compulsory","FILE","density","the file on which to write the grid."); keys.add("optional","FMT","the format that should be used to output real numbers"); } GridPrintingBase::GridPrintingBase(const ActionOptions&ao): -Action(ao), -ActionPilot(ao), -fmt("%f") + Action(ao), + ActionPilot(ao), + fmt("%f") { std::string mlab; parse("GRID",mlab); vesselbase::ActionWithVessel* mves= plumed.getActionSet().selectWithLabel(mlab); if(!mves) error("action labelled " + mlab + " does not exist or does not have vessels"); addDependency(mves); - for(unsigned i=0;igetNumberOfVessels();++i){ - ingrid=dynamic_cast( mves->getPntrToVessel(i) ); - if( ingrid ) break; + for(unsigned i=0; igetNumberOfVessels(); ++i) { + ingrid=dynamic_cast( mves->getPntrToVessel(i) ); + if( ingrid ) break; } if( !ingrid ) error("input action does not calculate a grid"); - parse("FILE",filename); + parse("FILE",filename); if(filename.length()==0) error("name out output file was not specified"); log.printf(" outputting grid calculated by action %s to file named %s",mves->getLabel().c_str(), filename.c_str() ); - if( keywords.exists("FMT") ){ - parse("FMT",fmt); log.printf(" with format %s \n", fmt.c_str() ); + if( keywords.exists("FMT") ) { + parse("FMT",fmt); log.printf(" with format %s \n", fmt.c_str() ); } else { - log.printf("\n"); + log.printf("\n"); } } -void GridPrintingBase::update(){ +void GridPrintingBase::update() { if( getStep()==0 || getStride()==0 ) return ; OFile ofile; ofile.link(*this); @@ -70,7 +70,7 @@ void GridPrintingBase::update(){ ofile.open( filename ); printGrid( ofile ); ofile.close(); } -void GridPrintingBase::runFinalJobs(){ +void GridPrintingBase::runFinalJobs() { if( getStride()>0 ) return; OFile ofile; ofile.link(*this); diff --git a/src/gridtools/GridPrintingBase.h b/src/gridtools/GridPrintingBase.h index a9b79cd329..d33865d73b 100644 --- a/src/gridtools/GridPrintingBase.h +++ b/src/gridtools/GridPrintingBase.h @@ -36,8 +36,8 @@ class GridPrintingBase : public ActionPilot { public: static void registerKeywords( Keywords& keys ); explicit GridPrintingBase(const ActionOptions&ao); - void calculate(){} - void apply(){} + void calculate() {} + void apply() {} void update(); void runFinalJobs(); virtual void printGrid( OFile& ofile ) const=0; diff --git a/src/gridtools/GridToXYZ.cpp b/src/gridtools/GridToXYZ.cpp index 214e33903d..75e508a3f2 100644 --- a/src/gridtools/GridToXYZ.cpp +++ b/src/gridtools/GridToXYZ.cpp @@ -43,13 +43,13 @@ class GridToXYZ : public GridPrintingBase { unsigned mycomp; public: static void registerKeywords( Keywords& keys ); - explicit GridToXYZ(const ActionOptions&ao); + explicit GridToXYZ(const ActionOptions&ao); void printGrid( OFile& ofile ) const ; }; PLUMED_REGISTER_ACTION(GridToXYZ,"GRID_TO_XYZ") -void GridToXYZ::registerKeywords( Keywords& keys ){ +void GridToXYZ::registerKeywords( Keywords& keys ) { GridPrintingBase::registerKeywords( keys ); keys.add("optional","COMPONENT","if your input is a vector field use this to specifiy the component of the input vector field for which you wish to output"); keys.add("compulsory","UNITS","PLUMED","the units in which to print out the coordinates. PLUMED means internal PLUMED units"); @@ -58,32 +58,32 @@ void GridToXYZ::registerKeywords( Keywords& keys ){ } GridToXYZ::GridToXYZ(const ActionOptions&ao): -Action(ao), -GridPrintingBase(ao) + Action(ao), + GridPrintingBase(ao) { if( ingrid->getDimension()!=3 ) error("cannot print grid xyz file if grid does not contain three dimensional data"); - fmt = " " + fmt; + fmt = " " + fmt; - if( ingrid->getNumberOfComponents()==1 ){ - mycomp=0; + if( ingrid->getNumberOfComponents()==1 ) { + mycomp=0; } else { - int tcomp=-1; parse("COMPONENT",tcomp); - if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); - mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; - log.printf(" using %dth component of grid \n",tcomp ); + int tcomp=-1; parse("COMPONENT",tcomp); + if( tcomp<0 ) error("component of vector field was not specified - use COMPONENT keyword"); + mycomp=tcomp*(1+ingrid->getDimension()); if( ingrid->noDerivatives() ) mycomp=tcomp; + log.printf(" using %dth component of grid \n",tcomp ); } fmt="%f"; std::string precision; parse("PRECISION",precision); - if(precision.length()>0){ - int p; Tools::convert(precision,p); - log<<" with precision "<0) { + int p; Tools::convert(precision,p); + log<<" with precision "< point( 3 ); double val; ofile.printf("%u\n",ingrid->getNumberOfPoints()); ofile.printf("Grid converted to xyz file \n"); - for(unsigned i=0;igetNumberOfPoints();++i){ - ingrid->getGridPointCoordinates( i, point ); - ofile.printf("X"); double val=ingrid->getGridElement( i, 0 ); - if( ingrid->getType()=="flat" ) val=1.0; - else val=ingrid->getGridElement( i, 0 ); - for(unsigned j=0;j<3;++j){ ofile.printf( (" " + fmt).c_str(), val*lenunit*point[j] ); } - ofile.printf("\n"); + for(unsigned i=0; igetNumberOfPoints(); ++i) { + ingrid->getGridPointCoordinates( i, point ); + ofile.printf("X"); double val=ingrid->getGridElement( i, 0 ); + if( ingrid->getType()=="flat" ) val=1.0; + else val=ingrid->getGridElement( i, 0 ); + for(unsigned j=0; j<3; ++j) { ofile.printf( (" " + fmt).c_str(), val*lenunit*point[j] ); } + ofile.printf("\n"); } } diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp index f09e3f21a8..5282667a4c 100644 --- a/src/gridtools/GridVessel.cpp +++ b/src/gridtools/GridVessel.cpp @@ -27,7 +27,7 @@ namespace PLMD { namespace gridtools { -void GridVessel::registerKeywords( Keywords& keys ){ +void GridVessel::registerKeywords( Keywords& keys ) { AveragingVessel::registerKeywords( keys ); keys.add("compulsory","TYPE","flat","how the grid points are being generated"); keys.add("compulsory","COMPONENTS","the names of the components in the vector"); @@ -36,12 +36,12 @@ void GridVessel::registerKeywords( Keywords& keys ){ } GridVessel::GridVessel( const vesselbase::VesselOptions& da ): -AveragingVessel(da), -bounds_set(false), -cube_units(1.0), -noderiv(false), -npoints(0), -wasforced(false) + AveragingVessel(da), + bounds_set(false), + cube_units(1.0), + noderiv(false), + npoints(0), + wasforced(false) { std::string geom; parse("TYPE",geom); if( geom=="flat" ) gtype=flat; @@ -49,102 +49,102 @@ wasforced(false) else plumed_merror( geom + " is invalid geometry type"); std::vector compnames; parseVector("COMPONENTS",compnames); std::vector coordnames; parseVector("COORDINATES",coordnames); - if( gtype==flat ){ - dimension=coordnames.size(); - str_min.resize( dimension); str_max.resize( dimension ); stride.resize( dimension ); - max.resize( dimension ); dx.resize( dimension ); nbin.resize( dimension ); min.resize( dimension ); - } else if( gtype==fibonacci ){ - if( coordnames.size()!=3 ) error("cannot generate fibonacci grid points on surface of sphere if not 3 input coordinates"); - dimension=3; + if( gtype==flat ) { + dimension=coordnames.size(); + str_min.resize( dimension); str_max.resize( dimension ); stride.resize( dimension ); + max.resize( dimension ); dx.resize( dimension ); nbin.resize( dimension ); min.resize( dimension ); + } else if( gtype==fibonacci ) { + if( coordnames.size()!=3 ) error("cannot generate fibonacci grid points on surface of sphere if not 3 input coordinates"); + dimension=3; } unsigned n=0; nper=compnames.size()*( 1 + coordnames.size() ); arg_names.resize( coordnames.size() + compnames.size()*( 1 + coordnames.size() ) ); - for(unsigned i=0;i spbc( dimension ); parseVector("PBC",spbc); - for(unsigned i=0;i tnames( dimension ), cnames(nper); - for(unsigned i=0;i& smin, const std::vector& smax, - const std::vector& binsin, const std::vector& spacing ){ + const std::vector& binsin, const std::vector& spacing ) { plumed_dbg_assert( smin.size()==dimension && smax.size()==dimension ); plumed_assert( gtype==flat && (spacing.size()==dimension || binsin.size()==dimension) ); npoints=1; bounds_set=true; - for(unsigned i=0;iepsilon ) spc += 1; - if( spc>binsin[i] ) nbin[i]=spc; else nbin[i]=binsin[i]; - } else if( binsin.size()==dimension ) nbin[i]=binsin[i]; - else if( spacing.size()==dimension ) nbin[i] = std::floor(( max[i] - min[i] ) / spacing[i]) + 1; - else plumed_error(); - dx[i] = ( max[i] - min[i] ) / static_cast( nbin[i] ); - if( !pbc[i] ){ max[i] +=dx[i]; nbin[i]+=1; } - stride[i]=npoints; - npoints*=nbin[i]; + for(unsigned i=0; iepsilon ) spc += 1; + if( spc>binsin[i] ) nbin[i]=spc; else nbin[i]=binsin[i]; + } else if( binsin.size()==dimension ) nbin[i]=binsin[i]; + else if( spacing.size()==dimension ) nbin[i] = std::floor(( max[i] - min[i] ) / spacing[i]) + 1; + else plumed_error(); + dx[i] = ( max[i] - min[i] ) / static_cast( nbin[i] ); + if( !pbc[i] ) { max[i] +=dx[i]; nbin[i]+=1; } + stride[i]=npoints; + npoints*=nbin[i]; } - resize(); // Always resize after setting new bounds as grid size may have have changed -} + resize(); // Always resize after setting new bounds as grid size may have have changed +} -void GridVessel::setupFibonacciGrid( const unsigned& np ){ +void GridVessel::setupFibonacciGrid( const unsigned& np ) { bounds_set=true; npoints = np; fib_increment = pi*( 3 - sqrt(5) ); - fib_offset = 2 / static_cast( npoints ); + fib_offset = 2 / static_cast( npoints ); Random random; fib_rnd = std::floor( npoints*random.RandU01() ); resize(); } -std::string GridVessel::description(){ +std::string GridVessel::description() { if( !bounds_set ) return ""; - + std::string des; - if( gtype==flat ){ - des="grid of "; std::string num; - for(unsigned i=0;i0, "Number of datapoints at each grid point has not been set"); - resizeBuffer( getNumberOfBufferPoints()*nper + 1 + 2*getAction()->getNumberOfDerivatives() ); + resizeBuffer( getNumberOfBufferPoints()*nper + 1 + 2*getAction()->getNumberOfDerivatives() ); setDataSize( npoints*nper ); forces.resize( npoints ); if( active.size()!=npoints) active.resize( npoints, true ); } @@ -153,18 +153,18 @@ unsigned GridVessel::getIndex( const std::vector& indices ) const { plumed_dbg_assert( gtype==flat && bounds_set && indices.size()==dimension ); // indices are flattended using a column-major order unsigned index=indices[dimension-1]; - for(unsigned i=dimension-1;i>0;--i){ + for(unsigned i=dimension-1; i>0; --i) { index=index*nbin[i-1]+indices[i-1]; - } + } return index; } -void GridVessel::getIndices( const std::vector& point, std::vector& indices ) const { +void GridVessel::getIndices( const std::vector& point, std::vector& indices ) const { plumed_dbg_assert( gtype==flat && bounds_set && point.size()==dimension && indices.size()==dimension ); - for(unsigned i=0;inbin[i] ) plumed_merror("point is outside grid range"); + for(unsigned i=0; inbin[i] ) plumed_merror("point is outside grid range"); } } @@ -175,37 +175,37 @@ unsigned GridVessel::getIndex( const std::vector& point ) const { } void GridVessel::convertIndexToIndices( const unsigned& index, const std::vector& nnbin, std::vector& indices ) const { - plumed_dbg_assert( gtype==flat ); unsigned kk=index; indices[0]=index%nnbin[0]; - for(unsigned i=1;i=2){ // I think this is wrong + } + if(dimension>=2) { // I think this is wrong indices[dimension-1]=(kk-indices[dimension-2])/nnbin[dimension-2]; - } + } } void GridVessel::getIndices( const unsigned& index, std::vector& indices ) const { - plumed_dbg_assert( gtype==flat ); convertIndexToIndices( index, nbin, indices ); + plumed_dbg_assert( gtype==flat ); convertIndexToIndices( index, nbin, indices ); } -void GridVessel::getGridPointCoordinates( const unsigned& ipoint , std::vector& x ) const { +void GridVessel::getGridPointCoordinates( const unsigned& ipoint, std::vector& x ) const { plumed_dbg_assert( bounds_set && x.size()==dimension && ipoint tindices( dimension ); getIndices( ipoint, tindices ); - for(unsigned i=0;i tindices( dimension ); getIndices( ipoint, tindices ); + for(unsigned i=0; i tmp_indices( dimension ); std::vector my_indices( dimension ); getIndices( mybox, my_indices ); - for(unsigned i=0;ierror("Extrapolating function on grid"); - if( pbc[j] && i0==nbin[j]) i0=0; - tmp_indices[j]=i0; - } - mysneigh[i]=getIndex( tmp_indices ); - plumed_massert( active[mysneigh[i]], "inactive grid point required for splines"); + for(unsigned i=0; ierror("Extrapolating function on grid"); + if( pbc[j] && i0==nbin[j]) i0=0; + tmp_indices[j]=i0; + } + mysneigh[i]=getIndex( tmp_indices ); + plumed_massert( active[mysneigh[i]], "inactive grid point required for splines"); } } @@ -233,22 +233,22 @@ double GridVessel::getGridElement( const unsigned& ipoint, const unsigned& jelem return getDataElement( nper*ipoint + jelement ); } -void GridVessel::setGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ){ +void GridVessel::setGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ) { plumed_dbg_assert( bounds_set && ipoint& buffer, std::vector& der_list ) const { plumed_dbg_assert( myvals.getNumberOfValues()==(nper+1) ); - for(unsigned i=0;i& buffer ){ +void GridVessel::finish( const std::vector& buffer ) { if( wasforced ) getFinalForces( buffer, finalForces ); else AveragingVessel::finish( buffer ); } @@ -257,14 +257,14 @@ double GridVessel::getGridElement( const std::vector& indices, const u return getGridElement( getIndex( indices ), jelement ); } -void GridVessel::setGridElement( const std::vector& indices, const unsigned& jelement, const double& value ){ +void GridVessel::setGridElement( const std::vector& indices, const unsigned& jelement, const double& value ) { setGridElement( getIndex( indices ), jelement, value ); } std::vector GridVessel::getMin() const { plumed_dbg_assert( gtype==flat ); return str_min; } - + std::vector GridVessel::getMax() const { plumed_dbg_assert( gtype==flat ); return str_max; } @@ -272,9 +272,9 @@ std::vector GridVessel::getMax() const { std::vector GridVessel::getNbin() const { plumed_dbg_assert( gtype==flat && bounds_set ); std::vector ngrid( dimension ); - for(unsigned i=0;i& pp, const std::vector< plumed_dbg_assert( gtype==flat && bounds_set && nneigh.size()==dimension ); std::vector indices( dimension ); - for(unsigned i=0;i& indices, const std::vector& nneigh, +void GridVessel::getNeighbors( const std::vector& indices, const std::vector& nneigh, unsigned& num_neighbors, std::vector& neighbors ) const { plumed_dbg_assert( gtype==flat && bounds_set && nneigh.size()==dimension ); unsigned num_neigh=1; std::vector small_bin( dimension ); - for(unsigned i=0;i s_indices(dimension), t_indices(dimension); - for(unsigned index=0;index=nbin[i]) found=false; - if( pbc[i] && i0<0) i0=nbin[i]-(-i0)%nbin[i]; - if( pbc[i] && i0>=nbin[i]) i0%=nbin[i]; - t_indices[i]=static_cast(i0); - } - if( found ){ - neighbors[num_neighbors]=getIndex( t_indices ); - num_neighbors++; - } + for(unsigned index=0; index=nbin[i]) found=false; + if( pbc[i] && i0<0) i0=nbin[i]-(-i0)%nbin[i]; + if( pbc[i] && i0>=nbin[i]) i0%=nbin[i]; + t_indices[i]=static_cast(i0); + } + if( found ) { + neighbors[num_neighbors]=getIndex( t_indices ); + num_neighbors++; + } } } -void GridVessel::setCubeUnits( const double& units ){ +void GridVessel::setCubeUnits( const double& units ) { plumed_dbg_assert( gtype==flat ); cube_units=units; } @@ -329,17 +329,17 @@ double GridVessel::getCubeUnits() const { std::string GridVessel::getInputString() const { std::string mstring="COORDINATES="+arg_names[0]; - for(unsigned i=1;i& x, const u std::vector xfloor(dimension); getGridPointCoordinates( getIndex(x), xfloor ); // loop over neighbors - for(unsigned int ipoint=0;ipoint& to_activate ){ +void GridVessel::activateThesePoints( const std::vector& to_activate ) { plumed_dbg_assert( to_activate.size()==npoints ); - for(unsigned i=0;i& inforces ){ +void GridVessel::setForce( const std::vector& inforces ) { plumed_dbg_assert( inforces.size()==npoints ); - wasforced=true; for(unsigned i=0;i& fforces ){ - plumed_dbg_assert( fforces.size()==finalForces.size() ); +bool GridVessel::applyForce( std::vector& fforces ) { + plumed_dbg_assert( fforces.size()==finalForces.size() ); if( !wasforced ) return false; - for(unsigned i=0;i min, max; + std::vector min, max; /// The numerical distance between adjacent grid points - std::vector stride; + std::vector stride; /// The number of bins in each grid direction - std::vector nbin; + std::vector nbin; /// The grid point that was requested last by getGridPointCoordinates - unsigned currentGridPoint; + unsigned currentGridPoint; /// The forces that will be output at the end of the calculation - std::vector finalForces; + std::vector finalForces; protected: /// Is forced - bool wasforced; + bool wasforced; /// Forces acting on grid elements - std::vector forces; + std::vector forces; /// Do we have derivatives - bool noderiv; + bool noderiv; /// The names of the various columns in the grid file - std::vector arg_names; -/// The number of pieces of information we are storing for each + std::vector arg_names; +/// The number of pieces of information we are storing for each /// point in the grid - unsigned nper; + unsigned nper; /// Is this direction periodic - std::vector pbc; -/// The minimum and maximum in the grid stored as strings - std::vector str_min, str_max; + std::vector pbc; +/// The minimum and maximum in the grid stored as strings + std::vector str_min, str_max; /// The spacing between grid points - std::vector dx; + std::vector dx; /// The dimensionality of the grid - unsigned dimension; + unsigned dimension; /// Which grid points are we actively accumulating - std::vector active; + std::vector active; /// Convert a point in space the the correspoinding grid point - unsigned getIndex( const std::vector& p ) const ; + unsigned getIndex( const std::vector& p ) const ; public: /// keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Constructor - explicit GridVessel( const vesselbase::VesselOptions& ); -/// Remove the derivatives - void setNoDerivatives(); + explicit GridVessel( const vesselbase::VesselOptions& ); +/// Remove the derivatives + void setNoDerivatives(); /// Get the type of grid we are using - std::string getType() const ; + std::string getType() const ; /// Set the minimum and maximum of the grid - virtual void setBounds( const std::vector& smin, const std::vector& smax, const std::vector& nbins, const std::vector& spacing ); + virtual void setBounds( const std::vector& smin, const std::vector& smax, const std::vector& nbins, const std::vector& spacing ); /// Setup the grid if it is a fibonacci grid on the surface of a sphere - void setupFibonacciGrid( const unsigned& np ); + void setupFibonacciGrid( const unsigned& np ); /// Get a description of the grid to output to the log - std::string description(); + std::string description(); /// Convert an index into indices - void convertIndexToIndices( const unsigned& index, const std::vector& nnbin, std::vector& indices ) const ; + void convertIndexToIndices( const unsigned& index, const std::vector& nnbin, std::vector& indices ) const ; /// Flatten the grid and get the grid index for a point - unsigned getIndex( const std::vector& indices ) const ; + unsigned getIndex( const std::vector& indices ) const ; /// Get the indices fof a point - void getIndices( const unsigned& index, std::vector& indices ) const ; + void getIndices( const unsigned& index, std::vector& indices ) const ; /// Get the indices of a particular point - void getIndices( const std::vector& point, std::vector& indices ) const ; + void getIndices( const std::vector& point, std::vector& indices ) const ; /// Operations on one of the elements of grid point i - void setGridElement( const unsigned&, const unsigned&, const double& ); + void setGridElement( const unsigned&, const unsigned&, const double& ); /// Add data to an element of the grid - void addToGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ); + void addToGridElement( const unsigned& ipoint, const unsigned& jelement, const double& value ); /// Operations on one of the elements of grid point specified by vector - double getGridElement( const std::vector&, const unsigned& ) const ; - void setGridElement( const std::vector&, const unsigned&, const double& ); + double getGridElement( const std::vector&, const unsigned& ) const ; + void setGridElement( const std::vector&, const unsigned&, const double& ); /// Set the size of the buffer equal to nper*npoints - virtual void resize(); + virtual void resize(); /// Get the number of points in the grid - unsigned getNumberOfPoints() const; + unsigned getNumberOfPoints() const; /// Get the coordinates for a point in the grid - void getGridPointCoordinates( const unsigned& , std::vector& ) const ; + void getGridPointCoordinates( const unsigned&, std::vector& ) const ; /// Get the dimensionality of the function - unsigned getDimension() const ; + unsigned getDimension() const ; /// Get the number of components in the vector stored on each grid point - virtual unsigned getNumberOfComponents() const ; + virtual unsigned getNumberOfComponents() const ; /// Is the grid periodic in the ith direction - bool isPeriodic( const unsigned& i ) const ; + bool isPeriodic( const unsigned& i ) const ; /// Get the number of quantities we have stored at each grid point - unsigned getNumberOfQuantities() const ; + unsigned getNumberOfQuantities() const ; /// Get the number of grid points for each dimension - std::vector getNbin() const ; + std::vector getNbin() const ; /// Get the name of the ith component - std::string getComponentName( const unsigned& i ) const ; + std::string getComponentName( const unsigned& i ) const ; /// Get the vector containing the minimum value of the grid in each dimension - std::vector getMin() const ; + std::vector getMin() const ; /// Get the vector containing the maximum value of the grid in each dimension - std::vector getMax() const ; + std::vector getMax() const ; /// Get the number of points needed in the buffer - virtual unsigned getNumberOfBufferPoints() const ; + virtual unsigned getNumberOfBufferPoints() const ; /// Get the stride (the distance between the grid points of an index) - const std::vector& getStride() const ; + const std::vector& getStride() const ; /// Return the volume of one of the grid cells - double getCellVolume() const ; -/// Get the value of the ith grid element - virtual double getGridElement( const unsigned&, const unsigned& ) const ; + double getCellVolume() const ; +/// Get the value of the ith grid element + virtual double getGridElement( const unsigned&, const unsigned& ) const ; /// Get the set of points neighouring a particular location in space - void getNeighbors( const std::vector& pp, const std::vector& nneigh, - unsigned& num_neighbours, std::vector& neighbors ) const ; + void getNeighbors( const std::vector& pp, const std::vector& nneigh, + unsigned& num_neighbours, std::vector& neighbors ) const ; /// Get the neighbors for a set of indices of a point - void getNeighbors( const std::vector& indices, const std::vector& nneigh, - unsigned& num_neighbors, std::vector& neighbors ) const ; + void getNeighbors( const std::vector& indices, const std::vector& nneigh, + unsigned& num_neighbors, std::vector& neighbors ) const ; /// Get the points neighboring a particular spline point - void getSplineNeighbors( const unsigned& mybox, std::vector& mysneigh ) const ; + void getSplineNeighbors( const unsigned& mybox, std::vector& mysneigh ) const ; /// Get the spacing between grid points - const std::vector& getGridSpacing() const ; + const std::vector& getGridSpacing() const ; /// Get the extent of the grid in one of the axis - double getGridExtent( const unsigned& i ) const ; + double getGridExtent( const unsigned& i ) const ; /// Copy data from the action into the grid - virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; + virtual void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const ; /// Finish the calculation - virtual void finish( const std::vector& buffer ); + virtual void finish( const std::vector& buffer ); /// This ensures that Gaussian cube fies are in correct units - void setCubeUnits( const double& units ); + void setCubeUnits( const double& units ); /// This ensures that Gaussian cube files are in correct units - double getCubeUnits() const ; + double getCubeUnits() const ; /// Return a string containing the input to the grid so we can clone it - std::string getInputString() const ; + std::string getInputString() const ; /// Does this have derivatives - bool noDerivatives() const ; + bool noDerivatives() const ; /// Get the value and derivatives at a particular location using spline interpolation - double getValueAndDerivatives( const std::vector& x, const unsigned& ind, std::vector& der ) const ; + double getValueAndDerivatives( const std::vector& x, const unsigned& ind, std::vector& der ) const ; /// Deactivate all the grid points - void activateThesePoints( const std::vector& to_activate ); + void activateThesePoints( const std::vector& to_activate ); /// Is this point active - bool inactive( const unsigned& ip ) const ; + bool inactive( const unsigned& ip ) const ; /// This retrieves the final force - virtual void getFinalForces( const std::vector& buffer, std::vector& finalForces ){ plumed_error(); } + virtual void getFinalForces( const std::vector& buffer, std::vector& finalForces ) { plumed_error(); } /// Apply the forces - void setForce( const std::vector& inforces ); + void setForce( const std::vector& inforces ); /// Was a force added to the grid - bool wasForced() const ; + bool wasForced() const ; /// And retrieve the forces - bool applyForce( std::vector& fforces ); + bool applyForce( std::vector& fforces ); }; inline @@ -200,11 +200,11 @@ const std::vector& GridVessel::getGridSpacing() const { inline double GridVessel::getCellVolume() const { - if( gtype==flat ){ - double myvol=1.0; for(unsigned i=0;i( getNumberOfPoints() ); + return 4*pi / static_cast( getNumberOfPoints() ); } } diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index 6fac76cd56..43fe891c27 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace gridtools { -void HistogramOnGrid::registerKeywords( Keywords& keys ){ +void HistogramOnGrid::registerKeywords( Keywords& keys ) { GridVessel::registerKeywords( keys ); keys.add("compulsory","KERNEL","the type of kernel to use"); keys.add("compulsory","BANDWIDTH","the bandwidths"); @@ -33,23 +33,23 @@ void HistogramOnGrid::registerKeywords( Keywords& keys ){ } HistogramOnGrid::HistogramOnGrid( const vesselbase::VesselOptions& da ): -GridVessel(da), -neigh_tot(0), -addOneKernelAtATime(false), -bandwidths(dimension), -discrete(false) + GridVessel(da), + neigh_tot(0), + addOneKernelAtATime(false), + bandwidths(dimension), + discrete(false) { - if( getType()=="flat" ){ - parse("KERNEL",kerneltype); - if( kerneltype=="discrete" || kerneltype=="DISCRETE" ){ - discrete=true; setNoDerivatives(); - } else { - parseVector("BANDWIDTH",bandwidths); - } + if( getType()=="flat" ) { + parse("KERNEL",kerneltype); + if( kerneltype=="discrete" || kerneltype=="DISCRETE" ) { + discrete=true; setNoDerivatives(); + } else { + parseVector("BANDWIDTH",bandwidths); + } } else { - parse("CONCENTRATION",von_misses_concentration); - von_misses_norm = von_misses_concentration / ( 4*pi*sinh( von_misses_concentration ) ); - } + parse("CONCENTRATION",von_misses_concentration); + von_misses_norm = von_misses_concentration / ( 4*pi*sinh( von_misses_concentration ) ); + } } bool HistogramOnGrid::noDiscreteKernels() const { @@ -57,151 +57,151 @@ bool HistogramOnGrid::noDiscreteKernels() const { } void HistogramOnGrid::setBounds( const std::vector& smin, const std::vector& smax, - const std::vector& nbins, const std::vector& spacing ){ + const std::vector& nbins, const std::vector& spacing ) { GridVessel::setBounds( smin, smax, nbins, spacing ); - if( !discrete ){ - std::vector point(dimension,0); - KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true ); neigh_tot=1; - nneigh=kernel.getSupport( dx ); std::vector support( kernel.getContinuousSupport() ); - for(unsigned i=0;igetGridExtent(i) ) error("bandwidth is too large for periodic grid"); - neigh_tot *= (2*nneigh[i]+1); - } - } + if( !discrete ) { + std::vector point(dimension,0); + KernelFunctions kernel( point, bandwidths, kerneltype, false, 1.0, true ); neigh_tot=1; + nneigh=kernel.getSupport( dx ); std::vector support( kernel.getContinuousSupport() ); + for(unsigned i=0; igetGridExtent(i) ) error("bandwidth is too large for periodic grid"); + neigh_tot *= (2*nneigh[i]+1); + } + } } KernelFunctions* HistogramOnGrid::getKernelAndNeighbors( std::vector& point, unsigned& num_neigh, std::vector& neighbors ) const { - if( discrete ){ - plumed_assert( getType()=="flat" ); - num_neigh=1; for(unsigned i=0;igetCenter(), nneigh, num_neigh, neighbors ); - return kernel; + if( discrete ) { + plumed_assert( getType()=="flat" ); + num_neigh=1; for(unsigned i=0; igetCenter(), nneigh, num_neigh, neighbors ); + return kernel; } else { - num_neigh = getNumberOfPoints(); - if( neighbors.size()!=getNumberOfPoints() ) neighbors.resize( getNumberOfPoints() ); - for(unsigned i=0;i HistogramOnGrid::getVectorOfValues() const { std::vector vv; - for(unsigned i=0;isetDomain( str_min[i], str_max[i] ); - else vv[i]->setNotPeriodic(); + for(unsigned i=0; isetDomain( str_min[i], str_max[i] ); + else vv[i]->setNotPeriodic(); } return vv; } void HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { - if( addOneKernelAtATime ){ - plumed_dbg_assert( myvals.getNumberOfValues()==2 && !wasforced ); - std::vector der( dimension ); - for(unsigned i=0;igetPositionInCurrentTaskList(current), myvals.get(0), myvals.get(1), der, buffer ); + if( addOneKernelAtATime ) { + plumed_dbg_assert( myvals.getNumberOfValues()==2 && !wasforced ); + std::vector der( dimension ); + for(unsigned i=0; igetPositionInCurrentTaskList(current), myvals.get(0), myvals.get(1), der, buffer ); } else { - plumed_dbg_assert( myvals.getNumberOfValues()==dimension+2 ); - std::vector point( dimension ); double weight=myvals.get(0)*myvals.get( 1+dimension ); - for(unsigned i=0;i neighbors; - std::vector der( dimension ); - KernelFunctions* kernel=getKernelAndNeighbors( point, num_neigh, neighbors ); - - if( !kernel && getType()=="flat" ){ - plumed_dbg_assert( num_neigh==1 ); der.resize(0); - accumulate( neighbors[0], weight, 1.0, der, buffer ); - } else { - double totwforce=0.0; - std::vector intforce( 2*dimension, 0.0 ); - std::vector vv( getVectorOfValues() ); - - double newval; std::vector xx( dimension ); - for(unsigned i=0;iset(xx[j]); - newval = kernel->evaluate( vv, der, true ); - } else { - // Evalulate dot product - double dot=0; for(unsigned j=0;jgetNumberOfDerivatives(); - unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); - for(unsigned j=0;j point( dimension ); double weight=myvals.get(0)*myvals.get( 1+dimension ); + for(unsigned i=0; i neighbors; + std::vector der( dimension ); + KernelFunctions* kernel=getKernelAndNeighbors( point, num_neigh, neighbors ); + + if( !kernel && getType()=="flat" ) { + plumed_dbg_assert( num_neigh==1 ); der.resize(0); + accumulate( neighbors[0], weight, 1.0, der, buffer ); + } else { + double totwforce=0.0; + std::vector intforce( 2*dimension, 0.0 ); + std::vector vv( getVectorOfValues() ); + + double newval; std::vector xx( dimension ); + for(unsigned i=0; iset(xx[j]); + newval = kernel->evaluate( vv, der, true ); + } else { + // Evalulate dot product + double dot=0; for(unsigned j=0; jgetNumberOfDerivatives(); + unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); + for(unsigned j=0; j& der, std::vector& buffer ) const { - buffer[bufstart+nper*ipoint] += weight*dens; - if( der.size()>0 ) for(unsigned j=0;j0 ) for(unsigned j=0; j& der, std::vector& intforce ) const { - for(unsigned j=0;j& buffer, std::vector& finalForces ){ +void HistogramOnGrid::getFinalForces( const std::vector& buffer, std::vector& finalForces ) { if( finalForces.size()!=getAction()->getNumberOfDerivatives() ) finalForces.resize( getAction()->getNumberOfDerivatives() ); // And the final force - unsigned nder = getAction()->getNumberOfDerivatives(); + unsigned nder = getAction()->getNumberOfDerivatives(); // Derivatives due to normalization unsigned gridbuf = getNumberOfBufferPoints()*getNumberOfQuantities(); - for(unsigned i=0;i& buffer ){ - if( addOneKernelAtATime ){ - for(unsigned i=0;igetCurrentNumberOfActiveTasks();++i){ - for(unsigned j=0;jgetActiveTask(i)+j, buffer[bufstart+i*nper+j] ); - } +void HistogramOnGrid::finish( const std::vector& buffer ) { + if( addOneKernelAtATime ) { + for(unsigned i=0; igetCurrentNumberOfActiveTasks(); ++i) { + for(unsigned j=0; jgetActiveTask(i)+j, buffer[bufstart+i*nper+j] ); + } } else { - GridVessel::finish( buffer ); + GridVessel::finish( buffer ); } } diff --git a/src/gridtools/HistogramOnGrid.h b/src/gridtools/HistogramOnGrid.h index 5171a9f6cc..2eb9a253da 100644 --- a/src/gridtools/HistogramOnGrid.h +++ b/src/gridtools/HistogramOnGrid.h @@ -53,7 +53,7 @@ class HistogramOnGrid : public GridVessel { unsigned getNumberOfBufferPoints() const ; KernelFunctions* getKernelAndNeighbors( std::vector& point, unsigned& num_neigh, std::vector& neighbors ) const; std::vector getVectorOfValues() const ; - void addOneKernelEachTimeOnly(){ addOneKernelAtATime=true; } + void addOneKernelEachTimeOnly() { addOneKernelAtATime=true; } virtual void getFinalForces( const std::vector& buffer, std::vector& finalForces ); bool noDiscreteKernels() const ; }; diff --git a/src/gridtools/IntegrateGrid.cpp b/src/gridtools/IntegrateGrid.cpp index 02f59826ad..fc966a46d1 100644 --- a/src/gridtools/IntegrateGrid.cpp +++ b/src/gridtools/IntegrateGrid.cpp @@ -43,13 +43,13 @@ class IntegrateGrid : public ActionWithIntegral { PLUMED_REGISTER_ACTION(IntegrateGrid,"INTEGRATE_GRID") -void IntegrateGrid::registerKeywords( Keywords& keys ){ +void IntegrateGrid::registerKeywords( Keywords& keys ) { ActionWithIntegral::registerKeywords( keys ); } IntegrateGrid::IntegrateGrid(const ActionOptions&ao): -Action(ao), -ActionWithIntegral(ao) + Action(ao), + ActionWithIntegral(ao) { } diff --git a/src/gridtools/InterpolateGrid.cpp b/src/gridtools/InterpolateGrid.cpp index f35f10de8c..e8f97c0d4a 100644 --- a/src/gridtools/InterpolateGrid.cpp +++ b/src/gridtools/InterpolateGrid.cpp @@ -28,20 +28,20 @@ /* Interpolate a smooth function stored on a grid onto a grid with a smaller grid spacing. -This action takes a function evaluated on a grid as input and can be used to interpolate the values of that +This action takes a function evaluated on a grid as input and can be used to interpolate the values of that function on to a finer grained grid. The interpolation within this algorithm is done using splines. \par Examples -The input below can be used to postprocess a trajectory. It calculates a \ref HISTOGRAM as a function the +The input below can be used to postprocess a trajectory. It calculates a \ref HISTOGRAM as a function the distance between atoms 1 and 2 using kernel density estimation. During the calculation the values of the kernels -are evaluated at 100 points on a uniform grid between 0.0 and 3.0. Prior to outputting this function at the end of the -simulation this function is interpolated onto a finer grid of 200 points between 0.0 and 3.0. +are evaluated at 100 points on a uniform grid between 0.0 and 3.0. Prior to outputting this function at the end of the +simulation this function is interpolated onto a finer grid of 200 points between 0.0 and 3.0. \verbatim x: DISTANCE ATOMS=1,2 -hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 -ii: INTERPOLATE_GRID GRID=hA1 GRID_BIN=200 +hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 +ii: INTERPOLATE_GRID GRID=hA1 GRID_BIN=200 DUMPGRID GRID=ii FILE=histo.dat \endverbatim @@ -57,42 +57,42 @@ class InterpolateGrid : public ActionWithInputGrid { explicit InterpolateGrid(const ActionOptions&ao); unsigned getNumberOfQuantities() const ; void compute( const unsigned& current, MultiValue& myvals ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(InterpolateGrid,"INTERPOLATE_GRID") -void InterpolateGrid::registerKeywords( Keywords& keys ){ +void InterpolateGrid::registerKeywords( Keywords& keys ) { ActionWithInputGrid::registerKeywords( keys ); keys.add("optional","GRID_BIN","the number of bins for the grid"); keys.add("optional","GRID_SPACING","the approximate grid spacing (to be used as an alternative or together with GRID_BIN)"); - keys.remove("KERNEL"); keys.remove("BANDWIDTH"); + keys.remove("KERNEL"); keys.remove("BANDWIDTH"); } InterpolateGrid::InterpolateGrid(const ActionOptions&ao): -Action(ao), -ActionWithInputGrid(ao) + Action(ao), + ActionWithInputGrid(ao) { plumed_assert( ingrid->getNumberOfComponents()==1 ); - if( ingrid->noDerivatives() ) error("cannot interpolate a grid that does not have derivatives"); + if( ingrid->noDerivatives() ) error("cannot interpolate a grid that does not have derivatives"); // Create the input from the old string createGrid( "grid", "COMPONENTS=" + getLabel() + " " + ingrid->getInputString() ); - std::vector nbin; parseVector("GRID_BIN",nbin); + std::vector nbin; parseVector("GRID_BIN",nbin); std::vector gspacing; parseVector("GRID_SPACING",gspacing); - if( nbin.size()!=ingrid->getDimension() && gspacing.size()!=ingrid->getDimension() ){ - error("GRID_BIN or GRID_SPACING must be set"); - } + if( nbin.size()!=ingrid->getDimension() && gspacing.size()!=ingrid->getDimension() ) { + error("GRID_BIN or GRID_SPACING must be set"); + } // Need this for creation of tasks - mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), nbin, gspacing ); + mygrid->setBounds( ingrid->getMin(), ingrid->getMax(), nbin, gspacing ); setAveragingAction( mygrid, true ); // Now create task list - for(unsigned i=0;igetNumberOfPoints();++i) addTaskToList(i); + for(unsigned i=0; igetNumberOfPoints(); ++i) addTaskToList(i); // And activate all tasks - deactivateAllTasks(); - for(unsigned i=0;igetNumberOfPoints();++i) taskFlags[i]=1; + deactivateAllTasks(); + for(unsigned i=0; igetNumberOfPoints(); ++i) taskFlags[i]=1; lockContributors(); } @@ -103,8 +103,8 @@ unsigned InterpolateGrid::getNumberOfQuantities() const { void InterpolateGrid::compute( const unsigned& current, MultiValue& myvals ) const { std::vector pos( mygrid->getDimension() ); mygrid->getGridPointCoordinates( current, pos ); std::vector der( mygrid->getDimension() ); double val = getFunctionValueAndDerivatives( pos, der ); - myvals.setValue( 0, 1.0 ); myvals.setValue(1, val ); - for(unsigned i=0;igetDimension();++i) myvals.setValue( 2+i, der[i] ); + myvals.setValue( 0, 1.0 ); myvals.setValue(1, val ); + for(unsigned i=0; igetDimension(); ++i) myvals.setValue( 2+i, der[i] ); } } diff --git a/src/main/main.cpp b/src/main/main.cpp index 797ce80396..4e3d6376cd 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -32,10 +32,10 @@ using namespace std; This main uses only the interface published in Plumed.h. The object file generated from this .cpp is the only part of the plumed library that should - not be linked with external MD codes, so as + not be linked with external MD codes, so as to avoid linker error. */ -int main(int argc,char**argv){ +int main(int argc,char**argv) { #ifdef __PLUMED_HAS_MPI bool nompi=false; if(argc>1 && !strcmp(argv[1],"--no-mpi")) nompi=true; @@ -48,7 +48,7 @@ int main(int argc,char**argv){ p->cmd("CLTool setArgc",&argc); p->cmd("CLTool setArgv",argv); #ifdef __PLUMED_HAS_MPI - if(!nompi){ + if(!nompi) { MPI_Comm comm; MPI_Comm_dup(MPI_COMM_WORLD,&comm); p->cmd("CLTool setMPIComm",&comm); diff --git a/src/manyrestraints/LWalls.cpp b/src/manyrestraints/LWalls.cpp index 4075bacd8b..7c0ad569ec 100644 --- a/src/manyrestraints/LWalls.cpp +++ b/src/manyrestraints/LWalls.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace manyrestraints { -//+PLUMEDOC MCOLVARB LWALLS +//+PLUMEDOC MCOLVARB LWALLS /* Add \ref LOWER_WALLS restraints on all the multicolvar values @@ -36,20 +36,20 @@ keyword and places a restraint on each quantity, \f$x\f$, with the following fun k((x-a+o)/s)^e \f$ -\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and +\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and \f$e\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFF = 0. \par Examples The following set of commands can be used to stop any of the 800 atoms in group A from moving more than 2.46425 nm -in the z direction from atom 34137. This is done by adding a lower wall on the z-distance between all the atoms in -group A and the position of 34137. +in the z direction from atom 34137. This is done by adding a lower wall on the z-distance between all the atoms in +group A and the position of 34137. \verbatim l: ZDISTANCES GROUPA=1-800 GROUPB=34137 NOPBC LWALLS DATA=l AT=2.46465 KAPPA=150.0 EXP=2 EPS=1 OFFSET=0 LABEL=lwall \endverbatim - + */ //+ENDPLUMEDOC @@ -70,7 +70,7 @@ class LWalls : public ManyRestraintsBase { PLUMED_REGISTER_ACTION(LWalls,"LWALLS") -void LWalls::registerKeywords( Keywords& keys ){ +void LWalls::registerKeywords( Keywords& keys ) { ManyRestraintsBase::registerKeywords( keys ); keys.add("compulsory","AT","the radius of the sphere"); keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall."); @@ -80,8 +80,8 @@ void LWalls::registerKeywords( Keywords& keys ){ } LWalls::LWalls(const ActionOptions& ao): -Action(ao), -ManyRestraintsBase(ao) + Action(ao), + ManyRestraintsBase(ao) { parse("AT",at); parse("OFFSET",offset); @@ -91,13 +91,13 @@ ManyRestraintsBase(ao) checkRead(); } -double LWalls::calcPotential( const double& val, double& df ) const { +double LWalls::calcPotential( const double& val, double& df ) const { double uscale = (val - at + offset)/eps; - if( uscale < 0. ){ - double power = pow( uscale, exp ); - df = ( kappa / eps ) * exp * power / uscale; + if( uscale < 0. ) { + double power = pow( uscale, exp ); + df = ( kappa / eps ) * exp * power / uscale; - return kappa*power; + return kappa*power; } return 0.0; diff --git a/src/manyrestraints/ManyRestraintsBase.cpp b/src/manyrestraints/ManyRestraintsBase.cpp index 60dd82b2e5..d13d51cfac 100644 --- a/src/manyrestraints/ManyRestraintsBase.cpp +++ b/src/manyrestraints/ManyRestraintsBase.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace manyrestraints { -void ManyRestraintsBase::registerKeywords( Keywords& keys ){ +void ManyRestraintsBase::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionWithVessel::registerKeywords( keys ); @@ -37,11 +37,11 @@ void ManyRestraintsBase::registerKeywords( Keywords& keys ){ } ManyRestraintsBase::ManyRestraintsBase(const ActionOptions& ao): -Action(ao), -ActionWithValue(ao), -ActionPilot(ao), -ActionWithVessel(ao), -ActionWithInputVessel(ao) + Action(ao), + ActionWithValue(ao), + ActionPilot(ao), + ActionWithVessel(ao), + ActionWithInputVessel(ao) { // Read in the vessel we are action on readArgument("bridge"); @@ -49,44 +49,44 @@ ActionWithInputVessel(ao) plumed_assert( getDependencies().size()==1 && aves ); log.printf(" adding restraints on variables calculated by %s action with label %s\n", - aves->getName().c_str(),aves->getLabel().c_str()); + aves->getName().c_str(),aves->getLabel().c_str()); // Add a task list in order to avoid problems - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList( aves->getTaskCode(i) ); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList( aves->getTaskCode(i) ); // And turn on the derivatives (note problems here because of ActionWithValue) turnOnDerivatives(); needsDerivatives(); // Now create the vessel std::string fake_input="LABEL=bias"; - addVessel( "SUM", fake_input, 0 ); + addVessel( "SUM", fake_input, 0 ); readVesselKeywords(); } -void ManyRestraintsBase::doJobsRequiredBeforeTaskList(){ +void ManyRestraintsBase::doJobsRequiredBeforeTaskList() { ActionWithVessel::doJobsRequiredBeforeTaskList(); ActionWithValue::clearDerivatives(); } void ManyRestraintsBase::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const { outvals.setValue( 0, invals.get(0) ); - + // Get the potential double dval=0, val=calcPotential( invals.get(1), dval ); outvals.setValue( 1, val ); - for(unsigned i=0;iaddForce( -1.0*getStride() ); } diff --git a/src/manyrestraints/ManyRestraintsBase.h b/src/manyrestraints/ManyRestraintsBase.h index 9e1c3cae96..565ea340df 100644 --- a/src/manyrestraints/ManyRestraintsBase.h +++ b/src/manyrestraints/ManyRestraintsBase.h @@ -32,10 +32,10 @@ namespace PLMD { namespace manyrestraints { class ManyRestraintsBase : - public ActionWithValue, - public ActionPilot, - public vesselbase::ActionWithVessel, - public vesselbase::ActionWithInputVessel + public ActionWithValue, + public ActionPilot, + public vesselbase::ActionWithVessel, + public vesselbase::ActionWithInputVessel { private: /// Pointer to underlying action with vessel @@ -43,13 +43,13 @@ class ManyRestraintsBase : public: static void registerKeywords( Keywords& keys ); explicit ManyRestraintsBase(const ActionOptions&); - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } unsigned getNumberOfDerivatives(); /// Routines that have to be defined so as not to have problems with virtual methods - void deactivate_task( const unsigned & task_index ){}; -/// Don't actually clear the derivatives when this is called from plumed main. -/// They are calculated inside another action and clearing them would be bad - void clearDerivatives(){} + void deactivate_task( const unsigned & task_index ) {}; +/// Don't actually clear the derivatives when this is called from plumed main. +/// They are calculated inside another action and clearing them would be bad + void clearDerivatives() {} /// Do jobs required before tasks are undertaken void doJobsRequiredBeforeTaskList(); /// This actually does the calculation @@ -57,16 +57,16 @@ class ManyRestraintsBase : /// Calculate the potential virtual double calcPotential( const double& val, double& df ) const=0; // Calculate does nothing - void calculate(){}; + void calculate() {}; /// This should never be called - void performTask( const unsigned& , const unsigned& , MultiValue& ) const { plumed_error(); } + void performTask( const unsigned&, const unsigned&, MultiValue& ) const { plumed_error(); } /// Deactivate task now does nothing void apply(); - void applyBridgeForces( const std::vector& bb ){ plumed_assert( bb.size()==0 ); } + void applyBridgeForces( const std::vector& bb ) { plumed_assert( bb.size()==0 ); } }; inline -unsigned ManyRestraintsBase::getNumberOfDerivatives(){ +unsigned ManyRestraintsBase::getNumberOfDerivatives() { return aves->getNumberOfDerivatives(); } diff --git a/src/manyrestraints/UWalls.cpp b/src/manyrestraints/UWalls.cpp index 474eab490c..f4c75f0d89 100644 --- a/src/manyrestraints/UWalls.cpp +++ b/src/manyrestraints/UWalls.cpp @@ -25,7 +25,7 @@ namespace PLMD { namespace manyrestraints { -//+PLUMEDOC MCOLVARB UWALLS +//+PLUMEDOC MCOLVARB UWALLS /* Add \ref UPPER_WALLS restraints on all the multicolvar values @@ -36,14 +36,14 @@ keyword and places a restraint on each quantity, \f$x\f$, with the following fun k((x-a+o)/s)^e \f$ -\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and +\f$k\f$ (KAPPA) is an energy constant in internal unit of the code, \f$s\f$ (EPS) a rescaling factor and \f$e\f$ (EXP) the exponent determining the power law. By default: EXP = 2, EPS = 1.0, OFF = 0. \par Examples -The following set of commands can be used to stop a cluster composed of 20 atoms subliming. The position of -the centre of mass of the cluster is calculated by the \ref COM command labelled c1. The \ref DISTANCES -command labelled d1 is then used to calculate the distance between each of the 20 atoms in the cluster +The following set of commands can be used to stop a cluster composed of 20 atoms subliming. The position of +the centre of mass of the cluster is calculated by the \ref COM command labelled c1. The \ref DISTANCES +command labelled d1 is then used to calculate the distance between each of the 20 atoms in the cluster and the center of mass of the cluster. These distances are then passed to the UWALLS command, which adds a \ref UPPER_WALLS restraint on each of them and thereby prevents each of them from moving very far from the centre of mass of the cluster. @@ -53,7 +53,7 @@ COM ATOMS=1-20 LABEL=c1 DISTANCES GROUPA=c1 GROUPB=1-20 LABEL=d1 UWALLS DATA=d1 AT=2.5 KAPPA=0.2 LABEL=sr \endverbatim - + */ //+ENDPLUMEDOC @@ -74,7 +74,7 @@ class UWalls : public ManyRestraintsBase { PLUMED_REGISTER_ACTION(UWalls,"UWALLS") -void UWalls::registerKeywords( Keywords& keys ){ +void UWalls::registerKeywords( Keywords& keys ) { ManyRestraintsBase::registerKeywords( keys ); keys.add("compulsory","AT","the radius of the sphere"); keys.add("compulsory","KAPPA","the force constant for the wall. The k_i in the expression for a wall."); @@ -84,8 +84,8 @@ void UWalls::registerKeywords( Keywords& keys ){ } UWalls::UWalls(const ActionOptions& ao): -Action(ao), -ManyRestraintsBase(ao) + Action(ao), + ManyRestraintsBase(ao) { parse("AT",at); parse("OFFSET",offset); @@ -95,13 +95,13 @@ ManyRestraintsBase(ao) checkRead(); } -double UWalls::calcPotential( const double& val, double& df ) const { +double UWalls::calcPotential( const double& val, double& df ) const { double uscale = (val - at + offset)/eps; - if( uscale > 0. ){ - double power = pow( uscale, exp ); - df = ( kappa / eps ) * exp * power / uscale; + if( uscale > 0. ) { + double power = pow( uscale, exp ); + df = ( kappa / eps ) * exp * power / uscale; - return kappa*power; + return kappa*power; } return 0.0; diff --git a/src/mapping/Mapping.cpp b/src/mapping/Mapping.cpp index ac80b6bee0..c1a6dba33d 100644 --- a/src/mapping/Mapping.cpp +++ b/src/mapping/Mapping.cpp @@ -31,72 +31,72 @@ namespace PLMD { namespace mapping { -void Mapping::registerKeywords( Keywords& keys ){ - Action::registerKeywords( keys ); +void Mapping::registerKeywords( Keywords& keys ) { + Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); - ActionWithArguments::registerKeywords( keys ); - ActionAtomistic::registerKeywords( keys ); + ActionWithArguments::registerKeywords( keys ); + ActionAtomistic::registerKeywords( keys ); vesselbase::ActionWithVessel::registerKeywords( keys ); keys.add("compulsory","REFERENCE","a pdb file containing the set of reference configurations"); keys.add("compulsory","PROPERTY","the property to be used in the index. This should be in the REMARK of the reference"); keys.add("compulsory","TYPE","OPTIMAL-FAST","the manner in which distances are calculated. More information on the different " - "metrics that are available in PLUMED can be found in the section of the manual on " - "\\ref dists"); + "metrics that are available in PLUMED can be found in the section of the manual on " + "\\ref dists"); keys.addFlag("DISABLE_CHECKS",false,"disable checks on reference input structures."); } Mapping::Mapping(const ActionOptions&ao): -Action(ao), -ActionAtomistic(ao), -ActionWithArguments(ao), -ActionWithValue(ao), -ActionWithVessel(ao) + Action(ao), + ActionAtomistic(ao), + ActionWithArguments(ao), + ActionWithValue(ao), + ActionWithVessel(ao) { // Read the input std::string mtype; parse("TYPE",mtype); bool skipchecks; parseFlag("DISABLE_CHECKS",skipchecks); // Setup the object that does the mapping - mymap = new PointWiseMapping( mtype, skipchecks ); - + mymap = new PointWiseMapping( mtype, skipchecks ); + // Read the properties we require - if( keywords.exists("PROPERTY") ){ - std::vector property; - parseVector("PROPERTY",property); - if(property.size()==0) error("no properties were specified"); - mymap->setPropertyNames( property, false ); + if( keywords.exists("PROPERTY") ) { + std::vector property; + parseVector("PROPERTY",property); + if(property.size()==0) error("no properties were specified"); + mymap->setPropertyNames( property, false ); } else { - std::vector property(1); - property[0]="spath"; - mymap->setPropertyNames( property, true ); + std::vector property(1); + property[0]="spath"; + mymap->setPropertyNames( property, true ); } // Open reference file - std::string reference; parse("REFERENCE",reference); - FILE* fp=fopen(reference.c_str(),"r"); + std::string reference; parse("REFERENCE",reference); + FILE* fp=fopen(reference.c_str(),"r"); if(!fp) error("could not open reference file " + reference ); - // Read all reference configurations - bool do_read=true; std::vector weights; + // Read all reference configurations + bool do_read=true; std::vector weights; unsigned nfram=0, wnorm=0., ww; - while (do_read){ - PDB mypdb; - // Read the pdb file - do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); - // Fix argument names - expandArgKeywordInPDB( mypdb ); - if(do_read){ - mymap->readFrame( mypdb ); ww=mymap->getWeight( nfram ); - weights.push_back( ww ); - wnorm+=ww; nfram++; - } else { - break; - } + while (do_read) { + PDB mypdb; + // Read the pdb file + do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); + // Fix argument names + expandArgKeywordInPDB( mypdb ); + if(do_read) { + mymap->readFrame( mypdb ); ww=mymap->getWeight( nfram ); + weights.push_back( ww ); + wnorm+=ww; nfram++; + } else { + break; + } } - fclose(fp); + fclose(fp); if(nfram==0 ) error("no reference configurations were specified"); log.printf(" found %u configurations in file %s\n",nfram,reference.c_str() ); - for(unsigned i=0;isetWeights( weights ); // Finish the setup of the mapping object @@ -106,49 +106,49 @@ ActionWithVessel(ao) requestAtoms( atoms ); std::vector req_args; interpretArgumentList( args, req_args ); requestArguments( req_args ); // Duplicate all frames (duplicates are used by sketch-map) - // mymap->duplicateFrameList(); + // mymap->duplicateFrameList(); // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); // plumed_assert( !mymap->mappingNeedsSetup() ); // Resize all derivative arrays // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() ); // Resize forces array - if( getNumberOfAtoms()>0 ){ - forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); + if( getNumberOfAtoms()>0 ) { + forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); } else { - forcesToApply.resize( getNumberOfArguments() ); + forcesToApply.resize( getNumberOfArguments() ); } } -void Mapping::turnOnDerivatives(){ +void Mapping::turnOnDerivatives() { ActionWithValue::turnOnDerivatives(); needsDerivatives(); -} +} -Mapping::~Mapping(){ +Mapping::~Mapping() { delete mymap; } -void Mapping::prepare(){ - if( mymap->mappingNeedsSetup() ){ - // Get the arguments and atoms that are required - std::vector atoms; std::vector args; - mymap->getAtomAndArgumentRequirements( atoms, args ); - requestAtoms( atoms ); std::vector req_args; - interpretArgumentList( args, req_args ); requestArguments( req_args ); - // Duplicate all frames (duplicates are used by sketch-map) - //mymap->duplicateFrameList(); - // Get the number of frames in the path - // unsigned nfram=getNumberOfReferencePoints(); - // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); - // plumed_assert( !mymap->mappingNeedsSetup() ); - // Resize all derivative arrays - // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() ); - // Resize forces array - if( getNumberOfAtoms()>0 ){ - forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); - } else { - forcesToApply.resize( getNumberOfArguments() ); - } +void Mapping::prepare() { + if( mymap->mappingNeedsSetup() ) { + // Get the arguments and atoms that are required + std::vector atoms; std::vector args; + mymap->getAtomAndArgumentRequirements( atoms, args ); + requestAtoms( atoms ); std::vector req_args; + interpretArgumentList( args, req_args ); requestArguments( req_args ); + // Duplicate all frames (duplicates are used by sketch-map) + //mymap->duplicateFrameList(); + // Get the number of frames in the path + // unsigned nfram=getNumberOfReferencePoints(); + // fframes.resize( 2*nfram, 0.0 ); dfframes.resize( 2*nfram, 0.0 ); + // plumed_assert( !mymap->mappingNeedsSetup() ); + // Resize all derivative arrays + // mymap->setNumberOfAtomsAndArguments( atoms.size(), args.size() ); + // Resize forces array + if( getNumberOfAtoms()>0 ) { + forcesToApply.resize( 3*getNumberOfAtoms() + 9 + getNumberOfArguments() ); + } else { + forcesToApply.resize( getNumberOfArguments() ); + } } } @@ -156,72 +156,72 @@ unsigned Mapping::getPropertyIndex( const std::string& name ) const { return mymap->getPropertyIndex( name ); } -void Mapping::setPropertyValue( const unsigned& iframe, const unsigned& jprop, const double& property ){ +void Mapping::setPropertyValue( const unsigned& iframe, const unsigned& jprop, const double& property ) { mymap->setProjectionCoordinate( iframe, jprop, property ); } -double Mapping::getLambda(){ +double Mapping::getLambda() { plumed_merror("lambda is not defined in this mapping type"); } -std::string Mapping::getArgumentName( unsigned& iarg ){ +std::string Mapping::getArgumentName( unsigned& iarg ) { if( iarg < getNumberOfArguments() ) return getPntrToArgument(iarg)->getName(); unsigned iatom=iarg - getNumberOfArguments(); std::string atnum; Tools::convert( getAbsoluteIndex(iatom).serial(),atnum); unsigned icomp=iatom%3; if(icomp==0) return "pos" + atnum + "x"; if(icomp==1) return "pos" + atnum + "y"; - return "pos" + atnum + "z"; -} + return "pos" + atnum + "z"; +} void Mapping::finishPackSetup( const unsigned& ifunc, ReferenceValuePack& mypack ) const { - ReferenceConfiguration* myref=mymap->getFrame(ifunc); mypack.setValIndex(0); - unsigned nargs2=myref->getNumberOfReferenceArguments(); unsigned nat2=myref->getNumberOfReferencePositions(); - if( mypack.getNumberOfAtoms()!=nat2 || mypack.getNumberOfArguments()!=nargs2 ) mypack.resize( nargs2, nat2 ); - if( nat2>0 ){ - ReferenceAtoms* myat2=dynamic_cast( myref ); plumed_dbg_assert( myat2 ); - for(unsigned i=0;igetAtomIndex(i) ); - } + ReferenceConfiguration* myref=mymap->getFrame(ifunc); mypack.setValIndex(0); + unsigned nargs2=myref->getNumberOfReferenceArguments(); unsigned nat2=myref->getNumberOfReferencePositions(); + if( mypack.getNumberOfAtoms()!=nat2 || mypack.getNumberOfArguments()!=nargs2 ) mypack.resize( nargs2, nat2 ); + if( nat2>0 ) { + ReferenceAtoms* myat2=dynamic_cast( myref ); plumed_dbg_assert( myat2 ); + for(unsigned i=0; igetAtomIndex(i) ); + } } double Mapping::calculateDistanceFunction( const unsigned& ifunc, ReferenceValuePack& myder, const bool& squared ) const { // Calculate the distance - double dd = mymap->calcDistanceFromConfiguration( ifunc, getPositions(), getPbc(), getArguments(), myder, squared ); + double dd = mymap->calcDistanceFromConfiguration( ifunc, getPositions(), getPbc(), getArguments(), myder, squared ); // Transform distance by whatever double df, ff=transformHD( dd, df ); myder.scaleAllDerivatives( df ); // And the virial - if( getNumberOfAtoms()>0 && !myder.virialWasSet() ){ - Tensor tvir; tvir.zero(); - for(unsigned i=0;i0 && !myder.virialWasSet() ) { + Tensor tvir; tvir.zero(); + for(unsigned i=0; igetFrame( ifunc ); } -void Mapping::calculateNumericalDerivatives( ActionWithValue* a ){ - if( getNumberOfArguments()>0 ){ - ActionWithArguments::calculateNumericalDerivatives( a ); +void Mapping::calculateNumericalDerivatives( ActionWithValue* a ) { + if( getNumberOfArguments()>0 ) { + ActionWithArguments::calculateNumericalDerivatives( a ); } - if( getNumberOfAtoms()>0 ){ - Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); - for(unsigned j=0;jgetDerivative(i); - } - calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); - for(unsigned j=0;jaddDerivative( i, save_derivatives(j,i) ); - } + if( getNumberOfAtoms()>0 ) { + Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); + for(unsigned j=0; jgetDerivative(i); + } + calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); + for(unsigned j=0; jaddDerivative( i, save_derivatives(j,i) ); + } } } -void Mapping::apply(){ - if( getForcesFromVessels( forcesToApply ) ){ - addForcesOnArguments( forcesToApply ); - if( getNumberOfAtoms()>0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); +void Mapping::apply() { + if( getForcesFromVessels( forcesToApply ) ) { + addForcesOnArguments( forcesToApply ); + if( getNumberOfAtoms()>0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); } } diff --git a/src/mapping/Mapping.h b/src/mapping/Mapping.h index 9b3145129a..02299d4c3a 100644 --- a/src/mapping/Mapping.h +++ b/src/mapping/Mapping.h @@ -40,8 +40,8 @@ class Mapping : public ActionWithArguments, public ActionWithValue, public vesselbase::ActionWithVessel - { -friend class TrigonometricPathVessel; +{ + friend class TrigonometricPathVessel; private: // The derivative wrt to the distance from the frame std::vector dfframes; @@ -76,10 +76,10 @@ friend class TrigonometricPathVessel; void lockRequests(); void unlockRequests(); /// Distance from a point is never periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } /// Get the number of derivatives for this action unsigned getNumberOfDerivatives(); // N.B. This is replacing the virtual function in ActionWithValue -/// Get the value of lambda for paths and property maps +/// Get the value of lambda for paths and property maps virtual double getLambda(); /// This does the transformation of the distance by whatever function is required virtual double transformHD( const double& dist, double& df ) const=0; @@ -87,7 +87,7 @@ friend class TrigonometricPathVessel; unsigned getNumberOfProperties() const ; /// Get the name of the ith property we are projecting std::string getPropertyName( const unsigned& iprop ) const ; -/// Get the index of a particular named property +/// Get the index of a particular named property unsigned getPropertyIndex( const std::string& name ) const ; /// Set the value of one of the projection coordinates void setPropertyValue( const unsigned& iframe, const unsigned& iprop, const double& property ); @@ -97,57 +97,57 @@ friend class TrigonometricPathVessel; double getPropertyValue( const unsigned& current, const unsigned& iprop ) const ; /// Stuff to do before we do the calculation void prepare(); -/// Apply the forces +/// Apply the forces void apply(); }; inline unsigned Mapping::getNumberOfReferencePoints() const { - return mymap->getNumberOfMappedPoints(); + return mymap->getNumberOfMappedPoints(); } inline -unsigned Mapping::getNumberOfDerivatives(){ +unsigned Mapping::getNumberOfDerivatives() { unsigned nat=getNumberOfAtoms(); if(nat>0) return 3*nat + 9 + getNumberOfArguments(); return getNumberOfArguments(); } inline -void Mapping::lockRequests(){ +void Mapping::lockRequests() { ActionWithArguments::lockRequests(); ActionAtomistic::lockRequests(); } inline -void Mapping::unlockRequests(){ +void Mapping::unlockRequests() { ActionWithArguments::unlockRequests(); ActionAtomistic::unlockRequests(); } inline unsigned Mapping::getNumberOfProperties() const { - return mymap->getNumberOfProperties(); + return mymap->getNumberOfProperties(); } inline std::string Mapping::getPropertyName( const unsigned& iprop ) const { - return mymap->getPropertyName(iprop); + return mymap->getPropertyName(iprop); } inline double Mapping::getPropertyValue( const unsigned& cur, const unsigned& iprop ) const { plumed_dbg_assert( ipropgetPropertyValue( cur, iprop ); + return mymap->getPropertyValue( cur, iprop ); } inline double Mapping::getWeight( const unsigned& current ) const { - return mymap->getWeight( current ); + return mymap->getWeight( current ); } inline -void Mapping::storeDistanceFunction( const unsigned& ifunc ){ +void Mapping::storeDistanceFunction( const unsigned& ifunc ) { plumed_dbg_assert( ifunc& Mapping::getAllReferenceConfigurations(){ +std::vector& Mapping::getAllReferenceConfigurations() { return mymap->getReferenceConfigurations(); } diff --git a/src/mapping/PCAVars.cpp b/src/mapping/PCAVars.cpp index 0ae940a749..d029720ed8 100644 --- a/src/mapping/PCAVars.cpp +++ b/src/mapping/PCAVars.cpp @@ -33,25 +33,25 @@ /* Projection on principal component eigenvectors or other high dimensional linear subspace -The collective variables described in \ref dists allow one to calculate the distance between the -instaneous structure adopted by the system and some high-dimensional, reference configuration. The +The collective variables described in \ref dists allow one to calculate the distance between the +instaneous structure adopted by the system and some high-dimensional, reference configuration. The problem with doing this is that, as one gets further and further from the reference configuration, the distance from it becomes a progressively poorer and poorer collective variable. This happens because -the ``number" of structures at a distance \f$d\f$ from a reference configuration is proportional to \f$d^N\f$ in -an \f$N\f$ dimensional space. Consequently, when \f$d\f$ is small the distance from the reference configuration +the ``number" of structures at a distance \f$d\f$ from a reference configuration is proportional to \f$d^N\f$ in +an \f$N\f$ dimensional space. Consequently, when \f$d\f$ is small the distance from the reference configuration may well be a good collective variable. However, when \f$d\f$ is large it is unlikely that the distance from the reference -structure is a good CV. When the distance is large there will almost certainly be markedly different -configuration that have the same CV value and hence barriers in transverse degrees of -freedom. +structure is a good CV. When the distance is large there will almost certainly be markedly different +configuration that have the same CV value and hence barriers in transverse degrees of +freedom. -For these reasons dimensionality reduction is often employed so a projection \f$\mathbf{s}\f$ of a high-dimensional configuration +For these reasons dimensionality reduction is often employed so a projection \f$\mathbf{s}\f$ of a high-dimensional configuration \f$\mathbf{X}\f$ in a lower dimensionality space using a function: \f[ \mathbf{s} = F(\mathbf{X}-\mathbf{X}^{ref}) \f] -where here we have introduced some high-dimensional reference configuration \f$\mathbf{X}^{ref}\f$. By far the simplest way to +where here we have introduced some high-dimensional reference configuration \f$\mathbf{X}^{ref}\f$. By far the simplest way to do this is to use some linear operator for \f$F\f$. That is to say we find a low-dimensional projection by rotating the basis vectors using some linear algebra: @@ -61,9 +61,9 @@ by rotating the basis vectors using some linear algebra: Here \f$A\f$ is a \f$d\f$ by \f$D\f$ matrix where \f$D\f$ is the dimensionality of the high dimensional space and \f$d\f$ is the dimensionality of the lower dimensional subspace. In plumed when this kind of projection you can use the majority -of the metrics detailed on \ref dists to calculate the displacement, \f$\mathbf{X}-\mathbf{X}^{ref}\f$, from the reference configuration. -The matrix \f$A\f$ can be found by various means including principal component analysis and normal mode analysis. In both these methods the -rows of \f$A\f$ would be the principle eigenvectors of a square matrix. For PCA the covariance while for normal modes the Hessian. +of the metrics detailed on \ref dists to calculate the displacement, \f$\mathbf{X}-\mathbf{X}^{ref}\f$, from the reference configuration. +The matrix \f$A\f$ can be found by various means including principal component analysis and normal mode analysis. In both these methods the +rows of \f$A\f$ would be the principle eigenvectors of a square matrix. For PCA the covariance while for normal modes the Hessian. \bug It is not possible to use the \ref DRMSD metric with this variable. You can get around this by listing the set of distances you wish to calculate for your DRMSD in the plumed file explicitally and using the EUCLIDEAN metric. MAHALONOBIS and NORM-EUCLIDEAN also do not work with this variable but using these options makes little sense when projecting on a linear subspace. @@ -72,19 +72,19 @@ rows of \f$A\f$ would be the principle eigenvectors of a square matrix. For PCA The following input calculates a projection on a linear subspace where the displacements from the reference configuration are calculated using the OPTIMAL metric. Consequently, both translation of the center of mass of the atoms and rotation of the reference -frame are removed from these displacements. The matrix \f$A\f$ and the reference -configuration \f$R^{ref}\f$ are specified in the pdb input file reference.pdb and the +frame are removed from these displacements. The matrix \f$A\f$ and the reference +configuration \f$R^{ref}\f$ are specified in the pdb input file reference.pdb and the value of all projections (and the residual) are output to a file called colvar2. \verbatim PCAVARS REFERENCE=reference.pdb TYPE=OPTIMAL LABEL=pca2 -PRINT ARG=pca2.* FILE=colvar2 +PRINT ARG=pca2.* FILE=colvar2 \endverbatim The reference configurations can be specified using a pdb file. The first configuration that you provide is the reference configuration, -which is refered to in the above as \f$X^{ref}\f$ subsequent configurations give the directions of row vectors that are contained in -the matrix \f$A\f$ above. These directions can be specified by specifying a second configuration - in this case a vector will -be constructed by calculating the displacement of this second configuration from the reference configuration. A pdb input prepared +which is refered to in the above as \f$X^{ref}\f$ subsequent configurations give the directions of row vectors that are contained in +the matrix \f$A\f$ above. These directions can be specified by specifying a second configuration - in this case a vector will +be constructed by calculating the displacement of this second configuration from the reference configuration. A pdb input prepared in this way would look as follows: \verbatim @@ -106,7 +106,7 @@ ATOM 21 HH32 NME 3 18.572 -13.148 -16.346 1.00 1.00 END \endverbatim -Alternatively, the second configuration can specify the components of \f$A\f$ explicitally. In this case you need to include the +Alternatively, the second configuration can specify the components of \f$A\f$ explicitally. In this case you need to include the keyword TYPE=DIRECTION in the remarks to the pdb as shown below. \verbatim @@ -134,12 +134,12 @@ for each of the frames of your path. An input file in this case might look like \verbatim DESCRIPTION: a pca eigenvector specified using the start point and direction in the HD space. -REMARK WEIGHT=1.0 -REMARK ARG=d1,d2 +REMARK WEIGHT=1.0 +REMARK ARG=d1,d2 REMARK d1=1.0 d2=1.0 END REMARK TYPE=DIRECTION -REMARK ARG=d1,d2 +REMARK ARG=d1,d2 REMARK d1=0.1 d2=0.25 END \endverbatim @@ -151,11 +151,11 @@ If we wanted to specify the direction in this metric using the start and end poi \verbatim DESCRIPTION: a pca eigenvector specified using the start and end point of a vector in the HD space. -REMARK WEIGHT=1.0 -REMARK ARG=d1,d2 +REMARK WEIGHT=1.0 +REMARK ARG=d1,d2 REMARK d1=1.0 d2=1.0 END -REMARK ARG=d1,d2 +REMARK ARG=d1,d2 REMARK d1=1.1 d2=1.25 END \endverbatim @@ -170,13 +170,13 @@ class PCAVars : public ActionWithValue, public ActionAtomistic, public ActionWithArguments - { +{ private: /// The holders for the derivatives MultiValue myvals; ReferenceValuePack mypack; /// The position of the reference configuration (the one we align to) - ReferenceConfiguration* myref; + ReferenceConfiguration* myref; /// The eigenvectors we are interested in std::vector directions; /// Stuff for applying forces @@ -195,30 +195,30 @@ class PCAVars : PLUMED_REGISTER_ACTION(PCAVars,"PCAVARS") -void PCAVars::registerKeywords( Keywords& keys ){ +void PCAVars::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionWithArguments::registerKeywords( keys ); componentsAreNotOptional(keys); - keys.addOutputComponent("eig","default","the projections on each eigenvalue are stored on values labeled eig-1, eig-2, ..."); + keys.addOutputComponent("eig","default","the projections on each eigenvalue are stored on values labeled eig-1, eig-2, ..."); keys.addOutputComponent("residual","default","the distance of the configuration from the linear subspace defined " - "by the vectors, \\f$e_i\\f$, that are contained in the rows of \\f$A\\f$. In other words this is " - "\\f$\\sqrt( r^2 - \\sum_i [\\mathbf{r}.\\mathbf{e_i}]^2)\\f$ where " - "\\f$r\\f$ is the distance between the instantaneous position and the " - "reference point."); + "by the vectors, \\f$e_i\\f$, that are contained in the rows of \\f$A\\f$. In other words this is " + "\\f$\\sqrt( r^2 - \\sum_i [\\mathbf{r}.\\mathbf{e_i}]^2)\\f$ where " + "\\f$r\\f$ is the distance between the instantaneous position and the " + "reference point."); keys.add("compulsory","REFERENCE","a pdb file containing the reference configuration and configurations that define the directions for each eigenvector"); keys.add("compulsory","TYPE","OPTIMAL","The method we are using for alignment to the reference structure"); keys.addFlag("NORMALIZE",false,"calculate the length of the eigenvector input and divide the components by it so as to have a normalised vector"); } PCAVars::PCAVars(const ActionOptions& ao): -Action(ao), -ActionWithValue(ao), -ActionAtomistic(ao), -ActionWithArguments(ao), -myvals(1,0), -mypack(0,0,myvals) + Action(ao), + ActionWithValue(ao), + ActionAtomistic(ao), + ActionWithArguments(ao), + myvals(1,0), + mypack(0,0,myvals) { // What type of distance are we calculating @@ -229,30 +229,30 @@ mypack(0,0,myvals) FILE* fp=fopen(reference.c_str(),"r"); if(!fp) error("could not open reference file " + reference ); - // Read all reference configurations + // Read all reference configurations MultiReferenceBase myframes( "", false ); bool do_read=true; unsigned nfram=0; - while (do_read){ - PDB mypdb; - // Read the pdb file - do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); - // Fix argument names - expandArgKeywordInPDB( mypdb ); - if(do_read){ - if( nfram==0 ){ - myref = metricRegister().create( mtype, mypdb ); - Direction* tdir = dynamic_cast( myref ); - if( tdir ) error("first frame should be reference configuration - not direction of vector"); - if( !myref->pcaIsEnabledForThisReference() ) error("can't do PCA with reference type " + mtype ); - std::vector remarks( mypdb.getRemark() ); std::string rtype; - bool found=Tools::parse( remarks, "TYPE", rtype ); - if(!found){ std::vector newrem(1); newrem[0]="TYPE="+mtype; mypdb.addRemark(newrem); } - myframes.readFrame( mypdb ); - } else myframes.readFrame( mypdb ); - nfram++; - } else { - break; - } + while (do_read) { + PDB mypdb; + // Read the pdb file + do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength()); + // Fix argument names + expandArgKeywordInPDB( mypdb ); + if(do_read) { + if( nfram==0 ) { + myref = metricRegister().create( mtype, mypdb ); + Direction* tdir = dynamic_cast( myref ); + if( tdir ) error("first frame should be reference configuration - not direction of vector"); + if( !myref->pcaIsEnabledForThisReference() ) error("can't do PCA with reference type " + mtype ); + std::vector remarks( mypdb.getRemark() ); std::string rtype; + bool found=Tools::parse( remarks, "TYPE", rtype ); + if(!found) { std::vector newrem(1); newrem[0]="TYPE="+mtype; mypdb.addRemark(newrem); } + myframes.readFrame( mypdb ); + } else myframes.readFrame( mypdb ); + nfram++; + } else { + break; + } } fclose(fp); @@ -267,170 +267,170 @@ mypack(0,0,myvals) interpretArgumentList( args, req_args ); requestArguments( req_args ); // Setup the derivative pack - if( atoms.size()>0 ) myvals.resize( 1, args.size() + 3*atoms.size() + 9 ); + if( atoms.size()>0 ) myvals.resize( 1, args.size() + 3*atoms.size() + 9 ); else myvals.resize( 1, args.size() ); - mypack.resize( args.size(), atoms.size() ); - for(unsigned i=0;isetupPCAStorage( mypack ); // Retrieve the position of the first frame, as we use this for alignment myref->setNamesAndAtomNumbers( atoms, args ); // Check there are no periodic arguments - for(unsigned i=0;iisPeriodic() ) error("cannot use periodic variables in pca projections"); + for(unsigned i=0; iisPeriodic() ) error("cannot use periodic variables in pca projections"); } // Work out if the user wants to normalise the input vector bool nflag; parseFlag("NORMALIZE",nflag); checkRead(); - // Resize the matrices that will hold our eivenvectors - for(unsigned i=1;iextractDisplacementVector( myref->getReferencePositions(), getArguments(), myref->getReferenceArguments(), false, nflag, directions[i-1] ); - // Create a component to store the output - std::string num; Tools::convert( i, num ); - addComponentWithDerivatives("eig-"+num); componentIsNotPeriodic("eig-"+num); + // Now calculate the eigenvectors + for(unsigned i=1; iextractDisplacementVector( myref->getReferencePositions(), getArguments(), myref->getReferenceArguments(), false, nflag, directions[i-1] ); + // Create a component to store the output + std::string num; Tools::convert( i, num ); + addComponentWithDerivatives("eig-"+num); componentIsNotPeriodic("eig-"+num); } addComponentWithDerivatives("residual"); componentIsNotPeriodic("residual"); // Get appropriate number of derivatives unsigned nder; - if( getNumberOfAtoms()>0 ){ - nder = 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); + if( getNumberOfAtoms()>0 ) { + nder = 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); } else { - nder = getNumberOfArguments(); + nder = getNumberOfArguments(); } // Resize all derivative arrays - forces.resize( nder ); forcesToApply.resize( nder ); - for(unsigned i=0;iresizeDerivatives(nder); + forces.resize( nder ); forcesToApply.resize( nder ); + for(unsigned i=0; iresizeDerivatives(nder); } -PCAVars::~PCAVars(){ - delete myref; +PCAVars::~PCAVars() { + delete myref; } -unsigned PCAVars::getNumberOfDerivatives(){ - if( getNumberOfAtoms()>0 ){ - return 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); - } +unsigned PCAVars::getNumberOfDerivatives() { + if( getNumberOfAtoms()>0 ) { + return 3*getNumberOfAtoms() + 9 + getNumberOfArguments(); + } return getNumberOfArguments(); -} +} -void PCAVars::lockRequests(){ +void PCAVars::lockRequests() { ActionWithArguments::lockRequests(); ActionAtomistic::lockRequests(); } -void PCAVars::unlockRequests(){ - ActionWithArguments::unlockRequests(); +void PCAVars::unlockRequests() { + ActionWithArguments::unlockRequests(); ActionAtomistic::unlockRequests(); -} +} -void PCAVars::calculate(){ +void PCAVars::calculate() { // Clear the reference value pack mypack.clear(); // Calculate distance between instaneous configuration and reference double dist = myref->calculate( getPositions(), getPbc(), getArguments(), mypack, true ); - + // Start accumulating residual by adding derivatives of distance Value* resid=getPntrToComponent( getNumberOfComponents()-1 ); unsigned nargs=getNumberOfArguments(); - for(unsigned j=0;jaddDerivative( j, mypack.getArgumentDerivative(j) ); - for(unsigned j=0;jaddDerivative( nargs +3*j+k, ader[k] ); + for(unsigned j=0; jaddDerivative( j, mypack.getArgumentDerivative(j) ); + for(unsigned j=0; jaddDerivative( nargs +3*j+k, ader[k] ); } // Retrieve the values of all arguments - std::vector args( getNumberOfArguments() ); for(unsigned i=0;i args( getNumberOfArguments() ); for(unsigned i=0; iprojectDisplacementOnVector( directions[i], getPositions(), getArguments(), args, mypack ); - - // And now accumulate derivatives - Value* eid=getPntrToComponent(i); - for(unsigned j=0;jaddDerivative( j, mypack.getArgumentDerivative(j) ); - if( getNumberOfAtoms()>0 ){ - tvir.zero(); - for(unsigned j=0;jaddDerivative( nargs + 3*j+k, myader[k] ); - resid->addDerivative( nargs + 3*j+k, -2*proj*myader[k] ); - } - tvir += -1.0*Tensor( getPosition(j), myader ); - } - for(unsigned j=0;j<3;++j){ - for(unsigned k=0;k<3;++k) eid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); - } + for(unsigned i=0; iprojectDisplacementOnVector( directions[i], getPositions(), getArguments(), args, mypack ); + + // And now accumulate derivatives + Value* eid=getPntrToComponent(i); + for(unsigned j=0; jaddDerivative( j, mypack.getArgumentDerivative(j) ); + if( getNumberOfAtoms()>0 ) { + tvir.zero(); + for(unsigned j=0; jaddDerivative( nargs + 3*j+k, myader[k] ); + resid->addDerivative( nargs + 3*j+k, -2*proj*myader[k] ); + } + tvir += -1.0*Tensor( getPosition(j), myader ); + } + for(unsigned j=0; j<3; ++j) { + for(unsigned k=0; k<3; ++k) eid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); } - dist -= proj*proj; // Subtract square from total squared distance to get residual squared - // Derivatives of residual - for(unsigned j=0;jaddDerivative( j, -2*proj*eid->getDerivative(j) ); - // for(unsigned j=0;jaddDerivative( j, -2*proj*arg_eigv(i,j) ); - // And set final value - getPntrToComponent(i)->set( proj ); + } + dist -= proj*proj; // Subtract square from total squared distance to get residual squared + // Derivatives of residual + for(unsigned j=0; jaddDerivative( j, -2*proj*eid->getDerivative(j) ); + // for(unsigned j=0;jaddDerivative( j, -2*proj*arg_eigv(i,j) ); + // And set final value + getPntrToComponent(i)->set( proj ); } dist=sqrt(dist); resid->set( dist ); // Take square root of residual derivatives double prefactor = 0.5 / dist; - for(unsigned j=0;jsetDerivative( j, prefactor*resid->getDerivative(j) ); - for(unsigned j=0;jsetDerivative( nargs + 3*j+k, prefactor*resid->getDerivative( nargs+3*j+k ) ); + for(unsigned j=0; jsetDerivative( j, prefactor*resid->getDerivative(j) ); + for(unsigned j=0; jsetDerivative( nargs + 3*j+k, prefactor*resid->getDerivative( nargs+3*j+k ) ); } // And finally virial for residual - if( getNumberOfAtoms()>0 ){ - tvir.zero(); - for(unsigned j=0;jgetDerivative( nargs + 3*j+k ); - tvir += -1.0*Tensor( getPosition(j), ader ); - } - for(unsigned j=0;j<3;++j){ - for(unsigned k=0;k<3;++k) resid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); - } + if( getNumberOfAtoms()>0 ) { + tvir.zero(); + for(unsigned j=0; jgetDerivative( nargs + 3*j+k ); + tvir += -1.0*Tensor( getPosition(j), ader ); + } + for(unsigned j=0; j<3; ++j) { + for(unsigned k=0; k<3; ++k) resid->addDerivative( nargs + 3*getNumberOfAtoms() + 3*j + k, tvir(j,k) ); + } } } -void PCAVars::calculateNumericalDerivatives( ActionWithValue* a ){ - if( getNumberOfArguments()>0 ){ - ActionWithArguments::calculateNumericalDerivatives( a ); +void PCAVars::calculateNumericalDerivatives( ActionWithValue* a ) { + if( getNumberOfArguments()>0 ) { + ActionWithArguments::calculateNumericalDerivatives( a ); } - if( getNumberOfAtoms()>0 ){ - Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); - for(unsigned j=0;jgetDerivative(i); - } - calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); - for(unsigned j=0;jaddDerivative( i, save_derivatives(j,i) ); - } + if( getNumberOfAtoms()>0 ) { + Matrix save_derivatives( getNumberOfComponents(), getNumberOfArguments() ); + for(unsigned j=0; jgetDerivative(i); + } + calculateAtomicNumericalDerivatives( a, getNumberOfArguments() ); + for(unsigned j=0; jaddDerivative( i, save_derivatives(j,i) ); + } } -} +} -void PCAVars::apply(){ +void PCAVars::apply() { bool wasforced=false; forcesToApply.assign(forcesToApply.size(),0.0); - for(unsigned i=0;iapplyForce( forces ) ){ - wasforced=true; - for(unsigned i=0;iapplyForce( forces ) ) { + wasforced=true; + for(unsigned i=0; i0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); + if( wasforced ) { + addForcesOnArguments( forcesToApply ); + if( getNumberOfAtoms()>0 ) setForcesOnAtoms( forcesToApply, getNumberOfArguments() ); } } diff --git a/src/mapping/Path.cpp b/src/mapping/Path.cpp index 7928ff3a2c..37db777d2e 100644 --- a/src/mapping/Path.cpp +++ b/src/mapping/Path.cpp @@ -24,14 +24,14 @@ //+PLUMEDOC COLVAR PATH /* -Path collective variables with a more flexible framework for the distance metric being used. +Path collective variables with a more flexible framework for the distance metric being used. The Path Collective Variables developed by Branduardi and co-workers \cite brand07 allow one to compute the progress along a high-dimensional path and the distance from the high-dimensional path. The progress along the path (s) is computed using: \f[ -s = \frac{ \sum_{i=1}^N i \exp( -\lambda R[X - X_i] ) }{ \sum_{i=1}^N \exp( -\lambda R[X - X_i] ) } +s = \frac{ \sum_{i=1}^N i \exp( -\lambda R[X - X_i] ) }{ \sum_{i=1}^N \exp( -\lambda R[X - X_i] ) } \f] while the distance from the path (z) is measured using: @@ -44,7 +44,7 @@ In these expressions \f$N\f$ high-dimensional frames (\f$X_i\f$) are used to des space. The two expressions above are then functions of the distances from each of the high-dimensional frames \f$R[X - X_i]\f$. Within PLUMED there are multiple ways to define the distance from a high-dimensional configuration. You could calculate the RMSD distance or you could calculate the ammount by which a set of collective variables change. As such this implementation -of the path cv allows one to use all the difference distance metrics that are discussed in \ref dists. This is as opposed to +of the path cv allows one to use all the difference distance metrics that are discussed in \ref dists. This is as opposed to the alternative implementation of path (\ref PATHMSD) which is a bit faster but which only allows one to use the RMSD distance. The \f$s\f$ and \f$z\f$ variables are calculated using the above formulas by default. However, there is an alternative method @@ -54,14 +54,14 @@ geometry (as opposed to algebra, which is used in the equations above). In this \f[ s = i_2 + \textrm{sign}(i_2-i_1) \frac{ \sqrt{( \mathbf{v}_1\cdot\mathbf{v}_2 )^2 - |\mathbf{v}_3|^2(|\mathbf{v}_1|^2 - |\mathbf{v}_2|^2) } }{2|\mathbf{v}_3|^2} - \frac{\mathbf{v}_1\cdot\mathbf{v}_3 - |\mathbf{v}_3|^2}{2|\mathbf{v}_3|^2} -\f] +\f] -where \f$\mathbf{v}_1\f$ and \f$\mathbf{v}_3\f$ are the vectors connecting the current position to the closest and second closest node of the path, -respectfully and \f$i_1\f$ and \f$i_2\f$ are the projections of the closest and second closest frames of the path. \f$\mathbf{v}_2\f$, meanwhile, is the +where \f$\mathbf{v}_1\f$ and \f$\mathbf{v}_3\f$ are the vectors connecting the current position to the closest and second closest node of the path, +respectfully and \f$i_1\f$ and \f$i_2\f$ are the projections of the closest and second closest frames of the path. \f$\mathbf{v}_2\f$, meanwhile, is the vector connecting the closest frame to the second closest frame. The distance from the path, \f$z\f$ is calculated using: \f[ -z = \sqrt{ \left[ |\mathbf{v}_1|^2 - |\mathbf{v}_2| \left( \frac{ \sqrt{( \mathbf{v}_1\cdot\mathbf{v}_2 )^2 - |\mathbf{v}_3|^2(|\mathbf{v}_1|^2 - |\mathbf{v}_2|^2) } }{2|\mathbf{v}_3|^2} - \frac{\mathbf{v}_1\cdot\mathbf{v}_3 - |\mathbf{v}_3|^2}{2|\mathbf{v}_3|^2} \right) \right]^2 } +z = \sqrt{ \left[ |\mathbf{v}_1|^2 - |\mathbf{v}_2| \left( \frac{ \sqrt{( \mathbf{v}_1\cdot\mathbf{v}_2 )^2 - |\mathbf{v}_3|^2(|\mathbf{v}_1|^2 - |\mathbf{v}_2|^2) } }{2|\mathbf{v}_3|^2} - \frac{\mathbf{v}_1\cdot\mathbf{v}_3 - |\mathbf{v}_3|^2}{2|\mathbf{v}_3|^2} \right) \right]^2 } \f] The symbols here are as they were for \f$s\f$. If you would like to use these equations to calculate \f$s\f$ and \f$z\f$ then you should use the GPATH flag. @@ -71,26 +71,26 @@ The values of \f$s\f$ and \f$z\f$ can then be referenced using the gspath and gz In the example below the path is defined using RMSD distance from frames. The reference frames in the path are defined in the pdb file. In this frame -each configuration in the path is separated by a line containing just the word END. +each configuration in the path is separated by a line containing just the word END. -\verbatim -p1: PATH REFERENCE=file.pdb TYPE=OPTIMAL LAMBDA=500.0 +\verbatim +p1: PATH REFERENCE=file.pdb TYPE=OPTIMAL LAMBDA=500.0 PRINT ARG=p1.sss,p1.zzz STRIDE=1 FILE=colvar FMT=%8.4f \endverbatim In the example below the path is defined using the values of two torsional angles (t1 and t2). -In addition, the \f$s\f$ and \f$z\f$ are calculated using the geometric expressions described +In addition, the \f$s\f$ and \f$z\f$ are calculated using the geometric expressions described above rather than the alegebraic expressions that are used by default. \verbatim t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 pp: PATH TYPE=EUCLIDEAN REFERENCE=epath.pdb GPATH NOSPATH NOZPATH -PRINT ARG=pp.* FILE=colvar +PRINT ARG=pp.* FILE=colvar \endverbatim Notice that the LAMBDA parameter is not required here as we are not calculating \f$s\f$ and \f$s\f$ -using the algebraic formulae defined earlier. The positions of the frames in the path are defined +using the algebraic formulae defined earlier. The positions of the frames in the path are defined in the file epath.pdb. An extract from this file looks as shown below. \verbatim @@ -102,16 +102,16 @@ REMARK ARG=t1,t2 t1=-3.96947 t2=3.61947 END \endverbatim -The remarks in this pdb file tell PLUMED the labels that are being used to define the position in the +The remarks in this pdb file tell PLUMED the labels that are being used to define the position in the high dimensional space and the values that these arguments have at each point on the path. -The following input instructs PLUMED to calculate the values of the path collective variables. The frames that make up this -path are defined in the file all.pdb and all distances are measured using the OPTIMAL metric that is discussed in the manual -page on \ref RMSD. +The following input instructs PLUMED to calculate the values of the path collective variables. The frames that make up this +path are defined in the file all.pdb and all distances are measured using the OPTIMAL metric that is discussed in the manual +page on \ref RMSD. \verbatim p2: PATH REFERENCE=all.pdb LAMBDA=69087 -PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar +PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar \endverbatim If you wish to use collective variable values in the definition of your path you would use an input file with something like this: @@ -120,19 +120,19 @@ If you wish to use collective variable values in the definition of your path you d1: DISTANCE ATOMS=1,2 d2: DISTANCE ATOMS=3,4a p2: PATH REFERENCE=mypath.pdb LAMBDA=2 TYPE=EUCLIDEAN -PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar +PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar \endverbatim The corresponding pdb file containing the definitions of the frames in the path would then look like this: \verbatim DESCRIPTION: a defintiion of a PATH -REMARK TYPE=EUCLIDEAN -REMARK ARG=d1,d2 +REMARK TYPE=EUCLIDEAN +REMARK ARG=d1,d2 REMARK d1=1.0 d2=1.0 END REMARK TYPE=EUCLIDEAN -REMARK ARG=d1,d2 +REMARK ARG=d1,d2 REMARK d1=2.0 d2=2.0 END \endverbatim @@ -144,7 +144,7 @@ of the system and the reference configurations together with the values that the //+ENDPLUMEDOC namespace PLMD { -namespace mapping{ +namespace mapping { class Path : public PathBase { public: @@ -154,27 +154,27 @@ class Path : public PathBase { PLUMED_REGISTER_ACTION(Path,"PATH") -void Path::registerKeywords( Keywords& keys ){ +void Path::registerKeywords( Keywords& keys ) { PathBase::registerKeywords( keys ); keys.remove("PROPERTY"); keys.addFlag("NOSPATH",false,"do not calculate the spath position"); keys.remove("LOWMEM"); keys.use("GPATH"); } Path::Path(const ActionOptions& ao): -Action(ao), -PathBase(ao) + Action(ao), + PathBase(ao) { - setLowMemOption( true ); + setLowMemOption( true ); bool nos; parseFlag("NOSPATH",nos); std::string empty; - if(!nos){ - if( getPropertyIndex("spath")!=0 || getNumberOfProperties()>1 ){ - error("paths only work when there is a single property called sss being calculated"); - } - if( getLambda()==0 ) error("you must set LAMBDA parameter in order to calculate spath position. Use LAMBDA/NOSPATH keyword"); - empty="LABEL=spath"; - addVessel("SPATH",empty,0); + if(!nos) { + if( getPropertyIndex("spath")!=0 || getNumberOfProperties()>1 ) { + error("paths only work when there is a single property called sss being calculated"); + } + if( getLambda()==0 ) error("you must set LAMBDA parameter in order to calculate spath position. Use LAMBDA/NOSPATH keyword"); + empty="LABEL=spath"; + addVessel("SPATH",empty,0); } readVesselKeywords(); checkRead(); diff --git a/src/mapping/PathBase.cpp b/src/mapping/PathBase.cpp index 25c2862f9a..af50f0375d 100644 --- a/src/mapping/PathBase.cpp +++ b/src/mapping/PathBase.cpp @@ -23,41 +23,41 @@ #include "tools/SwitchingFunction.h" namespace PLMD { -namespace mapping{ +namespace mapping { -void PathBase::registerKeywords( Keywords& keys ){ - Mapping::registerKeywords( keys ); +void PathBase::registerKeywords( Keywords& keys ) { + Mapping::registerKeywords( keys ); keys.add("compulsory","LAMBDA","0","the value of the lambda parameter for paths"); keys.addFlag("NOZPATH",false,"do not calculate the zpath position"); } PathBase::PathBase(const ActionOptions& ao): -Action(ao), -Mapping(ao) + Action(ao), + Mapping(ao) { weightHasDerivatives=true; bool noz; parseFlag("NOZPATH",noz); parse("LAMBDA",lambda); // Create the list of tasks - for(unsigned i=0;i& iargs, std::vector& pp ): -mydpack( 1, pp[0]->getNumberOfReferenceArguments() + 3*pp[0]->getNumberOfReferencePositions() + 9 ), -mypack( pp[0]->getNumberOfReferenceArguments(), pp[0]->getNumberOfReferencePositions(), mydpack ), -mypath(pp), -pbc(ipbc), -args(iargs), -mydir(ReferenceConfigurationOptions("DIRECTION")), -len(pp.size()), -sumlen(pp.size()), -sfrac(pp.size()), -MAXCYCLES(100) +PathReparameterization::PathReparameterization( const Pbc& ipbc, const std::vector& iargs, std::vector& pp ): + mydpack( 1, pp[0]->getNumberOfReferenceArguments() + 3*pp[0]->getNumberOfReferencePositions() + 9 ), + mypack( pp[0]->getNumberOfReferenceArguments(), pp[0]->getNumberOfReferencePositions(), mydpack ), + mypath(pp), + pbc(ipbc), + args(iargs), + mydir(ReferenceConfigurationOptions("DIRECTION")), + len(pp.size()), + sumlen(pp.size()), + sfrac(pp.size()), + MAXCYCLES(100) { - mydir.setNamesAndAtomNumbers( pp[0]->getAbsoluteIndexes(), pp[0]->getArgumentNames() ); + mydir.setNamesAndAtomNumbers( pp[0]->getAbsoluteIndexes(), pp[0]->getArgumentNames() ); mydir.zeroDirection(); pp[0]->setupPCAStorage( mypack ); } bool PathReparameterization::loopEnd( const int& index, const int& end, const int& inc ) const { if( inc>0 && indexend ) return false; - return true; + return true; } -void PathReparameterization::calcCurrentPathSpacings( const int& istart, const int& iend ){ +void PathReparameterization::calcCurrentPathSpacings( const int& istart, const int& iend ) { plumed_dbg_assert( istartiend ){ incr=-1; } + int incr=1; if( istart>iend ) { incr=-1; } - for(int i=istart+incr;loopEnd(i,iend+incr,incr)==false;i+=incr){ - len[i] = mypath[i-incr]->calc( mypath[i]->getReferencePositions(), pbc, args, mypath[i]->getReferenceArguments(), mypack, false ); - sumlen[i] = sumlen[i-incr] + len[i]; - //printf("FRAME %d TO FRAME %d EQUALS %f : %f \n",i-incr,i,len[i],sumlen[i] ); + for(int i=istart+incr; loopEnd(i,iend+incr,incr)==false; i+=incr) { + len[i] = mypath[i-incr]->calc( mypath[i]->getReferencePositions(), pbc, args, mypath[i]->getReferenceArguments(), mypack, false ); + sumlen[i] = sumlen[i-incr] + len[i]; + //printf("FRAME %d TO FRAME %d EQUALS %f : %f \n",i-incr,i,len[i],sumlen[i] ); } } -void PathReparameterization::reparameterizePart( const int& istart, const int& iend, const double& target, const double& TOL ){ +void PathReparameterization::reparameterizePart( const int& istart, const int& iend, const double& target, const double& TOL ) { calcCurrentPathSpacings( istart, iend ); unsigned cfin; // If a target separation is set we fix where we want the nodes - int incr=1; if( istart>iend ){ incr=-1; } - - if( target>0 ){ - if( iend>istart ){ - for(unsigned i=istart;iiend-1;--i) sfrac[i]=target*(istart-i); - } - cfin = iend+incr; + int incr=1; if( istart>iend ) { incr=-1; } + + if( target>0 ) { + if( iend>istart ) { + for(unsigned i=istart; iiend-1; --i) sfrac[i]=target*(istart-i); + } + cfin = iend+incr; } else { - cfin = iend; + cfin = iend; } std::vector newpath; - for(unsigned i=0;igetAbsoluteIndexes(), mypath[i]->getArgumentNames() ); + for(unsigned i=0; igetAbsoluteIndexes(), mypath[i]->getArgumentNames() ); } double prevsum=0.; - for(unsigned iter=0;iter( iend - istart ); - for(unsigned i=istart;i=sfrac[i])) ){ - k+=incr; - if( cfin==iend && k>= iend+1 ) plumed_merror("path reparameterization error"); - else if( cfin==(iend+1) && k>=iend ){ k=iend-1; break; } - else if( cfin==(iend-1) && k<=iend ){ k=iend+1; break; } - } - double dr = (sfrac[i]-sumlen[k])/len[k+incr]; - // Calculate the displacement between the appropriate points - // double dd = mypath[k]->calc( mypath[k+incr]->getReferencePositions(), pbc, args, mypath[k+incr]->getReferenceArguments(), mypack, true ); - // Copy the reference configuration from the configuration to a tempory direction - newpath[i].setDirection( mypath[k]->getReferencePositions(), mypath[k]->getReferenceArguments() ); - // Get the displacement of the path - mypath[k]->extractDisplacementVector( mypath[k+incr]->getReferencePositions(), args, mypath[k+incr]->getReferenceArguments(), false, false, mydir ); - // Set our direction equal to the displacement - // mydir.setDirection( mypack ); - // Shift the reference configuration by this ammount - newpath[i].displaceReferenceConfiguration( dr, mydir ); - } - - // Copy the positions of the new path to the new paths - for(int i=istart+incr;loopEnd(i,cfin,incr)==false;i+=incr){ - mypath[i]->setReferenceConfig( newpath[i].getReferencePositions(), newpath[i].getReferenceArguments(), mypath[i]->getReferenceMetric() ); - } - - // Recompute the separations between frames - calcCurrentPathSpacings( istart, iend ); + for(unsigned iter=0; iter( iend - istart ); + for(unsigned i=istart; i=sfrac[i])) ) { + k+=incr; + if( cfin==iend && k>= iend+1 ) plumed_merror("path reparameterization error"); + else if( cfin==(iend+1) && k>=iend ) { k=iend-1; break; } + else if( cfin==(iend-1) && k<=iend ) { k=iend+1; break; } + } + double dr = (sfrac[i]-sumlen[k])/len[k+incr]; + // Calculate the displacement between the appropriate points + // double dd = mypath[k]->calc( mypath[k+incr]->getReferencePositions(), pbc, args, mypath[k+incr]->getReferenceArguments(), mypack, true ); + // Copy the reference configuration from the configuration to a tempory direction + newpath[i].setDirection( mypath[k]->getReferencePositions(), mypath[k]->getReferenceArguments() ); + // Get the displacement of the path + mypath[k]->extractDisplacementVector( mypath[k+incr]->getReferencePositions(), args, mypath[k+incr]->getReferenceArguments(), false, false, mydir ); + // Set our direction equal to the displacement + // mydir.setDirection( mypack ); + // Shift the reference configuration by this ammount + newpath[i].displaceReferenceConfiguration( dr, mydir ); + } + + // Copy the positions of the new path to the new paths + for(int i=istart+incr; loopEnd(i,cfin,incr)==false; i+=incr) { + mypath[i]->setReferenceConfig( newpath[i].getReferencePositions(), newpath[i].getReferenceArguments(), mypath[i]->getReferenceMetric() ); + } + + // Recompute the separations between frames + calcCurrentPathSpacings( istart, iend ); } } -void PathReparameterization::reparameterize( const int& ifix1, const int& ifix2, const double& TOL ){ +void PathReparameterization::reparameterize( const int& ifix1, const int& ifix2, const double& TOL ) { plumed_dbg_assert( ifix10 ) reparameterizePart( ifix1, 0, target, TOL ); if( ifix2<(mypath.size()-1) ) reparameterizePart( ifix2, mypath.size()-1, target, TOL ); -// calcCurrentPathSpacings( 0, mypath.size()-1 ); +// calcCurrentPathSpacings( 0, mypath.size()-1 ); } } diff --git a/src/mapping/PathReparameterization.h b/src/mapping/PathReparameterization.h index dfbf61e62e..9a5a6c318f 100644 --- a/src/mapping/PathReparameterization.h +++ b/src/mapping/PathReparameterization.h @@ -55,7 +55,7 @@ class PathReparameterization { /// Reparameterize the frames of the path between istart and iend and make the spacing equal to target void reparameterizePart( const int& istart, const int& iend, const double& target, const double& TOL ); public: - PathReparameterization( const Pbc& ipbc, const std::vector& iargs, std::vector& pp ); + PathReparameterization( const Pbc& ipbc, const std::vector& iargs, std::vector& pp ); /// Reparameterize the frames of the path between istart and iend so as to make the spacing constant void reparameterize( const int& istart, const int& iend, const double& TOL ); }; diff --git a/src/mapping/PathTools.cpp b/src/mapping/PathTools.cpp index a4884b4fa9..abb9f7c5cc 100644 --- a/src/mapping/PathTools.cpp +++ b/src/mapping/PathTools.cpp @@ -35,30 +35,30 @@ using namespace std; namespace PLMD { -namespace mapping{ +namespace mapping { //+PLUMEDOC TOOLS pathtools /* pathtools can be used to construct paths from pdb data The path CVs in PLUMED are curvilinear coordinates through a high dimensional vector space. -Enhanced sampling calculations are ofen run using the progress along the paths and the distance from the path as CVs +Enhanced sampling calculations are ofen run using the progress along the paths and the distance from the path as CVs as this provides a convenient way of defining a reaction coordinate for a complicated process. This method is explained in the documentation for \ref PATH. The path itself is an ordered set of equally-spaced, high-dimensional frames the way in which these frames should be constructed will depend on the problem in hand. In other words, you will need to understand the reaction -you wish to study in order to select a sensible set of frames to use in your path CV. This tool provides two +you wish to study in order to select a sensible set of frames to use in your path CV. This tool provides two methods that may be useful when it comes to constructing paths; namely: - A tool that takes in an initial guess path in which the frames are not equally spaced. This tool adjusts the positions of the frames in order to make them equally spaced so that they can be used as the basis for a path CV. -- A tool that takes two frames as input and that allows you to return a linear path connecting these two frames. The -output from this method may be useful as an initial guess path. It is arguable that a linear path rather defeats the +- A tool that takes two frames as input and that allows you to return a linear path connecting these two frames. The +output from this method may be useful as an initial guess path. It is arguable that a linear path rather defeats the purpose of the path CV method, however, as the whole purpose is to be able to define non-linear paths. -Notice that you can use these two methods and take advantage of all the ways of measuring \ref dists that are available within +Notice that you can use these two methods and take advantage of all the ways of measuring \ref dists that are available within PLUMED. The way you do this with each of these tools described above is explained in the example below. \par Examples @@ -75,12 +75,12 @@ The example below shows how can create an initial linear path connecting the two end.pdb. In this case the path output to path.pdb will consist of 6 frames: the initial and final frames that were contained in start.pdb and end.pdb as well as four equally spaced frames along the vector connecting start.pdb to end.pdb. - + \verbatim plumed pathtools --start start.pdb --end end.pdb --nframes 4 --metric OPTIMAL --out path.pdb \endverbatim -Often the idea with path cvs is to create a path connecting some initial state A to some final state B. You would +Often the idea with path cvs is to create a path connecting some initial state A to some final state B. You would in this case have representative configurations from your A and B states defined in the input files to pathtools that we have called start.pdb and end.pdb in the example above. Furthermore, it may be useful to have a few frames before your start frame and after your end frame. You can use path tools to create these extended paths as shown below. @@ -93,7 +93,7 @@ plumed pathtools --start start.pdb --end end.pdb --nframes 4 --metric OPTIMAL -- \endverbatim Notice also that when you reparameterise paths you must choose two frames to fix. Generally you chose to fix the states -that are representative of your states A and B. By default pathtools will fix the first and last frames. You can, however, +that are representative of your states A and B. By default pathtools will fix the first and last frames. You can, however, change the states to fix by taking advantage of the fixed flag as shown below. \verbatim @@ -104,20 +104,20 @@ plumed pathtools --path inpath.pdb --metric EUCLIDEAN --out outpath.pdb --fixed //+ENDPLUMEDOC class PathTools : -public CLTool + public CLTool { public: static void registerKeywords( Keywords& keys ); explicit PathTools(const CLToolOptions& co ); int main(FILE* in, FILE*out,Communicator& pc); - string description()const{ + string description()const { return "print out a description of the keywords for an action in html"; } }; PLUMED_REGISTER_CLTOOL(PathTools,"pathtools") -void PathTools::registerKeywords( Keywords& keys ){ +void PathTools::registerKeywords( Keywords& keys ) { CLTool::registerKeywords( keys ); keys.add("atoms","--start","a pdb file that contains the structure for the initial frame of your path"); keys.add("atoms","--end","a pdb file that contains the structure for the final frame of your path"); @@ -133,160 +133,160 @@ void PathTools::registerKeywords( Keywords& keys ){ } PathTools::PathTools(const CLToolOptions& co ): -CLTool(co) + CLTool(co) { inputdata=commandline; } -int PathTools::main(FILE* in, FILE*out,Communicator& pc){ - - std::string mtype; parse("--metric",mtype); - std::string ifilename; parse("--path",ifilename); - std::string ofmt; parse("--arg-fmt",ofmt); - std::string ofilename; parse("--out",ofilename); - if( ifilename.length()>0 ){ - fprintf(out,"Reparameterising path in file named %s so that all frames are equally spaced \n",ifilename.c_str() ); - FILE* fp=fopen(ifilename.c_str(),"r"); - bool do_read=true; std::vector frames; - while (do_read) { - PDB mypdb; - // Read the pdb file - do_read=mypdb.readFromFilepointer(fp,false,0.1); - if( do_read ){ - ReferenceConfiguration* mymsd=metricRegister().create( mtype, mypdb ); - frames.push_back( mymsd ); mymsd->checkRead(); - } - } - std::vector fixed; parseVector("--fixed",fixed); - if( fixed.size()==1 ){ - if( fixed[0]!=0 ) error("input to --fixed should be two integers"); - fixed.resize(2); fixed[0]=0; fixed[1]=frames.size()-1; - } else if( fixed.size()==2 ){ - if( fixed[0]<0 || fixed[1]<0 || fixed[0]>(frames.size()-1) || fixed[1]>(frames.size()-1) ){ - error("input to --fixed should be two numbers between 0 and the number of frames-1"); - } - } else { - error("input to --fixed should be two integers"); - } - std::vector atoms; std::vector arg_names; - for(unsigned i=0;igetAtomRequests( atoms); - frames[i]->getArgumentRequests( arg_names ); - } - // Generate stuff to reparameterize - Pbc fake_pbc; std::vector vals; - for(unsigned i=0;igetNumberOfReferenceArguments();++i){ - vals.push_back(new Value()); vals[vals.size()-1]->setNotPeriodic(); - } - // And reparameterize - PathReparameterization myparam( fake_pbc, vals, frames ); - // And make all points equally spaced - double tol; parse("--tolerance",tol); myparam.reparameterize( fixed[0], fixed[1], tol ); - - // Ouput data on spacings - double mean=0; - MultiValue myvpack( 1, frames[0]->getNumberOfReferenceArguments() + 3*frames[0]->getNumberOfReferencePositions() + 9 ); - ReferenceValuePack mypack( frames[0]->getNumberOfReferenceArguments(), frames[0]->getNumberOfReferencePositions(), myvpack ); - for(unsigned i=1;icalc( frames[i-1]->getReferencePositions(), fake_pbc, vals, frames[i-1]->getReferenceArguments(), mypack, false ); - printf("FINAL DISTANCE BETWEEN FRAME %u AND %u IS %f \n",i-1,i,len ); - mean+=len; - } - printf("SUGGESTED LAMBDA PARAMETER IS THUS %f \n",2.3/mean/static_cast( frames.size()-1 ) ); - - // Delete all the frames - OFile ofile; ofile.open(ofilename); - for(unsigned i=0;iprint( ofile, ofmt, 10. ); delete frames[i]; } - // Delete the vals as we don't need them - for(unsigned i=0;i( mtype, mystartpdb ); - fclose(fp2); - - // Read final frame - std::string iend; parse("--end",iend); FILE* fp1=fopen(iend.c_str(),"r"); PDB myendpdb; - if( iend.length()==0 ) error("input is missing using --istart + --iend or --path"); - if( !myendpdb.readFromFilepointer(fp1,false,0.1) ) error("could not read fila " + iend); - ReferenceConfiguration* eframe=metricRegister().create( mtype, myendpdb ); - fclose(fp1); - - // Get atoms and arg requests - std::vector atoms; std::vector arg_names; - sframe->getAtomRequests( atoms); eframe->getAtomRequests( atoms); - sframe->getArgumentRequests( arg_names ); eframe->getArgumentRequests( arg_names ); - - // Now read in the rest of the instructions - unsigned nbefore, nbetween, nafter; - parse("--nframes-before-start",nbefore); parse("--nframes",nbetween); parse("--nframes-after-end",nafter); - nbetween++; - fprintf(out,"Generating linear path connecting structure in file named %s to structure in file named %s \n",istart.c_str(),iend.c_str() ); - fprintf(out,"A path consisting of %u equally-spaced frames before the initial structure, %u frames between the intial and final structures " - "and %u frames after the final structure will be created \n",nbefore,nbetween,nafter); - - // Create a vector of arguments to use for calculating displacements - Pbc fpbc; std::vector args; - for(unsigned i=0;igetNumberOfReferenceArguments();++i){ - args.push_back(new Value()); args[args.size()-1]->setNotPeriodic(); - } - - // Calculate the distance between the start and the end - MultiValue myvpack( 1, sframe->getNumberOfReferenceArguments() + 3*sframe->getNumberOfReferencePositions() + 9); - ReferenceValuePack mypack( sframe->getNumberOfReferenceArguments(), sframe->getNumberOfReferencePositions(), myvpack ); - double pathlen = sframe->calc( eframe->getReferencePositions(), fpbc, args, eframe->getReferenceArguments(), mypack, false ); - // And the spacing between frames - double delr = 1.0 / static_cast( nbetween ); - // Calculate the vector connecting the start to the end - Direction mydir(ReferenceConfigurationOptions("DIRECTION")); sframe->setupPCAStorage( mypack ); - mydir.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); mydir.zeroDirection(); - sframe->extractDisplacementVector( eframe->getReferencePositions(), args, eframe->getReferenceArguments(), false, false, mydir ); - - - // Now create frames - std::vector final_path; - Direction pos(ReferenceConfigurationOptions("DIRECTION")); - pos.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); - for(int i=0;i0 ) { + fprintf(out,"Reparameterising path in file named %s so that all frames are equally spaced \n",ifilename.c_str() ); + FILE* fp=fopen(ifilename.c_str(),"r"); + bool do_read=true; std::vector frames; + while (do_read) { + PDB mypdb; + // Read the pdb file + do_read=mypdb.readFromFilepointer(fp,false,0.1); + if( do_read ) { + ReferenceConfiguration* mymsd=metricRegister().create( mtype, mypdb ); + frames.push_back( mymsd ); mymsd->checkRead(); + } + } + std::vector fixed; parseVector("--fixed",fixed); + if( fixed.size()==1 ) { + if( fixed[0]!=0 ) error("input to --fixed should be two integers"); + fixed.resize(2); fixed[0]=0; fixed[1]=frames.size()-1; + } else if( fixed.size()==2 ) { + if( fixed[0]<0 || fixed[1]<0 || fixed[0]>(frames.size()-1) || fixed[1]>(frames.size()-1) ) { + error("input to --fixed should be two numbers between 0 and the number of frames-1"); + } + } else { + error("input to --fixed should be two integers"); + } + std::vector atoms; std::vector arg_names; + for(unsigned i=0; igetAtomRequests( atoms); + frames[i]->getArgumentRequests( arg_names ); + } + // Generate stuff to reparameterize + Pbc fake_pbc; std::vector vals; + for(unsigned i=0; igetNumberOfReferenceArguments(); ++i) { + vals.push_back(new Value()); vals[vals.size()-1]->setNotPeriodic(); + } + // And reparameterize + PathReparameterization myparam( fake_pbc, vals, frames ); + // And make all points equally spaced + double tol; parse("--tolerance",tol); myparam.reparameterize( fixed[0], fixed[1], tol ); + + // Ouput data on spacings + double mean=0; + MultiValue myvpack( 1, frames[0]->getNumberOfReferenceArguments() + 3*frames[0]->getNumberOfReferencePositions() + 9 ); + ReferenceValuePack mypack( frames[0]->getNumberOfReferenceArguments(), frames[0]->getNumberOfReferencePositions(), myvpack ); + for(unsigned i=1; icalc( frames[i-1]->getReferencePositions(), fake_pbc, vals, frames[i-1]->getReferenceArguments(), mypack, false ); + printf("FINAL DISTANCE BETWEEN FRAME %u AND %u IS %f \n",i-1,i,len ); + mean+=len; + } + printf("SUGGESTED LAMBDA PARAMETER IS THUS %f \n",2.3/mean/static_cast( frames.size()-1 ) ); + + // Delete all the frames + OFile ofile; ofile.open(ofilename); + for(unsigned i=0; iprint( ofile, ofmt, 10. ); delete frames[i]; } + // Delete the vals as we don't need them + for(unsigned i=0; i( mtype, mystartpdb ); + fclose(fp2); + +// Read final frame + std::string iend; parse("--end",iend); FILE* fp1=fopen(iend.c_str(),"r"); PDB myendpdb; + if( iend.length()==0 ) error("input is missing using --istart + --iend or --path"); + if( !myendpdb.readFromFilepointer(fp1,false,0.1) ) error("could not read fila " + iend); + ReferenceConfiguration* eframe=metricRegister().create( mtype, myendpdb ); + fclose(fp1); + +// Get atoms and arg requests + std::vector atoms; std::vector arg_names; + sframe->getAtomRequests( atoms); eframe->getAtomRequests( atoms); + sframe->getArgumentRequests( arg_names ); eframe->getArgumentRequests( arg_names ); + +// Now read in the rest of the instructions + unsigned nbefore, nbetween, nafter; + parse("--nframes-before-start",nbefore); parse("--nframes",nbetween); parse("--nframes-after-end",nafter); + nbetween++; + fprintf(out,"Generating linear path connecting structure in file named %s to structure in file named %s \n",istart.c_str(),iend.c_str() ); + fprintf(out,"A path consisting of %u equally-spaced frames before the initial structure, %u frames between the intial and final structures " + "and %u frames after the final structure will be created \n",nbefore,nbetween,nafter); + +// Create a vector of arguments to use for calculating displacements + Pbc fpbc; std::vector args; + for(unsigned i=0; igetNumberOfReferenceArguments(); ++i) { + args.push_back(new Value()); args[args.size()-1]->setNotPeriodic(); + } + +// Calculate the distance between the start and the end + MultiValue myvpack( 1, sframe->getNumberOfReferenceArguments() + 3*sframe->getNumberOfReferencePositions() + 9); + ReferenceValuePack mypack( sframe->getNumberOfReferenceArguments(), sframe->getNumberOfReferencePositions(), myvpack ); + double pathlen = sframe->calc( eframe->getReferencePositions(), fpbc, args, eframe->getReferenceArguments(), mypack, false ); +// And the spacing between frames + double delr = 1.0 / static_cast( nbetween ); +// Calculate the vector connecting the start to the end + Direction mydir(ReferenceConfigurationOptions("DIRECTION")); sframe->setupPCAStorage( mypack ); + mydir.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); mydir.zeroDirection(); + sframe->extractDisplacementVector( eframe->getReferencePositions(), args, eframe->getReferenceArguments(), false, false, mydir ); + + +// Now create frames + std::vector final_path; + Direction pos(ReferenceConfigurationOptions("DIRECTION")); + pos.setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); + for(int i=0; igetReferencePositions(), sframe->getReferenceArguments() ); - pos.displaceReferenceConfiguration( -i*delr, mydir ); - final_path.push_back( metricRegister().create(mtype) ); + pos.displaceReferenceConfiguration( -i*delr, mydir ); + final_path.push_back( metricRegister().create(mtype) ); final_path[final_path.size()-1]->setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); final_path[final_path.size()-1]->setReferenceConfig( pos.getReferencePositions(), pos.getReferenceArguments(), sframe->getReferenceMetric() ); - } - for(unsigned i=1;igetReferencePositions(), sframe->getReferenceArguments() ); pos.displaceReferenceConfiguration( i*delr, mydir ); - final_path.push_back( metricRegister().create(mtype) ); + final_path.push_back( metricRegister().create(mtype) ); final_path[final_path.size()-1]->setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); final_path[final_path.size()-1]->setReferenceConfig( pos.getReferencePositions(), pos.getReferenceArguments(), sframe->getReferenceMetric() ); - } - for(unsigned i=0;igetReferencePositions(), eframe->getReferenceArguments() ); pos.displaceReferenceConfiguration( i*delr, mydir ); final_path.push_back( metricRegister().create(mtype) ); final_path[final_path.size()-1]->setNamesAndAtomNumbers( sframe->getAbsoluteIndexes(), sframe->getArgumentNames() ); final_path[final_path.size()-1]->setReferenceConfig( pos.getReferencePositions(), pos.getReferenceArguments(), sframe->getReferenceMetric() ); - } + } - double mean=0; printf("DISTANCE BETWEEN ORIGINAL FRAMES %f \n",pathlen); - for(unsigned i=1;icalc( final_path[i-1]->getReferencePositions(), fpbc, args, final_path[i-1]->getReferenceArguments(), mypack, false ); printf("FINAL DISTANCE BETWEEN FRAME %u AND %u IS %f \n",i-1,i,len ); mean+=len; - } - printf("SUGGESTED LAMBDA PARAMETER IS THUS %f \n",2.3/mean/static_cast( final_path.size()-1 ) ); - - OFile ofile; ofile.open(ofilename); - for(unsigned i=0;iprint( ofile, ofmt, 10. ); delete final_path[i]; } - // Delete the args as we don't need them anymore - for(unsigned i=0;i( final_path.size()-1 ) ); + + OFile ofile; ofile.open(ofilename); + for(unsigned i=0; iprint( ofile, ofmt, 10. ); delete final_path[i]; } +// Delete the args as we don't need them anymore + for(unsigned i=0; i( getAction() ); plumed_massert( mymap, "SpathVessel can only be used with mappings"); // Retrieve the index of the property in the underlying mapping - mycoordnumber=mymap->getPropertyIndex( getLabel() ); - usetol=true; norm=true; + mycoordnumber=mymap->getPropertyIndex( getLabel() ); + usetol=true; norm=true; - for(unsigned i=0;igetFullNumberOfTasks();++i){ - if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) { + if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); } } -std::string SpathVessel::value_descriptor(){ +std::string SpathVessel::value_descriptor() { return "the position on the path"; } -void SpathVessel::prepare(){ +void SpathVessel::prepare() { foundoneclose=false; } @@ -78,10 +78,10 @@ void SpathVessel::calculate( const unsigned& current, MultiValue& myvals, std::v double pp=mymap->getPropertyValue( current, mycoordnumber ), weight=myvals.get(0); if( weightgetNumberOfDerivatives(); - buffer[bufstart] += weight*pp; buffer[bufstart+1+nderivatives] += weight; - if( getAction()->derivativesAreRequired() ){ - myvals.chainRule( 0, 0, 1, 0, pp, bufstart, buffer ); - myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); + buffer[bufstart] += weight*pp; buffer[bufstart+1+nderivatives] += weight; + if( getAction()->derivativesAreRequired() ) { + myvals.chainRule( 0, 0, 1, 0, pp, bufstart, buffer ); + myvals.chainRule( 0, 1, 1, 0, 1.0, bufstart, buffer ); } } diff --git a/src/mapping/TrigonometricPathVessel.cpp b/src/mapping/TrigonometricPathVessel.cpp index 920a792e8e..adf049b708 100644 --- a/src/mapping/TrigonometricPathVessel.cpp +++ b/src/mapping/TrigonometricPathVessel.cpp @@ -27,193 +27,193 @@ namespace mapping { PLUMED_REGISTER_VESSEL(TrigonometricPathVessel,"GPATH") -void TrigonometricPathVessel::registerKeywords( Keywords& keys ){ +void TrigonometricPathVessel::registerKeywords( Keywords& keys ) { StoreDataVessel::registerKeywords(keys); } -void TrigonometricPathVessel::reserveKeyword( Keywords& keys ){ +void TrigonometricPathVessel::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","GPATH","calculate the position on the path using trigonometry"); keys.addOutputComponent("gspath","GPATH","the position on the path calculated using trigonometry"); keys.addOutputComponent("gzpath","GPATH","the distance from the path calculated using trigonometry"); } TrigonometricPathVessel::TrigonometricPathVessel( const vesselbase::VesselOptions& da ): -StoreDataVessel(da), -projdir(ReferenceConfigurationOptions("DIRECTION")), -mydpack1( 1, getAction()->getNumberOfDerivatives() ), -mydpack2( 1, getAction()->getNumberOfDerivatives() ), -mydpack3( 1, getAction()->getNumberOfDerivatives() ), -mypack1( 0, 0, mydpack1 ), -mypack2( 0, 0, mydpack2 ), -mypack3( 0, 0, mydpack3 ) + StoreDataVessel(da), + projdir(ReferenceConfigurationOptions("DIRECTION")), + mydpack1( 1, getAction()->getNumberOfDerivatives() ), + mydpack2( 1, getAction()->getNumberOfDerivatives() ), + mydpack3( 1, getAction()->getNumberOfDerivatives() ), + mypack1( 0, 0, mydpack1 ), + mypack2( 0, 0, mydpack2 ), + mypack3( 0, 0, mydpack3 ) { mymap=dynamic_cast( getAction() ); plumed_massert( mymap, "Trigonometric path vessel can only be used with mappings"); // Retrieve the index of the property in the underlying mapping if( mymap->getNumberOfProperties()!=1 ) error("cannot use trigonometric paths when there are multiple properties"); - for(unsigned i=0;igetFullNumberOfTasks();++i){ - if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) { + if( mymap->getTaskCode(i)!=mymap->getPositionInFullTaskList(i) ) error("mismatched tasks and codes"); } - mymap->addComponentWithDerivatives("gspath"); mymap->componentIsNotPeriodic("gspath"); + mymap->addComponentWithDerivatives("gspath"); mymap->componentIsNotPeriodic("gspath"); sp=mymap->copyOutput( mymap->getNumberOfComponents()-1 ); sp->resizeDerivatives( mymap->getNumberOfDerivatives() ); - mymap->addComponentWithDerivatives("gzpath"); mymap->componentIsNotPeriodic("gzpath"); + mymap->addComponentWithDerivatives("gzpath"); mymap->componentIsNotPeriodic("gzpath"); zp=mymap->copyOutput( mymap->getNumberOfComponents()-1 ); zp->resizeDerivatives( mymap->getNumberOfDerivatives() ); // Check we have PCA - ReferenceConfiguration* ref0=mymap->getReferenceConfiguration(0); - for(unsigned i=0;igetFullNumberOfTasks();++i){ - if( !(mymap->getReferenceConfiguration(i))->pcaIsEnabledForThisReference() ) error("pca must be implemented in order to use trigometric path"); - if( ref0->getName()!=(mymap->getReferenceConfiguration(i))->getName() ) error("cannot use mixed metrics"); - if( mymap->getNumberOfAtoms()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferencePositions() ) error("all frames must use the same set of atoms"); - if( mymap->getNumberOfArguments()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferenceArguments() ) error("all frames must use the same set of arguments"); + ReferenceConfiguration* ref0=mymap->getReferenceConfiguration(0); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) { + if( !(mymap->getReferenceConfiguration(i))->pcaIsEnabledForThisReference() ) error("pca must be implemented in order to use trigometric path"); + if( ref0->getName()!=(mymap->getReferenceConfiguration(i))->getName() ) error("cannot use mixed metrics"); + if( mymap->getNumberOfAtoms()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferencePositions() ) error("all frames must use the same set of atoms"); + if( mymap->getNumberOfArguments()!=(mymap->getReferenceConfiguration(i))->getNumberOfReferenceArguments() ) error("all frames must use the same set of arguments"); } cargs.resize( mymap->getNumberOfArguments() ); std::vector argument_names( mymap->getNumberOfArguments() ); - for(unsigned i=0;igetNumberOfArguments();++i) argument_names[i] = (mymap->getPntrToArgument(i))->getName(); + for(unsigned i=0; igetNumberOfArguments(); ++i) argument_names[i] = (mymap->getPntrToArgument(i))->getName(); projdir.setNamesAndAtomNumbers( mymap->getAbsoluteIndexes(), argument_names ); mypack1.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); ref0->setupPCAStorage( mypack1 ); mypack2.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); ref0->setupPCAStorage( mypack2 ); - mypack3.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); - for(unsigned i=0;igetNumberOfAtoms();++i){ mypack1.setAtomIndex(i,i); mypack2.setAtomIndex(i,i); mypack3.setAtomIndex(i,i); } + mypack3.resize( mymap->getNumberOfArguments(), mymap->getNumberOfAtoms() ); + for(unsigned i=0; igetNumberOfAtoms(); ++i) { mypack1.setAtomIndex(i,i); mypack2.setAtomIndex(i,i); mypack3.setAtomIndex(i,i); } mypack1_stashd_atoms.resize( mymap->getNumberOfAtoms() ); mypack1_stashd_args.resize( mymap->getNumberOfArguments() ); } -std::string TrigonometricPathVessel::description(){ - return "values gspath and gzpath contain the position on and distance from the path calculated using trigonometry"; +std::string TrigonometricPathVessel::description() { + return "values gspath and gzpath contain the position on and distance from the path calculated using trigonometry"; } -void TrigonometricPathVessel::resize(){ +void TrigonometricPathVessel::resize() { StoreDataVessel::resize(); - if( getAction()->derivativesAreRequired() ){ + if( getAction()->derivativesAreRequired() ) { unsigned nderivatives=getAction()->getNumberOfDerivatives(); sp->resizeDerivatives( nderivatives ); zp->resizeDerivatives( nderivatives ); } } -void TrigonometricPathVessel::finish( const std::vector& buffer ){ +void TrigonometricPathVessel::finish( const std::vector& buffer ) { // Store the data calculated during mpi loop StoreDataVessel::finish( buffer ); - // Get current value of all arguments - for(unsigned i=0;igetArgument(i); + // Get current value of all arguments + for(unsigned i=0; igetArgument(i); // Determine closest and second closest point to current position double lambda=mymap->getLambda(); std::vector dist( getNumberOfComponents() ), dist2( getNumberOfComponents() );; - retrieveSequentialValue( 0, false, dist ); + retrieveSequentialValue( 0, false, dist ); retrieveSequentialValue( 1, false, dist2 ); iclose1=getStoreIndex(0); iclose2=getStoreIndex(1); - double mindist1=dist[0], mindist2=dist2[0]; - if( lambda>0.0 ){ - mindist1=-std::log( dist[0] ) / lambda; - mindist2=-std::log( dist2[0] ) / lambda; + double mindist1=dist[0], mindist2=dist2[0]; + if( lambda>0.0 ) { + mindist1=-std::log( dist[0] ) / lambda; + mindist2=-std::log( dist2[0] ) / lambda; } - if( mindist20.0 ) ndist=-std::log( dist[0] ) / lambda; - if( ndist0.0 ) ndist=-std::log( dist[0] ) / lambda; + if( ndist1 ) isign=1; else if( isign<-1 ) isign=-1; int iclose3 = iclose1 + isign; double v2v2; - // We now have to compute vectors connecting the three closest points to the + // We now have to compute vectors connecting the three closest points to the // new point double v1v1 = (mymap->getReferenceConfiguration( iclose1 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack1, true ); - double v3v3 = (mymap->getReferenceConfiguration( iclose2 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack3, true ); - if( iclose3<0 || iclose3>=mymap->getFullNumberOfTasks() ){ - ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); - v2v2=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), - conf2->getReferenceArguments(), mypack2, true ); - (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), - conf2->getReferenceArguments(), true, false, projdir ); + double v3v3 = (mymap->getReferenceConfiguration( iclose2 ))->calculate( mymap->getPositions(), mymap->getPbc(), mymap->getArguments(), mypack3, true ); + if( iclose3<0 || iclose3>=mymap->getFullNumberOfTasks() ) { + ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); + v2v2=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), + conf2->getReferenceArguments(), mypack2, true ); + (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), + conf2->getReferenceArguments(), true, false, projdir ); } else { - ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose3 ); - v2v2=(mymap->getReferenceConfiguration( iclose1 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), - conf2->getReferenceArguments(), mypack2, true ); - (mymap->getReferenceConfiguration( iclose1 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), - conf2->getReferenceArguments(), true, false, projdir ); + ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose3 ); + v2v2=(mymap->getReferenceConfiguration( iclose1 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), + conf2->getReferenceArguments(), mypack2, true ); + (mymap->getReferenceConfiguration( iclose1 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), + conf2->getReferenceArguments(), true, false, projdir ); } // Stash derivatives of v1v1 - for(unsigned i=0;igetNumberOfArguments();++i) mypack1_stashd_args[i]=mypack1.getArgumentDerivative(i); - for(unsigned i=0;igetNumberOfAtoms();++i) mypack1_stashd_atoms[i]=mypack1.getAtomDerivative(i); + for(unsigned i=0; igetNumberOfArguments(); ++i) mypack1_stashd_args[i]=mypack1.getArgumentDerivative(i); + for(unsigned i=0; igetNumberOfAtoms(); ++i) mypack1_stashd_atoms[i]=mypack1.getAtomDerivative(i); // Calculate the dot product of v1 with v2 double v1v2 = (mymap->getReferenceConfiguration(iclose1))->projectDisplacementOnVector( projdir, mymap->getPositions(), mymap->getArguments(), cargs, mypack1 ); - + // This computes s value double spacing = mymap->getPropertyValue( iclose1, 0 ) - mymap->getPropertyValue( iclose2, 0 ); double root = sqrt( v1v2*v1v2 - v2v2 * ( v1v1 - v3v3) ); dx = 0.5 * ( (root + v1v2) / v2v2 - 1.); - double path_s = mymap->getPropertyValue(iclose1, 0) + spacing * dx; sp->set( path_s ); - double fact = 0.25*spacing / v2v2; + double path_s = mymap->getPropertyValue(iclose1, 0) + spacing * dx; sp->set( path_s ); + double fact = 0.25*spacing / v2v2; // Derivative of s wrt arguments - for(unsigned i=0;igetNumberOfArguments();++i){ - sp->setDerivative( i, fact*( mypack2.getArgumentDerivative(i) + (v2v2 * (-mypack1_stashd_args[i] + mypack3.getArgumentDerivative(i)) + for(unsigned i=0; igetNumberOfArguments(); ++i) { + sp->setDerivative( i, fact*( mypack2.getArgumentDerivative(i) + (v2v2 * (-mypack1_stashd_args[i] + mypack3.getArgumentDerivative(i)) + v1v2*mypack2.getArgumentDerivative(i) )/root ) ); } // Derivative of s wrt atoms unsigned narg=mymap->getNumberOfArguments(); Tensor vir; vir.zero(); fact = 0.5*spacing / v2v2; - if( mymap->getNumberOfAtoms()>0 ){ - for(unsigned i=0;igetNumberOfAtoms();++i){ - Vector ader = fact*(( v1v2*mypack1.getAtomDerivative(i) + 0.5*v2v2*(-mypack1_stashd_atoms[i] + mypack3.getAtomDerivative(i) ) )/root + mypack1.getAtomDerivative(i) ); - for(unsigned k=0;k<3;++k) sp->setDerivative( narg+3*i+k, ader[k] ); - vir-=Tensor( mymap->getPosition(i), ader ); - } - // Set the virial - unsigned nbase=narg+3*mymap->getNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) sp->setDerivative( nbase+3*i+j, vir(i,j) ); + if( mymap->getNumberOfAtoms()>0 ) { + for(unsigned i=0; igetNumberOfAtoms(); ++i) { + Vector ader = fact*(( v1v2*mypack1.getAtomDerivative(i) + 0.5*v2v2*(-mypack1_stashd_atoms[i] + mypack3.getAtomDerivative(i) ) )/root + mypack1.getAtomDerivative(i) ); + for(unsigned k=0; k<3; ++k) sp->setDerivative( narg+3*i+k, ader[k] ); + vir-=Tensor( mymap->getPosition(i), ader ); + } + // Set the virial + unsigned nbase=narg+3*mymap->getNumberOfAtoms(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) sp->setDerivative( nbase+3*i+j, vir(i,j) ); } // Now compute z value ReferenceConfiguration* conf2=mymap->getReferenceConfiguration( iclose1 ); - double v4v4=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), - conf2->getReferenceArguments(), mypack2, true ); + double v4v4=(mymap->getReferenceConfiguration( iclose2 ))->calc( conf2->getReferencePositions(), mymap->getPbc(), mymap->getArguments(), + conf2->getReferenceArguments(), mypack2, true ); // Extract vector connecting frames (mymap->getReferenceConfiguration( iclose2 ))->extractDisplacementVector( conf2->getReferencePositions(), mymap->getArguments(), - conf2->getReferenceArguments(), true, false, projdir ); + conf2->getReferenceArguments(), true, false, projdir ); // Calculate projection of vector on line connnecting frames double proj = (mymap->getReferenceConfiguration(iclose1))->projectDisplacementOnVector( projdir, mymap->getPositions(), mymap->getArguments(), cargs, mypack1 ); - double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; + double path_z = v1v1 + dx*dx*v4v4 - 2*dx*proj; - // Derivatives for z path - path_z = sqrt(path_z); zp->set( path_z ); vir.zero(); - for(unsigned i=0;igetNumberOfArguments();++i) zp->setDerivative( i, (mypack1_stashd_args[i] - 2*dx*mypack1.getArgumentDerivative(i))/(2.0*path_z) ); + // Derivatives for z path + path_z = sqrt(path_z); zp->set( path_z ); vir.zero(); + for(unsigned i=0; igetNumberOfArguments(); ++i) zp->setDerivative( i, (mypack1_stashd_args[i] - 2*dx*mypack1.getArgumentDerivative(i))/(2.0*path_z) ); // Derivative wrt atoms - if( mymap->getNumberOfAtoms()>0 ){ - for(unsigned i=0;igetNumberOfAtoms();++i){ - Vector dxder; for(unsigned k=0;k<3;++k) dxder[k] = ( 2*v4v4*dx - 2*proj )*spacing*sp->getDerivative( narg + 3*i+k ); - Vector ader = ( mypack1_stashd_atoms[i] - 2.*dx*mypack1.getAtomDerivative(i) + dxder )/ (2.0*path_z); - for(unsigned k=0;k<3;++k) zp->setDerivative( narg+3*i+k, ader[k] ); - vir-=Tensor( mymap->getPosition(i), ader ); - } - // Set the virial - unsigned nbase=narg+3*mymap->getNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) zp->setDerivative( nbase+3*i+j, vir(i,j) ); + if( mymap->getNumberOfAtoms()>0 ) { + for(unsigned i=0; igetNumberOfAtoms(); ++i) { + Vector dxder; for(unsigned k=0; k<3; ++k) dxder[k] = ( 2*v4v4*dx - 2*proj )*spacing*sp->getDerivative( narg + 3*i+k ); + Vector ader = ( mypack1_stashd_atoms[i] - 2.*dx*mypack1.getAtomDerivative(i) + dxder )/ (2.0*path_z); + for(unsigned k=0; k<3; ++k) zp->setDerivative( narg+3*i+k, ader[k] ); + vir-=Tensor( mymap->getPosition(i), ader ); + } + // Set the virial + unsigned nbase=narg+3*mymap->getNumberOfAtoms(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) zp->setDerivative( nbase+3*i+j, vir(i,j) ); } } -bool TrigonometricPathVessel::applyForce( std::vector& forces ){ - std::vector tmpforce( forces.size(), 0.0 ); - forces.assign(forces.size(),0.0); bool wasforced=false; - if( sp->applyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;j& forces ) { + std::vector tmpforce( forces.size(), 0.0 ); + forces.assign(forces.size(),0.0); bool wasforced=false; + if( sp->applyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; japplyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; j( getAction() ); plumed_massert( mymap, "ZpathVessel should only be used with mappings"); invlambda = 1.0 / mymap->getLambda(); usetol=true; } -std::string ZpathVessel::value_descriptor(){ +std::string ZpathVessel::value_descriptor() { return "the distance from the low-dimensional manifold"; } @@ -65,10 +65,10 @@ double ZpathVessel::calcTransform( const double& val, double& dv ) const { dv=0.0; return 1.0; } -double ZpathVessel::finalTransform( const double& val, double& dv ){ - dv = -invlambda / val; - return -invlambda*std::log( val ); -} +double ZpathVessel::finalTransform( const double& val, double& dv ) { + dv = -invlambda / val; + return -invlambda*std::log( val ); +} } } diff --git a/src/multicolvar/ActionVolume.cpp b/src/multicolvar/ActionVolume.cpp index d490ef31d9..5f12881e13 100644 --- a/src/multicolvar/ActionVolume.cpp +++ b/src/multicolvar/ActionVolume.cpp @@ -24,7 +24,7 @@ namespace PLMD { namespace multicolvar { -void ActionVolume::registerKeywords( Keywords& keys ){ +void ActionVolume::registerKeywords( Keywords& keys ) { VolumeGradientBase::registerKeywords( keys ); if( keys.reserved("VMEAN") ) keys.use("VMEAN"); keys.use("MEAN"); keys.use("LESS_THAN"); keys.use("MORE_THAN"); @@ -35,39 +35,39 @@ void ActionVolume::registerKeywords( Keywords& keys ){ } ActionVolume::ActionVolume(const ActionOptions&ao): -Action(ao), -VolumeGradientBase(ao) + Action(ao), + VolumeGradientBase(ao) { // Find number of quantities - if( getPntrToMultiColvar()->isDensity() ) nquantities=2; // Value + weight + if( getPntrToMultiColvar()->isDensity() ) nquantities=2; // Value + weight else if( getPntrToMultiColvar()->getNumberOfQuantities()==2 ) nquantities=2; // Value + weight - else nquantities = 1 + getPntrToMultiColvar()->getNumberOfQuantities()-2 + 1; // Norm + vector + weight + else nquantities = 1 + getPntrToMultiColvar()->getNumberOfQuantities()-2 + 1; // Norm + vector + weight // Output some nice information std::string functype=getPntrToMultiColvar()->getName(); std::transform( functype.begin(), functype.end(), functype.begin(), tolower ); - log.printf(" calculating %s inside region of insterest\n",functype.c_str() ); + log.printf(" calculating %s inside region of insterest\n",functype.c_str() ); parseFlag("OUTSIDE",not_in); sigma=0.0; - if( keywords.exists("SIGMA") ) parse("SIGMA",sigma); - if( keywords.exists("KERNEL") ) parse("KERNEL",kerneltype); - - if( getPntrToMultiColvar()->isDensity() ){ - std::string input; - addVessel( "SUM", input, -1 ); // -1 here means that this value will be named getLabel() - } + if( keywords.exists("SIGMA") ) parse("SIGMA",sigma); + if( keywords.exists("KERNEL") ) parse("KERNEL",kerneltype); + + if( getPntrToMultiColvar()->isDensity() ) { + std::string input; + addVessel( "SUM", input, -1 ); // -1 here means that this value will be named getLabel() + } readVesselKeywords(); } void ActionVolume::calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const { Vector catom_pos=getPntrToMultiColvar()->getCentralAtomPos( curr ); - double weight; Vector wdf; Tensor vir; std::vector refders( getNumberOfAtoms() ); - weight=calculateNumberInside( catom_pos, wdf, vir, refders ); - if( not_in ){ - weight = 1.0 - weight; wdf *= -1.; vir *=-1; - for(unsigned i=0;i refders( getNumberOfAtoms() ); + weight=calculateNumberInside( catom_pos, wdf, vir, refders ); + if( not_in ) { + weight = 1.0 - weight; wdf *= -1.; vir *=-1; + for(unsigned i=0; i all_atoms; @@ -129,28 +129,28 @@ MultiColvarBase(ao) // Resize target target.resize( getFullNumberOfTasks() ); // Setup central atom indices - std::vector catom_ind(4, false); + std::vector catom_ind(4, false); catom_ind[1]=catom_ind[2]=true; setAtomsForCentralAtom( catom_ind ); // Read in reference values unsigned ntarget=0; - for(unsigned i=0;i0 ){ + if( sfinput.length()>0 ) { + use_sf=true; + weightHasDerivatives=true; + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + sf2.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); + } else { + parse("SWITCHA",sfinput); + if(sfinput.length()>0) { use_sf=true; weightHasDerivatives=true; sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); + sfinput.clear(); parse("SWITCHB",sfinput); + if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); - } else { - parse("SWITCHA",sfinput); - if(sfinput.length()>0){ - use_sf=true; - weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); - sfinput.clear(); parse("SWITCHB",sfinput); - if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); - sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); - log.printf(" only calculating angles when the distance between GROUPA and GROUPB atoms is less than %s\n", sf1.description().c_str() ); - log.printf(" only calculating angles when the distance between GROUPA and GROUPC atoms is less than %s\n", sf2.description().c_str() ); - } + if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); + log.printf(" only calculating angles when the distance between GROUPA and GROUPB atoms is less than %s\n", sf1.description().c_str() ); + log.printf(" only calculating angles when the distance between GROUPA and GROUPC atoms is less than %s\n", sf2.description().c_str() ); + } } // Read in the atoms std::vector all_atoms; readGroupKeywords( "GROUP", "GROUPA", "GROUPB", "GROUPC", false, true, all_atoms ); if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 3, all_atoms ); setupMultiColvarBase( all_atoms ); - // Set cutoff for link cells - if( use_sf ){ - setLinkCellCutoff( sf1.get_dmax() ); - rcut2_1=sf1.get_dmax()*sf1.get_dmax(); - rcut2_2=sf2.get_dmax()*sf2.get_dmax(); + // Set cutoff for link cells + if( use_sf ) { + setLinkCellCutoff( sf1.get_dmax() ); + rcut2_1=sf1.get_dmax()*sf1.get_dmax(); + rcut2_2=sf2.get_dmax()*sf2.get_dmax(); } // And check everything has been read in correctly @@ -180,23 +180,23 @@ use_sf(false) } double Angles::calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& myatoms ) const { - if(!use_sf) return 1.0; + if(!use_sf) return 1.0; Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) ); Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double w1, w2, dw1, dw2, wtot; - double ldij = dij.modulo2(), ldik = dik.modulo2(); + double ldij = dij.modulo2(), ldik = dik.modulo2(); - if( use_sf ){ - if( ldij>rcut2_1 || ldik>rcut2_2 ) return 0.0; + if( use_sf ) { + if( ldij>rcut2_1 || ldik>rcut2_2 ) return 0.0; } w1=sf1.calculateSqr( ldij, dw1 ); w2=sf2.calculateSqr( ldik, dw2 ); - wtot=w1*w2; dw1*=weight*w2; dw2*=weight*w1; + wtot=w1*w2; dw1*=weight*w2; dw2*=weight*w1; addAtomDerivatives( 0, 1, dw2*dik, myatoms ); - addAtomDerivatives( 0, 0, -dw1*dij - dw2*dik, myatoms ); + addAtomDerivatives( 0, 0, -dw1*dij - dw2*dik, myatoms ); addAtomDerivatives( 0, 2, dw1*dij, myatoms ); myatoms.addBoxDerivatives( 0, (-dw1)*Tensor(dij,dij) + (-dw2)*Tensor(dik,dik) ); return wtot; @@ -206,7 +206,7 @@ double Angles::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { Vector dij=getSeparation( myatoms.getPosition(0), myatoms.getPosition(2) ); Vector dik=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - Vector ddij,ddik; PLMD::Angle a; + Vector ddij,ddik; PLMD::Angle a; double angle=a.compute(dij,dik,ddij,ddik); // And finish the calculation diff --git a/src/multicolvar/AtomValuePack.cpp b/src/multicolvar/AtomValuePack.cpp index 6126aa4cb3..99a52a8fb5 100644 --- a/src/multicolvar/AtomValuePack.cpp +++ b/src/multicolvar/AtomValuePack.cpp @@ -27,67 +27,67 @@ namespace PLMD { namespace multicolvar { AtomValuePack::AtomValuePack( MultiValue& vals, MultiColvarBase const * mcolv ): -myvals(vals), -mycolv(mcolv), -natoms(0), -indices( vals.getIndices() ), -sort_vector( vals.getSortIndices() ), -myatoms( vals.getAtomVector() ) + myvals(vals), + mycolv(mcolv), + natoms(0), + indices( vals.getIndices() ), + sort_vector( vals.getSortIndices() ), + myatoms( vals.getAtomVector() ) { - if( indices.size()!=mcolv->getNumberOfAtoms() ){ - indices.resize( mcolv->getNumberOfAtoms() ); - sort_vector.resize( mcolv->getNumberOfAtoms() ); + if( indices.size()!=mcolv->getNumberOfAtoms() ) { + indices.resize( mcolv->getNumberOfAtoms() ); + sort_vector.resize( mcolv->getNumberOfAtoms() ); myatoms.resize( mcolv->getNumberOfAtoms() ); } } -unsigned AtomValuePack::setupAtomsFromLinkCells( const std::vector& cind, const Vector& cpos, const LinkCells& linkcells ){ - natoms=cind.size(); for(unsigned i=0;igetPositionOfAtomForLinkCells( indices[i] ) - cpos; +unsigned AtomValuePack::setupAtomsFromLinkCells( const std::vector& cind, const Vector& cpos, const LinkCells& linkcells ) { + natoms=cind.size(); for(unsigned i=0; igetPositionOfAtomForLinkCells( indices[i] ) - cpos; if( mycolv->usesPbc() ) mycolv->applyPbc( myatoms, natoms ); return natoms; } -void AtomValuePack::updateUsingIndices(){ +void AtomValuePack::updateUsingIndices() { if( myvals.updateComplete() ) return; unsigned jactive=0; - for(unsigned i=0;igetNumberOfAtoms(); - if( myvals.isActive( nvir ) ){ - for(unsigned i=0;i<9;++i) myvals.putIndexInActiveArray( nvir + i ); + if( myvals.isActive( nvir ) ) { + for(unsigned i=0; i<9; ++i) myvals.putIndexInActiveArray( nvir + i ); } myvals.completeUpdate(); } -void AtomValuePack::addComDerivatives( const int& ind, const Vector& der, CatomPack& catom_der ){ - if( ind<0 ){ - for(unsigned ider=0;ider& myatoms; /// - void addDerivative( const unsigned& , const unsigned& , const double& ); + void addDerivative( const unsigned&, const unsigned&, const double& ); /// - void addAtomsDerivatives( const unsigned& , const unsigned& , const Vector& ); + void addAtomsDerivatives( const unsigned&, const unsigned&, const Vector& ); /// void addTemporyAtomsDerivatives( const unsigned& jder, const Vector& der ); public: @@ -60,7 +60,7 @@ friend class LocalAverage; /// Set the number of atoms void setNumberOfAtoms( const unsigned& ); /// Set the index for one of the atoms - void setIndex( const unsigned& , const unsigned& ); + void setIndex( const unsigned&, const unsigned& ); /// void setAtomIndex( const unsigned& j, const unsigned& ind ); /// @@ -76,13 +76,13 @@ friend class LocalAverage; /// Get the position of the ith atom Vector& getPosition( const unsigned& ); /// - void setValue( const unsigned& , const double& ); + void setValue( const unsigned&, const double& ); /// void addValue( const unsigned& ival, const double& vv ); /// double getValue( const unsigned& ) const ; /// - void addBoxDerivatives( const unsigned& , const Tensor& ); + void addBoxDerivatives( const unsigned&, const Tensor& ); /// void addTemporyBoxDerivatives( const Tensor& vir ); /// @@ -90,13 +90,13 @@ friend class LocalAverage; /// void updateDynamicList(); /// - void addComDerivatives( const int& , const Vector& , CatomPack& ); + void addComDerivatives( const int&, const Vector&, CatomPack& ); /// MultiValue& getUnderlyingMultiValue(); }; inline -void AtomValuePack::setNumberOfAtoms( const unsigned& nat ){ +void AtomValuePack::setNumberOfAtoms( const unsigned& nat ) { natoms=nat; } @@ -111,17 +111,17 @@ unsigned AtomValuePack::getNumberOfDerivatives() const { } inline -void AtomValuePack::setIndex( const unsigned& j, const unsigned& ind ){ - plumed_dbg_assert( jgetPositionOfAtomForLinkCells( ind ); } @@ -131,18 +131,18 @@ unsigned AtomValuePack::getIndex( const unsigned& j ) const { } inline -Vector& AtomValuePack::getPosition( const unsigned& iatom ){ +Vector& AtomValuePack::getPosition( const unsigned& iatom ) { plumed_dbg_assert( iatomgetNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addTemporyDerivative( nvir + 3*i+j, vir(i,j) ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addTemporyDerivative( nvir + 3*i+j, vir(i,j) ); } inline -void AtomValuePack::addBoxDerivatives( const unsigned& ival , const Tensor& vir ){ +void AtomValuePack::addBoxDerivatives( const unsigned& ival, const Tensor& vir ) { unsigned nvir=3*mycolv->getNumberOfAtoms(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addDerivative( ival, nvir + 3*i+j, vir(i,j) ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addDerivative( ival, nvir + 3*i+j, vir(i,j) ); } inline -void AtomValuePack::updateDynamicList(){ +void AtomValuePack::updateDynamicList() { if( myvals.updateComplete() ) return; myvals.updateDynamicList(); } inline -MultiValue& AtomValuePack::getUnderlyingMultiValue(){ +MultiValue& AtomValuePack::getUnderlyingMultiValue() { return myvals; -} +} } } diff --git a/src/multicolvar/Bridge.cpp b/src/multicolvar/Bridge.cpp index e56ec84d11..42198ffa1e 100644 --- a/src/multicolvar/Bridge.cpp +++ b/src/multicolvar/Bridge.cpp @@ -29,10 +29,10 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { -//+PLUMEDOC MCOLVAR BRIDGE +//+PLUMEDOC MCOLVAR BRIDGE /* Calculate the number of atoms that bridge two parts of a structure @@ -40,20 +40,20 @@ This quantity calculates: \f[ f(x) = \sum_{ijk} s_A(r_{ij})s_B(r_{ik}) -\f] +\f] -where the sum over \f$i\f$ is over all the ``bridging atoms" and +where the sum over \f$i\f$ is over all the ``bridging atoms" and \f$s_A\f$ and \f$s_B\f$ are \ref switchingfunction. \par Examples The following example instructs plumed to calculate the number of water molecules -that are bridging betweeen atoms 1-10 and atoms 11-20 and to print the value +that are bridging betweeen atoms 1-10 and atoms 11-20 and to print the value to a file \verbatim BRIDGE BRIDGING_ATOMS=100-200 GROUPA=1-10 GROUPB=11-20 LABEL=w1 -PRINT ARG=a1.mean FILE=colvar +PRINT ARG=a1.mean FILE=colvar \endverbatim */ @@ -69,27 +69,27 @@ class Bridge : public MultiColvarBase { explicit Bridge(const ActionOptions&); // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(Bridge,"BRIDGE") -void Bridge::registerKeywords( Keywords& keys ){ +void Bridge::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("atoms-2","BRIDGING_ATOMS","The list of atoms that can form the bridge between the two interesting parts " - "of the structure."); - keys.add("atoms-2","GROUPA","The list of atoms that are in the first interesting part of the structure"); - keys.add("atoms-2","GROUPB","The list of atoms that are in the second interesting part of the structure"); + "of the structure."); + keys.add("atoms-2","GROUPA","The list of atoms that are in the first interesting part of the structure"); + keys.add("atoms-2","GROUPB","The list of atoms that are in the second interesting part of the structure"); keys.add("optional","SWITCH","The parameters of the two \\ref switchingfunction in the above formula"); keys.add("optional","SWITCHA","The \\ref switchingfunction on the distance between bridging atoms and the atoms in " - "group A"); + "group A"); keys.add("optional","SWITCHB","The \\ref switchingfunction on the distance between the bridging atoms and the atoms in " - "group B"); + "group B"); } Bridge::Bridge(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms std::vector all_atoms; @@ -98,27 +98,27 @@ MultiColvarBase(ao) setupMultiColvarBase( all_atoms ); // Setup Central atom atoms std::vector catom_ind(3, false); catom_ind[0]=true; - setAtomsForCentralAtom( catom_ind ); + setAtomsForCentralAtom( catom_ind ); std::string sfinput,errors; parse("SWITCH",sfinput); - if( sfinput.length()>0 ){ + if( sfinput.length()>0 ) { + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + sf2.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } else { + parse("SWITCHA",sfinput); + if(sfinput.length()>0) { + weightHasDerivatives=true; sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); + sfinput.clear(); parse("SWITCHB",sfinput); + if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - } else { - parse("SWITCHA",sfinput); - if(sfinput.length()>0){ - weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors ); - sfinput.clear(); parse("SWITCHB",sfinput); - if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB"); - sf2.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); - } else { - error("missing definition of switching functions"); - } + if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors ); + } else { + error("missing definition of switching functions"); + } } log.printf(" distance between bridging atoms and atoms in GROUPA must be less than %s\n",sf1.description().c_str()); log.printf(" distance between bridging atoms and atoms in GROUPB must be less than %s\n",sf2.description().c_str()); @@ -137,18 +137,18 @@ MultiColvarBase(ao) double Bridge::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { double tot=0; - for(unsigned i=2;i(mlab); @@ -47,12 +47,12 @@ MultiColvarBase(ao) myBridgeVessel = mycolv->addBridgingVessel( this ); addDependency(mycolv); weightHasDerivatives=true; usespecies=mycolv->usespecies; // Number of tasks is the same as the number in the underlying MultiColvar - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList( mycolv->getTaskCode(i) ); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList( mycolv->getTaskCode(i) ); } -void BridgedMultiColvarFunction::turnOnDerivatives(){ +void BridgedMultiColvarFunction::turnOnDerivatives() { BridgedMultiColvarFunction* check = dynamic_cast( mycolv ); - if( check ){ + if( check ) { if( check->getNumberOfAtoms()>0 ) error("cannot calculate required derivatives of this quantity"); } MultiColvarBase::turnOnDerivatives(); @@ -60,18 +60,18 @@ void BridgedMultiColvarFunction::turnOnDerivatives(){ void BridgedMultiColvarFunction::transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const { completeTask( current, invals, outvals ); - + // Now update the outvals derivatives lists - if( derivativesAreRequired() ){ - outvals.emptyActiveMembers(); - if( mycolv->isDensity() ){ - for(unsigned j=0;j<3;++j) outvals.putIndexInActiveArray( 3*current+j ); - for(unsigned j=invals.getNumberOfDerivatives()-9;jisDensity() ) { + for(unsigned j=0; j<3; ++j) outvals.putIndexInActiveArray( 3*current+j ); + for(unsigned j=invals.getNumberOfDerivatives()-9; jgetTemporyMultiValue(); if( invals.getNumberOfValues()!=mycolv->getNumberOfQuantities() || - invals.getNumberOfDerivatives()!=mycolv->getNumberOfDerivatives() ){ - invals.resize( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() ); + invals.getNumberOfDerivatives()!=mycolv->getNumberOfDerivatives() ) { + invals.resize( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() ); } invals.clearAll(); mycolv->performTask( taskIndex, current, invals ); - transformBridgedDerivatives( taskIndex, invals, myvals ); + transformBridgedDerivatives( taskIndex, invals, myvals ); } -void BridgedMultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ){ - if(!a){ +void BridgedMultiColvarFunction::calculateNumericalDerivatives( ActionWithValue* a ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"cannot compute numerical derivatives for an action without values"); } - if( myBridgeVessel ){ - myBridgeVessel->completeNumericalDerivatives(); + if( myBridgeVessel ) { + myBridgeVessel->completeNumericalDerivatives(); } else { - error("numerical derivatives are not implemented"); + error("numerical derivatives are not implemented"); } } -void BridgedMultiColvarFunction::applyBridgeForces( const std::vector& bb ){ +void BridgedMultiColvarFunction::applyBridgeForces( const std::vector& bb ) { if( getNumberOfAtoms()==0 ) return ; std::vector& f( modifyForces() ); - for(unsigned i=0;iisPeriodic(); } -void BridgedMultiColvarFunction::deactivate_task( const unsigned& taskno ){ +void BridgedMultiColvarFunction::deactivate_task( const unsigned& taskno ) { plumed_merror("This should never be called"); } -void BridgedMultiColvarFunction::getCentralAtomPack( const unsigned& basn, const unsigned& curr, CatomPack& mypack ){ +void BridgedMultiColvarFunction::getCentralAtomPack( const unsigned& basn, const unsigned& curr, CatomPack& mypack ) { return mycolv->getCentralAtomPack( basn, curr, mypack ); } diff --git a/src/multicolvar/BridgedMultiColvarFunction.h b/src/multicolvar/BridgedMultiColvarFunction.h index 216bd52a1b..b23ccb9065 100644 --- a/src/multicolvar/BridgedMultiColvarFunction.h +++ b/src/multicolvar/BridgedMultiColvarFunction.h @@ -29,8 +29,8 @@ namespace PLMD { namespace multicolvar { class BridgedMultiColvarFunction : public MultiColvarBase { -friend class MultiColvarBase; -friend class MultiColvarFunction; + friend class MultiColvarBase; + friend class MultiColvarFunction; private: /// This is used for storing positions properly Vector tmp_p; @@ -51,23 +51,23 @@ friend class MultiColvarFunction; explicit BridgedMultiColvarFunction(const ActionOptions&); /// Get a pointer to the base multicolvar MultiColvarBase* getPntrToMultiColvar() const ; -/// Don't actually clear the derivatives when this is called from plumed main. -/// They are calculated inside another action and clearing them would be bad - void clearDerivatives(){} +/// Don't actually clear the derivatives when this is called from plumed main. +/// They are calculated inside another action and clearing them would be bad + void clearDerivatives() {} /// Check nothing impossible being done with derivatives virtual void turnOnDerivatives(); /// Get the number of derivatives for this action - unsigned getNumberOfDerivatives(); + unsigned getNumberOfDerivatives(); /// Get the size of the atoms with derivatives array unsigned getSizeOfAtomsWithDerivatives(); /// Is the output quantity periodic bool isPeriodic(); -/// Routines that have to be defined so as not to have problems with virtual methods +/// Routines that have to be defined so as not to have problems with virtual methods void deactivate_task( const unsigned& taskno ); - void calculate(){} + void calculate() {} /// This does the task void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const ; - void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; + void performTask( const unsigned&, const unsigned&, MultiValue& ) const ; virtual void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const=0; /// Get the central atom position Vector retrieveCentralAtomPos(); @@ -77,11 +77,11 @@ friend class MultiColvarFunction; const std::vector & getAbsoluteIndexes()const ; /// We need our own calculate numerical derivatives here void calculateNumericalDerivatives( ActionWithValue* a=NULL ); - void apply(){}; -/// Is this atom currently being copied + void apply() {}; +/// Is this atom currently being copied bool isCurrentlyActive( const unsigned& ); /// This should not be called - Vector calculateCentralAtomPosition(){ plumed_error(); } + Vector calculateCentralAtomPosition() { plumed_error(); } double compute( const unsigned& tindex, AtomValuePack& myvals ) const { plumed_error(); } Vector getPositionOfAtomForLinkCells( const unsigned& iatom ) const ; void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector& indices ); @@ -103,33 +103,33 @@ MultiColvarBase* BridgedMultiColvarFunction::getPntrToMultiColvar() const { } inline -unsigned BridgedMultiColvarFunction::getNumberOfDerivatives(){ +unsigned BridgedMultiColvarFunction::getNumberOfDerivatives() { return mycolv->getNumberOfDerivatives() + 3*getNumberOfAtoms(); } inline -bool BridgedMultiColvarFunction::isCurrentlyActive( const unsigned& code ){ +bool BridgedMultiColvarFunction::isCurrentlyActive( const unsigned& code ) { return mycolv->isCurrentlyActive( code ); } inline -unsigned BridgedMultiColvarFunction::getSizeOfAtomsWithDerivatives(){ +unsigned BridgedMultiColvarFunction::getSizeOfAtomsWithDerivatives() { return mycolv->getNumberOfAtoms(); } -inline -Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { +inline +Vector BridgedMultiColvarFunction::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { return mycolv->getPositionOfAtomForLinkCells(iatom); } inline -Vector BridgedMultiColvarFunction::getCentralAtomPos( const unsigned& curr ){ +Vector BridgedMultiColvarFunction::getCentralAtomPos( const unsigned& curr ) { return mycolv->getCentralAtomPos( curr ); } inline AtomNumber BridgedMultiColvarFunction::getAbsoluteIndexOfCentralAtom(const unsigned& i) const { - return mycolv->getAbsoluteIndexOfCentralAtom(i); + return mycolv->getAbsoluteIndexOfCentralAtom(i); } inline diff --git a/src/multicolvar/CatomPack.cpp b/src/multicolvar/CatomPack.cpp index 59e1d8e44b..900fa5e706 100644 --- a/src/multicolvar/CatomPack.cpp +++ b/src/multicolvar/CatomPack.cpp @@ -21,10 +21,10 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "CatomPack.h" -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { -void CatomPack::resize( const unsigned& size ){ +void CatomPack::resize( const unsigned& size ) { indices.resize(size); derivs.resize(size); } diff --git a/src/multicolvar/CatomPack.h b/src/multicolvar/CatomPack.h index e960d3db51..130e971cdb 100644 --- a/src/multicolvar/CatomPack.h +++ b/src/multicolvar/CatomPack.h @@ -36,24 +36,24 @@ class CatomPack { std::vector derivs; public: void resize( const unsigned& ); - void setIndex( const unsigned& , const unsigned& ); - void setDerivative( const unsigned& , const Tensor& ); + void setIndex( const unsigned&, const unsigned& ); + void setDerivative( const unsigned&, const Tensor& ); unsigned getNumberOfAtomsWithDerivatives() const ; unsigned getIndex( const unsigned& ) const ; - double getDerivative( const unsigned&, const unsigned& , const Vector& ) const ; + double getDerivative( const unsigned&, const unsigned&, const Vector& ) const ; }; inline -void CatomPack::setIndex( const unsigned& jind, const unsigned& ind ){ +void CatomPack::setIndex( const unsigned& jind, const unsigned& ind ) { plumed_dbg_assert( jind( mycolv ); - if( mybr ){ - requestAtoms( (mybr->getPntrToMultiColvar())->getAbsoluteIndexes() ); comp=1; - } else { - if( mycolv->getNumberOfQuantities()>5 ){ - int incomp=-1; parse("COMPONENT",incomp); - if( incomp<0 ) error("vector input but component was not specified"); - comp=incomp; - } else { - comp=1; - } - requestAtoms( mycolv->getAbsoluteIndexes () ); + if( mybr ) { + requestAtoms( (mybr->getPntrToMultiColvar())->getAbsoluteIndexes() ); comp=1; + } else { + if( mycolv->getNumberOfQuantities()>5 ) { + int incomp=-1; parse("COMPONENT",incomp); + if( incomp<0 ) error("vector input but component was not specified"); + comp=incomp; + } else { + comp=1; + } + requestAtoms( mycolv->getAbsoluteIndexes () ); } // We need the derivatives - mycolv->turnOnDerivatives(); addDependency(mycolv); + mycolv->turnOnDerivatives(); addDependency(mycolv); mystash = mycolv->buildDataStashes( NULL ); log.printf(" building center of mass based on weights calculated in multicolvar action named %s \n",mycolv->getLabel().c_str() ); } -void CenterOfMultiColvar::calculate(){ +void CenterOfMultiColvar::calculate() { // Retrieve the periodic boundary conditions const Pbc& pbc=mycolv->getPbc(); - if( !pbc.isOrthorombic() ) error("Berry phase does not work for non orthorhombic cells"); - + if( !pbc.isOrthorombic() ) error("Berry phase does not work for non orthorhombic cells"); + // Create a multivalue to store the derivatives MultiValue myvals( 7, mycolv->getNumberOfDerivatives() ); myvals.clearAll(); MultiValue tvals( mycolv->getNumberOfQuantities(), mycolv->getNumberOfDerivatives() ); tvals.clearAll(); - // Now loop over all active multicolvars - Vector stmp, ctmp, scom, ccom, sder, cder; + // Now loop over all active multicolvars + Vector stmp, ctmp, scom, ccom, sder, cder; scom.zero(); ccom.zero(); double norm=0; std::vector cvals( mycolv->getNumberOfQuantities() ); - for(unsigned i=0;igetNumberOfStoredValues();++i){ - // Retrieve value and derivatives - mystash->retrieveSequentialValue( i, false, cvals ); - mystash->retrieveDerivatives( mycolv->getPositionInFullTaskList(i), false, tvals ); - // Convert position into fractionals - Vector fpos = pbc.realToScaled( mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(i) ) ); - // Now accumulate Berry phase averages - for(unsigned j=0;j<3;++j){ - stmp[j] = sin( 2*pi*fpos[j] ); ctmp[j] = cos( 2*pi*fpos[j] ); - scom[j] += cvals[0]*cvals[comp]*stmp[j]; ccom[j] += cvals[0]*cvals[comp]*ctmp[j]; - double icell = 1.0 / getPbc().getBox().getRow(j).modulo(); - sder[j] = 2*pi*icell*cvals[0]*cvals[comp]*cos( 2*pi*fpos[j] ); - cder[j]=-2*pi*icell*cvals[0]*cvals[comp]*sin( 2*pi*fpos[j] ); - } - // Now accumulate derivatives - for(unsigned k=0;kgetNumberOfStoredValues(); ++i) { + // Retrieve value and derivatives + mystash->retrieveSequentialValue( i, false, cvals ); + mystash->retrieveDerivatives( mycolv->getPositionInFullTaskList(i), false, tvals ); + // Convert position into fractionals + Vector fpos = pbc.realToScaled( mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(i) ) ); + // Now accumulate Berry phase averages + for(unsigned j=0; j<3; ++j) { + stmp[j] = sin( 2*pi*fpos[j] ); ctmp[j] = cos( 2*pi*fpos[j] ); + scom[j] += cvals[0]*cvals[comp]*stmp[j]; ccom[j] += cvals[0]*cvals[comp]*ctmp[j]; + double icell = 1.0 / getPbc().getBox().getRow(j).modulo(); + sder[j] = 2*pi*icell*cvals[0]*cvals[comp]*cos( 2*pi*fpos[j] ); + cder[j]=-2*pi*icell*cvals[0]*cvals[comp]*sin( 2*pi*fpos[j] ); + } + // Now accumulate derivatives + for(unsigned k=0; kgetCentralAtomPack( 0, mycolv->getPositionInFullTaskList(i), mypack ); - for(unsigned j=0;jgetCentralAtomPack( 0, mycolv->getPositionInFullTaskList(i), mypack ); + for(unsigned j=0; j fderiv( getNumberOfAtoms() ); - for(unsigned j=0;j0){ - switchingFunction.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + if(sw.length()>0) { + switchingFunction.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + } else { + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" coordination of central atom and those within %s\n",( switchingFunction.description() ).c_str() ); // Set the link cell cutoff @@ -121,20 +121,20 @@ MultiColvarBase(ao) } double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - // Calculate the coordination number - double dfunc, d2, sw; - for(unsigned i=1;i& weight, MultiColvarFunction* func ){} void getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector& indices ); // unsigned getNumberOfQuantities(); @@ -69,37 +69,37 @@ class Density : public MultiColvarBase { PLUMED_REGISTER_ACTION(Density,"DENSITY") -void Density::registerKeywords( Keywords& keys ){ +void Density::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("SPECIES"); + keys.use("SPECIES"); } Density::Density(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { std::vector all_atoms; parseMultiColvarAtomList("SPECIES", -1, all_atoms); - ablocks.resize(1); ablocks[0].resize( atom_lab.size() ); - for(unsigned i=0;i& indices ){ - indices[jstore]=0; +void Density::getIndexList( const unsigned& ntotal, const unsigned& jstore, const unsigned& maxder, std::vector& indices ) { + indices[jstore]=0; } // unsigned Density::getNumberOfQuantities(){ // return 2; // } -void Density::getValueForTask( const unsigned& iatom, std::vector& vals ){ - plumed_dbg_assert( vals.size()==2 ); vals[0]=vals[1]=1.0; +void Density::getValueForTask( const unsigned& iatom, std::vector& vals ) { + plumed_dbg_assert( vals.size()==2 ); vals[0]=vals[1]=1.0; } } diff --git a/src/multicolvar/DihedralCorrelation.cpp b/src/multicolvar/DihedralCorrelation.cpp index fb5b644c42..e75bde6680 100644 --- a/src/multicolvar/DihedralCorrelation.cpp +++ b/src/multicolvar/DihedralCorrelation.cpp @@ -29,8 +29,8 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC COLVAR DIHCOR /* @@ -87,39 +87,39 @@ class DihedralCorrelation : public MultiColvarBase { static void registerKeywords( Keywords& keys ); explicit DihedralCorrelation(const ActionOptions&); virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(DihedralCorrelation,"DIHCOR") -void DihedralCorrelation::registerKeywords( Keywords& keys ){ +void DihedralCorrelation::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("numbered","ATOMS","the atoms involved in each of the dihedral correlation values you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dihedral correlation will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of 8 atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one dihedral correlation will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of 8 atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); } DihedralCorrelation::DihedralCorrelation(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms std::vector all_atoms; readAtomsLikeKeyword( "ATOMS", 8, all_atoms ); setupMultiColvarBase( all_atoms ); // Stuff for central atoms - std::vector catom_ind(8, false); + std::vector catom_ind(8, false); catom_ind[1]=catom_ind[2]=catom_ind[5]=catom_ind[6]=true; setAtomsForCentralAtom( catom_ind ); // And setup the ActionWithVessel - if( getNumberOfVessels()==0 ){ - std::string fake_input; - addVessel( "SUM", fake_input, -1 ); // -1 here means that this value will be named getLabel() - readVesselKeywords(); // This makes sure resizing is done + if( getNumberOfVessels()==0 ) { + std::string fake_input; + addVessel( "SUM", fake_input, -1 ); // -1 here means that this value will be named getLabel() + readVesselKeywords(); // This makes sure resizing is done } // And check everything has been read in correctly @@ -148,9 +148,9 @@ double DihedralCorrelation::compute( const unsigned& tindex, AtomValuePack& myat const double value = 0.5*(1.+cos(diff)); // Derivatives wrt phi1 const double dval = 0.5*sin(diff); - dd10 *= dval; - dd11 *= dval; - dd12 *= dval; + dd10 *= dval; + dd11 *= dval; + dd12 *= dval; // And add addAtomDerivatives(1, 0, dd10, myatoms ); addAtomDerivatives(1, 1, dd11-dd10, myatoms ); diff --git a/src/multicolvar/DistanceFromContour.cpp b/src/multicolvar/DistanceFromContour.cpp index 3a942c5fb2..214930392e 100644 --- a/src/multicolvar/DistanceFromContour.cpp +++ b/src/multicolvar/DistanceFromContour.cpp @@ -31,7 +31,7 @@ Calculate the perpendicular distance from a Willard-Chandler dividing surface. Suppose that you have calculated a multicolvar. By doing so you have calculated a -set of colvars, \f$s_i\f$, and each of these colvars has a well defined position in +set of colvars, \f$s_i\f$, and each of these colvars has a well defined position in space \f$(x_i,y_i,z_i)\f$. You can use this information to calculate a phase-field model of the colvar density using: @@ -39,7 +39,7 @@ model of the colvar density using: p(x,y,x) = \sum_{i} s_i K\left[\frac{x-x_i}{\sigma_x},\frac{y-y_i}{\sigma_y},\frac{z-z_i}{\sigma_z} \right] \f] -In this expression \f$\sigma_x, \sigma_y\f$ and \f$\sigma_z\f$ are bandwidth parameters and +In this expression \f$\sigma_x, \sigma_y\f$ and \f$\sigma_z\f$ are bandwidth parameters and \f$K\f$ is one of the \ref kernelfunctions. This is what is done within \ref MULTICOLVARDENS The Willard-Chandler surface is a surface of constant density in the above phase field \f$p(x,y,z)\f$. @@ -50,13 +50,13 @@ p(x',y',z') = \rho \f] where \f$\rho\f$ is some target density. This action caculates the distance projected on the \f$x, y\f$ or -\f$z\f$ axis between the position of some test particle and this surface of constant field density. +\f$z\f$ axis between the position of some test particle and this surface of constant field density. \par Examples -In this example atoms 2-100 are assumed to be concentraed along some part of the \f$z\f$ axis so that you -an interface between a liquid/solid and the vapour. The quantity dc measures the distance between the -surface at which the density of 2-100 atoms is equal to 0.2 and the position of the test particle atom 1. +In this example atoms 2-100 are assumed to be concentraed along some part of the \f$z\f$ axis so that you +an interface between a liquid/solid and the vapour. The quantity dc measures the distance between the +surface at which the density of 2-100 atoms is equal to 0.2 and the position of the test particle atom 1. \verbatim dens: DENSITY SPECIES=2-100 @@ -81,7 +81,7 @@ class DistanceFromContour : public MultiColvarBase { std::vector bw, pos1, pos2, dirv, dirv2; std::vector forces; std::vector perp_dirs; - vesselbase::ValueVessel* myvalue_vessel; + vesselbase::ValueVessel* myvalue_vessel; vesselbase::ValueVessel* myderiv_vessel; RootFindingBase mymin; public: @@ -91,16 +91,16 @@ class DistanceFromContour : public MultiColvarBase { bool isDensity() const { return true; } void calculate(); unsigned getNumberOfQuantities() const ; - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; double getDifferenceFromContour( const std::vector& x, std::vector& der ); -// We need an apply action as we are using an independent value +// We need an apply action as we are using an independent value void apply(); }; PLUMED_REGISTER_ACTION(DistanceFromContour,"DISTANCE_FROM_CONTOUR") -void DistanceFromContour::registerKeywords( Keywords& keys ){ +void DistanceFromContour::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.addOutputComponent("dist1","default","the distance between the reference atom and the nearest contour"); keys.addOutputComponent("dist2","default","the distance between the reference atom and the other contour"); @@ -110,31 +110,31 @@ void DistanceFromContour::registerKeywords( Keywords& keys ){ keys.add("atoms","ATOM","The atom whose perpendicular distance we are calculating from the contour"); keys.add("compulsory","BANDWIDTH","the bandwidths for kernel density esimtation"); keys.add("compulsory","KERNEL","gaussian","the kernel function you are using. More details on the kernels available " - "in plumed plumed can be found in \\ref kernelfunctions."); + "in plumed plumed can be found in \\ref kernelfunctions."); keys.add("compulsory","DIR","the direction perpendicular to the contour that you are looking for"); keys.add("compulsory","CONTOUR","the value we would like for the contour"); keys.add("compulsory","TOLERANCE","0.1","this parameter is used to manage periodic boundary conditions. The problem " - "here is that we can be between contours even when we are not within the membrane " - "because of periodic boundary conditions. When we are in the contour, however, we " - "should have it so that the sums of the absoluate values of the distances to the two " - "contours is approximately the distance between the two contours. There can be numerical errors in these calculations, however, so " - "we specify a small tolerance here"); + "here is that we can be between contours even when we are not within the membrane " + "because of periodic boundary conditions. When we are in the contour, however, we " + "should have it so that the sums of the absoluate values of the distances to the two " + "contours is approximately the distance between the two contours. There can be numerical errors in these calculations, however, so " + "we specify a small tolerance here"); } DistanceFromContour::DistanceFromContour( const ActionOptions& ao ): -Action(ao), -MultiColvarBase(ao), -derivTime(false), -bw(3), -pos1(3,0.0), -pos2(3,0.0), -dirv(3,0.0), -dirv2(3,0.0), -perp_dirs(2), -mymin(this) + Action(ao), + MultiColvarBase(ao), + derivTime(false), + bw(3), + pos1(3,0.0), + pos2(3,0.0), + dirv(3,0.0), + dirv2(3,0.0), + perp_dirs(2), + mymin(this) { // Read in the multicolvar/atoms - std::vector all_atoms; parse("TOLERANCE",pbc_param); + std::vector all_atoms; parse("TOLERANCE",pbc_param); bool read2 = parseMultiColvarAtomList("DATA", -1, all_atoms); if( !read2 ) error("missing DATA keyword"); bool read1 = parseMultiColvarAtomList("ATOM", -1, all_atoms); @@ -146,10 +146,10 @@ mymin(this) if( getNumberOfBaseMultiColvars()!=1 ) error("should only be one input multicolvar"); // Get the direction - std::string ldir; parse("DIR",ldir ); - if( ldir=="x" ){ dir=0; perp_dirs[0]=1; perp_dirs[1]=2; dirv[0]=1; dirv2[0]=-1; } - else if( ldir=="y" ){ dir=1; perp_dirs[0]=0; perp_dirs[1]=2; dirv[1]=1; dirv2[1]=-1; } - else if( ldir=="z" ){ dir=2; perp_dirs[0]=0; perp_dirs[1]=1; dirv[2]=1; dirv2[2]=-1; } + std::string ldir; parse("DIR",ldir ); + if( ldir=="x" ) { dir=0; perp_dirs[0]=1; perp_dirs[1]=2; dirv[0]=1; dirv2[0]=-1; } + else if( ldir=="y" ) { dir=1; perp_dirs[0]=0; perp_dirs[1]=2; dirv[1]=1; dirv2[1]=-1; } + else if( ldir=="z" ) { dir=2; perp_dirs[0]=0; perp_dirs[1]=1; dirv[2]=1; dirv2[2]=-1; } else error(ldir + " is not a valid direction use x, y or z"); // Read in details of phase field construction @@ -158,45 +158,45 @@ mymin(this) log.printf(" constructing phase field using %s kernels with bandwidth (%f, %f, %f) \n",kerneltype.c_str(), bw[0], bw[1], bw[2] ); // Now create a task list - for(unsigned i=0;igetFullNumberOfTasks();++i) addTaskToList(i); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList(i); // And a cutoff std::vector pp( bw.size(),0 ); KernelFunctions kernel( pp, bw, kerneltype, false, 1.0, true ); - double rcut = kernel.getCutoff( bw[0] ); - for(unsigned j=1;jrcut ) rcut=kernel.getCutoff(bw[j]); + double rcut = kernel.getCutoff( bw[0] ); + for(unsigned j=1; jrcut ) rcut=kernel.getCutoff(bw[j]); } - rcut2=rcut*rcut; - // Create the values + rcut2=rcut*rcut; + // Create the values addComponent("thickness"); componentIsNotPeriodic("thickness"); addComponent("dist1"); componentIsNotPeriodic("dist1"); addComponent("dist2"); componentIsNotPeriodic("dist2"); addComponentWithDerivatives("qdist"); componentIsNotPeriodic("qdist"); - // Create sum vessels + // Create sum vessels std::string fake_input; std::string deriv_input="COMPONENT=2"; - if( mybasemulticolvars[0]->isDensity() ){ - addVessel( "SUM", fake_input, -1 ); addVessel( "SUM", deriv_input, -1 ); - } else { - addVessel( "MEAN", fake_input, -1 ); addVessel( "MEAN", deriv_input, -1 ); + if( mybasemulticolvars[0]->isDensity() ) { + addVessel( "SUM", fake_input, -1 ); addVessel( "SUM", deriv_input, -1 ); + } else { + addVessel( "MEAN", fake_input, -1 ); addVessel( "MEAN", deriv_input, -1 ); } // And convert to a value vessel so we can get the final value myvalue_vessel = dynamic_cast( getPntrToVessel(0) ); - myderiv_vessel = dynamic_cast( getPntrToVessel(1) ); - plumed_assert( myvalue_vessel && myderiv_vessel ); resizeFunctions(); + myderiv_vessel = dynamic_cast( getPntrToVessel(1) ); + plumed_assert( myvalue_vessel && myderiv_vessel ); resizeFunctions(); // Create the vector of values that holds the position - for(unsigned i=0;i<3;++i) pval.push_back( new Value() ); + for(unsigned i=0; i<3; ++i) pval.push_back( new Value() ); } -DistanceFromContour::~DistanceFromContour(){ - for(unsigned i=0;i<3;++i) delete pval[i]; +DistanceFromContour::~DistanceFromContour() { + for(unsigned i=0; i<3; ++i) delete pval[i]; } unsigned DistanceFromContour::getNumberOfQuantities() const { return 3; } -void DistanceFromContour::calculate(){ +void DistanceFromContour::calculate() { // Check box is orthorhombic if( !getPbc().isOrthorombic() ) error("cell box must be orthorhombic"); @@ -207,14 +207,14 @@ void DistanceFromContour::calculate(){ deactivateAllTasks(); Vector myvec = getSeparation( getPosition(getNumberOfAtoms()-1), getPosition(0) ); pos2[dir]=myvec[dir]; taskFlags[0]=1; double d2, mindist = myvec.modulo2(); - for(unsigned j=1;jepsilon ){ pos2[dir]=distance[dir]; mindist = d2; } - taskFlags[j]=1; - } + for(unsigned j=1; jepsilon ) { pos2[dir]=distance[dir]; mindist = d2; } + taskFlags[j]=1; + } } lockContributors(); derivTime=false; // pos1 position of the nanoparticle, in the first time @@ -224,29 +224,29 @@ void DistanceFromContour::calculate(){ std::vector faked(3); double fa = getDifferenceFromContour( pos1, faked ); double fb = getDifferenceFromContour( pos2, faked ); - if( fa*fb>0 ){ - unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); - for(unsigned i=0;i0)? -1 : +1; // If the nanoparticle is inside the membrane push it out - pos1[dir] += sign*bw[dir]; fa = getDifferenceFromContour( pos1, faked ); - if( fa*fb<0 ) break; - // if fa*fb is less than zero the new pos 1 is outside the contour - } + if( fa*fb>0 ) { + unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); + for(unsigned i=0; i0)? -1 : +1; // If the nanoparticle is inside the membrane push it out + pos1[dir] += sign*bw[dir]; fa = getDifferenceFromContour( pos1, faked ); + if( fa*fb<0 ) break; + // if fa*fb is less than zero the new pos 1 is outside the contour + } } // Set direction for contour search - dirv[dir] = pos2[dir] - pos1[dir]; + dirv[dir] = pos2[dir] - pos1[dir]; // Bracket for second root starts in center of membrane - double fc = getDifferenceFromContour( pos2, faked ); - if( fc*fb>0 ){ - // first time is true, because fc=fb - // push pos2 from its initial position inside the membrane towards the second contourn - unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); - for(unsigned i=0;i0)? +1 : -1; - pos2[dir] += sign*bw[dir]; fc = getDifferenceFromContour( pos2, faked ); - if( fc*fb<0 ) break; - } - dirv2[dir] = ( pos1[dir] + dirv[dir] ) - pos2[dir]; + double fc = getDifferenceFromContour( pos2, faked ); + if( fc*fb>0 ) { + // first time is true, because fc=fb + // push pos2 from its initial position inside the membrane towards the second contourn + unsigned maxtries = std::floor( ( getBox()(dir,dir) ) / bw[dir] ); + for(unsigned i=0; i0)? +1 : -1; + pos2[dir] += sign*bw[dir]; fc = getDifferenceFromContour( pos2, faked ); + if( fc*fb<0 ) break; + } + dirv2[dir] = ( pos1[dir] + dirv[dir] ) - pos2[dir]; } // Now do a search for the two contours @@ -255,50 +255,50 @@ void DistanceFromContour::calculate(){ Vector root1; root1.zero(); root1[dir] = pval[dir]->get(); mymin.lsearch( dirv2, pos2, &DistanceFromContour::getDifferenceFromContour ); // Calculate the separation between the two roots using PBC - Vector root2; root2.zero(); root2[dir]=pval[dir]->get(); + Vector root2; root2.zero(); root2[dir]=pval[dir]->get(); Vector sep = getSeparation( root1, root2 ); double spacing = fabs( sep[dir] ); plumed_assert( spacing>epsilon ); getPntrToComponent("thickness")->set( spacing ); // Make sure the sign is right - double predir=(root1[dir]*root2[dir]<0)? -1 : 1; - // This deals with periodic boundary conditions - if we are inside the membrane the sum of the absolute + double predir=(root1[dir]*root2[dir]<0)? -1 : 1; + // This deals with periodic boundary conditions - if we are inside the membrane the sum of the absolute // distances from the contours should add up to the spacing. When this is not the case we must be outside // the contour - // if( predir==-1 && (fabs(root1[dir])+fabs(root2[dir]))>(spacing+pbc_param) ) predir=1; + // if( predir==-1 && (fabs(root1[dir])+fabs(root2[dir]))>(spacing+pbc_param) ) predir=1; // Set the final value to root that is closest to the "origin" = position of atom - if( fabs(root1[dir])set( predir*fabs(root1[dir]) ); - getPntrToComponent("dist2")->set( fabs(root2[dir]) ); - } else { - getPntrToComponent("dist1")->set( predir*fabs(root2[dir]) ); - getPntrToComponent("dist2")->set( fabs(root1[dir]) ); + if( fabs(root1[dir])set( predir*fabs(root1[dir]) ); + getPntrToComponent("dist2")->set( fabs(root2[dir]) ); + } else { + getPntrToComponent("dist1")->set( predir*fabs(root2[dir]) ); + getPntrToComponent("dist2")->set( fabs(root1[dir]) ); } getPntrToComponent("qdist")->set( root2[dir]*root1[dir] ); // Now calculate the derivatives - if( !doNotCalculateDerivatives() ){ - Value* ival=myvalue_vessel->getFinalValue(); ival->clearDerivatives(); - std::vector root1v(3); for(unsigned i=0;i<3;++i) root1v[i]=root1[i]; - derivTime=true; std::vector der(3); getDifferenceFromContour( root1v, der ); double prefactor; - if( mybasemulticolvars[0]->isDensity() ) prefactor = root2[dir] / myderiv_vessel->getOutputValue(); - else plumed_error(); - Value* val=getPntrToComponent("qdist"); - for(unsigned i=0;igetNumberOfDerivatives();++i) val->setDerivative( i, -prefactor*ival->getDerivative(i) ); - ival->clearDerivatives(); - std::vector root2v(3); for(unsigned i=0;i<3;++i) root2v[i]=root2[i]; - getDifferenceFromContour( root2v, der ); - if( mybasemulticolvars[0]->isDensity() ) prefactor = root1[dir] / myderiv_vessel->getOutputValue(); - else plumed_error(); - for(unsigned i=0;igetNumberOfDerivatives();++i) val->addDerivative( i, -prefactor*ival->getDerivative(i) ); + if( !doNotCalculateDerivatives() ) { + Value* ival=myvalue_vessel->getFinalValue(); ival->clearDerivatives(); + std::vector root1v(3); for(unsigned i=0; i<3; ++i) root1v[i]=root1[i]; + derivTime=true; std::vector der(3); getDifferenceFromContour( root1v, der ); double prefactor; + if( mybasemulticolvars[0]->isDensity() ) prefactor = root2[dir] / myderiv_vessel->getOutputValue(); + else plumed_error(); + Value* val=getPntrToComponent("qdist"); + for(unsigned i=0; igetNumberOfDerivatives(); ++i) val->setDerivative( i, -prefactor*ival->getDerivative(i) ); + ival->clearDerivatives(); + std::vector root2v(3); for(unsigned i=0; i<3; ++i) root2v[i]=root2[i]; + getDifferenceFromContour( root2v, der ); + if( mybasemulticolvars[0]->isDensity() ) prefactor = root1[dir] / myderiv_vessel->getOutputValue(); + else plumed_error(); + for(unsigned i=0; igetNumberOfDerivatives(); ++i) val->addDerivative( i, -prefactor*ival->getDerivative(i) ); } } -double DistanceFromContour::getDifferenceFromContour( const std::vector& x, std::vector& der ){ - std::string min, max; - for(unsigned j=0;j<3;++j){ - Tools::convert( -0.5*getBox()(j,j), min ); - Tools::convert( +0.5*getBox()(j,j), max ); - pval[j]->setDomain( min, max ); pval[j]->set( x[j] ); +double DistanceFromContour::getDifferenceFromContour( const std::vector& x, std::vector& der ) { + std::string min, max; + for(unsigned j=0; j<3; ++j) { + Tools::convert( -0.5*getBox()(j,j), min ); + Tools::convert( +0.5*getBox()(j,j), max ); + pval[j]->setDomain( min, max ); pval[j]->set( x[j] ); } runAllTasks(); return myvalue_vessel->getOutputValue() - contour; @@ -306,24 +306,24 @@ double DistanceFromContour::getDifferenceFromContour( const std::vector& double DistanceFromContour::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { Vector distance = getSeparation( getPosition(getNumberOfAtoms()-1), myatoms.getPosition(0) ); - std::vector pp(3), der(3,0); for(unsigned j=0;j<3;++j) pp[j] = distance[j]; + std::vector pp(3), der(3,0); for(unsigned j=0; j<3; ++j) pp[j] = distance[j]; // Now create the kernel and evaluate KernelFunctions kernel( pp, bw, kerneltype, false, 1.0, true ); double newval = kernel.evaluate( pval, der, true ); - if( mybasemulticolvars[0]->isDensity() ){ - if( !doNotCalculateDerivatives() && derivTime ){ - MultiValue& myvals=myatoms.getUnderlyingMultiValue(); - Vector vder; unsigned basen=myvals.getNumberOfDerivatives() - 12; - for(unsigned i=0;i<3;++i){ - vder[i]=der[i]; myvals.addDerivative( 1, basen+i, vder[i] ); - } - myatoms.setValue( 2, der[dir] ); - addAtomDerivatives( 1, 0, -vder, myatoms ); - myatoms.addBoxDerivatives( 1, Tensor(vder,distance) ); + if( mybasemulticolvars[0]->isDensity() ) { + if( !doNotCalculateDerivatives() && derivTime ) { + MultiValue& myvals=myatoms.getUnderlyingMultiValue(); + Vector vder; unsigned basen=myvals.getNumberOfDerivatives() - 12; + for(unsigned i=0; i<3; ++i) { + vder[i]=der[i]; myvals.addDerivative( 1, basen+i, vder[i] ); } - myatoms.setValue( 0, 1.0 ); return newval; + myatoms.setValue( 2, der[dir] ); + addAtomDerivatives( 1, 0, -vder, myatoms ); + myatoms.addBoxDerivatives( 1, Tensor(vder,distance) ); + } + myatoms.setValue( 0, 1.0 ); return newval; } // This does the stuff for averaging @@ -332,10 +332,10 @@ double DistanceFromContour::compute( const unsigned& tindex, AtomValuePack& myat // This gets the average if we are using a phase field std::vector cvals( mybasemulticolvars[0]->getNumberOfQuantities() ); mybasedata[0]->retrieveValueWithIndex( tindex, false, cvals ); - return newval*cvals[0]*cvals[1]; + return newval*cvals[0]*cvals[1]; } -void DistanceFromContour::apply(){ +void DistanceFromContour::apply() { if( getPntrToComponent("qdist")->applyForce( forces ) ) setForcesOnAtoms( forces ); } diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp index 4ea6d867e9..d5cb8fde00 100644 --- a/src/multicolvar/Distances.cpp +++ b/src/multicolvar/Distances.cpp @@ -30,17 +30,17 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR DISTANCES /* Calculate the distances between one or many pairs of atoms. You can then calculate functions of the distribution of -distances such as the minimum, the number less than a certain quantity and so on. +distances such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the distances between atoms 3 and 5 and between atoms 1 and 2 and to +The following input tells plumed to calculate the distances between atoms 3 and 5 and between atoms 1 and 2 and to print the minimum for these two distances. \verbatim DISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 @@ -70,7 +70,7 @@ In other words the distances between atoms 1 and 2 and the distance between atom more than 0.1 is then printed to a file. \verbatim DISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) @@ -80,7 +80,7 @@ PRINT ARG=d1.gt0.1 To calculate and print the minimum distance between two groups of atoms you use the following commands \verbatim -d1: DISTANCES GROUPA=1-10 GROUPB=11-20 MIN={BETA=500.} +d1: DISTANCES GROUPA=1-10 GROUPB=11-20 MIN={BETA=500.} PRINT ARG=d1.min FILE=colvar STRIDE=10 \endverbatim (see \ref DISTANCES and \ref PRINT) @@ -93,29 +93,29 @@ s = \frac{\beta}{ \log \sum_i \exp\left( \frac{\beta}{s_i} \right) } where \f$\beta\f$ is a user specified parameter. -This input is used rather than a separate MINDIST colvar so that the same routine and the same input style can be -used to calculate minimum coordinatetion numbers (see \ref COORDINATIONNUMBER), minimum -angles (see \ref ANGLES) and many other variables. +This input is used rather than a separate MINDIST colvar so that the same routine and the same input style can be +used to calculate minimum coordinatetion numbers (see \ref COORDINATIONNUMBER), minimum +angles (see \ref ANGLES) and many other variables. This new way of calculating mindist is part of plumed 2's multicolvar functionality. These special actions -allow you to calculate multiple functions of a distribution of simple collective variables. As an example you +allow you to calculate multiple functions of a distribution of simple collective variables. As an example you can calculate the number of distances less than 1.0, the minimum distance, the number of distances more than 2.0 and the number of distances between 1.0 and 2.0 by using the following command: \verbatim DISTANCES ... - GROUPA=1-10 GROUPB=11-20 - LESS_THAN={RATIONAL R_0=1.0} - MORE_THAN={RATIONAL R_0=2.0} - BETWEEN={GAUSSIAN LOWER=1.0 UPPER=2.0} + GROUPA=1-10 GROUPB=11-20 + LESS_THAN={RATIONAL R_0=1.0} + MORE_THAN={RATIONAL R_0=2.0} + BETWEEN={GAUSSIAN LOWER=1.0 UPPER=2.0} MIN={BETA=500.} ... DISTANCES PRINT ARG=d1.lessthan,d1.morethan,d1.between,d1.min FILE=colvar STRIDE=10 \endverbatim (see \ref DISTANCES and \ref PRINT) -A calculation performed this way is fast because the expensive part of the calculation - the calculation of all the distances - is only -done once per step. Furthermore, it can be made faster by using the TOL keyword to discard those distance that make only a small contributions +A calculation performed this way is fast because the expensive part of the calculation - the calculation of all the distances - is only +done once per step. Furthermore, it can be made faster by using the TOL keyword to discard those distance that make only a small contributions to the final values together with the NL_STRIDE keyword, which ensures that the distances that make only a small contribution to the final values aren't calculated at every step. @@ -131,35 +131,35 @@ class Distances : public MultiColvarBase { // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(Distances,"DISTANCES") -void Distances::registerKeywords( Keywords& keys ){ +void Distances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); // keys.use("DHENERGY"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the distances you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); } Distances::Distances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms - std::vector all_atoms; + std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); if( atom_lab.size()==0 ) readAtomsLikeKeyword( "ATOMS", 2, all_atoms ); setupMultiColvarBase( all_atoms ); @@ -168,44 +168,44 @@ MultiColvarBase(ao) // Now check if we can use link cells bool use_link=false; double rcut; - if( getNumberOfVessels()>0 ){ - vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); - if( lt ){ - use_link=true; rcut=lt->getCutoff(); - } else { - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); - if( bt ){ use_link=true; rcut=bt->getCutoff(); } - } - if( use_link ){ - for(unsigned i=1;i( getPntrToVessel(i) ); - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); - if( lt2 ){ - double tcut=lt2->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else if( bt ){ - double tcut=bt->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else { - use_link=false; - } - } - } - if( use_link ) setLinkCellCutoff( rcut ); + if( getNumberOfVessels()>0 ) { + vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); + if( lt ) { + use_link=true; rcut=lt->getCutoff(); + } else { + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); + if( bt ) { use_link=true; rcut=bt->getCutoff(); } + } + if( use_link ) { + for(unsigned i=1; i( getPntrToVessel(i) ); + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); + if( lt2 ) { + double tcut=lt2->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else if( bt ) { + double tcut=bt->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else { + use_link=false; + } + } + } + if( use_link ) setLinkCellCutoff( rcut ); } } double Distances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector distance; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - const double value=distance.modulo(); - const double invvalue=1.0/value; - - // And finish the calculation - addAtomDerivatives( 1, 0,-invvalue*distance, myatoms ); - addAtomDerivatives( 1, 1, invvalue*distance, myatoms ); - myatoms.addBoxDerivatives( 1, -invvalue*Tensor(distance,distance) ); - return value; + Vector distance; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + const double value=distance.modulo(); + const double invvalue=1.0/value; + + // And finish the calculation + addAtomDerivatives( 1, 0,-invvalue*distance, myatoms ); + addAtomDerivatives( 1, 1, invvalue*distance, myatoms ); + myatoms.addBoxDerivatives( 1, -invvalue*Tensor(distance,distance) ); + return value; } } diff --git a/src/multicolvar/DumpMultiColvar.cpp b/src/multicolvar/DumpMultiColvar.cpp index 39760fbd46..27029a4369 100644 --- a/src/multicolvar/DumpMultiColvar.cpp +++ b/src/multicolvar/DumpMultiColvar.cpp @@ -40,13 +40,13 @@ namespace PLMD { namespace multicolvar { -//+PLUMEDOC PRINTANALYSIS DUMPMULTICOLVAR +//+PLUMEDOC PRINTANALYSIS DUMPMULTICOLVAR /* Dump atom positions and multicolvar on a file. \par Examples -In this examples we calculate the distances between the atoms of the first and the second -group and we write them in the file MULTICOLVAR.xyz. For each couple it writes the +In this examples we calculate the distances between the atoms of the first and the second +group and we write them in the file MULTICOLVAR.xyz. For each couple it writes the coordinates of their geometric center and their distance. \verbatim @@ -69,21 +69,21 @@ class DumpMultiColvar: { OFile of; double lenunit; - MultiColvarBase* mycolv; + MultiColvarBase* mycolv; std::string fmt_xyz; public: explicit DumpMultiColvar(const ActionOptions&); ~DumpMultiColvar(); static void registerKeywords( Keywords& keys ); - void calculate(){} - void calculateNumericalDerivatives( ActionWithValue* vv ){ plumed_error(); } - void apply(){} + void calculate() {} + void calculateNumericalDerivatives( ActionWithValue* vv ) { plumed_error(); } + void apply() {} void update(); }; PLUMED_REGISTER_ACTION(DumpMultiColvar,"DUMPMULTICOLVAR") -void DumpMultiColvar::registerKeywords( Keywords& keys ){ +void DumpMultiColvar::registerKeywords( Keywords& keys ) { Action::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); @@ -103,7 +103,7 @@ DumpMultiColvar::DumpMultiColvar(const ActionOptions&ao): { readArgument("store"); mycolv = dynamic_cast( getDependencies()[0] ); - plumed_assert( getDependencies().size()==1 ); + plumed_assert( getDependencies().size()==1 ); if(!mycolv) error("action labeled " + mycolv->getLabel() + " is not a multicolvar"); log.printf(" printing colvars calculated by action %s \n",mycolv->getLabel().c_str() ); @@ -121,7 +121,7 @@ DumpMultiColvar::DumpMultiColvar(const ActionOptions&ao): fmt_xyz="%f"; string precision; parse("PRECISION",precision); - if(precision.length()>0){ + if(precision.length()>0) { int p; Tools::convert(precision,p); log<<" with precision "<getCurrentNumberOfActiveTasks()); const Tensor & t(mycolv->getPbc().getBox()); - if(mycolv->getPbc().isOrthorombic()){ + if(mycolv->getPbc().isOrthorombic()) { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(),lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ + } else { of.printf((" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz+"\n").c_str(), - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); } vesselbase::StoreDataVessel* stash=dynamic_cast( getPntrToArgument() ); plumed_dbg_assert( stash ); std::vector cvals( mycolv->getNumberOfQuantities() ); - for(unsigned i=0;igetCurrentNumberOfActiveTasks();++i){ + for(unsigned i=0; igetCurrentNumberOfActiveTasks(); ++i) { const char* defname="X"; const char* name=defname; @@ -167,18 +167,18 @@ void DumpMultiColvar::update(){ if( getNumberOfAtoms()>0 ) apos=pbcDistance( getPosition(0), apos ); of.printf(("%s "+fmt_xyz+" "+fmt_xyz+" "+fmt_xyz).c_str(),name,lenunit*apos[0],lenunit*apos[1],lenunit*apos[2]); stash->retrieveSequentialValue( i, true, cvals ); - if( mycolv->weightWithDerivatives() ){ - for(unsigned j=0;jweightWithDerivatives() ) { + for(unsigned j=0; jisPeriodic() ){ - std::string min, max; getPntrToMultiColvar()->retrieveDomain( min, max ); - double mlow, mhigh; Tools::convert( min,mlow ); Tools::convert( max, mhigh); - hb.isPeriodic( mlow, mhigh ); + if( getPntrToMultiColvar()->isPeriodic() ) { + std::string min, max; getPntrToMultiColvar()->retrieveDomain( min, max ); + double mlow, mhigh; Tools::convert( min,mlow ); Tools::convert( max, mhigh); + hb.isPeriodic( mlow, mhigh ); } else { - hb.isNotPeriodic(); + hb.isNotPeriodic(); } - if(sw.length()>0){ - hb.set(sw,errors); - if( errors.length()!=0 ) error("problem reading BEAD keyword : " + errors ); + if(sw.length()>0) { + hb.set(sw,errors); + if( errors.length()!=0 ) error("problem reading BEAD keyword : " + errors ); } else { - double l, u, s; std::string ll, uu, ss; - parse("LOWER",l); parse("UPPER",u); parse("SMEAR",s); - Tools::convert(l,ll); Tools::convert(u,uu); Tools::convert(s,ss); - sw="GAUSSIAN LOWER=" + ll + " UPPER=" + uu + " SMEAR=" + ss; - hb.set(sw,errors); plumed_massert(errors.length()==0,"problems with bead" + errors); + double l, u, s; std::string ll, uu, ss; + parse("LOWER",l); parse("UPPER",u); parse("SMEAR",s); + Tools::convert(l,ll); Tools::convert(u,uu); Tools::convert(s,ss); + sw="GAUSSIAN LOWER=" + ll + " UPPER=" + uu + " SMEAR=" + ss; + hb.set(sw,errors); plumed_massert(errors.length()==0,"problems with bead" + errors); } log.printf(" filtering colvar values and focussing only on those values in range %s\n",( hb.description() ).c_str() ); - checkRead(); + checkRead(); } double FilterBetween::applyFilter( const double& val, double& df ) const { - double f = hb.calculate( val, df ); + double f = hb.calculate( val, df ); return f; } diff --git a/src/multicolvar/FilterLessThan.cpp b/src/multicolvar/FilterLessThan.cpp index e24d8ad23c..6363bcbb43 100644 --- a/src/multicolvar/FilterLessThan.cpp +++ b/src/multicolvar/FilterLessThan.cpp @@ -27,9 +27,9 @@ /* This action can be useed to transform the colvar values calculated by a multicolvar using a \ref switchingfunction -In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that -is equal to one if the colvar is less than a certain target value and which is equal to zero otherwise. -It is important to understand the distinction between what is done here and what is done by \ref MFILTER_LESS. +In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that +is equal to one if the colvar is less than a certain target value and which is equal to zero otherwise. +It is important to understand the distinction between what is done here and what is done by \ref MFILTER_LESS. In \ref MFILTER_LESS a weight, \f$w_i\f$ for the colvar is calculated using the \ref switchingfunction. If one calculates the MEAN for \ref MFILTER_LESS one is thus calculating: @@ -37,19 +37,19 @@ MEAN for \ref MFILTER_LESS one is thus calculating: \mu = \frac{ \sum_i \sigma(s_i) s_i }{\sum_i \simga(s_i) } \f] -where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by +where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. If one thus calculates a MEAN for thia action one computes: \f[ -\mu = \frac{ \sum_{i=1}^N \simga(s_i) }{ N } +\mu = \frac{ \sum_{i=1}^N \simga(s_i) }{ N } \f] -In other words, you are calculating the mean for the transformed colvar. +In other words, you are calculating the mean for the transformed colvar. \par Examples -The following input gives an example of how a MTRANSFORM_LESS action can be used to duplicate -functionality that is elsehwere in PLUMED. +The following input gives an example of how a MTRANSFORM_LESS action can be used to duplicate +functionality that is elsehwere in PLUMED. \verbatim DISTANCES ... @@ -63,30 +63,30 @@ In this case you can achieve the same result by using: \verbatim DISTANCES ... - GROUPA=1-10 GROUPB=11-20 + GROUPA=1-10 GROUPB=11-20 LESS_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} ... DISTANCES \endverbatim (see \ref DISTANCES) The advantage of MTRANSFORM_LESS comes, however, if you want to use transformed colvars as input -for \ref MULTICOLVARDENS +for \ref MULTICOLVARDENS */ //+ENDPLUMEDOC //+PLUMEDOC MFILTERS MFILTER_LESS /* -This action can be used to filter the distribution of colvar values in a multicolvar +This action can be used to filter the distribution of colvar values in a multicolvar so that one can compute the mean and so on for only those multicolvars less than a tolerance. This action can be used to create a dynamic group of atom based on the value of a multicolvar. In this action a multicolvar is within the dynamic group if its value is less than a target. In practise a weight, \f$w_i\f$ is ascribed to each colvar, \f$s_i\f$ calculated by a multicolvar -and this weight measures the degree to which a colvar is a member of the group. This weight is a number -between 0 and 1 that is calculated using a \ref switchingfunction , \f$\sigma\f$. +and this weight measures the degree to which a colvar is a member of the group. This weight is a number +between 0 and 1 that is calculated using a \ref switchingfunction , \f$\sigma\f$. If one calculates a function of the set of multicolvars -these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered +these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered multicolvar what is computed is the following: \f[ @@ -117,41 +117,41 @@ class FilterLess : public MultiColvarFilter { static void registerKeywords( Keywords& keys ); explicit FilterLess(const ActionOptions& ao); double applyFilter( const double& val, double& df ) const ; -}; +}; PLUMED_REGISTER_ACTION(FilterLess,"MFILTER_LESS") PLUMED_REGISTER_ACTION(FilterLess,"MTRANSFORM_LESS") -void FilterLess::registerKeywords( Keywords& keys ){ +void FilterLess::registerKeywords( Keywords& keys ) { MultiColvarFilter::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function "); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); } FilterLess::FilterLess(const ActionOptions& ao): -Action(ao), -MultiColvarFilter(ao) + Action(ao), + MultiColvarFilter(ao) { // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - sf.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if(sw.length()>0) { + sf.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - sf.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + sf.set(nn,mm,r_0,d_0); } log.printf(" filtering colvar values and focussing only on those less than %s\n",( sf.description() ).c_str() ); - checkRead(); + checkRead(); } double FilterLess::applyFilter( const double& val, double& df ) const { diff --git a/src/multicolvar/FilterMoreThan.cpp b/src/multicolvar/FilterMoreThan.cpp index 2c0f0e68e6..961c33d016 100644 --- a/src/multicolvar/FilterMoreThan.cpp +++ b/src/multicolvar/FilterMoreThan.cpp @@ -27,9 +27,9 @@ /* This action can be useed to transform the colvar values calculated by a multicolvar using one minus a \ref switchingfunction -In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that -is equal to one if the colvar is greater than a certain target value and which is equal to zero otherwise. -It is important to understand the distinction between what is done here and what is done by \ref MFILTER_MORE. +In this action each colvar, \f$s_i\f$, calculated by multicolvar is transformed by a \ref switchingfunction function that +is equal to one if the colvar is greater than a certain target value and which is equal to zero otherwise. +It is important to understand the distinction between what is done here and what is done by \ref MFILTER_MORE. In \ref MFILTER_MORE a weight, \f$w_i\f$ for the colvar is calculated using the \ref histogrambead. If one calculates the MEAN for \ref MFILTER_MORE one is thus calculating: @@ -37,19 +37,19 @@ MEAN for \ref MFILTER_MORE one is thus calculating: \mu = \frac{ \sum_i [1 - \sigma(s_i) ] s_i }{\sum_i [1 - \sigma(s_i)] } \f] -where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. +where \f$\sigma\f$ is the \ref switchingfunction. In this action by contrast the colvar is being transformed by the \ref switchingfunction. If one thus calculates a MEAN for this action one computes: \f[ -\mu = \frac{ \sum_{i=1}^N 1 - \sigma(s_i) }{ N } +\mu = \frac{ \sum_{i=1}^N 1 - \sigma(s_i) }{ N } \f] -In other words, you are calculating the mean for the transformed colvar. +In other words, you are calculating the mean for the transformed colvar. \par Examples -The following input gives an example of how a MTRANSFORM_MORE action can be used to duplicate -functionality that is elsehwere in PLUMED. +The following input gives an example of how a MTRANSFORM_MORE action can be used to duplicate +functionality that is elsehwere in PLUMED. \verbatim DISTANCES ... @@ -63,27 +63,27 @@ In this case you can achieve the same result by using: \verbatim DISTANCES ... - GROUPA=1-10 GROUPB=11-20 + GROUPA=1-10 GROUPB=11-20 MORE_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} ... DISTANCES \endverbatim (see \ref DISTANCES) The advantage of MTRANSFORM_MORE comes, however, if you want to use transformed colvars as input -for \ref MULTICOLVARDENS +for \ref MULTICOLVARDENS */ //+ENDPLUMEDOC //+PLUMEDOC MFILTERS MFILTER_MORE /* -This action can be used to filter the distribution of colvar values in a multicolvar +This action can be used to filter the distribution of colvar values in a multicolvar so that one can compute the mean and so on for only those multicolvars more than a tolerance. This action can be used to create a dynamic group of atom based on the value of a multicolvar. In this action a multicolvar is within the dynamic group if its value is greater than a target. In practise a weight, \f$w_i\f$ is ascribed to each colvar, \f$s_i\f$ calculated by a multicolvar -and this weight measures the degree to which a colvar is a member of the group. This weight is +and this weight measures the degree to which a colvar is a member of the group. This weight is calculated using a \ref switchingfunction , \f$\sigma\f$ so it is given by: \f[ @@ -91,7 +91,7 @@ w_i = 1 - \sigma(s_i) \f] If one calculates a function of the set of multicolvars -these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered +these weights are included in the calculation. As such if one calculates the MEAN, \f$\mu\f$ of a filtered multicolvar what is computed is the following: \f[ @@ -109,10 +109,10 @@ DISTANCES GROUPA=1 GROUPB=2-50 MEAN LABEL=d1 MFILTER_MORE DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} MEAN LABEL=d4 \endverbatim -More complicated things can be done by using the label of a filter as input to a new multicolvar as shown -in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination +More complicated things can be done by using the label of a filter as input to a new multicolvar as shown +in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination number greater than 2 are then identified using the filter. This reduced list of atoms is then used as input -to a second coordination number calculation. This second coordination number thus measures the number of +to a second coordination number calculation. This second coordination number thus measures the number of two-coordinated atoms that each of the two-coordinated atoms is bound to. \verbatim @@ -134,41 +134,41 @@ class FilterMore : public MultiColvarFilter { static void registerKeywords( Keywords& keys ); explicit FilterMore(const ActionOptions& ao); double applyFilter( const double& val, double& df ) const ; -}; +}; PLUMED_REGISTER_ACTION(FilterMore,"MFILTER_MORE") PLUMED_REGISTER_ACTION(FilterMore,"MTRANSFORM_MORE") -void FilterMore::registerKeywords( Keywords& keys ){ +void FilterMore::registerKeywords( Keywords& keys ) { MultiColvarFilter::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); } FilterMore::FilterMore(const ActionOptions& ao): -Action(ao), -MultiColvarFilter(ao) + Action(ao), + MultiColvarFilter(ao) { // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - sf.set(sw,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + if(sw.length()>0) { + sf.set(sw,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - sf.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + sf.set(nn,mm,r_0,d_0); } log.printf(" filtering colvar values and focussing only on those more than %s\n",( sf.description() ).c_str() ); - checkRead(); + checkRead(); } double FilterMore::applyFilter( const double& val, double& df ) const { diff --git a/src/multicolvar/InPlaneDistances.cpp b/src/multicolvar/InPlaneDistances.cpp index 1801e31bf6..d041fa1e02 100644 --- a/src/multicolvar/InPlaneDistances.cpp +++ b/src/multicolvar/InPlaneDistances.cpp @@ -32,14 +32,14 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR INPLANEDISTANCES /* Calculate distances in the plane perpendicular to an axis -Each quantity calculated in this CV uses the positions of two atoms, this indices of which are specified using the VECTORSTART and VECTOREND keywords, to specify the +Each quantity calculated in this CV uses the positions of two atoms, this indices of which are specified using the VECTORSTART and VECTOREND keywords, to specify the orientation of a vector, \f$\mathbf{n}\f$. The perpendicular distance between this vector and the position of some third atom is then computed using: \f[ x_j = |\mathbf{r}_{j}| \sin (\theta_j) @@ -50,8 +50,8 @@ Keywords such as MORE_THAN and LESS_THAN can then be used to calculate the numbe \par Examples -The following input can be used to calculate the number of atoms that have indices greater than 3 and less than 101 that -are within a cylinder with a radius of 0.3 nm that has its long axis aligned with the vector connecting atoms 1 and 2. +The following input can be used to calculate the number of atoms that have indices greater than 3 and less than 101 that +are within a cylinder with a radius of 0.3 nm that has its long axis aligned with the vector connecting atoms 1 and 2. \verbatim d1: INPLANEDISTANCES VECTORSTART=1 VECTOREND=2 GROUP=3-100 LESS_THAN={RATIONAL D_0=0.2 R_0=0.1} @@ -67,16 +67,16 @@ class InPlaneDistances : public MultiColvarBase { static void registerKeywords( Keywords& keys ); explicit InPlaneDistances(const ActionOptions&); // active methods: - virtual double compute(const unsigned& tindex, AtomValuePack& myatoms ) const ; - bool isPeriodic(){ return false; } + virtual double compute(const unsigned& tindex, AtomValuePack& myatoms ) const ; + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(InPlaneDistances,"INPLANEDISTANCES") -void InPlaneDistances::registerKeywords( Keywords& keys ){ +void InPlaneDistances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.use("ALT_MIN"); keys.use("LOWEST"); keys.use("HIGHEST"); - keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); + keys.use("MEAN"); keys.use("MIN"); keys.use("MAX"); keys.use("LESS_THAN"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("atoms","VECTORSTART","The first atom position that is used to define the normal to the plane of interest"); keys.add("atoms","VECTOREND","The second atom position that is used to defin the normal to the plane of interest"); @@ -84,8 +84,8 @@ void InPlaneDistances::registerKeywords( Keywords& keys ){ } InPlaneDistances::InPlaneDistances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // Read in the atoms std::vector all_atoms; @@ -99,32 +99,32 @@ MultiColvarBase(ao) // And check everything has been read in correctly checkRead(); - // Now check if we can use link cells +// Now check if we can use link cells bool use_link=false; double rcut; - if( getNumberOfVessels()>0 ){ - vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); - if( lt ){ - use_link=true; rcut=lt->getCutoff(); - } else { - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); - if( bt ) use_link=true; rcut=bt->getCutoff(); - } - if( use_link ){ - for(unsigned i=1;i( getPntrToVessel(i) ); - vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); - if( lt2 ){ - double tcut=lt2->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else if( bt ){ - double tcut=bt->getCutoff(); - if( tcut>rcut ) rcut=tcut; - } else { - use_link=false; - } - } - } - if( use_link ) setLinkCellCutoff( rcut ); + if( getNumberOfVessels()>0 ) { + vesselbase::LessThan* lt=dynamic_cast( getPntrToVessel(0) ); + if( lt ) { + use_link=true; rcut=lt->getCutoff(); + } else { + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(0) ); + if( bt ) use_link=true; rcut=bt->getCutoff(); + } + if( use_link ) { + for(unsigned i=1; i( getPntrToVessel(i) ); + vesselbase::Between* bt=dynamic_cast( getPntrToVessel(i) ); + if( lt2 ) { + double tcut=lt2->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else if( bt ) { + double tcut=bt->getCutoff(); + if( tcut>rcut ) rcut=tcut; + } else { + use_link=false; + } + } + } + if( use_link ) setLinkCellCutoff( rcut ); } } @@ -132,7 +132,7 @@ double InPlaneDistances::compute( const unsigned& tindex, AtomValuePack& myatoms Vector normal=getSeparation( myatoms.getPosition(1), myatoms.getPosition(2) ); Vector dir=getSeparation( myatoms.getPosition(1), myatoms.getPosition(0) ); PLMD::Angle a; Vector ddij, ddik; double angle=a.compute(normal,dir,ddij,ddik); - double sangle=sin(angle), cangle=cos(angle); + double sangle=sin(angle), cangle=cos(angle); double dd=dir.modulo(), invdd=1.0/dd, val=dd*sangle; addAtomDerivatives( 1, 0, dd*cangle*ddik + sangle*invdd*dir, myatoms ); diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index 1e1d5c6c02..fdc3e09c4f 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -29,29 +29,29 @@ Calculate averages over spherical regions centered on atoms As is explained in this video certain multicolvars -calculate one scalar quantity or one vector for each of the atoms in the system. For example +calculate one scalar quantity or one vector for each of the atoms in the system. For example \ref COORDINATIONNUMBER measures the coordination number of each of the atoms in the system and \ref Q4 measures the 4th order Steinhardt parameter for each of the atoms in the system. These quantities provide tell us something about the disposition of the atoms in the first coordination sphere of each of the atoms of interest. Lechner and Dellago \cite dellago-q6 have suggested that one can probe local order in a system by taking the average value of such symmetry functions over the atoms within a spherical cutoff of each of these atoms in the systems. When this is done with Steinhardt parameters -they claim this gives a coordinate that is better able to distinguish solid and liquid configurations of Lennard-Jones atoms. +they claim this gives a coordinate that is better able to distinguish solid and liquid configurations of Lennard-Jones atoms. -You can calculate such locally averaged quantities within plumed by using the LOCAL_AVERAGE command. This command calculates +You can calculate such locally averaged quantities within plumed by using the LOCAL_AVERAGE command. This command calculates the following atom-centered quantities: \f[ -s_i = \frac{ c_i + \sum_j \sigma(r_{ij})c_j }{ 1 + \sum_j \sigma(r_{ij}) } +s_i = \frac{ c_i + \sum_j \sigma(r_{ij})c_j }{ 1 + \sum_j \sigma(r_{ij}) } \f] -where the \f$c_i\f$ and \f$c_j\f$ values can be for any one of the symmetry functions that can be calculated using plumed -multicolvars. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between +where the \f$c_i\f$ and \f$c_j\f$ values can be for any one of the symmetry functions that can be calculated using plumed +multicolvars. The function \f$\sigma( r_{ij} )\f$ is a \ref switchingfunction that acts on the distance between atoms \f$i\f$ and \f$j\f$. Lechner and Dellago suggest that the parameters of this function should be set so that it the function is equal to one -when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. +when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zero otherwise. -The \f$s_i\f$ quantities calculated using the above command can be again thought of as atom-centred symmetry functions. They +The \f$s_i\f$ quantities calculated using the above command can be again thought of as atom-centred symmetry functions. They thus operate much like multicolvars. You can thus calculate properties of the distribution of \f$s_i\f$ values using MEAN, LESS_THAN, HISTOGRAM -and so on. You can also probe the value of these averaged variables in regions of the box by using the command in tandem with the +and so on. You can also probe the value of these averaged variables in regions of the box by using the command in tandem with the \ref AROUND command. \par Examples @@ -62,12 +62,12 @@ spherical regions. The number of averaged coordination numbers that are greater \verbatim COORDINATIONNUMBER SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=d1 LOCAL_AVERAGE ARG=d1 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MORE_THAN={RATIONAL R_0=4} LABEL=la -PRINT ARG=la.* FILE=colvar +PRINT ARG=la.* FILE=colvar \endverbatim -This example input calculates the \f$q_4\f$ (see \ref Q4) vectors for each of the atoms in the system. These vectors are then averaged -component by component over a spherical region. The average value for this quantity is then outputeed to a file. This calculates the -quantities that were used in the paper by Lechner and Dellago \cite dellago-q6 +This example input calculates the \f$q_4\f$ (see \ref Q4) vectors for each of the atoms in the system. These vectors are then averaged +component by component over a spherical region. The average value for this quantity is then outputeed to a file. This calculates the +quantities that were used in the paper by Lechner and Dellago \cite dellago-q6 \verbatim Q4 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q4 @@ -95,49 +95,49 @@ class LocalAverage : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(LocalAverage,"LOCAL_AVERAGE") -void LocalAverage::registerKeywords( Keywords& keys ){ +void LocalAverage::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","NN","6","The n parameter of the switching function "); keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords keys.use("SPECIES"); keys.use("SPECIESA"); keys.use("SPECIESB"); keys.remove("LOWMEM"); keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); - keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); + keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); if( keys.reserved("VMEAN") ) keys.use("VMEAN"); if( keys.reserved("VSUM") ) keys.use("VSUM"); } LocalAverage::LocalAverage(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { if( getNumberOfBaseMultiColvars()>1 ) error("local average with more than one base colvar makes no sense"); // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" averaging over central molecule and those within %s\n",( switchingFunction.description() ).c_str() ); rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); setLinkCellCutoff( switchingFunction.get_dmax() ); - std::vector all_atoms; setupMultiColvarBase( all_atoms ); + std::vector all_atoms; setupMultiColvarBase( all_atoms ); } unsigned LocalAverage::getNumberOfQuantities() const { @@ -146,113 +146,113 @@ unsigned LocalAverage::getNumberOfQuantities() const { double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { double d2, sw, dfunc; MultiValue& myvals = myatoms.getUnderlyingMultiValue(); - std::vector values( getBaseMultiColvar(0)->getNumberOfQuantities() ); + std::vector values( getBaseMultiColvar(0)->getNumberOfQuantities() ); getInputData( 0, false, myatoms, values ); myvals.addTemporyValue( values[0] ); - if( values.size()>2 ){ - for(unsigned j=2;j2 ) { + for(unsigned j=2; j2 ){ - for(unsigned j=0;j2 ) { + for(unsigned j=0; j2 ){ - for(unsigned j=2;j2 ){ - for(unsigned j=0;j2 ) { + for(unsigned j=2; j2 ) { + for(unsigned j=0; j2){ - double norm=0; - for(unsigned i=2;i2) { + double norm=0; + for(unsigned i=2; i& all_atoms ){ +void MultiColvarBase::readAtomsLikeKeyword( const std::string & key, const int& natoms, std::vector& all_atoms ) { plumed_assert( !usespecies ); if( all_atoms.size()>0 ) return; std::vector t; - for(int i=1;;++i ){ - parseAtomList(key, i, t ); - if( t.empty() ) break; - - log.printf(" Colvar %d is calculated from atoms : ", i); - for(unsigned j=0;j( 0, ablocks.size()*(i-1)+j ) ); - } - t.resize(0); + for(int i=1;; ++i ) { + parseAtomList(key, i, t ); + if( t.empty() ) break; + + log.printf(" Colvar %d is calculated from atoms : ", i); + for(unsigned j=0; j( 0, ablocks.size()*(i-1)+j ) ); + } + t.resize(0); } - if( all_atoms.size()>0 ){ - nblock=0; - for(unsigned i=0;i0 ) { + nblock=0; + for(unsigned i=0; i& t){ - std::vector mlabs; +bool MultiColvarBase::parseMultiColvarAtomList(const std::string& key, const int& num, std::vector& t) { + std::vector mlabs; if( num<0 ) parseVector(key,mlabs); else parseNumberedVector(key,num,mlabs); if( mlabs.size()==0 ) return false; std::string mname; unsigned found_mcolv=mlabs.size(); - for(unsigned i=0;i(mlabs[i]); - if(!mycolv){ found_mcolv=i; break; } - // Check all base multicolvars are of same type - if( i==0 ){ - mname = mycolv->getName(); - if( mycolv->isPeriodic() ) error("multicolvar functions don't work with this multicolvar"); - } else { - if( mname!=mycolv->getName() ) error("All input multicolvars must be of same type"); - } - // And track which variable stores each colvar - for(unsigned j=0;jgetFullNumberOfTasks();++j) atom_lab.push_back( std::pair( mybasemulticolvars.size()+1, j ) ); - // And store the multicolvar base - mybasemulticolvars.push_back( mycolv ); - // And create a basedata stash - mybasedata.push_back( mybasemulticolvars[mybasemulticolvars.size()-1]->buildDataStashes( this ) ); - // Check if weight has derivatives - if( mybasemulticolvars[ mybasemulticolvars.size()-1 ]->weightHasDerivatives ) weightHasDerivatives=true; - plumed_assert( mybasemulticolvars.size()==mybasedata.size() ); + for(unsigned i=0; i(mlabs[i]); + if(!mycolv) { found_mcolv=i; break; } + // Check all base multicolvars are of same type + if( i==0 ) { + mname = mycolv->getName(); + if( mycolv->isPeriodic() ) error("multicolvar functions don't work with this multicolvar"); + } else { + if( mname!=mycolv->getName() ) error("All input multicolvars must be of same type"); + } + // And track which variable stores each colvar + for(unsigned j=0; jgetFullNumberOfTasks(); ++j) atom_lab.push_back( std::pair( mybasemulticolvars.size()+1, j ) ); + // And store the multicolvar base + mybasemulticolvars.push_back( mycolv ); + // And create a basedata stash + mybasedata.push_back( mybasemulticolvars[mybasemulticolvars.size()-1]->buildDataStashes( this ) ); + // Check if weight has derivatives + if( mybasemulticolvars[ mybasemulticolvars.size()-1 ]->weightHasDerivatives ) weightHasDerivatives=true; + plumed_assert( mybasemulticolvars.size()==mybasedata.size() ); } // Have we conventional atoms to read in - if( found_mcolv==0 ){ - std::vector tt; ActionAtomistic::interpretAtomList( mlabs, tt ); - for(unsigned i=0;i( 0, t.size() + i ) ); } - log.printf(" keyword %s takes atoms : ", key.c_str() ); - for(unsigned i=0;i tt; ActionAtomistic::interpretAtomList( mlabs, tt ); + for(unsigned i=0; i( 0, t.size() + i ) ); } + log.printf(" keyword %s takes atoms : ", key.c_str() ); + for(unsigned i=0; i& all_atoms ){ +void MultiColvarBase::readTwoGroups( const std::string& key0, const std::string& key1, const std::string& key2, std::vector& all_atoms ) { plumed_dbg_assert( keywords.exists(key0) && keywords.exists(key1) && keywords.exists(key2) ); ablocks.resize( 2 ); - if( parseMultiColvarAtomList(key0,-1,all_atoms) ){ - nblock=atom_lab.size(); for(unsigned i=0;i<2;++i) ablocks[i].resize(nblock); - resizeBookeepingArray( nblock, nblock ); - for(unsigned i=0;iablocks[1].size() ) nblock = ablocks[0].size(); - else nblock=ablocks[1].size(); - - resizeBookeepingArray( ablocks[0].size(), ablocks[1].size() ); - for(unsigned i=0;i0 && atom_lab[ablocks[1][j]].first>0 ){ - if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && - atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second ) addTaskToList( i*nblock + j ); - } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] ) addTaskToList( i*nblock + j ); - bookeeping(i,j).second=getFullNumberOfTasks(); - } + parseMultiColvarAtomList(key1,-1,all_atoms); + ablocks[0].resize( atom_lab.size() ); for(unsigned i=0; iablocks[1].size() ) nblock = ablocks[0].size(); + else nblock=ablocks[1].size(); + + resizeBookeepingArray( ablocks[0].size(), ablocks[1].size() ); + for(unsigned i=0; i0 && atom_lab[ablocks[1][j]].first>0 ) { + if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && + atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second ) addTaskToList( i*nblock + j ); + } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] ) addTaskToList( i*nblock + j ); + bookeeping(i,j).second=getFullNumberOfTasks(); } + } } } -void MultiColvarBase::readGroupKeywords( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& key3, - const bool& no_third_dim_accum, const bool& symmetric, std::vector& all_atoms ){ +void MultiColvarBase::readGroupKeywords( const std::string& key0, const std::string& key1, const std::string& key2, const std::string& key3, + const bool& no_third_dim_accum, const bool& symmetric, std::vector& all_atoms ) { plumed_dbg_assert( keywords.exists(key0) && keywords.exists(key1) && keywords.exists(key2) && keywords.exists(key3) ); ablocks.resize( 3 ); - if( parseMultiColvarAtomList(key0,-1,all_atoms) ){ - if( no_third_dim_accum ){ - nblock=atom_lab.size(); ablocks[0].resize(nblock); ablocks[1].resize( nblock ); - for(unsigned i=0;i& all_atoms ){ +void MultiColvarBase::readThreeGroups( const std::string& key1, const std::string& key2, const std::string& key3, + const bool& allow2, const bool& no_third_dim_accum, std::vector& all_atoms ) { plumed_dbg_assert( keywords.exists(key1) && keywords.exists(key2) && keywords.exists(key3) ); ablocks.resize( 3 ); bool readkey1=parseMultiColvarAtomList(key1,-1,all_atoms); - ablocks[0].resize( atom_lab.size() ); for(unsigned i=0;iablocks[0].size() ) nblock=ablocks[1].size(); - else nblock=ablocks[0].size(); - - ablocks[2].resize( ablocks[1].size() ); - for(unsigned i=0;i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ){ - if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && - atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && - all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && - all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } - bookeeping(i,j).second=getFullNumberOfTasks(); + if( !readkey3 && !allow2 ) { + error("missing atom specification " + key3); + } else if( !readkey3 ) { + if( ablocks[1].size()>ablocks[0].size() ) nblock=ablocks[1].size(); + else nblock=ablocks[0].size(); + + ablocks[2].resize( ablocks[1].size() ); + for(unsigned i=0; i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ) { + if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && + atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); + } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && + all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && + all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); } + bookeeping(i,j).second=getFullNumberOfTasks(); } + } } else { - ablocks[2].resize( atom_lab.size() - ablocks[1].size() - ablocks[0].size() ); - for(unsigned i=0;iablocks[0].size() ) nblock=ablocks[1].size(); - else nblock=ablocks[0].size(); - if( ablocks[2].size()>nblock ) nblock=ablocks[2].size(); - - unsigned kcount; if( no_third_dim_accum ) kcount=1; else kcount=ablocks[2].size(); - - for(unsigned i=0;i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ){ - if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && - atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && - atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && - all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && - all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); - } - bookeeping(i,j).second=getFullNumberOfTasks(); - } + ablocks[2].resize( atom_lab.size() - ablocks[1].size() - ablocks[0].size() ); + for(unsigned i=0; iablocks[0].size() ) nblock=ablocks[1].size(); + else nblock=ablocks[0].size(); + if( ablocks[2].size()>nblock ) nblock=ablocks[2].size(); + + unsigned kcount; if( no_third_dim_accum ) kcount=1; else kcount=ablocks[2].size(); + + for(unsigned i=0; i0 && atom_lab[ablocks[1][j]].first>0 && atom_lab[ablocks[2][k]].first>0 ) { + if( mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[0][i]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + mybasemulticolvars[atom_lab[ablocks[1][j]].first-1]->getLabel()!=mybasemulticolvars[atom_lab[ablocks[2][k]].first-1]->getLabel() && + atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[1][j]].second && atom_lab[ablocks[0][i]].second!=atom_lab[ablocks[2][k]].second && + atom_lab[ablocks[1][j]].second!=atom_lab[ablocks[2][k]].second ) addTaskToList( nblock*nblock*i + nblock*j + k ); + } else if( all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[1][j]].second] && + all_atoms[atom_lab[ablocks[0][i]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] && + all_atoms[atom_lab[ablocks[1][j]].second]!=all_atoms[atom_lab[ablocks[2][k]].second] ) addTaskToList( nblock*nblock*i + nblock*j + k ); + } + bookeeping(i,j).second=getFullNumberOfTasks(); } + } } } -void MultiColvarBase::buildSets(){ +void MultiColvarBase::buildSets() { std::vector fake_atoms; if( !parseMultiColvarAtomList("DATA",-1,fake_atoms) ) error("missing DATA keyword"); if( fake_atoms.size()>0 ) error("no atoms should appear in the specification for this object. Input should be other multicolvars"); nblock = mybasemulticolvars[0]->getFullNumberOfTasks(); - for(unsigned i=0;igetFullNumberOfTasks()!=nblock ){ - error("mismatch between numbers of tasks in various base multicolvars"); - } + for(unsigned i=0; igetFullNumberOfTasks()!=nblock ) { + error("mismatch between numbers of tasks in various base multicolvars"); + } } ablocks.resize( mybasemulticolvars.size() ); usespecies=false; - for(unsigned i=0;iresizeTemporyMultiValues( mybasemulticolvars.size() ); setupMultiColvarBase( fake_atoms ); } -void MultiColvarBase::addTaskToList( const unsigned& taskCode ){ +void MultiColvarBase::addTaskToList( const unsigned& taskCode ) { plumed_assert( getNumberOfVessels()==0 ); ActionWithVessel::addTaskToList( taskCode ); } -void MultiColvarBase::resizeBookeepingArray( const unsigned& num1, const unsigned& num2 ){ +void MultiColvarBase::resizeBookeepingArray( const unsigned& num1, const unsigned& num2 ) { bookeeping.resize( num1, num2 ); - for(unsigned i=0;i& atoms ){ +void MultiColvarBase::setupMultiColvarBase( const std::vector& atoms ) { if( !matsums && atom_lab.size()==0 ) error("No atoms have been read in"); std::vector all_atoms; // Setup decoder array - if( !usespecies && nblock>0 ){ - - ncentral=ablocks.size(); use_for_central_atom.resize( ablocks.size(), true ); - numberForCentralAtom = 1.0 / static_cast( ablocks.size() ); - if( ablocks.size()==3 ){ - allthirdblockintasks=uselinkforthree=true; - for(unsigned i=0;istd::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); - } else { - decoder.resize( ablocks.size() ); - // Check if number of atoms is too large - if( pow( double(nblock), double(ablocks.size()) )>std::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); - } - unsigned code=1; for(unsigned i=0;i( ablocks.size() ); - } else if( keywords.exists("SPECIESA") ){ - plumed_assert( atom_lab.size()==0 && all_atoms.size()==0 ); - ablocks.resize( 1 ); bool readspecies=parseMultiColvarAtomList("SPECIES", -1, all_atoms); - if( readspecies ){ - ablocks[0].resize( atom_lab.size() ); for(unsigned i=0;i0 && atom_lab[j].first>0 ){ - if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== - mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ){ found=true; inum=j; break; } - } else if( all_atoms[atom_lab[nat1+i].second]==all_atoms[atom_lab[j].second] ){ found=true; inum=j; break; } - } - // This prevents mistakes being made in colvar setup - if( found ){ ablocks[0][i]=inum; } - else { ablocks[0][i]=nat1 + i; } - } - } - } - if( mybasemulticolvars.size()>0 ){ - for(unsigned i=0;iresizeTemporyMultiValues(2); mybasemulticolvars[i]->my_tmp_capacks.resize(2); + if( !usespecies && nblock>0 ) { + + ncentral=ablocks.size(); use_for_central_atom.resize( ablocks.size(), true ); + numberForCentralAtom = 1.0 / static_cast( ablocks.size() ); + if( ablocks.size()==3 ) { + allthirdblockintasks=uselinkforthree=true; + for(unsigned i=0; istd::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); + } else { + decoder.resize( ablocks.size() ); + // Check if number of atoms is too large + if( pow( double(nblock), double(ablocks.size()) )>std::numeric_limits::max() ) error("number of atoms in groups is too big for PLUMED to handle"); + } + unsigned code=1; for(unsigned i=0; i( ablocks.size() ); + } else if( keywords.exists("SPECIESA") ) { + plumed_assert( atom_lab.size()==0 && all_atoms.size()==0 ); + ablocks.resize( 1 ); bool readspecies=parseMultiColvarAtomList("SPECIES", -1, all_atoms); + if( readspecies ) { + ablocks[0].resize( atom_lab.size() ); for(unsigned i=0; i0 && atom_lab[j].first>0 ) { + if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== + mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ) { found=true; inum=j; break; } + } else if( all_atoms[atom_lab[nat1+i].second]==all_atoms[atom_lab[j].second] ) { found=true; inum=j; break; } + } + // This prevents mistakes being made in colvar setup + if( found ) { ablocks[0][i]=inum; } + else { ablocks[0][i]=nat1 + i; } + } + } + } + if( mybasemulticolvars.size()>0 ) { + for(unsigned i=0; iresizeTemporyMultiValues(2); mybasemulticolvars[i]->my_tmp_capacks.resize(2); + } } - // Copy lists of atoms involved from base multicolvars + // Copy lists of atoms involved from base multicolvars std::vector tmp_atoms; - for(unsigned i=0;igetAbsoluteIndexes(); - for(unsigned j=0;jgetAbsoluteIndexes(); + for(unsigned j=0; j& catom_ind ){ +void MultiColvarBase::setAtomsForCentralAtom( const std::vector& catom_ind ) { unsigned nat=0; plumed_assert( catom_ind.size()==ablocks.size() ); - for(unsigned i=0;i0 ); ncentral=nat; numberForCentralAtom = 1.0 / static_cast( nat ); } -void MultiColvarBase::turnOnDerivatives(){ +void MultiColvarBase::turnOnDerivatives() { ActionWithValue::turnOnDerivatives(); - needsDerivatives(); + needsDerivatives(); forcesToApply.resize( getNumberOfDerivatives() ); -} +} -void MultiColvarBase::setLinkCellCutoff( const double& lcut, double tcut ){ +void MultiColvarBase::setLinkCellCutoff( const double& lcut, double tcut ) { plumed_assert( usespecies || ablocks.size()<4 ); if( tcut<0 ) tcut=lcut; - linkcells.setCutoff( lcut ); + linkcells.setCutoff( lcut ); threecells.setCutoff( tcut ); } @@ -498,131 +498,131 @@ double MultiColvarBase::getLinkCellCutoff() const { return linkcells.getCutoff(); } -void MultiColvarBase::setupLinkCells(){ +void MultiColvarBase::setupLinkCells() { if( (!usespecies && nblock==0) || !linkcells.enabled() ) return ; // Retrieve any atoms that haven't already been retrieved - for(std::vector::iterator p=mybasemulticolvars.begin();p!=mybasemulticolvars.end();++p){ - (*p)->retrieveAtoms(); + for(std::vector::iterator p=mybasemulticolvars.begin(); p!=mybasemulticolvars.end(); ++p) { + (*p)->retrieveAtoms(); } retrieveAtoms(); unsigned iblock; - if( usespecies ){ - iblock=0; - } else if( ablocks.size()<4 ){ - iblock=1; + if( usespecies ) { + iblock=0; + } else if( ablocks.size()<4 ) { + iblock=1; } else { - plumed_error(); + plumed_error(); } - + // Count number of currently active atoms nactive_atoms=0; - for(unsigned i=0;i0 ){ - std::vector ltmp_pos( nactive_atoms ); - std::vector ltmp_ind( nactive_atoms ); - - nactive_atoms=0; - if( usespecies ){ - for(unsigned i=0;i0 ) { + std::vector ltmp_pos( nactive_atoms ); + std::vector ltmp_ind( nactive_atoms ); + + nactive_atoms=0; + if( usespecies ) { + for(unsigned i=0; i0 ){ - // Get some parallel info - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if( serialCalculation() ){ stride=1; rank=0; } - - // Ensure we only do tasks where atoms are in appropriate link cells - std::vector linked_atoms( 1+ablocks[1].size() ); - for(unsigned i=rank;i0 ){ - // Get some parallel info - unsigned stride=comm.Get_size(); - unsigned rank=comm.Get_rank(); - if( serialCalculation() ){ stride=1; rank=0; } - - unsigned nactive_three=0; - for(unsigned i=0;i lttmp_pos( nactive_three ); - std::vector lttmp_ind( nactive_three ); - - nactive_three=0; - if( allthirdblockintasks ){ - for(unsigned i=0;i linked_atoms( 1+ablocks[1].size() ); - std::vector tlinked_atoms( 1+ablocks[2].size() ); - for(unsigned i=rank;i0 ) { + // Get some parallel info + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if( serialCalculation() ) { stride=1; rank=0; } + + // Ensure we only do tasks where atoms are in appropriate link cells + std::vector linked_atoms( 1+ablocks[1].size() ); + for(unsigned i=rank; i0 ) { + // Get some parallel info + unsigned stride=comm.Get_size(); + unsigned rank=comm.Get_rank(); + if( serialCalculation() ) { stride=1; rank=0; } + + unsigned nactive_three=0; + for(unsigned i=0; i lttmp_pos( nactive_three ); + std::vector lttmp_ind( nactive_three ); + + nactive_three=0; + if( allthirdblockintasks ) { + for(unsigned i=0; i linked_atoms( 1+ablocks[1].size() ); + std::vector tlinked_atoms( 1+ablocks[2].size() ); + for(unsigned i=rank; i& atoms ) const { @@ -630,118 +630,118 @@ void MultiColvarBase::decodeIndexToAtoms( const unsigned& taskCode, std::vector< if( atoms.size()!=decoder.size() ) atoms.resize( decoder.size() ); unsigned scode = taskCode; - for(unsigned i=0;i task_atoms(1); task_atoms[0]=taskCode; - unsigned natomsper=myatoms.setupAtomsFromLinkCells( task_atoms, getLinkCellPosition(task_atoms), linkcells ); - return natomsper>1; - } else if( matsums ){ - myatoms.setNumberOfAtoms( getNumberOfAtoms() ); - for(unsigned i=0;i atoms(2); decodeIndexToAtoms( taskCode, atoms ); - myatoms.setupAtomsFromLinkCells( atoms, getLinkCellPosition(atoms), threecells ); - } else if( nblock>0 ){ - std::vector atoms( ablocks.size() ); - decodeIndexToAtoms( taskCode, atoms ); myatoms.setNumberOfAtoms( ablocks.size() ); - for(unsigned i=0;i task_atoms(1); task_atoms[0]=taskCode; + unsigned natomsper=myatoms.setupAtomsFromLinkCells( task_atoms, getLinkCellPosition(task_atoms), linkcells ); + return natomsper>1; + } else if( matsums ) { + myatoms.setNumberOfAtoms( getNumberOfAtoms() ); + for(unsigned i=0; i atoms(2); decodeIndexToAtoms( taskCode, atoms ); + myatoms.setupAtomsFromLinkCells( atoms, getLinkCellPosition(atoms), threecells ); + } else if( nblock>0 ) { + std::vector atoms( ablocks.size() ); + decodeIndexToAtoms( taskCode, atoms ); myatoms.setNumberOfAtoms( ablocks.size() ); + for(unsigned i=0; i& active_tasks, const std::string& input_label ){ - if( !setup_completed ){ - bool justVolumes=false; - if( usespecies ){ - justVolumes=true; - for(unsigned i=0;i( getPntrToVessel(i) ); - if( mys ) continue; - vesselbase::BridgeVessel* myb=dynamic_cast( getPntrToVessel(i) ); - if( !myb ){ justVolumes=false; break; } - ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); - if( !myv ){ justVolumes=false; break; } - } +void MultiColvarBase::setupActiveTaskSet( std::vector& active_tasks, const std::string& input_label ) { + if( !setup_completed ) { + bool justVolumes=false; + if( usespecies ) { + justVolumes=true; + for(unsigned i=0; i( getPntrToVessel(i) ); + if( mys ) continue; + vesselbase::BridgeVessel* myb=dynamic_cast( getPntrToVessel(i) ); + if( !myb ) { justVolumes=false; break; } + ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); + if( !myv ) { justVolumes=false; break; } } - deactivateAllTasks(); - if( justVolumes && mydata ){ - if( mydata->getNumberOfDataUsers()==0 ) justVolumes=false; - - for(unsigned i=0;igetNumberOfDataUsers();++i){ - MultiColvarBase* myu=dynamic_cast( mydata->getDataUser(i) ); - if( myu ){ - myu->setupActiveTaskSet( taskFlags, getLabel() ); - } else { - for(unsigned i=0;igetNumberOfDataUsers()==0 ) justVolumes=false; + + for(unsigned i=0; igetNumberOfDataUsers(); ++i) { + MultiColvarBase* myu=dynamic_cast( mydata->getDataUser(i) ); + if( myu ) { + myu->setupActiveTaskSet( taskFlags, getLabel() ); + } else { + for(unsigned i=0; i( getPntrToVessel(j) ); - if( !myb ) continue ; - ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); - if( !myv ) continue ; - myv->retrieveAtoms(); myv->setupRegions(); - - for(unsigned i=0;iinVolumeOfInterest(i) ) taskFlags[i]=1; - } - } - } else { - for(unsigned i=0;i( getPntrToVessel(j) ); + if( !myb ) continue ; + ActionVolume* myv=dynamic_cast( myb->getOutputAction() ); + if( !myv ) continue ; + myv->retrieveAtoms(); myv->setupRegions(); + + for(unsigned i=0; iinVolumeOfInterest(i) ) taskFlags[i]=1; + } + } + } else { + for(unsigned i=0; igetLabel()==input_label ){ input_code=i+1; break; } - } - - MultiValue my_tvals( getNumberOfQuantities(), getNumberOfDerivatives() ); - AtomValuePack mytmp_atoms( my_tvals, this ); - for(unsigned i=0;igetLabel()==input_label ) { input_code=i+1; break; } + } + + MultiValue my_tvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + AtomValuePack mytmp_atoms( my_tvals, this ); + for(unsigned i=0; i( mybasemulticolvars[i] ); - if( myfilt || mybasemulticolvars[i]->filtersUsedAsInput() ) inputAreFilters=true; + for(unsigned i=0; i( mybasemulticolvars[i] ); + if( myfilt || mybasemulticolvars[i]->filtersUsedAsInput() ) inputAreFilters=true; } return inputAreFilters; } -void MultiColvarBase::calculate(){ +void MultiColvarBase::calculate() { // Recursive function that sets up tasks setupActiveTaskSet( taskFlags, getLabel() ); @@ -749,38 +749,38 @@ void MultiColvarBase::calculate(){ if( mybasemulticolvars.size()>0 && filtersUsedAsInput() ) setupLinkCells(); // Setup the link cells if we are not using species - if( !usespecies && ablocks.size()>1 ){ - // This loop finds the first active atom, which is always checked because - // of a peculiarity in linkcells - unsigned first_active; - for(unsigned i=0;i1 ) { + // This loop finds the first active atom, which is always checked because + // of a peculiarity in linkcells + unsigned first_active; + for(unsigned i=0; i0 ) plumed_merror("cannot calculate numerical derivatives for this quantity"); calculateAtomicNumericalDerivatives( this, 0 ); } -void MultiColvarBase::prepare(){ +void MultiColvarBase::prepare() { setup_completed=false; atomsWereRetrieved=false; } -void MultiColvarBase::retrieveAtoms(){ - if( !atomsWereRetrieved ){ ActionAtomistic::retrieveAtoms(); atomsWereRetrieved=true; } +void MultiColvarBase::retrieveAtoms() { + if( !atomsWereRetrieved ) { ActionAtomistic::retrieveAtoms(); atomsWereRetrieved=true; } } void MultiColvarBase::mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, - const unsigned& jatom, const std::vector& der, - MultiValue& myder, AtomValuePack& myatoms ) const { + const unsigned& jatom, const std::vector& der, + MultiValue& myder, AtomValuePack& myatoms ) const { MultiValue& myvals=myatoms.getUnderlyingMultiValue(); plumed_dbg_assert( ivaltaskIsCurrentlyActive( atom_lab[katom].second ) ); // Get start of indices for this atom - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9; + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9; plumed_dbg_assert( basen%3==0 ); // Check the number of atoms is consistent with input derivatives unsigned virbas = myvals.getNumberOfDerivatives()-9; - for(unsigned j=0;jgetNumberOfDerivatives()-9 ){ - unsigned kder=basen+jder; - for(unsigned icomp=start;icompgetNumberOfDerivatives() + 9); - for(unsigned icomp=start;icompgetNumberOfDerivatives()-9 ) { + unsigned kder=basen+jder; + for(unsigned icomp=start; icompgetNumberOfDerivatives() + 9); + for(unsigned icomp=start; icomp& der, - MultiValue& myder, AtomValuePack& myatoms ) const { + const unsigned& jatom, const std::vector& der, + MultiValue& myder, AtomValuePack& myatoms ) const { MultiValue& myvals=myatoms.getUnderlyingMultiValue(); plumed_dbg_assert( ivaltaskIsCurrentlyActive( atom_lab[katom].second ) ); // Get start of indices for this atom - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9; + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9; plumed_dbg_assert( basen%3==0 ); // Check the number of atoms is consistent with input derivatives unsigned virbas = myvals.getNumberOfDerivatives()-9; - for(unsigned j=0;jgetNumberOfDerivatives()-9 ){ - unsigned kder=basen+jder; plumed_assert( kdergetNumberOfDerivatives() + 9); - for(unsigned icomp=start;icompgetNumberOfDerivatives()-9 ) { + unsigned kder=basen+jder; plumed_assert( kdergetNumberOfDerivatives() + 9); + for(unsigned icomp=start; icomp(myatoms.getUnderlyingMultiValue().getNumberOfValues()) && iatom0 ); // Find base colvar unsigned mmc = atom_lab[katom].first - 1; plumed_dbg_assert( mybasemulticolvars[mmc]->taskIsCurrentlyActive( atom_lab[katom].second ) ); - if( usespecies && iatom==0 ){ myatoms.addComDerivatives( ival, der, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); return; } + if( usespecies && iatom==0 ) { myatoms.addComDerivatives( ival, der, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); return; } // Get start of indices for this atom - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9) / 3; + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9) / 3; mybasemulticolvars[mmc]->getCentralAtomPack( basen, atom_lab[katom].second, mybasemulticolvars[mmc]->my_tmp_capacks[1] ); myatoms.addComDerivatives( ival, der, mybasemulticolvars[mmc]->my_tmp_capacks[1] ); } -void MultiColvarBase::getInputData( const unsigned& ind, const bool& normed, - const multicolvar::AtomValuePack& myatoms, +void MultiColvarBase::getInputData( const unsigned& ind, const bool& normed, + const multicolvar::AtomValuePack& myatoms, std::vector& orient ) const { // Converint input atom to local index - unsigned katom = myatoms.getIndex(ind); plumed_dbg_assert( atom_lab[katom].first>0 ); + unsigned katom = myatoms.getIndex(ind); plumed_dbg_assert( atom_lab[katom].first>0 ); // Find base colvar unsigned mmc = atom_lab[katom].first - 1; plumed_dbg_assert( mybasemulticolvars[mmc]->taskIsCurrentlyActive( atom_lab[katom].second ) ); // Check if orient is the correct size - if( orient.size()!=mybasemulticolvars[mmc]->getNumberOfQuantities() ) orient.resize( mybasemulticolvars[mmc]->getNumberOfQuantities() ); - // Retrieve the value + if( orient.size()!=mybasemulticolvars[mmc]->getNumberOfQuantities() ) orient.resize( mybasemulticolvars[mmc]->getNumberOfQuantities() ); + // Retrieve the value mybasedata[mmc]->retrieveValueWithIndex( atom_lab[katom].second, normed, orient ); } MultiValue& MultiColvarBase::getInputDerivatives( const unsigned& iatom, const bool& normed, const multicolvar::AtomValuePack& myatoms ) const { // Converint input atom to local index - unsigned katom = myatoms.getIndex(iatom); plumed_dbg_assert( atom_lab[katom].first>0 ); + unsigned katom = myatoms.getIndex(iatom); plumed_dbg_assert( atom_lab[katom].first>0 ); // Find base colvar unsigned mmc = atom_lab[katom].first - 1; plumed_dbg_assert( mybasemulticolvars[mmc]->taskIsCurrentlyActive( atom_lab[katom].second ) ); if( usespecies && !normed && iatom==0 ) return mybasedata[mmc]->getTemporyMultiValue(0); unsigned oval=0; if( iatom>0 ) oval=1; - MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(oval); + MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(oval); if( myder.getNumberOfValues()!=mybasemulticolvars[mmc]->getNumberOfQuantities() || - myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ){ - myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); - } + myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ) { + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); + } mybasedata[mmc]->retrieveDerivatives( atom_lab[katom].second, normed, myder ); return myder; } @@ -891,31 +891,31 @@ void MultiColvarBase::accumulateSymmetryFunction( const int& ival, const unsigne double weighti=1.0; if( atom_lab[jatom].first>0 ) weighti=mybasedata[atom_lab[jatom].first-1]->retrieveWeightWithIndex( atom_lab[jatom].second ); // Accumulate the value if( ival<0 ) myatoms.getUnderlyingMultiValue().addTemporyValue( weight0*weighti*val ); - else myatoms.addValue( ival, weight0*weighti*val ); + else myatoms.addValue( ival, weight0*weighti*val ); // Return if we don't need derivatives if( doNotCalculateDerivatives() ) return ; // And virial - if( ival<0 ) myatoms.addTemporyBoxDerivatives( weight0*weighti*vir ); + if( ival<0 ) myatoms.addTemporyBoxDerivatives( weight0*weighti*vir ); else myatoms.addBoxDerivatives( ival, weight0*weighti*vir ); // Add derivatives of central atom - if( atom_lab[katom].first>0 ){ - addComDerivatives( ival, 0, -weight0*weighti*der, myatoms ); - std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); - tmpder[0]=weighti*val; mergeInputDerivatives( ival, 0, 1, 0, tmpder, getInputDerivatives(0, false, myatoms), myatoms ); + if( atom_lab[katom].first>0 ) { + addComDerivatives( ival, 0, -weight0*weighti*der, myatoms ); + std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); + tmpder[0]=weighti*val; mergeInputDerivatives( ival, 0, 1, 0, tmpder, getInputDerivatives(0, false, myatoms), myatoms ); } else { - if( ival<0 ) myatoms.addTemporyAtomsDerivatives( 0, -der ); - else myatoms.addAtomsDerivatives( ival, 0, -der ); + if( ival<0 ) myatoms.addTemporyAtomsDerivatives( 0, -der ); + else myatoms.addAtomsDerivatives( ival, 0, -der ); } // Add derivatives of atom in coordination sphere - if( atom_lab[jatom].first>0 ){ - addComDerivatives( ival, iatom, weight0*weighti*der, myatoms ); - std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); - tmpder[0]=weight0*val; mergeInputDerivatives( ival, 0, 1, iatom, tmpder, getInputDerivatives(iatom, false, myatoms), myatoms ); + if( atom_lab[jatom].first>0 ) { + addComDerivatives( ival, iatom, weight0*weighti*der, myatoms ); + std::vector tmpder( mybasemulticolvars[atom_lab[katom].first - 1]->getNumberOfQuantities(), 0. ); + tmpder[0]=weight0*val; mergeInputDerivatives( ival, 0, 1, iatom, tmpder, getInputDerivatives(iatom, false, myatoms), myatoms ); } else { - if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); - else myatoms.addAtomsDerivatives( ival, iatom, der ); + if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); + else myatoms.addAtomsDerivatives( ival, iatom, der ); } } @@ -923,11 +923,11 @@ void MultiColvarBase::addAtomDerivatives( const int& ival, const unsigned& iatom if( doNotCalculateDerivatives() ) return ; unsigned jatom=myatoms.getIndex(iatom); - if( atom_lab[jatom].first>0 ){ - addComDerivatives( ival, iatom, der, myatoms ); + if( atom_lab[jatom].first>0 ) { + addComDerivatives( ival, iatom, der, myatoms ); } else { - if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); - else myatoms.addAtomsDerivatives( ival, iatom, der ); + if( ival<0 ) myatoms.addTemporyAtomsDerivatives( iatom, der ); + else myatoms.addAtomsDerivatives( ival, iatom, der ); } } @@ -940,61 +940,61 @@ void MultiColvarBase::performTask( const unsigned& task_index, const unsigned& c // Retrieve the atom list if( !setupCurrentAtomList( current, myatoms ) ) return; // Get weight due to dynamic groups - double weight = 1.0; - if( !matsums ){ - for(unsigned i=0;i1 ) break; - unsigned mmc = atom_lab[myatoms.getIndex(i)].first - 1; - weight *= mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); - } - } else if( usespecies ){ - if( atom_lab[myatoms.getIndex(0)].first>0 ){ - if( mybasedata[atom_lab[myatoms.getIndex(0)].first-1]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(0)].second )1 ) break; + unsigned mmc = atom_lab[myatoms.getIndex(i)].first - 1; + weight *= mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); + } + } else if( usespecies ) { + if( atom_lab[myatoms.getIndex(0)].first>0 ) { + if( mybasedata[atom_lab[myatoms.getIndex(0)].first-1]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(0)].second )0 ){ - MultiValue& outder=myatoms.getUnderlyingMultiValue(); MultiValue myder(0,0); - for(unsigned i=0;igetNumberOfQuantities() || myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ){ - myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); - } - mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(i)].second, false, myder ); - - // Retrieve the prefactor (product of all other weights) - double prefactor = multweight*weight / mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); - // And accumulate the derivatives - for(unsigned j=0;j0 ) { + MultiValue& outder=myatoms.getUnderlyingMultiValue(); MultiValue myder(0,0); + for(unsigned i=0; igetNumberOfQuantities() || myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ) { + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); } + mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(i)].second, false, myder ); + + // Retrieve the prefactor (product of all other weights) + double prefactor = multweight*weight / mybasedata[mmc]->retrieveWeightWithIndex( atom_lab[myatoms.getIndex(i)].second ); + // And accumulate the derivatives + for(unsigned j=0; j0 && atom_lab[myatoms.getIndex(0)].first>0 ){ - unsigned mmc = atom_lab[0].first - 1; - MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(0); - if( myder.getNumberOfValues()!=mybasemulticolvars[mmc]->getNumberOfQuantities() || - myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ){ - myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); - } - mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(0)].second, false, myder ); - unsigned basen=0; for(unsigned i=0;igetNumberOfDerivatives() - 9; - mybasemulticolvars[mmc]->getCentralAtomPack( basen, atom_lab[myatoms.getIndex(0)].second, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); + if( !doNotCalculateDerivatives() ) { + if( usespecies && mybasemulticolvars.size()>0 && atom_lab[myatoms.getIndex(0)].first>0 ) { + unsigned mmc = atom_lab[0].first - 1; + MultiValue& myder=mybasedata[mmc]->getTemporyMultiValue(0); + if( myder.getNumberOfValues()!=mybasemulticolvars[mmc]->getNumberOfQuantities() || + myder.getNumberOfDerivatives()!=mybasemulticolvars[mmc]->getNumberOfDerivatives() ) { + myder.resize( mybasemulticolvars[mmc]->getNumberOfQuantities(), mybasemulticolvars[mmc]->getNumberOfDerivatives() ); } + mybasedata[mmc]->retrieveDerivatives( atom_lab[myatoms.getIndex(0)].second, false, myder ); + unsigned basen=0; for(unsigned i=0; igetNumberOfDerivatives() - 9; + mybasemulticolvars[mmc]->getCentralAtomPack( basen, atom_lab[myatoms.getIndex(0)].second, mybasemulticolvars[mmc]->my_tmp_capacks[0] ); + } } // Compute everything double vv=compute( task_index, myatoms ); updateActiveAtoms( myatoms ); @@ -1007,71 +1007,71 @@ void MultiColvarBase::updateActiveAtoms( AtomValuePack& myatoms ) const { else myatoms.updateDynamicList(); } -Vector MultiColvarBase::getCentralAtomPos( const unsigned& taskIndex ){ +Vector MultiColvarBase::getCentralAtomPos( const unsigned& taskIndex ) { unsigned curr=getTaskCode( taskIndex ); - if( usespecies || isDensity() ){ - return getPositionOfAtomForLinkCells(curr); - } else if( nblock>0 ){ - // double factor=1.0/static_cast( ablocks.size() ); - Vector mypos; mypos.zero(); - std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); - for(unsigned i=0;i0 ) { + // double factor=1.0/static_cast( ablocks.size() ); + Vector mypos; mypos.zero(); + std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); + for(unsigned i=0; i0 ){ - if( mypack.getNumberOfAtomsWithDerivatives()!=ncentral ) mypack.resize(ncentral); - unsigned k=0; - std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); - for(unsigned i=0;i0 ) { + if( mypack.getNumberOfAtomsWithDerivatives()!=ncentral ) mypack.resize(ncentral); + unsigned k=0; + std::vector atoms( ablocks.size() ); decodeIndexToAtoms( curr, atoms ); + for(unsigned i=0; i& dlist, unsigned int max_index) const { - if (usepbc) pbcApply(dlist, max_index); + if (usepbc) pbcApply(dlist, max_index); } -void MultiColvarBase::apply(){ +void MultiColvarBase::apply() { if( getForcesFromVessels( forcesToApply ) ) setForcesOnAtoms( forcesToApply ); } - + } } diff --git a/src/multicolvar/MultiColvarBase.h b/src/multicolvar/MultiColvarBase.h index 8d94a93220..89574a70a6 100644 --- a/src/multicolvar/MultiColvarBase.h +++ b/src/multicolvar/MultiColvarBase.h @@ -42,11 +42,11 @@ class MultiColvarBase : public ActionAtomistic, public ActionWithValue, public vesselbase::ActionWithVessel - { - friend class BridgedMultiColvarFunction; - friend class VolumeGradientBase; - friend class MultiColvarFilter; - friend class AtomValuePack; +{ + friend class BridgedMultiColvarFunction; + friend class VolumeGradientBase; + friend class MultiColvarFilter; + friend class AtomValuePack; private: /// Use periodic boundary conditions bool usepbc; @@ -105,9 +105,9 @@ class MultiColvarBase : /// Finish setting up the multicolvar base void setupMultiColvarBase( const std::vector& atoms ); /// Add some derivatives to a particular component of a particular atom - void addAtomDerivatives( const int& , const unsigned& , const Vector& , multicolvar::AtomValuePack& ) const ; + void addAtomDerivatives( const int&, const unsigned&, const Vector&, multicolvar::AtomValuePack& ) const ; /// Add derivative of the input value - void mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, const unsigned& jatom, + void mergeInputDerivatives( const unsigned& ival, const unsigned& start, const unsigned& end, const unsigned& jatom, const std::vector& der, MultiValue& myder, AtomValuePack& myatoms ) const ; /// This routine take the ith set of input derivatives and adds it to each of the (end-start) output derivatives /// In other words one set of derivatives comes in and end-start sets of derivatives come out @@ -150,9 +150,9 @@ class MultiColvarBase : void buildSets(); public: explicit MultiColvarBase(const ActionOptions&); - ~MultiColvarBase(){} + ~MultiColvarBase() {} static void registerKeywords( Keywords& keys ); -/// Turn on the derivatives +/// Turn on the derivatives virtual void turnOnDerivatives(); /// Do we use pbc to calculate this quantity bool usesPbc() const ; @@ -169,7 +169,7 @@ class MultiColvarBase : /// Calculate numerical derivatives virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); /// Perform one of the tasks - virtual void performTask( const unsigned& , const unsigned& , MultiValue& ) const ; + virtual void performTask( const unsigned&, const unsigned&, MultiValue& ) const ; /// Update the active atoms virtual void updateActiveAtoms( AtomValuePack& myatoms ) const ; /// This gets the position of an atom for the link cell setup @@ -199,12 +199,12 @@ class MultiColvarBase : /// This is true if multicolvar is calculating a vector or if the multicolvar is the density virtual bool hasDifferentiableOrientation() const { return false; } /// This makes sure we are not calculating the director when we do LocalAverage - virtual void doNotCalculateDirector(){} + virtual void doNotCalculateDirector() {} /// Ensure that derivatives are only calculated when needed bool doNotCalculateDerivatives() const ; -/// Get the icolv th base multicolvar +/// Get the icolv th base multicolvar MultiColvarBase* getBaseMultiColvar( const unsigned& icolv ) const ; -/// Get the number of base multicolvars +/// Get the number of base multicolvars unsigned getNumberOfBaseMultiColvars() const ; /// Get an input data virtual void getInputData( const unsigned& ind, const bool& normed, const multicolvar::AtomValuePack& myatoms, std::vector& orient ) const ; @@ -213,10 +213,10 @@ class MultiColvarBase : }; inline -bool MultiColvarBase::isCurrentlyActive( const unsigned& code ){ - if( setup_completed && atom_lab[code].first>0 ){ - unsigned mmc=atom_lab[code].first - 1; - return mybasedata[mmc]->storedValueIsActive( atom_lab[code].second ); +bool MultiColvarBase::isCurrentlyActive( const unsigned& code ) { + if( setup_completed && atom_lab[code].first>0 ) { + unsigned mmc=atom_lab[code].first - 1; + return mybasedata[mmc]->storedValueIsActive( atom_lab[code].second ); } return true; } @@ -224,20 +224,20 @@ bool MultiColvarBase::isCurrentlyActive( const unsigned& code ){ inline AtomNumber MultiColvarBase::getAbsoluteIndexOfCentralAtom( const unsigned& iatom ) const { plumed_dbg_assert( iatom0 ){ - unsigned mmc=atom_lab[iatom].first - 1; - return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); + if( atom_lab[iatom].first>0 ) { + unsigned mmc=atom_lab[iatom].first - 1; + return mybasemulticolvars[mmc]->getAbsoluteIndexOfCentralAtom( atom_lab[iatom].second ); } plumed_dbg_assert( usespecies ); return ActionAtomistic::getAbsoluteIndex( atom_lab[getTaskCode(iatom)].second ); -} +} inline Vector MultiColvarBase::getPositionOfAtomForLinkCells( const unsigned& iatom ) const { plumed_dbg_assert( iatom0 ){ - unsigned mmc=atom_lab[iatom].first - 1; - return mybasemulticolvars[mmc]->getCentralAtomPos( atom_lab[iatom].second ); + if( atom_lab[iatom].first>0 ) { + unsigned mmc=atom_lab[iatom].first - 1; + return mybasemulticolvars[mmc]->getCentralAtomPos( atom_lab[iatom].second ); } return ActionAtomistic::getPosition( atom_lab[iatom].second ); } @@ -245,10 +245,10 @@ Vector MultiColvarBase::getPositionOfAtomForLinkCells( const unsigned& iatom ) c inline Vector MultiColvarBase::getLinkCellPosition( const std::vector& atoms ) const { return getPositionOfAtomForLinkCells( atoms[0] ); -} +} inline -unsigned MultiColvarBase::getNumberOfDerivatives(){ +unsigned MultiColvarBase::getNumberOfDerivatives() { return 3*getNumberOfAtoms()+9; } @@ -265,14 +265,14 @@ bool MultiColvarBase::doNotCalculateDerivatives() const { inline unsigned MultiColvarBase::getNumberOfBaseMultiColvars() const { - return mybasemulticolvars.size(); -} + return mybasemulticolvars.size(); +} -inline +inline MultiColvarBase* MultiColvarBase::getBaseMultiColvar( const unsigned& icolv ) const { plumed_dbg_assert( icolv -#include +#include //+PLUMEDOC MCOLVARF MCOLV_COMBINE /* @@ -47,46 +47,46 @@ class MultiColvarCombine : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(MultiColvarCombine,"MCOLV_COMBINE") -void MultiColvarCombine::registerKeywords( Keywords& keys ){ +void MultiColvarCombine::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","DATA","the multicolvars you are calculating linear combinations for"); keys.add("compulsory","COEFFICIENTS","1.0","the coeficients to use for the various multicolvars"); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); + keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); keys.use("MIN"); keys.use("MAX"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("ALT_MIN"); keys.use("BETWEEN"); keys.use("MOMENTS"); } MultiColvarCombine::MultiColvarCombine(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { buildSets(); - for(unsigned i=0;iweightWithDerivatives() ) error("cannot combine multicolvars with weights"); + for(unsigned i=0; iweightWithDerivatives() ) error("cannot combine multicolvars with weights"); } coeff.resize( getNumberOfBaseMultiColvars() ); parseVector("COEFFICIENTS",coeff); log.printf(" coefficients of multicolvars %f", coeff[0] ); - for(unsigned i=1;i tval(2); - for(unsigned i=0;i tval(2); + for(unsigned i=0; i cc(2); - for(unsigned i=0;i cc(2); + for(unsigned i=0; i atom; parseAtomList("ORIGIN",atom); @@ -151,82 +151,82 @@ ActionWithGrid(ao) parseFlag("FRACTIONAL",fractional); std::string direction; parse("DIR",direction); log.printf(" calculating for %s density profile along ", mycolv->getLabel().c_str() ); - if( direction=="x" ){ - log.printf("x axis"); - directions.resize(1); directions[0]=0; - } else if( direction=="y" ){ - log.printf("y axis"); - directions.resize(1); directions[0]=1; - } else if( direction=="z" ){ - log.printf("z axis"); - directions.resize(1); directions[0]=2; - } else if( direction=="xy" ){ - log.printf("x and y axes"); - directions.resize(2); directions[0]=0; directions[1]=1; - } else if( direction=="xz" ){ - log.printf("x and z axes"); - directions.resize(2); directions[0]=0; directions[1]=2; - } else if( direction=="yz" ){ - log.printf("y and z axis"); - directions.resize(2); directions[0]=1; directions[1]=2; - } else if( direction=="xyz" ){ - log.printf("x, y and z axes"); - directions.resize(3); directions[0]=0; directions[1]=1; directions[2]=2; + if( direction=="x" ) { + log.printf("x axis"); + directions.resize(1); directions[0]=0; + } else if( direction=="y" ) { + log.printf("y axis"); + directions.resize(1); directions[0]=1; + } else if( direction=="z" ) { + log.printf("z axis"); + directions.resize(1); directions[0]=2; + } else if( direction=="xy" ) { + log.printf("x and y axes"); + directions.resize(2); directions[0]=0; directions[1]=1; + } else if( direction=="xz" ) { + log.printf("x and z axes"); + directions.resize(2); directions[0]=0; directions[1]=2; + } else if( direction=="yz" ) { + log.printf("y and z axis"); + directions.resize(2); directions[0]=1; directions[1]=2; + } else if( direction=="xyz" ) { + log.printf("x, y and z axes"); + directions.resize(3); directions[0]=0; directions[1]=1; directions[2]=2; } else { - error( direction + " is not valid gradient direction"); - } + error( direction + " is not valid gradient direction"); + } log.printf(" for colvars calculated by action %s \n",mycolv->getLabel().c_str() ); parseVector("NBINS",nbins); parseVector("SPACING",gspacing); if( nbins.size()!=directions.size() && gspacing.size()!=directions.size() ) error("NBINS or SPACING must be set"); confined.resize( directions.size() ); cmin.resize( directions.size(), 0 ); cmax.resize( directions.size(), 0 ); - for(unsigned i=0;igetLabel() + ".dens"; vstring +=" COORDINATES="; if( directions[0]==0 ) vstring+="x"; else if( directions[0]==1 ) vstring+="y"; else if( directions[0]==2 ) vstring+="z"; - for(unsigned i=1;igetFullNumberOfTasks();++i) addTaskToList(i); + for(unsigned i=0; igetFullNumberOfTasks(); ++i) addTaskToList(i); // And create the grid if( mycolv->isDensity() ) createGrid( "histogram", vstring ); else createGrid( "average", vstring ); @@ -234,12 +234,12 @@ ActionWithGrid(ao) setAveragingAction( mygrid, true ); // Enusre units for cube files are set correctly - if( !fractional ){ - if( plumed.getAtoms().usingNaturalUnits() ) mygrid->setCubeUnits( 1.0/0.5292 ); - else mygrid->setCubeUnits( plumed.getAtoms().getUnits().getLength()/.05929 ); + if( !fractional ) { + if( plumed.getAtoms().usingNaturalUnits() ) mygrid->setCubeUnits( 1.0/0.5292 ); + else mygrid->setCubeUnits( plumed.getAtoms().getUnits().getLength()/.05929 ); } - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); // Stupid dependencies cleared by requestAtoms - why GBussi why? That's got me so many times addDependency( mycolv ); } @@ -248,49 +248,49 @@ unsigned MultiColvarDensity::getNumberOfQuantities() const { return directions.size() + 2; } -void MultiColvarDensity::clearAverage(){ +void MultiColvarDensity::clearAverage() { std::vector min(directions.size()), max(directions.size()); std::vector gmin(directions.size()), gmax(directions.size());; - for(unsigned i=0;igetPbc().isOrthorombic() ){ - error("I think that density profiles with non-orthorhombic cells don't work. If you want it have a look and see if you can work it out"); - } - - for(unsigned i=0;igetBox()(directions[i],directions[i]); - max[i]*=mycolv->getBox()(directions[i],directions[i]); - } else { - min[i]=cmin[i]; max[i]=cmax[i]; - } - } + for(unsigned i=0; igetPbc().isOrthorombic() ) { + error("I think that density profiles with non-orthorhombic cells don't work. If you want it have a look and see if you can work it out"); + } + + for(unsigned i=0; igetBox()(directions[i],directions[i]); + max[i]*=mycolv->getBox()(directions[i],directions[i]); + } else { + min[i]=cmin[i]; max[i]=cmax[i]; + } + } } - for(unsigned i=0;isetBounds( gmin, gmax, nbins, gspacing ); resizeFunctions(); } -void MultiColvarDensity::prepareForAveraging(){ - for(unsigned i=0;igetBox()(directions[i],directions[i]), max ); - if( max!=mygrid->getMax()[i] ) error("box size should be fixed. Use FRACTIONAL"); +void MultiColvarDensity::prepareForAveraging() { + for(unsigned i=0; igetBox()(directions[i],directions[i]), max ); + if( max!=mygrid->getMax()[i] ) error("box size should be fixed. Use FRACTIONAL"); } // Ensure we only work with active multicolvars deactivateAllTasks(); - for(unsigned i=0;igetNumberOfStoredValues();++i) taskFlags[i]=1; + for(unsigned i=0; igetNumberOfStoredValues(); ++i) taskFlags[i]=1; lockContributors(); // Retrieve the origin - origin = getPosition(0); + origin = getPosition(0); } void MultiColvarDensity::compute( const unsigned& current, MultiValue& myvals ) const { std::vector cvals( mycolv->getNumberOfQuantities() ); stash->retrieveSequentialValue( current, false, cvals ); Vector fpos, apos = pbcDistance( origin, mycolv->getCentralAtomPos( mycolv->getPositionInFullTaskList(current) ) ); - if( fractional ){ fpos = getPbc().realToScaled( apos ); } else { fpos=apos; } + if( fractional ) { fpos = getPbc().realToScaled( apos ); } else { fpos=apos; } - myvals.setValue( 0, cweight*cvals[0] ); for(unsigned j=0;jisDensity() ) error("filtering/transforming density makes no sense"); @@ -43,10 +43,10 @@ BridgedMultiColvarFunction(ao) filter=false; } - readVesselKeywords(); + readVesselKeywords(); } -void MultiColvarFilter::doJobsRequiredBeforeTaskList(){ +void MultiColvarFilter::doJobsRequiredBeforeTaskList() { ActionWithValue::clearDerivatives(); ActionWithVessel::doJobsRequiredBeforeTaskList(); } @@ -54,39 +54,39 @@ void MultiColvarFilter::doJobsRequiredBeforeTaskList(){ void MultiColvarFilter::completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const { invals.copyValues( outvals ); if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); - + // Retrive the value of the multicolvar and apply filter double val=invals.get(1), df, weight=applyFilter( val, df ); // Now propegate derivatives - if( filter && !getPntrToMultiColvar()->weightHasDerivatives ){ - outvals.setValue( 0, weight ); - if( derivativesAreRequired() ){ - for(unsigned i=0;iweightHasDerivatives ) { + outvals.setValue( 0, weight ); + if( derivativesAreRequired() ) { + for(unsigned i=0; i& bb ){ +void MultiColvarFilter::addBridgeForces( const std::vector& bb ) { plumed_dbg_assert( bb.size()==0 ); } diff --git a/src/multicolvar/MultiColvarFilter.h b/src/multicolvar/MultiColvarFilter.h index 8ad4f58f15..e6310bf109 100644 --- a/src/multicolvar/MultiColvarFilter.h +++ b/src/multicolvar/MultiColvarFilter.h @@ -30,7 +30,7 @@ namespace multicolvar { /** \ingroup INHERIT -This is the abstract base class to use for implementing a new way of filtering collective variable values +This is the abstract base class to use for implementing a new way of filtering collective variable values to see whether or not they are within a certain range */ diff --git a/src/multicolvar/MultiColvarProduct.cpp b/src/multicolvar/MultiColvarProduct.cpp index 627cacc530..c7dd7d2c34 100644 --- a/src/multicolvar/MultiColvarProduct.cpp +++ b/src/multicolvar/MultiColvarProduct.cpp @@ -24,7 +24,7 @@ #include "core/ActionRegister.h" #include -#include +#include //+PLUMEDOC MCOLVARF MCOLV_PRODUCT /* @@ -46,41 +46,41 @@ class MultiColvarProduct : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(MultiColvarProduct,"MCOLV_PRODUCT") -void MultiColvarProduct::registerKeywords( Keywords& keys ){ +void MultiColvarProduct::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("compulsory","DATA","the multicolvars you are calculating the product of"); - keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); + keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("SUM"); keys.use("LESS_THAN"); keys.use("HISTOGRAM"); keys.use("HISTOGRAM"); keys.use("MIN"); keys.use("MAX"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("ALT_MIN"); keys.use("BETWEEN"); keys.use("MOMENTS"); } MultiColvarProduct::MultiColvarProduct(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { buildSets(); - for(unsigned i=0;iweightWithDerivatives() ) error("cannot take product of multicolvars with weights"); + for(unsigned i=0; iweightWithDerivatives() ) error("cannot take product of multicolvars with weights"); } } double MultiColvarProduct::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - double dot=1; std::vector tval(2); - for(unsigned i=0;i tval(2); + for(unsigned i=0; i cc(2); - for(unsigned i=0;i cc(2); + for(unsigned i=0; i -#include +#include -//+PLUMEDOC MCOLVARF NLINKS +//+PLUMEDOC MCOLVARF NLINKS /* Calculate number of pairs of atoms/molecules that are "linked" In its simplest guise this coordinate calculates a coordination number. Each pair -of atoms is assumed "linked" if they are within some cutoff of each other. In more +of atoms is assumed "linked" if they are within some cutoff of each other. In more complex applications each entity is a vector and this quantity measures whether -pairs of vectors are (a) within a certain cutoff and (b) if the two vectors have +pairs of vectors are (a) within a certain cutoff and (b) if the two vectors have similar orientations. The vectors on individual atoms could be Steinhardt parameters (see \ref Q3, \ref Q4 and \ref Q6) or they could describe some internal vector in a molecule. @@ -50,7 +50,7 @@ PRINT ARG=dd FILE=colvar \endverbatim The following calculates how many pairs of neighbouring atoms in a system containg 64 atoms have -similar dispositions for the atoms in their coordination sphere. This calculation uses the +similar dispositions for the atoms in their coordination sphere. This calculation uses the dot product of the Q6 vectors on adjacent atoms to measure whether or not two atoms have the same ``orientation" @@ -58,7 +58,7 @@ dot product of the Q6 vectors on adjacent atoms to measure whether or not two at Q6 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q6 NLINKS ARG=q6 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=dd PRINT ARG=dd FILE=colvar -\endverbatim +\endverbatim */ //+ENDPLUMEDOC @@ -69,7 +69,7 @@ namespace multicolvar { class NumberOfLinks : public MultiColvarBase { private: /// The values of the quantities in the dot products - std::vector orient0, orient1; + std::vector orient0, orient1; /// The switching function that tells us if atoms are close enough together SwitchingFunction switchingFunction; public: @@ -80,12 +80,12 @@ class NumberOfLinks : public MultiColvarBase { /// Actually do the calculation double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Is the variable periodic - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(NumberOfLinks,"NLINKS") -void NumberOfLinks::registerKeywords( Keywords& keys ){ +void NumberOfLinks::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); keys.add("atoms","GROUP",""); keys.add("atoms-1","GROUPA",""); @@ -95,36 +95,36 @@ void NumberOfLinks::registerKeywords( Keywords& keys ){ keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords - keys.remove("LOWMEM"); + keys.remove("LOWMEM"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); } NumberOfLinks::NumberOfLinks(const ActionOptions& ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { // The weight of this does have derivatives weightHasDerivatives=true; // Read in the switching function std::string sw, errors; parse("SWITCH",sw); - if(sw.length()>0){ - switchingFunction.set(sw,errors); + if(sw.length()>0) { + switchingFunction.set(sw,errors); } else { - double r_0=-1.0, d_0; int nn, mm; - parse("NN",nn); parse("MM",mm); - parse("R_0",r_0); parse("D_0",d_0); - if( r_0<0.0 ) error("you must set a value for R_0"); - switchingFunction.set(nn,mm,r_0,d_0); + double r_0=-1.0, d_0; int nn, mm; + parse("NN",nn); parse("MM",mm); + parse("R_0",r_0); parse("D_0",d_0); + if( r_0<0.0 ) error("you must set a value for R_0"); + switchingFunction.set(nn,mm,r_0,d_0); } log.printf(" calculating number of links with atoms separation of %s\n",( switchingFunction.description() ).c_str() ); - std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); - setupMultiColvarBase( all_atoms ); setLinkCellCutoff( switchingFunction.get_dmax() ); + std::vector all_atoms; readTwoGroups( "GROUP", "GROUPA", "GROUPB", all_atoms ); + setupMultiColvarBase( all_atoms ); setLinkCellCutoff( switchingFunction.get_dmax() ); - for(unsigned i=0;ihasDifferentiableOrientation() ) error("cannot use multicolvar of type " + getBaseMultiColvar(i)->getName() ); } @@ -139,36 +139,36 @@ double NumberOfLinks::calculateWeight( const unsigned& taskCode, const double& w Vector distance = getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); double dfunc, sw = switchingFunction.calculateSqr( distance.modulo2(), dfunc ); - if( !doNotCalculateDerivatives() ){ - addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); - addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); - myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); + if( !doNotCalculateDerivatives() ) { + addAtomDerivatives( 0, 0, (-dfunc)*weight*distance, myatoms ); + addAtomDerivatives( 0, 1, (dfunc)*weight*distance, myatoms ); + myatoms.addBoxDerivatives( 0, (-dfunc)*weight*Tensor(distance,distance) ); } return sw; } double NumberOfLinks::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; + if( getBaseMultiColvar(0)->getNumberOfQuantities()<3 ) return 1.0; - unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities(); + unsigned ncomp=getBaseMultiColvar(0)->getNumberOfQuantities(); - std::vector orient0( ncomp ), orient1( ncomp ); - getInputData( 0, true, myatoms, orient0 ); - getInputData( 1, true, myatoms, orient1 ); + std::vector orient0( ncomp ), orient1( ncomp ); + getInputData( 0, true, myatoms, orient0 ); + getInputData( 1, true, myatoms, orient1 ); - double dot=0; - for(unsigned k=2;k all_atoms; + int natoms=4; std::vector all_atoms; readAtomsLikeKeyword( "ATOMS", natoms, all_atoms ); setupMultiColvarBase( all_atoms ); - std::vector catom_ind(4, false); + std::vector catom_ind(4, false); catom_ind[1]=catom_ind[2]=true; setAtomsForCentralAtom( catom_ind ); // Read in the vessels - readVesselKeywords(); + readVesselKeywords(); // And check everything has been read in correctly checkRead(); } diff --git a/src/multicolvar/VolumeAround.cpp b/src/multicolvar/VolumeAround.cpp index 69bbfd62c4..bab79d8e0a 100644 --- a/src/multicolvar/VolumeAround.cpp +++ b/src/multicolvar/VolumeAround.cpp @@ -25,31 +25,31 @@ //+PLUMEDOC VOLUMES AROUND /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a particular, user-specified part of of the cell. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(x_i,y_i,z_i) }{ \sum_i w(x_i,y_i,z_i) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(x_i,y_i,z_i) }{ \sum_i w(x_i,y_i,z_i) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (x_i,y_i,z_i)\f$. The function \f$ w(x_i,y_i,z_i) \f$ measures whether or not the system is in the subregion of interest. It is equal to: \f[ -w(x_i,y_i,z_i) = \int_{xl}^{xu} \int_{yl}^{yu} \int_{zl}^{zu} \textrm{d}x\textrm{d}y\textrm{d}z K\left( \frac{x - x_i}{\sigma} \right)K\left( \frac{y - y_i}{\sigma} \right)K\left( \frac{z - z_i}{\sigma} \right) +w(x_i,y_i,z_i) = \int_{xl}^{xu} \int_{yl}^{yu} \int_{zl}^{zu} \textrm{d}x\textrm{d}y\textrm{d}z K\left( \frac{x - x_i}{\sigma} \right)K\left( \frac{y - y_i}{\sigma} \right)K\left( \frac{z - z_i}{\sigma} \right) \f] where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -When AROUND is used with the \ref DENSITY action the number of atoms in the specified region is calculated +When AROUND is used with the \ref DENSITY action the number of atoms in the specified region is calculated \par Examples @@ -79,11 +79,11 @@ class VolumeAround : public ActionVolume { explicit VolumeAround(const ActionOptions& ao); void setupRegions(); double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const ; -}; +}; PLUMED_REGISTER_ACTION(VolumeAround,"AROUND") -void VolumeAround::registerKeywords( Keywords& keys ){ +void VolumeAround::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOM","the atom whose vicinity we are interested in examining"); keys.add("compulsory","XLOWER","0.0","the lower boundary in x relative to the x coordinate of the atom (0 indicates use full extent of box)."); @@ -95,10 +95,10 @@ void VolumeAround::registerKeywords( Keywords& keys ){ } VolumeAround::VolumeAround(const ActionOptions& ao): -Action(ao), -ActionVolume(ao) + Action(ao), + ActionVolume(ao) { - std::vector atom; + std::vector atom; parseAtomList("ATOM",atom); if( atom.size()!=1 ) error("should only be one atom specified"); log.printf(" boundaries for region are calculated based on positions of atom : %d\n",atom[0].serial() ); @@ -108,13 +108,13 @@ ActionVolume(ao) doz=true; parse("ZLOWER",zlow); parse("ZUPPER",zhigh); if( xlow==0.0 && xhigh==0.0 ) dox=false; if( ylow==0.0 && yhigh==0.0 ) doy=false; - if( zlow==0.0 && zhigh==0.0 ) doz=false; + if( zlow==0.0 && zhigh==0.0 ) doz=false; if( !dox && !doy && !doz ) error("no subregion defined use XLOWER, XUPPER, YLOWER, YUPPER, ZLOWER, ZUPPER"); log.printf(" boundaries for region (region of interest about atom) : x %f %f, y %f %f, z %f %f \n",xlow,xhigh,ylow,yhigh,zlow,zhigh); - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); } -void VolumeAround::setupRegions(){ } +void VolumeAround::setupRegions() { } double VolumeAround::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const { // Setup the histogram bead @@ -122,27 +122,27 @@ double VolumeAround::calculateNumberInside( const Vector& cpos, Vector& derivati // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); - double xcontr, ycontr, zcontr, xder, yder, zder; - if( dox ){ - bead.set( xlow, xhigh, getSigma() ); - xcontr=bead.calculate( fpos[0], xder ); + double xcontr, ycontr, zcontr, xder, yder, zder; + if( dox ) { + bead.set( xlow, xhigh, getSigma() ); + xcontr=bead.calculate( fpos[0], xder ); } else { - xcontr=1.; xder=0.; + xcontr=1.; xder=0.; } - if( doy ){ - bead.set( ylow, yhigh, getSigma() ); - ycontr=bead.calculate( fpos[1], yder ); + if( doy ) { + bead.set( ylow, yhigh, getSigma() ); + ycontr=bead.calculate( fpos[1], yder ); } else { - ycontr=1.; yder=0.; + ycontr=1.; yder=0.; } - if( doz ){ - bead.set( zlow, zhigh, getSigma() ); - zcontr=bead.calculate( fpos[2], zder ); + if( doz ) { + bead.set( zlow, zhigh, getSigma() ); + zcontr=bead.calculate( fpos[2], zder ); } else { - zcontr=1.; zder=0.; + zcontr=1.; zder=0.; } - derivatives[0]=xder*ycontr*zcontr; - derivatives[1]=xcontr*yder*zcontr; + derivatives[0]=xder*ycontr*zcontr; + derivatives[1]=xcontr*yder*zcontr; derivatives[2]=xcontr*ycontr*zder; // Add derivatives wrt to position of origin atom refders[0] = -derivatives; diff --git a/src/multicolvar/VolumeCavity.cpp b/src/multicolvar/VolumeCavity.cpp index 65c232a90f..af14a2be05 100644 --- a/src/multicolvar/VolumeCavity.cpp +++ b/src/multicolvar/VolumeCavity.cpp @@ -28,22 +28,22 @@ //+PLUMEDOC VOLUMES CAVITY /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a box defined by the positions of four atoms. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (u_i,v_i,z_i)\f$. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ +Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation matrix as follows: \f[ @@ -63,23 +63,23 @@ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation m \right) \f] -where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the -refererence positions specified by the user. The first of these unit vectors points from the first reference atom to the second. -The second is then the normal to the plane containing atoms 1,2 and 3 and the the third is the unit vector orthogonal to -these first two vectors. \f$(x_o,y_o,z_o)\f$, meanwhile, specifies the position of the first reference atom. +where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the +refererence positions specified by the user. The first of these unit vectors points from the first reference atom to the second. +The second is then the normal to the plane containing atoms 1,2 and 3 and the the third is the unit vector orthogonal to +these first two vectors. \f$(x_o,y_o,z_o)\f$, meanwhile, specifies the position of the first reference atom. In the previous function \f$ w(u_i,v_i,w_i) \f$ measures whether or not the system is in the subregion of interest. It is equal to: \f[ -w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w - K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) +w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w + K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) \f] where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. -The vector connecting atom 1 to atom 4 is used to define the extent of the box in each of the \f$u\f$, \f$v\f$ and \f$w\f$ +The vector connecting atom 1 to atom 4 is used to define the extent of the box in each of the \f$u\f$, \f$v\f$ and \f$w\f$ directions. Essentially the vector connecting atom 1 to atom 4 is projected onto the three unit vectors -described above and the resulting projections determine the \f$u'\f$, \f$v'\f$ and \f$w'\f$ parameters in the above expression. +described above and the resulting projections determine the \f$u'\f$, \f$v'\f$ and \f$w'\f$ parameters in the above expression. \par Examples @@ -87,11 +87,11 @@ The following commands tell plumed to calculate the number of atoms in an ion ch The extent of the chanel is calculated from the positions of atoms 1, 4, 5 and 11. The final value will be labeled cav. \verbatim -d1: DENSITY SPECIES=20-500 +d1: DENSITY SPECIES=20-500 CAVITY DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 LABEL=cav \endverbatim -The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water +The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water molecules in the protein channel described above. The average coordination number and the number of coordination numbers more than 4 is then calculated. The values of these two quantities are given the labels cav.mean and cav.morethan @@ -127,7 +127,7 @@ class VolumeCavity : public ActionVolume { PLUMED_REGISTER_ACTION(VolumeCavity,"CAVITY") -void VolumeCavity::registerKeywords( Keywords& keys ){ +void VolumeCavity::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOMS","the positions of four atoms that define spatial extent of the cavity"); keys.addFlag("PRINT_BOX",false,"write out the positions of the corners of the box to an xyz file"); @@ -136,54 +136,54 @@ void VolumeCavity::registerKeywords( Keywords& keys ){ } VolumeCavity::VolumeCavity(const ActionOptions& ao): -Action(ao), -ActionVolume(ao), -boxout(false), -lenunit(1.0), -dlbi(4), -dlcross(4), -dlperp(4), -dbi(3), -dcross(3), -dperp(3) + Action(ao), + ActionVolume(ao), + boxout(false), + lenunit(1.0), + dlbi(4), + dlcross(4), + dlperp(4), + dbi(3), + dcross(3), + dperp(3) { std::vector atoms; parseAtomList("ATOMS",atoms); if( atoms.size()!=4 ) error("number of atoms should be equal to four"); log.printf(" boundaries for region are calculated based on positions of atoms : "); - for(unsigned i=0;i0 ){ - Units u; u.setLength(unitname); - lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); - } else { - unitname="nm"; - } - boxfile.link(*this); - boxfile.open( boxfname.c_str() ); - log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); - } + if(boxout) { + std::string boxfname; parse("FILE",boxfname); + if(boxfname.length()==0) error("no name for box file specified"); + std::string unitname; parse("UNITS",unitname); + if ( unitname.length()>0 ) { + Units u; u.setLength(unitname); + lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); + } else { + unitname="nm"; + } + boxfile.link(*this); + boxfile.open( boxfname.c_str() ); + log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); + } checkRead(); requestAtoms(atoms); // We have to readd the dependency because requestAtoms removes it - addDependency( getPntrToMultiColvar() ); + addDependency( getPntrToMultiColvar() ); } -VolumeCavity::~VolumeCavity(){ +VolumeCavity::~VolumeCavity() { } -void VolumeCavity::setupRegions(){ +void VolumeCavity::setupRegions() { // Make some space for things Vector d1, d2, d3; - + // Retrieve the sigma value sigma=getSigma(); // Set the position of the origin @@ -194,21 +194,21 @@ void VolumeCavity::setupRegions(){ double d1l=d1.modulo(); d2 = pbcDistance(origin,getPosition(2)); - // Find the vector connecting the origin to the top corner of + // Find the vector connecting the origin to the top corner of // the subregion d3 = pbcDistance(origin,getPosition(3)); // Create a set of unit vectors bi = d1 / d1l; len_bi=dotProduct( d3, bi ); - cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); + cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); cross = cross / crossmod; len_cross=dotProduct( d3, cross ); perp = crossProduct( cross, bi ); len_perp=dotProduct( d3, perp ); // Calculate derivatives of box shape with respect to atoms - double d1l3=d1l*d1l*d1l; + double d1l3=d1l*d1l*d1l; dbi[0](0,0) = ( -(d1[1]*d1[1]+d1[2]*d1[2])/d1l3 ); // dx/dx dbi[0](0,1) = ( d1[0]*d1[1]/d1l3 ); // dx/dy - dbi[0](0,2) = ( d1[0]*d1[2]/d1l3 ); // dx/dz + dbi[0](0,2) = ( d1[0]*d1[2]/d1l3 ); // dx/dz dbi[0](1,0) = ( d1[1]*d1[0]/d1l3 ); // dy/dx dbi[0](1,1) = ( -(d1[0]*d1[0]+d1[2]*d1[2])/d1l3 ); // dy/dy dbi[0](1,2) = ( d1[1]*d1[2]/d1l3 ); @@ -233,7 +233,7 @@ void VolumeCavity::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,-1.0) ) + crossProduct( Vector(0.0,0.0,-1.0), d2 ) ); dcross[0](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[0](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[0](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[0](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[0](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -246,7 +246,7 @@ void VolumeCavity::setupRegions(){ tcderiv.setCol( 2, crossProduct( Vector(0.0,0.0,1.0), d2 ) ); dcross[1](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[1](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[1](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[1](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[1](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -259,7 +259,7 @@ void VolumeCavity::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,1.0) ) ); dcross[2](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[2](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[2](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[2](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[2](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -280,33 +280,33 @@ void VolumeCavity::setupRegions(){ dperp[2].setCol( 2, ( crossProduct( dcross[2].getCol(2), bi ) ) ); // Ensure that all lengths are positive - if( len_bi<0 ){ - bi=-bi; len_bi=-len_bi; - for(unsigned i=0;i<3;++i) dbi[i]*=-1.0; + if( len_bi<0 ) { + bi=-bi; len_bi=-len_bi; + for(unsigned i=0; i<3; ++i) dbi[i]*=-1.0; } - if( len_cross<0 ){ - cross=-cross; len_cross=-len_cross; - for(unsigned i=0;i<3;++i) dcross[i]*=-1.0; + if( len_cross<0 ) { + cross=-cross; len_cross=-len_cross; + for(unsigned i=0; i<3; ++i) dcross[i]*=-1.0; + } + if( len_perp<0 ) { + perp=-perp; len_perp=-len_perp; + for(unsigned i=0; i<3; ++i) dperp[i]*=-1.0; } - if( len_perp<0 ){ - perp=-perp; len_perp=-len_perp; - for(unsigned i=0;i<3;++i) dperp[i]*=-1.0; - } if( len_bi<=0 || len_cross<=0 || len_bi<=0 ) plumed_merror("Invalid box coordinates"); // Now derivatives of lengths - Tensor dd3( Tensor::identity() ); - dlbi[0] = matmul(d3,dbi[0]) - matmul(bi,dd3); + Tensor dd3( Tensor::identity() ); + dlbi[0] = matmul(d3,dbi[0]) - matmul(bi,dd3); dlbi[1] = matmul(d3,dbi[1]); dlbi[2] = matmul(d3,dbi[2]); dlbi[3] = matmul(bi,dd3); - dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); + dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); dlcross[1] = matmul(d3,dcross[1]); dlcross[2] = matmul(d3,dcross[2]); dlcross[3] = matmul(cross,dd3); - dlperp[0] = matmul(d3,dperp[0]) - matmul(perp,dd3); + dlperp[0] = matmul(d3,dperp[0]) - matmul(perp,dd3); dlperp[1] = matmul(d3,dperp[1]); dlperp[2] = matmul(d3,dperp[2]); dlperp[3] = matmul(perp,dd3); @@ -319,39 +319,39 @@ void VolumeCavity::setupRegions(){ jacob_det = fabs( jacob.determinant() ); } -void VolumeCavity::update(){ - if(boxout){ - boxfile.printf("%d\n",8); - const Tensor & t(getPbc().getBox()); - if(getPbc().isOrthorombic()){ - boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ - boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); - } - boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); - Vector ut, vt, wt; - ut = origin + len_bi*bi; - vt = origin + len_cross*cross; - wt = origin + len_perp*perp; - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]) , lenunit*(ut[1]), lenunit*(ut[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]) , lenunit*(vt[1]), lenunit*(vt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]) , lenunit*(wt[1]), lenunit*(wt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_bi*bi[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), - lenunit*(ut[1]+len_perp*perp[1]), - lenunit*(ut[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), - lenunit*(vt[1]+len_perp*perp[1]), - lenunit*(vt[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); +void VolumeCavity::update() { + if(boxout) { + boxfile.printf("%d\n",8); + const Tensor & t(getPbc().getBox()); + if(getPbc().isOrthorombic()) { + boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); + } else { + boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); + } + boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); + Vector ut, vt, wt; + ut = origin + len_bi*bi; + vt = origin + len_cross*cross; + wt = origin + len_perp*perp; + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]), lenunit*(ut[1]), lenunit*(ut[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]), lenunit*(vt[1]), lenunit*(vt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]), lenunit*(wt[1]), lenunit*(wt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_bi*bi[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), + lenunit*(ut[1]+len_perp*perp[1]), + lenunit*(ut[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), + lenunit*(vt[1]+len_perp*perp[1]), + lenunit*(vt[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); } } @@ -367,8 +367,8 @@ double VolumeCavity::calculateNumberInside( const Vector& cpos, Vector& derivati bead.set( 0, len_bi, sigma ); double upos=dotProduct( datom, bi ); ucontr=bead.calculate( upos, uder ); - double udlen=bead.uboundDerivative( upos ); - double uder2 = bead.lboundDerivative( upos ) - udlen; + double udlen=bead.uboundDerivative( upos ); + double uder2 = bead.lboundDerivative( upos ) - udlen; // Calculate contribution from integral along cross bead.set( 0, len_cross, sigma ); @@ -388,24 +388,24 @@ double VolumeCavity::calculateNumberInside( const Vector& cpos, Vector& derivati derivatives[0] = (dfd[0]*bi[0]+dfd[1]*cross[0]+dfd[2]*perp[0]); derivatives[1] = (dfd[0]*bi[1]+dfd[1]*cross[1]+dfd[2]*perp[1]); derivatives[2] = (dfd[0]*bi[2]+dfd[1]*cross[2]+dfd[2]*perp[2]); - double tot = ucontr*vcontr*wcontr*jacob_det; + double tot = ucontr*vcontr*wcontr*jacob_det; // Add reference atom derivatives dfd[0]=uder2*vcontr*wcontr; dfd[1]=ucontr*vder2*wcontr; dfd[2]=ucontr*vcontr*wder2; Vector dfld; dfld[0]=udlen*vcontr*wcontr; dfld[1]=ucontr*vdlen*wcontr; dfld[2]=ucontr*vcontr*wdlen; rderiv[0] = dfd[0]*matmul(datom,dbi[0]) + dfd[1]*matmul(datom,dcross[0]) + dfd[2]*matmul(datom,dperp[0]) + - dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; - rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + + dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; + rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + dfld[0]*dlbi[1] + dfld[1]*dlcross[1] + dfld[2]*dlperp[1]; - rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + + rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + dfld[0]*dlbi[2] + dfld[1]*dlcross[2] + dfld[2]*dlperp[2]; rderiv[3] = dfld[0]*dlbi[3] + dfld[1]*dlcross[3] + dfld[2]*dlperp[3]; vir.zero(); vir-=Tensor( cpos,derivatives ); - for(unsigned i=0;i<4;++i){ - vir -= Tensor( getPosition(i), rderiv[i] ); + for(unsigned i=0; i<4; ++i) { + vir -= Tensor( getPosition(i), rderiv[i] ); } - + return tot; } diff --git a/src/multicolvar/VolumeGradientBase.cpp b/src/multicolvar/VolumeGradientBase.cpp index ffbda80d6f..db1b48f6ab 100644 --- a/src/multicolvar/VolumeGradientBase.cpp +++ b/src/multicolvar/VolumeGradientBase.cpp @@ -27,121 +27,121 @@ namespace PLMD { namespace multicolvar { -void VolumeGradientBase::registerKeywords( Keywords& keys ){ +void VolumeGradientBase::registerKeywords( Keywords& keys ) { BridgedMultiColvarFunction::registerKeywords( keys ); } VolumeGradientBase::VolumeGradientBase(const ActionOptions&ao): -Action(ao), -BridgedMultiColvarFunction(ao) + Action(ao), + BridgedMultiColvarFunction(ao) { } -void VolumeGradientBase::requestAtoms( const std::vector& atoms ){ +void VolumeGradientBase::requestAtoms( const std::vector& atoms ) { ActionAtomistic::requestAtoms(atoms); bridgeVariable=3*atoms.size(); - std::map checklabs; - for(const auto & p : getDependencies() ) checklabs.insert(std::pair(p->getLabel(),false)); - for(const auto & p : plumed.getActionSet() ){ - if( p->getLabel()==getPntrToMultiColvar()->getLabel() ) break; - if( checklabs.count(p->getLabel()) ) checklabs[p->getLabel()]=true; + std::map checklabs; + for(const auto & p : getDependencies() ) checklabs.insert(std::pair(p->getLabel(),false)); + for(const auto & p : plumed.getActionSet() ) { + if( p->getLabel()==getPntrToMultiColvar()->getLabel() ) break; + if( checklabs.count(p->getLabel()) ) checklabs[p->getLabel()]=true; } - for(const auto & p : checklabs ){ - if( !p.second ) error("the input for the virtual atoms used in the input for this action must appear in the input file before the input multicolvar"); + for(const auto & p : checklabs ) { + if( !p.second ) error("the input for the virtual atoms used in the input for this action must appear in the input file before the input multicolvar"); } - addDependency( getPntrToMultiColvar() ); + addDependency( getPntrToMultiColvar() ); tmpforces.resize( 3*atoms.size()+9 ); } -void VolumeGradientBase::doJobsRequiredBeforeTaskList(){ +void VolumeGradientBase::doJobsRequiredBeforeTaskList() { ActionWithValue::clearDerivatives(); retrieveAtoms(); setupRegions(); ActionWithVessel::doJobsRequiredBeforeTaskList(); } void VolumeGradientBase::completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const { - if( getPntrToMultiColvar()->isDensity() ){ - outvals.setValue(0, 1.0); outvals.setValue(1, 1.0); + if( getPntrToMultiColvar()->isDensity() ) { + outvals.setValue(0, 1.0); outvals.setValue(1, 1.0); } else { - // Copy derivatives of the colvar and the value of the colvar - invals.copyValues( outvals ); - if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); + // Copy derivatives of the colvar and the value of the colvar + invals.copyValues( outvals ); + if( derivativesAreRequired() ) invals.copyDerivatives( outvals ); } - calculateAllVolumes( curr, outvals ); + calculateAllVolumes( curr, outvals ); } -void VolumeGradientBase::setNumberInVolume( const unsigned& ivol, const unsigned& curr, const double& weight, - const Vector& wdf, const Tensor& virial, const std::vector& refders, - MultiValue& outvals ) const { - MultiColvarBase* mcolv=getPntrToMultiColvar(); - if( !mcolv->weightHasDerivatives ){ - outvals.setValue(ivol, weight ); - if( derivativesAreRequired() ){ - CatomPack catom; mcolv->getCentralAtomPack( 0, curr, catom ); - for(unsigned i=0;igetNumberOfDerivatives(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) outvals.addDerivative( ivol, nmder-9+3*i+j, virial(i,j) ); - for(unsigned i=0;i& refders, + MultiValue& outvals ) const { + MultiColvarBase* mcolv=getPntrToMultiColvar(); + if( !mcolv->weightHasDerivatives ) { + outvals.setValue(ivol, weight ); + if( derivativesAreRequired() ) { + CatomPack catom; mcolv->getCentralAtomPack( 0, curr, catom ); + for(unsigned i=0; igetCentralAtomPack( 0, curr, catom ); - for(unsigned i=0;igetNumberOfDerivatives(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) outvals.addDerivative( ivol, nmder-9+3*i+j, ww*virial(i,j) ); - for(unsigned i=0;igetNumberOfDerivatives(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) outvals.addDerivative( ivol, nmder-9+3*i+j, virial(i,j) ); + for(unsigned i=0; igetCentralAtomPack( 0, curr, catom ); + for(unsigned i=0; igetNumberOfDerivatives(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) outvals.addDerivative( ivol, nmder-9+3*i+j, ww*virial(i,j) ); + for(unsigned i=0; igetCentralAtomPack( 0, curr, catom ); - for(unsigned i=0;igetNumberOfDerivatives(); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) outvals.addDerivative( ivol, nmder-9+3*i+j, ww*virial(i,j) ); - for(unsigned i=0;igetCentralAtomPack( 0, curr, catom ); + for(unsigned i=0; igetNumberOfDerivatives(); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) outvals.addDerivative( ivol, nmder-9+3*i+j, ww*virial(i,j) ); + for(unsigned i=0; i& bb ){ +void VolumeGradientBase::addBridgeForces( const std::vector& bb ) { plumed_dbg_assert( bb.size()==tmpforces.size()-9 ); // Forces on local atoms - for(unsigned i=0;i tmpforces; @@ -41,10 +41,10 @@ friend class MultiColvarBase; Vector pbcDistance( const Vector& v1, const Vector& v2) const; /// Get position of atom Vector getPosition( int iatom ) const ; -/// Request the atoms +/// Request the atoms void requestAtoms( const std::vector& atoms ); /// Set the number in the volume - void setNumberInVolume( const unsigned& , const unsigned& , const double& , const Vector& , const Tensor& , const std::vector& , MultiValue& ) const ; + void setNumberInVolume( const unsigned&, const unsigned&, const double&, const Vector&, const Tensor&, const std::vector&, MultiValue& ) const ; public: static void registerKeywords( Keywords& keys ); explicit VolumeGradientBase(const ActionOptions&); @@ -54,40 +54,40 @@ friend class MultiColvarBase; void completeTask( const unsigned& curr, MultiValue& invals, MultiValue& outvals ) const ; /// Calculate what is in the volumes virtual void calculateAllVolumes( const unsigned& curr, MultiValue& outvals ) const=0; -/// Setup the regions that this is based on +/// Setup the regions that this is based on virtual void setupRegions()=0; /// Forces here are applied through the bridge void addBridgeForces( const std::vector& bb ); }; inline -const Tensor & VolumeGradientBase::getBox()const{ +const Tensor & VolumeGradientBase::getBox()const { return getPntrToMultiColvar()->getBox(); -} +} inline const Pbc & VolumeGradientBase::getPbc() const { - return getPntrToMultiColvar()->getPbc(); + return getPntrToMultiColvar()->getPbc(); } inline Vector VolumeGradientBase::pbcDistance( const Vector& v1, const Vector& v2) const { - return getPntrToMultiColvar()->pbcDistance(v1,v2); + return getPntrToMultiColvar()->pbcDistance(v1,v2); } inline Vector VolumeGradientBase::getPosition( int iatom ) const { - if( !checkNumericalDerivatives() ) return ActionAtomistic::getPosition(iatom); - // This is for numerical derivatives of quantity wrt to the local atoms - Vector tmp_p = ActionAtomistic::getPosition(iatom); - if( bridgeVariable<3*getNumberOfAtoms() ){ + if( !checkNumericalDerivatives() ) return ActionAtomistic::getPosition(iatom); +// This is for numerical derivatives of quantity wrt to the local atoms + Vector tmp_p = ActionAtomistic::getPosition(iatom); + if( bridgeVariable<3*getNumberOfAtoms() ) { if( bridgeVariable>=3*iatom && bridgeVariable<(iatom+1)*3 ) tmp_p[bridgeVariable%3]+=sqrt(epsilon); - } - // This makes sure that numerical derivatives of virial are calculated correctly - tmp_p = ActionAtomistic::getPbc().realToScaled( tmp_p ); - tmp_p = getPbc().scaledToReal( tmp_p ); - return tmp_p; -} + } +// This makes sure that numerical derivatives of virial are calculated correctly + tmp_p = ActionAtomistic::getPbc().realToScaled( tmp_p ); + tmp_p = getPbc().scaledToReal( tmp_p ); + return tmp_p; +} } } diff --git a/src/multicolvar/VolumeInCylinder.cpp b/src/multicolvar/VolumeInCylinder.cpp index 3008bd156d..eb6bc611e4 100644 --- a/src/multicolvar/VolumeInCylinder.cpp +++ b/src/multicolvar/VolumeInCylinder.cpp @@ -26,33 +26,33 @@ //+PLUMEDOC VOLUMES INCYLINDER /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a particular, user-specified part of of the cell. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r_{xy}) }{ \sum_i \sigma(r_{xy}) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r_{xy}) }{ \sum_i \sigma(r_{xy}) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (x_i,y_i,z_i)\f$. -The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the -collective is located \f$(x_i,y_i,z_i)\f$ and the position of the atom that was specified using the ORIGIN keyword +The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the +collective is located \f$(x_i,y_i,z_i)\f$ and the position of the atom that was specified using the ORIGIN keyword projected in the xy plane if DIRECTION=z is used. In other words: \f[ r_{xy} = sqrt{ ( x_i - x_0)^2 + ( y_i - y_0)^2 } \f] -In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a cylinder that +In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a cylinder that runs along the axis specified using the DIRECTION keyword and that is centered on the position of the atom specified using ORIGIN. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated +When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated \par Examples @@ -60,7 +60,7 @@ The input below can be use to calculate the average coordination numbers for tho of radius 1.5 nm that is centered on the position of atom 101 and that has its long axis parallel to the z-axis. \verbatim -c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} +c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} d2: INCYLINDER ATOM=101 DATA=d1 DIRECTION=Z RADIUS={TANH R_0=1.5} SIGMA=0.1 LOWER=-0.1 UPPER=0.1 MEAN PRINT ARG=d2.* FILE=colvar \endverbatim @@ -76,18 +76,18 @@ class VolumeInCylinder : public ActionVolume { bool docylinder; Vector origin; HistogramBead bead; - std::vector dir; + std::vector dir; SwitchingFunction switchingFunction; public: static void registerKeywords( Keywords& keys ); explicit VolumeInCylinder (const ActionOptions& ao); void setupRegions(); double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const ; -}; +}; PLUMED_REGISTER_ACTION(VolumeInCylinder,"INCYLINDER") -void VolumeInCylinder::registerKeywords( Keywords& keys ){ +void VolumeInCylinder::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOM","the atom whose vicinity we are interested in examining"); keys.add("compulsory","DIRECTION","the direction of the long axis of the cylinder. Must be x, y or z"); @@ -98,21 +98,21 @@ void VolumeInCylinder::registerKeywords( Keywords& keys ){ } VolumeInCylinder::VolumeInCylinder(const ActionOptions& ao): -Action(ao), -ActionVolume(ao), -docylinder(false) + Action(ao), + ActionVolume(ao), + docylinder(false) { - std::vector atom; + std::vector atom; parseAtomList("ATOM",atom); if( atom.size()!=1 ) error("should only be one atom specified"); log.printf(" center of cylinder is at position of atom : %d\n",atom[0].serial() ); std::string sdir; parse("DIRECTION",sdir); - if( sdir=="X"){dir.push_back(1); dir.push_back(2); dir.push_back(0); } - else if( sdir=="Y"){dir.push_back(0); dir.push_back(2); dir.push_back(1); } - else if( sdir=="Z"){dir.push_back(0); dir.push_back(1); dir.push_back(2); } + if( sdir=="X") {dir.push_back(1); dir.push_back(2); dir.push_back(0); } + else if( sdir=="Y") {dir.push_back(0); dir.push_back(2); dir.push_back(1); } + else if( sdir=="Z") {dir.push_back(0); dir.push_back(1); dir.push_back(2); } else { error(sdir + "is not a valid direction. Should be X, Y or Z"); } - log.printf(" cylinder's long axis is along %s axis\n",sdir.c_str() ); + log.printf(" cylinder's long axis is along %s axis\n",sdir.c_str() ); std::string sw, errors; parse("RADIUS",sw); if(sw.length()==0) error("missing RADIUS keyword"); @@ -121,33 +121,33 @@ docylinder(false) log.printf(" radius of cylinder is given by %s \n", ( switchingFunction.description() ).c_str() ); double min, max; parse("LOWER",min); parse("UPPER",max); - if( min!=0.0 || max!=0.0 ){ - if( min>max ) error("minimum of cylinder should be less than maximum"); - docylinder=true; - log.printf(" cylinder extends from %f to %f along the %s axis\n",min,max,sdir.c_str() ); - bead.isNotPeriodic(); bead.setKernelType( getKernelType() ); bead.set( min, max, getSigma() ); + if( min!=0.0 || max!=0.0 ) { + if( min>max ) error("minimum of cylinder should be less than maximum"); + docylinder=true; + log.printf(" cylinder extends from %f to %f along the %s axis\n",min,max,sdir.c_str() ); + bead.isNotPeriodic(); bead.setKernelType( getKernelType() ); bead.set( min, max, getSigma() ); } - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); } -void VolumeInCylinder::setupRegions(){ } +void VolumeInCylinder::setupRegions() { } double VolumeInCylinder::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const { // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); - + double vcylinder, dcylinder; - if( docylinder ){ - vcylinder=bead.calculate( fpos[dir[2]], dcylinder ); + if( docylinder ) { + vcylinder=bead.calculate( fpos[dir[2]], dcylinder ); } else { - vcylinder=1.0; dcylinder=0.0; + vcylinder=1.0; dcylinder=0.0; } const double dd = fpos[dir[0]]*fpos[dir[0]] + fpos[dir[1]]*fpos[dir[1]]; double dfunc, vswitch = switchingFunction.calculateSqr( dd, dfunc ); derivatives.zero(); double value=vswitch*vcylinder; - derivatives[dir[0]]=vcylinder*dfunc*fpos[dir[0]]; + derivatives[dir[0]]=vcylinder*dfunc*fpos[dir[0]]; derivatives[dir[1]]=vcylinder*dfunc*fpos[dir[1]]; derivatives[dir[2]]=vswitch*dcylinder; // Add derivatives wrt to position of origin atom diff --git a/src/multicolvar/VolumeInSphere.cpp b/src/multicolvar/VolumeInSphere.cpp index 61badf5f35..632af88df5 100644 --- a/src/multicolvar/VolumeInSphere.cpp +++ b/src/multicolvar/VolumeInSphere.cpp @@ -26,40 +26,40 @@ //+PLUMEDOC VOLUMES INSPHERE /* -This quantity can be used to calculate functions of the distribution of collective +This quantity can be used to calculate functions of the distribution of collective variables for the atoms that lie in a particular, user-specified part of of the cell. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r) }{ \sum_i \sigma(r) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) \sigma(r) }{ \sum_i \sigma(r) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (x_i,y_i,z_i)\f$. -The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the +The function \f$\sigma\f$ is a \ref switchingfunction that acts on the distance between the point at which the collective is located \f$(x_i,y_i,z_i)\f$ and the position of the atom that was specified using the ORIGIN keyword. In other words: \f[ r = sqrt{ ( x_i - x_0)^2 + ( y_i - y_0)^2 + ( z_i - z_0)^2} -\f] -In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a sphere that is +\f] +In short this function, \f$\sigma(r_{xy})\f$, measures whether or not the CV is within a sphere that is centered on the position of the atom specified using the keyword ORIGIN. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated +When INCYLINDER is used with the \ref DENSITY action the number of atoms in the specified region is calculated \par Examples -The input below can be use to calculate the average coordination numbers for those atoms that are within a sphere +The input below can be use to calculate the average coordination numbers for those atoms that are within a sphere of radius 1.5 nm that is centered on the position of atom 101. \verbatim -c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} +c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} d2: INSPHERE ATOM=101 DATA=d1 RADIUS={TANH R_0=1.5} SIGMA=0.1 LOWER=-0.1 UPPER=0.1 MEAN PRINT ARG=d2.* FILE=colvar \endverbatim @@ -79,11 +79,11 @@ class VolumeInSphere : public ActionVolume { explicit VolumeInSphere(const ActionOptions& ao); void setupRegions(); double calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const ; -}; +}; PLUMED_REGISTER_ACTION(VolumeInSphere,"INSPHERE") -void VolumeInSphere::registerKeywords( Keywords& keys ){ +void VolumeInSphere::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOM","the atom whose vicinity we are interested in examining"); keys.add("compulsory","RADIUS","the switching function that tells us the extent of the sphereical region of interest"); @@ -91,10 +91,10 @@ void VolumeInSphere::registerKeywords( Keywords& keys ){ } VolumeInSphere::VolumeInSphere(const ActionOptions& ao): -Action(ao), -ActionVolume(ao) + Action(ao), + ActionVolume(ao) { - std::vector atom; + std::vector atom; parseAtomList("ATOM",atom); if( atom.size()!=1 ) error("should only be one atom specified"); log.printf(" center of sphere is at position of atom : %d\n",atom[0].serial() ); @@ -105,15 +105,15 @@ ActionVolume(ao) if( errors.length()!=0 ) error("problem reading RADIUS keyword : " + errors ); log.printf(" radius of sphere is given by %s \n", ( switchingFunction.description() ).c_str() ); - checkRead(); requestAtoms(atom); + checkRead(); requestAtoms(atom); } -void VolumeInSphere::setupRegions(){ } +void VolumeInSphere::setupRegions() { } double VolumeInSphere::calculateNumberInside( const Vector& cpos, Vector& derivatives, Tensor& vir, std::vector& refders ) const { // Calculate position of atom wrt to origin Vector fpos=pbcDistance( getPosition(0), cpos ); - double dfunc, value = switchingFunction.calculateSqr( fpos.modulo2(), dfunc ); + double dfunc, value = switchingFunction.calculateSqr( fpos.modulo2(), dfunc ); derivatives.zero(); derivatives = dfunc*fpos; refders[0] = -derivatives; // Add a virial contribution vir -= Tensor(fpos,derivatives); diff --git a/src/multicolvar/VolumeTetrapore.cpp b/src/multicolvar/VolumeTetrapore.cpp index f2cb668b30..98fe915c33 100644 --- a/src/multicolvar/VolumeTetrapore.cpp +++ b/src/multicolvar/VolumeTetrapore.cpp @@ -26,24 +26,24 @@ #include "tools/Pbc.h" #include "ActionVolume.h" -//+PLUMEDOC VOLUMES TETRAHEDRALPORE +//+PLUMEDOC VOLUMES TETRAHEDRALPORE /* This quantity can be used to calculate functions of the distribution of collective variables for the atoms lie that lie in a box defined by the positions of four atoms at the corners of a tetrahedron. -Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three +Each of the base quantities calculated by a multicolvar can can be assigned to a particular point in three dimensional space. For example, if we have the coordination numbers for all the atoms in the -system each coordination number can be assumed to lie on the position of the central atom. +system each coordination number can be assumed to lie on the position of the central atom. Because each base quantity can be assigned to a particular point in space we can calculate functions of the distribution of base quantities in a particular part of the box by using: \f[ -\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } -\f] +\overline{s}_{\tau} = \frac{ \sum_i f(s_i) w(u_i,v_i,w_i) }{ \sum_i w(u_i,v_i,w_i) } +\f] where the sum is over the collective variables, \f$s_i\f$, each of which can be thought to be at \f$ (u_i,v_i,z_i)\f$. The function \f$(s_i)\f$ can be any of the usual LESS_THAN, MORE_THAN, WITHIN etc that are used in all other multicolvars. -Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ +Notice that here (at variance with what is done in \ref AROUND) we have transformed from the usual \f$(x_i,y_i,z_i)\f$ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation matrix as follows: \f[ @@ -63,10 +63,10 @@ position to a position in \f$ (u_i,v_i,z_i)\f$. This is done using a rotation m \right) \f] -where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the -refererence positions specified by the user. Initially unit vectors are found by calculating the bisector, \f$\mathbf{b}\f$, and -cross product, \f$\mathbf{c}\f$, of the vectors connecting atoms 1 and 2. A third unit vector, \f$\mathbf{p}\f$ is then found by taking the cross -product between the cross product calculated during the first step, \f$\mathbf{c}\f$ and the bisector, \f$\mathbf{b}\f$. From this +where \f$\mathbf{R}\f$ is a rotation matrix that is calculated by constructing a set of three orthonormal vectors from the +refererence positions specified by the user. Initially unit vectors are found by calculating the bisector, \f$\mathbf{b}\f$, and +cross product, \f$\mathbf{c}\f$, of the vectors connecting atoms 1 and 2. A third unit vector, \f$\mathbf{p}\f$ is then found by taking the cross +product between the cross product calculated during the first step, \f$\mathbf{c}\f$ and the bisector, \f$\mathbf{b}\f$. From this second cross product \f$\mathbf{p}\f$ and the bisector \f$\mathbf{b}\f$ two new vectors are calculated using: \f[ @@ -78,13 +78,13 @@ In the previous function \f$ w(u_i,v_i,w_i) \f$ measures whether or not the syst is equal to: \f[ -w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w - K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) +w(u_i,v_i,w_i) = \int_{0}^{u'} \int_{0}^{v'} \int_{0}^{w'} \textrm{d}u\textrm{d}v\textrm{d}w + K\left( \frac{u - u_i}{\sigma} \right)K\left( \frac{v - v_i}{\sigma} \right)K\left( \frac{w - w_i}{\sigma} \right) \f] -where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. -The values of \f$u'\f$ and \f$v'\f$ are found by finding the projections of the vectors connecting atoms 1 and 2 and 1 -and 3 \f$v_1\f$ and \f$v_2\f$. This gives four projections: the largest two projections are used in the remainder of +where \f$K\f$ is one of the kernel functions described on \ref histogrambead and \f$\sigma\f$ is a bandwidth parameter. +The values of \f$u'\f$ and \f$v'\f$ are found by finding the projections of the vectors connecting atoms 1 and 2 and 1 +and 3 \f$v_1\f$ and \f$v_2\f$. This gives four projections: the largest two projections are used in the remainder of the calculations. \f$w'\f$ is calculated by taking the projection of the vector connecting atoms 1 and 4 on the vector \f$\mathbf{c}\f$. Notice that the manner by which this box is constructed differs from the way this is done in \ref CAVITY. This is in fact the only point of difference between these two actions. @@ -95,11 +95,11 @@ The following commands tell plumed to calculate the number of atom inside a tetr cavity is calculated from the positions of atoms 1, 4, 5, and 11, The final value will be labeled cav. \verbatim -d1: DENSITY SPECIES=20-500 +d1: DENSITY SPECIES=20-500 TETRAHEDRALPORE DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 LABEL=cav \endverbatim -The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water +The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water molecules in the tetrahedral cavity described above. The average coordination number and the number of coordination numbers more than 4 is then calculated. The values of these two quantities are given the labels cav.mean and cav.morethan @@ -135,7 +135,7 @@ class VolumeTetrapore : public ActionVolume { PLUMED_REGISTER_ACTION(VolumeTetrapore,"TETRAHEDRALPORE") -void VolumeTetrapore::registerKeywords( Keywords& keys ){ +void VolumeTetrapore::registerKeywords( Keywords& keys ) { ActionVolume::registerKeywords( keys ); keys.add("atoms","ATOMS","the positions of four atoms that define spatial extent of the cavity"); keys.addFlag("PRINT_BOX",false,"write out the positions of the corners of the box to an xyz file"); @@ -144,54 +144,54 @@ void VolumeTetrapore::registerKeywords( Keywords& keys ){ } VolumeTetrapore::VolumeTetrapore(const ActionOptions& ao): -Action(ao), -ActionVolume(ao), -boxout(false), -lenunit(1.0), -dlbi(4), -dlcross(4), -dlperp(4), -dbi(3), -dcross(3), -dperp(3) + Action(ao), + ActionVolume(ao), + boxout(false), + lenunit(1.0), + dlbi(4), + dlcross(4), + dlperp(4), + dbi(3), + dcross(3), + dperp(3) { std::vector atoms; parseAtomList("ATOMS",atoms); if( atoms.size()!=4 ) error("number of atoms should be equal to four"); log.printf(" boundaries for region are calculated based on positions of atoms : "); - for(unsigned i=0;i0 ){ - Units u; u.setLength(unitname); - lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); - } else { - unitname="nm"; - } - boxfile.link(*this); - boxfile.open( boxfname.c_str() ); - log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); - } + if(boxout) { + std::string boxfname; parse("FILE",boxfname); + if(boxfname.length()==0) error("no name for box file specified"); + std::string unitname; parse("UNITS",unitname); + if ( unitname.length()>0 ) { + Units u; u.setLength(unitname); + lenunit=plumed.getAtoms().getUnits().getLength()/u.getLength(); + } else { + unitname="nm"; + } + boxfile.link(*this); + boxfile.open( boxfname.c_str() ); + log.printf(" printing box coordinates on file named %s in %s \n",boxfname.c_str(), unitname.c_str() ); + } checkRead(); requestAtoms(atoms); // We have to readd the dependency because requestAtoms removes it - addDependency( getPntrToMultiColvar() ); + addDependency( getPntrToMultiColvar() ); } -VolumeTetrapore::~VolumeTetrapore(){ +VolumeTetrapore::~VolumeTetrapore() { } -void VolumeTetrapore::setupRegions(){ +void VolumeTetrapore::setupRegions() { // Make some space for things Vector d1, d2, d3; - + // Retrieve the sigma value sigma=getSigma(); // Set the position of the origin @@ -201,7 +201,7 @@ void VolumeTetrapore::setupRegions(){ d1 = pbcDistance(origin,getPosition(1)); d2 = pbcDistance(origin,getPosition(2)); - // Find the vector connecting the origin to the top corner of + // Find the vector connecting the origin to the top corner of // the subregion d3 = pbcDistance(origin,getPosition(3)); @@ -209,19 +209,19 @@ void VolumeTetrapore::setupRegions(){ Vector bisector = d1 + d2; double bmod=bisector.modulo(); bisector=bisector/bmod; // bi = d1 / d1l; len_bi=dotProduct( d3, bi ); - cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); + cross = crossProduct( d1, d2 ); double crossmod=cross.modulo(); cross = cross / crossmod; len_cross=dotProduct( d3, cross ); - Vector truep = crossProduct( cross, bisector ); + Vector truep = crossProduct( cross, bisector ); // These are our true vectors 45 degrees from bisector bi = cos(pi/4.0)*bisector + sin(pi/4.0)*truep; - perp = cos(pi/4.0)*bisector - sin(pi/4.0)*truep; + perp = cos(pi/4.0)*bisector - sin(pi/4.0)*truep; // And the lengths of the various parts average distance to opposite corners of tetetrahedron len_bi = dotProduct( d1, bi ); double len_bi2 = dotProduct( d2, bi ); unsigned lbi=1; - if( len_bi2>len_bi ){ len_bi=len_bi2; lbi=2; } + if( len_bi2>len_bi ) { len_bi=len_bi2; lbi=2; } len_perp = dotProduct( d1, perp ); double len_perp2 = dotProduct( d2, perp ); unsigned lpi=1; - if( len_perp2>len_perp ){ len_perp=len_perp2; lpi=2; } + if( len_perp2>len_perp ) { len_perp=len_perp2; lpi=2; } plumed_assert( lbi!=lpi ); Tensor tcderiv; double cmod3=crossmod*crossmod*crossmod; Vector ucross=crossmod*cross; @@ -230,7 +230,7 @@ void VolumeTetrapore::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,-1.0) ) + crossProduct( Vector(0.0,0.0,-1.0), d2 ) ); dcross[0](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[0](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[0](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[0](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[0](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[0](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -243,7 +243,7 @@ void VolumeTetrapore::setupRegions(){ tcderiv.setCol( 2, crossProduct( Vector(0.0,0.0,1.0), d2 ) ); dcross[1](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[1](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[1](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[1](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[1](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[1](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -256,7 +256,7 @@ void VolumeTetrapore::setupRegions(){ tcderiv.setCol( 2, crossProduct( d1, Vector(0.0,0.0,1.0) ) ); dcross[2](0,0)=( tcderiv(0,0)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dx/dx dcross[2](0,1)=( tcderiv(0,1)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dx/dy - dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz + dcross[2](0,2)=( tcderiv(0,2)/crossmod - ucross[0]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dx/dz dcross[2](1,0)=( tcderiv(1,0)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,0) + ucross[1]*tcderiv(1,0) + ucross[2]*tcderiv(2,0))/cmod3 ); // dy/dx dcross[2](1,1)=( tcderiv(1,1)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,1) + ucross[1]*tcderiv(1,1) + ucross[2]*tcderiv(2,1))/cmod3 ); // dy/dy dcross[2](1,2)=( tcderiv(1,2)/crossmod - ucross[1]*(ucross[0]*tcderiv(0,2) + ucross[1]*tcderiv(1,2) + ucross[2]*tcderiv(2,2))/cmod3 ); // dy/dz @@ -310,38 +310,38 @@ void VolumeTetrapore::setupRegions(){ dtruep[2].setCol( 2, ( crossProduct( dcross[2].getCol(2), bisector ) + crossProduct( cross, dbisector[2].getCol(2) ) ) ); // Now convert these to the derivatives of the true axis - for(unsigned i=0;i<3;++i){ - dbi[i] = cos(pi/4.0)*dbisector[i] + sin(pi/4.0)*dtruep[i]; - dperp[i] = cos(pi/4.0)*dbisector[i] - sin(pi/4.0)*dtruep[i]; + for(unsigned i=0; i<3; ++i) { + dbi[i] = cos(pi/4.0)*dbisector[i] + sin(pi/4.0)*dtruep[i]; + dperp[i] = cos(pi/4.0)*dbisector[i] - sin(pi/4.0)*dtruep[i]; } // Ensure that all lengths are positive - if( len_bi<0 ){ - bi=-bi; len_bi=-len_bi; - for(unsigned i=0;i<3;++i) dbi[i]*=-1.0; + if( len_bi<0 ) { + bi=-bi; len_bi=-len_bi; + for(unsigned i=0; i<3; ++i) dbi[i]*=-1.0; + } + if( len_cross<0 ) { + cross=-cross; len_cross=-len_cross; + for(unsigned i=0; i<3; ++i) dcross[i]*=-1.0; } - if( len_cross<0 ){ - cross=-cross; len_cross=-len_cross; - for(unsigned i=0;i<3;++i) dcross[i]*=-1.0; + if( len_perp<0 ) { + perp=-perp; len_perp=-len_perp; + for(unsigned i=0; i<3; ++i) dperp[i]*=-1.0; } - if( len_perp<0 ){ - perp=-perp; len_perp=-len_perp; - for(unsigned i=0;i<3;++i) dperp[i]*=-1.0; - } if( len_bi<=0 || len_cross<=0 || len_bi<=0 ) plumed_merror("Invalid box coordinates"); // Now derivatives of lengths Tensor dd3( Tensor::identity() ); Vector ddb2=d1; if( lbi==2 ) ddb2=d2; dlbi[1].zero(); dlbi[2].zero(); dlbi[3].zero(); - dlbi[0] = matmul(ddb2,dbi[0]) - matmul(bi,dd3); + dlbi[0] = matmul(ddb2,dbi[0]) - matmul(bi,dd3); dlbi[lbi] = matmul(ddb2,dbi[lbi]) + matmul(bi,dd3); // Derivative wrt d1 - dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); + dlcross[0] = matmul(d3,dcross[0]) - matmul(cross,dd3); dlcross[1] = matmul(d3,dcross[1]); dlcross[2] = matmul(d3,dcross[2]); dlcross[3] = matmul(cross,dd3); - ddb2=d1; if( lpi==2 ) ddb2=d2; + ddb2=d1; if( lpi==2 ) ddb2=d2; dlperp[1].zero(); dlperp[2].zero(); dlperp[3].zero(); dlperp[0] = matmul(ddb2,dperp[0]) - matmul( perp, dd3 ); dlperp[lpi] = matmul(ddb2,dperp[lpi]) + matmul(perp, dd3); @@ -354,39 +354,39 @@ void VolumeTetrapore::setupRegions(){ jacob_det = fabs( jacob.determinant() ); } -void VolumeTetrapore::update(){ - if(boxout){ - boxfile.printf("%d\n",8); - const Tensor & t(getPbc().getBox()); - if(getPbc().isOrthorombic()){ - boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); - }else{ - boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", - lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), - lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), - lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) - ); - } - boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); - Vector ut, vt, wt; - ut = origin + len_bi*bi; - vt = origin + len_cross*cross; - wt = origin + len_perp*perp; - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]) , lenunit*(ut[1]), lenunit*(ut[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]) , lenunit*(vt[1]), lenunit*(vt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]) , lenunit*(wt[1]), lenunit*(wt[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_bi*bi[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), - lenunit*(ut[1]+len_perp*perp[1]), - lenunit*(ut[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), - lenunit*(vt[1]+len_perp*perp[1]), - lenunit*(vt[2]+len_perp*perp[2]) ); - boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), - lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), - lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); +void VolumeTetrapore::update() { + if(boxout) { + boxfile.printf("%d\n",8); + const Tensor & t(getPbc().getBox()); + if(getPbc().isOrthorombic()) { + boxfile.printf(" %f %f %f\n",lenunit*t(0,0),lenunit*t(1,1),lenunit*t(2,2)); + } else { + boxfile.printf(" %f %f %f %f %f %f %f %f %f\n", + lenunit*t(0,0),lenunit*t(0,1),lenunit*t(0,2), + lenunit*t(1,0),lenunit*t(1,1),lenunit*t(1,2), + lenunit*t(2,0),lenunit*t(2,1),lenunit*t(2,2) + ); + } + boxfile.printf("AR %f %f %f \n",lenunit*origin[0],lenunit*origin[1],lenunit*origin[2]); + Vector ut, vt, wt; + ut = origin + len_bi*bi; + vt = origin + len_cross*cross; + wt = origin + len_perp*perp; + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]), lenunit*(ut[1]), lenunit*(ut[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]), lenunit*(vt[1]), lenunit*(vt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(wt[0]), lenunit*(wt[1]), lenunit*(wt[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_bi*bi[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(ut[0]+len_perp*perp[0]), + lenunit*(ut[1]+len_perp*perp[1]), + lenunit*(ut[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]), + lenunit*(vt[1]+len_perp*perp[1]), + lenunit*(vt[2]+len_perp*perp[2]) ); + boxfile.printf("AR %f %f %f \n",lenunit*(vt[0]+len_perp*perp[0]+len_bi*bi[0]), + lenunit*(vt[1]+len_perp*perp[1]+len_bi*bi[1]), + lenunit*(vt[2]+len_perp*perp[2]+len_bi*bi[2]) ); } } @@ -402,8 +402,8 @@ double VolumeTetrapore::calculateNumberInside( const Vector& cpos, Vector& deriv bead.set( 0, len_bi, sigma ); double upos=dotProduct( datom, bi ); ucontr=bead.calculate( upos, uder ); - double udlen=bead.uboundDerivative( upos ); - double uder2 = bead.lboundDerivative( upos ) - udlen; + double udlen=bead.uboundDerivative( upos ); + double uder2 = bead.lboundDerivative( upos ) - udlen; // Calculate contribution from integral along cross bead.set( 0, len_cross, sigma ); @@ -423,22 +423,22 @@ double VolumeTetrapore::calculateNumberInside( const Vector& cpos, Vector& deriv derivatives[0] = (dfd[0]*bi[0]+dfd[1]*cross[0]+dfd[2]*perp[0]); derivatives[1] = (dfd[0]*bi[1]+dfd[1]*cross[1]+dfd[2]*perp[1]); derivatives[2] = (dfd[0]*bi[2]+dfd[1]*cross[2]+dfd[2]*perp[2]); - double tot = ucontr*vcontr*wcontr*jacob_det; + double tot = ucontr*vcontr*wcontr*jacob_det; // Add reference atom derivatives dfd[0]=uder2*vcontr*wcontr; dfd[1]=ucontr*vder2*wcontr; dfd[2]=ucontr*vcontr*wder2; Vector dfld; dfld[0]=udlen*vcontr*wcontr; dfld[1]=ucontr*vdlen*wcontr; dfld[2]=ucontr*vcontr*wdlen; rderiv[0] = dfd[0]*matmul(datom,dbi[0]) + dfd[1]*matmul(datom,dcross[0]) + dfd[2]*matmul(datom,dperp[0]) + - dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; - rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + + dfld[0]*dlbi[0] + dfld[1]*dlcross[0] + dfld[2]*dlperp[0] - derivatives; + rderiv[1] = dfd[0]*matmul(datom,dbi[1]) + dfd[1]*matmul(datom,dcross[1]) + dfd[2]*matmul(datom,dperp[1]) + dfld[0]*dlbi[1] + dfld[1]*dlcross[1] + dfld[2]*dlperp[1]; - rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + + rderiv[2] = dfd[0]*matmul(datom,dbi[2]) + dfd[1]*matmul(datom,dcross[2]) + dfd[2]*matmul(datom,dperp[2]) + dfld[0]*dlbi[2] + dfld[1]*dlcross[2] + dfld[2]*dlperp[2]; rderiv[3] = dfld[0]*dlbi[3] + dfld[1]*dlcross[3] + dfld[2]*dlperp[3]; vir.zero(); vir-=Tensor( cpos,derivatives ); - for(unsigned i=0;i<4;++i){ - vir -= Tensor( getPosition(i), rderiv[i] ); + for(unsigned i=0; i<4; ++i) { + vir -= Tensor( getPosition(i), rderiv[i] ); } return tot; diff --git a/src/multicolvar/XAngle.cpp b/src/multicolvar/XAngle.cpp index 2e8791003b..fbc2ab1d71 100644 --- a/src/multicolvar/XAngle.cpp +++ b/src/multicolvar/XAngle.cpp @@ -30,17 +30,17 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XANGLES /* -Calculate the angles between the vector connecting two atoms and the x axis. +Calculate the angles between the vector connecting two atoms and the x axis. \par Examples The following input tells plumed to calculate the angles between the x-axis and the vector connecting atom 3 to atom 5 and between the x-axis -and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \verbatim XANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -51,12 +51,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YANGLES /* -Calculate the angles between the vector connecting two atoms and the y axis. +Calculate the angles between the vector connecting two atoms and the y axis. \par Examples The following input tells plumed to calculate the angles between the y-axis and the vector connecting atom 3 to atom 5 and between the y-axis -and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \verbatim YANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -67,12 +67,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR ZANGLES /* -Calculate the angles between the vector connecting two atoms and the z axis. +Calculate the angles between the vector connecting two atoms and the z axis. \par Examples The following input tells plumed to calculate the angles between the z-axis and the vector connecting atom 3 to atom 5 and between the z-axis -and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \verbatim ZANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -86,7 +86,7 @@ PRINT ARG=d1.min class XAngles : public MultiColvarBase { private: bool use_sf; - unsigned myc; + unsigned myc; SwitchingFunction sf1; public: static void registerKeywords( Keywords& keys ); @@ -95,38 +95,38 @@ class XAngles : public MultiColvarBase { virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; double calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(XAngles,"XANGLES") PLUMED_REGISTER_ACTION(XAngles,"YANGLES") PLUMED_REGISTER_ACTION(XAngles,"ZANGLES") -void XAngles::registerKeywords( Keywords& keys ){ +void XAngles::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MAX"); keys.use("ALT_MIN"); keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the angles you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one angle will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one angle will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); keys.add("optional","SWITCH","A switching function that ensures that only angles are only computed when atoms are within " - "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); + "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); } XAngles::XAngles(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao), -use_sf(false) + Action(ao), + MultiColvarBase(ao), + use_sf(false) { if( getName().find("X")!=std::string::npos) myc=0; else if( getName().find("Y")!=std::string::npos) myc=1; @@ -135,12 +135,12 @@ use_sf(false) // Read in switching function std::string sfinput, errors; parse("SWITCH",sfinput); - if( sfinput.length()>0 ){ - use_sf=true; weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); - setLinkCellCutoff( sf1.get_dmax() ); + if( sfinput.length()>0 ) { + use_sf=true; weightHasDerivatives=true; + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); + setLinkCellCutoff( sf1.get_dmax() ); } // Read in the atoms @@ -156,7 +156,7 @@ double XAngles::calculateWeight( const unsigned& taskCode, const double& weight, if(!use_sf) return 1.0; Vector distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); + double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); addAtomDerivatives( 0, 0, (-dw)*distance, myatoms ); addAtomDerivatives( 0, 1, (+dw)*distance, myatoms ); myatoms.addBoxDerivatives( 0, (-dw)*Tensor(distance,distance) ); @@ -164,14 +164,14 @@ double XAngles::calculateWeight( const unsigned& taskCode, const double& weight, } double XAngles::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector ddij, ddik, axis, distance; axis.zero(); axis[myc]=1; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - PLMD::Angle a; double angle=a.compute( distance, axis, ddij, ddik ); - - addAtomDerivatives( 1, 0, -ddij, myatoms ); - addAtomDerivatives( 1, 1, ddij, myatoms ); - myatoms.addBoxDerivatives( 1, -Tensor( distance,ddij ) ); - return angle; + Vector ddij, ddik, axis, distance; axis.zero(); axis[myc]=1; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + PLMD::Angle a; double angle=a.compute( distance, axis, ddij, ddik ); + + addAtomDerivatives( 1, 0, -ddij, myatoms ); + addAtomDerivatives( 1, 1, ddij, myatoms ); + myatoms.addBoxDerivatives( 1, -Tensor( distance,ddij ) ); + return angle; } } diff --git a/src/multicolvar/XDistances.cpp b/src/multicolvar/XDistances.cpp index 6bff7887e0..009b04de59 100644 --- a/src/multicolvar/XDistances.cpp +++ b/src/multicolvar/XDistances.cpp @@ -28,20 +28,20 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XDISTANCES /* -Calculate the x components of the vectors connecting one or many pairs of atoms. +Calculate the x components of the vectors connecting one or many pairs of atoms. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and -the x-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and +the x-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +printed \verbatim XDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -49,8 +49,8 @@ PRINT ARG=d1.min (See also \ref PRINT). -The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and -the x-component of the vector connecting atom 1 to atom 2. The number of values that are +The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and +the x-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. \verbatim XDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} @@ -58,8 +58,8 @@ PRINT ARG=d1.lt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction). -The following input tells plumed to calculate the x-components of all the distinct vectors that can be created -between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). +The following input tells plumed to calculate the x-components of all the distinct vectors that can be created +between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. \verbatim XDISTANCES GROUP=1-3 AVERAGE LABEL=d1 @@ -68,11 +68,11 @@ PRINT ARG=d1.average (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. -In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values +In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. \verbatim XDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) */ @@ -80,15 +80,15 @@ PRINT ARG=d1.gt0.1 //+PLUMEDOC MCOLVAR YDISTANCES /* -Calculate the y components of the vectors connecting one or many pairs of atoms. +Calculate the y components of the vectors connecting one or many pairs of atoms. You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and -the y-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and +the y-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +printed \verbatim YDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -96,8 +96,8 @@ PRINT ARG=d1.min (See also \ref PRINT). -The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and -the y-component of the vector connecting atom 1 to atom 2. The number of values that are +The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and +the y-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. \verbatim YDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} @@ -105,8 +105,8 @@ PRINT ARG=d1.lt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction). -The following input tells plumed to calculate the y-components of all the distinct vectors that can be created -between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). +The following input tells plumed to calculate the y-components of all the distinct vectors that can be created +between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. \verbatim YDISTANCES GROUP=1-3 AVERAGE LABEL=d1 @@ -115,11 +115,11 @@ PRINT ARG=d1.average (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. -In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values +In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. \verbatim YDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) @@ -128,15 +128,15 @@ PRINT ARG=d1.gt0.1 //+PLUMEDOC MCOLVAR ZDISTANCES /* -Calculate the z components of the vectors connecting one or many pairs of atoms. +Calculate the z components of the vectors connecting one or many pairs of atoms. You can then calculate functions of the distribution of values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and -the z-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and +the z-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then +printed \verbatim ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -144,8 +144,8 @@ PRINT ARG=d1.min (See also \ref PRINT). -The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and -the z-component of the vector connecting atom 1 to atom 2. The number of values that are +The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and +the z-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. \verbatim ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} @@ -153,8 +153,8 @@ PRINT ARG=d1.lt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction). -The following input tells plumed to calculate the z-components of all the distinct vectors that can be created -between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). +The following input tells plumed to calculate the z-components of all the distinct vectors that can be created +between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. \verbatim ZDISTANCES GROUP=1-3 AVERAGE LABEL=d1 @@ -163,11 +163,11 @@ PRINT ARG=d1.average (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. -In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values +In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. \verbatim ZDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} -PRINT ARG=d1.gt0.1 +PRINT ARG=d1.gt0.1 \endverbatim (See also \ref PRINT \ref switchingfunction) @@ -184,35 +184,35 @@ class XDistances : public MultiColvarBase { // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(XDistances,"XDISTANCES") PLUMED_REGISTER_ACTION(XDistances,"YDISTANCES") PLUMED_REGISTER_ACTION(XDistances,"ZDISTANCES") -void XDistances::registerKeywords( Keywords& keys ){ +void XDistances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MAX"); keys.use("ALT_MIN"); keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the distances you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the indices of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the indices of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); } XDistances::XDistances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { if( getName().find("X")!=std::string::npos) myc=0; else if( getName().find("Y")!=std::string::npos) myc=1; @@ -229,16 +229,16 @@ MultiColvarBase(ao) } double XDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector distance; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - const double value=distance[myc]; - - Vector myvec; myvec.zero(); - // And finish the calculation - myvec[myc]=+1; addAtomDerivatives( 1, 1, myvec, myatoms ); - myvec[myc]=-1; addAtomDerivatives( 1, 0, myvec, myatoms ); - myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); - return value; + Vector distance; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + const double value=distance[myc]; + + Vector myvec; myvec.zero(); + // And finish the calculation + myvec[myc]=+1; addAtomDerivatives( 1, 1, myvec, myatoms ); + myvec[myc]=-1; addAtomDerivatives( 1, 0, myvec, myatoms ); + myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); + return value; } } diff --git a/src/multicolvar/XYDistances.cpp b/src/multicolvar/XYDistances.cpp index a6a2e978a9..767c64a86a 100644 --- a/src/multicolvar/XYDistances.cpp +++ b/src/multicolvar/XYDistances.cpp @@ -28,21 +28,21 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XYDISTANCES /* -Calculate distance between a pair of atoms neglecting the z-component. +Calculate distance between a pair of atoms neglecting the z-component. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 -to atom 5 projected in the xy-plane and the projection of the length of the vector -the vector connecting atom 1 to atom 2 in the xy-plane. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 +to atom 5 projected in the xy-plane and the projection of the length of the vector +the vector connecting atom 1 to atom 2 in the xy-plane. The minimum of these two quantities is then +printed \verbatim XYDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -54,16 +54,16 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR XZDISTANCES /* -Calculate distance between a pair of atoms neglecting the y-component. +Calculate distance between a pair of atoms neglecting the y-component. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 -to atom 5 projected in the xz-plane and the projection of the length of the vector -the vector connecting atom 1 to atom 2 in the xz-plane. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 +to atom 5 projected in the xz-plane and the projection of the length of the vector +the vector connecting atom 1 to atom 2 in the xz-plane. The minimum of these two quantities is then +printed \verbatim XZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -75,16 +75,16 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YZDISTANCES /* -Calculate distance between a pair of atoms neglecting the x-component. +Calculate distance between a pair of atoms neglecting the x-component. You can then calculate functions of the distribution of -values such as the minimum, the number less than a certain quantity and so on. +values such as the minimum, the number less than a certain quantity and so on. \par Examples -The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 -to atom 5 in the yz-plane and the projection of the length of the vector -the vector connecting atom 1 to atom 2 in the yz-plane. The minimum of these two quantities is then -printed +The following input tells plumed to calculate the projection of the length of the vector connecting atom 3 +to atom 5 in the yz-plane and the projection of the length of the vector +the vector connecting atom 1 to atom 2 in the yz-plane. The minimum of these two quantities is then +printed \verbatim YZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -104,41 +104,41 @@ class XYDistances : public MultiColvarBase { // active methods: virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return false; } + bool isPeriodic() { return false; } }; PLUMED_REGISTER_ACTION(XYDistances,"XYDISTANCES") PLUMED_REGISTER_ACTION(XYDistances,"XZDISTANCES") PLUMED_REGISTER_ACTION(XYDistances,"YZDISTANCES") -void XYDistances::registerKeywords( Keywords& keys ){ +void XYDistances::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); - keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MEAN"); keys.use("MIN"); keys.use("LESS_THAN"); keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("MORE_THAN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the distances you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the incides of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one distance will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the incides of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); } XYDistances::XYDistances(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao) + Action(ao), + MultiColvarBase(ao) { - if( getName().find("XY")!=std::string::npos){ - myc1=0; myc2=1; - } else if( getName().find("XZ")!=std::string::npos){ - myc1=0; myc2=2; - } else if( getName().find("YZ")!=std::string::npos){ - myc1=1; myc2=2; + if( getName().find("XY")!=std::string::npos) { + myc1=0; myc2=1; + } else if( getName().find("XZ")!=std::string::npos) { + myc1=0; myc2=2; + } else if( getName().find("YZ")!=std::string::npos) { + myc1=1; myc2=2; } else plumed_error(); // Read in the atoms @@ -151,17 +151,17 @@ MultiColvarBase(ao) } double XYDistances::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector distance; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - const double value=sqrt(distance[myc1]*distance[myc1] + distance[myc2]*distance[myc2] ); - const double invvalue=1.0/value; - - Vector myvec; myvec.zero(); - // And finish the calculation - myvec[myc1]=+invvalue*distance[myc1]; myvec[myc2]=+invvalue*distance[myc2]; addAtomDerivatives( 1, 1, myvec, myatoms ); - myvec[myc1]=-invvalue*distance[myc1]; myvec[myc2]=-invvalue*distance[myc2]; addAtomDerivatives( 1, 0, myvec, myatoms ); - myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); - return value; + Vector distance; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + const double value=sqrt(distance[myc1]*distance[myc1] + distance[myc2]*distance[myc2] ); + const double invvalue=1.0/value; + + Vector myvec; myvec.zero(); + // And finish the calculation + myvec[myc1]=+invvalue*distance[myc1]; myvec[myc2]=+invvalue*distance[myc2]; addAtomDerivatives( 1, 1, myvec, myatoms ); + myvec[myc1]=-invvalue*distance[myc1]; myvec[myc2]=-invvalue*distance[myc2]; addAtomDerivatives( 1, 0, myvec, myatoms ); + myatoms.addBoxDerivatives( 1, Tensor(distance,myvec) ); + return value; } } diff --git a/src/multicolvar/XYTorsion.cpp b/src/multicolvar/XYTorsion.cpp index a263a2abdd..fd512799a4 100644 --- a/src/multicolvar/XYTorsion.cpp +++ b/src/multicolvar/XYTorsion.cpp @@ -30,17 +30,17 @@ using namespace std; -namespace PLMD{ -namespace multicolvar{ +namespace PLMD { +namespace multicolvar { //+PLUMEDOC MCOLVAR XYTORSIONS /* -Calculate the torsional angle around the x axis from the positive y direction. +Calculate the torsional angle around the x axis from the positive y direction. \par Examples -The following input tells plumed to calculate the angle around the x direction between the positive y-axis and the vector connecting atom 3 to atom 5 and -the angle around the x direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the x direction between the positive y-axis and the vector connecting atom 3 to atom 5 and +the angle around the x direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim XYTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -51,12 +51,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR XZTORSIONS /* -Calculate the torsional angle around the x axis from the positive z direction. +Calculate the torsional angle around the x axis from the positive z direction. \par Examples -The following input tells plumed to calculate the angle around the x direction between the positive z-axis and the vector connecting atom 3 to atom 5 and -the angle around the x direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the x direction between the positive z-axis and the vector connecting atom 3 to atom 5 and +the angle around the x direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim XZTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -67,12 +67,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YXTORSIONS /* -Calculate the torsional angle around the y axis from the positive x direction. +Calculate the torsional angle around the y axis from the positive x direction. \par Examples -The following input tells plumed to calculate the angle around the y direction between the positive x-direction and the vector connecting atom 3 to atom 5 and -the angle around the y direction between the positive x axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the y direction between the positive x-direction and the vector connecting atom 3 to atom 5 and +the angle around the y direction between the positive x axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim YXTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -83,12 +83,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR YZTORSIONS /* -Calculate the torsional angle around the y axis from the positive z direction. +Calculate the torsional angle around the y axis from the positive z direction. \par Examples -The following input tells plumed to calculate the angle around the y direction between the positive z-direction and the vector connecting atom 3 to atom 5 and -the angle around the y direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the y direction between the positive z-direction and the vector connecting atom 3 to atom 5 and +the angle around the y direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim YZTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -99,12 +99,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR ZXTORSIONS /* -Calculate the torsional angle around the z axis from the positive x direction. +Calculate the torsional angle around the z axis from the positive x direction. \par Examples -The following input tells plumed to calculate the angle around the z direction between the positive x-direction and the vector connecting atom 3 to atom 5 and -the angle around the z direction between the positive x-direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the z direction between the positive x-direction and the vector connecting atom 3 to atom 5 and +the angle around the z direction between the positive x-direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim ZXTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -115,12 +115,12 @@ PRINT ARG=d1.min //+PLUMEDOC MCOLVAR ZYTORSIONS /* -Calculate the torsional angle around the z axis from the positive y direction. +Calculate the torsional angle around the z axis from the positive y direction. \par Examples -The following input tells plumed to calculate the angle around the z direction between the positive y-axis and the vector connecting atom 3 to atom 5 and -the angle around the z direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output +The following input tells plumed to calculate the angle around the z direction between the positive y-axis and the vector connecting atom 3 to atom 5 and +the angle around the z direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output \verbatim ZYTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min @@ -135,7 +135,7 @@ PRINT ARG=d1.min class XYTorsion : public MultiColvarBase { private: bool use_sf; - unsigned myc1, myc2; + unsigned myc1, myc2; SwitchingFunction sf1; public: static void registerKeywords( Keywords& keys ); @@ -144,8 +144,8 @@ class XYTorsion : public MultiColvarBase { virtual double compute( const unsigned& tindex, AtomValuePack& myatoms ) const ; double calculateWeight( const unsigned& taskCode, const double& weight, AtomValuePack& ) const ; /// Returns the number of coordinates of the field - bool isPeriodic(){ return true; } - void retrieveDomain( std::string& min, std::string& max){ min="-pi"; max="pi"; } + bool isPeriodic() { return true; } + void retrieveDomain( std::string& min, std::string& max) { min="-pi"; max="pi"; } }; PLUMED_REGISTER_ACTION(XYTorsion,"XYTORSIONS") @@ -155,48 +155,48 @@ PLUMED_REGISTER_ACTION(XYTorsion,"YZTORSIONS") PLUMED_REGISTER_ACTION(XYTorsion,"ZXTORSIONS") PLUMED_REGISTER_ACTION(XYTorsion,"ZYTORSIONS") -void XYTorsion::registerKeywords( Keywords& keys ){ +void XYTorsion::registerKeywords( Keywords& keys ) { MultiColvarBase::registerKeywords( keys ); - keys.use("MAX"); keys.use("ALT_MIN"); - keys.use("MEAN"); keys.use("MIN"); - keys.use("LOWEST"); keys.use("HIGHEST"); + keys.use("MAX"); keys.use("ALT_MIN"); + keys.use("MEAN"); keys.use("MIN"); + keys.use("LOWEST"); keys.use("HIGHEST"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); keys.add("numbered","ATOMS","the atoms involved in each of the torsions you wish to calculate. " - "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one torsion will be " - "calculated for each ATOM keyword you specify (all ATOM keywords should " - "specify the incides of two atoms). The eventual number of quantities calculated by this " - "action will depend on what functions of the distribution you choose to calculate."); + "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one torsion will be " + "calculated for each ATOM keyword you specify (all ATOM keywords should " + "specify the incides of two atoms). The eventual number of quantities calculated by this " + "action will depend on what functions of the distribution you choose to calculate."); keys.reset_style("ATOMS","atoms"); keys.add("atoms-1","GROUP","Calculate the distance between each distinct pair of atoms in the group"); keys.add("atoms-2","GROUPA","Calculate the distances between all the atoms in GROUPA and all " - "the atoms in GROUPB. This must be used in conjuction with GROUPB."); + "the atoms in GROUPB. This must be used in conjuction with GROUPB."); keys.add("atoms-2","GROUPB","Calculate the distances between all the atoms in GROUPA and all the atoms " - "in GROUPB. This must be used in conjuction with GROUPA."); + "in GROUPB. This must be used in conjuction with GROUPA."); keys.add("optional","SWITCH","A switching function that ensures that only angles are only computed when atoms are within " - "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); + "are within a certain fixed cutoff. The following provides information on the \\ref switchingfunction that are available."); } XYTorsion::XYTorsion(const ActionOptions&ao): -Action(ao), -MultiColvarBase(ao), -use_sf(false) + Action(ao), + MultiColvarBase(ao), + use_sf(false) { - if( getName().find("XY")!=std::string::npos){ myc1=0; myc2=1; } - else if( getName().find("XZ")!=std::string::npos){ myc1=0; myc2=2; } - else if( getName().find("YX")!=std::string::npos){ myc1=1; myc2=0; } - else if( getName().find("YZ")!=std::string::npos){ myc1=1; myc2=2; } - else if( getName().find("ZX")!=std::string::npos){ myc1=2; myc2=0; } - else if( getName().find("ZY")!=std::string::npos){ myc1=2; myc2=1; } + if( getName().find("XY")!=std::string::npos) { myc1=0; myc2=1; } + else if( getName().find("XZ")!=std::string::npos) { myc1=0; myc2=2; } + else if( getName().find("YX")!=std::string::npos) { myc1=1; myc2=0; } + else if( getName().find("YZ")!=std::string::npos) { myc1=1; myc2=2; } + else if( getName().find("ZX")!=std::string::npos) { myc1=2; myc2=0; } + else if( getName().find("ZY")!=std::string::npos) { myc1=2; myc2=1; } else plumed_error(); // Read in switching function std::string sfinput, errors; parse("SWITCH",sfinput); - if( sfinput.length()>0 ){ - use_sf=true; weightHasDerivatives=true; - sf1.set(sfinput,errors); - if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); - log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); - setLinkCellCutoff( sf1.get_dmax() ); + if( sfinput.length()>0 ) { + use_sf=true; weightHasDerivatives=true; + sf1.set(sfinput,errors); + if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors ); + log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() ); + setLinkCellCutoff( sf1.get_dmax() ); } // Read in the atoms @@ -212,7 +212,7 @@ double XYTorsion::calculateWeight( const unsigned& taskCode, const double& weigh if(!use_sf) return 1.0; Vector distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); + double dw, w = sf1.calculateSqr( distance.modulo2(), dw ); addAtomDerivatives( 0, 0, (-dw)*distance, myatoms ); addAtomDerivatives( 0, 1, (+dw)*distance, myatoms ); myatoms.addBoxDerivatives( 0, (-dw)*Tensor(distance,distance) ); @@ -220,15 +220,15 @@ double XYTorsion::calculateWeight( const unsigned& taskCode, const double& weigh } double XYTorsion::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { - Vector dd0, dd1, dd2, axis, rot, distance; - axis.zero(); rot.zero(); rot[myc1]=1; axis[myc2]=1; - distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); - PLMD::Torsion t; double torsion=t.compute( distance, rot, axis, dd0, dd1, dd2 ); - - addAtomDerivatives( 1, 0, -dd0, myatoms ); - addAtomDerivatives( 1, 1, dd0, myatoms ); - myatoms.addBoxDerivatives( 1, -extProduct(distance,dd0) ); - return torsion; + Vector dd0, dd1, dd2, axis, rot, distance; + axis.zero(); rot.zero(); rot[myc1]=1; axis[myc2]=1; + distance=getSeparation( myatoms.getPosition(0), myatoms.getPosition(1) ); + PLMD::Torsion t; double torsion=t.compute( distance, rot, axis, dd0, dd1, dd2 ); + + addAtomDerivatives( 1, 0, -dd0, myatoms ); + addAtomDerivatives( 1, 1, dd0, myatoms ); + myatoms.addBoxDerivatives( 1, -extProduct(distance,dd0) ); + return torsion; } } diff --git a/src/reference/ArgumentOnlyDistance.cpp b/src/reference/ArgumentOnlyDistance.cpp index 4664044af6..0e4a3e2aee 100644 --- a/src/reference/ArgumentOnlyDistance.cpp +++ b/src/reference/ArgumentOnlyDistance.cpp @@ -25,24 +25,24 @@ namespace PLMD { ArgumentOnlyDistance::ArgumentOnlyDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ReferenceArguments(ro) + ReferenceConfiguration(ro), + ReferenceArguments(ro) { } -void ArgumentOnlyDistance::read( const PDB& pdb ){ +void ArgumentOnlyDistance::read( const PDB& pdb ) { readArgumentsFromPDB( pdb ); } double ArgumentOnlyDistance::calculate( const std::vector& vals, ReferenceValuePack& myder, const bool& squared ) const { std::vector tmparg( vals.size() ); - for(unsigned i=0;iget(); + for(unsigned i=0; iget(); double d=calculateArgumentDistance( vals, tmparg, myder, squared ); if( !myder.updateComplete() ) myder.updateDynamicLists(); return d; } -double ArgumentOnlyDistance::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, +double ArgumentOnlyDistance::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( pos.size()==0 ); double d=calculateArgumentDistance( vals, arg, myder, squared ); diff --git a/src/reference/ArgumentOnlyDistance.h b/src/reference/ArgumentOnlyDistance.h index 67923c17b3..3636f0764e 100644 --- a/src/reference/ArgumentOnlyDistance.h +++ b/src/reference/ArgumentOnlyDistance.h @@ -35,8 +35,8 @@ class ArgumentOnlyDistance : public ReferenceArguments { public: explicit ArgumentOnlyDistance( const ReferenceConfigurationOptions& ro ); void read( const PDB& pdb ); - bool pcaIsEnabledForThisReference(){ return true; } - void setupPCAStorage( ReferenceValuePack& mypack ){ mypack.switchOnPCAOption(); } + bool pcaIsEnabledForThisReference() { return true; } + void setupPCAStorage( ReferenceValuePack& mypack ) { mypack.switchOnPCAOption(); } double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const ; double calculate( const std::vector& vals, ReferenceValuePack& myder, const bool& squared ) const ; }; diff --git a/src/reference/DRMSD.cpp b/src/reference/DRMSD.cpp index d9ee501a69..88183ac5de 100644 --- a/src/reference/DRMSD.cpp +++ b/src/reference/DRMSD.cpp @@ -28,84 +28,84 @@ namespace PLMD { PLUMED_REGISTER_METRIC(DRMSD,"DRMSD") DRMSD::DRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -SingleDomainRMSD( ro ), -nopbc(true), -bounds_were_set(false), -lower(0), -upper(std::numeric_limits::max( )) + ReferenceConfiguration( ro ), + SingleDomainRMSD( ro ), + nopbc(true), + bounds_were_set(false), + lower(0), + upper(std::numeric_limits::max( )) { } -void DRMSD::setBoundsOnDistances( bool dopbc, double lbound, double ubound ){ - bounds_were_set=true; nopbc=!dopbc; +void DRMSD::setBoundsOnDistances( bool dopbc, double lbound, double ubound ) { + bounds_were_set=true; nopbc=!dopbc; lower=lbound; upper=ubound; } -void DRMSD::readBounds(){ - parseFlag("NOPBC",nopbc); +void DRMSD::readBounds() { + parseFlag("NOPBC",nopbc); parse("LOWER_CUTOFF",lower,true); parse("UPPER_CUTOFF",upper,true); setBoundsOnDistances( !nopbc, lower, upper ); } -void DRMSD::read( const PDB& pdb ){ +void DRMSD::read( const PDB& pdb ) { readAtomsFromPDB( pdb ); readBounds(); setup_targets(); } -void DRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ){ +void DRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { SingleDomainRMSD::setReferenceAtoms( conf, align_in, displace_in ); setup_targets(); } -void DRMSD::setup_targets(){ +void DRMSD::setup_targets() { plumed_massert( bounds_were_set, "I am missing a call to DRMSD::setBoundsOnDistances"); unsigned natoms = getNumberOfReferencePositions(); - for(unsigned i=0;i lower ){ - targets[std::make_pair(i,j)] = distance; - } - } + for(unsigned i=0; i lower ) { + targets[std::make_pair(i,j)] = distance; + } + } } - if( targets.empty() ) error("drmsd will compare no distances - check upper and lower bounds are sensible"); + if( targets.empty() ) error("drmsd will compare no distances - check upper and lower bounds are sensible"); } double DRMSD::calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert(!targets.empty()); - Vector distance; - myder.clear(); - double drmsd=0.; - for(const auto & it : targets){ - - const unsigned i=getAtomIndex( it.first.first ); - const unsigned j=getAtomIndex( it.first.second ); - - if(nopbc) distance=delta( pos[i] , pos[j] ); - else distance=pbc.distance( pos[i] , pos[j] ); - - const double len = distance.modulo(); - const double diff = len - it.second; - const double der = diff / len; - - drmsd += diff * diff; - myder.addAtomDerivatives( i, -der * distance ); - myder.addAtomDerivatives( j, der * distance ); - myder.addBoxDerivatives( - der * Tensor(distance,distance) ); + Vector distance; + myder.clear(); + double drmsd=0.; + for(const auto & it : targets) { + + const unsigned i=getAtomIndex( it.first.first ); + const unsigned j=getAtomIndex( it.first.second ); + + if(nopbc) distance=delta( pos[i], pos[j] ); + else distance=pbc.distance( pos[i], pos[j] ); + + const double len = distance.modulo(); + const double diff = len - it.second; + const double der = diff / len; + + drmsd += diff * diff; + myder.addAtomDerivatives( i, -der * distance ); + myder.addAtomDerivatives( j, der * distance ); + myder.addBoxDerivatives( - der * Tensor(distance,distance) ); } const double inpairs = 1./static_cast(targets.size()); double idrmsd; - if(squared){ - drmsd = drmsd * inpairs; - idrmsd = 2.0 * inpairs; + if(squared) { + drmsd = drmsd * inpairs; + idrmsd = 2.0 * inpairs; } else { - drmsd = sqrt( drmsd * inpairs ); - idrmsd = inpairs / drmsd ; + drmsd = sqrt( drmsd * inpairs ); + idrmsd = inpairs / drmsd ; } myder.scaleAllDerivatives( idrmsd ); diff --git a/src/reference/DRMSD.h b/src/reference/DRMSD.h index 634d031626..e99f382f4e 100644 --- a/src/reference/DRMSD.h +++ b/src/reference/DRMSD.h @@ -35,12 +35,12 @@ class DRMSD : public SingleDomainRMSD { protected: bool bounds_were_set; double lower, upper; - std::map< std::pair , double> targets; + std::map< std::pair , double> targets; /// Read in NOPBC, LOWER_CUTOFF and UPPER_CUTOFF void readBounds(); public: explicit DRMSD( const ReferenceConfigurationOptions& ro ); -/// This sets upper and lower bounds on distances to be used in DRMSD +/// This sets upper and lower bounds on distances to be used in DRMSD void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits::max( ) ); /// Check that similar comparisons are being performed - perhaps this is needed ask Davide? GAT // void check( ReferenceConfiguration* , ReferenceConfiguration* ); diff --git a/src/reference/Direction.cpp b/src/reference/Direction.cpp index fa04b643da..5e50e9b333 100644 --- a/src/reference/Direction.cpp +++ b/src/reference/Direction.cpp @@ -27,47 +27,47 @@ namespace PLMD { PLUMED_REGISTER_METRIC(Direction,"DIRECTION") Direction::Direction( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ReferenceAtoms(ro), -ReferenceArguments(ro) + ReferenceConfiguration(ro), + ReferenceAtoms(ro), + ReferenceArguments(ro) { } -void Direction::read( const PDB& pdb ){ +void Direction::read( const PDB& pdb ) { readAtomsFromPDB( pdb ); readArgumentsFromPDB( pdb ); } -void Direction::setDirection( const std::vector& conf, const std::vector& args ){ +void Direction::setDirection( const std::vector& conf, const std::vector& args ) { std::vector sigma( args.size(), 1.0 ); setReferenceArguments( args, sigma ); reference_atoms.resize( conf.size() ); align.resize( conf.size() ); displace.resize( conf.size() ); atom_der_index.resize( conf.size() ); - for(unsigned i=0;i& pos, const Pbc& pbc, const std::vector& vals, const std::vector& args, ReferenceValuePack& myder, const bool& squared ) const { - plumed_merror("You should never be calling calc for a direction"); return 1.0; + plumed_merror("You should never be calling calc for a direction"); return 1.0; } void Direction::extractArgumentDisplacement( const std::vector& vals, const std::vector& arg, std::vector& dirout ) const { - for(unsigned i=0;i& pos, const bool& anflag, std::vector& dirout ) const { - for(unsigned i=0;i& conf, const std::vector& args ); void addDirection( const double& weight, const Direction& dir ); - void setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ){ plumed_error(); } -/// This allows us to extract the reference positions, which are the direction in this case + void setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { plumed_error(); } +/// This allows us to extract the reference positions, which are the direction in this case void extractArgumentDisplacement( const std::vector& vals, const std::vector& arg, std::vector& dirout ) const ; - void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& dirout ) const ; + void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& dirout ) const ; void zeroDirection(); }; diff --git a/src/reference/DotProductDistance.cpp b/src/reference/DotProductDistance.cpp index bfda1290c5..0b0f4eb73d 100644 --- a/src/reference/DotProductDistance.cpp +++ b/src/reference/DotProductDistance.cpp @@ -35,18 +35,18 @@ class DotProductDistance : public ArgumentOnlyDistance { PLUMED_REGISTER_METRIC(DotProductDistance,"DOTPRODUCT") DotProductDistance::DotProductDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ArgumentOnlyDistance(ro) + ReferenceConfiguration(ro), + ArgumentOnlyDistance(ro) { } -void DotProductDistance::read( const PDB& pdb ){ +void DotProductDistance::read( const PDB& pdb ) { readArgumentsFromPDB( pdb ); } -double DotProductDistance::calculateArgumentDistance( const std::vector & vals, const std::vector& arg, - ReferenceValuePack& myder, const bool& squared ) const { - double dot=0.0; +double DotProductDistance::calculateArgumentDistance( const std::vector & vals, const std::vector& arg, + ReferenceValuePack& myder, const bool& squared ) const { + double dot=0.0; for (unsigned long i=0; i& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { - plumed_merror("should not be called"); return 1.0; + void read( const PDB& ) { plumed_merror("should not be called"); } + double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { + plumed_merror("should not be called"); return 1.0; } }; diff --git a/src/reference/IntermolecularDRMSD.cpp b/src/reference/IntermolecularDRMSD.cpp index 223a43f3bf..6903c83522 100644 --- a/src/reference/IntermolecularDRMSD.cpp +++ b/src/reference/IntermolecularDRMSD.cpp @@ -31,37 +31,37 @@ class IntermolecularDRMSD : public DRMSD { public: explicit IntermolecularDRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& pdb ); - void setup_targets(); + void setup_targets(); }; PLUMED_REGISTER_METRIC(IntermolecularDRMSD,"INTER-DRMSD") IntermolecularDRMSD::IntermolecularDRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -DRMSD( ro ), -nblocks(0) + ReferenceConfiguration( ro ), + DRMSD( ro ), + nblocks(0) { } -void IntermolecularDRMSD::read( const PDB& pdb ){ +void IntermolecularDRMSD::read( const PDB& pdb ) { readAtomsFromPDB( pdb, true ); nblocks = pdb.getNumberOfAtomBlocks(); blocks.resize( nblocks+1 ); if( nblocks==1 ) error("Trying to compute intermolecular rmsd but found no TERs in input PDB"); - blocks[0]=0; for(unsigned i=0;i lower ) targets[std::make_pair(iatom,jatom)] = distance; - } - } + for(unsigned i=1; i lower ) targets[std::make_pair(iatom,jatom)] = distance; + } } + } } } diff --git a/src/reference/IntramolecularDRMSD.cpp b/src/reference/IntramolecularDRMSD.cpp index cd7b022c90..2a7b4b64ff 100644 --- a/src/reference/IntramolecularDRMSD.cpp +++ b/src/reference/IntramolecularDRMSD.cpp @@ -31,35 +31,35 @@ class IntramolecularDRMSD : public DRMSD { public: explicit IntramolecularDRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& pdb ); - void setup_targets(); + void setup_targets(); }; PLUMED_REGISTER_METRIC(IntramolecularDRMSD,"INTRA-DRMSD") IntramolecularDRMSD::IntramolecularDRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -DRMSD( ro ), -nblocks(0) + ReferenceConfiguration( ro ), + DRMSD( ro ), + nblocks(0) { } -void IntramolecularDRMSD::read( const PDB& pdb ){ +void IntramolecularDRMSD::read( const PDB& pdb ) { readAtomsFromPDB( pdb, true ); nblocks = pdb.getNumberOfAtomBlocks(); blocks.resize( nblocks+1 ); if( nblocks==1 ) error("Trying to compute intramolecular rmsd but found no TERs in input PDB"); - blocks[0]=0; for(unsigned i=0;i lower ) targets[std::make_pair(iatom,jatom)] = distance; - } + for(unsigned i=0; i lower ) targets[std::make_pair(iatom,jatom)] = distance; } + } } } diff --git a/src/reference/MahalanobisDistance.cpp b/src/reference/MahalanobisDistance.cpp index 7a50bf5e00..19a3e96697 100644 --- a/src/reference/MahalanobisDistance.cpp +++ b/src/reference/MahalanobisDistance.cpp @@ -32,8 +32,8 @@ class MahalanobisDistance : public ArgumentOnlyDistance { PLUMED_REGISTER_METRIC(MahalanobisDistance,"MAHALANOBIS") MahalanobisDistance::MahalanobisDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ArgumentOnlyDistance(ro) + ReferenceConfiguration(ro), + ArgumentOnlyDistance(ro) { hasmetric=true; } diff --git a/src/reference/MetricRegister.cpp b/src/reference/MetricRegister.cpp index 0c240fa0fb..dfff4d5e01 100644 --- a/src/reference/MetricRegister.cpp +++ b/src/reference/MetricRegister.cpp @@ -22,35 +22,35 @@ #include "MetricRegister.h" #include -namespace PLMD{ +namespace PLMD { -MetricRegister::~MetricRegister(){ - if(m.size()>0){ +MetricRegister::~MetricRegister() { + if(m.size()>0) { std::string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: ReferenceConfiguration "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -MetricRegister& metricRegister(){ +MetricRegister& metricRegister() { static MetricRegister ans; return ans; } -void MetricRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void MetricRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void MetricRegister::add( std::string type, creator_pointer f ){ +void MetricRegister::add( std::string type, creator_pointer f ) { plumed_massert(m.count(type)==0,"type has already been registered"); m.insert(std::pair(type,f)); } -bool MetricRegister::check(std::string type){ +bool MetricRegister::check(std::string type) { if( m.count(type)>0 ) return true; return false; } diff --git a/src/reference/MetricRegister.h b/src/reference/MetricRegister.h index 91b44a590f..64cb3424ef 100644 --- a/src/reference/MetricRegister.h +++ b/src/reference/MetricRegister.h @@ -31,11 +31,11 @@ #include "tools/PDB.h" #include "ReferenceConfiguration.h" -namespace PLMD{ +namespace PLMD { class PDB; -class MetricRegister{ +class MetricRegister { private: /// Pointer to a function which, given the type for a ReferenceConfiguration, creates it typedef ReferenceConfiguration*(*creator_pointer)(const ReferenceConfigurationOptions&); @@ -53,9 +53,9 @@ class MetricRegister{ /// Create a reference configuration and don't set a point of reference template T* create( const std::string& type ); -/// Create a reference configuration and set the point of reference from the pdb +/// Create a reference configuration and set the point of reference from the pdb template - T* create( const std::string& type , const PDB& pdb ); + T* create( const std::string& type, const PDB& pdb ); }; MetricRegister& metricRegister(); @@ -69,13 +69,13 @@ MetricRegister& metricRegister(); } classname##RegisterMeObject; template -T* MetricRegister::create( const std::string& type ){ +T* MetricRegister::create( const std::string& type ) { std::string ftype; - if( type.find("MULTI-")!=std::string::npos ){ - ftype="MULTI"; + if( type.find("MULTI-")!=std::string::npos ) { + ftype="MULTI"; } else { - std::size_t dash=type.find("-FAST"); // We must remove the fast label - ftype=type.substr(0,dash); + std::size_t dash=type.find("-FAST"); // We must remove the fast label + ftype=type.substr(0,dash); } plumed_massert( check(ftype), "metric " + ftype + " does not exist" ); ReferenceConfigurationOptions ro( type ); @@ -86,16 +86,16 @@ T* MetricRegister::create( const std::string& type ){ } template -T* MetricRegister::create( const std::string& type, const PDB& pdb ){ +T* MetricRegister::create( const std::string& type, const PDB& pdb ) { std::string rtype; - if( type.length()==0 ){ - std::vector remarks( pdb.getRemark() ); - bool found=Tools::parse( remarks, "TYPE", rtype ); - if(!found) plumed_merror("TYPE not specified in pdb input file"); + if( type.length()==0 ) { + std::vector remarks( pdb.getRemark() ); + bool found=Tools::parse( remarks, "TYPE", rtype ); + if(!found) plumed_merror("TYPE not specified in pdb input file"); } else { - rtype=type; - } - T* confout=create( rtype ); + rtype=type; + } + T* confout=create( rtype ); confout->set( pdb ); return confout; } diff --git a/src/reference/MultiDomainRMSD.cpp b/src/reference/MultiDomainRMSD.cpp index c6ef4ae7ec..fc0bcca62e 100644 --- a/src/reference/MultiDomainRMSD.cpp +++ b/src/reference/MultiDomainRMSD.cpp @@ -29,125 +29,125 @@ namespace PLMD { PLUMED_REGISTER_METRIC(MultiDomainRMSD,"MULTI") MultiDomainRMSD::MultiDomainRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ReferenceAtoms(ro), -ftype(ro.getMultiRMSDType()) + ReferenceConfiguration(ro), + ReferenceAtoms(ro), + ftype(ro.getMultiRMSDType()) { } -MultiDomainRMSD::~MultiDomainRMSD(){ - for(unsigned i=0;i positions; std::vector align, displace; - std::string num; blocks.resize( nblocks+1 ); blocks[0]=0; - for(unsigned i=0;i::max( ); - parse("LOWER_CUTOFF",lower,true); - parse("UPPER_CUTOFF",upper,true); - bool nopbc=false; parseFlag("NOPBC",nopbc); - - for(unsigned i=1;i<=nblocks;++i){ - Tools::convert(i,num); - if( ftype=="RMSD" ){ - parse("TYPE"+num, ftype ); - parse("LOWER_CUTOFF"+num,lower,true); - parse("UPPER_CUTOFF"+num,upper,true); - nopbc=false; parseFlag("NOPBC"+num,nopbc); - } - domains.push_back( metricRegister().create( ftype ) ); - positions.resize( blocks[i] - blocks[i-1] ); - align.resize( blocks[i] - blocks[i-1] ); - displace.resize( blocks[i] - blocks[i-1] ); - unsigned n=0; - for(unsigned j=blocks[i-1];jsetBoundsOnDistances( !nopbc, lower, upper ); - domains[i-1]->setReferenceAtoms( positions, align, displace ); - domains[i-1]->setupRMSDObject(); - - double ww=0; parse("WEIGHT"+num, ww, true ); - if( ww==0 ) weights.push_back( 1.0 ); - else weights.push_back( ww ); - } - // And set the atom numbers for this object - setAtomNumbers( pdb.getAtomNumbers() ); +void MultiDomainRMSD::read( const PDB& pdb ) { + unsigned nblocks = pdb.getNumberOfAtomBlocks(); + if( nblocks<2 ) error("multidomain RMSD only has one block of atoms"); + + std::vector positions; std::vector align, displace; + std::string num; blocks.resize( nblocks+1 ); blocks[0]=0; + for(unsigned i=0; i::max( ); + parse("LOWER_CUTOFF",lower,true); + parse("UPPER_CUTOFF",upper,true); + bool nopbc=false; parseFlag("NOPBC",nopbc); + + for(unsigned i=1; i<=nblocks; ++i) { + Tools::convert(i,num); + if( ftype=="RMSD" ) { + parse("TYPE"+num, ftype ); + parse("LOWER_CUTOFF"+num,lower,true); + parse("UPPER_CUTOFF"+num,upper,true); + nopbc=false; parseFlag("NOPBC"+num,nopbc); + } + domains.push_back( metricRegister().create( ftype ) ); + positions.resize( blocks[i] - blocks[i-1] ); + align.resize( blocks[i] - blocks[i-1] ); + displace.resize( blocks[i] - blocks[i-1] ); + unsigned n=0; + for(unsigned j=blocks[i-1]; jsetBoundsOnDistances( !nopbc, lower, upper ); + domains[i-1]->setReferenceAtoms( positions, align, displace ); + domains[i-1]->setupRMSDObject(); + + double ww=0; parse("WEIGHT"+num, ww, true ); + if( ww==0 ) weights.push_back( 1.0 ); + else weights.push_back( ww ); + } + // And set the atom numbers for this object + setAtomNumbers( pdb.getAtomNumbers() ); } -void MultiDomainRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ){ +void MultiDomainRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { plumed_error(); } double MultiDomainRMSD::calculate( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { - double totd=0.; Tensor tvirial; std::vector mypos; MultiValue tvals( 1, 3*pos.size()+9 ); + double totd=0.; Tensor tvirial; std::vector mypos; MultiValue tvals( 1, 3*pos.size()+9 ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); myder.clear(); - for(unsigned i=0;isetupPCAStorage( tder ); - unsigned n=0; for(unsigned j=blocks[i];jcalculate( mypos, pbc, tder, true ); - // Now merge the derivative - myder.copyScaledDerivatives( 0, weights[i], tvals ); - // If PCA copy PCA stuff - if( myder.calcUsingPCAOption() ){ - unsigned n=0; - if( tder.centeredpos.size()>0 ) myder.rot[i]=tder.rot[0]; - for(unsigned j=blocks[i];j0 ){ - myder.centeredpos[j]=tder.centeredpos[n]; - for(unsigned p=0;p<3;++p) for(unsigned q=0;q<3;++q) myder.DRotDPos(p,q)[j]=tder.DRotDPos(p,q)[n]; - } - n++; + for(unsigned i=0; isetupPCAStorage( tder ); + unsigned n=0; for(unsigned j=blocks[i]; jcalculate( mypos, pbc, tder, true ); + // Now merge the derivative + myder.copyScaledDerivatives( 0, weights[i], tvals ); + // If PCA copy PCA stuff + if( myder.calcUsingPCAOption() ) { + unsigned n=0; + if( tder.centeredpos.size()>0 ) myder.rot[i]=tder.rot[0]; + for(unsigned j=blocks[i]; j0 ) { + myder.centeredpos[j]=tder.centeredpos[n]; + for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) myder.DRotDPos(p,q)[j]=tder.DRotDPos(p,q)[n]; } - } - // Make sure virial status is set correctly in output derivative pack - // This is only done here so I do this by using class friendship - if( tder.virialWasSet() ) myder.boxWasSet=true; + n++; + } + } + // Make sure virial status is set correctly in output derivative pack + // This is only done here so I do this by using class friendship + if( tder.virialWasSet() ) myder.boxWasSet=true; } if( !myder.updateComplete() ) myder.updateDynamicLists(); - if( !squared ){ - totd=sqrt(totd); double xx=0.5/totd; - myder.scaleAllDerivatives( xx ); + if( !squared ) { + totd=sqrt(totd); double xx=0.5/totd; + myder.scaleAllDerivatives( xx ); } return totd; } -double MultiDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, +double MultiDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 ); return calculate( pos, pbc, myder, squared ); } -bool MultiDomainRMSD::pcaIsEnabledForThisReference(){ - bool enabled=true; - for(unsigned i=0;ipcaIsEnabledForThisReference() ) enabled=false; +bool MultiDomainRMSD::pcaIsEnabledForThisReference() { + bool enabled=true; + for(unsigned i=0; ipcaIsEnabledForThisReference() ) enabled=false; } return enabled; } -void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ){ +void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ) { plumed_dbg_assert( pcaIsEnabledForThisReference() ); mypack.switchOnPCAOption(); mypack.displacement.resize( getNumberOfAtoms() ); mypack.centeredpos.resize( getNumberOfAtoms() ); mypack.DRotDPos.resize(3,3); mypack.rot.resize( domains.size() ); - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) mypack.DRotDPos(i,j).resize( getNumberOfAtoms() ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) mypack.DRotDPos(i,j).resize( getNumberOfAtoms() ); } // Vector MultiDomainRMSD::getAtomicDisplacement( const unsigned& iatom ){ @@ -161,47 +161,47 @@ void MultiDomainRMSD::setupPCAStorage( ReferenceValuePack& mypack ){ // } void MultiDomainRMSD::extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& direction ) const { - std::vector mypos, mydir; - for(unsigned i=0;iextractAtomicDisplacement( mypos, anflag, mydir ); - // Extract the direction - n=0; for(unsigned j=blocks[i];j mypos, mydir; + for(unsigned i=0; iextractAtomicDisplacement( mypos, anflag, mydir ); + // Extract the direction + n=0; for(unsigned j=blocks[i]; j& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { - double totd=0.; std::vector tvecs; std::vector mypos; mypack.clear(); - MultiValue tvals( 1, mypack.getNumberOfDerivatives() ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); - for(unsigned i=0;isetupPCAStorage( tder ); - if( tder.centeredpos.size()>0 ){ - for(unsigned p=0;p<3;++p) for(unsigned q=0;q<3;++q) tder.DRotDPos(p,q).resize( mypos.size() ); + double totd=0.; std::vector tvecs; std::vector mypos; mypack.clear(); + MultiValue tvals( 1, mypack.getNumberOfDerivatives() ); ReferenceValuePack tder( 0, getNumberOfAtoms(), tvals ); + for(unsigned i=0; isetupPCAStorage( tder ); + if( tder.centeredpos.size()>0 ) { + for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) tder.DRotDPos(p,q).resize( mypos.size() ); + } + // Extract information from storage pack and put in local pack + if( tder.centeredpos.size()>0 ) tder.rot[0]=mypack.rot[i]; + unsigned n=0; + for(unsigned j=blocks[i]; j0 ) { + tder.centeredpos[n]=mypack.centeredpos[j]; + for(unsigned p=0; p<3; ++p) for(unsigned q=0; q<3; ++q) tder.DRotDPos(p,q)[n]=mypack.DRotDPos(p,q)[j]; } - // Extract information from storage pack and put in local pack - if( tder.centeredpos.size()>0 ) tder.rot[0]=mypack.rot[i]; - unsigned n=0; - for(unsigned j=blocks[i];j0 ){ - tder.centeredpos[n]=mypack.centeredpos[j]; - for(unsigned p=0;p<3;++p) for(unsigned q=0;q<3;++q) tder.DRotDPos(p,q)[n]=mypack.DRotDPos(p,q)[j]; - } - n++; - } - for(unsigned k=n;kprojectAtomicDisplacementOnVector( tvecs, mypos, tder ); - - // And derivatives - mypack.copyScaledDerivatives( 0, weights[i], tvals ); + n++; + } + for(unsigned k=n; kprojectAtomicDisplacementOnVector( tvecs, mypos, tder ); + + // And derivatives + mypack.copyScaledDerivatives( 0, weights[i], tvals ); } if( !mypack.updateComplete() ) mypack.updateDynamicLists(); diff --git a/src/reference/MultiDomainRMSD.h b/src/reference/MultiDomainRMSD.h index ed2e5ad306..524f42f42b 100644 --- a/src/reference/MultiDomainRMSD.h +++ b/src/reference/MultiDomainRMSD.h @@ -51,8 +51,8 @@ class MultiDomainRMSD : public ReferenceAtoms { /// bool pcaIsEnabledForThisReference(); void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& direction ) const ; - double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; - void setupPCAStorage( ReferenceValuePack& mypack ); + double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; + void setupPCAStorage( ReferenceValuePack& mypack ); }; } diff --git a/src/reference/MultiReferenceBase.cpp b/src/reference/MultiReferenceBase.cpp index bdbe148d01..3468d1c137 100644 --- a/src/reference/MultiReferenceBase.cpp +++ b/src/reference/MultiReferenceBase.cpp @@ -26,25 +26,25 @@ namespace PLMD { MultiReferenceBase::MultiReferenceBase( const std::string& type, const bool& checksoff ): -wasSet(false), -skipchecks(checksoff), -mtype(type) + wasSet(false), + skipchecks(checksoff), + mtype(type) { if(checksoff) plumed_assert( mtype.length()==0 ); } -MultiReferenceBase::~MultiReferenceBase(){ - for(unsigned i=0;i( mtype, mypdb ); // Save everything @@ -55,11 +55,11 @@ void MultiReferenceBase::readFrame( PDB& mypdb ){ mymsd->checkRead(); } -void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector& atoms, std::vector& args ){ +void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector& atoms, std::vector& args ) { plumed_assert( atoms.size()==0 && args.size()==0 ); - for(unsigned i=0;igetAtomRequests( atoms ); - frames[i]->getArgumentRequests( args ); + for(unsigned i=0; igetAtomRequests( atoms ); + frames[i]->getArgumentRequests( args ); } } @@ -70,7 +70,7 @@ void MultiReferenceBase::getAtomAndArgumentRequirements( std::vector // } // } -void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ){ +void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ) { // Create a reference configuration of the appropriate type ReferenceConfiguration* mymsd=metricRegister().create( frameToCopy->getName() ); // Copy names of arguments and and indexes @@ -80,25 +80,25 @@ void MultiReferenceBase::copyFrame( ReferenceConfiguration* frameToCopy ){ // Copy weight mymsd->setWeight( frameToCopy->getWeight() ); // Easy bit - copy the frame - frames.push_back( mymsd ); + frames.push_back( mymsd ); // This resizes the low dim array resizeRestOfFrame(); } -void MultiReferenceBase::setWeights( const std::vector& weights ){ - plumed_assert( weights.size()==frames.size() ); - for(unsigned i=0;isetWeight( weights[i] ); +void MultiReferenceBase::setWeights( const std::vector& weights ) { + plumed_assert( weights.size()==frames.size() ); + for(unsigned i=0; isetWeight( weights[i] ); } -void MultiReferenceBase::calculateAllDistances( const Pbc& pbc, const std::vector & vals, Communicator& comm, Matrix& distances, const bool& squared ){ +void MultiReferenceBase::calculateAllDistances( const Pbc& pbc, const std::vector & vals, Communicator& comm, Matrix& distances, const bool& squared ) { distances=0.0; - unsigned k=0, size=comm.Get_size(), rank=comm.Get_rank(); - for(unsigned i=1;i frames; /// Read something from the last frame template - void parse(const std::string& key, T& val ); + void parse(const std::string& key, T& val ); public: MultiReferenceBase( const std::string& type, const bool& checksoff ); /// Destructor deletes all polymorphic pointers virtual ~MultiReferenceBase(); /// Delete all the data in the reference object void clearFrames(); - virtual void clearRestOfData(){}; + virtual void clearRestOfData() {}; /// Read a frame from the input - void readFrame( PDB& pdb ); + void readFrame( PDB& pdb ); /// Find what is required of us from the reference frames void getAtomAndArgumentRequirements( std::vector& atoms, std::vector& args ); /// Finish setup of frames // void setNumberOfAtomsAndArguments( const unsigned& natoms, const unsigned& nargs ); /// Do additional reading required by derived class - virtual void readRestOfFrame(){} + virtual void readRestOfFrame() {} /// Do additional resizing required by derived class - virtual void resizeRestOfFrame(){} + virtual void resizeRestOfFrame() {} /// Return the size of the frames vector - unsigned getNumberOfReferenceFrames() const ; + unsigned getNumberOfReferenceFrames() const ; /// Calculate the distance from one of the reference points double calcDistanceFromConfiguration( const unsigned& ifunc, const std::vector& pos, const Pbc& pbc, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const ; @@ -68,7 +68,7 @@ class MultiReferenceBase { /// Return a reference to all the reference frames std::vector& getReferenceConfigurations(); /// Copy a reference configuration into the multi reference object - void copyFrame( ReferenceConfiguration* frameToCopy ); + void copyFrame( ReferenceConfiguration* frameToCopy ); /// Set the weight of the ith frame void setWeights( const std::vector& ww ); /// Retrieve the weight of one of the frames @@ -78,37 +78,37 @@ class MultiReferenceBase { }; template -void MultiReferenceBase::parse(const std::string& key, T& val ){ +void MultiReferenceBase::parse(const std::string& key, T& val ) { frames[frames.size()-1]->parse(key,val); } inline double MultiReferenceBase::calcDistanceFromConfiguration( const unsigned& ifunc, const std::vector& pos, const Pbc& pbc, - const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { - return frames[ifunc]->calculate( pos, pbc, arg, myder, squared ); + const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { + return frames[ifunc]->calculate( pos, pbc, arg, myder, squared ); } inline unsigned MultiReferenceBase::getNumberOfReferenceFrames() const { - return frames.size(); + return frames.size(); } inline -double MultiReferenceBase::getWeight( const unsigned& ifram ) const { +double MultiReferenceBase::getWeight( const unsigned& ifram ) const { plumed_dbg_assert( iframgetWeight(); } inline -ReferenceConfiguration* MultiReferenceBase::getFrame( const unsigned& iframe ){ - plumed_dbg_assert( iframe& MultiReferenceBase::getReferenceConfigurations(){ +std::vector& MultiReferenceBase::getReferenceConfigurations() { return frames; -} +} } #endif diff --git a/src/reference/NormalizedEuclideanDistance.cpp b/src/reference/NormalizedEuclideanDistance.cpp index 0fa8eb7547..9b4d14a321 100644 --- a/src/reference/NormalizedEuclideanDistance.cpp +++ b/src/reference/NormalizedEuclideanDistance.cpp @@ -32,8 +32,8 @@ class NormalizedEuclideanDistance : public ArgumentOnlyDistance { PLUMED_REGISTER_METRIC(NormalizedEuclideanDistance,"NORM-EUCLIDEAN") NormalizedEuclideanDistance::NormalizedEuclideanDistance( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -ArgumentOnlyDistance(ro) + ReferenceConfiguration(ro), + ArgumentOnlyDistance(ro) { hasweights=true; } diff --git a/src/reference/OptimalRMSD.cpp b/src/reference/OptimalRMSD.cpp index 6d3ca828a7..dc4d7f31b4 100644 --- a/src/reference/OptimalRMSD.cpp +++ b/src/reference/OptimalRMSD.cpp @@ -24,7 +24,7 @@ #include "tools/Matrix.h" #include "tools/RMSD.h" -namespace PLMD{ +namespace PLMD { class OptimalRMSD : public RMSDBase { private: @@ -34,45 +34,45 @@ class OptimalRMSD : public RMSDBase { explicit OptimalRMSD(const ReferenceConfigurationOptions& ro); void read( const PDB& ); double calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; - bool pcaIsEnabledForThisReference(){ return true; } - void setupRMSDObject(){ myrmsd.clear(); myrmsd.set(getAlign(),getDisplace(),getReferencePositions(),"OPTIMAL"); } - void setupPCAStorage( ReferenceValuePack& mypack ){ - mypack.switchOnPCAOption(); - mypack.centeredpos.resize( getNumberOfAtoms() ); - mypack.displacement.resize( getNumberOfAtoms() ); - mypack.DRotDPos.resize(3,3); mypack.rot.resize(1); + bool pcaIsEnabledForThisReference() { return true; } + void setupRMSDObject() { myrmsd.clear(); myrmsd.set(getAlign(),getDisplace(),getReferencePositions(),"OPTIMAL"); } + void setupPCAStorage( ReferenceValuePack& mypack ) { + mypack.switchOnPCAOption(); + mypack.centeredpos.resize( getNumberOfAtoms() ); + mypack.displacement.resize( getNumberOfAtoms() ); + mypack.DRotDPos.resize(3,3); mypack.rot.resize(1); } - void extractAtomicDisplacement( const std::vector& pos, const bool & anflag, std::vector& direction ) const ; - double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; + void extractAtomicDisplacement( const std::vector& pos, const bool & anflag, std::vector& direction ) const ; + double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; }; PLUMED_REGISTER_METRIC(OptimalRMSD,"OPTIMAL") OptimalRMSD::OptimalRMSD(const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -RMSDBase(ro) + ReferenceConfiguration(ro), + RMSDBase(ro) { fast=ro.usingFastOption(); } -void OptimalRMSD::read( const PDB& pdb ){ - readReference( pdb ); setupRMSDObject(); +void OptimalRMSD::read( const PDB& pdb ) { + readReference( pdb ); setupRMSDObject(); } double OptimalRMSD::calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const { - double d; - if( myder.calcUsingPCAOption() ){ - std::vector centeredreference( getNumberOfAtoms () ); - d=myrmsd.calc_PCAelements(pos,myder.getAtomVector(),myder.rot[0],myder.DRotDPos,myder.getAtomsDisplacementVector(),myder.centeredpos,centeredreference,squared); - unsigned nat = pos.size(); for(unsigned i=0;i(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); - else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + double d; + if( myder.calcUsingPCAOption() ) { + std::vector centeredreference( getNumberOfAtoms () ); + d=myrmsd.calc_PCAelements(pos,myder.getAtomVector(),myder.rot[0],myder.DRotDPos,myder.getAtomsDisplacementVector(),myder.centeredpos,centeredreference,squared); + unsigned nat = pos.size(); for(unsigned i=0; i(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); } else { - if( getAlign()==getDisplace() ) d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); - else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + if( getAlign()==getDisplace() ) d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); + else d=myrmsd.optimalAlignment(getAlign(),getDisplace(),pos,getReferencePositions(),myder.getAtomVector(),squared); } - myder.clear(); for(unsigned i=0;i& pos, con std::vector centeredreference( getNumberOfAtoms() ), centeredpos( getNumberOfAtoms() ), avector( getNumberOfAtoms() ); double d=myrmsd.calc_PCAelements(pos,avector,rot[0],DRotDPos,direction,centeredpos,centeredreference,true); unsigned nat = pos.size(); double scale=1.0; if( anflag ) scale = 1.0 / static_cast( nat ); - for(unsigned i=0;i& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { plumed_dbg_assert( mypack.calcUsingPCAOption() ); double proj=0.0; mypack.clear(); - for(unsigned i=0;i( getNumberOfAtoms() ); - for(unsigned n=0;n& prop, const bool isp ){ +void PointWiseMapping::setPropertyNames( const std::vector& prop, const bool isp ) { property.resize( prop.size() ); ispath=isp; - for(unsigned i=0;i( getFrame( getNumberOfReferenceFrames() - 1 ) ); if( tdir ) plumed_merror("cannot use directions in mapping"); plumed_dbg_assert( property.size()>0 ); std::vector labelvals; - if( !ispath ){ - labelvals.resize( property.size() ); - for(unsigned i=0;i( frames.size() ); + labelvals.resize(1); + labelvals[0]=static_cast( frames.size() ); } - low_dim.push_back( labelvals ); + low_dim.push_back( labelvals ); plumed_dbg_assert( low_dim.size()==getNumberOfReferenceFrames() ); } -void PointWiseMapping::clearRestOfData(){ +void PointWiseMapping::clearRestOfData() { low_dim.resize(0); -} +} -void PointWiseMapping::resizeRestOfFrame(){ +void PointWiseMapping::resizeRestOfFrame() { plumed_dbg_assert( property.size()>0 ); std::vector labelvals( property.size() ); low_dim.push_back( labelvals ); plumed_dbg_assert( low_dim.size()==getNumberOfReferenceFrames() ); } -void PointWiseMapping::duplicateFrameList(){ +void PointWiseMapping::duplicateFrameList() { unsigned nframes=frames.size(); - for(unsigned i=0;igetWeight(), property[0].c_str(), low_dim[i][0] ); - for(unsigned j=1;jprint( afile, fmt, lunits ); + for(unsigned i=0; igetWeight(), property[0].c_str(), low_dim[i][0] ); + for(unsigned j=1; jprint( afile, fmt, lunits ); } -} +} } diff --git a/src/reference/PointWiseMapping.h b/src/reference/PointWiseMapping.h index 1345e62fc4..a530d3492b 100644 --- a/src/reference/PointWiseMapping.h +++ b/src/reference/PointWiseMapping.h @@ -35,7 +35,7 @@ class PointWiseMapping : public MultiReferenceBase { /// The names of the projection coordinates std::vector property; /// These are where the reference configurations should be projected - std::vector< std::vector > low_dim; + std::vector< std::vector > low_dim; public: PointWiseMapping( const std::string& type, const bool& checksoff ); /// Set the names of the low dimensional properties @@ -44,11 +44,11 @@ class PointWiseMapping : public MultiReferenceBase { bool mappingNeedsSetup() const; /// Delete the low dimensional projections void clearRestOfData(); -/// Read in the data from a file +/// Read in the data from a file void readRestOfFrame(); /// Resize everything else from a file void resizeRestOfFrame(); -/// Make a second copy of the frame list +/// Make a second copy of the frame list void duplicateFrameList(); /// Get the number of points we are mapping into the lower dimensional space unsigned getNumberOfMappedPoints() const ; @@ -71,7 +71,7 @@ class PointWiseMapping : public MultiReferenceBase { /// Get a pointer to the matrix of pairwise distances Matrix& modifyDmat(); /// Print out the low dimensional mapping - void print( const std::string& method, const double & time, OFile& afile, + void print( const std::string& method, const double & time, OFile& afile, const std::string& fmt, const double& lunits ); /// Get the low dimensional embedding coordinate double getProjectionCoordinate( const unsigned& iframe, const unsigned& jcoord ) const ; @@ -86,7 +86,7 @@ bool PointWiseMapping::mappingNeedsSetup() const { } inline -void PointWiseMapping::copyFrameDerivatives( const unsigned& from, const unsigned& to ){ +void PointWiseMapping::copyFrameDerivatives( const unsigned& from, const unsigned& to ) { plumed_dbg_assert( to>=frames.size()/2 && fromcopyDerivatives( frames[from] ); } @@ -117,7 +117,7 @@ double PointWiseMapping::getPropertyValue( const unsigned& iframe, const unsigne // Vector PointWiseMapping::getAtomDerivatives( const unsigned& iframe, const unsigned& jatom ){ // return frames[iframe]->getAtomDerivative(jatom); // } -// +// // inline // bool PointWiseMapping::getVirial( const unsigned& iframe, Tensor& vir ){ // return frames[iframe]->getVirial( vir ); @@ -129,7 +129,7 @@ double PointWiseMapping::getPropertyValue( const unsigned& iframe, const unsigne // } inline -Matrix& PointWiseMapping::modifyDmat(){ +Matrix& PointWiseMapping::modifyDmat() { if( dmat.nrows()!=frames.size() || dmat.ncols()!=frames.size() ) dmat.resize( frames.size(), frames.size() ); return dmat; } @@ -141,10 +141,10 @@ double PointWiseMapping::getProjectionCoordinate( const unsigned& iframe, const } inline -void PointWiseMapping::setProjectionCoordinate( const unsigned& iframe, const unsigned& jcoord, const double& coord ){ +void PointWiseMapping::setProjectionCoordinate( const unsigned& iframe, const unsigned& jcoord, const double& coord ) { plumed_dbg_assert( iframe& pos, ReferenceValuePack& myder, const bool& squared ) const { -// clearDerivatives(); +// clearDerivatives(); return calc( pos, myder, squared ); -} +} double RMSDBase::calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( pos.size()==getNumberOfAtoms() ); diff --git a/src/reference/RMSDBase.h b/src/reference/RMSDBase.h index 9a59d1f1c8..e1fb621e26 100644 --- a/src/reference/RMSDBase.h +++ b/src/reference/RMSDBase.h @@ -36,7 +36,7 @@ class RMSDBase : public SingleDomainRMSD { public: explicit RMSDBase( const ReferenceConfigurationOptions& ro ); double calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const; - double calculate( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; + double calculate( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; virtual double calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const=0; }; diff --git a/src/reference/ReferenceArguments.cpp b/src/reference/ReferenceArguments.cpp index 20c6cb5b5c..e051f1d7b2 100644 --- a/src/reference/ReferenceArguments.cpp +++ b/src/reference/ReferenceArguments.cpp @@ -27,204 +27,204 @@ namespace PLMD { ReferenceArguments::ReferenceArguments( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -hasweights(false), -hasmetric(false) + ReferenceConfiguration(ro), + hasweights(false), + hasmetric(false) { } -void ReferenceArguments::readArgumentsFromPDB( const PDB& pdb ){ +void ReferenceArguments::readArgumentsFromPDB( const PDB& pdb ) { ReferenceAtoms* aref=dynamic_cast( this ); if( !aref ) parseVector( "ARG", arg_names ); else parseVector( "ARG", arg_names, true ); reference_args.resize( arg_names.size() ); - for(unsigned i=0;i& arg_vals ){ - reference_args.resize( arg_vals.size() ); - arg_names.resize( arg_vals.size() ); +void ReferenceArguments::setArgumentNames( const std::vector& arg_vals ) { + reference_args.resize( arg_vals.size() ); + arg_names.resize( arg_vals.size() ); arg_der_index.resize( arg_vals.size() ); - for(unsigned i=0;i& arg_vals, const std::vector& sigma ){ +void ReferenceArguments::setReferenceArguments( const std::vector& arg_vals, const std::vector& sigma ) { moveReferenceArguments( arg_vals ); - - if( hasmetric ){ - unsigned k=0; - for(unsigned i=0;i& arg_vals ){ +void ReferenceArguments::moveReferenceArguments( const std::vector& arg_vals ) { plumed_dbg_assert( reference_args.size()==arg_vals.size() ); - for(unsigned i=0;i& argout, bool disable_checks ){ +void ReferenceArguments::getArgumentRequests( std::vector& argout, bool disable_checks ) { arg_der_index.resize( arg_names.size() ); - if( argout.size()==0 ){ - for(unsigned i=0;i0 ){ - ofile.printf("REMARK ARG=%s", arg_names[0].c_str() ); - for(unsigned i=1;i0 ) { + ofile.printf("REMARK ARG=%s", arg_names[0].c_str() ); + for(unsigned i=1; i& ReferenceArguments::getReferenceMetric(){ - if( hasmetric ){ - unsigned ntot=(reference_args.size() / 2 )*(reference_args.size()+1); - if( trig_metric.size()!=ntot ) trig_metric.resize( ntot ); - unsigned k=0; - for(unsigned i=0;i& ReferenceArguments::getReferenceMetric() { + if( hasmetric ) { + unsigned ntot=(reference_args.size() / 2 )*(reference_args.size()+1); + if( trig_metric.size()!=ntot ) trig_metric.resize( ntot ); + unsigned k=0; + for(unsigned i=0; i & vals, const std::vector& arg, - ReferenceValuePack& myder, const bool& squared ) const { +double ReferenceArguments::calculateArgumentDistance( const std::vector & vals, const std::vector& arg, + ReferenceValuePack& myder, const bool& squared ) const { double r=0; std::vector arg_ders( vals.size() ); - if( hasmetric ){ - for(unsigned i=0;idifference( reference_args[i], arg[ik] ); - for(unsigned j=0;jdifference( reference_args[j], arg[jk] ); - - arg_ders[ ik ]+=2.0*metric(i,j)*dp_j; // Factor of two for off diagonal terms as you have terms from ij and ji - r+=dp_i*dp_j*metric(i,j); - } + if( hasmetric ) { + for(unsigned i=0; idifference( reference_args[i], arg[ik] ); + for(unsigned j=0; jdifference( reference_args[j], arg[jk] ); + + arg_ders[ ik ]+=2.0*metric(i,j)*dp_j; // Factor of two for off diagonal terms as you have terms from ij and ji + r+=dp_i*dp_j*metric(i,j); } + } } else { - for(unsigned i=0;idifference( reference_args[i], arg[ik] ); - r+=weights[i]*dp_i*dp_i; arg_ders[ik]=2.0*weights[i]*dp_i; - } + for(unsigned i=0; idifference( reference_args[i], arg[ik] ); + r+=weights[i]*dp_i*dp_i; arg_ders[ik]=2.0*weights[i]*dp_i; + } } - if(!squared){ - r=sqrt(r); double ir=1.0/(2.0*r); - for(unsigned i=0;i& vals, const std::vector& arg, std::vector& dirout ) const { - if( hasmetric ){ - plumed_error(); + if( hasmetric ) { + plumed_error(); } else { - for(unsigned j=0;jdifference( reference_args[j], arg[jk] ); - } + for(unsigned j=0; jdifference( reference_args[j], arg[jk] ); + } } } double ReferenceArguments::projectArgDisplacementOnVector( const std::vector& eigv, const std::vector& vals, const std::vector& arg, ReferenceValuePack& mypack ) const { - if( hasmetric ){ - plumed_error(); + if( hasmetric ) { + plumed_error(); } else { - double proj=0; - for(unsigned j=0;jdifference( reference_args[j], arg[jk] ); - mypack.setArgumentDerivatives( jk, eigv[j]*sqrtweight[j] ); - } - return proj; + double proj=0; + for(unsigned j=0; jdifference( reference_args[j], arg[jk] ); + mypack.setArgumentDerivatives( jk, eigv[j]*sqrtweight[j] ); + } + return proj; } } -void ReferenceArguments::displaceReferenceArguments( const double& weight, const std::vector& displace ){ +void ReferenceArguments::displaceReferenceArguments( const double& weight, const std::vector& displace ) { plumed_dbg_assert( displace.size()==getNumberOfReferenceArguments() ); - for(unsigned i=0;i weights, sqrtweight; @@ -60,7 +60,7 @@ friend class ReferenceConfiguration; protected: /// Are we reading weights from input bool hasweights; -/// Are we calculating a Malanobius distance +/// Are we calculating a Malanobius distance bool hasmetric; /// Read in the atoms from the pdb file void readArgumentsFromPDB( const PDB& pdb ); @@ -70,7 +70,7 @@ friend class ReferenceConfiguration; explicit ReferenceArguments( const ReferenceConfigurationOptions& ro ); /// Get the number of reference arguments unsigned getNumberOfReferenceArguments() const ; -/// Get the arguments required +/// Get the arguments required void getArgumentRequests( std::vector&, bool disable_checks=false ); /// Set the names of the arguments void setArgumentNames( const std::vector& arg_vals ); @@ -110,7 +110,7 @@ const std::vector& ReferenceArguments::getReferenceArguments() const { } inline -const std::vector& ReferenceArguments::getArgumentNames(){ +const std::vector& ReferenceArguments::getArgumentNames() { return arg_names; } diff --git a/src/reference/ReferenceAtoms.cpp b/src/reference/ReferenceAtoms.cpp index e2d2ad05ed..7120786f3c 100644 --- a/src/reference/ReferenceAtoms.cpp +++ b/src/reference/ReferenceAtoms.cpp @@ -26,100 +26,100 @@ namespace PLMD { ReferenceAtoms::ReferenceAtoms( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration(ro), -checks_were_disabled(false) + ReferenceConfiguration(ro), + checks_were_disabled(false) { } -void ReferenceAtoms::readAtomsFromPDB( const PDB& pdb, const bool allowblocks ){ - if( !allowblocks && pdb.getNumberOfAtomBlocks()!=1 ) error("found multi-atom-block pdb format but expecting only one block of atoms"); +void ReferenceAtoms::readAtomsFromPDB( const PDB& pdb, const bool allowblocks ) { + if( !allowblocks && pdb.getNumberOfAtomBlocks()!=1 ) error("found multi-atom-block pdb format but expecting only one block of atoms"); - for(unsigned i=0;i& numbers ){ +void ReferenceAtoms::setAtomNumbers( const std::vector& numbers ) { reference_atoms.resize( numbers.size() ); align.resize( numbers.size() ); displace.resize( numbers.size() ); atom_der_index.resize( numbers.size() ); indices.resize( numbers.size() ); - for(unsigned i=0;i& numbers ){ +bool ReferenceAtoms::parseAtomList( const std::string& key, std::vector& numbers ) { plumed_assert( numbers.size()==0 ); - std::vector strings; + std::vector strings; if( !parseVector(key,strings,true) ) return false; - Tools::interpretRanges(strings); - - numbers.resize( strings.size() ); - for(unsigned i=0;i& numbers, bool disable_checks ){ +void ReferenceAtoms::getAtomRequests( std::vector& numbers, bool disable_checks ) { singleDomainRequests(numbers,disable_checks); } -void ReferenceAtoms::singleDomainRequests( std::vector& numbers, bool disable_checks ){ +void ReferenceAtoms::singleDomainRequests( std::vector& numbers, bool disable_checks ) { checks_were_disabled=disable_checks; atom_der_index.resize( indices.size() ); - if( numbers.size()==0 ){ - for(unsigned i=0;i& dir ){ +void ReferenceAtoms::displaceReferenceAtoms( const double& weight, const std::vector& dir ) { plumed_dbg_assert( dir.size()==reference_atoms.size() ); - for(unsigned i=0;i& atomnumbers ); /// Read a list of atoms from the pdb input file - bool parseAtomList( const std::string& , std::vector& ); + bool parseAtomList( const std::string&, std::vector& ); /// Get the vector of alignment weights const std::vector & getAlign() const ; /// Get the vector of displacement weights const std::vector & getDisplace() const ; /// Get the position of the ith atom - Vector getReferencePosition( const unsigned& iatom ) const ; + Vector getReferencePosition( const unsigned& iatom ) const ; /// Add derivatives to iatom th atom in list // void addAtomicDerivatives( const unsigned& , const Vector& ); /// Get the atomic derivatives on the ith atom in the list @@ -105,14 +105,14 @@ friend class ReferenceConfiguration; /// This returns how many atoms there should be unsigned getNumberOfAtoms() const ; /// Displace the positions of the reference atoms a bit - void displaceReferenceAtoms( const double& weight, const std::vector& dir ); + void displaceReferenceAtoms( const double& weight, const std::vector& dir ); /// Extract a displacement from a position in space virtual void extractAtomicDisplacement( const std::vector& pos, const bool & anflag, std::vector& direction ) const { - plumed_error(); + plumed_error(); } /// Project the displacement on a vector virtual double projectAtomicDisplacementOnVector( const std::vector& eigv, const std::vector& pos, ReferenceValuePack& mypack ) const { - plumed_error(); return 1; + plumed_error(); return 1; } }; @@ -171,7 +171,7 @@ const std::vector & ReferenceAtoms::getReferencePositions() const { // } inline -const std::vector& ReferenceAtoms::getAbsoluteIndexes(){ +const std::vector& ReferenceAtoms::getAbsoluteIndexes() { return indices; } diff --git a/src/reference/ReferenceConfiguration.cpp b/src/reference/ReferenceConfiguration.cpp index 1df1bc694d..61d554a205 100644 --- a/src/reference/ReferenceConfiguration.cpp +++ b/src/reference/ReferenceConfiguration.cpp @@ -27,10 +27,10 @@ #include "tools/OFile.h" #include "tools/PDB.h" -namespace PLMD{ +namespace PLMD { ReferenceConfigurationOptions::ReferenceConfigurationOptions( const std::string& type ): -tt(type) + tt(type) { } @@ -41,11 +41,11 @@ bool ReferenceConfigurationOptions::usingFastOption() const { std::string ReferenceConfigurationOptions::getMultiRMSDType() const { plumed_assert( tt.find("MULTI-")!=std::string::npos ); std::size_t dot=tt.find_first_of("MULTI-"); - return tt.substr(dot+6); + return tt.substr(dot+6); } ReferenceConfiguration::ReferenceConfiguration( const ReferenceConfigurationOptions& ro ): -name(ro.tt) + name(ro.tt) // arg_ders(0), // atom_ders(0) { @@ -60,11 +60,11 @@ std::string ReferenceConfiguration::getName() const { return name; } -void ReferenceConfiguration::set( const PDB& pdb ){ - line=pdb.getRemark(); - std::string ignore; - if( parse("TYPE",ignore,true) ){ - if(ignore!=name) error("mismatch for name"); +void ReferenceConfiguration::set( const PDB& pdb ) { + line=pdb.getRemark(); + std::string ignore; + if( parse("TYPE",ignore,true) ) { + if(ignore!=name) error("mismatch for name"); } if( !parse("WEIGHT",weight,true) ) weight=1.0; read( pdb ); @@ -83,66 +83,66 @@ void ReferenceConfiguration::set( const PDB& pdb ){ // return virialWasSet; // } -void ReferenceConfiguration::parseFlag( const std::string&key, bool&t ){ +void ReferenceConfiguration::parseFlag( const std::string&key, bool&t ) { Tools::parseFlag(line,key,t); } -void ReferenceConfiguration::error(const std::string& msg){ +void ReferenceConfiguration::error(const std::string& msg) { plumed_merror("error reading reference configuration of type " + name + " : " + msg ); } -void ReferenceConfiguration::setNamesAndAtomNumbers( const std::vector& numbers, const std::vector& arg ){ - ReferenceAtoms* atoms=dynamic_cast( this ); - if(!atoms){ - plumed_massert( numbers.size()==0, "expecting no atomic positions"); - //setNumberOfAtoms( 0 ); - } else { - atoms->setAtomNumbers( numbers ); - // setNumberOfAtoms( numbers.size() ); +void ReferenceConfiguration::setNamesAndAtomNumbers( const std::vector& numbers, const std::vector& arg ) { + ReferenceAtoms* atoms=dynamic_cast( this ); + if(!atoms) { + plumed_massert( numbers.size()==0, "expecting no atomic positions"); + //setNumberOfAtoms( 0 ); + } else { + atoms->setAtomNumbers( numbers ); + // setNumberOfAtoms( numbers.size() ); } // Copy the arguments to the reference ReferenceArguments* args=dynamic_cast( this ); - if(!args){ - plumed_massert( arg.size()==0, "expecting no arguments"); - // setNumberOfArguments(0); + if(!args) { + plumed_massert( arg.size()==0, "expecting no arguments"); + // setNumberOfArguments(0); } else { - args->setArgumentNames( arg ); - // setNumberOfArguments( arg.size() ); + args->setArgumentNames( arg ); + // setNumberOfArguments( arg.size() ); } } -void ReferenceConfiguration::setReferenceConfig( const std::vector& pos, const std::vector& arg, const std::vector& metric ){ +void ReferenceConfiguration::setReferenceConfig( const std::vector& pos, const std::vector& arg, const std::vector& metric ) { // plumed_dbg_assert( pos.size()==atom_ders.size() && arg.size()==arg_ders.size() ); // Copy the atomic positions to the reference ReferenceAtoms* atoms=dynamic_cast( this ); - if(!atoms){ - plumed_massert( pos.size()==0, "expecting no atomic positions"); - } else { - std::vector align_in( pos.size(), 1.0 ), displace_in( pos.size(), 1.0 ); - atoms->setReferenceAtoms( pos, align_in, displace_in ); + if(!atoms) { + plumed_massert( pos.size()==0, "expecting no atomic positions"); + } else { + std::vector align_in( pos.size(), 1.0 ), displace_in( pos.size(), 1.0 ); + atoms->setReferenceAtoms( pos, align_in, displace_in ); } // Copy the arguments to the reference ReferenceArguments* args=dynamic_cast( this ); - if(!args){ - plumed_massert( arg.size()==0 && metric.size()==0, "expecting no arguments"); + if(!args) { + plumed_massert( arg.size()==0 && metric.size()==0, "expecting no arguments"); } else { - args->setReferenceArguments( arg, metric ); + args->setReferenceArguments( arg, metric ); } } -void ReferenceConfiguration::checkRead(){ - if(!line.empty()){ +void ReferenceConfiguration::checkRead() { + if(!line.empty()) { std::string msg="cannot understand the following words from the input line : "; - for(unsigned i=0;i& pos, const Pbc& pbc, const std::vector& vals, - ReferenceValuePack& myder, const bool& squared ) const { +double ReferenceConfiguration::calculate( const std::vector& pos, const Pbc& pbc, const std::vector& vals, + ReferenceValuePack& myder, const bool& squared ) const { // clearDerivatives(); std::vector tmparg( vals.size() ); - for(unsigned i=0;iget(); + for(unsigned i=0; iget(); return calc( pos, pbc, vals, tmparg, myder, squared ); } @@ -153,12 +153,12 @@ double ReferenceConfiguration::calculate( const std::vector& pos, const // virialWasSet=ref->virialWasSet; virial=ref->virial; // } -void ReferenceConfiguration::print( OFile& ofile, const double& time, const double& weight, const double& lunits, const double& old_norm ){ +void ReferenceConfiguration::print( OFile& ofile, const double& time, const double& weight, const double& lunits, const double& old_norm ) { ofile.printf("REMARK TIME=%f LOG_WEIGHT=%f OLD_NORM=%f\n",time, weight, old_norm ); print( ofile, "%f", lunits ); // HARD CODED FORMAT HERE AS THIS IS FOR CHECKPOINT FILE } -void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt, const double& lunits ){ +void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt, const double& lunits ) { ofile.printf("REMARK TYPE=%s\n",getName().c_str() ); ReferenceArguments* args=dynamic_cast(this); if(args) args->printArguments( ofile, fmt ); @@ -167,61 +167,61 @@ void ReferenceConfiguration::print( OFile& ofile, const std::string& fmt, const ofile.printf("END\n"); } -void ReferenceConfiguration::displaceReferenceConfiguration( const double& weight, Direction& dir ){ +void ReferenceConfiguration::displaceReferenceConfiguration( const double& weight, Direction& dir ) { ReferenceArguments* args=dynamic_cast(this); if( args ) args->displaceReferenceArguments( weight, dir.getReferenceArguments() ); ReferenceAtoms* atoms=dynamic_cast(this); if( atoms ) atoms->displaceReferenceAtoms( weight, dir.getReferencePositions() ); } -void ReferenceConfiguration::extractDisplacementVector( const std::vector& pos, const std::vector& vals, - const std::vector& arg, const bool & anflag, const bool& nflag, - Direction& mydir ) const { +void ReferenceConfiguration::extractDisplacementVector( const std::vector& pos, const std::vector& vals, + const std::vector& arg, const bool & anflag, const bool& nflag, + Direction& mydir ) const { const ReferenceAtoms* atoms=dynamic_cast( this ); if( atoms ) atoms->extractAtomicDisplacement( pos, anflag, mydir.reference_atoms ); const ReferenceArguments* args=dynamic_cast( this ); if( args ) args->extractArgumentDisplacement( vals, arg, mydir.reference_args ); // Normalize direction if required - if( nflag ){ - // Calculate length of vector - double tmp, norm=0; - for(unsigned i=0;i& pos, - const std::vector& vals, const std::vector& arg, - ReferenceValuePack& mypack ) const { + const std::vector& vals, const std::vector& arg, + ReferenceValuePack& mypack ) const { double proj=0; const ReferenceAtoms* atoms=dynamic_cast( this ); if( atoms ) proj += atoms->projectAtomicDisplacementOnVector( mydir.getReferencePositions(), pos, mypack ); const ReferenceArguments* args=dynamic_cast( this ); if( args ) proj += args->projectArgDisplacementOnVector( mydir.getReferenceArguments(), vals, arg, mypack ); return proj; -} +} -double distance( const Pbc& pbc, const std::vector & vals, ReferenceConfiguration* ref1, ReferenceConfiguration* ref2, const bool& squared ){ +double distance( const Pbc& pbc, const std::vector & vals, ReferenceConfiguration* ref1, ReferenceConfiguration* ref2, const bool& squared ) { unsigned nder; if( ref1->getReferencePositions().size()>0 ) nder=ref1->getReferenceArguments().size() + 3*ref1->getReferencePositions().size() + 9; else nder=ref1->getReferenceArguments().size(); - MultiValue myvals( 1, nder ); ReferenceValuePack myder( ref1->getReferenceArguments().size() , ref1->getReferencePositions().size() , myvals ); + MultiValue myvals( 1, nder ); ReferenceValuePack myder( ref1->getReferenceArguments().size(), ref1->getReferencePositions().size(), myvals ); double dist1=ref1->calc( ref2->getReferencePositions(), pbc, vals, ref2->getReferenceArguments(), myder, squared ); #ifndef NDEBUG // Check that A - B = B - A double dist2=ref2->calc( ref1->getReferencePositions(), pbc, vals, ref1->getReferenceArguments(), myder, squared ); plumed_dbg_assert( fabs(dist1-dist2) & vals, ReferenceConfiguration*, ReferenceConfiguration*, const bool& squared ); + friend class SingleDomainRMSD; + friend double distance( const Pbc& pbc, const std::vector & vals, ReferenceConfiguration*, ReferenceConfiguration*, const bool& squared ); private: /// The name of this particular config std::string name; @@ -81,14 +81,14 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere protected: /// Derivatives wrt to the arguments // std::vector arg_ders; -/// The virial contribution has to be stored +/// The virial contribution has to be stored // bool virialWasSet; // Tensor virial; /// Derivatives wrt to the atoms // std::vector atom_ders; /// Crash with an error void error(const std::string& msg); -/// Clear the derivatives +/// Clear the derivatives // void clearDerivatives(); public: explicit ReferenceConfiguration( const ReferenceConfigurationOptions& ro ); @@ -100,16 +100,16 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere virtual unsigned getNumberOfReferencePositions() const ; virtual unsigned getNumberOfReferenceArguments() const ; /// Retrieve the atoms that are required for this guy - virtual void getAtomRequests( std::vector&, bool disable_checks=false ){} + virtual void getAtomRequests( std::vector&, bool disable_checks=false ) {} /// Retrieve the arguments that are required for this guy - virtual void getArgumentRequests( std::vector&, bool disable_checks=false ){} + virtual void getArgumentRequests( std::vector&, bool disable_checks=false ) {} /// Set the final number of arguments // virtual void setNumberOfArguments( const unsigned& ); /// Set the final number of atoms // virtual void setNumberOfAtoms( const unsigned& ); -/// Set the reference configuration using a PDB +/// Set the reference configuration using a PDB virtual void set( const PDB& ); -/// Do all local business for setting the configuration +/// Do all local business for setting the configuration virtual void read( const PDB& )=0; /// Set the weight for this frame void setWeight( const double& ww ); @@ -118,16 +118,16 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere /// Calculate the distance from the reference configuration double calculate( const std::vector& pos, const Pbc& pbc, const std::vector& vals, ReferenceValuePack& myder, const bool& squared=false ) const ; /// Calculate the distance from the reference configuration - virtual double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& args, + virtual double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& args, ReferenceValuePack& myder, const bool& squared ) const=0; // /// Return the derivative wrt to the ith atom // Vector getAtomDerivative( const unsigned& ) const ; // /// Return the derivative wrt to the ith argument // double getArgumentDerivative( const unsigned& ) const ; /// Return the derivatives of the distance wrt the cell vectors. This returns false -/// for everything other than DRMSD as these sort of calculations have to be done -/// separately when you use RMSD -// bool getVirial( Tensor& virout ) const ; +/// for everything other than DRMSD as these sort of calculations have to be done +/// separately when you use RMSD +// bool getVirial( Tensor& virout ) const ; /// Parse something from the pdb remarks template bool parse( const std::string&key, T&t, bool ignore_missing=false ); @@ -149,24 +149,24 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere void print( OFile& ofile, const std::string& fmt, const double& lunits ); /// Get one of the referene arguments virtual double getReferenceArgument( const unsigned& i ) const { plumed_error(); return 0.0; } -/// These are overwritten in ReferenceArguments and ReferenceAtoms but are required here +/// These are overwritten in ReferenceArguments and ReferenceAtoms but are required here /// to make PLMD::distance work - virtual const std::vector& getReferencePositions() const ; - virtual const std::vector& getReferenceArguments() const ; + virtual const std::vector& getReferencePositions() const ; + virtual const std::vector& getReferenceArguments() const ; virtual const std::vector& getReferenceMetric(); /// These are overwritten in ReferenceArguments and ReferenceAtoms to make frame copying work virtual const std::vector& getAbsoluteIndexes(); virtual const std::vector& getArgumentNames(); /// Extract a Direction giving you the displacement from some position void extractDisplacementVector( const std::vector& pos, const std::vector& vals, - const std::vector& arg, const bool& anflag, const bool& nflag, + const std::vector& arg, const bool& anflag, const bool& nflag, Direction& mydir ) const ; /// Stuff for pca - virtual bool pcaIsEnabledForThisReference(){ return false; } - double projectDisplacementOnVector( const Direction& mydir, const std::vector& pos, const std::vector& vals, + virtual bool pcaIsEnabledForThisReference() { return false; } + double projectDisplacementOnVector( const Direction& mydir, const std::vector& pos, const std::vector& vals, const std::vector& arg, ReferenceValuePack& mypack ) const ; /// Stuff to setup pca - virtual void setupPCAStorage( ReferenceValuePack& mypack ){ plumed_error(); } + virtual void setupPCAStorage( ReferenceValuePack& mypack ) { plumed_error(); } /// Move the reference configuration by an ammount specified using a Direction void displaceReferenceConfiguration( const double& weight, Direction& dir ); }; @@ -184,7 +184,7 @@ friend double distance( const Pbc& pbc, const std::vector & vals, Refere // } inline -void ReferenceConfiguration::setWeight( const double& ww ){ +void ReferenceConfiguration::setWeight( const double& ww ) { weight=ww; } @@ -194,21 +194,21 @@ double ReferenceConfiguration::getWeight() const { } template -bool ReferenceConfiguration::parse(const std::string&key, T&t, bool ignore_missing ){ +bool ReferenceConfiguration::parse(const std::string&key, T&t, bool ignore_missing ) { bool found=Tools::parse(line,key,t); - if(!ignore_missing && !found) error(key + " is missing"); + if(!ignore_missing && !found) error(key + " is missing"); return found; } template -bool ReferenceConfiguration::parseVector(const std::string&key,std::vector&t, bool ignore_missing){ +bool ReferenceConfiguration::parseVector(const std::string&key,std::vector&t, bool ignore_missing) { bool found=Tools::parseVector(line,key,t); if(!ignore_missing && !found) error(key + " is missing"); return found; } inline -const std::vector& ReferenceConfiguration::getReferencePositions() const { +const std::vector& ReferenceConfiguration::getReferencePositions() const { return fake_refatoms; } @@ -218,17 +218,17 @@ const std::vector& ReferenceConfiguration::getReferenceArguments() const } inline -const std::vector& ReferenceConfiguration::getReferenceMetric(){ +const std::vector& ReferenceConfiguration::getReferenceMetric() { return fake_metric; } inline -const std::vector& ReferenceConfiguration::getAbsoluteIndexes(){ +const std::vector& ReferenceConfiguration::getAbsoluteIndexes() { return fake_atom_numbers; } inline -const std::vector& ReferenceConfiguration::getArgumentNames(){ +const std::vector& ReferenceConfiguration::getArgumentNames() { return fake_arg_names; } diff --git a/src/reference/ReferenceValuePack.cpp b/src/reference/ReferenceValuePack.cpp index 9fd9fc6f8e..106e1f1487 100644 --- a/src/reference/ReferenceValuePack.cpp +++ b/src/reference/ReferenceValuePack.cpp @@ -24,72 +24,72 @@ namespace PLMD { ReferenceValuePack::ReferenceValuePack( const unsigned& nargs, const unsigned& natoms, MultiValue& vals ): -boxWasSet(false), -numberOfArgs(nargs), -oind_set(false), -myvals(vals), -atom_indices(myvals.getIndices()), -pca(false) + boxWasSet(false), + numberOfArgs(nargs), + oind_set(false), + myvals(vals), + atom_indices(myvals.getIndices()), + pca(false) { - if( atom_indices.size()!=natoms ){ atom_indices.resize( natoms ); myvals.getAtomVector().resize( natoms ); } - if( vals.getNumberOfValues()==1 ){ oind=0; oind_set=true; } + if( atom_indices.size()!=natoms ) { atom_indices.resize( natoms ); myvals.getAtomVector().resize( natoms ); } + if( vals.getNumberOfValues()==1 ) { oind=0; oind_set=true; } } -void ReferenceValuePack::resize( const unsigned& nargs, const unsigned& natoms ){ - numberOfArgs=nargs; atom_indices.resize( natoms ); +void ReferenceValuePack::resize( const unsigned& nargs, const unsigned& natoms ) { + numberOfArgs=nargs; atom_indices.resize( natoms ); myvals.getAtomVector().resize( natoms ); } -void ReferenceValuePack::updateDynamicLists(){ +void ReferenceValuePack::updateDynamicLists() { myvals.emptyActiveMembers(); - for(unsigned i=0;i0 ){ - for(unsigned i=0;i<9;++i){ - myvals.addDerivative( oind, nbase+i, 0.0 ); - myvals.putIndexInActiveArray( nbase+i ); - } - } + if( atom_indices.size()>0 ) { + for(unsigned i=0; i<9; ++i) { + myvals.addDerivative( oind, nbase+i, 0.0 ); + myvals.putIndexInActiveArray( nbase+i ); + } + } myvals.completeUpdate(); } -void ReferenceValuePack::clear(){ +void ReferenceValuePack::clear() { if( !myvals.updateComplete() ) updateDynamicLists(); myvals.clearAll(); boxWasSet=false; } -void ReferenceValuePack::scaleAllDerivatives( const double& scalef ){ +void ReferenceValuePack::scaleAllDerivatives( const double& scalef ) { if( !myvals.updateComplete() ) updateDynamicLists(); - for(unsigned i=0;i& atom_indices; -/// Are we using pca +/// Are we using pca bool pca; /// A vector of vectors to save us some overhead for vector resizes std::vector centeredpos; @@ -79,7 +79,7 @@ friend class OptimalRMSD; void addAtomDerivatives( const unsigned& iatom, const Vector& der ); /// void addBoxDerivatives( const Tensor& vir ); -/// +/// bool updateComplete() const ; /// void updateDynamicLists(); @@ -123,23 +123,23 @@ unsigned ReferenceValuePack::getNumberOfAtoms() const { } inline -void ReferenceValuePack::setAtomIndex( const unsigned& iatom, const unsigned& jindex ){ +void ReferenceValuePack::setAtomIndex( const unsigned& iatom, const unsigned& jindex ) { plumed_dbg_assert( iatom0 ); boxWasSet=true; unsigned nbase = myvals.getNumberOfDerivatives() - 9; - for(unsigned i=0;i<3;++i) for(unsigned j=0;j<3;++j) myvals.addDerivative( oind, nbase + 3*i + j , vir(i,j) ); + for(unsigned i=0; i<3; ++i) for(unsigned j=0; j<3; ++j) myvals.addDerivative( oind, nbase + 3*i + j, vir(i,j) ); } inline -void ReferenceValuePack::setValIndex( const unsigned& ind ){ +void ReferenceValuePack::setValIndex( const unsigned& ind ) { oind=ind; oind_set=true; } @@ -186,7 +186,7 @@ Vector ReferenceValuePack::getAtomDerivative( const unsigned& iatom ) const { Vector tmp; plumed_dbg_assert( oind_set && iatom& ReferenceValuePack::getAtomVector(){ +std::vector& ReferenceValuePack::getAtomVector() { return myvals.getAtomVector(); } inline -std::vector& ReferenceValuePack::getAtomsDisplacementVector(){ +std::vector& ReferenceValuePack::getAtomsDisplacementVector() { return displacement; } diff --git a/src/reference/SimpleRMSD.cpp b/src/reference/SimpleRMSD.cpp index 9b06563edf..4c0d825326 100644 --- a/src/reference/SimpleRMSD.cpp +++ b/src/reference/SimpleRMSD.cpp @@ -23,7 +23,7 @@ #include "MetricRegister.h" #include "tools/RMSD.h" -namespace PLMD{ +namespace PLMD { class SimpleRMSD : public RMSDBase { private: @@ -32,30 +32,30 @@ class SimpleRMSD : public RMSDBase { explicit SimpleRMSD( const ReferenceConfigurationOptions& ro ); void read( const PDB& ); double calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const ; - bool pcaIsEnabledForThisReference(){ return true; } - void setupPCAStorage( ReferenceValuePack& mypack ){ - mypack.switchOnPCAOption(); mypack.getAtomsDisplacementVector().resize( getNumberOfAtoms() ); + bool pcaIsEnabledForThisReference() { return true; } + void setupPCAStorage( ReferenceValuePack& mypack ) { + mypack.switchOnPCAOption(); mypack.getAtomsDisplacementVector().resize( getNumberOfAtoms() ); } void extractAtomicDisplacement( const std::vector& pos, const bool& anflag, std::vector& direction ) const ; - double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; + double projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const ; }; PLUMED_REGISTER_METRIC(SimpleRMSD,"SIMPLE") SimpleRMSD::SimpleRMSD( const ReferenceConfigurationOptions& ro ): -ReferenceConfiguration( ro ), -RMSDBase( ro ) + ReferenceConfiguration( ro ), + RMSDBase( ro ) { } -void SimpleRMSD::read( const PDB& pdb ){ +void SimpleRMSD::read( const PDB& pdb ) { readReference( pdb ); } double SimpleRMSD::calc( const std::vector& pos, ReferenceValuePack& myder, const bool& squared ) const { if( myder.getAtomsDisplacementVector().size()!=pos.size() ) myder.getAtomsDisplacementVector().resize( pos.size() ); double d=myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), myder.getAtomVector(), myder.getAtomsDisplacementVector(), squared ); - myder.clear(); for(unsigned i=0;i& pos, cons std::vector tder( getNumberOfAtoms() ); double d=myrmsd.simpleAlignment( getAlign(), getDisplace(), pos, getReferencePositions(), tder, direction, true ); double scale=1.0; if( anflag ) scale = 1.0 / static_cast( pos.size() ); - for(unsigned i=0;i& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { +double SimpleRMSD::projectAtomicDisplacementOnVector( const std::vector& vecs, const std::vector& pos, ReferenceValuePack& mypack ) const { plumed_dbg_assert( mypack.calcUsingPCAOption() ); Vector comder; comder.zero(); - for(unsigned j=0;j& conf, const std::vector& align_in, const std::vector& displace_in ){ - reference_atoms.resize( conf.size() ); align.resize( conf.size() ); +void SingleDomainRMSD::setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ) { + reference_atoms.resize( conf.size() ); align.resize( conf.size() ); displace.resize( conf.size() ); atom_der_index.resize( conf.size() ); - double wa=0, wd=0; - for(unsigned i=0;i& pos, const Pbc& p return calc( pos, pbc, myder, squared ); } -double SingleDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, +double SingleDomainRMSD::calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const { plumed_dbg_assert( vals.size()==0 && pos.size()==getNumberOfAtoms() && arg.size()==0 ); return calc( pos, pbc, myder, squared ); diff --git a/src/reference/SingleDomainRMSD.h b/src/reference/SingleDomainRMSD.h index 9c6369e55a..9ecf96123d 100644 --- a/src/reference/SingleDomainRMSD.h +++ b/src/reference/SingleDomainRMSD.h @@ -36,14 +36,14 @@ class SingleDomainRMSD : public ReferenceAtoms { /// Set the reference structure virtual void setReferenceAtoms( const std::vector& conf, const std::vector& align_in, const std::vector& displace_in ); /// Calculate - double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const; + double calc( const std::vector& pos, const Pbc& pbc, const std::vector& vals, const std::vector& arg, ReferenceValuePack& myder, const bool& squared ) const; double calculate( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const; /// Calculate the distance using the input position virtual double calc( const std::vector& pos, const Pbc& pbc, ReferenceValuePack& myder, const bool& squared ) const=0; /// This sets upper and lower bounds on distances to be used in DRMSD (here it does nothing) - virtual void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits::max( ) ){}; + virtual void setBoundsOnDistances( bool dopbc, double lbound=0.0, double ubound=std::numeric_limits::max( ) ) {}; /// This is used by MultiDomainRMSD to setup the RMSD object in Optimal RMSD type - virtual void setupRMSDObject(){}; + virtual void setupRMSDObject() {}; }; } diff --git a/src/secondarystructure/AlphaRMSD.cpp b/src/secondarystructure/AlphaRMSD.cpp index 0f29dc024c..6c9b49083e 100644 --- a/src/secondarystructure/AlphaRMSD.cpp +++ b/src/secondarystructure/AlphaRMSD.cpp @@ -34,13 +34,13 @@ Probe the alpha helical content of a protein structure. Any chain of six contiguous residues in a protein chain can form an alpha helix. This colvar thus generates the set of all possible six residue sections and calculates the RMSD distance between the configuration in which the residues find themselves -and an idealized alpha helical structure. These distances can be calculated by either +and an idealized alpha helical structure. These distances can be calculated by either aligning the instantaneous structure with the reference structure and measuring each atomic displacement or by calculating differences between the set of interatomic -distances in the reference and instantaneous structures. +distances in the reference and instantaneous structures. -This colvar is based on the following reference \cite pietrucci09jctc. The authors of -this paper use the set of distances from the alpha helix configurations to measure +This colvar is based on the following reference \cite pietrucci09jctc. The authors of +this paper use the set of distances from the alpha helix configurations to measure the number of segments that have an alpha helical configuration. This is done by calculating the following sum of functions of the rmsd distances: @@ -48,24 +48,24 @@ the following sum of functions of the rmsd distances: s = \sum_i \frac{ 1 - \left(\frac{r_i-d_0}{r_0}\right)^n } { 1 - \left(\frac{r_i-d_0}{r_0}\right)^m } \f] -where the sum runs over all possible segments of alpha helix. By default the +where the sum runs over all possible segments of alpha helix. By default the NN, MM and D_0 parameters are set equal to those used in \cite pietrucci09jctc. The R_0 parameter must be set by the user - the value used in \cite pietrucci09jctc was 0.08 nm. If you change the function in the above sum you can calculate quantities such as the average -distance from a purely the alpha helical configuration or the distance between the set of -residues that is closest to an alpha helix and the reference configuration. To do these sorts of +distance from a purely the alpha helical configuration or the distance between the set of +residues that is closest to an alpha helix and the reference configuration. To do these sorts of calculations you can use the AVERAGE and MIN keywords. In addition you can use the LESS_THAN keyword if you would like to change the form of the switching function. If you use any of these -options you no longer need to specify NN, R_0, MM and D_0. +options you no longer need to specify NN, R_0, MM and D_0. -Please be aware that for codes like gromacs you must ensure that plumed +Please be aware that for codes like gromacs you must ensure that plumed reconstructs the chains involved in your CV when you calculate this CV using anthing other than TYPE=DRMSD. For more details as to how to do this see \ref WHOLEMOLECULES. \par Examples -The following input calculates the number of six residue segments of +The following input calculates the number of six residue segments of protein that are in an alpha helical configuration. \verbatim @@ -81,33 +81,33 @@ class AlphaRMSD : public SecondaryStructureRMSD { public: static void registerKeywords( Keywords& keys ); explicit AlphaRMSD(const ActionOptions&); -}; +}; PLUMED_REGISTER_ACTION(AlphaRMSD,"ALPHARMSD") -void AlphaRMSD::registerKeywords( Keywords& keys ){ +void AlphaRMSD::registerKeywords( Keywords& keys ) { SecondaryStructureRMSD::registerKeywords( keys ); } AlphaRMSD::AlphaRMSD(const ActionOptions&ao): -Action(ao), -SecondaryStructureRMSD(ao) + Action(ao), + SecondaryStructureRMSD(ao) { // read in the backbone atoms std::vector chains; readBackboneAtoms( "protein", chains); // This constructs all conceivable sections of alpha helix in the backbone of the chains unsigned nres, nprevious=0; std::vector nlist(30); - for(unsigned i=0;i chains; readBackboneAtoms( "protein", chains ); - bool intra_chain(false), inter_chain(false); + bool intra_chain(false), inter_chain(false); std::string style; parse("STYLE",style); - if( style=="all" ){ - intra_chain=true; inter_chain=true; - } else if( style=="inter"){ - intra_chain=false; inter_chain=true; - } else if( style=="intra"){ - intra_chain=true; inter_chain=false; + if( style=="all" ) { + intra_chain=true; inter_chain=true; + } else if( style=="inter") { + intra_chain=false; inter_chain=true; + } else if( style=="intra") { + intra_chain=true; inter_chain=false; } else { - error( style + " is not a valid directive for the STYLE keyword"); + error( style + " is not a valid directive for the STYLE keyword"); } - + // Align the atoms based on the positions of these two atoms setAtomsFromStrands( 6, 21 ); // This constructs all conceivable sections of antibeta sheet in the backbone of the chains - if( intra_chain ){ + if( intra_chain ) { unsigned nres, nprevious=0; std::vector nlist(30); - for(unsigned i=0;i nlist(30); - for(unsigned ichain=1;ichain nlist(30); + for(unsigned ichain=1; ichain chains; readBackboneAtoms( "protein", chains ); - bool intra_chain(false), inter_chain(false); + bool intra_chain(false), inter_chain(false); std::string style; parse("STYLE",style); - if( style=="all" ){ - intra_chain=true; inter_chain=true; - } else if( style=="inter"){ - intra_chain=false; inter_chain=true; - } else if( style=="intra"){ - intra_chain=true; inter_chain=false; + if( style=="all" ) { + intra_chain=true; inter_chain=true; + } else if( style=="inter") { + intra_chain=false; inter_chain=true; + } else if( style=="intra") { + intra_chain=true; inter_chain=false; } else { - error( style + " is not a valid directive for the STYLE keyword"); + error( style + " is not a valid directive for the STYLE keyword"); } // Align the atoms based on the positions of these two atoms setAtomsFromStrands( 6, 21 ); // This constructs all conceivable sections of antibeta sheet in the backbone of the chains - if( intra_chain ){ + if( intra_chain ) { unsigned nres, nprevious=0; std::vector nlist(30); - for(unsigned i=0;i nlist(30); - for(unsigned ichain=1;ichain nlist(30); + for(unsigned ichain=1; ichainlabel.lessthan-1, label.lessthan-2 and so on unless you " "exploit the fact that these labels are customizable. In particular, by using the LABEL keyword in the " - "description of you LESS_THAN function you can set name of the component that you are calculating"); + "description of you LESS_THAN function you can set name of the component that you are calculating"); } SecondaryStructureRMSD::SecondaryStructureRMSD(const ActionOptions&ao): -Action(ao), -ActionAtomistic(ao), -ActionWithValue(ao), -ActionWithVessel(ao), -align_strands(false), -s_cutoff2(0), -align_atom_1(0), -align_atom_2(0) + Action(ao), + ActionAtomistic(ao), + ActionWithValue(ao), + ActionWithVessel(ao), + align_strands(false), + s_cutoff2(0), + align_atom_1(0), + align_atom_2(0) { parse("TYPE",alignType); log.printf(" distances from secondary structure elements are calculated using %s algorithm\n",alignType.c_str() ); log<<" Bibliography "<0) log.printf(" ignoring contributions from strands that are more than %f apart\n",s_cutoff); @@ -93,95 +93,95 @@ align_atom_2(0) } } -SecondaryStructureRMSD::~SecondaryStructureRMSD(){ - for(unsigned i=0;i& chain_lengths ){ +void SecondaryStructureRMSD::readBackboneAtoms( const std::string& moltype, std::vector& chain_lengths ) { std::vector moldat=plumed.getActionSet().select(); if( moldat.size()==0 ) error("Unable to find MOLINFO in input"); std::vector resstrings; parseVector( "RESIDUES", resstrings ); - if( !verbose_output ){ - if(resstrings[0]=="all"){ - log.printf(" examining all possible secondary structure combinations\n"); - } else { - log.printf(" examining secondary structure in residue positions : %s \n",resstrings[0].c_str() ); - for(unsigned i=1;i > backatoms; moldat[0]->getBackbone( resstrings, moltype, backatoms ); chain_lengths.resize( backatoms.size() ); - for(unsigned i=0;i& newatoms ){ +void SecondaryStructureRMSD::addColvar( const std::vector& newatoms ) { if( colvar_atoms.size()>0 ) plumed_assert( colvar_atoms[0].size()==newatoms.size() ); - if( verbose_output ){ - log.printf(" Secondary structure segment %u contains atoms : ", static_cast(colvar_atoms.size()+1)); - for(unsigned i=0;i(colvar_atoms.size()+1)); + for(unsigned i=0; i& structure, double bondlength, double units ){ +void SecondaryStructureRMSD::setSecondaryStructure( std::vector& structure, double bondlength, double units ) { // If we are in natural units get conversion factor from nm into natural length units - if( plumed.getAtoms().usingNaturalUnits() ){ - error("cannot use this collective variable when using natural units"); + if( plumed.getAtoms().usingNaturalUnits() ) { + error("cannot use this collective variable when using natural units"); } - plumed_massert( !(align_strands && align_atom_1==0 && align_atom_2==0), "you must use setAtomsFromStrands with strands cutoff"); + plumed_massert( !(align_strands && align_atom_1==0 && align_atom_2==0), "you must use setAtomsFromStrands with strands cutoff"); // Convert into correct units - for(unsigned i=0;i( alignType ) ); + references.push_back( metricRegister().create( alignType ) ); unsigned nn=references.size()-1; std::vector align( structure.size(), 1.0 ), displace( structure.size(), 1.0 ); - references[nn]->setBoundsOnDistances( true , bondlength ); // We always use pbc + references[nn]->setBoundsOnDistances( true, bondlength ); // We always use pbc references[nn]->setReferenceAtoms( structure, align, displace ); // references[nn]->setNumberOfAtoms( structure.size() ); // And prepare the task list deactivateAllTasks(); - for(unsigned i=0;i pos( references[0]->getNumberOfAtoms() ); const unsigned n=pos.size(); - for(unsigned i=0;i0 ){ - if( distance.modulo2()>s_cutoff2 ){ - myvals.setValue( 0, 0.0 ); - return; - } + Vector distance=pbcDistance( pos[align_atom_1],pos[align_atom_2] ); + if( s_cutoff2>0 ) { + if( distance.modulo2()>s_cutoff2 ) { + myvals.setValue( 0, 0.0 ); + return; + } } // This aligns the two strands if this is required - if( alignType!="DRMSD" && align_strands ){ - Vector origin_old, origin_new; origin_old=pos[align_atom_2]; - origin_new=pos[align_atom_1]+distance; - for(unsigned i=15;i<30;++i){ - pos[i]+=( origin_new - origin_old ); - } + if( alignType!="DRMSD" && align_strands ) { + Vector origin_old, origin_new; origin_old=pos[align_atom_2]; + origin_new=pos[align_atom_1]+distance; + for(unsigned i=15; i<30; ++i) { + pos[i]+=( origin_new - origin_old ); + } } // Create a holder for the derivatives ReferenceValuePack mypack( 0, pos.size(), myvals ); mypack.setValIndex( 1 ); - for(unsigned i=0;icalculate( pos, pbc, mypack, false ); const unsigned rs = references.size(); - for(unsigned i=1;icalculate( pos, pbc, mypack, false ); - if( nr0 ) mypack.moveDerivatives( closest+1, 1 ); - if( !mypack.virialWasSet() ){ + if( !mypack.virialWasSet() ) { Tensor vir; const unsigned cacs = colvar_atoms[current].size(); - for(unsigned i=0;i -namespace PLMD{ +namespace PLMD { -double Angle::compute(const Vector& v1,const Vector& v2)const{ - return std::acos(dotProduct(v1,v2)/(v1.modulo()*v2.modulo())); +double Angle::compute(const Vector& v1,const Vector& v2)const { + return std::acos(dotProduct(v1,v2)/(v1.modulo()*v2.modulo())); } -double Angle::compute(const Vector& v1,const Vector& v2,Vector& d1,Vector& d2)const{ - const double dp(dotProduct(v1,v2)); - const Vector& dp_dv1(v2); - const Vector& dp_dv2(v1); - const double sv1(v1.modulo2()); - const double sv2(v2.modulo2()); - const Vector dsv1_dv1(2*v1); - const Vector dsv2_dv2(2*v2); - const double nn(1.0/sqrt(sv1*sv2)); - const Vector dnn_dv1(-0.5*nn/sv1*dsv1_dv1); - const Vector dnn_dv2(-0.5*nn/sv2*dsv2_dv2); +double Angle::compute(const Vector& v1,const Vector& v2,Vector& d1,Vector& d2)const { + const double dp(dotProduct(v1,v2)); + const Vector& dp_dv1(v2); + const Vector& dp_dv2(v1); + const double sv1(v1.modulo2()); + const double sv2(v2.modulo2()); + const Vector dsv1_dv1(2*v1); + const Vector dsv2_dv2(2*v2); + const double nn(1.0/sqrt(sv1*sv2)); + const Vector dnn_dv1(-0.5*nn/sv1*dsv1_dv1); + const Vector dnn_dv2(-0.5*nn/sv2*dsv2_dv2); - const double dpnn(dp*nn); + const double dpnn(dp*nn); - if(dpnn>=1.0-epsilon){ - d1=Vector(0.0,0.0,0.0); - d2=Vector(0.0,0.0,0.0); - return 0.0; - } - if(dpnn<=-1.0+epsilon){ - d1=Vector(0.0,0.0,0.0); - d2=Vector(0.0,0.0,0.0); - return pi; - } - const Vector ddpnn_dv1(dp*dnn_dv1+dp_dv1*nn); - const Vector ddpnn_dv2(dp*dnn_dv2+dp_dv2*nn); + if(dpnn>=1.0-epsilon) { + d1=Vector(0.0,0.0,0.0); + d2=Vector(0.0,0.0,0.0); + return 0.0; + } + if(dpnn<=-1.0+epsilon) { + d1=Vector(0.0,0.0,0.0); + d2=Vector(0.0,0.0,0.0); + return pi; + } + const Vector ddpnn_dv1(dp*dnn_dv1+dp_dv1*nn); + const Vector ddpnn_dv2(dp*dnn_dv2+dp_dv2*nn); - const double x(-1.0/sqrt(1-dpnn*dpnn)); + const double x(-1.0/sqrt(1-dpnn*dpnn)); - d1=x*ddpnn_dv1; - d2=x*ddpnn_dv2; + d1=x*ddpnn_dv1; + d2=x*ddpnn_dv2; - return std::acos(dpnn); + return std::acos(dpnn); } } diff --git a/src/tools/Angle.h b/src/tools/Angle.h index 9a9f2b2000..1d6a58e520 100644 --- a/src/tools/Angle.h +++ b/src/tools/Angle.h @@ -24,7 +24,7 @@ #include "Vector.h" -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX /// Class to compute angles. @@ -36,7 +36,7 @@ namespace PLMD{ /// I know it is a bit misleading. If we really do not need to store "options" /// inside the Angle class, we can remove it later and write compute as /// a static function. -class Angle{ +class Angle { // still empty, but may accomodate some options in the future public: /// Compute the angle between vectors v1 and v2 diff --git a/src/tools/AtomNumber.h b/src/tools/AtomNumber.h index b150189306..60eb9ca775 100644 --- a/src/tools/AtomNumber.h +++ b/src/tools/AtomNumber.h @@ -25,7 +25,7 @@ #include "Exception.h" #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -36,7 +36,7 @@ namespace PLMD{ no ambiguity about using the "from 0" (index) or "from 1" (serial) numbering (names as in VMD convention). */ -class AtomNumber{ +class AtomNumber { unsigned index_; /// Construct with a given index. /// This constructor is kept private to avoid implicit cast. @@ -71,27 +71,27 @@ class AtomNumber{ }; inline -AtomNumber::AtomNumber(){ +AtomNumber::AtomNumber() { index_=0; } inline -AtomNumber::AtomNumber(unsigned i){ +AtomNumber::AtomNumber(unsigned i) { index_=i; } inline -unsigned AtomNumber::serial()const{ +unsigned AtomNumber::serial()const { return index_+1; } inline -unsigned AtomNumber::index()const{ +unsigned AtomNumber::index()const { return index_; } inline -AtomNumber & AtomNumber::setSerial(unsigned i){ +AtomNumber & AtomNumber::setSerial(unsigned i) { plumed_massert(i>0,"serial of an atom cannot be zero"); plumed_massert(i::max()/2,"serial cannot be negative"); index_=i-1; @@ -99,50 +99,50 @@ AtomNumber & AtomNumber::setSerial(unsigned i){ } inline -AtomNumber & AtomNumber::setIndex(unsigned i){ +AtomNumber & AtomNumber::setIndex(unsigned i) { index_=i; return *this; } inline -AtomNumber AtomNumber::serial(unsigned i){ +AtomNumber AtomNumber::serial(unsigned i) { plumed_massert(i>0,"serial of an atom cannot be zero"); plumed_massert(i::max()/2,"serial cannot be negative"); return AtomNumber(i-1); } inline -AtomNumber AtomNumber::index(unsigned i){ +AtomNumber AtomNumber::index(unsigned i) { return AtomNumber(i); } inline -bool operator<(const AtomNumber&a,const AtomNumber&b){ +bool operator<(const AtomNumber&a,const AtomNumber&b) { return a.index_(const AtomNumber&a,const AtomNumber&b){ +bool operator>(const AtomNumber&a,const AtomNumber&b) { return a.index_>b.index_; } inline -bool operator<=(const AtomNumber&a,const AtomNumber&b){ +bool operator<=(const AtomNumber&a,const AtomNumber&b) { return a.index_<=b.index_; } inline -bool operator>=(const AtomNumber&a,const AtomNumber&b){ +bool operator>=(const AtomNumber&a,const AtomNumber&b) { return a.index_>=b.index_; } inline -bool operator==(const AtomNumber&a,const AtomNumber&b){ +bool operator==(const AtomNumber&a,const AtomNumber&b) { return a.index_==b.index_; } inline -bool operator!=(const AtomNumber&a,const AtomNumber&b){ +bool operator!=(const AtomNumber&a,const AtomNumber&b) { return a.index_!=b.index_; } diff --git a/src/tools/BiasRepresentation.cpp b/src/tools/BiasRepresentation.cpp index 89ae941a56..d37be2916f 100644 --- a/src/tools/BiasRepresentation.cpp +++ b/src/tools/BiasRepresentation.cpp @@ -29,247 +29,247 @@ namespace PLMD { using namespace std; /// the constructor here -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc ):hasgrid(false),rescaledToBias(false),mycomm(cc),BiasGrid_(NULL){ - lowI_=0.0; - uppI_=0.0; - doInt_=false; - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc ):hasgrid(false),rescaledToBias(false),mycomm(cc),BiasGrid_(NULL) { + lowI_=0.0; + uppI_=0.0; + doInt_=false; + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } +} +/// overload the constructor: add the sigma at constructor time +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & sigma ):hasgrid(false), rescaledToBias(false), histosigma(sigma),mycomm(cc),BiasGrid_(NULL) { + lowI_=0.0; + uppI_=0.0; + doInt_=false; + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } +} +/// overload the constructor: add the grid at constructor time +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & gmin, const vector & gmax, + const vector & nbin, bool doInt, double lowI, double uppI ):hasgrid(false), rescaledToBias(false), mycomm(cc), BiasGrid_(NULL) { + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } + doInt_=doInt; + lowI_=lowI; + uppI_=uppI; + // initialize the grid + addGrid(gmin,gmax,nbin); } -/// overload the constructor: add the sigma at constructor time -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & sigma ):hasgrid(false), rescaledToBias(false), histosigma(sigma),mycomm(cc),BiasGrid_(NULL){ - lowI_=0.0; - uppI_=0.0; - doInt_=false; - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } -} -/// overload the constructor: add the grid at constructor time -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc , const vector & gmin, const vector & gmax, - const vector & nbin, bool doInt, double lowI, double uppI ):hasgrid(false), rescaledToBias(false), mycomm(cc), BiasGrid_(NULL){ - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } - doInt_=doInt; - lowI_=lowI; - uppI_=uppI; - // initialize the grid - addGrid(gmin,gmax,nbin); -} /// overload the constructor with some external sigmas: needed for histogram -BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc , const vector & gmin, const vector & gmax, const vector & nbin , const vector & sigma):hasgrid(false), rescaledToBias(false),histosigma(sigma),mycomm(cc),BiasGrid_(NULL){ - lowI_=0.0; - uppI_=0.0; - doInt_=false; - ndim=tmpvalues.size(); - for(int i=0;igetName()); - } - // initialize the grid - addGrid(gmin,gmax,nbin); +BiasRepresentation::BiasRepresentation(const vector & tmpvalues, Communicator &cc, const vector & gmin, const vector & gmax, const vector & nbin, const vector & sigma):hasgrid(false), rescaledToBias(false),histosigma(sigma),mycomm(cc),BiasGrid_(NULL) { + lowI_=0.0; + uppI_=0.0; + doInt_=false; + ndim=tmpvalues.size(); + for(int i=0; igetName()); + } + // initialize the grid + addGrid(gmin,gmax,nbin); } -BiasRepresentation::~BiasRepresentation(){ +BiasRepresentation::~BiasRepresentation() { if(BiasGrid_) delete BiasGrid_; - for(unsigned i=0;i & gmin, const vector & gmax, const vector & nbin ){ - plumed_massert(hills.size()==0,"you can set the grid before loading the hills"); - plumed_massert(hasgrid==false,"to build the grid you should not having the grid in this bias representation"); - string ss; ss="file.free"; - vector vv;for(unsigned i=0;i & gmin, const vector & gmax, const vector & nbin ) { + plumed_massert(hills.size()==0,"you can set the grid before loading the hills"); + plumed_massert(hasgrid==false,"to build the grid you should not having the grid in this bias representation"); + string ss; ss="file.free"; + vector vv; for(unsigned i=0; i BiasRepresentation::getNames(){ - return names; -} -const string & BiasRepresentation::getName(unsigned i){ - return names[i]; -} +unsigned BiasRepresentation::getNumberOfDimensions() { + return values.size(); +} +vector BiasRepresentation::getNames() { + return names; +} +const string & BiasRepresentation::getName(unsigned i) { + return names[i]; +} -const vector& BiasRepresentation::getPtrToValues(){ - return values; -} -Value* BiasRepresentation::getPtrToValue(unsigned i){ - return values[i]; -} +const vector& BiasRepresentation::getPtrToValues() { + return values; +} +Value* BiasRepresentation::getPtrToValue(unsigned i) { + return values[i]; +} -KernelFunctions* BiasRepresentation::readFromPoint(IFile *ifile){ - vector cc( names.size() ); - for(unsigned i=0;iscanField(names[i],cc[i]); - } - double h=1.0; - return new KernelFunctions(cc,histosigma,"gaussian",false,h,false); +KernelFunctions* BiasRepresentation::readFromPoint(IFile *ifile) { + vector cc( names.size() ); + for(unsigned i=0; iscanField(names[i],cc[i]); + } + double h=1.0; + return new KernelFunctions(cc,histosigma,"gaussian",false,h,false); } -void BiasRepresentation::pushKernel( IFile *ifile ){ - KernelFunctions *kk=NULL; - // here below the reading of the kernel is completely hidden - if(histosigma.size()==0){ - ifile->allowIgnoredFields(); - kk=KernelFunctions::read(ifile,names) ; - }else{ - // when doing histogram assume gaussian with a given diagonal sigma - // and neglect all the rest - kk=readFromPoint(ifile) ; - } - hills.push_back(kk); - // the bias factor is not something about the kernels but - // must be stored to keep the bias/free energy duality - string dummy; double dummyd; - if(ifile->FieldExist("biasf")){ - ifile->scanField("biasf",dummy); - Tools::convert(dummy,dummyd); - }else{dummyd=1.0;} - biasf.push_back(dummyd); - // the domain does not pertain to the kernel but to the values here defined - string mins,maxs,minv,maxv,mini,maxi;mins="min_";maxs="max_"; - for(int i=0 ; iisPeriodic()){ - ifile->scanField(mins+names[i],minv); - ifile->scanField(maxs+names[i],maxv); - // verify that the domain is correct - values[i]->getDomain(mini,maxi); - plumed_massert(mini==minv,"the input periodicity in hills and in value definition does not match" ); - plumed_massert(maxi==maxv,"the input periodicity in hills and in value definition does not match" ); - } +void BiasRepresentation::pushKernel( IFile *ifile ) { + KernelFunctions *kk=NULL; + // here below the reading of the kernel is completely hidden + if(histosigma.size()==0) { + ifile->allowIgnoredFields(); + kk=KernelFunctions::read(ifile,names) ; + } else { + // when doing histogram assume gaussian with a given diagonal sigma + // and neglect all the rest + kk=readFromPoint(ifile) ; + } + hills.push_back(kk); + // the bias factor is not something about the kernels but + // must be stored to keep the bias/free energy duality + string dummy; double dummyd; + if(ifile->FieldExist("biasf")) { + ifile->scanField("biasf",dummy); + Tools::convert(dummy,dummyd); + } else {dummyd=1.0;} + biasf.push_back(dummyd); + // the domain does not pertain to the kernel but to the values here defined + string mins,maxs,minv,maxv,mini,maxi; mins="min_"; maxs="max_"; + for(int i=0 ; iisPeriodic()) { + ifile->scanField(mins+names[i],minv); + ifile->scanField(maxs+names[i],maxv); + // verify that the domain is correct + values[i]->getDomain(mini,maxi); + plumed_massert(mini==minv,"the input periodicity in hills and in value definition does not match" ); + plumed_massert(maxi==maxv,"the input periodicity in hills and in value definition does not match" ); + } + } + // if grid is defined then it should be added on the grid + //cerr<<"now with "< nneighb; + if(doInt_&&(kk->getCenter()[0]+kk->getContinuousSupport()[0] > uppI_ || kk->getCenter()[0]-kk->getContinuousSupport()[0] < lowI_ )) { + nneighb=BiasGrid_->getNbin(); + } else nneighb=kk->getSupport(BiasGrid_->getDx()); + vector neighbors=BiasGrid_->getNeighbors(kk->getCenter(),nneighb); + vector der(ndim); + vector xx(ndim); + if(mycomm.Get_size()==1) { + for(unsigned i=0; igetPoint(ineigh,xx); + // assign xx to a new vector of values + for(int j=0; jset(xx[j]);} + double bias; + if(doInt_) bias=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); + else bias=kk->evaluate(values,der,true); + if(rescaledToBias) { + double f=(biasf.back()-1.)/(biasf.back()); + bias*=f; + for(int j=0; j nneighb; - if(doInt_&&(kk->getCenter()[0]+kk->getContinuousSupport()[0] > uppI_ || kk->getCenter()[0]-kk->getContinuousSupport()[0] < lowI_ )) { - nneighb=BiasGrid_->getNbin(); - } else nneighb=kk->getSupport(BiasGrid_->getDx()); - vector neighbors=BiasGrid_->getNeighbors(kk->getCenter(),nneighb); - vector der(ndim); - vector xx(ndim); - if(mycomm.Get_size()==1){ - for(unsigned i=0;igetPoint(ineigh,xx); - // assign xx to a new vector of values - for(int j=0;jset(xx[j]);} - double bias; - if(doInt_) bias=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); - else bias=kk->evaluate(values,der,true); - if(rescaledToBias){ - double f=(biasf.back()-1.)/(biasf.back()); - bias*=f; - for(int j=0;jaddValueAndDerivatives(ineigh,bias,der); - } - } else { - unsigned stride=mycomm.Get_size(); - unsigned rank=mycomm.Get_rank(); - vector allder(ndim*neighbors.size(),0.0); - vector allbias(neighbors.size(),0.0); - vector tmpder(ndim); - for(unsigned i=rank;igetPoint(ineigh,xx); - for(int j=0;jset(xx[j]);} - if(doInt_) allbias[i]=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); - else allbias[i]=kk->evaluate(values,der,true); - if(rescaledToBias){ - double f=(biasf.back()-1.)/(biasf.back()); - allbias[i]*=f; - for(int j=0;jaddValueAndDerivatives(ineigh,allbias[i],der); - } - } + BiasGrid_->addValueAndDerivatives(ineigh,bias,der); + } + } else { + unsigned stride=mycomm.Get_size(); + unsigned rank=mycomm.Get_rank(); + vector allder(ndim*neighbors.size(),0.0); + vector allbias(neighbors.size(),0.0); + vector tmpder(ndim); + for(unsigned i=rank; igetPoint(ineigh,xx); + for(int j=0; jset(xx[j]);} + if(doInt_) allbias[i]=kk->evaluate(values,der,true,doInt_,lowI_,uppI_); + else allbias[i]=kk->evaluate(values,der,true); + if(rescaledToBias) { + double f=(biasf.back()-1.)/(biasf.back()); + allbias[i]*=f; + for(int j=0; jaddValueAndDerivatives(ineigh,allbias[i],der); + } + } + } } -int BiasRepresentation::getNumberOfKernels(){ - return hills.size(); +int BiasRepresentation::getNumberOfKernels() { + return hills.size(); } -Grid* BiasRepresentation::getGridPtr(){ - plumed_massert(hasgrid,"if you want the grid pointer then you should have defined a grid before"); - return BiasGrid_; +Grid* BiasRepresentation::getGridPtr() { + plumed_massert(hasgrid,"if you want the grid pointer then you should have defined a grid before"); + return BiasGrid_; } -void BiasRepresentation::getMinMaxBin(vector &vmin, vector &vmax, vector &vbin){ - vector ss,cc,binsize; - vmin.clear();vmin.resize(ndim,10.e20); - vmax.clear();vmax.resize(ndim,-10.e20); - vbin.clear();vbin.resize(ndim); - binsize.clear();binsize.resize(ndim,10.e20); - int ndiv=10; // adjustable parameter: division per support - for(unsigned i=0;igetContinuousSupport(); - } - cc=hills[i]->getCenter(); - for(int j=0;jvmax[j])vmax[j]=dmax; - if(ddivisPeriodic()){ - double minv,maxv; - values[j]->getDomain(minv,maxv); - if(minv>vmin[j])vmin[j]=minv; - if(maxv(ceil((vmax[j]-vmin[j])/binsize[j]) ); - } +void BiasRepresentation::getMinMaxBin(vector &vmin, vector &vmax, vector &vbin) { + vector ss,cc,binsize; + vmin.clear(); vmin.resize(ndim,10.e20); + vmax.clear(); vmax.resize(ndim,-10.e20); + vbin.clear(); vbin.resize(ndim); + binsize.clear(); binsize.resize(ndim,10.e20); + int ndiv=10; // adjustable parameter: division per support + for(unsigned i=0; igetContinuousSupport(); + } + cc=hills[i]->getCenter(); + for(int j=0; jvmax[j])vmax[j]=dmax; + if(ddivisPeriodic()) { + double minv,maxv; + values[j]->getDomain(minv,maxv); + if(minv>vmin[j])vmin[j]=minv; + if(maxv(ceil((vmax[j]-vmin[j])/binsize[j]) ); + } } -void BiasRepresentation::clear(){ - // clear the hills - for(const auto & it : hills) - { - delete it; - } - hills.clear(); - // clear the grid - if(hasgrid){ - BiasGrid_->clear(); - } +void BiasRepresentation::clear() { + // clear the hills + for(const auto & it : hills) + { + delete it; + } + hills.clear(); + // clear the grid + if(hasgrid) { + BiasGrid_->clear(); + } } diff --git a/src/tools/BiasRepresentation.h b/src/tools/BiasRepresentation.h index a66bf3778e..9533e53c49 100644 --- a/src/tools/BiasRepresentation.h +++ b/src/tools/BiasRepresentation.h @@ -27,75 +27,75 @@ #include "File.h" #include "Grid.h" -namespace PLMD{ +namespace PLMD { -//+PLUMEDOC INTERNAL biasrepresentation +//+PLUMEDOC INTERNAL biasrepresentation /* */ //+ENDPLUMEDOC -/// this class implements a general purpose class that aims to -/// provide a Grid/list -/// transparently add gaussians to a bias +/// this class implements a general purpose class that aims to +/// provide a Grid/list +/// transparently add gaussians to a bias class BiasRepresentation { - public: - /// create a bias representation from a list of pointer to values - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc ); - /// create a bias using explicit sigma in input (needed for histogram building) - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc , const std::vector & sigma); - /// create a bias containing a grid representation - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc , const std::vector & gmin, const std::vector & gmax, - const std::vector & nbin, bool doInt, double lowI_, double uppI_); - /// create a histogram with grid representation and sigmas in input - BiasRepresentation(const std::vector & tmpvalues, Communicator &cc , const std::vector & gmin, const std::vector & gmax, const std::vector & nbin , const std::vector & sigma); - /// destructor - ~BiasRepresentation(); - /// retrieve the number of dimension of the representation - unsigned getNumberOfDimensions(); - /// add the grid to the representation - void addGrid(const std::vector & gmin, const std::vector & gmax, const std::vector & nbin ); - /// push a kernel on the representation (includes widths and height) - void pushKernel( IFile * ff); - /// set the flag that rescales the free energy to the bias - void setRescaledToBias(bool rescaled); - /// check if the representation is rescaled to the bias - const bool & isRescaledToBias(); - /// check if the sigma values are already provided (in case of a histogram representation with input sigmas) - bool hasSigmaInInput(); - /// get the names of the variables - std::vector getNames(); - /// get the pointer to the values - const std::vector & getPtrToValues(); - /// get the number of kernels contained in the representation - int getNumberOfKernels(); - /// get the name of the i-th value - const std::string & getName(unsigned i); - /// get a pointer to a specific value - Value* getPtrToValue(unsigned i); - /// get the pointer to the grid - Grid* getGridPtr(); - /// get a new histogram point from a file - KernelFunctions* readFromPoint(IFile *ifile); - /// get an automatic min/max from the set so to know how to configure the grid - void getMinMaxBin(std::vector &vmin, std::vector &vmax, std::vector &vbin); - /// clear the representation (grid included) - void clear(); - private: - int ndim; - bool hasgrid; - bool rescaledToBias; - bool doInt_; - double lowI_; - double uppI_; - std::vector values; - std::vector names; - std::vector hills; - std::vector biasf; - std::vector histosigma; - Communicator& mycomm; - Grid* BiasGrid_; +public: + /// create a bias representation from a list of pointer to values + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc ); + /// create a bias using explicit sigma in input (needed for histogram building) + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc, const std::vector & sigma); + /// create a bias containing a grid representation + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc, const std::vector & gmin, const std::vector & gmax, + const std::vector & nbin, bool doInt, double lowI_, double uppI_); + /// create a histogram with grid representation and sigmas in input + BiasRepresentation(const std::vector & tmpvalues, Communicator &cc, const std::vector & gmin, const std::vector & gmax, const std::vector & nbin, const std::vector & sigma); + /// destructor + ~BiasRepresentation(); + /// retrieve the number of dimension of the representation + unsigned getNumberOfDimensions(); + /// add the grid to the representation + void addGrid(const std::vector & gmin, const std::vector & gmax, const std::vector & nbin ); + /// push a kernel on the representation (includes widths and height) + void pushKernel( IFile * ff); + /// set the flag that rescales the free energy to the bias + void setRescaledToBias(bool rescaled); + /// check if the representation is rescaled to the bias + const bool & isRescaledToBias(); + /// check if the sigma values are already provided (in case of a histogram representation with input sigmas) + bool hasSigmaInInput(); + /// get the names of the variables + std::vector getNames(); + /// get the pointer to the values + const std::vector & getPtrToValues(); + /// get the number of kernels contained in the representation + int getNumberOfKernels(); + /// get the name of the i-th value + const std::string & getName(unsigned i); + /// get a pointer to a specific value + Value* getPtrToValue(unsigned i); + /// get the pointer to the grid + Grid* getGridPtr(); + /// get a new histogram point from a file + KernelFunctions* readFromPoint(IFile *ifile); + /// get an automatic min/max from the set so to know how to configure the grid + void getMinMaxBin(std::vector &vmin, std::vector &vmax, std::vector &vbin); + /// clear the representation (grid included) + void clear(); +private: + int ndim; + bool hasgrid; + bool rescaledToBias; + bool doInt_; + double lowI_; + double uppI_; + std::vector values; + std::vector names; + std::vector hills; + std::vector biasf; + std::vector histosigma; + Communicator& mycomm; + Grid* BiasGrid_; }; } diff --git a/src/tools/Brent1DRootSearch.h b/src/tools/Brent1DRootSearch.h index 39ccdfcc4e..138760737c 100644 --- a/src/tools/Brent1DRootSearch.h +++ b/src/tools/Brent1DRootSearch.h @@ -27,7 +27,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /// A class for doing parabolic interpolation and minimisation of /// 1D functions using Brent's method. @@ -40,7 +40,7 @@ class Brent1DRootSearch { double tol; /// Maximum number of interactions in line minimiser const unsigned ITMAX; -/// A small number that protects against trying to achieve fractional +/// A small number that protects against trying to achieve fractional /// accuracy for a minimum that happens to be exactly zero const double EPS; /// The factor by which to expand the range when bracketing @@ -53,67 +53,67 @@ class Brent1DRootSearch { FCLASS myclass_func; public: explicit Brent1DRootSearch( const FCLASS& pf, const double& t=3.0E-8 ); -/// Bracket the minium +/// Bracket the minium void bracket( const double& ax, const double& xx, eng_pointer eng ); /// Find the minimum between two brackets - double search( eng_pointer eng ); + double search( eng_pointer eng ); }; template Brent1DRootSearch::Brent1DRootSearch( const FCLASS& pf, const double& t ): -bracketed(false), -tol(t), -ITMAX(100), -EPS(3.0E-8), -EXPAND(1.6), -ax(0), bx(0), -fa(0), fb(0), -myclass_func(pf) + bracketed(false), + tol(t), + ITMAX(100), + EPS(3.0E-8), + EXPAND(1.6), + ax(0), bx(0), + fa(0), fb(0), + myclass_func(pf) { } template -void Brent1DRootSearch::bracket( const double& a, const double& b, eng_pointer eng ){ - plumed_assert( a!=b ); ax=a; bx=b; fa=(myclass_func.*eng)(a); fb=(myclass_func.*eng)(b); - if ((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0)) plumed_merror("input points do not bracket root"); - bracketed=true; +void Brent1DRootSearch::bracket( const double& a, const double& b, eng_pointer eng ) { + plumed_assert( a!=b ); ax=a; bx=b; fa=(myclass_func.*eng)(a); fb=(myclass_func.*eng)(b); + if ((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0)) plumed_merror("input points do not bracket root"); + bracketed=true; } template -double Brent1DRootSearch::search( eng_pointer eng ){ - plumed_dbg_assert( bracketed ); +double Brent1DRootSearch::search( eng_pointer eng ) { + plumed_dbg_assert( bracketed ); - double cx=bx, d, e, min1, min2, fc=fb, p, q, r, s, tol1, xm; - for(unsigned iter=0;iter0.0 && fc>0.0) || (fb<0.0 && fc<0.0) ){ cx=ax; fc=fa; e=d=bx-ax; } - if( fabs(fc) < fabs(fb) ){ ax=bx; bx=cx; cx=ax; fa=fb; fb=fc; fc=fa; } - tol1=2*EPS*fabs(bx)+0.5*tol; xm=0.5*(cx-bx); - if( fabs(xm) <= tol1 || fb == 0.0 ) return bx; - if( fabs(e) >= tol1 && fabs(fa) > fabs(fb) ){ - s=fb/fa; - if( ax==cx ){ - p=2.0*xm*s; q=1.0-s; - } else { - q=fa/fc; r=fb/fc; p=s*(2.0*xm*q*(q-r)-(bx-ax)*(r-1.0)); q=(q-1.0)*(r-1.0)*(s-1.0); - } - if (p > 0.0) q = -q; - p=fabs(p); min1=3.0*xm*q-fabs(tol1*q); min2=fabs(e*q); - if (2.0*p < (min1 < min2 ? min1 : min2)) { - e=d; d=p/q; - } else { - d=xm; e=d; - } + double cx=bx, d, e, min1, min2, fc=fb, p, q, r, s, tol1, xm; + for(unsigned iter=0; iter0.0 && fc>0.0) || (fb<0.0 && fc<0.0) ) { cx=ax; fc=fa; e=d=bx-ax; } + if( fabs(fc) < fabs(fb) ) { ax=bx; bx=cx; cx=ax; fa=fb; fb=fc; fc=fa; } + tol1=2*EPS*fabs(bx)+0.5*tol; xm=0.5*(cx-bx); + if( fabs(xm) <= tol1 || fb == 0.0 ) return bx; + if( fabs(e) >= tol1 && fabs(fa) > fabs(fb) ) { + s=fb/fa; + if( ax==cx ) { + p=2.0*xm*s; q=1.0-s; } else { - d=xm; e=d; + q=fa/fc; r=fb/fc; p=s*(2.0*xm*q*(q-r)-(bx-ax)*(r-1.0)); q=(q-1.0)*(r-1.0)*(s-1.0); } - ax=bx; fa=fb; - if( fabs(d) > tol1 ) bx+=d; - else if(xm<0 ) bx -= fabs(tol1); // SIGN(tol1,xm); - else bx += tol1; - fb = (myclass_func.*eng)(bx); - } + if (p > 0.0) q = -q; + p=fabs(p); min1=3.0*xm*q-fabs(tol1*q); min2=fabs(e*q); + if (2.0*p < (min1 < min2 ? min1 : min2)) { + e=d; d=p/q; + } else { + d=xm; e=d; + } + } else { + d=xm; e=d; + } + ax=bx; fa=fb; + if( fabs(d) > tol1 ) bx+=d; + else if(xm<0 ) bx -= fabs(tol1); // SIGN(tol1,xm); + else bx += tol1; + fb = (myclass_func.*eng)(bx); + } - plumed_merror("Too many interactions in zbrent"); + plumed_merror("Too many interactions in zbrent"); } } diff --git a/src/tools/Citations.cpp b/src/tools/Citations.cpp index 0c320d4e91..508255c2c5 100644 --- a/src/tools/Citations.cpp +++ b/src/tools/Citations.cpp @@ -25,11 +25,11 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { -std::string Citations::cite(const std::string & item){ +std::string Citations::cite(const std::string & item) { unsigned i; - for(i=0;i #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -51,7 +51,7 @@ int main(int argc,char**argv){ \endverbatim */ -class Citations{ +class Citations { std::vector items; public: /// Add a citation. diff --git a/src/tools/Communicator.cpp b/src/tools/Communicator.cpp index e53b1db4df..ac10f3931a 100644 --- a/src/tools/Communicator.cpp +++ b/src/tools/Communicator.cpp @@ -25,11 +25,11 @@ using namespace std; -namespace PLMD{ +namespace PLMD { Communicator::Communicator() #ifdef __PLUMED_HAS_MPI -: communicator(MPI_COMM_SELF) + : communicator(MPI_COMM_SELF) #endif { } @@ -38,7 +38,7 @@ Communicator::Communicator() // Member variable 'Communicator::communicator' is not initialized in the constructor // this is a false positive so I suppress it // cppcheck-suppress uninitMemberVar -Communicator::Communicator(const Communicator&pc){ +Communicator::Communicator(const Communicator&pc) { Set_comm(pc.communicator); } @@ -48,14 +48,14 @@ Communicator::Status Communicator::StatusIgnore; // Member variable 'Communicator::communicator' is not assigned a value in 'Communicator::operator=' // this is a false positive so I suppress it // cppcheck-suppress operatorEqVarError -Communicator& Communicator::operator=(const Communicator&pc){ - if (this != &pc){ - Set_comm(pc.communicator); +Communicator& Communicator::operator=(const Communicator&pc) { + if (this != &pc) { + Set_comm(pc.communicator); } return *this; } -int Communicator::Get_rank()const{ +int Communicator::Get_rank()const { int r=0; #ifdef __PLUMED_HAS_MPI if(initialized()) MPI_Comm_rank(communicator,&r); @@ -63,7 +63,7 @@ int Communicator::Get_rank()const{ return r; } -Communicator& Communicator::Get_world(){ +Communicator& Communicator::Get_world() { static Communicator c; #ifdef __PLUMED_HAS_MPI if(initialized()) c.communicator=MPI_COMM_WORLD; @@ -72,7 +72,7 @@ Communicator& Communicator::Get_world(){ } -int Communicator::Get_size()const{ +int Communicator::Get_size()const { int s=1; #ifdef __PLUMED_HAS_MPI if(initialized()) MPI_Comm_size(communicator,&s); @@ -80,9 +80,9 @@ int Communicator::Get_size()const{ return s; } -void Communicator::Set_comm(MPI_Comm c){ +void Communicator::Set_comm(MPI_Comm c) { #ifdef __PLUMED_HAS_MPI - if(initialized()){ + if(initialized()) { if(communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator); if(c!=MPI_COMM_SELF) MPI_Comm_dup(c,&communicator); } @@ -91,26 +91,26 @@ void Communicator::Set_comm(MPI_Comm c){ #endif } -Communicator::~Communicator(){ +Communicator::~Communicator() { #ifdef __PLUMED_HAS_MPI if(initialized() && communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator); #endif } -void Communicator::Set_comm(void*val){ +void Communicator::Set_comm(void*val) { #ifdef __PLUMED_HAS_MPI - plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); - if(val) Set_comm(*(MPI_Comm*)val); + plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); + if(val) Set_comm(*(MPI_Comm*)val); #else - (void) val; - plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support"); + (void) val; + plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support"); #endif } -void Communicator::Set_fcomm(void*val){ +void Communicator::Set_fcomm(void*val) { #ifdef __PLUMED_HAS_MPI - plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); - if(val){ + plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); + if(val) { MPI_Comm comm=MPI_Comm_f2c(*(MPI_Fint*)val); Set_comm(comm); } @@ -120,9 +120,9 @@ void Communicator::Set_fcomm(void*val){ #endif } -void Communicator::Abort(int errorcode){ +void Communicator::Abort(int errorcode) { #ifdef __PLUMED_HAS_MPI - if(initialized()){ + if(initialized()) { MPI_Abort(communicator,errorcode); } std::exit(errorcode); @@ -133,7 +133,7 @@ void Communicator::Abort(int errorcode){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Bcast(Data data,int root){ +void Communicator::Bcast(Data data,int root) { #if defined(__PLUMED_HAS_MPI) if(initialized()) MPI_Bcast(data.pointer,data.size,data.type,root,communicator); #else @@ -144,7 +144,7 @@ void Communicator::Bcast(Data data,int root){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Sum(Data data){ +void Communicator::Sum(Data data) { #if defined(__PLUMED_HAS_MPI) if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_SUM,communicator); #else @@ -154,7 +154,7 @@ void Communicator::Sum(Data data){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -Communicator::Request Communicator::Isend(ConstData data,int source,int tag){ +Communicator::Request Communicator::Isend(ConstData data,int source,int tag) { Request req; #ifdef __PLUMED_HAS_MPI plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); @@ -171,7 +171,7 @@ Communicator::Request Communicator::Isend(ConstData data,int source,int tag){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs){ +void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs) { #if defined(__PLUMED_HAS_MPI) plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); void*s=const_cast((const void*)in.pointer); @@ -191,7 +191,7 @@ void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const i // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Allgather(ConstData in,Data out){ +void Communicator::Allgather(ConstData in,Data out) { #if defined(__PLUMED_HAS_MPI) plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); void*s=const_cast((const void*)in.pointer); @@ -207,7 +207,7 @@ void Communicator::Allgather(ConstData in,Data out){ // data should be passed by value to allow conversions // cppcheck-suppress passedByValue -void Communicator::Recv(Data data,int source,int tag,Status&status){ +void Communicator::Recv(Data data,int source,int tag,Status&status) { #ifdef __PLUMED_HAS_MPI plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); if(&status==&StatusIgnore) MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,MPI_STATUS_IGNORE); @@ -225,17 +225,17 @@ void Communicator::Recv(Data data,int source,int tag,Status&status){ -void Communicator::Barrier()const{ +void Communicator::Barrier()const { #ifdef __PLUMED_HAS_MPI if(initialized()) MPI_Barrier(communicator); #endif } -MPI_Comm & Communicator::Get_comm(){ - return communicator; +MPI_Comm & Communicator::Get_comm() { + return communicator; } -bool Communicator::initialized(){ +bool Communicator::initialized() { int flag=false; #if defined(__PLUMED_HAS_MPI) MPI_Initialized(&flag); @@ -244,9 +244,9 @@ bool Communicator::initialized(){ else return false; } -void Communicator::Request::wait(Status&s){ +void Communicator::Request::wait(Status&s) { #ifdef __PLUMED_HAS_MPI - plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); + plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); if(&s==&StatusIgnore) MPI_Wait(&r,MPI_STATUS_IGNORE); else MPI_Wait(&r,&s.s); #else @@ -256,23 +256,23 @@ void Communicator::Request::wait(Status&s){ } #ifdef __PLUMED_HAS_MPI -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_FLOAT;} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_DOUBLE;} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_FLOAT;} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_DOUBLE;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_INT;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_CHAR;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_UNSIGNED;} template<> MPI_Datatype Communicator::getMPIType() { return MPI_UNSIGNED_LONG;} #else -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} -template<> MPI_Datatype Communicator::getMPIType(){ return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} +template<> MPI_Datatype Communicator::getMPIType() { return MPI_Datatype();} #endif -void Communicator::Split(int color,int key,Communicator&pc)const{ +void Communicator::Split(int color,int key,Communicator&pc)const { #ifdef __PLUMED_HAS_MPI MPI_Comm_split(communicator,color,key,&pc.communicator); #else @@ -283,7 +283,7 @@ void Communicator::Split(int color,int key,Communicator&pc)const{ #endif } -int Communicator::Status::Get_count(MPI_Datatype type)const{ +int Communicator::Status::Get_count(MPI_Datatype type)const { int i; #ifdef __PLUMED_HAS_MPI plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized"); diff --git a/src/tools/Communicator.h b/src/tools/Communicator.h index d7be6e7cf8..86ef8314d6 100644 --- a/src/tools/Communicator.h +++ b/src/tools/Communicator.h @@ -32,23 +32,23 @@ #include "Tensor.h" #include "Matrix.h" -namespace PLMD{ +namespace PLMD { #ifndef __PLUMED_HAS_MPI /// Surrogate of MPI_Comm when MPI library is not available - class MPI_Comm {}; +class MPI_Comm {}; /// Surrogate of MPI_Datatype when MPI library is not available - class MPI_Datatype {}; +class MPI_Datatype {}; /// Surrogate of MPI_Status when MPI library is not available - class MPI_Status {}; +class MPI_Status {}; /// Surrogate of MPI_Request when MPI library is not available - class MPI_Request {}; +class MPI_Request {}; #endif /// \ingroup TOOLBOX /// Class containing wrappers to MPI. /// All the MPI related stuff is relegated here. -class Communicator{ +class Communicator { /// Communicator MPI_Comm communicator; /// Function returning the MPI type. @@ -62,7 +62,7 @@ class Communicator{ /// is grouped into a single object. It can be built starting from /// different kinds of data. To implement compatibility of MPI wrappers /// with e.g. vectors, add constructors here. - struct Data{ + struct Data { void*pointer; int size; MPI_Datatype type; @@ -71,32 +71,32 @@ class Communicator{ /// Init from reference template explicit Data(T&p): pointer(&p), size(1), type(getMPIType()) {} /// Init from pointer to VectorGeneric - template explicit Data(VectorGeneric *p,int s): pointer(p), size(n*s), type(getMPIType()) {} + template explicit Data(VectorGeneric *p,int s): pointer(p), size(n*s), type(getMPIType()) {} /// Init from reference to VectorGeneric - template explicit Data(VectorGeneric &p): pointer(&p), size(n), type(getMPIType()) {} + template explicit Data(VectorGeneric &p): pointer(&p), size(n), type(getMPIType()) {} /// Init from pointer to TensorGeneric - template explicit Data(TensorGeneric *p,int s): pointer(p), size(n*m*s), type(getMPIType()) {} + template explicit Data(TensorGeneric *p,int s): pointer(p), size(n*m*s), type(getMPIType()) {} /// Init from reference to TensorGeneric - template explicit Data(TensorGeneric &p): pointer(&p), size(n*m), type(getMPIType()) {} + template explicit Data(TensorGeneric &p): pointer(&p), size(n*m), type(getMPIType()) {} /// Init from reference to std::vector - template explicit Data(std::vector&v){ - if(v.size()>0){ Data d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } + template explicit Data(std::vector&v) { + if(v.size()>0) { Data d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } /// Init from reference to PLMD::Matrix - template explicit Data(Matrix&m ){ - if(m.nrows()*m.ncols()>0){ Data d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } - else{ pointer=NULL; size=0; } + template explicit Data(Matrix&m ) { + if(m.nrows()*m.ncols()>0) { Data d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } + else { pointer=NULL; size=0; } } /// Init from reference to std::string - explicit Data(std::string&s){ - if(s.size()>0){ Data d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } + explicit Data(std::string&s) { + if(s.size()>0) { Data d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } }; /// Const version of Communicator::Data /// See Communicator::Data documentation - struct ConstData{ + struct ConstData { const void*pointer; int size; MPI_Datatype type; @@ -106,27 +106,27 @@ class Communicator{ template explicit ConstData(const VectorGeneric &p): pointer(&p), size(n), type(getMPIType()) {} template explicit ConstData(const TensorGeneric *p,int s): pointer(p), size(n*m*s), type(getMPIType()) {} template explicit ConstData(const TensorGeneric &p): pointer(&p), size(n*m), type(getMPIType()) {} - template explicit ConstData(const std::vector&v){ - if(v.size()>0){ ConstData d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } + template explicit ConstData(const std::vector&v) { + if(v.size()>0) { ConstData d(&v[0],v.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } - template explicit ConstData(const Matrix&m ){ - if(m.nrows()*m.ncols()>0){ ConstData d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } - else{ pointer=NULL; size=0; } + template explicit ConstData(const Matrix&m ) { + if(m.nrows()*m.ncols()>0) { ConstData d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; } + else { pointer=NULL; size=0; } } - explicit ConstData(const std::string&s){ - if(s.size()>0){ ConstData d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } + explicit ConstData(const std::string&s) { + if(s.size()>0) { ConstData d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; } else { pointer=NULL; size=0; } } }; public: /// Wrapper class for MPI_Status - class Status{ + class Status { int Get_count(MPI_Datatype)const; public: MPI_Status s; template - int Get_count()const{return Get_count(getMPIType());} + int Get_count()const {return Get_count(getMPIType());} }; /// Special status used when status should be ignored. /// E.g. `Recv(a,0,1,Communicator::StatusIgnore);` @@ -134,7 +134,7 @@ class Communicator{ /// `Recv(a,0,1);` static Status StatusIgnore; /// Wrapper class for MPI_Request - class Request{ + class Request { public: MPI_Request r; void wait(Status&s=StatusIgnore); @@ -178,50 +178,52 @@ class Communicator{ /// Wrapper for MPI_Allreduce with MPI_SUM (data struct) void Sum(Data); /// Wrapper for MPI_Allreduce with MPI_SUM (pointer) - template void Sum(T*buf,int count){Sum(Data(buf,count));} + template void Sum(T*buf,int count) {Sum(Data(buf,count));} /// Wrapper for MPI_Allreduce with MPI_SUM (reference) - template void Sum(T&buf){Sum(Data(buf));} + template void Sum(T&buf) {Sum(Data(buf));} /// Wrapper for MPI_Bcast (data struct) void Bcast(Data,int); /// Wrapper for MPI_Bcast (pointer) - template void Bcast(T*buf,int count,int root){Bcast(Data(buf,count),root);} + template void Bcast(T*buf,int count,int root) {Bcast(Data(buf,count),root);} /// Wrapper for MPI_Bcast (reference) - template void Bcast(T&buf,int root){Bcast(Data(buf),root);} + template void Bcast(T&buf,int root) {Bcast(Data(buf),root);} /// Wrapper for MPI_Isend (data struct) Request Isend(ConstData,int,int); /// Wrapper for MPI_Isend (pointer) - template Request Isend(const T*buf,int count,int source,int tag){return Isend(ConstData(buf,count),source,tag);} + template Request Isend(const T*buf,int count,int source,int tag) {return Isend(ConstData(buf,count),source,tag);} /// Wrapper for MPI_Isend (reference) - template Request Isend(const T&buf,int source,int tag){return Isend(ConstData(buf),source,tag);} + template Request Isend(const T&buf,int source,int tag) {return Isend(ConstData(buf),source,tag);} /// Wrapper for MPI_Allgatherv (data struct) void Allgatherv(ConstData in,Data out,const int*,const int*); /// Wrapper for MPI_Allgatherv (pointer) - template void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs){ - Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs);} + template void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs) { + Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs); + } /// Wrapper for MPI_Allgatherv (reference) - template void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs){ - Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs);} + template void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs) { + Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs); + } /// Wrapper for MPI_Allgather (data struct) void Allgather(ConstData in,Data out); /// Wrapper for MPI_Allgatherv (pointer) - template void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount){ + template void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount) { Allgather(ConstData(sendbuf,sendcount),Data(recvbuf,recvcount*Get_size())); } /// Wrapper for MPI_Allgatherv (reference) - template void Allgather(const T&sendbuf,S&recvbuf){ + template void Allgather(const T&sendbuf,S&recvbuf) { Allgather(ConstData(sendbuf),Data(recvbuf)); } /// Wrapper for MPI_Recv (data struct) void Recv(Data,int,int,Status&s=StatusIgnore); /// Wrapper for MPI_Recv (pointer) - template void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore){Recv(Data(buf,count),source,tag,s);} + template void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf,count),source,tag,s);} /// Wrapper for MPI_Recv (reference) - template void Recv(T&buf,int source,int tag,Status&s=StatusIgnore){Recv(Data(buf),source,tag,s);} + template void Recv(T&buf,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf),source,tag,s);} /// Wrapper to MPI_Comm_split void Split(int,int,Communicator&)const; diff --git a/src/tools/CubicInterpolation.cpp b/src/tools/CubicInterpolation.cpp index e52ba8b626..fd35339bd5 100644 --- a/src/tools/CubicInterpolation.cpp +++ b/src/tools/CubicInterpolation.cpp @@ -23,208 +23,209 @@ namespace PLMD { -CInterpolation::CInterpolation( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : -bold(0) +CInterpolation::CInterpolation( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : + bold(0) { plumed_assert( fmin.size()==dd.size() && fmax.size()==dd.size() ); - + np.resize( dd.size() ); stride.resize( dd.size() ); unsigned totalp=1; - for(unsigned i=0;i delr( np.size() ); - for(unsigned j=0;j(np[j]-1); - - for(unsigned i=0;i(np[j]-1); + + for(unsigned i=0; i& nspline ) const { nspline.resize( np.size() ); - for(unsigned i=0;i& pos ){ +unsigned CInterpolation::findBox( const std::vector& pos ) { plumed_dbg_massert( pos.size()==np.size(), "position size does not match the size of the grid"); unsigned jold, ccf_box, bnew=0; - for(unsigned i=0;i( std::floor( double(bold)/double(stride[i]) ) ); - bold-=jold*stride[i]; - ccf_box=search1( i, pos[i], jold ); - bnew+=ccf_box; + for(unsigned i=0; i( std::floor( double(bold)/double(stride[i]) ) ); + bold-=jold*stride[i]; + ccf_box=search1( i, pos[i], jold ); + bnew+=ccf_box; } plumed_dbg_assert( bold==0 ); bold=bnew; - for(unsigned i=0;i=splinepoints(jl,kk) && x=splinepoints(jl, kk ) ){ - while(true){ - ju=jl+inc; - if( x=(np[kk]-1)*inc ){ju=(np[kk]-1)*inc; break; } - jl=ju; - } - } - else{ - ju=jl; - while(true){ - jl=jl-inc; - if( x>=splinepoints( jl, kk ) ) break; - else if( jl<=0 ){ jl=0; break; } - ju=jl; - } - } + int inc=stride[kk], jl=jold*stride[kk], ju=(jold+1)*stride[kk], jm; + if ( x>=splinepoints(jl,kk) && x=splinepoints(jl, kk ) ) { + while(true) { + ju=jl+inc; + if( x=(np[kk]-1)*inc ) {ju=(np[kk]-1)*inc; break; } + jl=ju; + } } - while( ju-jl>inc ){ - jm = (ju+jl) / (2*inc) ; - if ( x>splinepoints(jm*inc,kk) ) jl=jm*inc; else ju=jm*inc; + else { + ju=jl; + while(true) { + jl=jl-inc; + if( x>=splinepoints( jl, kk ) ) break; + else if( jl<=0 ) { jl=0; break; } + ju=jl; + } } - plumed_dbg_assert( jl%stride[kk]==0 && ju==jl+stride[kk] ); - return jl; + } + while( ju-jl>inc ) { + jm = (ju+jl) / (2*inc) ; + if ( x>splinepoints(jm*inc,kk) ) jl=jm*inc; else ju=jm*inc; + } + plumed_dbg_assert( jl%stride[kk]==0 && ju==jl+stride[kk] ); + return jl; } InterpolateCubic::InterpolateCubic( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : -CInterpolation(dd,fmin,fmax) + CInterpolation(dd,fmin,fmax) { plumed_massert(np.size()==1,"should be one dimensional data"); clist.resize( 4*np[0] ); } -void InterpolateCubic::set_table( const std::vector& ff ){ - plumed_assert( getNumberOfSplinePoints()==ff.size() ); +void InterpolateCubic::set_table( const std::vector& ff ) { + plumed_assert( getNumberOfSplinePoints()==ff.size() ); plumed_assert( ff[0].getNumberOfDerivatives()==1 ); double d1, norm; unsigned pij; - for(unsigned i=0;i& pos ){ +double InterpolateCubic::get_fdf( const std::vector& pos ) { plumed_dbg_assert( pos.size()==1 ); - + unsigned mybox=findBox( pos ); - double d1=ub[0] - lb[0]; + double d1=ub[0] - lb[0]; double b=( pos[0] - lb[0] ) / d1, a=( ub[0] - pos[0] ) / d1; - + double *cbase=&clist[(mybox*4)+3], *c3=cbase-1, *c2=c3-1, *c1=c2-1; double f=a*(*c1) + b*(*c2) + (a*a*a-a)*(*c3) + (b*b*b-b)*(*cbase); - return f; + return f; } InterpolateBicubic::InterpolateBicubic( const std::vector& dd, const std::vector& fmin, const std::vector& fmax ) : -CInterpolation(dd,fmin,fmax) + CInterpolation(dd,fmin,fmax) { plumed_massert(np.size()==2,"should be two dimensional data"); static int wt_d[16*16]= - {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - -3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, 0, 0, 0, 0, - 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0,-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, - 0, 0, 0, 0, 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, - -3, 3, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0, - 9,-9, 9,-9, 6, 3,-3,-6, 6,-6,-3, 3, 4, 2, 1, 2, - -6, 6,-6, 6,-4,-2, 2, 4,-3, 3, 3,-3,-2,-1,-1,-2, - 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, - -6, 6,-6, 6,-3,-3, 3, 3,-4, 4, 2,-2,-2,-2,-1,-1, - 4,-4, 4,-4, 2, 2,-2,-2, 2,-2,-2, 2, 1, 1, 1, 1}; + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + -3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, 0, 0, 0, 0, + 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0,-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, + 0, 0, 0, 0, 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, + -3, 3, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0, + 9,-9, 9,-9, 6, 3,-3,-6, 6,-6,-3, 3, 4, 2, 1, 2, + -6, 6,-6, 6,-4,-2, 2, 4,-3, 3, 3,-3,-2,-1,-1,-2, + 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0, + -6, 6,-6, 6,-3,-3, 3, 3,-4, 4, 2,-2,-2,-2,-1,-1, + 4,-4, 4,-4, 2, 2,-2,-2, 2,-2,-2, 2, 1, 1, 1, 1 + }; // This is to set up the coefficient matrix unsigned l=0; wt.resize(16,16); t1.resize(16); t2.resize(16); - for (unsigned i=0;i<16;i++) for (unsigned j=0;j<16;j++){ wt(i,j)=wt_d[l++]; } + for (unsigned i=0; i<16; i++) for (unsigned j=0; j<16; j++) { wt(i,j)=wt_d[l++]; } // Resize everything dcross.resize( np[0], np[1] ); clist.resize( np[0] * np[1] * 4 * 4 ); } -void InterpolateBicubic::set_table( const std::vector& ff ){ - plumed_assert( getNumberOfSplinePoints()==ff.size() ); +void InterpolateBicubic::set_table( const std::vector& ff ) { + plumed_assert( getNumberOfSplinePoints()==ff.size() ); plumed_assert( ff[0].getNumberOfDerivatives()==2 ); dcross=0.0; unsigned iplus, iminus; - for(unsigned i=1;i tc(4,4); std::vector y(4), dy1(4), dy2(4), d2y12(4); unsigned pij=0; unsigned ipos; - for (unsigned i=0;i& y, const std::vector& dy1, const std::vector& dy2, - const std::vector& d2y12, const double& d1, const double& d2, Matrix& c ){ +void InterpolateBicubic::IBicCoeff( const std::vector& y, const std::vector& dy1, const std::vector& dy2, + const std::vector& d2y12, const double& d1, const double& d2, Matrix& c ) { double xx, d1d2=d1*d2; - for(unsigned i=0;i<4;i++){ t1[i] = y[i]; t1[i+4] = dy1[i]*d1; t1[i+8] = dy2[i]*d2; t1[i+12] = d2y12[i]*d1d2; } - for(unsigned i=0;i<16;i++){ xx=0.0; for(unsigned k=0;k<16;k++){ xx += wt(i,k)*t1[k]; } t2[i]=xx; } - unsigned l=0; for(unsigned i=0;i<4;i++){ for(unsigned j=0;j<4;j++){ c(i,j)=t2[l++]; } } + for(unsigned i=0; i<4; i++) { t1[i] = y[i]; t1[i+4] = dy1[i]*d1; t1[i+8] = dy2[i]*d2; t1[i+12] = d2y12[i]*d1d2; } + for(unsigned i=0; i<16; i++) { xx=0.0; for(unsigned k=0; k<16; k++) { xx += wt(i,k)*t1[k]; } t2[i]=xx; } + unsigned l=0; for(unsigned i=0; i<4; i++) { for(unsigned j=0; j<4; j++) { c(i,j)=t2[l++]; } } } -double InterpolateBicubic::get_fdf( const std::vector& pos ){ +double InterpolateBicubic::get_fdf( const std::vector& pos ) { - plumed_dbg_assert( pos.size()==2 ); - unsigned mybox=findBox( pos ); - double d1 = ub[0] - lb[0], d2 = ub[1] - lb[1]; - double t = (pos[0] - lb[0]) / d1, u = (pos[1] - lb[1]) / d2; + plumed_dbg_assert( pos.size()==2 ); + unsigned mybox=findBox( pos ); + double d1 = ub[0] - lb[0], d2 = ub[1] - lb[1]; + double t = (pos[0] - lb[0]) / d1, u = (pos[1] - lb[1]) / d2; - //faster access by pointer arithmetic (dirty dirty dirty) - double *cbase=&clist[(mybox+1)*16-1], *c3, *c2, *c1, *c0; + //faster access by pointer arithmetic (dirty dirty dirty) + double *cbase=&clist[(mybox+1)*16-1], *c3, *c2, *c1, *c0; - double f=0.; - for (int i=3; i>=0; i--) { // Note to self - this has to be an int as unsigned cannot be less than zero - duh!! - c3=cbase; c2=c3-1; c1=c2-1; c0=c1-1; cbase=c0-1; - f= t*f + ( ( (*c3)*u + (*c2) )*u + (*c1) )*u + (*c0); - } - delete cbase; delete c3; delete c2; delete c1; delete c0; - return f; + double f=0.; + for (int i=3; i>=0; i--) { // Note to self - this has to be an int as unsigned cannot be less than zero - duh!! + c3=cbase; c2=c3-1; c1=c2-1; c0=c1-1; cbase=c0-1; + f= t*f + ( ( (*c3)*u + (*c2) )*u + (*c1) )*u + (*c0); + } + delete cbase; delete c3; delete c2; delete c1; delete c0; + return f; } } diff --git a/src/tools/CubicInterpolation.h b/src/tools/CubicInterpolation.h index 39ecca9684..fdbdcc3615 100644 --- a/src/tools/CubicInterpolation.h +++ b/src/tools/CubicInterpolation.h @@ -59,13 +59,13 @@ unsigned CInterpolation::getNumberOfSplinePoints() const { inline void CInterpolation::getSplinePoint( const unsigned nn, std::vector& pp ) const { plumed_dbg_assert( nn #endif -namespace PLMD{ +namespace PLMD { -bool DLLoader::installed(){ +bool DLLoader::installed() { #ifdef __PLUMED_HAS_DLOPEN return true; #else @@ -36,10 +36,10 @@ bool DLLoader::installed(){ } -void* DLLoader::load(const std::string&s){ +void* DLLoader::load(const std::string&s) { #ifdef __PLUMED_HAS_DLOPEN void* p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL); - if(!p){ + if(!p) { lastError=dlerror(); } else { lastError=""; @@ -51,20 +51,20 @@ void* DLLoader::load(const std::string&s){ #endif } -const std::string & DLLoader::error(){ +const std::string & DLLoader::error() { return lastError; } -DLLoader::~DLLoader(){ +DLLoader::~DLLoader() { #ifdef __PLUMED_HAS_DLOPEN - while(!handles.empty()){ + while(!handles.empty()) { dlclose(handles.top()); handles.pop(); } #endif } -DLLoader::DLLoader(){ +DLLoader::DLLoader() { // do nothing } diff --git a/src/tools/DLLoader.h b/src/tools/DLLoader.h index f2f76d0faf..fdad73f2a1 100644 --- a/src/tools/DLLoader.h +++ b/src/tools/DLLoader.h @@ -25,7 +25,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX /// Class taking care of dynamic loading. @@ -37,7 +37,7 @@ namespace PLMD{ /// means that they are not accessible from outside. Still, if they /// contain self-registering classes, they will register themselves /// to the ActionRegister object. -class DLLoader{ +class DLLoader { std::stack handles; std::string lastError; /// Private copy constructor diff --git a/src/tools/DynamicList.h b/src/tools/DynamicList.h index 2f006dcf57..c5252de5b0 100644 --- a/src/tools/DynamicList.h +++ b/src/tools/DynamicList.h @@ -30,7 +30,7 @@ namespace PLMD { /** \ingroup TOOLBOX A class for storing a list that changes which members are active as a function of time. It also -contains friends method that allows you to link two dynamic lists so that you can request +contains friends method that allows you to link two dynamic lists so that you can request stuff from list2 in list1 A PLMD::DynamicList can be used to change what elements in a list should be looped over at any given time. This class is, for the most part, used in tandem with PLMD::NeighbourList. For complex reasons @@ -56,10 +56,10 @@ aa to do at a given time. This is done by: \verbatim DynamicList list; std::vector aa; unsigned kk; for(unsigned i=0;i class DynamicList { /// This gathers data split across nodes list of Dynamic lists -template -friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList >& ); + template + friend void mpi_gatherActiveMembers(Communicator&, std::vector< DynamicList >& ); private: /// This is the list of all the relevent members std::vector all; @@ -155,14 +155,14 @@ friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList /// Constructor DynamicList():nactive(0),nprocessors(1),rank(0),allWereActivated(false),allWereDeactivated(false) {} /// An operator that returns the element from the current active list - inline T operator [] (const unsigned& i) const { - plumed_dbg_assert( i /// Find the index of in the list which has value t int getIndexOfElement( const T& t ) const ; /// Make a particular element inactive - void deactivate( const T& t ); + void deactivate( const T& t ); /// Make everything in the list inactive void deactivateAll(); /// Make something active @@ -204,19 +204,19 @@ friend void mpi_gatherActiveMembers(Communicator& , std::vector< DynamicList /// This sorts the elements in the active list void sortActiveList(); /// Retriee the list of active objects - std::vector retrieveActiveList(); + std::vector retrieveActiveList(); }; template -std::vector DynamicList::retrieveActiveList(){ +std::vector DynamicList::retrieveActiveList() { std::vector this_active(nactive); - for(unsigned k=0;k void DynamicList::clear() { - all.resize(0); + all.resize(0); onoff.resize(0); active.resize(0); } @@ -236,105 +236,105 @@ unsigned DynamicList::getNumberActive() const { } template -void DynamicList::addIndexToList( const T & ii ){ - all.push_back(ii); active.resize( all.size() ); onoff.push_back(0); +void DynamicList::addIndexToList( const T & ii ) { + all.push_back(ii); active.resize( all.size() ); onoff.push_back(0); } template -void DynamicList::createIndexListFromVector( const std::vector& myind ){ +void DynamicList::createIndexListFromVector( const std::vector& myind ) { plumed_dbg_assert( all.size()==0 ); onoff.resize( myind.size(), 0 ); - active.resize( myind.size() ); + active.resize( myind.size() ); all.insert( all.end(), myind.begin(), myind.end() ); } template -void DynamicList::setupMPICommunication( Communicator& comm ){ +void DynamicList::setupMPICommunication( Communicator& comm ) { nprocessors=comm.Get_size(); rank=comm.Get_rank(); } template int DynamicList::getIndexOfElement( const T& t ) const { - for(unsigned i=0;i -void DynamicList::deactivate( const T& t ){ +void DynamicList::deactivate( const T& t ) { plumed_dbg_assert( allWereActivated ); unsigned ii=getIndexOfElement( t ); if( onoff[ii]==0 || onoff[ii]%nprocessors!=0 ) return; // Deactivates the component if( rank==0 ) onoff[ii]=nprocessors-1; - else onoff[ii]=nprocessors-rank; + else onoff[ii]=nprocessors-rank; } template -void DynamicList::deactivateAll(){ +void DynamicList::deactivateAll() { allWereDeactivated=true; allWereActivated=false; - for(unsigned i=0;i -void DynamicList::activate( const unsigned ii ){ +void DynamicList::activate( const unsigned ii ) { plumed_dbg_massert(ii -void DynamicList::activateAll(){ - for(unsigned i=0;i::activateAll() { + for(unsigned i=0; i -void DynamicList::mpi_gatherActiveMembers(Communicator& comm){ +void DynamicList::mpi_gatherActiveMembers(Communicator& comm) { plumed_massert( comm.Get_size()==nprocessors, "error missing a call to DynamicList::setupMPICommunication"); comm.Sum(&onoff[0],onoff.size()); // When we mpi gather onoff to be on it should be active on ALL nodes - for(unsigned i=0;i0 && onoff[i]%nprocessors==0 ){ onoff[i]=nprocessors; } + for(unsigned i=0; i0 && onoff[i]%nprocessors==0 ) { onoff[i]=nprocessors; } updateActiveMembers(); } template -void DynamicList::updateActiveMembers(){ +void DynamicList::updateActiveMembers() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); unsigned kk=0; allWereActivated=allWereDeactivated=false; - for(unsigned i=0;i0 && onoff[i]%nprocessors==0 ){ active[kk]=i; kk++; } + for(unsigned i=0; i0 && onoff[i]%nprocessors==0 ) { active[kk]=i; kk++; } } - nactive=kk; + nactive=kk; } template -void DynamicList::emptyActiveMembers(){ +void DynamicList::emptyActiveMembers() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); nactive=0; } template -void DynamicList::putIndexInActiveArray( const unsigned& ii ){ +void DynamicList::putIndexInActiveArray( const unsigned& ii ) { plumed_dbg_assert( allWereActivated || allWereDeactivated ); plumed_dbg_assert( onoff[ii]>0 && onoff[ii]%nprocessors==0 ); active[nactive]=ii; nactive++; } template -void DynamicList::completeUpdate(){ +void DynamicList::completeUpdate() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); allWereActivated=allWereDeactivated=false; } template -void DynamicList::sortActiveList(){ +void DynamicList::sortActiveList() { plumed_dbg_assert( allWereActivated || allWereDeactivated ); allWereActivated=allWereDeactivated=false; std::sort( active.begin(), active.begin()+nactive ); @@ -347,31 +347,31 @@ bool DynamicList::updateComplete() const { } template -void mpi_gatherActiveMembers(Communicator& comm, std::vector< DynamicList >& ll ){ +void mpi_gatherActiveMembers(Communicator& comm, std::vector< DynamicList >& ll ) { // Setup an array to hold all data unsigned bufsize=0; unsigned size=comm.Get_size(); - for(unsigned i=0;i buffer( bufsize ); // Gather all onoff data into a single array bufsize=0; - for(unsigned i=0;i0 && buffer[bufsize]%size==0 ) ll[i].onoff[j]=size; - else ll[i].onoff[j]=size-1; - bufsize++; - } + bufsize=0; + for(unsigned i=0; i0 && buffer[bufsize]%size==0 ) ll[i].onoff[j]=size; + else ll[i].onoff[j]=size-1; + bufsize++; + } } - for(unsigned i=0;i & positions, vector &) +void ERMSD::clear() { + reference_mat.clear(); +} - void ERMSD::setReference(const vector & reference, const std::vector & pairs_vec, double mycutoff){ +//void ERMSD::calcLcs(const vector & positions, vector &) - - natoms = reference.size(); - nresidues = natoms/3; - unsigned npairs = pairs_vec.size()/2; - pairs.resize(npairs); - //for(unsigned i=0;i<2*npairs;++i) { - // std::cout << "CCC " << pairs_vec[i] << " "; - //} - for(unsigned i=0;i & reference, const std::vector & pairs_vec, double mycutoff) { - pairs[i].first = pairs_vec[2*i]; - pairs[i].second = pairs_vec[2*i+1]; - } - cutoff = mycutoff; - std::vector > deri; - deri.resize(natoms*natoms); - reference_mat.resize(nresidues*nresidues); - Pbc fake_pbc; - - - calcMat(reference,fake_pbc,reference_mat,deri); - - } - - - bool ERMSD::inPair(unsigned i, unsigned j){ - - //return true; - if(pairs.size()==0) return true; - for(unsigned idx=0;idx > deri; + deri.resize(natoms*natoms); + reference_mat.resize(nresidues*nresidues); + Pbc fake_pbc; + + + calcMat(reference,fake_pbc,reference_mat,deri); + +} + + +bool ERMSD::inPair(unsigned i, unsigned j) { + + //return true; + if(pairs.size()==0) return true; + for(unsigned idx=0; idx & positions, // std::vector &derivatives, Tensor& virial) const { // Pbc fake_pbc; // return ERMSD::calculate(positions,fake_pbc,derivatives,virial,false); // } - - - - void ERMSD::calcMat(const std::vector & positions,const Pbc& pbc, std::vector &mat, std::vector > &Gderi) { - - std::vector pos; - pos.resize(3*nresidues); - - std::vector deri; - deri.resize(nresidues*9); - - std::vector centers; - centers.resize(nresidues); - - unsigned idx_deri = 0; - - Tensor da_dxa = (2./3.)*Tensor::identity(); - Tensor da_dxb = -(1./3.)*Tensor::identity(); - Tensor da_dxc = -(1./3.)*Tensor::identity(); - - Tensor db_dxa = -(1./3.)*Tensor::identity(); - Tensor db_dxb = (2./3.)*Tensor::identity(); - Tensor db_dxc = -(1./3.)*Tensor::identity(); - - // Form factors - should this be somewhere else? - - double w = 1./3.; - Vector form_factor = Vector(2.0,2.0,1.0/0.3); - - for(unsigned res_idx=0;res_idx drtilde_dx; - drtilde_dx.resize(6); - unsigned pos_idx = 3*i; - unsigned deri_idx = 9*i; - for (unsigned at=0;at<3;at++){ - for (unsigned l=0;l<3;l++){ - Vector3d rvec = form_factor[l]*((pos[pos_idx+l])/3.); - Vector3d vvec = form_factor[l]*(matmul(deri[deri_idx+3*at+l],diff)); - drtilde_dx[at].setRow(l,vvec-rvec); - drtilde_dx[at+3].setRow(l,rvec); - } - } - - //std::vector > dG_dx; - //dG_dx.resize(6); - - double dummy1 = (cos(gamma*rtilde_norm) - dummy); - - idx1 = i*nresidues*6 + j*6; - - for (unsigned l=0;l<6;l++){ - //std::cout << i << " " << j << " " << idx1 << " " << idx1+l << "\n"; - - // components 1,2,3 - // sin(gamma*|rtilde|)/gamma*|rtilde|*d_rtilde + - // + ((d_rtilde*r_tilde/r_tilde^2) out r_tilde)* - // (cos(gamma*|rtilde| - sin(gamma*|rtilde|)/gamma*|rtilde|)) - Vector3d rdr = matmul(rtilde,drtilde_dx[l]); - Tensor tt = dummy*drtilde_dx[l] + (dummy1*irnorm*irnorm)*Tensor(rtilde,rdr); - for (unsigned m=0;m<3;m++){ - // Transpose here - //dG_dx[l].setRow(m,tt.getRow(m)); - Gderi[idx1+l].setRow(m,tt.getRow(m)); - } - // component 4 - // - sin(gamma*|rtilde|)/|rtilde|*(r_tilde*d_rtilde) - //dG_dx[l].setRow(3,-dummy*gamma*rdr); - Gderi[idx1+l].setRow(3,-dummy*gamma*rdr); - } - - - - - } - } - } - - } +void ERMSD::calcMat(const std::vector & positions,const Pbc& pbc, std::vector &mat, std::vector > &Gderi) { + + std::vector pos; + pos.resize(3*nresidues); + + std::vector deri; + deri.resize(nresidues*9); + + std::vector centers; + centers.resize(nresidues); + + unsigned idx_deri = 0; + + Tensor da_dxa = (2./3.)*Tensor::identity(); + Tensor da_dxb = -(1./3.)*Tensor::identity(); + Tensor da_dxc = -(1./3.)*Tensor::identity(); + + Tensor db_dxa = -(1./3.)*Tensor::identity(); + Tensor db_dxb = (2./3.)*Tensor::identity(); + Tensor db_dxc = -(1./3.)*Tensor::identity(); + + // Form factors - should this be somewhere else? + + double w = 1./3.; + Vector form_factor = Vector(2.0,2.0,1.0/0.3); + + for(unsigned res_idx=0; res_idx & positions,const Pbc& pbc,\ - std::vector &derivatives, Tensor& virial) { - - - double ermsd=0.; - std::vector mat; - mat.resize(nresidues*nresidues); - - std::vector > Gderi; - Gderi.resize(natoms*natoms); - - calcMat(positions,pbc,mat,Gderi); - - unsigned idx1 = 0; - for(unsigned i=0;i0.0 && i!=j){ - - for(unsigned k=0;k<3;k++){ - idx1 = i*nresidues*6 + j*6 + k; - - derivatives[3*i+k] += matmul(dd,Gderi[idx1]); - derivatives[3*j+k] += matmul(dd,Gderi[idx1+3]); - } - ermsd += val; - } + double rtilde_norm = rtilde.modulo(); + + double irnorm = 1./rtilde_norm; + + // ellipsoidal cutoff + if(rtilde_norm < cutoff) { + idx = i*nresidues + j; + //std::cout << i << " " << j << " " << rtilde_norm << " " << idx <<"\n"; + + + // fill 4d matrix + double dummy = sin(gamma*rtilde_norm)/(rtilde_norm*gamma); + mat[idx][0] = dummy*rtilde[0]; + mat[idx][1] = dummy*rtilde[1]; + mat[idx][2] = dummy*rtilde[2]; + mat[idx][3] = (1.+ cos(gamma*rtilde_norm))/gamma; + + // Derivative (drtilde_dx) + std::vector drtilde_dx; + drtilde_dx.resize(6); + unsigned pos_idx = 3*i; + unsigned deri_idx = 9*i; + for (unsigned at=0; at<3; at++) { + for (unsigned l=0; l<3; l++) { + Vector3d rvec = form_factor[l]*((pos[pos_idx+l])/3.); + Vector3d vvec = form_factor[l]*(matmul(deri[deri_idx+3*at+l],diff)); + drtilde_dx[at].setRow(l,vvec-rvec); + drtilde_dx[at+3].setRow(l,rvec); + } + } + + //std::vector > dG_dx; + //dG_dx.resize(6); + + double dummy1 = (cos(gamma*rtilde_norm) - dummy); + + idx1 = i*nresidues*6 + j*6; + + for (unsigned l=0; l<6; l++) { + //std::cout << i << " " << j << " " << idx1 << " " << idx1+l << "\n"; + + // components 1,2,3 + // sin(gamma*|rtilde|)/gamma*|rtilde|*d_rtilde + + // + ((d_rtilde*r_tilde/r_tilde^2) out r_tilde)* + // (cos(gamma*|rtilde| - sin(gamma*|rtilde|)/gamma*|rtilde|)) + Vector3d rdr = matmul(rtilde,drtilde_dx[l]); + Tensor tt = dummy*drtilde_dx[l] + (dummy1*irnorm*irnorm)*Tensor(rtilde,rdr); + for (unsigned m=0; m<3; m++) { + // Transpose here + //dG_dx[l].setRow(m,tt.getRow(m)); + Gderi[idx1+l].setRow(m,tt.getRow(m)); + } + // component 4 + // - sin(gamma*|rtilde|)/|rtilde|*(r_tilde*d_rtilde) + //dG_dx[l].setRow(3,-dummy*gamma*rdr); + Gderi[idx1+l].setRow(3,-dummy*gamma*rdr); + } + + + + } - } - - //std::cout << ermsd << " "; - //if(pairs.size()!=0) nresidues=pairs.size(); - //std::cout << ermsd << " " << nresidues; - ermsd = sqrt(ermsd/nresidues); - double iermsd = 1.0/(ermsd*nresidues); - for(unsigned i=0;i & positions,const Pbc& pbc,\ + std::vector &derivatives, Tensor& virial) { + + + double ermsd=0.; + std::vector mat; + mat.resize(nresidues*nresidues); + + std::vector > Gderi; + Gderi.resize(natoms*natoms); + + calcMat(positions,pbc,mat,Gderi); + + unsigned idx1 = 0; + for(unsigned i=0; i0.0 && i!=j) { + + for(unsigned k=0; k<3; k++) { + idx1 = i*nresidues*6 + j*6 + k; + + derivatives[3*i+k] += matmul(dd,Gderi[idx1]); + derivatives[3*j+k] += matmul(dd,Gderi[idx1+3]); + } + ermsd += val; + } + } + } + + //std::cout << ermsd << " "; + //if(pairs.size()!=0) nresidues=pairs.size(); + //std::cout << ermsd << " " << nresidues; + ermsd = sqrt(ermsd/nresidues); + double iermsd = 1.0/(ermsd*nresidues); + for(unsigned i=0; i #include -namespace PLMD{ +namespace PLMD { class PDB; class Pbc; /// A class that implements ERMSD calculations class ERMSD { - //std::map< std::pair , double> targets; - //unsigned natoms; - std::vector reference_mat; - unsigned natoms; - unsigned nresidues; - std::vector > pairs; - double cutoff; - - public: + //std::map< std::pair , double> targets; + //unsigned natoms; + std::vector reference_mat; + unsigned natoms; + unsigned nresidues; + std::vector > pairs; + double cutoff; + +public: /// Constructor - ERMSD(): natoms(0),nresidues(0), cutoff(0.0) {} + ERMSD(): natoms(0),nresidues(0), cutoff(0.0) {} /// clear the structure - void clear(); + void clear(); - bool inPair(unsigned i, unsigned j); + bool inPair(unsigned i, unsigned j); /// set reference coordinates - void setReference(const std::vector & reference, const std::vector & pairs_vec,double mycutoff=0.24); + void setReference(const std::vector & reference, const std::vector & pairs_vec,double mycutoff=0.24); - void calcMat(const std::vector & positions, const Pbc& pbc,std::vector &mat,std::vector > & Gderivatives); + void calcMat(const std::vector & positions, const Pbc& pbc,std::vector &mat,std::vector > & Gderivatives); /// Compute ermsd ( no pbc ) // double calculate(const std::vector & positions, // std::vector &derivatives, Tensor& virial) const ; /// Compute ermsd ( with pbc ) - double calculate(const std::vector& positions, const Pbc& pbc,std::vector &derivatives, Tensor& virial); + double calculate(const std::vector& positions, const Pbc& pbc,std::vector &derivatives, Tensor& virial); }; - + } #endif diff --git a/src/tools/Exception.cpp b/src/tools/Exception.cpp index 06a989c82e..223b4b1417 100644 --- a/src/tools/Exception.cpp +++ b/src/tools/Exception.cpp @@ -21,7 +21,7 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "Exception.h" -#if defined(__PLUMED_HAS_EXECINFO) +#if defined(__PLUMED_HAS_EXECINFO) #include #endif @@ -29,12 +29,12 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { -std::string Exception::format(const std::string&msg,const std::string&file,unsigned line,const std::string&function){ +std::string Exception::format(const std::string&msg,const std::string&file,unsigned line,const std::string&function) { std::string message; message="\n+++ Internal PLUMED error"; - if(file.length()>0){ + if(file.length()>0) { char cline[1000]; sprintf(cline,"%u",line); message += "\n+++ file "+file+", line "+cline; @@ -63,7 +63,7 @@ Exception::Exception(const std::string&msg,const std::string&file,unsigned line, abortIfExceptionsAreDisabled(); } -void Exception::abortIfExceptionsAreDisabled(){ +void Exception::abortIfExceptionsAreDisabled() { #if ! defined(__PLUMED_HAS_EXCEPTIONS) #ifdef __PLUMED_HAS_EXECINFO @@ -72,7 +72,7 @@ void Exception::abortIfExceptionsAreDisabled(){ int i, frames = backtrace(callstack, 128); char** strs = backtrace_symbols(callstack, frames); for (i = 0; i < frames; ++i) { - fprintf(stderr,"%s\n", strs[i]); + fprintf(stderr,"%s\n", strs[i]); } fprintf(stderr,"******** END STACK DUMP ********\n"); free(strs); diff --git a/src/tools/Exception.h b/src/tools/Exception.h index 9ed4f1afdb..9e3c6dcf2f 100644 --- a/src/tools/Exception.h +++ b/src/tools/Exception.h @@ -25,7 +25,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -45,7 +45,7 @@ or better add an error message to that if(something_bad) throw Exception("describe the error here); \endverbatim -Even better, you can use the predefined macros +Even better, you can use the predefined macros plumed_error(), plumed_assert(), plumed_merror() and plumed_massert(), which add information about the exact location of the error in the file (filename, line and, for g++, function name). Macros ending in "error" unconditionally throw @@ -108,9 +108,9 @@ class Exception : public std::exception /// With message plus file, line and function (meant to be used through a preprocessor macro) Exception(const std::string&,const std::string&,unsigned,const std::string&); /// Returns the error message - virtual const char* what() const throw(){return msg.c_str();} + virtual const char* what() const throw() {return msg.c_str();} /// Destructor should be defined and should not throw other exceptions - virtual ~Exception() throw(){} + virtual ~Exception() throw() {} }; // With GNU compiler, we can use __PRETTY_FUNCTION__ to get the function name @@ -132,7 +132,7 @@ class Exception : public std::exception #define plumed_massert(test,msg) if(!(test)) throw PLMD::Exception("assertion failed " #test ", " msg,__FILE__,__LINE__,__PRETTY_FUNCTION__) #ifdef NDEBUG -#define plumed_dbg_assert(test) +#define plumed_dbg_assert(test) #define plumed_dbg_massert(test,msg) #else /// \relates PLMD::Exception diff --git a/src/tools/FileBase.cpp b/src/tools/FileBase.cpp index fbcd97d86a..cc38ceebfe 100644 --- a/src/tools/FileBase.cpp +++ b/src/tools/FileBase.cpp @@ -37,62 +37,62 @@ #include #endif -namespace PLMD{ +namespace PLMD { -FileBase& FileBase::link(FILE*fp){ +FileBase& FileBase::link(FILE*fp) { plumed_massert(!this->fp,"cannot link an already open file"); this->fp=fp; cloned=true; return *this; } -FileBase& FileBase::flush(){ +FileBase& FileBase::flush() { if(fp) fflush(fp); return *this; } -FileBase& FileBase::link(Communicator&comm){ +FileBase& FileBase::link(Communicator&comm) { plumed_massert(!fp,"cannot link an already open file"); this->comm=&comm; return *this; } -FileBase& FileBase::link(PlumedMain&plumed){ +FileBase& FileBase::link(PlumedMain&plumed) { plumed_massert(!fp,"cannot link an already open file"); this->plumed=&plumed; link(plumed.comm); return *this; } -FileBase& FileBase::link(Action&action){ +FileBase& FileBase::link(Action&action) { plumed_massert(!fp,"cannot link an already open file"); this->action=&action; link(action.plumed); return *this; } -bool FileBase::FileExist(const std::string& path){ +bool FileBase::FileExist(const std::string& path) { bool do_exist=false; this->path=appendSuffix(path,getSuffix()); mode="r"; FILE *ff=std::fopen(const_cast(this->path.c_str()),"r"); - if(!ff){ + if(!ff) { this->path=path; ff=std::fopen(const_cast(this->path.c_str()),"r"); mode="r"; } if(ff) {do_exist=true; fclose(ff);} if(comm) comm->Barrier(); - return do_exist; + return do_exist; } -bool FileBase::isOpen(){ +bool FileBase::isOpen() { bool isopen=false; if(fp) isopen=true; - return isopen; + return isopen; } -void FileBase::close(){ +void FileBase::close() { plumed_assert(!cloned); eof=false; err=false; @@ -127,11 +127,11 @@ FileBase::~FileBase() #endif } -FileBase::operator bool()const{ +FileBase::operator bool()const { return !eof; } -std::string FileBase::appendSuffix(const std::string&path,const std::string&suffix){ +std::string FileBase::appendSuffix(const std::string&path,const std::string&suffix) { if(path=="/dev/null") return path; // do not append a suffix to /dev/null std::string ret=path; std::string ext=Tools::extension(path); @@ -144,7 +144,7 @@ std::string FileBase::appendSuffix(const std::string&path,const std::string&suff // Removing this line, any extension recognized by Tools::extension() would be considered // if(ext!="gz" && ext!="xtc" && ext!="trr") ext=""; - if(ext.length()>0){ + if(ext.length()>0) { int l=path.length()-(ext.length()+1); plumed_assert(l>=0); ret=ret.substr(0,l); @@ -154,13 +154,13 @@ std::string FileBase::appendSuffix(const std::string&path,const std::string&suff return ret; } -FileBase& FileBase::enforceSuffix(const std::string&suffix){ +FileBase& FileBase::enforceSuffix(const std::string&suffix) { enforcedSuffix_=true; enforcedSuffix=suffix; return *this; } -std::string FileBase::getSuffix()const{ +std::string FileBase::getSuffix()const { if(enforcedSuffix_) return enforcedSuffix; if(plumed) return plumed->getSuffix(); return ""; diff --git a/src/tools/FileBase.h b/src/tools/FileBase.h index f9715511e9..e205aa2cb2 100644 --- a/src/tools/FileBase.h +++ b/src/tools/FileBase.h @@ -24,7 +24,7 @@ #include -namespace PLMD{ +namespace PLMD { class Communicator; class PlumedMain; @@ -36,7 +36,7 @@ Base class for dealing with files. This class just provides things which are common among OFile and IFile */ -class FileBase{ +class FileBase { /// Copy constructor is disabled (private and unimplemented) explicit FileBase(const FileBase&); /// Assignment operator is disabled (private and unimplemented) @@ -44,13 +44,13 @@ class FileBase{ protected: /// Internal tool. /// Base for IFile::Field and OFile::Field - class FieldBase{ + class FieldBase { // everything is public to simplify usage public: std::string name; std::string value; bool constant; - FieldBase(): constant(false){} + FieldBase(): constant(false) {} }; /// file pointer @@ -113,7 +113,7 @@ class FileBase{ /// Check for error/eof. operator bool () const; /// Set heavyFlush flag - void setHeavyFlush(){ heavyFlush=true;} + void setHeavyFlush() { heavyFlush=true;} /// Opens the file virtual FileBase& open(const std::string&name)=0; /// Check if the file exists @@ -129,12 +129,12 @@ class FileBase{ }; inline -std::string FileBase::getPath()const{ +std::string FileBase::getPath()const { return path; } inline -std::string FileBase::getMode()const{ +std::string FileBase::getMode()const { return mode; } diff --git a/src/tools/Grid.cpp b/src/tools/Grid.cpp index 72533567a5..472ae2936d 100644 --- a/src/tools/Grid.cpp +++ b/src/tools/Grid.cpp @@ -37,913 +37,913 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { -Grid::Grid(const std::string& funcl, const std::vector & args, const vector & gmin, - const vector & gmax, const vector & nbin, bool dospline, bool usederiv, bool doclear){ +Grid::Grid(const std::string& funcl, const std::vector & args, const vector & gmin, + const vector & gmax, const vector & nbin, bool dospline, bool usederiv, bool doclear) { // various checks - plumed_massert(args.size()==gmin.size(),"grid min dimensions in input do not match number of arguments"); - plumed_massert(args.size()==nbin.size(),"number of bins on input do not match number of arguments"); - plumed_massert(args.size()==gmax.size(),"grid max dimensions in input do not match number of arguments"); - unsigned dim=gmax.size(); - std::vector names; - std::vector isperiodic; - std::vector pmin,pmax; - names.resize( dim ); - isperiodic.resize( dim ); - pmin.resize( dim ); - pmax.resize( dim ); - for(unsigned int i=0;igetName(); - if( args[i]->isPeriodic() ){ - isperiodic[i]=true; + plumed_massert(args.size()==gmin.size(),"grid min dimensions in input do not match number of arguments"); + plumed_massert(args.size()==nbin.size(),"number of bins on input do not match number of arguments"); + plumed_massert(args.size()==gmax.size(),"grid max dimensions in input do not match number of arguments"); + unsigned dim=gmax.size(); + std::vector names; + std::vector isperiodic; + std::vector pmin,pmax; + names.resize( dim ); + isperiodic.resize( dim ); + pmin.resize( dim ); + pmax.resize( dim ); + for(unsigned int i=0; igetName(); + if( args[i]->isPeriodic() ) { + isperiodic[i]=true; args[i]->getDomain( pmin[i], pmax[i] ); - } else { + } else { isperiodic[i]=false; pmin[i]="0."; pmax[i]="0."; + } } - } - // this is a value-independent initializator - Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); +// this is a value-independent initializator + Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); } -Grid::Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, - const vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ){ - // this calls the initializator - Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); +Grid::Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, + const vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ) { +// this calls the initializator + Init(funcl,names,gmin,gmax,nbin,dospline,usederiv,doclear,isperiodic,pmin,pmax); } -void Grid::Init(const std::string& funcl, const std::vector &names, const vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, - const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ){ - contour_location=0.0; fmt_="%14.9f"; +void Grid::Init(const std::string& funcl, const std::vector &names, const vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, bool doclear, + const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax ) { + contour_location=0.0; fmt_="%14.9f"; // various checks - plumed_massert(names.size()==gmin.size(),"grid dimensions in input do not match number of arguments"); - plumed_massert(names.size()==nbin.size(),"grid dimensions in input do not match number of arguments"); - plumed_massert(names.size()==gmax.size(),"grid dimensions in input do not match number of arguments"); - dimension_=gmax.size(); - str_min_=gmin; str_max_=gmax; - argnames.resize( dimension_ ); - min_.resize( dimension_ ); - max_.resize( dimension_ ); - pbc_.resize( dimension_ ); - for(unsigned int i=0;imin_[i],"maximum in grid must be larger than minimum"); + plumed_massert(nbin[i]>0,"number of grid points must be greater than zero"); + } + nbin_=nbin; + dospline_=dospline; + usederiv_=usederiv; + if(dospline_) plumed_assert(dospline_==usederiv_); + maxsize_=1; + for(unsigned int i=0; i( nbin_[i] ) ); + if( !pbc_[i] ) { max_[i] += dx_[i]; nbin_[i] += 1; } + maxsize_*=nbin_[i]; + } + if(doclear) clear(); +} + +void Grid::clear() { + grid_.resize(maxsize_); + if(usederiv_) der_.resize(maxsize_); + for(index_t i=0; imin_[i],"maximum in grid must be larger than minimum"); - plumed_massert(nbin[i]>0,"number of grid points must be greater than zero"); - } - nbin_=nbin; - dospline_=dospline; - usederiv_=usederiv; - if(dospline_) plumed_assert(dospline_==usederiv_); - maxsize_=1; - for(unsigned int i=0;i( nbin_[i] ) ); - if( !pbc_[i] ){ max_[i] += dx_[i]; nbin_[i] += 1; } - maxsize_*=nbin_[i]; - } - if(doclear) clear(); -} - -void Grid::clear(){ - grid_.resize(maxsize_); - if(usederiv_) der_.resize(maxsize_); - for(index_t i=0;i Grid::getMin() const { - return str_min_; + return str_min_; } vector Grid::getMax() const { - return str_max_; + return str_max_; } vector Grid::getDx() const { - return dx_; + return dx_; } double Grid::getBinVolume() const { - double vol=1.; - for(unsigned i=0;i Grid::getIsPeriodic() const { - return pbc_; + return pbc_; } vector Grid::getNbin() const { - return nbin_; + return nbin_; } vector Grid::getArgNames() const { - return argnames; + return argnames; } Grid::index_t Grid::getSize() const { - return maxsize_; + return maxsize_; } unsigned Grid::getDimension() const { - return dimension_; + return dimension_; } // we are flattening arrays using a column-major order Grid::index_t Grid::getIndex(const vector & indices) const { - plumed_dbg_assert(indices.size()==dimension_); - for(unsigned int i=0;i=nbin_[i]) { - std::string is; - Tools::convert(i,is); - std::string msg="ERROR: the system is looking for a value outside the grid along the " + is + " ("+getArgNames()[i]+")"; - plumed_merror(msg+" index!"); + plumed_dbg_assert(indices.size()==dimension_); + for(unsigned int i=0; i=nbin_[i]) { + std::string is; + Tools::convert(i,is); + std::string msg="ERROR: the system is looking for a value outside the grid along the " + is + " ("+getArgNames()[i]+")"; + plumed_merror(msg+" index!"); + } + index_t index=indices[dimension_-1]; + for(unsigned int i=dimension_-1; i>0; --i) { + index=index*nbin_[i-1]+indices[i-1]; } - index_t index=indices[dimension_-1]; - for(unsigned int i=dimension_-1;i>0;--i){ - index=index*nbin_[i-1]+indices[i-1]; - } - return index; + return index; } Grid::index_t Grid::getIndex(const vector & x) const { - plumed_dbg_assert(x.size()==dimension_); - return getIndex(getIndices(x)); + plumed_dbg_assert(x.size()==dimension_); + return getIndex(getIndices(x)); } // we are flattening arrays using a column-major order vector Grid::getIndices(index_t index) const { - vector indices(dimension_); - index_t kk=index; - indices[0]=(index%nbin_[0]); - for(unsigned int i=1;i=2){ - indices[dimension_-1]=((kk-indices[dimension_-2])/nbin_[dimension_-2]); - } - return indices; + vector indices(dimension_); + index_t kk=index; + indices[0]=(index%nbin_[0]); + for(unsigned int i=1; i=2) { + indices[dimension_-1]=((kk-indices[dimension_-2])/nbin_[dimension_-2]); + } + return indices; } vector Grid::getIndices(const vector & x) const { - plumed_dbg_assert(x.size()==dimension_); - vector indices; - for(unsigned int i=0;i indices; + for(unsigned int i=0; i Grid::getPoint(const vector & indices) const { - plumed_dbg_assert(indices.size()==dimension_); - vector x; - for(unsigned int i=0;i x; + for(unsigned int i=0; i Grid::getPoint(index_t index) const { - plumed_dbg_assert(index Grid::getPoint(const vector & x) const { - plumed_dbg_assert(x.size()==dimension_); - return getPoint(getIndices(x)); + plumed_dbg_assert(x.size()==dimension_); + return getPoint(getIndices(x)); } -void Grid::getPoint(index_t index,std::vector & point) const{ - plumed_dbg_assert(index & point) const { + plumed_dbg_assert(index & indices,std::vector & point) const{ - plumed_dbg_assert(indices.size()==dimension_); - plumed_dbg_assert(point.size()==dimension_); - for(unsigned int i=0;i & indices,std::vector & point) const { + plumed_dbg_assert(indices.size()==dimension_); + plumed_dbg_assert(point.size()==dimension_); + for(unsigned int i=0; i & x,std::vector & point) const{ - plumed_dbg_assert(x.size()==dimension_); - getPoint(getIndices(x),point); +void Grid::getPoint(const std::vector & x,std::vector & point) const { + plumed_dbg_assert(x.size()==dimension_); + getPoint(getIndices(x),point); } vector Grid::getNeighbors - (const vector &indices,const vector &nneigh)const{ - plumed_dbg_assert(indices.size()==dimension_ && nneigh.size()==dimension_); - - vector neighbors; - vector small_bin(dimension_); - - unsigned small_nbin=1; - for(unsigned j=0;j small_indices(dimension_); - vector tmp_indices; - for(unsigned index=0;index=2){ - small_indices[dimension_-1]=((kk-small_indices[dimension_-2])/small_bin[dimension_-2]); - } - unsigned ll=0; - for(unsigned i=0;i=nbin_[i]) continue; - if( pbc_[i] && i0<0) i0=nbin_[i]-(-i0)%nbin_[i]; - if( pbc_[i] && i0>=nbin_[i]) i0%=nbin_[i]; - tmp_indices[ll]=((unsigned)i0); - ll++; - } - tmp_indices.resize(ll); - if(tmp_indices.size()==dimension_){neighbors.push_back(getIndex(tmp_indices));} - } - return neighbors; -} - +(const vector &indices,const vector &nneigh)const { + plumed_dbg_assert(indices.size()==dimension_ && nneigh.size()==dimension_); + + vector neighbors; + vector small_bin(dimension_); + + unsigned small_nbin=1; + for(unsigned j=0; j small_indices(dimension_); + vector tmp_indices; + for(unsigned index=0; index=2) { + small_indices[dimension_-1]=((kk-small_indices[dimension_-2])/small_bin[dimension_-2]); + } + unsigned ll=0; + for(unsigned i=0; i=nbin_[i]) continue; + if( pbc_[i] && i0<0) i0=nbin_[i]-(-i0)%nbin_[i]; + if( pbc_[i] && i0>=nbin_[i]) i0%=nbin_[i]; + tmp_indices[ll]=((unsigned)i0); + ll++; + } + tmp_indices.resize(ll); + if(tmp_indices.size()==dimension_) {neighbors.push_back(getIndex(tmp_indices));} + } + return neighbors; +} + vector Grid::getNeighbors - (const vector & x,const vector & nneigh)const{ - plumed_dbg_assert(x.size()==dimension_ && nneigh.size()==dimension_); - return getNeighbors(getIndices(x),nneigh); +(const vector & x,const vector & nneigh)const { + plumed_dbg_assert(x.size()==dimension_ && nneigh.size()==dimension_); + return getNeighbors(getIndices(x),nneigh); } vector Grid::getNeighbors - (index_t index,const vector & nneigh)const{ - plumed_dbg_assert(index Grid::getSplineNeighbors(const vector & indices)const{ - plumed_dbg_assert(indices.size()==dimension_); - vector neighbors; - unsigned nneigh=unsigned(pow(2.0,int(dimension_))); - - for(unsigned int i=0;i nindices; - for(unsigned int j=0;j & nneigh)const { + plumed_dbg_assert(index Grid::getSplineNeighbors(const vector & indices)const { + plumed_dbg_assert(indices.size()==dimension_); + vector neighbors; + unsigned nneigh=unsigned(pow(2.0,int(dimension_))); + + for(unsigned int i=0; i nindices; + for(unsigned int j=0; j nneighb=kernel.getSupport( dx_ ); std::vector neighbors=getNeighbors( kernel.getCenter(), nneighb ); std::vector xx( dimension_ ); std::vector vv( dimension_ ); std::string str_min, str_max; - for(unsigned i=0;isetDomain( str_min, str_max ); - } else { - vv[i]->setNotPeriodic(); - } + for(unsigned i=0; isetDomain( str_min, str_max ); + } else { + vv[i]->setNotPeriodic(); + } } std::vector der( dimension_ ); - for(unsigned i=0;iset(xx[j]); - double newval = kernel.evaluate( vv, der, usederiv_ ); - if( usederiv_ ) addValueAndDerivatives( ineigh, newval, der ); - else addValue( ineigh, newval ); + for(unsigned i=0; iset(xx[j]); + double newval = kernel.evaluate( vv, der, usederiv_ ); + if( usederiv_ ) addValueAndDerivatives( ineigh, newval, der ); + else addValue( ineigh, newval ); } - for(unsigned i=0;imaxval)maxval=grid_[i]; - } - return maxval; + double maxval; + maxval=DBL_MIN; + for(index_t i=0; imaxval)maxval=grid_[i]; + } + return maxval; } double Grid::getValue(const vector & indices) const { - return getValue(getIndex(indices)); + return getValue(getIndex(indices)); } double Grid::getValue(const vector & x) const { - if(!dospline_){ - return getValue(getIndex(x)); - } else { - vector der(dimension_); - return getValueAndDerivatives(x,der); - } + if(!dospline_) { + return getValue(getIndex(x)); + } else { + vector der(dimension_); + return getValueAndDerivatives(x,der); + } } double Grid::getValueAndDerivatives - (index_t index, vector& der) const{ - plumed_dbg_assert(index& der) const { + plumed_dbg_assert(index & indices, vector& der) const{ - return getValueAndDerivatives(getIndex(indices),der); +(const vector & indices, vector& der) const { + return getValueAndDerivatives(getIndex(indices),der); } double Grid::getValueAndDerivatives (const vector & x, vector& der) const { - plumed_dbg_assert(der.size()==dimension_ && usederiv_); - - if(dospline_){ - double X,X2,X3,value; - vector fd(dimension_); - vector C(dimension_); - vector D(dimension_); - vector dder(dimension_); + plumed_dbg_assert(der.size()==dimension_ && usederiv_); + + if(dospline_) { + double X,X2,X3,value; + vector fd(dimension_); + vector C(dimension_); + vector D(dimension_); + vector dder(dimension_); // reset - value=0.0; - for(unsigned int i=0;i indices=getIndices(x); - vector neigh=getSplineNeighbors(indices); - vector xfloor=getPoint(x); + vector indices=getIndices(x); + vector neigh=getSplineNeighbors(indices); + vector xfloor=getPoint(x); // loop over neighbors - for(unsigned int ipoint=0;ipoint nindices=getIndices(neigh[ipoint]); - double ff=1.0; - - for(unsigned j=0;j nindices=getIndices(neigh[ipoint]); + double ff=1.0; + + for(unsigned j=0; j & indices, double value){ - setValue(getIndex(indices),value); +void Grid::setValue(const vector & indices, double value) { + setValue(getIndex(indices),value); } void Grid::setValueAndDerivatives - (index_t index, double value, vector& der){ - plumed_dbg_assert(index& der) { + plumed_dbg_assert(index & indices, double value, vector& der){ - setValueAndDerivatives(getIndex(indices),value,der); +(const vector & indices, double value, vector& der) { + setValueAndDerivatives(getIndex(indices),value,der); } -void Grid::addValue(index_t index, double value){ - plumed_dbg_assert(index & indices, double value){ - addValue(getIndex(indices),value); +void Grid::addValue(const vector & indices, double value) { + addValue(getIndex(indices),value); } void Grid::addValueAndDerivatives - (index_t index, double value, vector& der){ - plumed_dbg_assert(index& der) { + plumed_dbg_assert(index & indices, double value, vector& der){ - addValueAndDerivatives(getIndex(indices),value,der); +(const vector & indices, double value, vector& der) { + addValueAndDerivatives(getIndex(indices),value,der); } -void Grid::scaleAllValuesAndDerivatives( const double& scalef ){ - if(usederiv_){ - for(index_t i=0;i xx(dimension_); - vector der(dimension_); - double f; - writeHeader(ofile); - for(index_t i=0;i0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); - for(unsigned j=0;j(nbin_[j]) ); - if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); - else ofile.printField("periodic_" + argnames[j], "false" ); - } - for(unsigned j=0;j xx(dimension_); + vector der(dimension_); + double f; + writeHeader(ofile); + for(index_t i=0; i0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); + for(unsigned j=0; j(nbin_[j]) ); + if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); + else ofile.printField("periodic_" + argnames[j], "false" ); + } + for(unsigned j=0; j pp(3); - for(pp[0]=0;pp[0] & args, IFile& ifile, - const vector & gmin,const vector & gmax, - const vector & nbin,bool dosparse, bool dospline, bool doder){ +Grid* Grid::create(const std::string& funcl, const std::vector & args, IFile& ifile, + const vector & gmin,const vector & gmax, + const vector & nbin,bool dosparse, bool dospline, bool doder) { Grid* grid=Grid::create(funcl,args,ifile,dosparse,dospline,doder); std::vector cbin( grid->getNbin() ); std::vector cmin( grid->getMin() ), cmax( grid->getMax() ); - for(unsigned i=0;iisPeriodic() ){ - plumed_massert( cbin[i]==nbin[i], "mismatched grid nbins" ); - } else { - plumed_massert( (cbin[i]-1)==nbin[i], "mismatched grid nbins"); - } + for(unsigned i=0; iisPeriodic() ) { + plumed_massert( cbin[i]==nbin[i], "mismatched grid nbins" ); + } else { + plumed_massert( (cbin[i]-1)==nbin[i], "mismatched grid nbins"); + } } return grid; } Grid* Grid::create(const std::string& funcl, const std::vector & args, IFile& ifile, bool dosparse, bool dospline, bool doder) { - Grid* grid=NULL; - unsigned nvar=args.size(); bool hasder=false; std::string pstring; - std::vector gbin1(nvar); std::vector gbin(nvar); - std::vector labels(nvar),gmin(nvar),gmax(nvar); - std::vector fieldnames; ifile.scanFieldList( fieldnames ); - // Retrieve names for fields - for(unsigned i=0;igetName(); - // And read the stuff from the header - plumed_massert( ifile.FieldExist( funcl ) , "no column labelled " + funcl + " in in grid input"); - for(unsigned i=0;i0 ); - if( args[i]->isPeriodic() ){ - plumed_massert( pstring=="true", "input value is periodic but grid is not"); - std::string pmin, pmax; - args[i]->getDomain( pmin, pmax ); gbin[i]=gbin1[i]; - if( pmin!=gmin[i] || pmax!=gmax[i] ) plumed_merror("mismatch between grid boundaries and periods of values"); - } else { - gbin[i]=gbin1[i]-1; // Note header in grid file indicates one more bin that there should be when data is not periodic - plumed_massert( pstring=="false", "input value is not periodic but grid is"); - } - hasder=ifile.FieldExist( "der_" + args[i]->getName() ); - if( doder && !hasder ) plumed_merror("missing derivatives from grid file"); - for(unsigned j=0;j xx(nvar),dder(nvar); - vector dx=grid->getDx(); - double f,x; - while( ifile.scanField(funcl,f) ){ - for(unsigned i=0;igetName(), dder[i] ); } } - index_t index=grid->getIndex(xx); - if(doder){grid->setValueAndDerivatives(index,f,dder);} - else{grid->setValue(index,f);} - ifile.scanField(); - } - return grid; + Grid* grid=NULL; + unsigned nvar=args.size(); bool hasder=false; std::string pstring; + std::vector gbin1(nvar); std::vector gbin(nvar); + std::vector labels(nvar),gmin(nvar),gmax(nvar); + std::vector fieldnames; ifile.scanFieldList( fieldnames ); +// Retrieve names for fields + for(unsigned i=0; igetName(); +// And read the stuff from the header + plumed_massert( ifile.FieldExist( funcl ), "no column labelled " + funcl + " in in grid input"); + for(unsigned i=0; i0 ); + if( args[i]->isPeriodic() ) { + plumed_massert( pstring=="true", "input value is periodic but grid is not"); + std::string pmin, pmax; + args[i]->getDomain( pmin, pmax ); gbin[i]=gbin1[i]; + if( pmin!=gmin[i] || pmax!=gmax[i] ) plumed_merror("mismatch between grid boundaries and periods of values"); + } else { + gbin[i]=gbin1[i]-1; // Note header in grid file indicates one more bin that there should be when data is not periodic + plumed_massert( pstring=="false", "input value is not periodic but grid is"); + } + hasder=ifile.FieldExist( "der_" + args[i]->getName() ); + if( doder && !hasder ) plumed_merror("missing derivatives from grid file"); + for(unsigned j=0; j xx(nvar),dder(nvar); + vector dx=grid->getDx(); + double f,x; + while( ifile.scanField(funcl,f) ) { + for(unsigned i=0; igetName(), dder[i] ); } } + index_t index=grid->getIndex(xx); + if(doder) {grid->setValueAndDerivatives(index,f,dder);} + else {grid->setValue(index,f);} + ifile.scanField(); + } + return grid; } // Sparse version of grid with map -void SparseGrid::clear(){ - map_.clear(); +void SparseGrid::clear() { + map_.clear(); } -Grid::index_t SparseGrid::getSize() const{ - return map_.size(); +Grid::index_t SparseGrid::getSize() const { + return map_.size(); } Grid::index_t SparseGrid::getMaxSize() const { - return maxsize_; + return maxsize_; } double Grid::getDifferenceFromContour( const std::vector& x, std::vector& der ) const { - return getValueAndDerivatives( x, der ) - contour_location; + return getValueAndDerivatives( x, der ) - contour_location; } void Grid::findSetOfPointsOnContour(const double& target, const std::vector& nosearch, - unsigned& npoints, std::vector >& points ){ - // Set contour location for function - contour_location=target; - // Resize points to maximum possible value - points.resize( dimension_*maxsize_ ); - - // Two points for search - std::vector ind(dimension_); - std::vector direction( dimension_, 0 ); - - // Run over whole grid - npoints=0; RootFindingBase mymin( this ); - for(unsigned i=0;isecond; - return value; + unsigned& npoints, std::vector >& points ) { +// Set contour location for function + contour_location=target; +// Resize points to maximum possible value + points.resize( dimension_*maxsize_ ); + +// Two points for search + std::vector ind(dimension_); + std::vector direction( dimension_, 0 ); + +// Run over whole grid + npoints=0; RootFindingBase mymin( this ); + for(unsigned i=0; isecond; + return value; } double SparseGrid::getValueAndDerivatives - (index_t index, vector& der)const{ - plumed_assert(indexsecond; - const auto itder=der_.find(index); - if(itder!=der_.end()) der=itder->second; - return value; +(index_t index, vector& der)const { + plumed_assert(indexsecond; + const auto itder=der_.find(index); + if(itder!=der_.end()) der=itder->second; + return value; } -void SparseGrid::setValue(index_t index, double value){ - plumed_assert(index& der){ - plumed_assert(index& der) { + plumed_assert(index& der){ - plumed_assert(index xx(dimension_); - vector der(dimension_); - double f; - writeHeader(ofile); - ofile.fmtField(" "+fmt_); - for(const auto & it : map_){ - index_t i=it.first; - xx=getPoint(i); - if(usederiv_){f=getValueAndDerivatives(i,der);} - else{f=getValue(i);} - if(i>0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); - for(unsigned j=0;j(nbin_[j]) ); - if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); - else ofile.printField("periodic_" + argnames[j], "false" ); - } - for(unsigned j=0;j &vHigh, WeightBase * ptr2obj ){ - unsigned i=0; - for(i=0;i& der) { + plumed_assert(index xx(dimension_); + vector der(dimension_); + double f; + writeHeader(ofile); + ofile.fmtField(" "+fmt_); + for(const auto & it : map_) { + index_t i=it.first; + xx=getPoint(i); + if(usederiv_) {f=getValueAndDerivatives(i,der);} + else {f=getValue(i);} + if(i>0 && dimension_>1 && getIndices(i)[dimension_-2]==0) ofile.printf("\n"); + for(unsigned j=0; j(nbin_[j]) ); + if( pbc_[j] ) ofile.printField("periodic_" + argnames[j], "true" ); + else ofile.printField("periodic_" + argnames[j], "false" ); + } + for(unsigned j=0; j &vHigh, WeightBase * ptr2obj ) { + unsigned i=0; + for(i=0; i vv(vHigh.size()); + for(unsigned j=0; jprojectInnerLoop(val,myv) ; + // to be added: bias (same as before without negative sign) + //std::cerr<<" VAL: "< & proj, WeightBase *ptr2obj ) { + // find extrema only for the projection + vector smallMin,smallMax; + vector smallBin; + vector dimMapping; + vector smallIsPeriodic; + vector smallName; + + // check if the two key methods are there + WeightBase* pp = dynamic_cast(ptr2obj); + if (!pp)plumed_merror("This WeightBase is not complete: you need a projectInnerLoop and projectOuterLoop "); + + for(unsigned j=0; j vv(vHigh.size()); - for(unsigned j=0;jprojectInnerLoop(val,myv) ; - // to be added: bias (same as before without negative sign) - //std::cerr<<" VAL: "< toBeIntegrated; + for(unsigned i=0; i v; + v=smallgrid.getIndices(i); + std::vector vHigh((getArgNames()).size(),-1); + for(unsigned j=0; j(ptr2obj)){ + // // smallgrid.addValue(i,vmin);// go to 1 + // //} + double vv=smallgrid.getValue(i); + smallgrid.setValue(i,ptr2obj->projectOuterLoop(vv)); + // //if(dynamic_cast(ptr2obj)){ + // // smallgrid.addValue(i,-vmin);// bring back to the value + // //} + } + + return smallgrid; } -Grid Grid::project(const std::vector & proj , WeightBase *ptr2obj ){ - // find extrema only for the projection - vector smallMin,smallMax; - vector smallBin; - vector dimMapping; - vector smallIsPeriodic; - vector smallName; - - // check if the two key methods are there - WeightBase* pp = dynamic_cast(ptr2obj); - if (!pp)plumed_merror("This WeightBase is not complete: you need a projectInnerLoop and projectOuterLoop "); - - for(unsigned j=0;j toBeIntegrated; - for(unsigned i=0;i v; - v=smallgrid.getIndices(i); - std::vector vHigh((getArgNames()).size(),-1); - for(unsigned j=0;j(ptr2obj)){ - // // smallgrid.addValue(i,vmin);// go to 1 - // //} - double vv=smallgrid.getValue(i); - smallgrid.setValue(i,ptr2obj->projectOuterLoop(vv)); - // //if(dynamic_cast(ptr2obj)){ - // // smallgrid.addValue(i,-vmin);// bring back to the value - // //} - } - - return smallgrid; -} - -double Grid::integrate( std::vector& npoints ){ +double Grid::integrate( std::vector& npoints ) { plumed_dbg_assert( npoints.size()==dimension_ ); plumed_assert( dospline_ ); unsigned ntotgrid=1; double box_vol=1.0; std::vector ispacing( npoints.size() ); - for(unsigned j=0;j( npoints[j] ); - npoints[j]+=1; - } else { - ispacing[j] = ( max_[j] - min_[j] ) / static_cast( npoints[j] ); - } - ntotgrid*=npoints[j]; box_vol*=ispacing[j]; + for(unsigned j=0; j( npoints[j] ); + npoints[j]+=1; + } else { + ispacing[j] = ( max_[j] - min_[j] ) / static_cast( npoints[j] ); + } + ntotgrid*=npoints[j]; box_vol*=ispacing[j]; } std::vector vals( dimension_ ); std::vector t_index( dimension_ ); double integral=0.0; - for(unsigned i=0;i=2 ) t_index[dimension_-1]=((kk-t_index[dimension_-1])/npoints[dimension_-2]); + for(unsigned i=0; i=2 ) t_index[dimension_-1]=((kk-t_index[dimension_-1])/npoints[dimension_-2]); - for(unsigned j=0;j #include -namespace PLMD{ +namespace PLMD { // simple function to enable various weighting -class WeightBase{ - public: - virtual double projectInnerLoop(double &input, double &v)=0; - virtual double projectOuterLoop(double &v)=0; - virtual ~WeightBase(){} +class WeightBase { +public: + virtual double projectInnerLoop(double &input, double &v)=0; + virtual double projectOuterLoop(double &v)=0; + virtual ~WeightBase() {} }; -class BiasWeight:public WeightBase{ - public: - double beta,invbeta; - explicit BiasWeight(double v){beta=v;invbeta=1./beta;} - double projectInnerLoop(double &input, double &v){return input+exp(beta*v);} - double projectOuterLoop(double &v){return -invbeta*std::log(v);} +class BiasWeight:public WeightBase { +public: + double beta,invbeta; + explicit BiasWeight(double v) {beta=v; invbeta=1./beta;} + double projectInnerLoop(double &input, double &v) {return input+exp(beta*v);} + double projectOuterLoop(double &v) {return -invbeta*std::log(v);} }; -class ProbWeight:public WeightBase{ - public: - double beta,invbeta; - explicit ProbWeight(double v){beta=v;invbeta=1./beta;} - double projectInnerLoop(double &input, double &v){return input+v;} - double projectOuterLoop(double &v){return -invbeta*std::log(v);} +class ProbWeight:public WeightBase { +public: + double beta,invbeta; + explicit ProbWeight(double v) {beta=v; invbeta=1./beta;} + double projectInnerLoop(double &input, double &v) {return input+v;} + double projectOuterLoop(double &v) {return -invbeta*std::log(v);} }; @@ -67,200 +67,200 @@ class KernelFunctions; class Communicator; /// \ingroup TOOLBOX -class Grid +class Grid { public: // we use a size_t here // should be 8 bytes on all 64-bit machines // and more portable than "unsigned long long" - typedef size_t index_t; + typedef size_t index_t; // to restore old implementation (unsigned) use the following instead: // typedef unsigned index_t; private: - double contour_location; - std::vector grid_; - std::vector< std::vector > der_; + double contour_location; + std::vector grid_; + std::vector< std::vector > der_; protected: - std::string funcname; - std::vector argnames; - std::vector str_min_, str_max_; - std::vector min_,max_,dx_; - std::vector nbin_; - std::vector pbc_; - index_t maxsize_; - unsigned dimension_; - bool dospline_, usederiv_; - std::string fmt_; // format for output - /// get "neighbors" for spline - std::vector getSplineNeighbors(const std::vector & indices)const; + std::string funcname; + std::vector argnames; + std::vector str_min_, str_max_; + std::vector min_,max_,dx_; + std::vector nbin_; + std::vector pbc_; + index_t maxsize_; + unsigned dimension_; + bool dospline_, usederiv_; + std::string fmt_; // format for output +/// get "neighbors" for spline + std::vector getSplineNeighbors(const std::vector & indices)const; public: - /// clear grid - virtual void clear(); - /// this constructor here is Value-aware - Grid(const std::string& funcl, const std::vector & args, const std::vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, - bool usederiv, bool doclear=true); - /// this constructor here is not Value-aware - Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, - bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, - const std::vector &pmax ); - /// this is the real initializator - void Init(const std::string & funcl, const std::vector &names, const std::vector & gmin, - const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, - bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax); +/// clear grid + virtual void clear(); +/// this constructor here is Value-aware + Grid(const std::string& funcl, const std::vector & args, const std::vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, + bool usederiv, bool doclear=true); +/// this constructor here is not Value-aware + Grid(const std::string& funcl, const std::vector &names, const std::vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, + bool usederiv, bool doclear, const std::vector &isperiodic, const std::vector &pmin, + const std::vector &pmax ); +/// this is the real initializator + void Init(const std::string & funcl, const std::vector &names, const std::vector & gmin, + const std::vector & gmax, const std::vector & nbin, bool dospline, bool usederiv, + bool doclear, const std::vector &isperiodic, const std::vector &pmin, const std::vector &pmax); /// get lower boundary - std::vector getMin() const; + std::vector getMin() const; /// get upper boundary - std::vector getMax() const; + std::vector getMax() const; /// get bin size - std::vector getDx() const; + std::vector getDx() const; /// get bin volume - double getBinVolume() const; + double getBinVolume() const; /// get number of bins - std::vector getNbin() const; + std::vector getNbin() const; /// get if periodic - std::vector getIsPeriodic() const; + std::vector getIsPeriodic() const; /// get grid dimension - unsigned getDimension() const; -/// get argument names of this grid - std::vector getArgNames() const; - -/// methods to handle grid indices - std::vector getIndices(index_t index) const; - std::vector getIndices(const std::vector & x) const; - index_t getIndex(const std::vector & indices) const; - index_t getIndex(const std::vector & x) const; - std::vector getPoint(index_t index) const; - std::vector getPoint(const std::vector & indices) const; - std::vector getPoint(const std::vector & x) const; + unsigned getDimension() const; +/// get argument names of this grid + std::vector getArgNames() const; + +/// methods to handle grid indices + std::vector getIndices(index_t index) const; + std::vector getIndices(const std::vector & x) const; + index_t getIndex(const std::vector & indices) const; + index_t getIndex(const std::vector & x) const; + std::vector getPoint(index_t index) const; + std::vector getPoint(const std::vector & indices) const; + std::vector getPoint(const std::vector & x) const; /// faster versions relying on preallocated vectors - void getPoint(index_t index,std::vector & point) const; - void getPoint(const std::vector & indices,std::vector & point) const; - void getPoint(const std::vector & x,std::vector & point) const; + void getPoint(index_t index,std::vector & point) const; + void getPoint(const std::vector & indices,std::vector & point) const; + void getPoint(const std::vector & x,std::vector & point) const; /// get neighbors - std::vector getNeighbors(index_t index,const std::vector & neigh) const; - std::vector getNeighbors(const std::vector & indices,const std::vector & neigh) const; - std::vector getNeighbors(const std::vector & x,const std::vector & neigh) const; + std::vector getNeighbors(index_t index,const std::vector & neigh) const; + std::vector getNeighbors(const std::vector & indices,const std::vector & neigh) const; + std::vector getNeighbors(const std::vector & x,const std::vector & neigh) const; /// write header for grid file - void writeHeader(OFile& file); + void writeHeader(OFile& file); /// read grid from file - static Grid* create(const std::string&,const std::vector&,IFile&,bool,bool,bool); + static Grid* create(const std::string&,const std::vector&,IFile&,bool,bool,bool); /// read grid from file and check boundaries are what is expected from input - static Grid* create(const std::string&,const std::vector&, IFile&, - const std::vector&,const std::vector&, - const std::vector&,bool,bool,bool); + static Grid* create(const std::string&,const std::vector&, IFile&, + const std::vector&,const std::vector&, + const std::vector&,bool,bool,bool); /// get grid size - virtual index_t getSize() const; + virtual index_t getSize() const; /// get grid value - virtual double getValue(index_t index) const; - virtual double getValue(const std::vector & indices) const; - virtual double getValue(const std::vector & x) const; + virtual double getValue(index_t index) const; + virtual double getValue(const std::vector & indices) const; + virtual double getValue(const std::vector & x) const; /// get minimum value virtual double getMinValue() const; /// get maximum value virtual double getMaxValue() const; /// get grid value and derivatives - virtual double getValueAndDerivatives(index_t index, std::vector& der) const ; - virtual double getValueAndDerivatives(const std::vector & indices, std::vector& der) const; - virtual double getValueAndDerivatives(const std::vector & x, std::vector& der) const; + virtual double getValueAndDerivatives(index_t index, std::vector& der) const ; + virtual double getValueAndDerivatives(const std::vector & indices, std::vector& der) const; + virtual double getValueAndDerivatives(const std::vector & x, std::vector& der) const; /// Get the difference from the contour - double getDifferenceFromContour(const std::vector & x, std::vector& der) const ; + double getDifferenceFromContour(const std::vector & x, std::vector& der) const ; /// Find a set of points on a contour in the function - void findSetOfPointsOnContour(const double& target, const std::vector& nosearch, unsigned& npoints, std::vector >& points ); + void findSetOfPointsOnContour(const double& target, const std::vector& nosearch, unsigned& npoints, std::vector >& points ); -/// set grid value - virtual void setValue(index_t index, double value); - virtual void setValue(const std::vector & indices, double value); +/// set grid value + virtual void setValue(index_t index, double value); + virtual void setValue(const std::vector & indices, double value); /// set grid value and derivatives - virtual void setValueAndDerivatives(index_t index, double value, std::vector& der); - virtual void setValueAndDerivatives(const std::vector & indices, double value, std::vector& der); + virtual void setValueAndDerivatives(index_t index, double value, std::vector& der); + virtual void setValueAndDerivatives(const std::vector & indices, double value, std::vector& der); /// add to grid value - virtual void addValue(index_t index, double value); - virtual void addValue(const std::vector & indices, double value); + virtual void addValue(index_t index, double value); + virtual void addValue(const std::vector & indices, double value); /// add to grid value and derivatives - virtual void addValueAndDerivatives(index_t index, double value, std::vector& der); - virtual void addValueAndDerivatives(const std::vector & indices, double value, std::vector& der); + virtual void addValueAndDerivatives(index_t index, double value, std::vector& der); + virtual void addValueAndDerivatives(const std::vector & indices, double value, std::vector& der); /// Scale all grid values and derivatives by a constant factor - virtual void scaleAllValuesAndDerivatives( const double& scalef ); -/// Takes the scalef times the logarithm of all grid values and derivatives - virtual void logAllValuesAndDerivatives( const double& scalef ); + virtual void scaleAllValuesAndDerivatives( const double& scalef ); +/// Takes the scalef times the logarithm of all grid values and derivatives + virtual void logAllValuesAndDerivatives( const double& scalef ); /// Set the minimum value of the grid to zero and translates accordingly - virtual void setMinToZero(); -/// apply function: takes pointer to function that accepts a double and apply - virtual void applyFunctionAllValuesAndDerivatives( double (*func)(double val), double (*funcder)(double valder) ); + virtual void setMinToZero(); +/// apply function: takes pointer to function that accepts a double and apply + virtual void applyFunctionAllValuesAndDerivatives( double (*func)(double val), double (*funcder)(double valder) ); /// add a kernel function to the grid - void addKernel( const KernelFunctions& kernel ); + void addKernel( const KernelFunctions& kernel ); /// dump grid on file - virtual void writeToFile(OFile&); + virtual void writeToFile(OFile&); /// dump grid to gaussian cube file - void writeCubeFile(OFile&, const double& lunit); + void writeCubeFile(OFile&, const double& lunit); - virtual ~Grid(){} + virtual ~Grid() {} -/// project a high dimensional grid onto a low dimensional one: this should be changed at some time +/// project a high dimensional grid onto a low dimensional one: this should be changed at some time /// to enable many types of weighting - Grid project( const std::vector & proj , WeightBase *ptr2obj ); - void projectOnLowDimension(double &val , std::vector &varHigh, WeightBase* ptr2obj ); + Grid project( const std::vector & proj, WeightBase *ptr2obj ); + void projectOnLowDimension(double &val, std::vector &varHigh, WeightBase* ptr2obj ); /// set output format - void setOutputFmt(const std::string & ss){fmt_=ss;} + void setOutputFmt(const std::string & ss) {fmt_=ss;} /// Integrate the function calculated on the grid - double integrate( std::vector& npoints ); + double integrate( std::vector& npoints ); /// - void mpiSumValuesAndDerivatives( Communicator& comm ); + void mpiSumValuesAndDerivatives( Communicator& comm ); }; - + class SparseGrid : public Grid { - std::map map_; - std::map< index_t,std::vector > der_; - - protected: - void clear(); - - public: - SparseGrid(const std::string& funcl, const std::vector & args, const std::vector & gmin, - const std::vector & gmax, - const std::vector & nbin, bool dospline, bool usederiv): - Grid(funcl,args,gmin,gmax,nbin,dospline,usederiv,false){} - - index_t getSize() const; - index_t getMaxSize() const; + std::map map_; + std::map< index_t,std::vector > der_; + +protected: + void clear(); + +public: + SparseGrid(const std::string& funcl, const std::vector & args, const std::vector & gmin, + const std::vector & gmax, + const std::vector & nbin, bool dospline, bool usederiv): + Grid(funcl,args,gmin,gmax,nbin,dospline,usederiv,false) {} + + index_t getSize() const; + index_t getMaxSize() const; /// this is to access to Grid:: version of these methods (allowing overloading of virtual methods) - using Grid::getValue; - using Grid::getValueAndDerivatives; - using Grid::setValue; - using Grid::setValueAndDerivatives; - using Grid::addValue; - using Grid::addValueAndDerivatives; - - /// get grid value - double getValue(index_t index) const; + using Grid::getValue; + using Grid::getValueAndDerivatives; + using Grid::setValue; + using Grid::setValueAndDerivatives; + using Grid::addValue; + using Grid::addValueAndDerivatives; + +/// get grid value + double getValue(index_t index) const; /// get grid value and derivatives - double getValueAndDerivatives(index_t index, std::vector& der) const; + double getValueAndDerivatives(index_t index, std::vector& der) const; -/// set grid value - void setValue(index_t index, double value); +/// set grid value + void setValue(index_t index, double value); /// set grid value and derivatives - void setValueAndDerivatives(index_t index, double value, std::vector& der); + void setValueAndDerivatives(index_t index, double value, std::vector& der); /// add to grid value - void addValue(index_t index, double value); + void addValue(index_t index, double value); /// add to grid value and derivatives - void addValueAndDerivatives(index_t index, double value, std::vector& der); + void addValueAndDerivatives(index_t index, double value, std::vector& der); /// dump grid on file - void writeToFile(OFile&); + void writeToFile(OFile&); - virtual ~SparseGrid(){} + virtual ~SparseGrid() {} }; } diff --git a/src/tools/HistogramBead.cpp b/src/tools/HistogramBead.cpp index c3bd83199d..bdef4556f6 100644 --- a/src/tools/HistogramBead.cpp +++ b/src/tools/HistogramBead.cpp @@ -25,9 +25,9 @@ #include "Tools.h" #include "Keywords.h" -namespace PLMD{ +namespace PLMD { -//+PLUMEDOC INTERNAL histogrambead +//+PLUMEDOC INTERNAL histogrambead /* A function that can be used to calculate whether quantities are between fixed upper and lower bounds. @@ -36,32 +36,32 @@ for that variable using a process called kernel density estimation: \f[ P(s) = \sum_i K\left( \frac{s - s_i}{w} \right) -\f] +\f] In this equation \f$K\f$ is a symmetric funciton that must integrate to one that is often -called a kernel function and \f$w\f$ is a smearing parameter. From a pdf calculated using +called a kernel function and \f$w\f$ is a smearing parameter. From a pdf calculated using kernel density estimation we can calculate the number/fraction of values between an upper and lower bound using: \f[ w(s) = \int_a^b \sum_i K\left( \frac{s - s_i}{w} \right) -\f] +\f] -All the input to calculate a quantity like \f$w(s)\f$ is generally provided through a single +All the input to calculate a quantity like \f$w(s)\f$ is generally provided through a single keyword that will have the following form: KEYWORD={TYPE UPPER=\f$a\f$ LOWER=\f$b\f$ SMEAR=\f$\frac{w}{b-a}\f$} This will calculate the number of values between \f$a\f$ and \f$b\f$. To calculate -the fraction of values you add the word NORM to the input specification. If the +the fraction of values you add the word NORM to the input specification. If the function keyword SMEAR is not present \f$w\f$ is set equal to \f$0.5(b-a)\f$. Finally, type should specify one of the kernel types that is present in plumed. These are listed in the table below: - - - + + + @@ -74,34 +74,34 @@ is to say the number of values between \f$a\f$ and \f$b\f$, the number of values something like KEYWORD={TYPE UPPER=\f$a\f$ LOWER=\f$b\f$ NBINS=\f$n\f$ SMEAR=\f$\frac{w}{n(b-a)}\f$} - -This specification would calculate the following vector of quantities: + +This specification would calculate the following vector of quantities: \f[ -w_j(s) = \int_{a + \frac{j-1}{n}(b-a)}^{a + \frac{j}{n}(b-a)} \sum_i K\left( \frac{s - s_i}{w} \right) +w_j(s) = \int_{a + \frac{j-1}{n}(b-a)}^{a + \frac{j}{n}(b-a)} \sum_i K\left( \frac{s - s_i}{w} \right) \f] */ //+ENDPLUMEDOC -void HistogramBead::registerKeywords( Keywords& keys ){ +void HistogramBead::registerKeywords( Keywords& keys ) { keys.add("compulsory","LOWER","the lower boundary for this particular bin"); keys.add("compulsory","UPPER","the upper boundary for this particular bin"); keys.add("compulsory","SMEAR","0.5","the ammount to smear the Gaussian for each value in the distribution"); } HistogramBead::HistogramBead(): -init(false), -lowb(0.0), -highb(0.0), -width(0.0), -cutoff(std::numeric_limits::max()), -type(gaussian), -periodicity(unset), -min(0.0), -max(0.0), -max_minus_min(0.0), -inv_max_minus_min(0.0) + init(false), + lowb(0.0), + highb(0.0), + width(0.0), + cutoff(std::numeric_limits::max()), + type(gaussian), + periodicity(unset), + min(0.0), + max(0.0), + max_minus_min(0.0), + inv_max_minus_min(0.0) { } @@ -111,7 +111,7 @@ std::string HistogramBead::description() const { return ostr.str(); } -void HistogramBead::generateBins( const std::string& params, std::vector& bins ){ +void HistogramBead::generateBins( const std::string& params, std::vector& bins ) { std::vector data=Tools::getWords(params); plumed_massert(data.size()>=1,"There is no input for this keyword"); @@ -124,78 +124,78 @@ void HistogramBead::generateBins( const std::string& params, std::vector( nbins ); - for(unsigned i=0;i=highb ) errormsg="Lower bound is higher than upper bound"; - + if( !found_r ) errormsg="Upper bound has not been specified use UPPER"; + if( lowb>=highb ) errormsg="Lower bound is higher than upper bound"; + smear=0.5; Tools::parse(data,"SMEAR",smear); width=smear*(highb-lowb); init=true; } -void HistogramBead::set( double l, double h, double w){ - init=true; lowb=l; highb=h; width=w; +void HistogramBead::set( double l, double h, double w) { + init=true; lowb=l; highb=h; width=w; const double DP2CUTOFF=6.25; if( type==gaussian ) cutoff=sqrt(2.0*DP2CUTOFF); else if( type==triangular ) cutoff=1.; else plumed_error(); -} +} -void HistogramBead::setKernelType( const std::string& ktype ){ +void HistogramBead::setKernelType( const std::string& ktype ) { if(ktype=="gaussian") type=gaussian; else if(ktype=="triangular") type=triangular; - else plumed_merror("cannot understand kernel type " + ktype ); -} + else plumed_merror("cannot understand kernel type " + ktype ); +} double HistogramBead::calculate( double x, double& df ) const { - plumed_dbg_assert(init && periodicity!=unset ); + plumed_dbg_assert(init && periodicity!=unset ); double lowB, upperB, f; - if( type==gaussian ){ - lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); - upperB = difference( x, highb ) / ( sqrt(2.0) * width ); - df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); - f = 0.5*( erf( upperB ) - erf( lowB ) ); - } else if( type==triangular ){ - lowB = ( difference( x, lowb ) / width ); - upperB = ( difference( x, highb ) / width ); - df=0; - if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; - if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; - if (upperB<=-1. || lowB >=1.){ - f=0.; - } else { - double ia, ib; - if( lowB>-1.0 ){ ia=lowB; }else{ ia=-1.0; } - if( upperB<1.0 ){ ib=upperB; } else{ ib=1.0; } - f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; - } + if( type==gaussian ) { + lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); + upperB = difference( x, highb ) / ( sqrt(2.0) * width ); + df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); + f = 0.5*( erf( upperB ) - erf( lowB ) ); + } else if( type==triangular ) { + lowB = ( difference( x, lowb ) / width ); + upperB = ( difference( x, highb ) / width ); + df=0; + if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; + if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; + if (upperB<=-1. || lowB >=1.) { + f=0.; + } else { + double ia, ib; + if( lowB>-1.0 ) { ia=lowB; } else { ia=-1.0; } + if( upperB<1.0 ) { ib=upperB; } else { ib=1.0; } + f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; + } } else { - plumed_merror("function type does not exist"); - } + plumed_merror("function type does not exist"); + } return f; } @@ -204,59 +204,59 @@ double HistogramBead::calculateWithCutoff( double x, double& df ) const { double lowB, upperB, f; lowB = difference( x, lowb ) / width ; upperB = difference( x, highb ) / width; - if( upperB<=-cutoff || lowB>=cutoff ){ df=0; return 0; } - - if( type==gaussian ){ - lowB /= sqrt(2.0); upperB /= sqrt(2.0); - df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); - f = 0.5*( erf( upperB ) - erf( lowB ) ); - } else if( type==triangular ){ - df=0; - if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; - if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; - if (upperB<=-1. || lowB >=1.){ - f=0.; - } else { - double ia, ib; - if( lowB>-1.0 ){ ia=lowB; }else{ ia=-1.0; } - if( upperB<1.0 ){ ib=upperB; } else{ ib=1.0; } - f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; - } + if( upperB<=-cutoff || lowB>=cutoff ) { df=0; return 0; } + + if( type==gaussian ) { + lowB /= sqrt(2.0); upperB /= sqrt(2.0); + df = ( exp( -lowB*lowB ) - exp( -upperB*upperB ) ) / ( sqrt(2*pi)*width ); + f = 0.5*( erf( upperB ) - erf( lowB ) ); + } else if( type==triangular ) { + df=0; + if( fabs(lowB)<1. ) df = (1 - fabs(lowB)) / width; + if( fabs(upperB)<1. ) df -= (1 - fabs(upperB)) / width; + if (upperB<=-1. || lowB >=1.) { + f=0.; + } else { + double ia, ib; + if( lowB>-1.0 ) { ia=lowB; } else { ia=-1.0; } + if( upperB<1.0 ) { ib=upperB; } else { ib=1.0; } + f = (ib*(2.-fabs(ib))-ia*(2.-fabs(ia)))*0.5; + } } else { - plumed_merror("function type does not exist"); + plumed_merror("function type does not exist"); } return f; } double HistogramBead::lboundDerivative( const double& x ) const { double lowB; - if( type==gaussian ){ - lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); - return exp( -lowB*lowB ) / ( sqrt(2*pi)*width ); - } else if ( type==triangular ){ - plumed_error(); + if( type==gaussian ) { + lowB = difference( x, lowb ) / ( sqrt(2.0) * width ); + return exp( -lowB*lowB ) / ( sqrt(2*pi)*width ); + } else if ( type==triangular ) { + plumed_error(); // lowB = fabs( difference( x, lowb ) / width ); // if( lowB<1 ) return ( 1 - (lowB) ) / 2*width; // else return 0; } else { - plumed_merror("function type does not exist"); + plumed_merror("function type does not exist"); } return 0; } -double HistogramBead::uboundDerivative( const double& x ) const { +double HistogramBead::uboundDerivative( const double& x ) const { plumed_dbg_assert(init && periodicity!=unset ); double upperB; - if( type==gaussian ){ - upperB = difference( x, highb ) / ( sqrt(2.0) * width ); - return exp( -upperB*upperB ) / ( sqrt(2*pi)*width ); - } else if ( type==triangular ){ - plumed_error(); + if( type==gaussian ) { + upperB = difference( x, highb ) / ( sqrt(2.0) * width ); + return exp( -upperB*upperB ) / ( sqrt(2*pi)*width ); + } else if ( type==triangular ) { + plumed_error(); // upperB = fabs( difference( x, highb ) / width ); -// if( upperB<1 ) return ( 1 - (upperB) ) / 2*width; +// if( upperB<1 ) return ( 1 - (upperB) ) / 2*width; // else return 0; } else { - plumed_merror("function type does not exist"); + plumed_merror("function type does not exist"); } return 0; } diff --git a/src/tools/HistogramBead.h b/src/tools/HistogramBead.h index 44fe12054f..aae33470c5 100644 --- a/src/tools/HistogramBead.h +++ b/src/tools/HistogramBead.h @@ -34,39 +34,39 @@ class Log; /** \ingroup TOOLBOX -A class for calculating whether or not values are within a given range using : \f$ \sum_i \int_a^b G( s_i, \sigma*(b-a) ) \f$ -*/ - -class HistogramBead{ -private: - bool init; - double lowb; - double highb; - double width; - double cutoff; - enum {gaussian,triangular} type; - enum {unset,periodic,notperiodic} periodicity; - double min, max, max_minus_min, inv_max_minus_min; - double difference( const double& d1, const double& d2 ) const ; +A class for calculating whether or not values are within a given range using : \f$ \sum_i \int_a^b G( s_i, \sigma*(b-a) ) \f$ +*/ + +class HistogramBead { +private: + bool init; + double lowb; + double highb; + double width; + double cutoff; + enum {gaussian,triangular} type; + enum {unset,periodic,notperiodic} periodicity; + double min, max, max_minus_min, inv_max_minus_min; + double difference( const double& d1, const double& d2 ) const ; public: - static void registerKeywords( Keywords& keys ); - static void generateBins( const std::string& params, std::vector& bins ); - HistogramBead(); - std::string description() const ; - bool hasBeenSet() const; - void isNotPeriodic(); - void isPeriodic( const double& mlow, const double& mhigh ); - void setKernelType( const std::string& ktype ); - void set(const std::string& params, std::string& errormsg); - void set(double l, double h, double w); - double calculate(double x, double&df) const; - double calculateWithCutoff( double x, double& df ) const; - double lboundDerivative( const double& x ) const; - double uboundDerivative( const double& x ) const; - double getlowb() const ; - double getbigb() const ; - double getCutoff() const ; -}; + static void registerKeywords( Keywords& keys ); + static void generateBins( const std::string& params, std::vector& bins ); + HistogramBead(); + std::string description() const ; + bool hasBeenSet() const; + void isNotPeriodic(); + void isPeriodic( const double& mlow, const double& mhigh ); + void setKernelType( const std::string& ktype ); + void set(const std::string& params, std::string& errormsg); + void set(double l, double h, double w); + double calculate(double x, double&df) const; + double calculateWithCutoff( double x, double& df ) const; + double lboundDerivative( const double& x ) const; + double uboundDerivative( const double& x ) const; + double getlowb() const ; + double getbigb() const ; + double getCutoff() const ; +}; inline bool HistogramBead::hasBeenSet() const { @@ -74,12 +74,12 @@ bool HistogramBead::hasBeenSet() const { } inline -void HistogramBead::isNotPeriodic(){ +void HistogramBead::isNotPeriodic() { periodicity=notperiodic; } inline -void HistogramBead::isPeriodic( const double& mlow, const double& mhigh ){ +void HistogramBead::isPeriodic( const double& mlow, const double& mhigh ) { periodicity=periodic; min=mlow; max=mhigh; max_minus_min=max-min; plumed_massert(max_minus_min>0, "your function has a very strange domain?"); @@ -88,7 +88,7 @@ void HistogramBead::isPeriodic( const double& mlow, const double& mhigh ){ inline double HistogramBead::getlowb() const { return lowb; } - + inline double HistogramBead::getbigb() const { return highb; } @@ -97,9 +97,9 @@ double HistogramBead::getCutoff() const { return cutoff*width; } inline double HistogramBead::difference( const double& d1, const double& d2 ) const { - if(periodicity==notperiodic){ + if(periodicity==notperiodic) { return d2-d1; - } else if(periodicity==periodic){ + } else if(periodicity==periodic) { // Make sure the point is in the target range double newx=d1*inv_max_minus_min; newx=Tools::pbc(newx); diff --git a/src/tools/IFile.cpp b/src/tools/IFile.cpp index c1334fb5cf..5cd3261350 100644 --- a/src/tools/IFile.cpp +++ b/src/tools/IFile.cpp @@ -36,12 +36,12 @@ #include #endif -namespace PLMD{ +namespace PLMD { -size_t IFile::llread(char*ptr,size_t s){ +size_t IFile::llread(char*ptr,size_t s) { plumed_assert(fp); size_t r; - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB int rr=gzread(gzFile(gzfp),ptr,s); if(rr==0) eof=true; @@ -58,22 +58,22 @@ size_t IFile::llread(char*ptr,size_t s){ return r; } -IFile& IFile::advanceField(){ +IFile& IFile::advanceField() { plumed_assert(!inMiddleOfField); std::string line; bool done=false; - while(!done){ + while(!done) { getline(line); - if(!*this){return *this;} + if(!*this) {return *this;} std::vector words=Tools::getWords(line); - if(words.size()>=2 && words[0]=="#!" && words[1]=="FIELDS"){ + if(words.size()>=2 && words[0]=="#!" && words[1]=="FIELDS") { fields.clear(); - for(unsigned i=2;i(this->path.c_str()),"r"); - if(Tools::extension(this->path)=="gz"){ + if(Tools::extension(this->path)=="gz") { #ifdef __PLUMED_HAS_ZLIB gzfp=(void*)gzopen(const_cast(this->path.c_str()),"r"); #else @@ -122,24 +122,24 @@ IFile& IFile::open(const std::string&path){ return *this; } -IFile& IFile::scanFieldList(std::vector&s){ +IFile& IFile::scanFieldList(std::vector&s) { if(!inMiddleOfField) advanceField(); if(!*this) return *this; s.clear(); - for(unsigned i=0;i slist; - scanFieldList(slist); - int mycount = (int) std::count(slist.begin(), slist.end(), s); - if(mycount>0) return true; - else return false; +bool IFile::FieldExist(const std::string& s) { + std::vector slist; + scanFieldList(slist); + int mycount = (int) std::count(slist.begin(), slist.end(), s); + if(mycount>0) return true; + else return false; } -IFile& IFile::scanField(const std::string&name,std::string&str){ +IFile& IFile::scanField(const std::string&name,std::string&str) { if(!inMiddleOfField) advanceField(); if(!*this) return *this; unsigned i=findField(name); @@ -148,40 +148,40 @@ IFile& IFile::scanField(const std::string&name,std::string&str){ return *this; } -IFile& IFile::scanField(const std::string&name,double &x){ +IFile& IFile::scanField(const std::string&name,double &x) { std::string str; scanField(name,str); if(*this) Tools::convert(str,x); return *this; } -IFile& IFile::scanField(const std::string&name,int &x){ +IFile& IFile::scanField(const std::string&name,int &x) { std::string str; scanField(name,str); if(*this) Tools::convert(str,x); return *this; } -IFile& IFile::scanField(Value* val){ +IFile& IFile::scanField(Value* val) { double ff=NAN; // this is to be sure a NAN value is replaced upon failure scanField( val->getName(), ff ); val->set( ff ); - if( FieldExist("min_" + val->getName() ) ){ - std::string min, max; - scanField("min_" + val->getName(), min ); - scanField("max_" + val->getName(), max ); - val->setDomain( min, max ); + if( FieldExist("min_" + val->getName() ) ) { + std::string min, max; + scanField("min_" + val->getName(), min ); + scanField("max_" + val->getName(), max ); + val->setDomain( min, max ); } else { - val->setNotPeriodic(); + val->setNotPeriodic(); } return *this; } -IFile& IFile::scanField(){ - if(!ignoreFields){ - for(unsigned i=0;i0) eof=false; - } else if(eof || err || tmp!='\n'){ + if(eof && noEOL) { + if(str.length()>0) eof=false; + } else if(eof || err || tmp!='\n') { eof = true; str=""; if(!err) fsetpos(fp,&pos); @@ -227,28 +227,28 @@ IFile& IFile::getline(std::string &str){ return *this; } -unsigned IFile::findField(const std::string&name)const{ +unsigned IFile::findField(const std::string&name)const { unsigned i; - for(i=0;i=fields.size()) plumed_merror(name); return i; } -void IFile::reset(bool reset){ - eof = reset; - err = reset; - if(!reset && fp) clearerr(fp); +void IFile::reset(bool reset) { + eof = reset; + err = reset; + if(!reset && fp) clearerr(fp); #ifdef __PLUMED_HAS_ZLIB - if(!reset && gzfp) gzclearerr(gzFile(gzfp)); + if(!reset && gzfp) gzclearerr(gzFile(gzfp)); #endif - return; -} + return; +} -void IFile::allowIgnoredFields(){ +void IFile::allowIgnoredFields() { ignoreFields=true; } -void IFile::allowNoEOL(){ +void IFile::allowNoEOL() { noEOL=true; } diff --git a/src/tools/IFile.h b/src/tools/IFile.h index 222f4a8ead..2d54338df6 100644 --- a/src/tools/IFile.h +++ b/src/tools/IFile.h @@ -25,7 +25,7 @@ #include "FileBase.h" #include -namespace PLMD{ +namespace PLMD { class Value; @@ -39,9 +39,9 @@ but only for sequential input. See OFile for sequential output. */ class IFile: /// Class identifying a single field for fielded output -public virtual FileBase{ + public virtual FileBase { class Field: - public FieldBase{ + public FieldBase { public: bool read; Field(): read(false) {} @@ -66,7 +66,7 @@ public virtual FileBase{ IFile(); /// Destructor ~IFile(); -/// Opens the file +/// Opens the file IFile& open(const std::string&name); /// Gets the list of all fields IFile& scanFieldList(std::vector&); @@ -76,20 +76,20 @@ public virtual FileBase{ IFile& scanField(const std::string&,int&); /// Read a string field IFile& scanField(const std::string&,std::string&); -/** - Ends a field-formatted line. + /** + Ends a field-formatted line. -Typically used as -\verbatim - if.scanField("a",a).scanField("b",b).scanField(); -\endverbatim -*/ + Typically used as + \verbatim + if.scanField("a",a).scanField("b",b).scanField(); + \endverbatim + */ IFile& scanField(); /// Get a full line as a string IFile& getline(std::string&); -/// Reset end of file +/// Reset end of file void reset(bool); -/// Check if a field exist +/// Check if a field exist bool FieldExist(const std::string& s); /// Read in a value IFile& scanField(Value* val); diff --git a/src/tools/KernelFunctions.cpp b/src/tools/KernelFunctions.cpp index 43714d9a96..d5da1a3872 100644 --- a/src/tools/KernelFunctions.cpp +++ b/src/tools/KernelFunctions.cpp @@ -21,7 +21,7 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "KernelFunctions.h" #include "IFile.h" -#include +#include #include namespace PLMD { @@ -30,21 +30,21 @@ namespace PLMD { /* Functions that are used to construct histograms -Constructing histograms is something you learnt to do relatively early in life. You perform an experiment a number of times, -count the number of times each result comes up and then draw a bar graph that describes how often each of the results came up. -This only works when there are a finite number of possible results. If the result a number between 0 and 1 the bar chart is -less easy to draw as there are as many possible results as there are numbers between zero and one - an infinite number. -To resolve this problem we replace probability, \f$P\f$ with probability density, \f$\pi\f$, and write the probability of getting +Constructing histograms is something you learnt to do relatively early in life. You perform an experiment a number of times, +count the number of times each result comes up and then draw a bar graph that describes how often each of the results came up. +This only works when there are a finite number of possible results. If the result a number between 0 and 1 the bar chart is +less easy to draw as there are as many possible results as there are numbers between zero and one - an infinite number. +To resolve this problem we replace probability, \f$P\f$ with probability density, \f$\pi\f$, and write the probability of getting a number between \f$a\f$ and \f$b\f$ as: \f[ -P = \int_{a}^b \textrm{d}x \pi(x) +P = \int_{a}^b \textrm{d}x \pi(x) \f] -To calculate probability densities from a set of results we use a process called kernel density estimation. +To calculate probability densities from a set of results we use a process called kernel density estimation. Histograms are accumulated by adding up kernel functions, \f$K\f$, with finite spatial extent, that integrate to one. These functions are centered on each of the \f$n\f$-dimensional data points, \f$\mathbf{x}_i\f$. The overall effect of this -is that each result we obtain in our experiments contributes to the probability density in a finite sized region of the space. +is that each result we obtain in our experiments contributes to the probability density in a finite sized region of the space. Expressing all this mathematically in kernel density estimation we write the probability density as: @@ -52,17 +52,17 @@ Expressing all this mathematically in kernel density estimation we write the pro \pi(\mathbf{x}) = \sum_i K\left[ (\mathbf{x} - \mathbf{x}_i)^T \Sigma (\mathbf{x} - \mathbf{x}_i) \right] \f] -where \f$\Sigma\f$ is an \f$n \times n\f$ matrix called the bandwidth that controls the spatial extent of -the kernel. Whenever we accumulate a histogram (e.g. in \ref HISTOGRAM or in \ref METAD) we use this -technique. +where \f$\Sigma\f$ is an \f$n \times n\f$ matrix called the bandwidth that controls the spatial extent of +the kernel. Whenever we accumulate a histogram (e.g. in \ref HISTOGRAM or in \ref METAD) we use this +technique. There is thus some flexibility in the particular function we use for \f$K[\mathbf{r}]\f$ in the above. The following variants are available.
TYPE FUNCTION
TYPE FUNCTION
GAUSSIAN \f$\frac{1}{\sqrt{2\pi}w} \exp\left( -\frac{(s-s_i)^2}{2w^2} \right)\f$
TRIANGULAR \f$ \frac{1}{2w} \left( 1. - \left| \frac{s-s_i}{w} \right| \right) \quad \frac{s-s_i}{w}<1 \f$
- - - + + + @@ -79,28 +79,28 @@ space which is given by: \f{eqnarray*}{ V &=& | \Sigma^{-1} | \frac{ \pi^{\frac{n}{2}} }{\left( \frac{n}{2} \right)! } \qquad \textrm{for even} \quad n \\ -V &=& | \Sigma^{-1} | \frac{ 2^{\frac{n+1}{2}} \pi^{\frac{n-1}{2}} }{ n!! } +V &=& | \Sigma^{-1} | \frac{ 2^{\frac{n+1}{2}} \pi^{\frac{n-1}{2}} }{ n!! } \f} In \ref METAD the normalization constants are ignored so that the value of the function at \f$r=0\f$ is equal -to one. In addition in \ref METAD we must be able to differentiate the bias in order to get forces. This limits -the kernels we can use in this method. Notice also that Gaussian kernels should have infinite support. When used -with grids, however, they are assumed to only be non-zero over a finite range. The difference between the +to one. In addition in \ref METAD we must be able to differentiate the bias in order to get forces. This limits +the kernels we can use in this method. Notice also that Gaussian kernels should have infinite support. When used +with grids, however, they are assumed to only be non-zero over a finite range. The difference between the truncated-gaussian and regular gaussian is that the trucated gaussian is scaled so that its integral over the grid -is equal to one when it is normalised. The integral of a regular gaussian when it is evaluated on a grid will be -slightly less that one because of the truncation of a function that should have infinite support. +is equal to one when it is normalised. The integral of a regular gaussian when it is evaluated on a grid will be +slightly less that one because of the truncation of a function that should have infinite support. */ //+ENDPLUMEDOC -KernelFunctions::KernelFunctions( const std::string& input, const bool& normed ){ +KernelFunctions::KernelFunctions( const std::string& input, const bool& normed ) { std::vector data=Tools::getWords(input); std::string name=data[0]; data.erase(data.begin()); - std::vector at; + std::vector at; bool foundc = Tools::parseVector(data,"CENTER",at); if(!foundc) plumed_merror("failed to find center keyword in definition of kernel"); - std::vector sig; + std::vector sig; bool founds = Tools::parseVector(data,"SIGMA",sig); if(!founds) plumed_merror("failed to find sigma keyword in definition of kernel"); @@ -111,68 +111,68 @@ KernelFunctions::KernelFunctions( const std::string& input, const bool& normed ) if( !multi && center.size()>1 && sig.size()!=center.size() ) plumed_merror("size mismatch between center size and sigma size"); double h; - bool foundh = Tools::parse(data,"HEIGHT",h); + bool foundh = Tools::parse(data,"HEIGHT",h); if( !foundh) h=1.0; setData( at, sig, name, multi, h, normed ); } -KernelFunctions::KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ){ +KernelFunctions::KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ) { setData( at, sig, type, multivariate, w, norm ); } -void KernelFunctions::setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ){ +void KernelFunctions::setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate, const double& w, const bool norm ) { - center.resize( at.size() ); for(unsigned i=0;i mymatrix( getMatrix() ), myinv( ncv, ncv ); - Invert(mymatrix,myinv); double logd; - logdet( myinv, logd ); - det=std::exp(logd); + Matrix mymatrix( getMatrix() ), myinv( ncv, ncv ); + Invert(mymatrix,myinv); double logd; + logdet( myinv, logd ); + det=std::exp(logd); } double volume; - if( ktype==gaussian ){ - if( type=="GAUSSIAN" || type=="gaussian" ) volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ); - else { - // This makes it so the gaussian integrates to one over the range over which it has support - const double DP2CUTOFF=sqrt(6.25); - volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ) * pow( 0.5 * ( erf(DP2CUTOFF) - erf(-DP2CUTOFF) ), ncv); - } - } else if( ktype==uniform || ktype==triangular ){ - if( ncv%2==1 ){ - double dfact=1; - for(unsigned i=1;i(i); - volume=( pow( pi, (ncv-1)/2 ) ) * ( pow( 2., (ncv+1)/2 ) ) / dfact; - } else { - double fact=1.; - for(unsigned i=1;i(i); - volume=pow( pi,ncv/2 ) / fact; - } - if(ktype==uniform) volume*=det; - else if(ktype==triangular) volume*=det / 3.; + if( ktype==gaussian ) { + if( type=="GAUSSIAN" || type=="gaussian" ) volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ); + else { + // This makes it so the gaussian integrates to one over the range over which it has support + const double DP2CUTOFF=sqrt(6.25); + volume=pow( 2*pi, 0.5*ncv ) * pow( det, 0.5 ) * pow( 0.5 * ( erf(DP2CUTOFF) - erf(-DP2CUTOFF) ), ncv); + } + } else if( ktype==uniform || ktype==triangular ) { + if( ncv%2==1 ) { + double dfact=1; + for(unsigned i=1; i(i); + volume=( pow( pi, (ncv-1)/2 ) ) * ( pow( 2., (ncv+1)/2 ) ) / dfact; + } else { + double fact=1.; + for(unsigned i=1; i(i); + volume=pow( pi,ncv/2 ) / fact; + } + if(ktype==uniform) volume*=det; + else if(ktype==triangular) volume*=det / 3.; } else { - plumed_merror("not a valid kernel type"); - } - height=w / volume; + plumed_merror("not a valid kernel type"); + } + height=w / volume; } else { height=w; } @@ -188,126 +188,126 @@ double KernelFunctions::getCutoff( const double& width ) const { } std::vector KernelFunctions::getContinuousSupport( ) const { - unsigned ncv=ndim(); + unsigned ncv=ndim(); std::vector support( ncv ); - if(diagonal){ - for(unsigned i=0;i mymatrix( getMatrix() ), myinv( ncv,ncv ); - Invert(mymatrix,myinv); - Matrix myautovec(ncv,ncv); std::vector myautoval(ncv); - diagMat(myinv,myautoval,myautovec); - double maxautoval;maxautoval=0.; - unsigned ind_maxautoval; - for (unsigned i=0;imaxautoval){maxautoval=myautoval[i];ind_maxautoval=i;} - } - for(unsigned i=0;i mymatrix( getMatrix() ), myinv( ncv,ncv ); + Invert(mymatrix,myinv); + Matrix myautovec(ncv,ncv); std::vector myautoval(ncv); + diagMat(myinv,myautoval,myautovec); + double maxautoval; maxautoval=0.; + unsigned ind_maxautoval; + for (unsigned i=0; imaxautoval) {maxautoval=myautoval[i]; ind_maxautoval=i;} + } + for(unsigned i=0; i KernelFunctions::getSupport( const std::vector& dx ) const { plumed_assert( ndim()==dx.size() ); std::vector support( dx.size() ); std::vector vv=getContinuousSupport( ); - for(unsigned i=0;i(ceil( vv[i]/dx[i] )); + for(unsigned i=0; i(ceil( vv[i]/dx[i] )); return support; } double KernelFunctions::evaluate( const std::vector& pos, std::vector& derivatives, bool usederiv, bool doInt, double lowI_, double uppI_) const { plumed_dbg_assert( pos.size()==ndim() && derivatives.size()==ndim() ); #ifndef NDEBUG - if( usederiv ) plumed_massert( ktype!=uniform, "step function can not be differentiated" ); + if( usederiv ) plumed_massert( ktype!=uniform, "step function can not be differentiated" ); #endif - if(doInt){ + if(doInt) { plumed_dbg_assert(center.size()==1); if(pos[0]->get()set(lowI_); if(pos[0]->get()>uppI_) pos[0]->set(uppI_); } double r2=0; - if(diagonal){ - for(unsigned i=0;idifference( center[i] ) / width[i]; - r2+=derivatives[i]*derivatives[i]; - derivatives[i] /= width[i]; - } + if(diagonal) { + for(unsigned i=0; idifference( center[i] ) / width[i]; + r2+=derivatives[i]*derivatives[i]; + derivatives[i] /= width[i]; + } } else { - Matrix mymatrix( getMatrix() ); - for(unsigned i=0;idifference( center[i] ); - for(unsigned j=0;jdifference( center[j] ); - - derivatives[i]+=mymatrix(i,j)*dp_j; - r2+=dp_i*dp_j*mymatrix(i,j); - } - } + Matrix mymatrix( getMatrix() ); + for(unsigned i=0; idifference( center[i] ); + for(unsigned j=0; jdifference( center[j] ); + + derivatives[i]+=mymatrix(i,j)*dp_j; + r2+=dp_i*dp_j*mymatrix(i,j); + } + } } double kderiv, kval; - if(ktype==gaussian){ - kval=height*std::exp(-0.5*r2); kderiv=-kval; + if(ktype==gaussian) { + kval=height*std::exp(-0.5*r2); kderiv=-kval; } else { - double r=sqrt(r2); - if(ktype==triangular){ - if( r<1.0 ){ - if(r==0) kderiv=0; - kderiv=-1; kval=height*( 1. - fabs(r) ); - } else { - kval=0.; kderiv=0.; - } - } else if(ktype==uniform){ - kderiv=0.; - if(r<1.0) kval=height; - else kval=0; - } else { - plumed_merror("Not a valid kernel type"); - } - kderiv*=height / r ; - } - for(unsigned i=0;iget() <= lowI_ || pos[0]->get() >= uppI_) && usederiv ) for(unsigned i=0;iget() <= lowI_ || pos[0]->get() >= uppI_) && usederiv ) for(unsigned i=0; i& valnames ){ +KernelFunctions* KernelFunctions::read( IFile* ifile, const std::vector& valnames ) { std::string sss; ifile->scanField("multivariate",sss); std::vector cc( valnames.size() ), sig; bool multivariate; - if( sss=="false" ){ - multivariate=false; - sig.resize( valnames.size() ); - for(unsigned i=0;iscanField(valnames[i],cc[i]); - ifile->scanField("sigma_"+valnames[i],sig[i]); - } - } else if( sss=="true" ){ - multivariate=true; - unsigned ncv=valnames.size(); - sig.resize( (ncv*(ncv+1))/2 ); - Matrix upper(ncv,ncv), lower(ncv,ncv); - for(unsigned i=0;iscanField(valnames[i],cc[i]); - for(unsigned j=0;jscanField("sigma_" +valnames[j+i] + "_" + valnames[j], lower(j+i,j) ); upper(j,j+i)=lower(j+i,j); } - } - Matrix mymult( ncv, ncv ), invmatrix(ncv,ncv); - mult(lower,upper,mymult); Invert( mymult, invmatrix ); - unsigned k=0; - for(unsigned i=0;iscanField(valnames[i],cc[i]); + ifile->scanField("sigma_"+valnames[i],sig[i]); + } + } else if( sss=="true" ) { + multivariate=true; + unsigned ncv=valnames.size(); + sig.resize( (ncv*(ncv+1))/2 ); + Matrix upper(ncv,ncv), lower(ncv,ncv); + for(unsigned i=0; iscanField(valnames[i],cc[i]); + for(unsigned j=0; jscanField("sigma_" +valnames[j+i] + "_" + valnames[j], lower(j+i,j) ); upper(j,j+i)=lower(j+i,j); } + } + Matrix mymult( ncv, ncv ), invmatrix(ncv,ncv); + mult(lower,upper,mymult); Invert( mymult, invmatrix ); + unsigned k=0; + for(unsigned i=0; iscanField("height",h); - return new KernelFunctions( cc, sig, "gaussian", multivariate ,h, false); + return new KernelFunctions( cc, sig, "gaussian", multivariate,h, false); } } diff --git a/src/tools/KernelFunctions.h b/src/tools/KernelFunctions.h index 381b831d50..a7535e0b28 100644 --- a/src/tools/KernelFunctions.h +++ b/src/tools/KernelFunctions.h @@ -42,23 +42,23 @@ class KernelFunctions { /// The height of the kernel double height; /// Used to set all the data in the kernel during construction - avoids double coding as this has two constructors - void setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate ,const double& w, const bool norm ); + void setData( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate,const double& w, const bool norm ); /// Convert the width into matrix form Matrix getMatrix() const; public: KernelFunctions( const std::string& input, const bool& normed ); - KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate ,const double& w, const bool norm ); + KernelFunctions( const std::vector& at, const std::vector& sig, const std::string& type, const bool multivariate,const double& w, const bool norm ); /// Get the dimensionality of the kernel unsigned ndim() const; /// Get the cutoff for a kernel double getCutoff( const double& width ) const ; -/// Get the position of the center +/// Get the position of the center std::vector getCenter() const; /// Get the support - std::vector getSupport( const std::vector& dx ) const; + std::vector getSupport( const std::vector& dx ) const; /// get it in continuous form - std::vector getContinuousSupport( ) const; -/// Evaluate the kernel function with constant intervals + std::vector getContinuousSupport( ) const; +/// Evaluate the kernel function with constant intervals double evaluate( const std::vector& pos, std::vector& derivatives, bool usederiv=true, bool doInt=false, double lowI_=-1, double uppI_=-1 ) const; /// Read a kernel function from a file static KernelFunctions* read( IFile* ifile, const std::vector& valnames ); @@ -66,11 +66,11 @@ class KernelFunctions { inline Matrix KernelFunctions::getMatrix() const { - unsigned k=0, ncv=ndim(); Matrix mymatrix(ncv,ncv); - for(unsigned i=0;i mymatrix(ncv,ncv); + for(unsigned i=0; i -namespace PLMD{ - -Keywords::KeyType::KeyType( const std::string& type ){ - if( type=="compulsory" ){ - style=compulsory; - } else if( type=="flag" ){ - style=flag; - } else if( type=="optional" ){ - style=optional; - } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ){ - style=atoms; - } else if( type=="hidden" ){ - style=hidden; - } else if( type=="vessel" ){ - style=vessel; +namespace PLMD { + +Keywords::KeyType::KeyType( const std::string& type ) { + if( type=="compulsory" ) { + style=compulsory; + } else if( type=="flag" ) { + style=flag; + } else if( type=="optional" ) { + style=optional; + } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) { + style=atoms; + } else if( type=="hidden" ) { + style=hidden; + } else if( type=="vessel" ) { + style=vessel; } else { - plumed_massert(false,"invalid keyword specifier " + type); - } -} - -void Keywords::KeyType::setStyle( const std::string& type ){ - if( type=="compulsory" ){ - style=compulsory; - } else if( type=="flag" ){ - style=flag; - } else if( type=="optional" ){ - style=optional; - } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ){ - style=atoms; - } else if( type=="hidden" ){ - style=hidden; - } else if( type=="vessel" ){ - style=vessel; + plumed_massert(false,"invalid keyword specifier " + type); + } +} + +void Keywords::KeyType::setStyle( const std::string& type ) { + if( type=="compulsory" ) { + style=compulsory; + } else if( type=="flag" ) { + style=flag; + } else if( type=="optional" ) { + style=optional; + } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ) { + style=atoms; + } else if( type=="hidden" ) { + style=hidden; + } else if( type=="vessel" ) { + style=vessel; } else { - plumed_massert(false,"invalid keyword specifier " + type); - } + plumed_massert(false,"invalid keyword specifier " + type); + } } -void Keywords::add( const Keywords& newkeys ){ - newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs ); +void Keywords::add( const Keywords& newkeys ) { + newkeys.copyData( keys, reserved_keys, types, allowmultiple, documentation, booldefs, numdefs, atomtags, cnames, ckey, cdocs ); } -void Keywords::copyData( std::vector& kk, std::vector& rk, std::map& tt, std::map& am, +void Keywords::copyData( std::vector& kk, std::vector& rk, std::map& tt, std::map& am, std::map& docs, std::map& bools, std::map& nums, std::map& atags, std::vector& cnam, std::map& ck, std::map& cd ) const { - for(unsigned i=0;i( thiskey,types.find(thiskey)->second) ); - if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); - plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); - am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); - plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); - docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); - if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); - if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); - } - for(unsigned i=0;i( thiskey,types.find(thiskey)->second) ); - if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); - plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); - am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); - plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); - docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); - if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); - if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); - } - for(unsigned i=0;i( thisnam, ckey.find(thisnam)->second) ); - plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" ); - cd.insert( std::pair( thisnam, cdocs.find(thisnam)->second) ); - } -} - -void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ){ + for(unsigned i=0; i( thiskey,types.find(thiskey)->second) ); + if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); + plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); + am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); + plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); + docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); + if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); + if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); + } + for(unsigned i=0; i( thiskey,types.find(thiskey)->second) ); + if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair( thiskey,atomtags.find(thiskey)->second) ); + plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" ); + am.insert( std::pair(thiskey,allowmultiple.find(thiskey)->second) ); + plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" ); + docs.insert( std::pair(thiskey,documentation.find(thiskey)->second) ); + if( booldefs.count( thiskey ) ) bools.insert( std::pair( thiskey,booldefs.find(thiskey)->second) ); + if( numdefs.count( thiskey ) ) nums.insert( std::pair( thiskey,numdefs.find(thiskey)->second) ); + } + for(unsigned i=0; i( thisnam, ckey.find(thisnam)->second) ); + plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" ); + cd.insert( std::pair( thisnam, cdocs.find(thisnam)->second) ); + } +} + +void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d ) { plumed_assert( !exists(k) && !reserved(k) ); std::string fd, lowkey=k; // Convert to lower case std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower); - // Remove any underscore characters - for(unsigned i=0;;++i){ - std::size_t num=lowkey.find_first_of("_"); - if( num==std::string::npos ) break; - lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 ); - } - if( t=="vessel" ){ - fd = d + " The final value can be referenced using label." + lowkey; - if(d.find("flag")==std::string::npos) fd += ". You can use multiple instances of this keyword i.e. " + - k +"1, " + k + "2, " + k + "3... The corresponding values are then " - "referenced using label."+ lowkey +"-1, label." + lowkey + - "-2, label." + lowkey + "-3..."; - allowmultiple.insert( std::pair(k,true) ); - types.insert( std::pair(k,KeyType("vessel")) ); - } else if( t=="numbered" ){ - fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; - allowmultiple.insert( std::pair(k,true) ); - types.insert( std::pair(k,KeyType("optional")) ); +// Remove any underscore characters + for(unsigned i=0;; ++i) { + std::size_t num=lowkey.find_first_of("_"); + if( num==std::string::npos ) break; + lowkey.erase( lowkey.begin() + num, lowkey.begin() + num + 1 ); + } + if( t=="vessel" ) { + fd = d + " The final value can be referenced using label." + lowkey; + if(d.find("flag")==std::string::npos) fd += ". You can use multiple instances of this keyword i.e. " + + k +"1, " + k + "2, " + k + "3... The corresponding values are then " + "referenced using label."+ lowkey +"-1, label." + lowkey + + "-2, label." + lowkey + "-3..."; + allowmultiple.insert( std::pair(k,true) ); + types.insert( std::pair(k,KeyType("vessel")) ); + } else if( t=="numbered" ) { + fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; + allowmultiple.insert( std::pair(k,true) ); + types.insert( std::pair(k,KeyType("optional")) ); } else { - fd = d; - if( t=="atoms" && isaction ) fd = d + ". For more information on how to specify lists of atoms see \\ref Group"; - allowmultiple.insert( std::pair(k,false) ); - types.insert( std::pair(k,KeyType(t)) ); - if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); + fd = d; + if( t=="atoms" && isaction ) fd = d + ". For more information on how to specify lists of atoms see \\ref Group"; + allowmultiple.insert( std::pair(k,false) ); + types.insert( std::pair(k,KeyType(t)) ); + if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); } - documentation.insert( std::pair(k,fd) ); - reserved_keys.push_back(k); + documentation.insert( std::pair(k,fd) ); + reserved_keys.push_back(k); } -void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ){ - plumed_assert( !exists(k) && !reserved(k) ); +void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d ) { + plumed_assert( !exists(k) && !reserved(k) ); std::string defstr; if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; } types.insert( std::pair(k,KeyType("flag")) ); std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower); fd=defstr + d; - documentation.insert( std::pair(k,fd) ); + documentation.insert( std::pair(k,fd) ); allowmultiple.insert( std::pair(k,false) ); - booldefs.insert( std::pair(k,def) ); - reserved_keys.push_back(k); + booldefs.insert( std::pair(k,def) ); + reserved_keys.push_back(k); } -void Keywords::use( const std::string & k ){ +void Keywords::use( const std::string & k ) { plumed_massert( reserved(k), "the " + k + " keyword is not reserved"); - for(unsigned i=0;isecond).setStyle(style); - if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true; + if( (types.find(k)->second).isVessel() ) allowmultiple[k]=true; if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,style) ); } -void Keywords::add( const std::string & t, const std::string & k, const std::string & d ){ - plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel" , "keyword " + k + " has already been registered"); +void Keywords::add( const std::string & t, const std::string & k, const std::string & d ) { + plumed_massert( !exists(k) && t!="flag" && !reserved(k) && t!="vessel", "keyword " + k + " has already been registered"); std::string fd; - if( t=="numbered" ){ - fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; - allowmultiple.insert( std::pair(k,true) ); - types.insert( std::pair(k, KeyType("optional")) ); - } else { - fd=d; - allowmultiple.insert( std::pair(k,false) ); - types.insert( std::pair(k,KeyType(t)) ); - if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); + if( t=="numbered" ) { + fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3..."; + allowmultiple.insert( std::pair(k,true) ); + types.insert( std::pair(k, KeyType("optional")) ); + } else { + fd=d; + allowmultiple.insert( std::pair(k,false) ); + types.insert( std::pair(k,KeyType(t)) ); + if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair(k,t) ); } if( t=="atoms" && isaction ) fd = d + ". For more information on how to specify lists of atoms see \\ref Group"; documentation.insert( std::pair(k,fd) ); - keys.push_back(k); + keys.push_back(k); } -void Keywords::add( const std::string & t, const std::string & k, const std::string & def, const std::string & d ){ +void Keywords::add( const std::string & t, const std::string & k, const std::string & def, const std::string & d ) { plumed_assert( !exists(k) && !reserved(k) && (t=="compulsory" || t=="hidden" )); // An optional keyword can't have a default - types.insert( std::pair(k, KeyType(t)) ); + types.insert( std::pair(k, KeyType(t)) ); documentation.insert( std::pair(k,"( default=" + def + " ) " + d) ); allowmultiple.insert( std::pair(k,false) ); numdefs.insert( std::pair(k,def) ); - keys.push_back(k); -} + keys.push_back(k); +} -void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ){ - plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered"); +void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ) { + plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered"); std::string defstr; if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; } types.insert( std::pair(k,KeyType("flag")) ); documentation.insert( std::pair(k,defstr + d) ); allowmultiple.insert( std::pair(k,false) ); - booldefs.insert( std::pair(k,def) ); - keys.push_back(k); -} + booldefs.insert( std::pair(k,def) ); + keys.push_back(k); +} -void Keywords::remove( const std::string & k ){ +void Keywords::remove( const std::string & k ) { bool found=false; unsigned j=0, n=0; - while(true){ - for(j=0;jsecond).toString()==t ) return true; - return false; + return false; } unsigned Keywords::size() const { @@ -252,15 +252,15 @@ std::string Keywords::getKeyword( const unsigned i ) const { } bool Keywords::exists( const std::string & k ) const { - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if( nkeys>0 ){ + if( nkeys>0 ) { std::string prevtag="start"; - for(unsigned i=0;isecond).isAtomList() ){ - plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); - if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break; - if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=", keys[i].c_str() ); - else printf(" %s=", keys[i].c_str() ); - prevtag=atomtags.find(keys[i])->second; - } + for(unsigned i=0; isecond).isAtomList() ) { + plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); + if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break; + if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=", keys[i].c_str() ); + else printf(" %s=", keys[i].c_str() ); + prevtag=atomtags.find(keys[i])->second; + } } } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; - } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isCompulsory() ){ - std::string def; - if( getDefaultValue( keys[i], def) ){ - printf(" %s=%s ", keys[i].c_str(), def.c_str() ); - } else { - printf(" %s= ", keys[i].c_str() ); - } - } else if (include_optional) { - // TG no defaults for optional keywords? - printf(" [%s]", keys[i].c_str() ); - } - } + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; + } + if( nkeys>0 ) { + for(unsigned i=0; isecond).isCompulsory() ) { + std::string def; + if( getDefaultValue( keys[i], def) ) { + printf(" %s=%s ", keys[i].c_str(), def.c_str() ); + } else { + printf(" %s= ", keys[i].c_str() ); + } + } else if (include_optional) { + // TG no defaults for optional keywords? + printf(" [%s]", keys[i].c_str() ); + } + } } printf("\n"); } void Keywords::print_vim() const { - for(unsigned i=0;isecond).isFlag() ){ - printf( ",flag:%s", keys[i].c_str() ); - } else { - if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() ); - else printf(",option:%s",keys[i].c_str() ); - } + for(unsigned i=0; isecond).isFlag() ) { + printf( ",flag:%s", keys[i].c_str() ); + } else { + if( allowmultiple.find(keys[i])->second ) printf(",numbered:%s",keys[i].c_str() ); + else printf(",option:%s",keys[i].c_str() ); + } } fprintf(stdout,"\n"); print(stdout); @@ -322,171 +322,171 @@ void Keywords::print_vim() const { void Keywords::print_html() const { // This is the part that outputs the details of the components - if( cnames.size()>0 ){ - unsigned ndef=0; - for(unsigned i=0;isecond=="default") ndef++; - } + if( cnames.size()>0 ) { + unsigned ndef=0; + for(unsigned i=0; isecond=="default") ndef++; + } - if( ndef>0 ){ - std::cout<<"\\par Description of components\n\n"; - std::cout< \n"; - printf("\n"); - unsigned nndef=0; - for(unsigned i=0;isecond=="default" ); - if( ckey.find(cnames[i])->second!="default" ){ nndef++; continue; } + if( ndef>0 ) { + std::cout<<"\\par Description of components\n\n"; + std::cout< \n"; + printf("\n"); + unsigned nndef=0; + for(unsigned i=0; isecond=="default" ); + if( ckey.find(cnames[i])->second!="default" ) { nndef++; continue; } + printf("\n"); + printf("\n",cnames[i].c_str() ); + printf("\n",(cdocs.find(cnames[i])->second).c_str() ); + printf("\n"); + } + std::cout<<"
TYPE FUNCTION
TYPE FUNCTION
gaussian \f$f(r) = \frac{1}{(2 \pi)^{n} \sqrt{|\Sigma^{-1}|}} \exp\left(-0.5 r^2 \right)\f$
truncated-gaussian \f$f(r) = \frac{1}{(2 \pi)^{n} \sqrt{|\Sigma^{-1}|} \left(\frac{\erf(-6.25/sqrt{2}) - \erf(-6.25/sqrt{2})}{2}\right)^n} \exp\left(-0.5 r^2 \right)\f$
Quantity Description
Quantity Description
%s %s
\n\n"; + if( nndef>0 ) { + std::cout<<"In addition the following quantities can be calculated by employing the keywords listed below"< \n"; + printf(" Quantity Keyword Description \n"); + for(unsigned i=0; isecond!="default") { printf("\n"); - printf(" %s \n",cnames[i].c_str() ); + printf(" %s %s \n", + cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); printf("\n"); - } - std::cout<<"\n\n"; - if( nndef>0 ){ - std::cout<<"In addition the following quantities can be calculated by employing the keywords listed below"< \n"; - printf(" Quantity Keyword Description \n"); - for(unsigned i=0;isecond!="default"){ - printf("\n"); - printf(" %s %s \n", - cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); - printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); - printf("\n"); - } - } - std::cout<<"\n\n"; - } - } else { - unsigned nregs=0; - for(unsigned i=0;isecond) ) nregs++; - } - if( nregs>0 ){ - std::cout<<"\\par Description of components\n\n"; - std::cout< \n"; - printf(" Quantity Keyword Description \n"); - for(unsigned i=0;isecond) ){ - printf("\n"); - printf(" %s %s \n", - cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); - printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); - printf("\n"); - } - } - std::cout<<"\n\n"; - } + } + } + std::cout<<"\n\n"; + } + } else { + unsigned nregs=0; + for(unsigned i=0; isecond) ) nregs++; + } + if( nregs>0 ) { + std::cout<<"\\par Description of components\n\n"; + std::cout< \n"; + printf(" Quantity Keyword Description \n"); + for(unsigned i=0; isecond) ) { + printf("\n"); + printf(" %s %s \n", + cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() ); + printf(" %s \n",(cdocs.find(cnames[i])->second).c_str() ); + printf("\n"); + } + } + std::cout<<"\n\n"; } + } } unsigned nkeys=0; - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if( nkeys>0 ){ + if( nkeys>0 ) { if(isaction) std::cout<<"\\par The atoms involved can be specified using\n\n"; else std::cout<<"\\par The input trajectory is specified using one of the following\n\n"; std::cout<<" \n"; std::string prevtag="start"; - for(unsigned i=0;isecond).isAtomList() ){ - plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); - if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ){ - std::cout<<"
\n\n"; - std::cout<<"\\par Or alternatively by using\n\n"; - std::cout<<" \n"; - } - print_html_item( keys[i] ); - prevtag=atomtags.find(keys[i])->second; + for(unsigned i=0; isecond).isAtomList() ) { + plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello"); + if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ) { + std::cout<<"
\n\n"; + std::cout<<"\\par Or alternatively by using\n\n"; + std::cout<<" \n"; } + print_html_item( keys[i] ); + prevtag=atomtags.find(keys[i])->second; + } } std::cout<<"
\n\n"; } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; - } - if( nkeys>0 ){ - if(isaction) std::cout<< "\\par Compulsory keywords\n\n"; - else std::cout<<"\\par The following must be present\n\n"; - std::cout<<" \n"; - for(unsigned i=0;isecond).isCompulsory() ) print_html_item( keys[i] ); - } - std::cout<<"
\n\n"; + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; + } + if( nkeys>0 ) { + if(isaction) std::cout<< "\\par Compulsory keywords\n\n"; + else std::cout<<"\\par The following must be present\n\n"; + std::cout<<" \n"; + for(unsigned i=0; isecond).isCompulsory() ) print_html_item( keys[i] ); + } + std::cout<<"
\n\n"; } nkeys=0; - for(unsigned i=0;isecond).isFlag() || (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; - } - if( nkeys>0 ){ - if(isaction) std::cout<<"\\par Options\n\n"; - else std::cout<<"\\par The following options are available\n\n"; - std::cout<<" \n"; - for(unsigned i=0;isecond).isFlag() ) print_html_item( keys[i] ); - } - std::cout<<"\n"; + for(unsigned i=0; isecond).isFlag() || (types.find(keys[i])->second).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; + } + if( nkeys>0 ) { + if(isaction) std::cout<<"\\par Options\n\n"; + else std::cout<<"\\par The following options are available\n\n"; + std::cout<<"
\n"; + for(unsigned i=0; isecond).isFlag() ) print_html_item( keys[i] ); + } + std::cout<<"\n"; } nkeys=0; - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) print_html_item( keys[i] ); - } - std::cout<<"\n"; + if( nkeys>0 ) { + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) print_html_item( keys[i] ); + } + std::cout<<"\n"; } std::cout<<"
\n\n"; } void Keywords::print( FILE* out ) const { unsigned nkeys=0; - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if( nkeys>0 ){ - fprintf(out,"The input trajectory can be in any of the following formats: \n\n"); - for(unsigned i=0;isecond).isAtomList() ) printKeyword( keys[i], out ); - } + if( nkeys>0 ) { + fprintf(out,"The input trajectory can be in any of the following formats: \n\n"); + for(unsigned i=0; isecond).isAtomList() ) printKeyword( keys[i], out ); + } } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; } unsigned ncompulsory=nkeys; - if( nkeys>0 ){ - fprintf(out,"\nThe following arguments are compulsory: \n\n"); - for(unsigned i=0;isecond).isCompulsory() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); - } - } - nkeys=0; - for(unsigned i=0;isecond).isFlag() ) nkeys++; - } - if( nkeys>0 ){ - if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n"); - else fprintf( out,"\nThe following options are available\n\n"); - for(unsigned i=0;isecond).isFlag() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); - } + if( nkeys>0 ) { + fprintf(out,"\nThe following arguments are compulsory: \n\n"); + for(unsigned i=0; isecond).isCompulsory() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + } + nkeys=0; + for(unsigned i=0; isecond).isFlag() ) nkeys++; + } + if( nkeys>0 ) { + if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n"); + else fprintf( out,"\nThe following options are available\n\n"); + for(unsigned i=0; isecond).isFlag() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } } nkeys=0; - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) nkeys++; } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); - } - fprintf(out,"\n"); + if( nkeys>0 ) { + for(unsigned i=0; isecond).isOptional() || (types.find(keys[i])->second).isVessel() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + fprintf(out,"\n"); } } @@ -495,59 +495,59 @@ void Keywords::printKeyword( const std::string& key, FILE* out ) const { std::vector w=Tools::getWords( documentation.find(key)->second ); fprintf(out,"%23s - ", key.c_str() ); unsigned nl=0; std::string blank=" "; - for(unsigned i=0;i60 ){ - fprintf(out,"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; - } else { - fprintf(out,"%s ", w[i].c_str() ); - } - if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot + for(unsigned i=0; i60 ) { + fprintf(out,"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; + } else { + fprintf(out,"%s ", w[i].c_str() ); + } + if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot } fprintf(out,"\n"); } void Keywords::print( Log& log ) const { unsigned nkeys=0; - for(unsigned i=0;isecond).isAtomList() ) nkeys++; + for(unsigned i=0; isecond).isAtomList() ) nkeys++; } - if (nkeys>0 ){ - log.printf( "The input for this keyword can be specified using one of the following \n\n"); - for(unsigned i=0;isecond).isAtomList() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } + if (nkeys>0 ) { + log.printf( "The input for this keyword can be specified using one of the following \n\n"); + for(unsigned i=0; isecond).isAtomList() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } } nkeys=0; - for(unsigned i=0;isecond).isCompulsory() ) nkeys++; + for(unsigned i=0; isecond).isCompulsory() ) nkeys++; } - if( nkeys>0 ){ - log.printf( "\n The compulsory keywords for this action are: \n\n"); - for(unsigned i=0;isecond).isCompulsory() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } + if( nkeys>0 ) { + log.printf( "\n The compulsory keywords for this action are: \n\n"); + for(unsigned i=0; isecond).isCompulsory() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } } nkeys=0; - for(unsigned i=0;isecond).isFlag() ) nkeys++; + for(unsigned i=0; isecond).isFlag() ) nkeys++; } - if( nkeys>0 ){ - log.printf( "\n The following options are available: \n\n"); - for(unsigned i=0;isecond).isFlag() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } - log.printf("\n"); + if( nkeys>0 ) { + log.printf( "\n The following options are available: \n\n"); + for(unsigned i=0; isecond).isFlag() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } + log.printf("\n"); } nkeys=0; - for(unsigned i=0;isecond).isOptional() ) nkeys++; + for(unsigned i=0; isecond).isOptional() ) nkeys++; } - if( nkeys>0 ){ - for(unsigned i=0;isecond).isOptional() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); - } - log.printf("\n"); + if( nkeys>0 ) { + for(unsigned i=0; isecond).isOptional() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] ); + } + log.printf("\n"); } } @@ -556,14 +556,14 @@ void Keywords::printKeyword( const std::string& key, Log& log ) const { std::vector w=Tools::getWords( documentation.find(key)->second ); log.printf("%23s - ", key.c_str() ); unsigned nl=0; std::string blank=" "; - for(unsigned i=0;i60 ){ - log.printf("\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; - } else { - log.printf("%s ", w[i].c_str() ); - } - if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot + for(unsigned i=0; i60 ) { + log.printf("\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; + } else { + log.printf("%s ", w[i].c_str() ); + } + if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot } log.printf("\n"); } @@ -581,42 +581,42 @@ std::string Keywords::get( const unsigned k ) const { } bool Keywords::getLogicalDefault( std::string key, bool& def ) const { - if( booldefs.find(key)!=booldefs.end() ){ - def=booldefs.find(key)->second; - return true; - } else { - return false; - } + if( booldefs.find(key)!=booldefs.end() ) { + def=booldefs.find(key)->second; + return true; + } else { + return false; + } } bool Keywords::getDefaultValue( std::string key, std::string& def ) const { - plumed_assert( style(key,"compulsory") || style(key,"hidden") ); + plumed_assert( style(key,"compulsory") || style(key,"hidden") ); - if( numdefs.find(key)!=numdefs.end() ){ - def=numdefs.find(key)->second; - return true; - } else { - return false; - } + if( numdefs.find(key)!=numdefs.end() ) { + def=numdefs.find(key)->second; + return true; + } else { + return false; + } } -void Keywords::destroyData(){ - keys.clear(); reserved_keys.clear(); types.clear(); - allowmultiple.clear(); documentation.clear(); - booldefs.clear(); numdefs.clear(); atomtags.clear(); - ckey.clear(); cdocs.clear(); ckey.clear(); +void Keywords::destroyData() { + keys.clear(); reserved_keys.clear(); types.clear(); + allowmultiple.clear(); documentation.clear(); + booldefs.clear(); numdefs.clear(); atomtags.clear(); + ckey.clear(); cdocs.clear(); ckey.clear(); } -void Keywords::setComponentsIntroduction( const std::string& instr ){ +void Keywords::setComponentsIntroduction( const std::string& instr ) { cstring = instr; } -void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ){ +void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ) { plumed_assert( !outputComponentExists( name, false ) ); plumed_massert( name.find("-")==std::string::npos,"dash is reseved character in component names" ); std::size_t num2=name.find_first_of("_"); - if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning"); + if( num2!=std::string::npos ) plumed_massert( num2==0, "underscore is reserved character in component names that has special meaning"); ckey.insert( std::pair(name,key) ); cdocs.insert( std::pair(name,descr) ); @@ -629,15 +629,15 @@ bool Keywords::outputComponentExists( const std::string& name, const bool& custo std::string sname; std::size_t num=name.find_first_of("-"); if( num!=std::string::npos ) sname=name.substr(0,num); else { - std::size_t num2=name.find_first_of("_"); - if( num2!=std::string::npos ) sname=name.substr(num2); - else sname=name; + std::size_t num2=name.find_first_of("_"); + if( num2!=std::string::npos ) sname=name.substr(num2); + else sname=name; } - for(unsigned i=0;i documentation; /// The default values for the flags (are they on or of) - std::map booldefs; + std::map booldefs; /// The default values (if there are default values) for compulsory keywords std::map numdefs; /// The tags for atoms - we use this so the manual can differentiate between different ways of specifying atoms @@ -94,12 +94,12 @@ friend class Action; /// Constructor Keywords() : isaction(true) {} /// - void isDriver(){ isaction=false; } + void isDriver() { isaction=false; } /// find out whether flag key is on or off by default. bool getLogicalDefault( std::string key, bool& def ) const ; /// Get the value of the default for the keyword named key bool getDefaultValue( std::string key, std::string& def ) const ; -/// Return the number of defined keywords +/// Return the number of defined keywords unsigned size() const; /// Check if numbered keywords are allowed for this action bool numbered( const std::string & k ) const ; @@ -109,7 +109,7 @@ friend class Action; void print( Log& log ) const ; /// Print the documentation to a file (use by PLUMED::CLTool::readCommandLineArgs) void print( FILE* out ) const ; -/// Reserve a keyword +/// Reserve a keyword void reserve( const std::string & t, const std::string & k, const std::string & d ); /// Reserve a flag void reserveFlag( const std::string & k, const bool def, const std::string & d ); @@ -143,9 +143,9 @@ friend class Action; void add( const Keywords& keys ); /// Copy the keywords data void copyData( std::vector& kk, std::vector& rk, std::map& tt, std::map& am, - std::map& docs, std::map& bools, std::map& nums, - std::map& atags, std::vector& cnam, std::map& ck, - std::map& cd ) const ; + std::map& docs, std::map& bools, std::map& nums, + std::map& atags, std::vector& cnam, std::map& ck, + std::map& cd ) const ; /// Clear everything from the keywords object void destroyData(); /// Set the text that introduces how the components for this action are introduced diff --git a/src/tools/LatticeReduction.cpp b/src/tools/LatticeReduction.cpp index e8658025d2..c0bc6b1d03 100644 --- a/src/tools/LatticeReduction.cpp +++ b/src/tools/LatticeReduction.cpp @@ -23,26 +23,26 @@ #include "Exception.h" #include -namespace PLMD{ +namespace PLMD { using namespace std; const double epsilon=1e-14; -void LatticeReduction::sort(Vector v[3]){ +void LatticeReduction::sort(Vector v[3]) { const double onePlusEpsilon=(1.0+epsilon); - for(int i=0;i<3;i++) for(int j=i+1;j<3;j++) if(modulo2(v[i])>modulo2(v[j])){ - Vector x=v[i]; v[i]=v[j]; v[j]=x; - } - for(int i=0;i<2;i++) plumed_assert(modulo2(v[i])<=modulo2(v[i+1])*onePlusEpsilon); + for(int i=0; i<3; i++) for(int j=i+1; j<3; j++) if(modulo2(v[i])>modulo2(v[j])) { + Vector x=v[i]; v[i]=v[j]; v[j]=x; + } + for(int i=0; i<2; i++) plumed_assert(modulo2(v[i])<=modulo2(v[i+1])*onePlusEpsilon); } -void LatticeReduction::reduce(Vector&a,Vector&b){ +void LatticeReduction::reduce(Vector&a,Vector&b) { double ma=modulo2(a); double mb=modulo2(b); unsigned counter=0; - while(true){ - if(mb>ma){ + while(true) { + if(mb>ma) { Vector t(a); a=b; b=t; double mt(ma); ma=mb; mb=mt; } @@ -56,16 +56,16 @@ void LatticeReduction::reduce(Vector&a,Vector&b){ Vector t(a); a=b; b=t; } -void LatticeReduction::reduce2(Vector&a,Vector&b,Vector&c){ +void LatticeReduction::reduce2(Vector&a,Vector&b,Vector&c) { Vector v[3]; v[0]=a; v[1]=b; v[2]=c; int iter=0; int ok=0; - while(ok<3){ + while(ok<3) { int i,j; - if(iter%3==0){ + if(iter%3==0) { i=0; j=1; - } else if(iter%3==1){ + } else if(iter%3==1) { i=0; j=2; } else { i=1; j=2; @@ -80,15 +80,15 @@ void LatticeReduction::reduce2(Vector&a,Vector&b,Vector&c){ a=v[0]; b=v[1]; c=v[2]; } -bool LatticeReduction::isReduced(const Vector&a,const Vector&b){ +bool LatticeReduction::isReduced(const Vector&a,const Vector&b) { const int cut=5; - for(int i=-cut;i<=cut;i++){ + for(int i=-cut; i<=cut; i++) { if(modulo2(b+i*a)=modulo2(v[2])) break; counter++; if(counter%10000==0) fprintf(stderr,"WARNING: LatticeReduction::reduceFast stuck after %u iterations\n",counter); @@ -148,7 +148,7 @@ void LatticeReduction::reduceFast(Tensor&t){ } -void LatticeReduction::reduceSlow(Tensor&t){ +void LatticeReduction::reduceSlow(Tensor&t) { Vector v[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); @@ -157,14 +157,14 @@ void LatticeReduction::reduceSlow(Tensor&t){ double e01=dotProduct(v[0],v[1]); double e02=dotProduct(v[0],v[2]); double e12=dotProduct(v[1],v[2]); - if(e01*e02*e12<0){ + if(e01*e02*e12<0) { int eps01=0; if(e01>0.0) eps01=1; else if(e01<0.0) eps01=-1; int eps02=0; if(e02>0.0) eps02=1; else if(e02<0.0) eps02=-1; Vector n=v[0]-eps01*v[1]-eps02*v[2]; int i=0; double mx=modulo2(v[i]); - for(int j=1;j<3;j++){ + for(int j=1; j<3; j++) { double f=modulo2(v[j]); - if(f>mx){ + if(f>mx) { i=j; mx=f; } @@ -177,23 +177,23 @@ void LatticeReduction::reduceSlow(Tensor&t){ t.setRow(2,v[2]); } -bool LatticeReduction::isReduced2(const Vector&a,const Vector&b,const Vector &c){ +bool LatticeReduction::isReduced2(const Vector&a,const Vector&b,const Vector &c) { return isReduced(a,b) && isReduced(a,b) && isReduced(b,c); } -bool LatticeReduction::isReduced(const Tensor&t){ +bool LatticeReduction::isReduced(const Tensor&t) { Vector v[3]; double m[3]; v[0]=t.getRow(0); v[1]=t.getRow(1); v[2]=t.getRow(2); - for(int i=0;i<3;i++) m[i]=modulo2(v[i]); + for(int i=0; i<3; i++) m[i]=modulo2(v[i]); if(!((m[0]<=m[1]) && m[1]<=m[2])) return false; const int cut=5; - for(int i=-cut;i<=cut;i++){ + for(int i=-cut; i<=cut; i++) { double mm=modulo2(v[1]+i*v[0]); if(mm& pos, const std::vector& indices, const Pbc& pbc ){ +void LinkCells::buildCellLists( const std::vector& pos, const std::vector& indices, const Pbc& pbc ) { plumed_assert( cutoffwasset && pos.size()==indices.size() ); // Must be able to check that pbcs are not nonsensical in some way?? -- GAT @@ -51,54 +51,54 @@ void LinkCells::buildCellLists( const std::vector& pos, const std::vecto mypbc.setBox( pbc.getBox() ); // Setup the lists - if( pos.size()!=allcells.size() ){ - allcells.resize( pos.size() ); lcell_lists.resize( pos.size() ); + if( pos.size()!=allcells.size() ) { + allcells.resize( pos.size() ); lcell_lists.resize( pos.size() ); } - { + { // This is the reciprocal lattice // notice that reciprocal.getRow(0) is a vector that is orthogonal to b and c // This allows to use linked cells in non orthorhomic boxes - Tensor reciprocal(transpose(mypbc.getInvBox())); - ncells[0] = std::floor( 1.0/ reciprocal.getRow(0).modulo() / link_cutoff ); - if( ncells[0]==0 ) ncells[0]=1; - ncells[1] = std::floor( 1.0/ reciprocal.getRow(1).modulo() / link_cutoff ); - if( ncells[1]==0 ) ncells[1]=1; - ncells[2] = std::floor( 1.0/ reciprocal.getRow(2).modulo() / link_cutoff ); - if( ncells[2]==0 ) ncells[2]=1; + Tensor reciprocal(transpose(mypbc.getInvBox())); + ncells[0] = std::floor( 1.0/ reciprocal.getRow(0).modulo() / link_cutoff ); + if( ncells[0]==0 ) ncells[0]=1; + ncells[1] = std::floor( 1.0/ reciprocal.getRow(1).modulo() / link_cutoff ); + if( ncells[1]==0 ) ncells[1]=1; + ncells[2] = std::floor( 1.0/ reciprocal.getRow(2).modulo() / link_cutoff ); + if( ncells[2]==0 ) ncells[2]=1; } // Setup the strides nstride[0]=1; nstride[1]=ncells[0]; nstride[2]=ncells[0]*ncells[1]; // Setup the storage for link cells unsigned ncellstot=ncells[0]*ncells[1]*ncells[2]; - if( lcell_tots.size()!=ncellstot ){ - lcell_tots.resize( ncellstot ); lcell_starts.resize( ncellstot ); + if( lcell_tots.size()!=ncellstot ) { + lcell_tots.resize( ncellstot ); lcell_starts.resize( ncellstot ); } // Clear nlcells - for(unsigned i=0;i celn( findMyCell( pos ) ); - for(int nx=LINKC_MIN(ncells[0]);nx LinkCells::findMyCell( const Vector& pos ) const { Vector fpos=mypbc.realToScaled( pos ); std::vector celn(3); - for(unsigned j=0;j<3;++j){ - celn[j] = std::floor( ( Tools::pbc(fpos[j]) + 0.5 ) * ncells[j] ); - plumed_assert( celn[j]>=0 && celn[j]=0 && celn[j]& pos, const std::vector& indices, const Pbc& pbc ); /// Find a list of relevant atoms - void retrieveNeighboringAtoms( const Vector& pos, unsigned& natomsper, std::vector& atoms ) const ; + void retrieveNeighboringAtoms( const Vector& pos, unsigned& natomsper, std::vector& atoms ) const ; }; inline diff --git a/src/tools/Log.h b/src/tools/Log.h index c0a378fe61..c25ca3f383 100644 --- a/src/tools/Log.h +++ b/src/tools/Log.h @@ -24,7 +24,7 @@ #include "OFile.h" -namespace PLMD{ +namespace PLMD { /// Class containing the log stream. /// diff --git a/src/tools/LoopUnroller.h b/src/tools/LoopUnroller.h index 87e8f5298c..83f33ed700 100644 --- a/src/tools/LoopUnroller.h +++ b/src/tools/LoopUnroller.h @@ -22,7 +22,7 @@ #ifndef __PLUMED_tools_LoopUnroller_h #define __PLUMED_tools_LoopUnroller_h -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -48,7 +48,7 @@ Here xxx is any of the methods of the class. */ template -class LoopUnroller{ +class LoopUnroller { public: /// Set to zero. /// Same as `for(unsigned i=0;i -void LoopUnroller::_zero(double*d){ +void LoopUnroller::_zero(double*d) { LoopUnroller::_zero(d); d[n-1]=0.0; } template<> inline -void LoopUnroller<1>::_zero(double*d){ +void LoopUnroller<1>::_zero(double*d) { d[0]=0.0; } template -void LoopUnroller::_add(double*d,const double*a){ +void LoopUnroller::_add(double*d,const double*a) { LoopUnroller::_add(d,a); d[n-1]+=a[n-1]; } template<> inline -void LoopUnroller<1>::_add(double*d,const double*a){ +void LoopUnroller<1>::_add(double*d,const double*a) { d[0]+=a[0]; } template -void LoopUnroller::_sub(double*d,const double*a){ +void LoopUnroller::_sub(double*d,const double*a) { LoopUnroller::_sub(d,a); d[n-1]-=a[n-1]; } template<> inline -void LoopUnroller<1>::_sub(double*d,const double*a){ +void LoopUnroller<1>::_sub(double*d,const double*a) { d[0]-=a[0]; } template -void LoopUnroller::_mul(double*d,const double s){ +void LoopUnroller::_mul(double*d,const double s) { LoopUnroller::_mul(d,s); d[n-1]*=s; } template<> inline -void LoopUnroller<1>::_mul(double*d,const double s){ +void LoopUnroller<1>::_mul(double*d,const double s) { d[0]*=s; } template -void LoopUnroller::_neg(double*d,const double*a ){ +void LoopUnroller::_neg(double*d,const double*a ) { LoopUnroller::_neg(d,a); d[n-1]=-a[n-1]; } template<> inline -void LoopUnroller<1>::_neg(double*d,const double*a){ +void LoopUnroller<1>::_neg(double*d,const double*a) { d[0]=-a[0]; } template -double LoopUnroller::_sum2(const double*d){ +double LoopUnroller::_sum2(const double*d) { return LoopUnroller::_sum2(d)+d[n-1]*d[n-1]; } template<> inline -double LoopUnroller<1>::_sum2(const double*d){ +double LoopUnroller<1>::_sum2(const double*d) { return d[0]*d[0]; } template -double LoopUnroller::_dot(const double*d,const double*v){ +double LoopUnroller::_dot(const double*d,const double*v) { return LoopUnroller::_dot(d,v)+d[n-1]*v[n-1]; } template<> inline -double LoopUnroller<1>::_dot(const double*d,const double*v){ +double LoopUnroller<1>::_dot(const double*d,const double*v) { return d[0]*v[0]; } diff --git a/src/tools/Matrix.h b/src/tools/Matrix.h index 1bfc5ee1b5..fd1e35d6d9 100644 --- a/src/tools/Matrix.h +++ b/src/tools/Matrix.h @@ -31,234 +31,234 @@ #include "Log.h" #include "lapack/lapack.h" -namespace PLMD{ +namespace PLMD { -/// Calculate the dot product between two vectors -template T dotProduct( const std::vector& A, const std::vector& B ){ - plumed_assert( A.size()==B.size() ); - T val; for(unsigned i=0;i T dotProduct( const std::vector& A, const std::vector& B ) { + plumed_assert( A.size()==B.size() ); + T val; for(unsigned i=0; i T norm( const std::vector& A ){ - T val; for(unsigned i=0;i T norm( const std::vector& A ) { + T val; for(unsigned i=0; i class Matrix: public MatrixSquareBracketsAccess,T> - { - /// Multiply matrix by scalar - template friend Matrix operator*(U&, const Matrix& ); - /// Matrix matrix multiply - template friend void mult( const Matrix& , const Matrix& , Matrix& ); - /// Matrix times a std::vector - template friend void mult( const Matrix&, const std::vector& , std::vector& ); - /// std::vector times a Matrix - template friend void mult( const std::vector&, const Matrix&, std::vector& ); - /// Matrix transpose - template friend void transpose( const Matrix&, Matrix& ); - /// Output the entire matrix on a single line - template friend Log& operator<<(Log&, const Matrix& ); - /// Output the Matrix in matrix form - template friend void matrixOut( Log&, const Matrix& ); - /// Diagonalize a symmetric matrix - returns zero if diagonalization worked - template friend int diagMat( const Matrix& , std::vector& , Matrix& ); - /// Calculate the Moore-Penrose Pseudoinverse of a matrix - template friend int pseudoInvert( const Matrix& , Matrix& ); - /// Calculate the logarithm of the determinant of a symmetric matrix - returns zero if succesfull - template friend int logdet( const Matrix& , double& ); - /// Invert a matrix (works for both symmetric and assymetric matrices) - returns zero if sucesfull - template friend int Invert( const Matrix& , Matrix& ); - /// Do a cholesky decomposition of a matrix - template friend void cholesky( const Matrix& , Matrix& ); - /// Solve a system of equations using the cholesky decomposition - template friend void chol_elsolve( const Matrix& , const std::vector& , std::vector& ); +{ + /// Multiply matrix by scalar + template friend Matrix operator*(U&, const Matrix& ); + /// Matrix matrix multiply + template friend void mult( const Matrix&, const Matrix&, Matrix& ); + /// Matrix times a std::vector + template friend void mult( const Matrix&, const std::vector&, std::vector& ); + /// std::vector times a Matrix + template friend void mult( const std::vector&, const Matrix&, std::vector& ); + /// Matrix transpose + template friend void transpose( const Matrix&, Matrix& ); + /// Output the entire matrix on a single line + template friend Log& operator<<(Log&, const Matrix& ); + /// Output the Matrix in matrix form + template friend void matrixOut( Log&, const Matrix& ); + /// Diagonalize a symmetric matrix - returns zero if diagonalization worked + template friend int diagMat( const Matrix&, std::vector&, Matrix& ); + /// Calculate the Moore-Penrose Pseudoinverse of a matrix + template friend int pseudoInvert( const Matrix&, Matrix& ); + /// Calculate the logarithm of the determinant of a symmetric matrix - returns zero if succesfull + template friend int logdet( const Matrix&, double& ); + /// Invert a matrix (works for both symmetric and assymetric matrices) - returns zero if sucesfull + template friend int Invert( const Matrix&, Matrix& ); + /// Do a cholesky decomposition of a matrix + template friend void cholesky( const Matrix&, Matrix& ); + /// Solve a system of equations using the cholesky decomposition + template friend void chol_elsolve( const Matrix&, const std::vector&, std::vector& ); private: - /// Number of elements in matrix (nrows*ncols) - unsigned sz; - /// Number of rows in matrix - unsigned rw; - /// Number of columns in matrix - unsigned cl; - /// The data in the matrix - std::vector data; + /// Number of elements in matrix (nrows*ncols) + unsigned sz; + /// Number of rows in matrix + unsigned rw; + /// Number of columns in matrix + unsigned cl; + /// The data in the matrix + std::vector data; public: - Matrix(const unsigned nr=0, const unsigned nc=0 ) : sz(nr*nc), rw(nr), cl(nc), data(nr*nc) {} - Matrix(const Matrix& t) : sz(t.sz), rw(t.rw), cl(t.cl), data(t.data) {} - /// Resize the matrix - void resize( const unsigned nr, const unsigned nc ){ rw=nr; cl=nc; sz=nr*nc; data.resize(sz); } - /// Return the number of rows - inline unsigned nrows() const { return rw; } - /// Return the number of columns - inline unsigned ncols() const { return cl; } - /// Return element i,j of the matrix - inline T operator () (const unsigned& i, const unsigned& j) const { return data[j+i*cl]; } - /// Return a referenre to element i,j of the matrix - inline T& operator () (const unsigned& i, const unsigned& j) { return data[j+i*cl]; } - /// Set all elements of the matrix equal to the value of v - Matrix& operator=(const T& v){ - for(unsigned i=0;i& operator=(const Matrix& m){ - sz=m.sz; - rw=m.rw; - cl=m.cl; - data=m.data; - return *this; - } - /// Set the Matrix equal to the value of a standard vector - used for readin - Matrix& operator=(const std::vector& v){ - plumed_dbg_assert( v.size()==sz ); - for(unsigned i=0;i operator+=(const T& v){ - for(unsigned i=0;i operator*=(const T& v){ - for(unsigned i=0;i& operator+=(const Matrix& m){ + Matrix(const unsigned nr=0, const unsigned nc=0 ) : sz(nr*nc), rw(nr), cl(nc), data(nr*nc) {} + Matrix(const Matrix& t) : sz(t.sz), rw(t.rw), cl(t.cl), data(t.data) {} + /// Resize the matrix + void resize( const unsigned nr, const unsigned nc ) { rw=nr; cl=nc; sz=nr*nc; data.resize(sz); } + /// Return the number of rows + inline unsigned nrows() const { return rw; } + /// Return the number of columns + inline unsigned ncols() const { return cl; } + /// Return element i,j of the matrix + inline T operator () (const unsigned& i, const unsigned& j) const { return data[j+i*cl]; } + /// Return a referenre to element i,j of the matrix + inline T& operator () (const unsigned& i, const unsigned& j) { return data[j+i*cl]; } + /// Set all elements of the matrix equal to the value of v + Matrix& operator=(const T& v) { + for(unsigned i=0; i& operator=(const Matrix& m) { + sz=m.sz; + rw=m.rw; + cl=m.cl; + data=m.data; + return *this; + } + /// Set the Matrix equal to the value of a standard vector - used for readin + Matrix& operator=(const std::vector& v) { + plumed_dbg_assert( v.size()==sz ); + for(unsigned i=0; i operator+=(const T& v) { + for(unsigned i=0; i operator*=(const T& v) { + for(unsigned i=0; i& operator+=(const Matrix& m) { plumed_dbg_assert( m.rw==rw && m.cl==cl ); data+=m.data; return *this; } /// Subtract v from all elements of the Matrix - Matrix operator-=(const T& v){ - for(unsigned i=0;i operator-=(const T& v) { + for(unsigned i=0; i& operator-=(const Matrix& m){ + Matrix& operator-=(const Matrix& m) { plumed_dbg_assert( m.rw==rw && m.cl==cl ); - data-=m.data; + data-=m.data; return *this; } /// Test if the matrix is symmetric or not - unsigned isSymmetric() const { - if (rw!=cl){ return 0; } - unsigned sym=1; - for(unsigned i=1;i1.e-10 ){ sym=0; break; } - return sym; + unsigned isSymmetric() const { + if (rw!=cl) { return 0; } + unsigned sym=1; + for(unsigned i=1; i1.e-10 ) { sym=0; break; } + return sym; } }; /// Multiply matrix by scalar -template Matrix operator*(T& v, const Matrix& m ){ +template Matrix operator*(T& v, const Matrix& m ) { Matrix new_m(m); new_m*=v; - return new_m; + return new_m; } -template void mult( const Matrix& A , const Matrix& B , Matrix& C ){ +template void mult( const Matrix& A, const Matrix& B, Matrix& C ) { plumed_assert(A.cl==B.rw); - if( A.rw !=C.rw || B.cl !=C.cl ){ C.resize( A.rw , B.cl ); } C=static_cast( 0 ); - for(unsigned i=0;i( 0 ); + for(unsigned i=0; i void mult( const Matrix& A, const std::vector& B, std::vector& C){ +template void mult( const Matrix& A, const std::vector& B, std::vector& C) { plumed_assert( A.cl==B.size() ); - if( C.size()!=A.rw ){ C.resize(A.rw); } - for(unsigned i=0;i( 0 ); } - for(unsigned i=0;i( 0 ); } + for(unsigned i=0; i void mult( const std::vector& A, const Matrix& B, std::vector& C){ +template void mult( const std::vector& A, const Matrix& B, std::vector& C) { plumed_assert( B.rw==A.size() ); - if( C.size()!=B.cl ){C.resize( B.cl );} - for(unsigned i=0;i( 0 ); } - for(unsigned i=0;i( 0 ); } + for(unsigned i=0; i void transpose( const Matrix& A, Matrix& AT ){ - if( A.rw!=AT.cl || A.cl!=AT.rw ) AT.resize( A.cl , A.rw ); - for(unsigned i=0;i void transpose( const Matrix& A, Matrix& AT ) { + if( A.rw!=AT.cl || A.cl!=AT.rw ) AT.resize( A.cl, A.rw ); + for(unsigned i=0; i Log& operator<<(Log& ostr, const Matrix& mat){ - for(unsigned i=0;i Log& operator<<(Log& ostr, const Matrix& mat) { + for(unsigned i=0; i void matrixOut( Log& ostr, const Matrix& mat){ - for(unsigned i=0;i void matrixOut( Log& ostr, const Matrix& mat) { + for(unsigned i=0; i int diagMat( const Matrix& A, std::vector& eigenvals, Matrix& eigenvecs ){ - - // Check matrix is square and symmetric - plumed_assert( A.rw==A.cl ); plumed_assert( A.isSymmetric()==1 ); - double *da=new double[A.sz]; unsigned k=0; double *evals=new double[ A.cl ]; - // Transfer the matrix to the local array - for (unsigned i=0; i( A(j,i) ); - - int n=A.cl; int lwork=-1, liwork=-1, m, info, one=1; - double *work=new double[A.cl]; int *iwork=new int[A.cl]; - double vl, vu, abstol=0.0; - int* isup=new int[2*A.cl]; double *evecs=new double[A.sz]; - - plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; - - // Retrieve correct sizes for work and iwork then reallocate - liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; - lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; - - plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; - - if( eigenvals.size()!=A.cl ){ eigenvals.resize( A.cl ); } - if( eigenvecs.rw!=A.rw || eigenvecs.cl!=A.cl ){ eigenvecs.resize( A.rw, A.cl ); } - k=0; - for(unsigned i=0;i1e-14) break; - if(j int diagMat( const Matrix& A, std::vector& eigenvals, Matrix& eigenvecs ) { + + // Check matrix is square and symmetric + plumed_assert( A.rw==A.cl ); plumed_assert( A.isSymmetric()==1 ); + double *da=new double[A.sz]; unsigned k=0; double *evals=new double[ A.cl ]; + // Transfer the matrix to the local array + for (unsigned i=0; i( A(j,i) ); + + int n=A.cl; int lwork=-1, liwork=-1, m, info, one=1; + double *work=new double[A.cl]; int *iwork=new int[A.cl]; + double vl, vu, abstol=0.0; + int* isup=new int[2*A.cl]; double *evecs=new double[A.sz]; + + plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; + + // Retrieve correct sizes for work and iwork then reallocate + liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; + lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; + + plumed_lapack_dsyevr("V", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; + + if( eigenvals.size()!=A.cl ) { eigenvals.resize( A.cl ); } + if( eigenvecs.rw!=A.rw || eigenvecs.cl!=A.cl ) { eigenvecs.resize( A.rw, A.cl ); } + k=0; + for(unsigned i=0; i1e-14) break; + if(j int pseudoInvert( const Matrix& A, Matrix& pseudoinverse ){ - double *da=new double[A.sz]; unsigned k=0; +template int pseudoInvert( const Matrix& A, Matrix& pseudoinverse ) { + double *da=new double[A.sz]; unsigned k=0; // Transfer the matrix to the local array for (unsigned i=0; i( A(j,i) ); - int nsv, info, nrows=A.rw, ncols=A.cl; - if(A.rw>A.cl){nsv=A.cl;}else{nsv=A.rw;} + int nsv, info, nrows=A.rw, ncols=A.cl; + if(A.rw>A.cl) {nsv=A.cl;} else {nsv=A.rw;} // Create some containers for stuff from single value decomposition double *S=new double[nsv]; double *U=new double[nrows*nrows]; @@ -274,19 +274,19 @@ template int pseudoInvert( const Matrix& A, Matrix& pseu // This does the singular value decomposition plumed_lapack_dgesdd( "A", &nrows, &ncols, da, &nrows, S, U, &nrows, VT, &ncols, work, &lwork, iwork, &info ); - if(info!=0) return info; + if(info!=0) return info; // Compute the tolerance on the singular values ( machine epsilon * number of singular values * maximum singular value ) - double tol; tol=S[0]; for(int i=1;itol ){ tol=S[i]; } } tol*=nsv*epsilon; + double tol; tol=S[0]; for(int i=1; itol ) { tol=S[i]; } } tol*=nsv*epsilon; // Get the inverses of the singlular values Matrix Si( ncols, nrows ); Si=0.0; - for(int i=0;itol ){ Si(i,i)=1./S[i]; }else{ Si(i,i)=0.0; } } + for(int i=0; itol ) { Si(i,i)=1./S[i]; } else { Si(i,i)=0.0; } } // Now extract matrices for pseudoinverse - Matrix V( ncols, ncols ), UT( nrows, nrows ), tmp( ncols, nrows ); - k=0; for(int i=0;i V( ncols, ncols ), UT( nrows, nrows ), tmp( ncols, nrows ); + k=0; for(int i=0; i int pseudoInvert( const Matrix& A, Matrix& pseu return 0; } -template int Invert( const Matrix& A, Matrix& inverse ){ - - if( A.isSymmetric()==1 ){ - // GAT -- I only ever use symmetric matrices so I can invert them like this. - // I choose to do this as I have had problems with the more general way of doing this that - // is implemented below. - std::vector eval(A.rw); Matrix evec(A.rw,A.cl), tevec(A.rw,A.cl); - int err; err=diagMat( A, eval, evec ); - if(err!=0) return err; - for (unsigned i=0; i int Invert( const Matrix& A, Matrix& inverse ) { + + if( A.isSymmetric()==1 ) { + // GAT -- I only ever use symmetric matrices so I can invert them like this. + // I choose to do this as I have had problems with the more general way of doing this that + // is implemented below. + std::vector eval(A.rw); Matrix evec(A.rw,A.cl), tevec(A.rw,A.cl); + int err; err=diagMat( A, eval, evec ); + if(err!=0) return err; + for (unsigned i=0; i( A(j,i) ); + double *da=new double[A.sz]; int *ipiv=new int[A.cl]; + unsigned k=0; int n=A.rw, info; + for(unsigned i=0; i( A(j,i) ); - plumed_lapack_dgetrf(&n,&n,da,&n,ipiv,&info); - if(info!=0) return info; + plumed_lapack_dgetrf(&n,&n,da,&n,ipiv,&info); + if(info!=0) return info; - int lwork=-1; double* work=new double[A.cl]; - plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); - if(info!=0) return info; + int lwork=-1; double* work=new double[A.cl]; + plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); + if(info!=0) return info; - lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; - plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); - if(info!=0) return info; + lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; + plumed_lapack_dgetri(&n,da,&n,ipiv,work,&lwork,&info); + if(info!=0) return info; - if( inverse.cl!=A.cl || inverse.rw!=A.rw ){ inverse.resize(A.rw,A.cl); } - k=0; for(unsigned i=0;i void cholesky( const Matrix& A, Matrix& B ){ +template void cholesky( const Matrix& A, Matrix& B ) { - plumed_assert( A.rw==A.cl && A.isSymmetric() ); - Matrix L(A.rw ,A.cl); L=0.; - std::vector D(A.rw,0.); - for(unsigned i=0; i L(A.rw,A.cl); L=0.; + std::vector D(A.rw,0.); + for(unsigned i=0; i( 1 ); - for (unsigned j=0; j( 0 ); - } - D[i]=A(i,i); - for (unsigned k=0; k0.?sqrt(D[i]):0.); - if( B.rw!=A.rw || B.cl!=A.cl ){ B.resize( A.rw, A.cl); } - B=0.; for(unsigned i=0; i( 1 ); + for (unsigned j=0; j( 0 ); + } + D[i]=A(i,i); + for (unsigned k=0; k0.?sqrt(D[i]):0.); + if( B.rw!=A.rw || B.cl!=A.cl ) { B.resize( A.rw, A.cl); } + B=0.; for(unsigned i=0; i void chol_elsolve( const Matrix& M, const std::vector& b, std::vector& y ){ +template void chol_elsolve( const Matrix& M, const std::vector& b, std::vector& y ) { - plumed_assert( M.rw==M.cl && M(0,1)==0.0 && b.size()==M.rw ); - if( y.size()!=M.rw ){ y.resize( M.rw ); } - for(unsigned i=0;i int logdet( const Matrix& M, double& ldet ){ - // Check matrix is square and symmetric - plumed_assert( M.rw==M.cl || M.isSymmetric() ); +template int logdet( const Matrix& M, double& ldet ) { + // Check matrix is square and symmetric + plumed_assert( M.rw==M.cl || M.isSymmetric() ); - double *da=new double[M.sz]; unsigned k=0; double *evals=new double[M.cl]; - // Transfer the matrix to the local array - for (unsigned i=0; i( M(j,i) ); + double *da=new double[M.sz]; unsigned k=0; double *evals=new double[M.cl]; + // Transfer the matrix to the local array + for (unsigned i=0; i( M(j,i) ); - int n=M.cl; int lwork=-1, liwork=-1, info, m, one=1; - double *work=new double[M.rw]; int *iwork=new int[M.rw]; - double vl, vu, abstol=0.0; - int* isup=new int[2*M.rw]; double *evecs=new double[M.sz]; - plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; + int n=M.cl; int lwork=-1, liwork=-1, info, m, one=1; + double *work=new double[M.rw]; int *iwork=new int[M.rw]; + double vl, vu, abstol=0.0; + int* isup=new int[2*M.rw]; double *evecs=new double[M.sz]; + plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; - // Retrieve correct sizes for work and iwork then reallocate - lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; - liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; + // Retrieve correct sizes for work and iwork then reallocate + lwork=static_cast( work[0] ); delete [] work; work=new double[lwork]; + liwork=iwork[0]; delete [] iwork; iwork=new int[liwork]; - plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n , - &abstol, &m, evals, evecs, &n, - isup, work, &lwork, iwork, &liwork, &info); - if (info!=0) return info; + plumed_lapack_dsyevr("N", "I", "U", &n, da, &n, &vl, &vu, &one, &n, + &abstol, &m, evals, evecs, &n, + isup, work, &lwork, iwork, &liwork, &info); + if (info!=0) return info; - // Transfer the eigenvalues and eigenvectors to the output - ldet=0; for(unsigned i=0;i -class MatrixSquareBracketsAccess{ +class MatrixSquareBracketsAccess { /// Small utility class which just contains a pointer to the T and the row number - class Const_row{ + class Const_row { friend class MatrixSquareBracketsAccess; // this so as to allow only T to instantiate Const_row - // the user should not manipulate it directly + // the user should not manipulate it directly const MatrixSquareBracketsAccess& t; const I i; Const_row(const MatrixSquareBracketsAccess&t,I i); // constructor is private and cannot be manipulated by the user public: - /// access element + /// access element const C & operator[] (J j)const; }; /// Small utility class which just contains a pointer to the T and the row number - class Row{ + class Row { friend class MatrixSquareBracketsAccess; // this so as to allow only T to instantiate Const_row - // the user should not manipulate it directly + // the user should not manipulate it directly MatrixSquareBracketsAccess& t; const I i; Row(MatrixSquareBracketsAccess&t,I i); // constructor is private and cannot be manipulated by the user public: - /// access element + /// access element C & operator[] (J j); }; public: @@ -98,29 +98,29 @@ class MatrixSquareBracketsAccess{ template MatrixSquareBracketsAccess::Const_row::Const_row(const MatrixSquareBracketsAccess&t,I i): - t(t),i(i){} + t(t),i(i) {} template MatrixSquareBracketsAccess::Row::Row(MatrixSquareBracketsAccess&t,I i): - t(t),i(i){} + t(t),i(i) {} template -const C & MatrixSquareBracketsAccess::Const_row::operator[] (J j)const{ +const C & MatrixSquareBracketsAccess::Const_row::operator[] (J j)const { return (*static_cast(&t))(i,j); } template -C & MatrixSquareBracketsAccess::Row::operator[] (J j){ +C & MatrixSquareBracketsAccess::Row::operator[] (J j) { return (*static_cast(&t))(i,j); } template -typename MatrixSquareBracketsAccess::Row MatrixSquareBracketsAccess::operator[] (I i){ +typename MatrixSquareBracketsAccess::Row MatrixSquareBracketsAccess::operator[] (I i) { return Row(*this,i); } template -typename MatrixSquareBracketsAccess::Const_row MatrixSquareBracketsAccess::operator[] (I i)const{ +typename MatrixSquareBracketsAccess::Const_row MatrixSquareBracketsAccess::operator[] (I i)const { return Const_row(*this,i); } diff --git a/src/tools/Minimise1DBrent.h b/src/tools/Minimise1DBrent.h index dca7800e91..097a05b444 100644 --- a/src/tools/Minimise1DBrent.h +++ b/src/tools/Minimise1DBrent.h @@ -27,7 +27,7 @@ #include #include -namespace PLMD{ +namespace PLMD { /// A class for doing parabolic interpolation and minimisation of /// 1D functions using Brent's method. @@ -50,7 +50,7 @@ class Minimise1DBrent { const unsigned ITMAX; /// The value of the golden ratio const double CGOLD; -/// A small number that protects against trying to achieve fractional +/// A small number that protects against trying to achieve fractional /// accuracy for a minimum that happens to be exactly zero const double ZEPS; /// This is the type specifier for the function to minimise @@ -61,128 +61,128 @@ class Minimise1DBrent { FCLASS myclass_func; public: explicit Minimise1DBrent( const FCLASS& pf, const double& t=3.0E-8 ); -/// Bracket the minium +/// Bracket the minium void bracket( const double& ax, const double& xx, eng_pointer eng ); /// Find the minimum between two brackets - double minimise( eng_pointer eng ); + double minimise( eng_pointer eng ); /// Return the value of the function at the minimum double getMinimumValue() const ; }; template Minimise1DBrent::Minimise1DBrent( const FCLASS& pf, const double& t ): -bracketed(false), -minimised(false), -tol(t), -GOLD(1.618034), -GLIMIT(100.0), -TINY(1.0E-20), -ITMAX(100), -CGOLD(0.3819660), -ZEPS(epsilon*1.0E-3), -ax(0),bx(0),cx(0), -fa(0),fb(0),fc(0), -fmin(0), -myclass_func(pf) + bracketed(false), + minimised(false), + tol(t), + GOLD(1.618034), + GLIMIT(100.0), + TINY(1.0E-20), + ITMAX(100), + CGOLD(0.3819660), + ZEPS(epsilon*1.0E-3), + ax(0),bx(0),cx(0), + fa(0),fb(0),fc(0), + fmin(0), + myclass_func(pf) { } template -void Minimise1DBrent::bracket( const double& a, const double& b, eng_pointer eng ){ - ax=a; bx=b; double fu; - fa=(myclass_func.*eng)(ax); fb=(myclass_func.*eng)(bx); - if( fb>fa ){ - double tmp; - tmp=ax; ax=bx; bx=tmp; - tmp=fa; fa=fb; fb=tmp; - } - cx=bx+GOLD*(bx-ax); - fc=(myclass_func.*eng)(cx); - while ( fb > fc ){ - double r=(bx-ax)*(fb-fc); - double q=(bx-cx)*(fb-fa); - double u=bx-((bx-cx)*q-(bx-ax)*r)/(2.0*(fabs(q-r)>TINY?fabs(q-r):TINY)*(q-r>=0?1:-1)); - double ulim=bx+GLIMIT*(cx-bx); - if((bx-u)*(u-cx) > 0.0 ){ - fu=(myclass_func.*eng)(u); - if( fu < fc ){ - ax=bx; bx=u; fa=fb; fb=fu; bracketed=true; return; - } else if( fu > fb ){ - cx=u; fc=fu; bracketed=true; return; - } - u=cx+GOLD*(cx-bx); fu=(myclass_func.*eng)(u); - } else if((cx-u)*(u-ulim) > 0.0 ){ - fu=(myclass_func.*eng)(u); - if( fu= 0.0 ){ - u=ulim; - fu=(myclass_func.*eng)(u); - } else { - u=cx+GOLD*(cx-bx); - fu=(myclass_func.*eng)(u); - } - ax=bx; bx=cx; cx=u; - fa=fb; fb=fc; fc=fu; - } - bracketed=true; +void Minimise1DBrent::bracket( const double& a, const double& b, eng_pointer eng ) { + ax=a; bx=b; double fu; + fa=(myclass_func.*eng)(ax); fb=(myclass_func.*eng)(bx); + if( fb>fa ) { + double tmp; + tmp=ax; ax=bx; bx=tmp; + tmp=fa; fa=fb; fb=tmp; + } + cx=bx+GOLD*(bx-ax); + fc=(myclass_func.*eng)(cx); + while ( fb > fc ) { + double r=(bx-ax)*(fb-fc); + double q=(bx-cx)*(fb-fa); + double u=bx-((bx-cx)*q-(bx-ax)*r)/(2.0*(fabs(q-r)>TINY?fabs(q-r):TINY)*(q-r>=0?1:-1)); + double ulim=bx+GLIMIT*(cx-bx); + if((bx-u)*(u-cx) > 0.0 ) { + fu=(myclass_func.*eng)(u); + if( fu < fc ) { + ax=bx; bx=u; fa=fb; fb=fu; bracketed=true; return; + } else if( fu > fb ) { + cx=u; fc=fu; bracketed=true; return; + } + u=cx+GOLD*(cx-bx); fu=(myclass_func.*eng)(u); + } else if((cx-u)*(u-ulim) > 0.0 ) { + fu=(myclass_func.*eng)(u); + if( fu= 0.0 ) { + u=ulim; + fu=(myclass_func.*eng)(u); + } else { + u=cx+GOLD*(cx-bx); + fu=(myclass_func.*eng)(u); + } + ax=bx; bx=cx; cx=u; + fa=fb; fb=fc; fc=fu; + } + bracketed=true; } template -double Minimise1DBrent::minimise( eng_pointer eng ){ - plumed_dbg_assert( bracketed ); - - double a,b,d=0.0,etemp,fu,fv,fw,fx; - double p,q,r,tol1,tol2,u,v,w,x,xm; - double e=0.0; - - a=(ax < cx ? ax : cx ); - b=(ax >= cx ? ax : cx ); - x=w=v=bx; - fw=fv=fx=(myclass_func.*eng)(x); - for(unsigned iter=0;iter tol1 ){ - r=(x-w)*(fx-fv); - q=(x-v)*(fx-fw); - p=(x-v)*q-(x-w)*r; - q=2.0*(q-r); - if( q > 0.0 ) p = -p; - q=fabs(q); - etemp=e; - e=d; - if( fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x) ){ - d = CGOLD*(e=(x >= xm ? a-x : b-x )); - } else { - d=p/q; u=x+d; - if(u-a < tol2 || b-u < tol2 ) d=(xm-x>=0?fabs(tol1):-fabs(tol1)); - } +double Minimise1DBrent::minimise( eng_pointer eng ) { + plumed_dbg_assert( bracketed ); + + double a,b,d=0.0,etemp,fu,fv,fw,fx; + double p,q,r,tol1,tol2,u,v,w,x,xm; + double e=0.0; + + a=(ax < cx ? ax : cx ); + b=(ax >= cx ? ax : cx ); + x=w=v=bx; + fw=fv=fx=(myclass_func.*eng)(x); + for(unsigned iter=0; iter tol1 ) { + r=(x-w)*(fx-fv); + q=(x-v)*(fx-fw); + p=(x-v)*q-(x-w)*r; + q=2.0*(q-r); + if( q > 0.0 ) p = -p; + q=fabs(q); + etemp=e; + e=d; + if( fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x) ) { + d = CGOLD*(e=(x >= xm ? a-x : b-x )); } else { - d=CGOLD*(e=( x >= xm ? a-x : b-x )); + d=p/q; u=x+d; + if(u-a < tol2 || b-u < tol2 ) d=(xm-x>=0?fabs(tol1):-fabs(tol1)); } - if( fabs(d)>=tol1) u=x+d; else u=x+(d>=0?fabs(tol1):-fabs(tol1)); - fu=(myclass_func.*eng)(u); - if( fu <= fx ){ - if( u >= x ) a=x; else b=x; - v=w; fv=fw; - w=x; fw=fx; - x=u; fx=fu; - } else { - if( u < x ) a=u; else b=u; - if( fu <=fw || w==x ){ - v=w; w=u; fv=fw; fw=fu; - } else if( fu <= fv || v==x || v==w ){ - v=u; fv=fu; - } + } else { + d=CGOLD*(e=( x >= xm ? a-x : b-x )); + } + if( fabs(d)>=tol1) u=x+d; else u=x+(d>=0?fabs(tol1):-fabs(tol1)); + fu=(myclass_func.*eng)(u); + if( fu <= fx ) { + if( u >= x ) a=x; else b=x; + v=w; fv=fw; + w=x; fw=fx; + x=u; fx=fu; + } else { + if( u < x ) a=u; else b=u; + if( fu <=fw || w==x ) { + v=w; w=u; fv=fw; fw=fu; + } else if( fu <= fv || v==x || v==w ) { + v=u; fv=fu; } - } - plumed_merror("Too many interactions in brent"); + } + } + plumed_merror("Too many interactions in brent"); } template diff --git a/src/tools/MinimiseBase.h b/src/tools/MinimiseBase.h index 80cfcc02e5..27714da7ca 100644 --- a/src/tools/MinimiseBase.h +++ b/src/tools/MinimiseBase.h @@ -47,7 +47,7 @@ class F1dim { engf_pointer calc; /// Member of class that calcualtes the energy we are trying to minimise engfnc_pointer calc2; -public: +public: explicit F1dim( const std::vector& pp, const std::vector& dd, FCLASS* ff, engf_pointer cc, engfnc_pointer cc2 ); /// Calculate the energy at \f$\mathbf{p} + xt*\mathbf{dir}\f$ double getEng( const double& xt ); @@ -55,21 +55,21 @@ class F1dim { template F1dim::F1dim( const std::vector& pp, const std::vector& dd, FCLASS* ff, engf_pointer cc, engfnc_pointer cc2 ): -p(pp), -dir(dd), -pt(pp.size()), -fake_der(pp.size()), -func(ff), -calc(cc), -calc2(cc2) + p(pp), + dir(dd), + pt(pp.size()), + fake_der(pp.size()), + func(ff), + calc(cc), + calc2(cc2) { plumed_assert( calc || calc2 ); } template -double F1dim::getEng( const double& xt ){ - for(unsigned j=0;j*calc)(pt,fake_der); +double F1dim::getEng( const double& xt ) { + for(unsigned j=0; j*calc)(pt,fake_der); return (func->*calc2)(pt,fake_der); } @@ -82,7 +82,7 @@ class MinimiseBase { /// The class that calculates the energy given a position FCLASS* myclass_func; protected: -/// This calculates the derivatives at a point +/// This calculates the derivatives at a point double calcDerivatives( const std::vector& p, std::vector& der, engf_pointer myfunc ); public: explicit MinimiseBase( FCLASS* funcc ) : myclass_func(funcc) {} @@ -91,8 +91,8 @@ class MinimiseBase { }; template -double MinimiseBase::linemin( const std::vector& dir, std::vector& p, engf_pointer myfunc ){ - // Construct the object that turns points on a line into vectors +double MinimiseBase::linemin( const std::vector& dir, std::vector& p, engf_pointer myfunc ) { + // Construct the object that turns points on a line into vectors F1dim f1dim( p, dir, myclass_func, NULL, myfunc ); // Construct an object that will do the line search for the minimum @@ -100,14 +100,14 @@ double MinimiseBase::linemin( const std::vector& dir, std::vecto // This does the actual line minimisation double ax=0.0, xx=1.0; - bb.bracket( ax, xx, &F1dim::getEng ); + bb.bracket( ax, xx, &F1dim::getEng ); double xmin=bb.minimise( &F1dim::getEng ); - for(unsigned i=0;i -double MinimiseBase::calcDerivatives( const std::vector& p, std::vector& der, engf_pointer myfunc ){ +double MinimiseBase::calcDerivatives( const std::vector& p, std::vector& der, engf_pointer myfunc ) { return (myclass_func->*myfunc)( p, der ); } diff --git a/src/tools/MolDataClass.cpp b/src/tools/MolDataClass.cpp index 49f0e0fac0..310267d5ac 100644 --- a/src/tools/MolDataClass.cpp +++ b/src/tools/MolDataClass.cpp @@ -26,156 +26,156 @@ namespace PLMD { -unsigned MolDataClass::numberOfAtomsPerResidueInBackbone( const std::string& type ){ +unsigned MolDataClass::numberOfAtomsPerResidueInBackbone( const std::string& type ) { if( type=="protein" ) return 5; else if( type=="dna" ) return 6; - else if( type=="rna" ) return 6; + else if( type=="rna" ) return 6; else return 0; } -bool MolDataClass::allowedResidue( const std::string& type, const std::string& residuename ){ - if( type=="protein" ){ - if(residuename=="ALA") return true; - else if(residuename=="ARG") return true; - else if(residuename=="ASN") return true; - else if(residuename=="ASP") return true; - else if(residuename=="CYS") return true; - else if(residuename=="GLN") return true; - else if(residuename=="GLU") return true; - else if(residuename=="GLY") return true; - else if(residuename=="HIS") return true; - else if(residuename=="ILE") return true; - else if(residuename=="LEU") return true; - else if(residuename=="LYS") return true; - else if(residuename=="MET") return true; - else if(residuename=="PHE") return true; - else if(residuename=="PRO") return true; - else if(residuename=="SER") return true; - else if(residuename=="THR") return true; - else if(residuename=="TRP") return true; - else if(residuename=="TYR") return true; - else if(residuename=="VAL") return true; +bool MolDataClass::allowedResidue( const std::string& type, const std::string& residuename ) { + if( type=="protein" ) { + if(residuename=="ALA") return true; + else if(residuename=="ARG") return true; + else if(residuename=="ASN") return true; + else if(residuename=="ASP") return true; + else if(residuename=="CYS") return true; + else if(residuename=="GLN") return true; + else if(residuename=="GLU") return true; + else if(residuename=="GLY") return true; + else if(residuename=="HIS") return true; + else if(residuename=="ILE") return true; + else if(residuename=="LEU") return true; + else if(residuename=="LYS") return true; + else if(residuename=="MET") return true; + else if(residuename=="PHE") return true; + else if(residuename=="PRO") return true; + else if(residuename=="SER") return true; + else if(residuename=="THR") return true; + else if(residuename=="TRP") return true; + else if(residuename=="TYR") return true; + else if(residuename=="VAL") return true; // Terminal groups - else if(residuename=="ACE") return true; - else if(residuename=="NME") return true; -// Alternative residue names in common force fiels - else if(residuename=="GLH") return true; // neutral GLU - else if(residuename=="ASH") return true; // neutral ASP - else if(residuename=="HID") return true; // HIS-D amber - else if(residuename=="HSD") return true; // HIS-D charmm - else if(residuename=="HIE") return true; // HIS-E amber - else if(residuename=="HSE") return true; // HIS-E charmm - else if(residuename=="HIP") return true; // HIS-P amber - else if(residuename=="HSP") return true; // HIS-P charmm - else return false; - } else if( type=="dna" ){ - if(residuename=="DA") return true; - else if(residuename=="DG") return true; - else if(residuename=="DT") return true; - else if(residuename=="DC") return true; - else if(residuename=="DA5") return true; - else if(residuename=="DA3") return true; - else if(residuename=="DAN") return true; - else if(residuename=="DG5") return true; - else if(residuename=="DG3") return true; - else if(residuename=="DGN") return true; - else if(residuename=="DT5") return true; - else if(residuename=="DT3") return true; - else if(residuename=="DTN") return true; - else if(residuename=="DC5") return true; - else if(residuename=="DC3") return true; - else if(residuename=="DCN") return true; - else return false; - } else if( type=="rna" ){ - if(residuename=="A") return true; - else if(residuename=="A5") return true; - else if(residuename=="A3") return true; - else if(residuename=="AN") return true; - else if(residuename=="G") return true; - else if(residuename=="G5") return true; - else if(residuename=="G3") return true; - else if(residuename=="GN") return true; - else if(residuename=="U") return true; - else if(residuename=="U5") return true; - else if(residuename=="U3") return true; - else if(residuename=="UN") return true; - else if(residuename=="C") return true; - else if(residuename=="C5") return true; - else if(residuename=="C3") return true; - else if(residuename=="CN") return true; - else if(residuename=="RA") return true; - else if(residuename=="RA5") return true; - else if(residuename=="RA3") return true; - else if(residuename=="RAN") return true; - else if(residuename=="RG") return true; - else if(residuename=="RG5") return true; - else if(residuename=="RG3") return true; - else if(residuename=="RGN") return true; - else if(residuename=="RU") return true; - else if(residuename=="RU5") return true; - else if(residuename=="RU3") return true; - else if(residuename=="RUN") return true; - else if(residuename=="RC") return true; - else if(residuename=="RC5") return true; - else if(residuename=="RC3") return true; - else if(residuename=="RCN") return true; - else return false; - } + else if(residuename=="ACE") return true; + else if(residuename=="NME") return true; +// Alternative residue names in common force fiels + else if(residuename=="GLH") return true; // neutral GLU + else if(residuename=="ASH") return true; // neutral ASP + else if(residuename=="HID") return true; // HIS-D amber + else if(residuename=="HSD") return true; // HIS-D charmm + else if(residuename=="HIE") return true; // HIS-E amber + else if(residuename=="HSE") return true; // HIS-E charmm + else if(residuename=="HIP") return true; // HIS-P amber + else if(residuename=="HSP") return true; // HIS-P charmm + else return false; + } else if( type=="dna" ) { + if(residuename=="DA") return true; + else if(residuename=="DG") return true; + else if(residuename=="DT") return true; + else if(residuename=="DC") return true; + else if(residuename=="DA5") return true; + else if(residuename=="DA3") return true; + else if(residuename=="DAN") return true; + else if(residuename=="DG5") return true; + else if(residuename=="DG3") return true; + else if(residuename=="DGN") return true; + else if(residuename=="DT5") return true; + else if(residuename=="DT3") return true; + else if(residuename=="DTN") return true; + else if(residuename=="DC5") return true; + else if(residuename=="DC3") return true; + else if(residuename=="DCN") return true; + else return false; + } else if( type=="rna" ) { + if(residuename=="A") return true; + else if(residuename=="A5") return true; + else if(residuename=="A3") return true; + else if(residuename=="AN") return true; + else if(residuename=="G") return true; + else if(residuename=="G5") return true; + else if(residuename=="G3") return true; + else if(residuename=="GN") return true; + else if(residuename=="U") return true; + else if(residuename=="U5") return true; + else if(residuename=="U3") return true; + else if(residuename=="UN") return true; + else if(residuename=="C") return true; + else if(residuename=="C5") return true; + else if(residuename=="C3") return true; + else if(residuename=="CN") return true; + else if(residuename=="RA") return true; + else if(residuename=="RA5") return true; + else if(residuename=="RA3") return true; + else if(residuename=="RAN") return true; + else if(residuename=="RG") return true; + else if(residuename=="RG5") return true; + else if(residuename=="RG3") return true; + else if(residuename=="RGN") return true; + else if(residuename=="RU") return true; + else if(residuename=="RU5") return true; + else if(residuename=="RU3") return true; + else if(residuename=="RUN") return true; + else if(residuename=="RC") return true; + else if(residuename=="RC5") return true; + else if(residuename=="RC3") return true; + else if(residuename=="RCN") return true; + else return false; + } return false; } -void MolDataClass::getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ){ +void MolDataClass::getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ) { std::string residuename=mypdb.getResidueName( residuenum ); plumed_massert( MolDataClass::allowedResidue( type, residuename ), "residue " + residuename + " unrecognized for molecule type " + type ); - if( type=="protein" ){ - if( residuename=="GLY"){ - atoms.resize(5); - atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); - atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); - atoms[2]=mypdb.getNamedAtomFromResidue("HA1",residuenum); - atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); - atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); - } else if( residuename=="ACE"){ - atoms.resize(1); - atoms[0]=mypdb.getNamedAtomFromResidue("C",residuenum); - } else if( residuename=="NME"){ - atoms.resize(1); - atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); - } else { - atoms.resize(5); - atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); - atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); - atoms[2]=mypdb.getNamedAtomFromResidue("CB",residuenum); - atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); - atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); - } - } else if( type=="dna" || type=="rna" ){ - atoms.resize(6); - atoms[0]=mypdb.getNamedAtomFromResidue("P",residuenum); - atoms[1]=mypdb.getNamedAtomFromResidue("O5\'",residuenum); - atoms[2]=mypdb.getNamedAtomFromResidue("C5\'",residuenum); - atoms[3]=mypdb.getNamedAtomFromResidue("C4\'",residuenum); - atoms[4]=mypdb.getNamedAtomFromResidue("C3\'",residuenum); - atoms[5]=mypdb.getNamedAtomFromResidue("O3\'",residuenum); - } + if( type=="protein" ) { + if( residuename=="GLY") { + atoms.resize(5); + atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); + atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); + atoms[2]=mypdb.getNamedAtomFromResidue("HA1",residuenum); + atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); + atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); + } else if( residuename=="ACE") { + atoms.resize(1); + atoms[0]=mypdb.getNamedAtomFromResidue("C",residuenum); + } else if( residuename=="NME") { + atoms.resize(1); + atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); + } else { + atoms.resize(5); + atoms[0]=mypdb.getNamedAtomFromResidue("N",residuenum); + atoms[1]=mypdb.getNamedAtomFromResidue("CA",residuenum); + atoms[2]=mypdb.getNamedAtomFromResidue("CB",residuenum); + atoms[3]=mypdb.getNamedAtomFromResidue("C",residuenum); + atoms[4]=mypdb.getNamedAtomFromResidue("O",residuenum); + } + } else if( type=="dna" || type=="rna" ) { + atoms.resize(6); + atoms[0]=mypdb.getNamedAtomFromResidue("P",residuenum); + atoms[1]=mypdb.getNamedAtomFromResidue("O5\'",residuenum); + atoms[2]=mypdb.getNamedAtomFromResidue("C5\'",residuenum); + atoms[3]=mypdb.getNamedAtomFromResidue("C4\'",residuenum); + atoms[4]=mypdb.getNamedAtomFromResidue("C3\'",residuenum); + atoms[5]=mypdb.getNamedAtomFromResidue("O3\'",residuenum); + } else { - plumed_merror(type + " is not a valid molecule type"); + plumed_merror(type + " is not a valid molecule type"); } } -bool MolDataClass::isTerminalGroup( const std::string& type, const std::string& residuename ){ - if( type=="protein" ){ - if( residuename=="ACE" ) return true; - else if( residuename=="NME" ) return true; - else return false; +bool MolDataClass::isTerminalGroup( const std::string& type, const std::string& residuename ) { + if( type=="protein" ) { + if( residuename=="ACE" ) return true; + else if( residuename=="NME" ) return true; + else return false; } else { - plumed_merror(type + " is not a valid molecule type"); - } + plumed_merror(type + " is not a valid molecule type"); + } return false; } -void MolDataClass::specialSymbol( const std::string& type, const std::string& symbol, const PDB& mypdb, std::vector& numbers ){ - if(type=="protein" || type=="rna" || type=="dna"){ +void MolDataClass::specialSymbol( const std::string& type, const std::string& symbol, const PDB& mypdb, std::vector& numbers ) { + if(type=="protein" || type=="rna" || type=="dna") { // symbol should be something like // phi-123 i.e. phi torsion of residue 123 of first chain // psi-A321 i.e. psi torsion of residue 321 of chain A @@ -186,7 +186,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy unsigned resnum; std::string resname; std::string chainid; - if(firstnum==dash+1){ + if(firstnum==dash+1) { Tools::convert( symbol.substr(dash+1), resnum ); resname= mypdb.getResidueName(resnum); chainid="*"; // this is going to match the first chain @@ -197,23 +197,23 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy } resname= mypdb.getResidueName(resnum,chainid); Tools::stripLeadingAndTrailingBlanks(resname); - if(allowedResidue("protein",resname)){ - if( name=="phi" && !isTerminalGroup("protein",resname) ){ + if(allowedResidue("protein",resname)) { + if( name=="phi" && !isTerminalGroup("protein",resname) ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum-1,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum,chainid)); - } else if( name=="psi" && !isTerminalGroup("protein",resname) ){ + } else if( name=="psi" && !isTerminalGroup("protein",resname) ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum+1,chainid)); - } else if( name=="omega" && !isTerminalGroup("protein",resname) ){ + } else if( name=="omega" && !isTerminalGroup("protein",resname) ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum+1,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum+1,chainid)); - } else if( name=="chi1" && !isTerminalGroup("protein",resname) ){ + } else if( name=="chi1" && !isTerminalGroup("protein",resname) ) { if ( resname=="GLY" || resname=="ALA" ) plumed_merror("chi-1 is not defined for Alanine and Glycine"); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CA",resnum,chainid)); @@ -229,7 +229,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy else numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("CG",resnum,chainid)); } else numbers.push_back(mypdb.getNamedAtomFromResidueAndChain(name,resnum,chainid)); - } else if( allowedResidue("rna",resname) || allowedResidue("dna",resname)){ + } else if( allowedResidue("rna",resname) || allowedResidue("dna",resname)) { std::string basetype; if(resname.find_first_of("A")!=std::string::npos) basetype+="A"; if(resname.find_first_of("U")!=std::string::npos) basetype+="U"; @@ -240,10 +240,10 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy if( name=="chi" ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O4\'",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C1\'",resnum,chainid)); - if(basetype=="T" || basetype=="U" || basetype=="C"){ + if(basetype=="T" || basetype=="U" || basetype=="C") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); - } else if(basetype=="G" || basetype=="A"){ + } else if(basetype=="G" || basetype=="A") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N9",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); } else plumed_error(); @@ -316,7 +316,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2\'",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C3\'",resnum,chainid)); } else if( name=="base" ) { - if(basetype=="C"){ + if(basetype=="C") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O2",resnum,chainid)); @@ -325,7 +325,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="U"){ + } else if(basetype=="U") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O2",resnum,chainid)); @@ -334,7 +334,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="T"){ + } else if(basetype=="T") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("O2",resnum,chainid)); @@ -344,7 +344,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C7",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="G"){ + } else if(basetype=="G") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N9",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N3",resnum,chainid)); @@ -356,7 +356,7 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C5",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N7",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C8",resnum,chainid)); - } else if(basetype=="A"){ + } else if(basetype=="A") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N9",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("N1",resnum,chainid)); @@ -370,19 +370,19 @@ void MolDataClass::specialSymbol( const std::string& type, const std::string& sy } else plumed_error(); } else if( name=="lcs" ) { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C2",resnum,chainid)); - if(basetype=="T" || basetype=="U" || basetype=="C"){ + if(basetype=="T" || basetype=="U" || basetype=="C") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); - } else if(basetype=="G" || basetype=="A"){ + } else if(basetype=="G" || basetype=="A") { numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C6",resnum,chainid)); numbers.push_back(mypdb.getNamedAtomFromResidueAndChain("C4",resnum,chainid)); - } else plumed_error(); + } else plumed_error(); } else numbers.push_back(mypdb.getNamedAtomFromResidueAndChain(name,resnum,chainid)); } } else { - plumed_merror(type + " is not a valid molecule type"); + plumed_merror(type + " is not a valid molecule type"); } -} +} } diff --git a/src/tools/MolDataClass.h b/src/tools/MolDataClass.h index 7ffb6c425e..e3ee323356 100644 --- a/src/tools/MolDataClass.h +++ b/src/tools/MolDataClass.h @@ -26,12 +26,12 @@ #include #include "AtomNumber.h" -namespace PLMD{ +namespace PLMD { class PDB; /// This class provides information on various kinds of molecules -/// for instance the kinds of residues that are in a protein +/// for instance the kinds of residues that are in a protein /// the atoms involved in the backbone of a particular residue etc class MolDataClass { public: @@ -40,7 +40,7 @@ class MolDataClass { /// Return the number of atoms in the backbone per residue e.g. 5 for proteins static unsigned numberOfAtomsPerResidueInBackbone( const std::string& type ); /// Return the names of the atoms in the backbone e.g. N, CA, CB, C, O for most protein residues - static void getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ); + static void getBackboneForResidue( const std::string& type, const unsigned& residuenum, const PDB& mypdb, std::vector& atoms ); /// Return true if the residue is a terminal group e.g. ACE, NME for proteins static bool isTerminalGroup( const std::string& type, const std::string& residuename ); /// Used to interpret special symbols - currently phi and psi and omega diff --git a/src/tools/MultiValue.cpp b/src/tools/MultiValue.cpp index 80a8f6b865..cdf2421659 100644 --- a/src/tools/MultiValue.cpp +++ b/src/tools/MultiValue.cpp @@ -21,98 +21,98 @@ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ #include "MultiValue.h" -namespace PLMD{ +namespace PLMD { MultiValue::MultiValue( const unsigned& nvals, const unsigned& nder ): -values(nvals), -nderivatives(nder), -derivatives(nvals*nder), -tmpval(0), -tmpder(nder), -atLeastOneSet(false) + values(nvals), + nderivatives(nder), + derivatives(nvals*nder), + tmpval(0), + tmpder(nder), + atLeastOneSet(false) { std::vector myind( nder ); - for(unsigned i=0;i myind( nder ); - for(unsigned i=0;i myind( nder ); + for(unsigned i=0; i& buffer ){ +void MultiValue::chainRule( const unsigned& ival, const unsigned& iout, const unsigned& stride, const unsigned& off, + const double& df, const unsigned& bufstart, std::vector& buffer ) { if( !hasDerivatives.updateComplete() ) hasDerivatives.updateActiveMembers(); plumed_dbg_assert( offepsilon ){ wpref=1.0/tmpval; } - else{ wpref=1.0; } + if( fabs(tmpval)>epsilon ) { wpref=1.0/tmpval; } + else { wpref=1.0; } double pref = values[nder]*wpref*wpref; - for(unsigned j=0;j indices, sort_indices; std::vector tmp_atoms; public: - MultiValue( const unsigned& , const unsigned& ); - void resize( const unsigned& , const unsigned& ); + MultiValue( const unsigned&, const unsigned& ); + void resize( const unsigned&, const unsigned& ); /// std::vector& getIndices(); std::vector& getSortIndices(); std::vector& getAtomVector(); /// Get the number of values in the stash - unsigned getNumberOfValues() const ; + unsigned getNumberOfValues() const ; /// Get the number of derivatives in the stash unsigned getNumberOfDerivatives() const ; /// Set value numbered @@ -63,7 +63,7 @@ class MultiValue { /// Add value numbered void addValue( const unsigned&, const double& ); /// Add derivative - void addDerivative( const unsigned& , const unsigned& , const double& ); + void addDerivative( const unsigned&, const unsigned&, const double& ); /// Add to the tempory value void addTemporyValue( const double& val ); /// Add tempory derivatives - this is used for calculating quotients @@ -75,7 +75,7 @@ class MultiValue { /// Return a derivative value double getDerivative( const unsigned&, const unsigned& ) const ; /// Get one of the tempory derivatives - double getTemporyDerivative( const unsigned& jder ) const ; + double getTemporyDerivative( const unsigned& jder ) const ; /// Clear all values void clearAll(); /// Clear the tempory derivatives @@ -96,7 +96,7 @@ class MultiValue { /// unsigned getActiveIndex( const unsigned& ) const ; /// Transfer derivatives to buffer - void chainRule( const unsigned& , const unsigned& , const unsigned&, const unsigned& , const double& , const unsigned& , std::vector& buffer ); + void chainRule( const unsigned&, const unsigned&, const unsigned&, const unsigned&, const double&, const unsigned&, std::vector& buffer ); /// void copyValues( MultiValue& ) const ; /// @@ -122,37 +122,37 @@ double MultiValue::get( const unsigned& ival ) const { } inline -void MultiValue::setValue( const unsigned& ival, const double& val){ +void MultiValue::setValue( const unsigned& ival, const double& val) { plumed_dbg_assert( ival<=values.size() ); values[ival]=val; } inline -void MultiValue::addValue( const unsigned& ival, const double& val){ +void MultiValue::addValue( const unsigned& ival, const double& val) { plumed_dbg_assert( ival<=values.size() ); values[ival]+=val; } inline -void MultiValue::addDerivative( const unsigned& ival, const unsigned& jder, const double& der){ +void MultiValue::addDerivative( const unsigned& ival, const unsigned& jder, const double& der) { plumed_dbg_assert( ival<=values.size() && jder& MultiValue::getIndices(){ +std::vector& MultiValue::getIndices() { return indices; } inline -std::vector& MultiValue::getSortIndices(){ +std::vector& MultiValue::getSortIndices() { return sort_indices; } inline -std::vector& MultiValue::getAtomVector(){ +std::vector& MultiValue::getAtomVector() { return tmp_atoms; } diff --git a/src/tools/NeighborList.cpp b/src/tools/NeighborList.cpp index 038aefd70d..8ce8fafd72 100644 --- a/src/tools/NeighborList.cpp +++ b/src/tools/NeighborList.cpp @@ -27,142 +27,142 @@ #include #include -namespace PLMD{ +namespace PLMD { using namespace std; NeighborList::NeighborList(const vector& list0, const vector& list1, const bool& do_pair, const bool& do_pbc, const Pbc& pbc, const double& distance, const unsigned& stride): reduced(false), - do_pair_(do_pair), do_pbc_(do_pbc), pbc_(&pbc), - distance_(distance), stride_(stride) + do_pair_(do_pair), do_pbc_(do_pbc), pbc_(&pbc), + distance_(distance), stride_(stride) { // store full list of atoms needed - fullatomlist_=list0; - fullatomlist_.insert(fullatomlist_.end(),list1.begin(),list1.end()); - nlist0_=list0.size(); - nlist1_=list1.size(); - twolists_=true; - if(!do_pair){ - nallpairs_=nlist0_*nlist1_; - }else{ - plumed_assert(nlist0_==nlist1_); - nallpairs_=nlist0_; - } - initialize(); - lastupdate_=0; + fullatomlist_=list0; + fullatomlist_.insert(fullatomlist_.end(),list1.begin(),list1.end()); + nlist0_=list0.size(); + nlist1_=list1.size(); + twolists_=true; + if(!do_pair) { + nallpairs_=nlist0_*nlist1_; + } else { + plumed_assert(nlist0_==nlist1_); + nallpairs_=nlist0_; + } + initialize(); + lastupdate_=0; } NeighborList::NeighborList(const vector& list0, const bool& do_pbc, const Pbc& pbc, const double& distance, const unsigned& stride): reduced(false), - do_pbc_(do_pbc), pbc_(&pbc), - distance_(distance), stride_(stride){ - fullatomlist_=list0; - nlist0_=list0.size(); - twolists_=false; - nallpairs_=nlist0_*(nlist0_-1)/2; - initialize(); - lastupdate_=0; + do_pbc_(do_pbc), pbc_(&pbc), + distance_(distance), stride_(stride) { + fullatomlist_=list0; + nlist0_=list0.size(); + twolists_=false; + nallpairs_=nlist0_*(nlist0_-1)/2; + initialize(); + lastupdate_=0; } void NeighborList::initialize() { - neighbors_.clear(); - for(unsigned int i=0;i& NeighborList::getFullAtomList() { - return fullatomlist_; + return fullatomlist_; } pair NeighborList::getIndexPair(unsigned ipair) { - pair index; - if(twolists_ && do_pair_){ - index=pair(ipair,ipair+nlist0_); - }else if (twolists_ && !do_pair_){ - index=pair(ipair/nlist1_,ipair%nlist1_+nlist0_); - }else if (!twolists_){ - unsigned ii = nallpairs_-1-ipair; - unsigned K = unsigned(floor((sqrt(double(8*ii+1))+1)/2)); - unsigned jj = ii-K*(K-1)/2; - index=pair(nlist0_-1-K,nlist0_-1-jj); - } - return index; + pair index; + if(twolists_ && do_pair_) { + index=pair(ipair,ipair+nlist0_); + } else if (twolists_ && !do_pair_) { + index=pair(ipair/nlist1_,ipair%nlist1_+nlist0_); + } else if (!twolists_) { + unsigned ii = nallpairs_-1-ipair; + unsigned K = unsigned(floor((sqrt(double(8*ii+1))+1)/2)); + unsigned jj = ii-K*(K-1)/2; + index=pair(nlist0_-1-K,nlist0_-1-jj); + } + return index; } void NeighborList::update(const vector& positions) { - neighbors_.clear(); - const double d2=distance_*distance_; -// check if positions array has the correct length - plumed_assert(positions.size()==fullatomlist_.size()); - for(unsigned int i=0;i index=getIndexPair(i); - unsigned index0=index.first; - unsigned index1=index.second; - Vector distance; - if(do_pbc_){ - distance=pbc_->distance(positions[index0],positions[index1]); - } else { - distance=delta(positions[index0],positions[index1]); - } - double value=modulo2(distance); - if(value<=d2) {neighbors_.push_back(index);} - } - setRequestList(); + neighbors_.clear(); + const double d2=distance_*distance_; +// check if positions array has the correct length + plumed_assert(positions.size()==fullatomlist_.size()); + for(unsigned int i=0; i index=getIndexPair(i); + unsigned index0=index.first; + unsigned index1=index.second; + Vector distance; + if(do_pbc_) { + distance=pbc_->distance(positions[index0],positions[index1]); + } else { + distance=delta(positions[index0],positions[index1]); + } + double value=modulo2(distance); + if(value<=d2) {neighbors_.push_back(index);} + } + setRequestList(); } void NeighborList::setRequestList() { - requestlist_.clear(); - for(unsigned int i=0;i& NeighborList::getReducedAtomList() { - if(!reduced)for(unsigned int i=0;i(newindex0,newindex1); - } - reduced=true; - return requestlist_; + auto p = std::find(requestlist_.begin(), requestlist_.end(), index0); plumed_assert(p!=requestlist_.end()); newindex0=p-requestlist_.begin(); + p = std::find(requestlist_.begin(), requestlist_.end(), index1); plumed_assert(p!=requestlist_.end()); newindex1=p-requestlist_.begin(); + neighbors_[i]=pair(newindex0,newindex1); + } + reduced=true; + return requestlist_; } unsigned NeighborList::getStride() const { - return stride_; + return stride_; } unsigned NeighborList::getLastUpdate() const { - return lastupdate_; + return lastupdate_; } void NeighborList::setLastUpdate(unsigned step) { - lastupdate_=step; + lastupdate_=step; } unsigned NeighborList::size() const { - return neighbors_.size(); + return neighbors_.size(); } - pair NeighborList::getClosePair(unsigned i) const { - return neighbors_[i]; +pair NeighborList::getClosePair(unsigned i) const { + return neighbors_[i]; } vector NeighborList::getNeighbors(unsigned index) { - vector neighbors; - for(unsigned int i=0;i neighbors; + for(unsigned int i=0; i -namespace PLMD{ +namespace PLMD { class Pbc; /// \ingroup TOOLBOX /// A class that implements neighbor lists from two lists or a single list of atoms -class NeighborList +class NeighborList { bool reduced; bool do_pair_,do_pbc_,twolists_; @@ -45,30 +45,30 @@ class NeighborList /// Initialize the neighbor list with all possible pairs void initialize(); /// Return the pair of indexes in the positions array -/// of the two atoms forming the i-th pair among all possible pairs +/// of the two atoms forming the i-th pair among all possible pairs std::pair getIndexPair(unsigned i); /// Extract the list of atoms from the current list of close pairs void setRequestList(); public: NeighborList(const std::vector& list0, const std::vector& list1, - const bool& do_pair, const bool& do_pbc, const PLMD::Pbc& pbc, + const bool& do_pair, const bool& do_pbc, const PLMD::Pbc& pbc, const double& distance=1.0e+30, const unsigned& stride=0); NeighborList(const std::vector& list0, const bool& do_pbc, const PLMD::Pbc& pbc, const double& distance=1.0e+30, const unsigned& stride=0); -/// Return the list of all atoms. These are needed to rebuild the neighbor list. +/// Return the list of all atoms. These are needed to rebuild the neighbor list. std::vector& getFullAtomList(); /// Update the indexes in the neighbor list to match the /// ordering in the new positions array /// and return the new list of atoms that must be requested to the main code std::vector& getReducedAtomList(); /// Update the neighbor list and prepare the new -/// list of atoms that will be requested to the main code +/// list of atoms that will be requested to the main code void update(const std::vector& positions); /// Get the update stride of the neighbor list unsigned getStride() const; -/// Get the last step in which the neighbor list was updated +/// Get the last step in which the neighbor list was updated unsigned getLastUpdate() const; /// Set the step of the last update void setLastUpdate(unsigned step); @@ -78,7 +78,7 @@ class NeighborList std::pair getClosePair(unsigned i) const; /// Get the list of neighbors of the i-th atom std::vector getNeighbors(unsigned i); - ~NeighborList(){} + ~NeighborList() {} }; } diff --git a/src/tools/OFile.cpp b/src/tools/OFile.cpp index dcadbd6ca4..92108a1321 100644 --- a/src/tools/OFile.cpp +++ b/src/tools/OFile.cpp @@ -38,14 +38,14 @@ #include #endif -namespace PLMD{ +namespace PLMD { -size_t OFile::llwrite(const char*ptr,size_t s){ +size_t OFile::llwrite(const char*ptr,size_t s) { size_t r; if(linked) return linked->llwrite(ptr,s); - if(! (comm && comm->Get_rank()>0)){ + if(! (comm && comm->Get_rank()>0)) { if(!fp) plumed_merror("writing on uninitilized File"); - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB r=gzwrite(gzFile(gzfp),ptr,s); #else @@ -57,7 +57,7 @@ size_t OFile::llwrite(const char*ptr,size_t s){ } // This barrier is apparently useless since it comes // just before a Bcast. -// +// // Anyway, it looks like it is solving an issue that appeared on // TRAVIS (at least on my laptop) so I add it here. // GB @@ -80,40 +80,40 @@ OFile::OFile(): actual_buffer_length=0; buffer=new char[buflen]; // these are set to zero to avoid valgrind errors - for(unsigned i=0;i=buflen-actual_buffer_length){ + if(r>=buflen-actual_buffer_length) { int newlen=buflen; while(newlen<=r+actual_buffer_length) newlen*=2; char* newbuf=new char [newlen]; memmove(newbuf,buffer,buflen); - for(int k=buflen;k0) llwrite(linePrefix.c_str(),linePrefix.length()); llwrite(p1,p2-p1+1); actual_buffer_length-=(p2-p1)+1; @@ -141,7 +141,7 @@ int OFile::printf(const char*fmt,...){ return r; } -OFile& OFile::addConstantField(const std::string&name){ +OFile& OFile::addConstantField(const std::string&name) { Field f; f.name=name; const_fields.push_back(f); @@ -149,39 +149,39 @@ OFile& OFile::addConstantField(const std::string&name){ } -OFile& OFile::clearFields(){ +OFile& OFile::clearFields() { fields.clear(); const_fields.clear(); previous_fields.clear(); return *this; } -OFile& OFile::fmtField(const std::string&fmt){ +OFile& OFile::fmtField(const std::string&fmt) { this->fieldFmt=fmt; return *this; } -OFile& OFile::fmtField(){ +OFile& OFile::fmtField() { this->fieldFmt="%23.16lg"; return *this; } -OFile& OFile::printField(const std::string&name,double v){ +OFile& OFile::printField(const std::string&name,double v) { sprintf(buffer_string,fieldFmt.c_str(),v); printField(name,buffer_string); return *this; } -OFile& OFile::printField(const std::string&name,int v){ +OFile& OFile::printField(const std::string&name,int v) { sprintf(buffer_string," %d",v); printField(name,buffer_string); return *this; } -OFile& OFile::printField(const std::string&name,const std::string & v){ +OFile& OFile::printField(const std::string&name,const std::string & v) { unsigned i; - for(i=0;i=const_fields.size()){ + for(i=0; i=const_fields.size()) { Field field; field.name=name; field.value=v; @@ -193,45 +193,45 @@ OFile& OFile::printField(const std::string&name,const std::string & v){ return *this; } -OFile& OFile::setupPrintValue( Value *val ){ - if( val->isPeriodic() ){ - addConstantField("min_" + val->getName() ); - addConstantField("max_" + val->getName() ); +OFile& OFile::setupPrintValue( Value *val ) { + if( val->isPeriodic() ) { + addConstantField("min_" + val->getName() ); + addConstantField("max_" + val->getName() ); } return *this; } -OFile& OFile::printField( Value* val, const double& v ){ +OFile& OFile::printField( Value* val, const double& v ) { printField( val->getName(), v ); - if( val->isPeriodic() ){ - std::string min, max; val->getDomain( min, max ); - printField( "min_" + val->getName(), min ); - printField("max_" + val->getName(), max ); - } + if( val->isPeriodic() ) { + std::string min, max; val->getDomain( min, max ); + printField( "min_" + val->getName(), min ); + printField("max_" + val->getName(), max ); + } return *this; } -OFile& OFile::printField(){ +OFile& OFile::printField() { bool reprint=false; - if(fieldChanged || fields.size()!=previous_fields.size()){ + if(fieldChanged || fields.size()!=previous_fields.size()) { reprint=true; - } else for(unsigned i=0;i0 && (!comm || comm->Get_rank()==0)){ - FILE* ff=std::fopen(const_cast(fname.c_str()),"r"); - if(ff){ - std::fclose(ff); - std::string backup; - size_t found=fname.find_last_of("/\\"); - std::string directory=fname.substr(0,found+1); - std::string file=fname.substr(found+1); - for(int i=0;;i++){ - std::string num; - Tools::convert(i,num); - if(i>maxbackup) plumed_merror("cannot backup file "+file+" maximum number of backup is "+num+"\n"); - backup=directory+bstring +"."+num+"."+file; - FILE* fff=std::fopen(backup.c_str(),"r"); - if(!fff) break; - else std::fclose(fff); - } - int check=rename(fname.c_str(),backup.c_str()); - plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for reason: "+strerror(errno)); - } - } +void OFile::backupFile( const std::string& bstring, const std::string& fname ) { + if(fname=="/dev/null") return; + int maxbackup=100; + if(std::getenv("PLUMED_MAXBACKUP")) Tools::convert(std::getenv("PLUMED_MAXBACKUP"),maxbackup); + if(maxbackup>0 && (!comm || comm->Get_rank()==0)) { + FILE* ff=std::fopen(const_cast(fname.c_str()),"r"); + if(ff) { + std::fclose(ff); + std::string backup; + size_t found=fname.find_last_of("/\\"); + std::string directory=fname.substr(0,found+1); + std::string file=fname.substr(found+1); + for(int i=0;; i++) { + std::string num; + Tools::convert(i,num); + if(i>maxbackup) plumed_merror("cannot backup file "+file+" maximum number of backup is "+num+"\n"); + backup=directory+bstring +"."+num+"."+file; + FILE* fff=std::fopen(backup.c_str(),"r"); + if(!fff) break; + else std::fclose(fff); + } + int check=rename(fname.c_str(),backup.c_str()); + plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for reason: "+strerror(errno)); + } + } } -OFile& OFile::open(const std::string&path){ +OFile& OFile::open(const std::string&path) { plumed_assert(!cloned); eof=false; err=false; @@ -294,26 +294,26 @@ OFile& OFile::open(const std::string&path){ gzfp=NULL; this->path=path; this->path=appendSuffix(path,getSuffix()); - if(checkRestart()){ - fp=std::fopen(const_cast(this->path.c_str()),"a"); - mode="a"; - if(Tools::extension(this->path)=="gz"){ + if(checkRestart()) { + fp=std::fopen(const_cast(this->path.c_str()),"a"); + mode="a"; + if(Tools::extension(this->path)=="gz") { #ifdef __PLUMED_HAS_ZLIB - gzfp=(void*)gzopen(const_cast(this->path.c_str()),"a9"); + gzfp=(void*)gzopen(const_cast(this->path.c_str()),"a9"); #else - plumed_merror("trying to use a gz file without zlib being linked"); + plumed_merror("trying to use a gz file without zlib being linked"); #endif - } + } } else { - backupFile( backstring, this->path ); - if(comm)comm->Barrier(); - fp=std::fopen(const_cast(this->path.c_str()),"w"); - mode="w"; - if(Tools::extension(this->path)=="gz"){ + backupFile( backstring, this->path ); + if(comm)comm->Barrier(); + fp=std::fopen(const_cast(this->path.c_str()),"w"); + mode="w"; + if(Tools::extension(this->path)=="gz") { #ifdef __PLUMED_HAS_ZLIB - gzfp=(void*)gzopen(const_cast(this->path.c_str()),"w9"); + gzfp=(void*)gzopen(const_cast(this->path.c_str()),"w9"); #else - plumed_merror("trying to use a gz file without zlib being linked"); + plumed_merror("trying to use a gz file without zlib being linked"); #endif } } @@ -321,18 +321,18 @@ OFile& OFile::open(const std::string&path){ return *this; } -OFile& OFile::rewind(){ +OFile& OFile::rewind() { // we use here "hard" rewind, which means close/reopen // the reason is that normal rewind does not work when in append mode // moreover, we can take a backup of the file plumed_assert(fp); clearFields(); - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB gzclose((gzFile)gzfp); #endif } else fclose(fp); - if(!comm || comm->Get_rank()==0){ + if(!comm || comm->Get_rank()==0) { std::string fname=this->path; size_t found=fname.find_last_of("/\\"); std::string directory=fname.substr(0,found+1); @@ -341,7 +341,7 @@ OFile& OFile::rewind(){ int check=rename(fname.c_str(),backup.c_str()); plumed_massert(check==0,"renaming "+fname+" into "+backup+" failed for reason: "+strerror(errno)); } - if(gzfp){ + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB gzfp=(void*)gzopen(const_cast(this->path.c_str()),"w9"); #endif @@ -349,14 +349,14 @@ OFile& OFile::rewind(){ return *this; } -FileBase& OFile::flush(){ - if(heavyFlush){ - if(gzfp){ +FileBase& OFile::flush() { + if(heavyFlush) { + if(gzfp) { #ifdef __PLUMED_HAS_ZLIB gzclose(gzFile(gzfp)); gzfp=(void*)gzopen(const_cast(path.c_str()),"a"); #endif - } else{ + } else { fclose(fp); fp=std::fopen(const_cast(path.c_str()),"a"); } @@ -372,7 +372,7 @@ FileBase& OFile::flush(){ return *this; } -bool OFile::checkRestart()const{ +bool OFile::checkRestart()const { if(enforceRestart_) return true; else if(enforceBackup_) return false; else if(action) return action->getRestart(); @@ -380,13 +380,13 @@ bool OFile::checkRestart()const{ else return false; } -OFile& OFile::enforceRestart(){ +OFile& OFile::enforceRestart() { enforceRestart_=true; enforceBackup_=false; return *this; } -OFile& OFile::enforceBackup(){ +OFile& OFile::enforceBackup() { enforceBackup_=true; enforceRestart_=false; return *this; diff --git a/src/tools/OFile.h b/src/tools/OFile.h index 106d88b6be..84f044a94d 100644 --- a/src/tools/OFile.h +++ b/src/tools/OFile.h @@ -26,7 +26,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class Value; @@ -90,7 +90,7 @@ the enforceRestart() method before opening a file. To have all files managed consistently, it is important to use OFile in the proper way. This should allow multi-replica plumed, restart and backups to work in -the expected way. For this reason all the operations in OFile and IFile +the expected way. For this reason all the operations in OFile and IFile are synchronizing all the processors of the group, so call to OFile functions should always be performed by all processes; for this reason is also not usefull to use Log for debugging because only master threads will actually write. @@ -129,7 +129,7 @@ int main(){ snp.flush(); // the only difference is that snp is rewound // notice that it should be rewound just before writing -// because rewind is going to move the file out of the way +// because rewind is going to move the file out of the way // to have a safe copy of the file ("bck.last.filename") // Also notice that snapshots should be flushed // for this reason, it is better to write them only @@ -145,7 +145,7 @@ int main(){ */ class OFile: -public virtual FileBase{ + public virtual FileBase { /// Pointer to a linked OFile. /// see link(OFile&) OFile* linked; @@ -159,7 +159,7 @@ public virtual FileBase{ unsigned actual_buffer_length; /// Class identifying a single field for fielded output class Field: - public FieldBase{ + public FieldBase { }; /// Low-level write size_t llwrite(const char*,size_t); @@ -208,13 +208,13 @@ public virtual FileBase{ /// Backup a file by giving it a different name void backupFile( const std::string& bstring, const std::string& fname ); /// This backs up all the files that would have been created with the -/// name str. It is used in analysis when you are not restarting. Analysis +/// name str. It is used in analysis when you are not restarting. Analysis /// output files at different times, which are names analysis.0., /// analysis.1. and , are backed up to bck.0.analysis.0., /// bck.0.analysis.1. and bck.0. void backupAllFiles( const std::string& str ); /// Opens the file using automatic append/backup - OFile& open(const std::string&name); + OFile& open(const std::string&name); /// Set the prefix for output. /// Typically "PLUMED: ". Notice that lines with a prefix cannot /// be parsed using fields in a IFile. @@ -235,18 +235,18 @@ public virtual FileBase{ OFile& setupPrintValue( Value *val ); /// Print a value OFile& printField( Value* val, const double& v ); -/** Close a line. -Typically used as -\verbatim - of.printField("a",a).printField("b",b).printField(); -\endverbatim -*/ + /** Close a line. + Typically used as + \verbatim + of.printField("a",a).printField("b",b).printField(); + \endverbatim + */ OFile& printField(); -/** -Resets the list of fields. -As it is only possible to add new constant fields (addConstantField()), -this method can be used to clean the field list. -*/ + /** + Resets the list of fields. + As it is only possible to add new constant fields (addConstantField()), + this method can be used to clean the field list. + */ OFile& clearFields(); /// Formatted output with explicit format - a la printf int printf(const char*fmt,...); @@ -266,7 +266,7 @@ this method can be used to clean the field list. /// Write using << syntax template -OFile& operator<<(OFile&of,const T &t){ +OFile& operator<<(OFile&of,const T &t) { of.oss< -namespace PLMD{ +namespace PLMD { -unsigned OpenMP::getCachelineSize(){ +unsigned OpenMP::getCachelineSize() { static unsigned cachelineSize=512; if(std::getenv("PLUMED_CACHELINE_SIZE")) Tools::convert(std::getenv("PLUMED_CACHELINE_SIZE"),cachelineSize); return cachelineSize; } -unsigned OpenMP::getNumThreads(){ +unsigned OpenMP::getNumThreads() { static unsigned numThreads=1; if(std::getenv("PLUMED_NUM_THREADS")) Tools::convert(std::getenv("PLUMED_NUM_THREADS"),numThreads); return numThreads; diff --git a/src/tools/OpenMP.h b/src/tools/OpenMP.h index 418451c176..c79258ff76 100644 --- a/src/tools/OpenMP.h +++ b/src/tools/OpenMP.h @@ -24,30 +24,30 @@ #include -namespace PLMD{ +namespace PLMD { -class OpenMP{ +class OpenMP { public: /// Get number of threads that can be used by openMP -static unsigned getNumThreads(); + static unsigned getNumThreads(); /// get cacheline size -static unsigned getCachelineSize(); + static unsigned getCachelineSize(); /// Get a reasonable number of threads so as to access to an array of size s located at x -template -static unsigned getGoodNumThreads(const T*x,unsigned s); + template + static unsigned getGoodNumThreads(const T*x,unsigned s); /// Get a reasonable number of threads so as to access to vector v; -template -static unsigned getGoodNumThreads(const std::vector & v); + template + static unsigned getGoodNumThreads(const std::vector & v); }; template -unsigned OpenMP::getGoodNumThreads(const T*x,unsigned n){ +unsigned OpenMP::getGoodNumThreads(const T*x,unsigned n) { unsigned long p=(unsigned long) x; (void) p; // this is not to have warnings. notice that the pointer location is not used actually. // a factor two is necessary since there is no guarantee that x is aligned @@ -61,7 +61,7 @@ unsigned OpenMP::getGoodNumThreads(const T*x,unsigned n){ template -unsigned OpenMP::getGoodNumThreads(const std::vector & v){ +unsigned OpenMP::getGoodNumThreads(const std::vector & v) { if(v.size()==0) return 1; else return getGoodNumThreads(&v[0],v.size()); } diff --git a/src/tools/PDB.cpp b/src/tools/PDB.cpp index f4e0d398a9..128e4620e9 100644 --- a/src/tools/PDB.cpp +++ b/src/tools/PDB.cpp @@ -27,14 +27,14 @@ using namespace std; -namespace PLMD{ +namespace PLMD { /// Tiny namespace for hybrid36 format. /// This namespace includes freely available tools for h36 format. /// I place them here for usage within PDB class. In case we need them /// in other places they might be better encapsulated in a c++ class /// and placed in a separate file. -namespace h36{ +namespace h36 { /*! C port of the hy36encode() and hy36decode() functions in the @@ -117,7 +117,7 @@ encode_pure( value = rest; } if (j) buf[i++] = '-'; - for(j=i;j 127) { *result = 0; @@ -270,15 +270,15 @@ hy36decode(unsigned width, const char* s, unsigned s_size, int* result) static int digits_values_upper[128U]; static int digits_values_lower[128U]; static const char* - ie_range = "internal error hy36decode: integer value out of range."; + ie_range = "internal error hy36decode: integer value out of range."; unsigned i; int di; const char* errmsg; if (first_call) { first_call = 0; - for(i=0;i<128U;i++) digits_values_upper[i] = -1; - for(i=0;i<128U;i++) digits_values_lower[i] = -1; - for(i=0;i<36U;i++) { + for(i=0; i<128U; i++) digits_values_upper[i] = -1; + for(i=0; i<128U; i++) digits_values_lower[i] = -1; + for(i=0; i<36U; i++) { di = digits_upper()[i]; if (di < 0 || di > 127) { *result = 0; @@ -286,7 +286,7 @@ hy36decode(unsigned width, const char* s, unsigned s_size, int* result) } digits_values_upper[di] = i; } - for(i=0;i<36U;i++) { + for(i=0; i<36U; i++) { di = digits_lower()[i]; if (di < 0 || di > 127) { *result = 0; @@ -341,72 +341,72 @@ hy36decode(unsigned width, const char* s, unsigned s_size, int* result) } -unsigned PDB::getNumberOfAtomBlocks()const{ +unsigned PDB::getNumberOfAtomBlocks()const { return block_ends.size(); } -const std::vector & PDB::getAtomBlockEnds()const{ +const std::vector & PDB::getAtomBlockEnds()const { return block_ends; } -const std::vector & PDB::getPositions()const{ +const std::vector & PDB::getPositions()const { return positions; } -void PDB::setPositions(const std::vector &v ){ - plumed_assert( v.size()==positions.size() ); - positions=v; +void PDB::setPositions(const std::vector &v ) { + plumed_assert( v.size()==positions.size() ); + positions=v; } -const std::vector & PDB::getOccupancy()const{ +const std::vector & PDB::getOccupancy()const { return occupancy; } -const std::vector & PDB::getBeta()const{ +const std::vector & PDB::getBeta()const { return beta; } -const std::vector & PDB::getRemark()const{ +const std::vector & PDB::getRemark()const { return remark; } -void PDB::addRemark( const std::vector& v1 ){ +void PDB::addRemark( const std::vector& v1 ) { remark.insert(remark.begin(),v1.begin(),v1.end()); } -const std::vector & PDB::getAtomNumbers()const{ +const std::vector & PDB::getAtomNumbers()const { return numbers; } -std::string PDB::getAtomName(AtomNumber a)const{ +std::string PDB::getAtomName(AtomNumber a)const { const auto p=number2index.find(a); if(p==number2index.end()) return ""; else return atomsymb[p->second]; } -unsigned PDB::getResidueNumber(AtomNumber a)const{ +unsigned PDB::getResidueNumber(AtomNumber a)const { const auto p=number2index.find(a); if(p==number2index.end()) return 0; else return residue[p->second]; } -std::string PDB::getResidueName(AtomNumber a) const{ +std::string PDB::getResidueName(AtomNumber a) const { const auto p=number2index.find(a); if(p==number2index.end()) return ""; else return residuenames[p->second]; } -unsigned PDB::size()const{ +unsigned PDB::size()const { return positions.size(); } -bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale){ +bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale) { //cerr< v1; v1=Tools::getWords(line.substr(6)); - addRemark( v1 ); + if(record=="TER") { between_ters=false; block_ends.push_back( positions.size() ); } + if(record=="END") { file_is_alive=true; break;} + if(record=="ENDMDL") { file_is_alive=true; break;} + if(record=="REMARK") { + vector v1; v1=Tools::getWords(line.substr(6)); + addRemark( v1 ); } - if(record=="ATOM" || record=="HETATM"){ + if(record=="ATOM" || record=="HETATM") { between_ters=true; AtomNumber a; unsigned resno; double o,b; @@ -439,7 +439,7 @@ bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale){ { int result; const char* errmsg = h36::hy36decode(5, serial.c_str(),5, &result); - if(errmsg){ + if(errmsg) { std::string msg(errmsg); plumed_merror(msg); } @@ -471,17 +471,17 @@ bool PDB::readFromFilepointer(FILE *fp,bool naturalUnits,double scale){ return file_is_alive; } -void PDB::setArgKeyword( const std::string& new_args ){ +void PDB::setArgKeyword( const std::string& new_args ) { bool replaced=false; - for(unsigned i=0;i& chains ) const { chains.resize(0); chains.push_back( chain[0] ); - for(unsigned i=1;i PDB::getAtomsInResidue(const unsigned& resnum,const std::string& chainid)const { std::vector tmp; - for(unsigned i=0;i PDB::getAtomsInResidue(const unsigned& resnum,const std: std::vector PDB::getAtomsInChain(const std::string& chainid)const { std::vector tmp; - for(unsigned i=0;i PDB::getAtomsInChain(const std::string& chainid)const { } std::string PDB::getChainID(const unsigned& resnumber) const { - for(unsigned i=0;isecond]; +Vector PDB::getPosition(AtomNumber a)const { + const auto p=number2index.find(a); + if(p==number2index.end()) plumed_merror("atom not available"); + else return positions[p->second]; } diff --git a/src/tools/PDB.h b/src/tools/PDB.h index 059ea4f6c1..05cee0a8a6 100644 --- a/src/tools/PDB.h +++ b/src/tools/PDB.h @@ -29,14 +29,14 @@ #include -namespace PLMD{ +namespace PLMD { class Log; /// Minimalistic pdb parser. /// Contain positions, atomic indexes, occupancy and beta. /// We should also add other info (e.g. residue name etc). -class PDB{ +class PDB { std::vector block_ends; std::vector atomsymb, chain; std::vector residue; @@ -59,11 +59,11 @@ class PDB{ /// Access to the beta array const std::vector & getBeta()const; /// This is used to set the keyword ARG - this is so we -/// we can use a1.* in the input for reference configurations +/// we can use a1.* in the input for reference configurations void setArgKeyword( const std::string& new_args ); /// Add information to the remark void addRemark( const std::vector& v1 ); -/// Access to the lines of REMARK +/// Access to the lines of REMARK const std::vector & getRemark()const; /// Access to the indexes const std::vector & getAtomNumbers()const; @@ -73,11 +73,11 @@ class PDB{ void getChainNames( std::vector& chains ) const; /// Get the residues in each of the chains void getResidueRange( const std::string& chainname, unsigned& res_start, unsigned& res_end, std::string& errmsg ) const; -/// Get the atoms in each of the chains +/// Get the atoms in each of the chains void getAtomRange( const std::string& chainname, AtomNumber& a_start, AtomNumber& a_end, std::string& errmsg ) const; /// Get the chain ID that a particular residue is a part of std::string getChainID(const unsigned& resnumber) const; -///use the log to dump information +///use the log to dump information friend Log& operator<<(Log& ostr, const PDB& pdb); /// return the name of a specific atom std::string getAtomName(AtomNumber a) const; @@ -99,9 +99,9 @@ class PDB{ /// Return the atom named aname from residue number resnum and chain. /// Chain=="*" matches any chain and makes it equivalent to getNamedAtomFromResidue. AtomNumber getNamedAtomFromResidueAndChain( const std::string& aname, const unsigned& resnum, const std::string& chain ) const; -/// Access to the atoms of a residue +/// Access to the atoms of a residue std::vector getAtomsInResidue(const unsigned& resnum,const std::string& chainid)const; -/// Access to the atoms of a chain +/// Access to the atoms of a chain std::vector getAtomsInChain(const std::string& chainid)const; /// Get the extents of the blocks containing the atoms const std::vector & getAtomBlockEnds() const ; diff --git a/src/tools/Pbc.cpp b/src/tools/Pbc.cpp index 025a2fa447..ff0ac18b0e 100644 --- a/src/tools/Pbc.cpp +++ b/src/tools/Pbc.cpp @@ -27,7 +27,7 @@ #include "Random.h" #include -namespace PLMD{ +namespace PLMD { Pbc::Pbc(): type(unset) @@ -36,83 +36,83 @@ Pbc::Pbc(): invBox.zero(); } -void Pbc::buildShifts(std::vector shifts[2][2][2])const{ +void Pbc::buildShifts(std::vector shifts[2][2][2])const { const double small=1e-28; // clear all shifts - for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) shifts[i][j][k].clear(); + for(int i=0; i<2; i++) for(int j=0; j<2; j++) for(int k=0; k<2; k++) shifts[i][j][k].clear(); // enumerate all possible shifts // since box is reduced, only 27 shifts have to be attempted - for(int l=-1;l<=1;l++) for(int m=-1;m<=1;m++) for(int n=-1;n<=1;n++){ + for(int l=-1; l<=1; l++) for(int m=-1; m<=1; m++) for(int n=-1; n<=1; n++) { // int/double shift vectors - int ishift[3]={l,m,n}; - Vector dshift(l,m,n); + int ishift[3]= {l,m,n}; + Vector dshift(l,m,n); // count how many components are != 0 - unsigned count=0; - for(int s=0;s<3;s++) if(ishift[s]!=0) count++; + unsigned count=0; + for(int s=0; s<3; s++) if(ishift[s]!=0) count++; // skips trivial (0,0,0) and cases with three shifts // only 18 shifts survive past this point - if(count==0 || count==3) continue; + if(count==0 || count==3) continue; // check if that Wigner-Seitz face is perpendicular to the axis. // this allows to eliminate shifts in symmetric cells. // e.g., if one lactice vector is orthogonal to the plane spanned // by the other two vectors, that shift should never be tried - Vector cosdir=matmul(reduced,transpose(reduced),dshift); - double dp=dotProduct(dshift,cosdir); - double ref=modulo2(dshift)*modulo2(cosdir); - if(std::fabs(ref-dp*dp)0) skip=true; - if(skip) continue; - skip=true; - for(int s=0;s<3;s++){ + bool skip=false; + for(int s=0; s<3; s++) if(ishift[s]*block[s]>0) skip=true; + if(skip) continue; + skip=true; + for(int s=0; s<3; s++) { // check that the components of cosdir along the non-shifted directions // have the proper sign - if(((1-ishift[s]*ishift[s])*block[s])*cosdir[s]<-small) skip=false; - } - if(skip)continue; + if(((1-ishift[s]*ishift[s])*block[s])*cosdir[s]<-small) skip=false; + } + if(skip)continue; // if we arrive to this point, shift is eligible and is added to the list - shifts[i][j][k].push_back(matmul(transpose(reduced),dshift)); - } - } + shifts[i][j][k].push_back(matmul(transpose(reduced),dshift)); + } + } } -void Pbc::fullSearch(Vector&d)const{ - if(type==unset) return; - Vector s=matmul(invReduced.transpose(),d); - for(int i=0;i<3;i++) s[i]=Tools::pbc(s[i]); - d=matmul(reduced.transpose(),s); - const int smax=4; - Vector a0(reduced.getRow(0)); - Vector a1(reduced.getRow(1)); - Vector a2(reduced.getRow(2)); - Vector best(d); - double lbest=d.modulo2(); - for(int i=-smax;i<=smax;i++) for(int j=-smax;j<=smax;j++) for(int k=-smax;k<=smax;k++){ - Vector trial=d+i*a0+j*a1+k*a2; - double ltrial=trial.modulo2(); - if(ltrial& dlist, unsigned max_index) const { - if (max_index==0) max_index=dlist.size(); - if(type==unset){ + if (max_index==0) max_index=dlist.size(); + if(type==unset) { } else if(type==orthorombic) { #ifdef __PLUMED_PBC_WHILE - for(unsigned k=0;khdiag[0]) dlist[k][0]-=diag[0]; while(dlist[k][0]<=mdiag[0]) dlist[k][0]+=diag[0]; while(dlist[k][1]>hdiag[1]) dlist[k][1]-=diag[1]; while(dlist[k][1]<=mdiag[1]) dlist[k][1]+=diag[1]; while(dlist[k][2]>hdiag[2]) dlist[k][2]-=diag[2]; - while(dlist[k][2]<=mdiag[2]) dlist[k][2]+=diag[2]; - } + while(dlist[k][2]<=mdiag[2]) dlist[k][2]+=diag[2]; + } #else - for(unsigned k=0;khdiag[i]) d[i]-=diag[i]; while(d[i]<=mdiag[i]) d[i]+=diag[i]; } #else - for(int i=0;i<3;i++) d[i]=Tools::pbc(d[i]*invBox(i,i))*box(i,i); + for(int i=0; i<3; i++) d[i]=Tools::pbc(d[i]*invBox(i,i))*box(i,i); #endif } else if(type==generic) { Vector s=matmul(d,invReduced); @@ -195,22 +195,22 @@ Vector Pbc::distance(const Vector&v1,const Vector&v2,int*nshifts)const{ // NOTICE: the check in the previous line, albeit correct, is breaking many regtest // since it does not apply Tools::pbc in many cases. Moreover, it does not // introduce a significant gain. I thus leave it out for the moment. - if(true){ + if(true) { // bring to -0.5,+0.5 region in scaled coordinates: - for(int i=0;i<3;i++) s[i]=Tools::pbc(s[i]); + for(int i=0; i<3; i++) s[i]=Tools::pbc(s[i]); d=matmul(s,reduced); // check if shifts have to be attempted: - if((std::fabs(s[0])+std::fabs(s[1])+std::fabs(s[2])>0.5)){ + if((std::fabs(s[0])+std::fabs(s[1])+std::fabs(s[2])>0.5)) { // list of shifts is specific for that "octant" (depends on signs of s[i]): const std::vector & myshifts(shifts[(s[0]>0?1:0)][(s[1]>0?1:0)][(s[2]>0?1:0)]); Vector best(d); double lbest(modulo2(best)); // loop over possible shifts: if(nshifts) *nshifts+=myshifts.size(); - for(unsigned i=0;i #include -namespace PLMD{ +namespace PLMD { /* Tool to deal with periodic boundary conditions. @@ -35,7 +35,7 @@ Tool to deal with periodic boundary conditions. This class is useful to apply periodic boundary conditions on interatomic distances. It stores privately information about reduced lattice vectors */ -class Pbc{ +class Pbc { /// Type of box enum {unset,orthorombic,generic} type; /// Box @@ -98,12 +98,12 @@ class Pbc{ }; inline -Vector Pbc::distance(const Vector& v1,const Vector& v2)const{ +Vector Pbc::distance(const Vector& v1,const Vector& v2)const { return distance(v1,v2,NULL); } inline -bool Pbc::isSet()const{ +bool Pbc::isSet()const { return type!=unset; } diff --git a/src/tools/RMSD.cpp b/src/tools/RMSD.cpp index 4818576700..0bc2eff548 100644 --- a/src/tools/RMSD.cpp +++ b/src/tools/RMSD.cpp @@ -27,45 +27,45 @@ #include #include "Tools.h" using namespace std; -namespace PLMD{ +namespace PLMD { RMSD::RMSD() : alignmentMethod(SIMPLE),reference_center_is_calculated(false),reference_center_is_removed(false),positions_center_is_calculated(false),positions_center_is_removed(false) {} /// -/// general method to set all the rmsd property at once by using a pdb where occupancy column sets the weights for the atoms involved in the -/// alignment and beta sets the weight that are used for calculating the displacement. +/// general method to set all the rmsd property at once by using a pdb where occupancy column sets the weights for the atoms involved in the +/// alignment and beta sets the weight that are used for calculating the displacement. /// -void RMSD::set(const PDB&pdb, const string & mytype, bool remove_center, bool normalize_weights ){ +void RMSD::set(const PDB&pdb, const string & mytype, bool remove_center, bool normalize_weights ) { - set(pdb.getOccupancy(),pdb.getBeta(),pdb.getPositions(),mytype,remove_center,normalize_weights); + set(pdb.getOccupancy(),pdb.getBeta(),pdb.getPositions(),mytype,remove_center,normalize_weights); } -void RMSD::set(const std::vector & align, const std::vector & displace, const std::vector & reference , const string & mytype, bool remove_center, bool normalize_weights ){ +void RMSD::set(const std::vector & align, const std::vector & displace, const std::vector & reference, const string & mytype, bool remove_center, bool normalize_weights ) { - setReference(reference); // this by default remove the com and assumes uniform weights - setAlign(align, normalize_weights, remove_center); // this recalculates the com with weights. If remove_center=false then it restore the center back - setDisplace(displace, normalize_weights); // this is does not affect any calculation of the weights - setType(mytype); + setReference(reference); // this by default remove the com and assumes uniform weights + setAlign(align, normalize_weights, remove_center); // this recalculates the com with weights. If remove_center=false then it restore the center back + setDisplace(displace, normalize_weights); // this is does not affect any calculation of the weights + setType(mytype); } -void RMSD::setType(const string & mytype){ +void RMSD::setType(const string & mytype) { - alignmentMethod=SIMPLE; // initialize with the simplest case: no rotation - if (mytype=="SIMPLE"){ - alignmentMethod=SIMPLE; - } - else if (mytype=="OPTIMAL"){ - alignmentMethod=OPTIMAL; - } - else if (mytype=="OPTIMAL-FAST"){ - alignmentMethod=OPTIMAL_FAST; - } - else plumed_merror("unknown RMSD type" + mytype); + alignmentMethod=SIMPLE; // initialize with the simplest case: no rotation + if (mytype=="SIMPLE") { + alignmentMethod=SIMPLE; + } + else if (mytype=="OPTIMAL") { + alignmentMethod=OPTIMAL; + } + else if (mytype=="OPTIMAL-FAST") { + alignmentMethod=OPTIMAL_FAST; + } + else plumed_merror("unknown RMSD type" + mytype); } -void RMSD::clear(){ +void RMSD::clear() { reference.clear(); reference_center_is_calculated=false; reference_center_is_removed=false; @@ -75,98 +75,98 @@ void RMSD::clear(){ positions_center_is_removed=false; } -string RMSD::getMethod(){ - string mystring; - switch(alignmentMethod){ - case SIMPLE: mystring.assign("SIMPLE");break; - case OPTIMAL: mystring.assign("OPTIMAL");break; - case OPTIMAL_FAST: mystring.assign("OPTIMAL-FAST");break; - } - return mystring; +string RMSD::getMethod() { + string mystring; + switch(alignmentMethod) { + case SIMPLE: mystring.assign("SIMPLE"); break; + case OPTIMAL: mystring.assign("OPTIMAL"); break; + case OPTIMAL_FAST: mystring.assign("OPTIMAL-FAST"); break; + } + return mystring; } /// /// this calculates the center of mass for the reference and removes it from the reference itself /// considering uniform weights for alignment /// -void RMSD::setReference(const vector & reference){ +void RMSD::setReference(const vector & reference) { unsigned n=reference.size(); this->reference=reference; plumed_massert(align.empty(),"you should first clear() an RMSD object, then set a new reference"); plumed_massert(displace.empty(),"you should first clear() an RMSD object, then set a new reference"); align.resize(n,1.0/n); displace.resize(n,1.0/n); - for(unsigned i=0;ireference[i]*align[i]; - for(unsigned i=0;ireference[i]-=reference_center; + for(unsigned i=0; ireference[i]*align[i]; + for(unsigned i=0; ireference[i]-=reference_center; reference_center_is_calculated=true; reference_center_is_removed=true; } /// /// the alignment weights are here normalized to 1 and the center of the reference is removed accordingly /// -void RMSD::setAlign(const vector & align, bool normalize_weights, bool remove_center){ +void RMSD::setAlign(const vector & align, bool normalize_weights, bool remove_center) { unsigned n=reference.size(); plumed_massert(this->align.size()==align.size(),"mismatch in dimension of align/displace arrays"); this->align=align; - if(normalize_weights){ - double w=0.0; - for(unsigned i=0;ialign[i]; - double inv=1.0/w; - for(unsigned i=0;ialign[i]*=inv; + if(normalize_weights) { + double w=0.0; + for(unsigned i=0; ialign[i]; + double inv=1.0/w; + for(unsigned i=0; ialign[i]*=inv; } // recalculate the center anyway // just remove the center if that is asked // if the center was removed before, then add it and store the new one - if(reference_center_is_removed){ - plumed_massert(reference_center_is_calculated," seems that the reference center has been removed but not calculated and stored!"); - addCenter(reference,reference_center); + if(reference_center_is_removed) { + plumed_massert(reference_center_is_calculated," seems that the reference center has been removed but not calculated and stored!"); + addCenter(reference,reference_center); } reference_center=calculateCenter(reference,this->align); reference_center_is_calculated=true; - if(remove_center){ - removeCenter(reference,reference_center); - reference_center_is_removed=true; + if(remove_center) { + removeCenter(reference,reference_center); + reference_center_is_removed=true; } else { - reference_center_is_removed=false; + reference_center_is_removed=false; } } /// /// here the weigth for normalized weighths are normalized and set /// -void RMSD::setDisplace(const vector & displace, bool normalize_weights){ +void RMSD::setDisplace(const vector & displace, bool normalize_weights) { unsigned n=reference.size(); plumed_massert(this->displace.size()==displace.size(),"mismatch in dimension of align/displace arrays"); this->displace=displace; double w=0.0; - for(unsigned i=0;idisplace[i]; + for(unsigned i=0; idisplace[i]; double inv=1.0/w; - if(normalize_weights){for(unsigned i=0;idisplace[i]*=inv;} + if(normalize_weights) {for(unsigned i=0; idisplace[i]*=inv;} } /// /// This is the main workhorse for rmsd that decides to use specific optimal alignment versions /// -double RMSD::calculate(const std::vector & positions,std::vector &derivatives, bool squared)const{ +double RMSD::calculate(const std::vector & positions,std::vector &derivatives, bool squared)const { double ret=0.; - switch(alignmentMethod){ - case SIMPLE : { - // do a simple alignment without rotation - std::vector displacement( derivatives.size() ); - ret=simpleAlignment(align,displace,positions,reference,derivatives,displacement,squared); - break; - } case OPTIMAL_FAST : { - // this is calling the fastest option: - if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - break; - - } case OPTIMAL : { - // this is the fast routine but in the "safe" mode, which gives less numerical error: - if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); - break; - } - } + switch(alignmentMethod) { + case SIMPLE : { + // do a simple alignment without rotation + std::vector displacement( derivatives.size() ); + ret=simpleAlignment(align,displace,positions,reference,derivatives,displacement,squared); + break; + } case OPTIMAL_FAST : { + // this is calling the fastest option: + if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + break; + + } case OPTIMAL : { + // this is the fast routine but in the "safe" mode, which gives less numerical error: + if(align==displace) ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + else ret=optimalAlignment(align,displace,positions,reference,derivatives,squared); + break; + } + } return ret; @@ -174,116 +174,116 @@ double RMSD::calculate(const std::vector & positions,std::vector /// convenience method for calculating the standard derivatives and the derivative of the rmsd respect to the reference position -double RMSD::calc_DDistDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef , const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef, squared); - else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); - else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - } +double RMSD::calc_DDistDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef, squared); + else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); + else ret=optimalAlignment_DDistDRef(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + } return ret; } /// convenience method for calculating the standard derivatives and the derivative of the rmsd respect to the reference position without the matrix contribution /// as required by SOMA -double RMSD::calc_SOMA( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef , const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef, squared); - else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); - else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); - break; - } +double RMSD::calc_SOMA( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef, squared); + else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); + else ret=optimalAlignment_SOMA(align,displace,positions,reference,derivatives,DDistDRef,squared); + break; + } return ret; } -double RMSD::calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); - break; - } +double RMSD::calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, squared); + break; + } return ret; } -double RMSD::calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, Matrix > &DRotDRef, const bool squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); - break; - } +double RMSD::calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &derivatives, std::vector& DDistDRef, Tensor & Rot, Matrix > &DRotDPos, Matrix > &DRotDRef, const bool squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + else ret=optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(align,displace,positions,reference,derivatives,DDistDRef, Rot, DRotDPos, DRotDRef, squared); + break; + } return ret; } double RMSD::calc_PCAelements( const std::vector& positions, std::vector &DDistDPos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & alignedpositions, std::vector & centeredpositions, std::vector ¢eredreference, const bool& squared ) const { - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - break; - case OPTIMAL: - if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); - break; - } + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + break; + case OPTIMAL: + if(align==displace) ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + else ret=optimalAlignment_PCA(align,displace,positions,reference, alignedpositions, centeredpositions,centeredreference,Rotation,DDistDPos,DRotDPos,squared); + break; + } return ret; } -double RMSD::calc_FitElements( const std::vector& positions, Tensor & Rotation, Matrix > & DRotDPos, std::vector & centeredpositions, Vector ¢er_positions, const bool& squared ){ - double ret=0.; - switch(alignmentMethod){ - case SIMPLE: - plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); - break; - case OPTIMAL_FAST: - if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); - else ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); - break; - case OPTIMAL: - if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); - else ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); - break; - } +double RMSD::calc_FitElements( const std::vector& positions, Tensor & Rotation, Matrix > & DRotDPos, std::vector & centeredpositions, Vector ¢er_positions, const bool& squared ) { + double ret=0.; + switch(alignmentMethod) { + case SIMPLE: + plumed_merror("derivative of the refreence frame not implemented for SIMPLE alignmentMethod \n"); + break; + case OPTIMAL_FAST: + if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); + else ret=optimalAlignment_Fit(align,displace,positions,reference, Rotation,DRotDPos,centeredpositions,center_positions,squared); + break; + case OPTIMAL: + if(align==displace)ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); + else ret=optimalAlignment_Fit(align,displace,positions,reference,Rotation,DRotDPos,centeredpositions,center_positions,squared); + break; + } return ret; } @@ -293,58 +293,58 @@ double RMSD::calc_FitElements( const std::vector& positions, Tensor & Ro double RMSD::simpleAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & displacement, - bool squared)const{ - - double dist(0); - unsigned n=reference.size(); - - Vector apositions; - Vector areference; - Vector dpositions; - Vector dreference; - - for(unsigned i=0;i & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & displacement, + bool squared)const { - Vector shift=((apositions-areference)-(dpositions-dreference)); - for(unsigned i=0;i double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const{ + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const { double dist(0); const unsigned n=reference.size(); // This is the trace of positions*positions + reference*reference @@ -358,13 +358,13 @@ double RMSD::optimalAlignment(const std::vector & align, Vector cpositions; // first expensive loop: compute centers - for(unsigned iat=0;iat & align, m[3][2] = m[2][3]; Tensor dm_drr01[4][4]; - if(!alEqDis){ + if(!alEqDis) { dm_drr01[0][0] = 2.0*Tensor(-1.0, 0.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0,-1.0); dm_drr01[1][1] = 2.0*Tensor(-1.0, 0.0, 0.0, 0.0,+1.0, 0.0, 0.0, 0.0,+1.0); dm_drr01[2][2] = 2.0*Tensor(+1.0, 0.0, 0.0, 0.0,-1.0, 0.0, 0.0, 0.0,+1.0); @@ -413,7 +413,7 @@ double RMSD::optimalAlignment(const std::vector & align, Matrix eigenvecs; int diagerror=diagMat(m, eigenvals, eigenvecs ); - if (diagerror!=0){ + if (diagerror!=0) { string sdiagerror; Tools::convert(diagerror,sdiagerror); string msg="DIAGONALIZATION FAILED WITH ERROR CODE "+sdiagerror; @@ -427,20 +427,20 @@ double RMSD::optimalAlignment(const std::vector & align, Vector4d q(eigenvecs[0][0],eigenvecs[0][1],eigenvecs[0][2],eigenvecs[0][3]); Tensor dq_drr01[4]; - if(!alEqDis){ + if(!alEqDis) { double dq_dm[4][4][4]; - for(unsigned i=0;i<4;i++) for(unsigned j=0;j<4;j++) for(unsigned k=0;k<4;k++){ - double tmp=0.0; + for(unsigned i=0; i<4; i++) for(unsigned j=0; j<4; j++) for(unsigned k=0; k<4; k++) { + double tmp=0.0; // perturbation theory for matrix m - for(unsigned l=1;l<4;l++) tmp+=eigenvecs[l][j]*eigenvecs[l][i]/(eigenvals[0]-eigenvals[l])*eigenvecs[0][k]; - dq_dm[i][j][k]=tmp; - } + for(unsigned l=1; l<4; l++) tmp+=eigenvecs[l][j]*eigenvecs[l][i]/(eigenvals[0]-eigenvals[l])*eigenvecs[0][k]; + dq_dm[i][j][k]=tmp; + } // propagation to _drr01 - for(unsigned i=0;i<4;i++){ + for(unsigned i=0; i<4; i++) { Tensor tmp; - for(unsigned j=0;j<4;j++) for(unsigned k=0;k<4;k++) { - tmp+=dq_dm[i][j][k]*dm_drr01[j][k]; - } + for(unsigned j=0; j<4; j++) for(unsigned k=0; k<4; k++) { + tmp+=dq_dm[i][j][k]*dm_drr01[j][k]; + } dq_drr01[i]=tmp; } } @@ -459,9 +459,9 @@ double RMSD::optimalAlignment(const std::vector & align, rotation[2][0]=2*(+q[0]*q[2]+q[1]*q[3]); rotation[2][1]=2*(-q[0]*q[1]+q[2]*q[3]); - + Tensor drotation_drr01[3][3]; - if(!alEqDis){ + if(!alEqDis) { drotation_drr01[0][0]=2*q[0]*dq_drr01[0]+2*q[1]*dq_drr01[1]-2*q[2]*dq_drr01[2]-2*q[3]*dq_drr01[3]; drotation_drr01[1][1]=2*q[0]*dq_drr01[0]-2*q[1]*dq_drr01[1]+2*q[2]*dq_drr01[2]-2*q[3]*dq_drr01[3]; drotation_drr01[2][2]=2*q[0]*dq_drr01[0]-2*q[1]*dq_drr01[1]-2*q[2]*dq_drr01[2]+2*q[3]*dq_drr01[3]; @@ -488,13 +488,13 @@ double RMSD::optimalAlignment(const std::vector & align, Vector ddist_dcpositions; // third expensive loop: derivatives - for(unsigned iat=0;iat & align, } } - if(!alEqDis){ + if(!alEqDis) { Tensor ddist_drr01; - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) ddist_drr01+=ddist_drotation[i][j]*drotation_drr01[i][j]; - for(unsigned iat=0;iat double RMSD::optimalAlignment(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, + const std::vector & reference, + std::vector & derivatives, bool squared) const { - //std::cerr<<"setting up the core data \n"; - RMSDCoreData cd(align,displace,positions,reference); - - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - return dist; + //std::cerr<<"setting up the core data \n"; + RMSDCoreData cd(align,displace,positions,reference); + + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + return dist; } #endif template double RMSD::optimalAlignment_DDistDRef(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReference(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReference(); + return dist; } template double RMSD::optimalAlignment_SOMA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReferenceSOMA(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReferenceSOMA(); + return dist; } template double RMSD::optimalAlignment_DDistDRef_Rot_DRotDPos(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - Tensor & Rotation, - Matrix > &DRotDPos, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReference(); - // get the rotation matrix - Rotation=cd.getRotationMatrixReferenceToPositions(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + Tensor & Rotation, + Matrix > &DRotDPos, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReference(); + // get the rotation matrix + Rotation=cd.getRotationMatrixReferenceToPositions(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(); + return dist; } template double RMSD::optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & ddistdref, - Tensor & Rotation, - Matrix > &DRotDPos, - Matrix > &DRotDRef, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); -// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - derivatives=cd.getDDistanceDPositions(); - ddistdref=cd.getDDistanceDReference(); - // get the rotation matrix - Rotation=cd.getRotationMatrixReferenceToPositions(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(); - DRotDRef=cd.getDRotationDReference(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & ddistdref, + Tensor & Rotation, + Matrix > &DRotDPos, + Matrix > &DRotDRef, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); +// make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + derivatives=cd.getDDistanceDPositions(); + ddistdref=cd.getDDistanceDReference(); + // get the rotation matrix + Rotation=cd.getRotationMatrixReferenceToPositions(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(); + DRotDRef=cd.getDRotationDReference(); + return dist; } template double RMSD::optimalAlignment_PCA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - std::vector & alignedpositions, - std::vector & centeredpositions, - std::vector & centeredreference, - Tensor & Rotation, - std::vector & DDistDPos, - Matrix > & DRotDPos, - bool squared) const { - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); - // make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) - DDistDPos=cd.getDDistanceDPositions(); - // get the rotation matrix - Rotation=cd.getRotationMatrixPositionsToReference(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse - // get aligned positions - alignedpositions=cd.getAlignedPositionsToReference(); - // get centered positions - centeredpositions=cd.getCenteredPositions(); - // get centered reference - centeredreference=cd.getCenteredReference(); - return dist; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & alignedpositions, + std::vector & centeredpositions, + std::vector & centeredreference, + Tensor & Rotation, + std::vector & DDistDPos, + Matrix > & DRotDPos, + bool squared) const { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); + // make the derivatives by using pieces calculated in coreCalc (probably the best is just to copy the vector...) + DDistDPos=cd.getDDistanceDPositions(); + // get the rotation matrix + Rotation=cd.getRotationMatrixPositionsToReference(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse + // get aligned positions + alignedpositions=cd.getAlignedPositionsToReference(); + // get centered positions + centeredpositions=cd.getCenteredPositions(); + // get centered reference + centeredreference=cd.getCenteredReference(); + return dist; } template double RMSD::optimalAlignment_Fit(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - Tensor & Rotation, - Matrix > & DRotDPos, - std::vector & centeredpositions, - Vector & center_positions, - bool squared){ - //initialize the data into the structure - // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business - RMSDCoreData cd(align,displace,positions,reference); - // transfer the settings for the center to let the CoreCalc deal with it - cd.setPositionsCenterIsRemoved(positions_center_is_removed); - if(positions_center_is_calculated){cd.setPositionsCenter(positions_center);} - else{cd.calcPositionsCenter();}; - - cd.setReferenceCenterIsRemoved(reference_center_is_removed); - if(!reference_center_is_calculated){cd.calcReferenceCenter();} - else{cd.setReferenceCenter(reference_center);} - - // Perform the diagonalization and all the needed stuff - cd.doCoreCalc(safe,alEqDis); - // make the core calc distance - double dist=cd.getDistance(squared); - // get the rotation matrix - Rotation=cd.getRotationMatrixPositionsToReference(); - // get its derivative - DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse - // get centered positions - centeredpositions=cd.getCenteredPositions(); + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + Tensor & Rotation, + Matrix > & DRotDPos, + std::vector & centeredpositions, + Vector & center_positions, + bool squared) { + //initialize the data into the structure + // typically the positions do not have the com neither calculated nor subtracted. This layer takes care of this business + RMSDCoreData cd(align,displace,positions,reference); + // transfer the settings for the center to let the CoreCalc deal with it + cd.setPositionsCenterIsRemoved(positions_center_is_removed); + if(positions_center_is_calculated) {cd.setPositionsCenter(positions_center);} + else {cd.calcPositionsCenter();}; + + cd.setReferenceCenterIsRemoved(reference_center_is_removed); + if(!reference_center_is_calculated) {cd.calcReferenceCenter();} + else {cd.setReferenceCenter(reference_center);} + + // Perform the diagonalization and all the needed stuff + cd.doCoreCalc(safe,alEqDis); + // make the core calc distance + double dist=cd.getDistance(squared); + // get the rotation matrix + Rotation=cd.getRotationMatrixPositionsToReference(); + // get its derivative + DRotDPos=cd.getDRotationDPositions(true); // this gives back the inverse + // get centered positions + centeredpositions=cd.getCenteredPositions(); // get center - center_positions=cd.getPositionsCenter(); - return dist; + center_positions=cd.getPositionsCenter(); + return dist; } @@ -786,27 +786,27 @@ double RMSD::optimalAlignment_Fit(const std::vector & align, /// This calculates the elements needed by the quaternion to calculate everything that is needed /// additional calls retrieve different components -/// note that this considers that the centers of both reference and positions are already setted -/// but automatically should properly account for non removed components: if not removed then it -/// removes prior to calculation of the alignment -void RMSDCoreData::doCoreCalc(bool safe,bool alEqDis, bool only_rotation){ +/// note that this considers that the centers of both reference and positions are already setted +/// but automatically should properly account for non removed components: if not removed then it +/// removes prior to calculation of the alignment +void RMSDCoreData::doCoreCalc(bool safe,bool alEqDis, bool only_rotation) { retrieve_only_rotation=only_rotation; const unsigned n=static_cast(reference.size()); - - plumed_massert(creference_is_calculated,"the center of the reference frame must be already provided at this stage"); - plumed_massert(cpositions_is_calculated,"the center of the positions frame must be already provided at this stage"); + + plumed_massert(creference_is_calculated,"the center of the reference frame must be already provided at this stage"); + plumed_massert(cpositions_is_calculated,"the center of the positions frame must be already provided at this stage"); // This is the trace of positions*positions + reference*reference rr00=0.; rr11=0.; // This is positions*reference Tensor rr01; -// center of mass managing: must subtract the center from the position or not? +// center of mass managing: must subtract the center from the position or not? Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; // second expensive loop: compute second moments wrt centers - for(unsigned iat=0;iatalEqDis=alEqDis; - this->safe=safe; + this->alEqDis=alEqDis; + this->safe=safe; isInitialized=true; } /// just retrieve the distance already calculated -double RMSDCoreData::getDistance( bool squared){ +double RMSDCoreData::getDistance( bool squared) { if(!isInitialized)plumed_merror("getDistance cannot calculate the distance without being initialized first by doCoreCalc "); dist=eigenvals[0]+rr00+rr11; - + if(safe || !alEqDis) dist=0.0; const unsigned n=static_cast(reference.size()); - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDPositions(){ +std::vector RMSDCoreData::getDDistanceDPositions() { std::vector derivatives; const unsigned n=static_cast(reference.size()); Vector ddist_dcpositions; @@ -972,8 +972,8 @@ std::vector RMSDCoreData::getDDistanceDPositions(){ if(!isInitialized)plumed_merror("getDPositionsDerivatives needs to initialize the coreData first!"); Vector csum; Vector tmp1,tmp2; - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDPositions(){ // derivative of cpositions ddist_dcpositions+=-tmp1; // these needed for com corrections - tmp2=matmul(ddist_drr01,reference[iat]-creference)*align[iat]; - derivatives[iat]+=tmp2; + tmp2=matmul(ddist_drr01,reference[iat]-creference)*align[iat]; + derivatives[iat]+=tmp2; csum+=tmp2; } } - if(!alEqDis) for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReference(){ +std::vector RMSDCoreData::getDDistanceDReference() { std::vector derivatives; const unsigned n=static_cast(reference.size()); Vector ddist_dcreference; @@ -1009,14 +1009,14 @@ std::vector RMSDCoreData::getDDistanceDReference(){ if(!isInitialized)plumed_merror("getDDistanceDReference to initialize the coreData first!"); // get the transpose rotation Tensor t_rotation=rotation.transpose(); - Tensor t_ddist_drr01=ddist_drr01.transpose(); - + Tensor t_ddist_drr01=ddist_drr01.transpose(); + // third expensive loop: derivatives - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReference(){ ddist_dcreference+=tmp1; // these below are needed for com correction tmp2=matmul(t_ddist_drr01,positions[iat]-cpositions)*align[iat]; - derivatives[iat]+=tmp2; - csum+=tmp2; + derivatives[iat]+=tmp2; + csum+=tmp2; } } - if(!alEqDis) for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReferenceSOMA(){ +std::vector RMSDCoreData::getDDistanceDReferenceSOMA() { std::vector derivatives; const unsigned n=static_cast(reference.size()); Vector ddist_dcreference; @@ -1051,13 +1051,13 @@ std::vector RMSDCoreData::getDDistanceDReferenceSOMA(){ if(!isInitialized)plumed_merror("getDDistanceDReference to initialize the coreData first!"); // get the transpose rotation Tensor t_rotation=rotation.transpose(); - + // third expensive loop: derivatives - for(unsigned iat=0;iat RMSDCoreData::getDDistanceDReferenceSOMA(){ } } - if(!alEqDis) for(unsigned iat=0;iat > RMSDCoreData::getDRotationDPositions( bool inverseTransform ){ +Matrix > RMSDCoreData::getDRotationDPositions( bool inverseTransform ) { const unsigned n=static_cast(reference.size()); plumed_massert(!retrieve_only_rotation,"You used only_rotation=true in doCoreCalc therefore you cannot retrieve this information now"); if(!isInitialized)plumed_merror("getDRotationDPosition to initialize the coreData first!"); - Matrix > DRotDPos=Matrix >(3,3); + Matrix > DRotDPos=Matrix >(3,3); // remember drotation_drr01 is Tensor drotation_drr01[3][3] - // (3x3 rot) (3x3 components of rr01) + // (3x3 rot) (3x3 components of rr01) std::vector v(n); Vector csum; // these below could probably be calculated in the main routine Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; - for(unsigned iat=0;iat > RMSDCoreData::getDRotationDReference( bool inverseTransform ){ +Matrix > RMSDCoreData::getDRotationDReference( bool inverseTransform ) { const unsigned n=static_cast(reference.size()); plumed_massert(!retrieve_only_rotation,"You used only_rotation=true in doCoreCalc therefore you cannot retrieve this information now"); if(!isInitialized)plumed_merror("getDRotationDPositions to initialize the coreData first!"); - Matrix > DRotDRef=Matrix >(3,3); + Matrix > DRotDRef=Matrix >(3,3); // remember drotation_drr01 is Tensor drotation_drr01[3][3] - // (3x3 rot) (3x3 components of rr01) + // (3x3 rot) (3x3 components of rr01) std::vector v(n); Vector csum; // these below could probably be calculated in the main routine Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; - for(unsigned iat=0;iat RMSDCoreData::getAlignedReferenceToPositions(){ - std::vector alignedref; - const unsigned n=static_cast(reference.size()); - alignedref.resize(n); - if(!isInitialized)plumed_merror("getAlignedReferenceToPostions needs to initialize the coreData first!"); - // avoid to calculate matrix element but use the sum of what you have - Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; - for(unsigned iat=0;iat RMSDCoreData::getAlignedReferenceToPositions() { + std::vector alignedref; + const unsigned n=static_cast(reference.size()); + alignedref.resize(n); + if(!isInitialized)plumed_merror("getAlignedReferenceToPostions needs to initialize the coreData first!"); + // avoid to calculate matrix element but use the sum of what you have + Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; + for(unsigned iat=0; iat RMSDCoreData::getAlignedPositionsToReference(){ - std::vector alignedpos; - if(!isInitialized)plumed_merror("getAlignedPostionsToReference needs to initialize the coreData first!"); - const unsigned n=static_cast(positions.size()); - alignedpos.resize(n); - Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; - // avoid to calculate matrix element but use the sum of what you have - for(unsigned iat=0;iat RMSDCoreData::getAlignedPositionsToReference() { + std::vector alignedpos; + if(!isInitialized)plumed_merror("getAlignedPostionsToReference needs to initialize the coreData first!"); + const unsigned n=static_cast(positions.size()); + alignedpos.resize(n); + Vector cp; cp.zero(); if(!cpositions_is_removed)cp=cpositions; + // avoid to calculate matrix element but use the sum of what you have + for(unsigned iat=0; iat RMSDCoreData::getCenteredPositions(){ - std::vector centeredpos; - const unsigned n=static_cast(reference.size()); - centeredpos.resize(n); - if(!isInitialized)plumed_merror("getCenteredPositions needs to initialize the coreData first!"); - // avoid to calculate matrix element but use the sum of what you have - for(unsigned iat=0;iat RMSDCoreData::getCenteredPositions() { + std::vector centeredpos; + const unsigned n=static_cast(reference.size()); + centeredpos.resize(n); + if(!isInitialized)plumed_merror("getCenteredPositions needs to initialize the coreData first!"); + // avoid to calculate matrix element but use the sum of what you have + for(unsigned iat=0; iat RMSDCoreData::getCenteredReference(){ - std::vector centeredref; - const unsigned n=static_cast(reference.size()); - centeredref.resize(n); - if(!isInitialized)plumed_merror("getCenteredReference needs to initialize the coreData first!"); - // avoid to calculate matrix element but use the sum of what you have - Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; - for(unsigned iat=0;iat RMSDCoreData::getCenteredReference() { + std::vector centeredref; + const unsigned n=static_cast(reference.size()); + centeredref.resize(n); + if(!isInitialized)plumed_merror("getCenteredReference needs to initialize the coreData first!"); + // avoid to calculate matrix element but use the sum of what you have + Vector cr; cr.zero(); if(!creference_is_removed)cr=creference; + for(unsigned iat=0; iat(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; template double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; template double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; template double RMSD::optimalAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, bool squared)const; + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, bool squared)const; diff --git a/src/tools/RMSD.h b/src/tools/RMSD.h index 8e1a8851a1..b7c80bfa4a 100644 --- a/src/tools/RMSD.h +++ b/src/tools/RMSD.h @@ -28,17 +28,17 @@ #include #include -namespace PLMD{ +namespace PLMD { class Log; class PDB; /** \ingroup TOOLBOX A class that implements RMSD calculations -This is a class that implements the various infrastructure to calculate the +This is a class that implements the various infrastructure to calculate the RMSD or MSD respect a given frame. It can be done through an optimal alignment scheme -as Kearsley or, more simply, by resetting the center of mass. -This is the class that decides this. A very simple use is +as Kearsley or, more simply, by resetting the center of mass. +This is the class that decides this. A very simple use is \verbatim #include "tools/PDB.h" #include "tools/RMSD.h" @@ -50,11 +50,11 @@ PDB pdb; pdb.read("file.pdb",true,1.0); string type; type.assign("OPTIMAL"); -// set the reference and the type +// set the reference and the type rmsd.set(pdb,type); // this calculates the rmsd and the derivatives vector derivs; -double val; +double val; val=rmsd.calculate(getPositions(),derivs,true); \endverbatim @@ -70,39 +70,39 @@ class RMSD std::vector align; // Weights for deviation std::vector displace; -// Center for reference and flag for its calculation +// Center for reference and flag for its calculation Vector reference_center; bool reference_center_is_calculated; - bool reference_center_is_removed; + bool reference_center_is_removed; // Center for running position (not used in principle but here to reflect reference/positio symmetry Vector positions_center; - bool positions_center_is_calculated; - bool positions_center_is_removed; + bool positions_center_is_calculated; + bool positions_center_is_removed; // calculates the center from the position provided - Vector calculateCenter(std::vector &p,std::vector &w){ - plumed_massert(p.size()==w.size(),"mismatch in dimension of position/align arrays while calculating the center"); - unsigned n; n=p.size(); - Vector c; c.zero(); - for(unsigned i=0;i &p,std::vector &w) { + plumed_massert(p.size()==w.size(),"mismatch in dimension of position/align arrays while calculating the center"); + unsigned n; n=p.size(); + Vector c; c.zero(); + for(unsigned i=0; i &p, Vector &c){ - unsigned n; n=p.size(); - for(unsigned i=0;i &p, Vector &c) { + unsigned n; n=p.size(); + for(unsigned i=0; i &p, Vector &c){Vector cc=c*-1.;removeCenter(p,cc);}; + void addCenter(std::vector &p, Vector &c) {Vector cc=c*-1.; removeCenter(p,cc);}; public: /// Constructor RMSD(); /// clear the structure void clear(); -/// set reference, align and displace from input pdb structure: evtl remove com from the initial structure and normalize the input weights from the pdb +/// set reference, align and displace from input pdb structure: evtl remove com from the initial structure and normalize the input weights from the pdb void set(const PDB&,const std::string & mytype, bool remove_center=true, bool normalize_weights=true); /// set align displace reference and type from input vectors - void set(const std::vector & align, const std::vector & displace, const std::vector & reference ,const std::string & mytype, bool remove_center=true , bool normalize_weights=true ); + void set(const std::vector & align, const std::vector & displace, const std::vector & reference,const std::string & mytype, bool remove_center=true, bool normalize_weights=true ); /// set the type of alignment we are doing void setType(const std::string & mytype); /// set reference coordinates, remove the com by using uniform weights @@ -111,215 +111,219 @@ class RMSD void setAlign(const std::vector & align, bool normalize_weights=true, bool remove_center=true); /// set align void setDisplace(const std::vector & displace, bool normalize_weights=true); -/// - std::string getMethod(); +/// + std::string getMethod(); /// workhorses double simpleAlignment(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & derivatives, - std::vector & displacement, - bool squared=false)const; -template + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & derivatives, + std::vector & displacement, + bool squared=false)const; + template double optimalAlignment(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , + const std::vector & reference, std::vector & DDistDPos, bool squared=false)const; -template -double optimalAlignment_DDistDRef(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - bool squared=false) const; + template + double optimalAlignment_DDistDRef(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + bool squared=false) const; -template -double optimalAlignment_SOMA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - bool squared=false) const; + template + double optimalAlignment_SOMA(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + bool squared=false) const; + + template + double optimalAlignment_DDistDRef_Rot_DRotDPos(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + Tensor & Rotation, + Matrix > &DRotDPos, + bool squared=false) const; -template -double optimalAlignment_DDistDRef_Rot_DRotDPos(const std::vector & align, + template + double optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const std::vector & align, + const std::vector & displace, + const std::vector & positions, + const std::vector & reference, + std::vector & DDistDPos, + std::vector & DDistDRef, + Tensor & Rotation, + Matrix > &DRotDPos, + Matrix > &DRotDRef, + bool squared=false) const; + + template + double optimalAlignment_PCA(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - Tensor & Rotation, - Matrix > &DRotDPos, - bool squared=false) const; + const std::vector & reference, + std::vector & alignedpositions, + std::vector & centeredpositions, + std::vector & centeredreference, + Tensor & Rotation, + std::vector & DDistDPos, + Matrix > & DRotDPos, + bool squared=false) const ; -template -double optimalAlignment_DDistDRef_Rot_DRotDPos_DRotDRef(const std::vector & align, + template + double optimalAlignment_Fit(const std::vector & align, const std::vector & displace, const std::vector & positions, - const std::vector & reference , - std::vector & DDistDPos, - std::vector & DDistDRef, - Tensor & Rotation, - Matrix > &DRotDPos, - Matrix > &DRotDRef, - bool squared=false) const; - -template -double optimalAlignment_PCA(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - std::vector & alignedpositions, - std::vector & centeredpositions, - std::vector & centeredreference, - Tensor & Rotation, - std::vector & DDistDPos, - Matrix > & DRotDPos, - bool squared=false) const ; - -template -double optimalAlignment_Fit(const std::vector & align, - const std::vector & displace, - const std::vector & positions, - const std::vector & reference, - Tensor & Rotation, - Matrix > & DRotDPos, - std::vector & centeredpositions, - Vector & center_positions, - bool squared=false); + const std::vector & reference, + Tensor & Rotation, + Matrix > & DRotDPos, + std::vector & centeredpositions, + Vector & center_positions, + bool squared=false); -/// Compute rmsd: note that this is an intermediate layer which is kept in order to evtl expand with more alignment types/user options to be called while keeping the workhorses separated +/// Compute rmsd: note that this is an intermediate layer which is kept in order to evtl expand with more alignment types/user options to be called while keeping the workhorses separated double calculate(const std::vector & positions,std::vector &derivatives, bool squared=false)const; /// Other convenience methods: -/// calculate the derivative of distance respect to position(DDistDPos) and reference (DDistDPos) - double calc_DDistDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , const bool squared=false ); +/// calculate the derivative of distance respect to position(DDistDPos) and reference (DDistDPos) + double calc_DDistDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, const bool squared=false ); /// calculate the derivative for SOMA (i.e. derivative respect to reference frame without the matrix derivative) - double calc_SOMA( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , const bool squared=false ); + double calc_SOMA( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, const bool squared=false ); /// - double calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , Tensor & Rotation,Matrix > &DRotDPos, const bool squared=false ); - double calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef , Tensor & Rotation,Matrix > &DRotDPos,Matrix > &DRotDRef, const bool squared=false ); - /// convenience method to retrieve all the bits and pieces for PCA - double calc_PCAelements( const std::vector& pos, std::vector &DDistDPos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & alignedpositions, std::vector & centeredpositions, std::vector ¢eredreference, const bool& squared=false) const ; - /// convenience method to retrieve all the bits and pieces needed by FitToTemplate - double calc_FitElements( const std::vector& pos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & centeredpositions ,Vector & center_positions, const bool& squared=false ); - /// static convenience method to get the matrix i,a from drotdpos (which is a bit tricky) - static Tensor getMatrixFromDRot(Matrix< std::vector > &drotdpos, const unsigned &i, const unsigned &a){ - Tensor t; - t[0][0]=drotdpos[0][0][i][a]; t[0][1]=drotdpos[0][1][i][a]; t[0][2]=drotdpos[0][2][i][a]; - t[1][0]=drotdpos[1][0][i][a]; t[1][1]=drotdpos[1][1][i][a]; t[1][2]=drotdpos[1][2][i][a]; - t[2][0]=drotdpos[2][0][i][a]; t[2][1]=drotdpos[2][1][i][a]; t[2][2]=drotdpos[2][2][i][a]; - return t; - }; + double calc_DDistDRef_Rot_DRotDPos( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, Tensor & Rotation,Matrix > &DRotDPos, const bool squared=false ); + double calc_DDistDRef_Rot_DRotDPos_DRotDRef( const std::vector& positions, std::vector &DDistDPos, std::vector& DDistDRef, Tensor & Rotation,Matrix > &DRotDPos,Matrix > &DRotDRef, const bool squared=false ); +/// convenience method to retrieve all the bits and pieces for PCA + double calc_PCAelements( const std::vector& pos, std::vector &DDistDPos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & alignedpositions, std::vector & centeredpositions, std::vector ¢eredreference, const bool& squared=false) const ; +/// convenience method to retrieve all the bits and pieces needed by FitToTemplate + double calc_FitElements( const std::vector& pos, Tensor & Rotation, Matrix > & DRotDPos,std::vector & centeredpositions,Vector & center_positions, const bool& squared=false ); +/// static convenience method to get the matrix i,a from drotdpos (which is a bit tricky) + static Tensor getMatrixFromDRot(Matrix< std::vector > &drotdpos, const unsigned &i, const unsigned &a) { + Tensor t; + t[0][0]=drotdpos[0][0][i][a]; t[0][1]=drotdpos[0][1][i][a]; t[0][2]=drotdpos[0][2][i][a]; + t[1][0]=drotdpos[1][0][i][a]; t[1][1]=drotdpos[1][1][i][a]; t[1][2]=drotdpos[1][2][i][a]; + t[2][0]=drotdpos[2][0][i][a]; t[2][1]=drotdpos[2][1][i][a]; t[2][2]=drotdpos[2][2][i][a]; + return t; + }; }; /// this is a class which is needed to share information across the various non-threadsafe routines -/// so that the public function of rmsd are threadsafe while the inner core can safely share information +/// so that the public function of rmsd are threadsafe while the inner core can safely share information class RMSDCoreData { - private: - bool alEqDis; - bool distanceIsMSD; // default is RMSD but can deliver the MSD - bool hasDistance; // distance is already calculated - bool isInitialized; - bool safe; +private: + bool alEqDis; + bool distanceIsMSD; // default is RMSD but can deliver the MSD + bool hasDistance; // distance is already calculated + bool isInitialized; + bool safe; - // this need to be copied and they are small, should not affect the performance - Vector creference; - bool creference_is_calculated; - bool creference_is_removed; - Vector cpositions; - bool cpositions_is_calculated; - bool cpositions_is_removed; - bool retrieve_only_rotation; + // this need to be copied and they are small, should not affect the performance + Vector creference; + bool creference_is_calculated; + bool creference_is_removed; + Vector cpositions; + bool cpositions_is_calculated; + bool cpositions_is_removed; + bool retrieve_only_rotation; - // use reference assignment to speed up instead of copying - const std::vector &positions; - const std::vector &reference; - const std::vector &align; - const std::vector &displace; + // use reference assignment to speed up instead of copying + const std::vector &positions; + const std::vector &reference; + const std::vector &align; + const std::vector &displace; - // the needed stuff for distance and more (one could use eigenvecs components and eigenvals for some reason) - double dist; - std::vector eigenvals; - Matrix eigenvecs; - double rr00; // sum of positions squared (needed for dist calc) - double rr11; // sum of reference squared (needed for dist calc) - Tensor rotation; // rotation derived from the eigenvector having the smallest eigenvalue - Tensor drotation_drr01[3][3]; // derivative of the rotation only available when align!=displace - Tensor ddist_drr01; - Tensor ddist_drotation; - std::vector d; // difference of components - public: - /// the constructor (note: only references are passed, therefore is rather fast) - /// note: this aligns the reference onto the positions - /// - /// this method assumes that the centers are already calculated and subtracted - RMSDCoreData(const std::vector &a ,const std::vector &d,const std::vector &p, const std::vector &r, Vector &cp, Vector &cr ): - alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), - creference(cr),creference_is_calculated(true),creference_is_removed(true), - cpositions(cp),cpositions_is_calculated(true),cpositions_is_removed(true),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0){}; + // the needed stuff for distance and more (one could use eigenvecs components and eigenvals for some reason) + double dist; + std::vector eigenvals; + Matrix eigenvecs; + double rr00; // sum of positions squared (needed for dist calc) + double rr11; // sum of reference squared (needed for dist calc) + Tensor rotation; // rotation derived from the eigenvector having the smallest eigenvalue + Tensor drotation_drr01[3][3]; // derivative of the rotation only available when align!=displace + Tensor ddist_drr01; + Tensor ddist_drotation; + std::vector d; // difference of components +public: + /// the constructor (note: only references are passed, therefore is rather fast) + /// note: this aligns the reference onto the positions + /// + /// this method assumes that the centers are already calculated and subtracted + RMSDCoreData(const std::vector &a,const std::vector &d,const std::vector &p, const std::vector &r, Vector &cp, Vector &cr ): + alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), + creference(cr),creference_is_calculated(true),creference_is_removed(true), + cpositions(cp),cpositions_is_calculated(true),cpositions_is_removed(true),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) {}; - // this constructor does not assume that the positions and reference have the center subtracted - RMSDCoreData(const std::vector &a ,const std::vector &d,const std::vector &p, const std::vector &r): - alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), - creference_is_calculated(false),creference_is_removed(false), - cpositions_is_calculated(false),cpositions_is_removed(false),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) - {cpositions.zero();creference.zero();}; + // this constructor does not assume that the positions and reference have the center subtracted + RMSDCoreData(const std::vector &a,const std::vector &d,const std::vector &p, const std::vector &r): + alEqDis(false),distanceIsMSD(false),hasDistance(false),isInitialized(false),safe(false), + creference_is_calculated(false),creference_is_removed(false), + cpositions_is_calculated(false),cpositions_is_removed(false),retrieve_only_rotation(false),positions(p),reference(r),align(a),displace(d),dist(0.0),rr00(0.0),rr11(0.0) + {cpositions.zero(); creference.zero();}; - // set the center on the fly without subtracting - void calcPositionsCenter(){plumed_massert(!cpositions_is_calculated,"the center was already calculated"); - cpositions.zero();for(unsigned i=0;i getDDistanceDPositions(); - // retrieve the derivative of the distance respect to the reference - std::vector getDDistanceDReference(); - // specific version for SOMA calculation (i.e. does not need derivative respect to rotation matrix) - std::vector getDDistanceDReferenceSOMA(); - // get aligned reference onto position - std::vector getAlignedReferenceToPositions(); - // get aligned position onto reference - std::vector getAlignedPositionsToReference(); - // get centered positions - std::vector getCenteredPositions(); - // get centered reference - std::vector getCenteredReference(); - // get center of positions - Vector getPositionsCenter(); - // get center of reference - Vector getReferenceCenter(); - // get rotation matrix (reference ->positions) - Tensor getRotationMatrixReferenceToPositions(); - // get rotation matrix (positions -> reference) - Tensor getRotationMatrixPositionsToReference(); - // get the derivative of the rotation matrix respect to positions - // note that the this transformation overlap the reference onto position - // if inverseTransform=true then aligns the positions onto reference - Matrix > getDRotationDPositions( bool inverseTransform=false ); - // get the derivative of the rotation matrix respect to reference - // note that the this transformation overlap the reference onto position - // if inverseTransform=true then aligns the positions onto reference - Matrix > getDRotationDReference(bool inverseTransform=false ); + // set the center on the fly without subtracting + void calcPositionsCenter() { + plumed_massert(!cpositions_is_calculated,"the center was already calculated"); + cpositions.zero(); for(unsigned i=0; i getDDistanceDPositions(); + // retrieve the derivative of the distance respect to the reference + std::vector getDDistanceDReference(); + // specific version for SOMA calculation (i.e. does not need derivative respect to rotation matrix) + std::vector getDDistanceDReferenceSOMA(); + // get aligned reference onto position + std::vector getAlignedReferenceToPositions(); + // get aligned position onto reference + std::vector getAlignedPositionsToReference(); + // get centered positions + std::vector getCenteredPositions(); + // get centered reference + std::vector getCenteredReference(); + // get center of positions + Vector getPositionsCenter(); + // get center of reference + Vector getReferenceCenter(); + // get rotation matrix (reference ->positions) + Tensor getRotationMatrixReferenceToPositions(); + // get rotation matrix (positions -> reference) + Tensor getRotationMatrixPositionsToReference(); + // get the derivative of the rotation matrix respect to positions + // note that the this transformation overlap the reference onto position + // if inverseTransform=true then aligns the positions onto reference + Matrix > getDRotationDPositions( bool inverseTransform=false ); + // get the derivative of the rotation matrix respect to reference + // note that the this transformation overlap the reference onto position + // if inverseTransform=true then aligns the positions onto reference + Matrix > getDRotationDReference(bool inverseTransform=false ); }; } diff --git a/src/tools/Random.cpp b/src/tools/Random.cpp index 8d5cac5d28..7d03b9da3d 100644 --- a/src/tools/Random.cpp +++ b/src/tools/Random.cpp @@ -25,7 +25,7 @@ #include #include -namespace PLMD{ +namespace PLMD { const double Random::fact=5.9604644775390625e-8; /* 1 / 2^24 */ const double Random::EPS=3.0e-16; @@ -43,92 +43,92 @@ Random::Random(const std::string & name): // static constructors. name(&name!=&noname?name:"noname") { - iy=0; - iv[0]=0; - setSeed(0); + iy=0; + iv[0]=0; + setSeed(0); } -void Random::setSeed(int idum_){ - idum=idum_; - incPrec=false; +void Random::setSeed(int idum_) { + idum=idum_; + incPrec=false; } double Random::RandU01 () { - if (incPrec) - return U01d(); - else - return U01(); + if (incPrec) + return U01d(); + else + return U01(); } double Random::U01d () { - double u; - u = U01(); - u += U01() * fact; - return (u < 1.0) ? u : (u - 1.0); + double u; + u = U01(); + u += U01() * fact; + return (u < 1.0) ? u : (u - 1.0); } -double Random::U01(){ - int j,k; - double temp; - if (idum <= 0 || !iy) { - if (-idum < 1) idum=1; - else idum = -idum; - for (j=NTAB+7;j>=0;j--) { - k=idum/IQ; - idum=IA*(idum-k*IQ)-IR*k; - if (idum < 0) idum += IM; - if (j < NTAB) iv[j] = idum; - } - iy=iv[0]; - } - k=idum/IQ; - idum=IA*(idum-k*IQ)-IR*k; - if (idum < 0) idum += IM; - j=iy/NDIV; - iy=iv[j]; - iv[j] = idum; - if ((temp=AM*iy) > RNMX) return RNMX; - else return temp; +double Random::U01() { + int j,k; + double temp; + if (idum <= 0 || !iy) { + if (-idum < 1) idum=1; + else idum = -idum; + for (j=NTAB+7; j>=0; j--) { + k=idum/IQ; + idum=IA*(idum-k*IQ)-IR*k; + if (idum < 0) idum += IM; + if (j < NTAB) iv[j] = idum; + } + iy=iv[0]; + } + k=idum/IQ; + idum=IA*(idum-k*IQ)-IR*k; + if (idum < 0) idum += IM; + j=iy/NDIV; + iy=iv[j]; + iv[j] = idum; + if ((temp=AM*iy) > RNMX) return RNMX; + else return temp; } -void Random::WriteStateFull(std::ostream & out)const{ - out<>idum>>iy; - for (int i = 0; i < NTAB; i++) in>>iv[i]; - in>>switchGaussian; - in>>saveGaussian; +void Random::ReadStateFull (std::istream & in) { + getline(in,name); + in>>idum>>iy; + for (int i = 0; i < NTAB; i++) in>>iv[i]; + in>>switchGaussian; + in>>saveGaussian; } -void Random::toString(std::string & str)const{ - std::ostringstream ostr; - ostr<>idum>>iy; - for (int i = 0; i < NTAB; i++) istr>>iv[i]; +void Random::fromString(const std::string & str) { + std::string s=str; + for(unsigned i=0; i>idum>>iy; + for (int i = 0; i < NTAB; i++) istr>>iv[i]; } // This allows to have the same stream of random numbers @@ -137,22 +137,22 @@ void Random::fromString(const std::string & str){ #pragma intel optimization_level 0 #endif -double Random::Gaussian(){ - double v1,v2,rsq; - if(switchGaussian){ - switchGaussian=false; - return saveGaussian; - } - while(true){ - v1=2.0*RandU01()-1.0; - v2=2.0*RandU01()-1.0; - rsq=v1*v1+v2*v2; - if(rsq<1.0 && rsq>0.0) break; - } - double fac=sqrt(-2.*std::log(rsq)/rsq); - saveGaussian=v1*fac; - switchGaussian=true; - return v2*fac; +double Random::Gaussian() { + double v1,v2,rsq; + if(switchGaussian) { + switchGaussian=false; + return saveGaussian; + } + while(true) { + v1=2.0*RandU01()-1.0; + v2=2.0*RandU01()-1.0; + rsq=v1*v1+v2*v2; + if(rsq<1.0 && rsq>0.0) break; + } + double fac=sqrt(-2.*std::log(rsq)/rsq); + saveGaussian=v1*fac; + switchGaussian=true; + return v2*fac; } } diff --git a/src/tools/Random.h b/src/tools/Random.h index 043b3bfe94..49e7a3b442 100644 --- a/src/tools/Random.h +++ b/src/tools/Random.h @@ -25,42 +25,42 @@ #include #include -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX -class Random{ - static const int IA=16807,IM=2147483647,IQ=127773,IR=2836,NTAB=32; - static const int NDIV=(1+(IM-1)/NTAB); - static const double EPS; - static const double AM; - static const double RNMX; - static const double fact; - static const std::string noname; - bool incPrec; - bool switchGaussian; - double saveGaussian; - int iy; - int iv[NTAB]; - int idum; - std::string name; +class Random { + static const int IA=16807,IM=2147483647,IQ=127773,IR=2836,NTAB=32; + static const int NDIV=(1+(IM-1)/NTAB); + static const double EPS; + static const double AM; + static const double RNMX; + static const double fact; + static const std::string noname; + bool incPrec; + bool switchGaussian; + double saveGaussian; + int iy; + int iv[NTAB]; + int idum; + std::string name; public: - explicit Random(const std::string & name=noname); - void setSeed(int idum); - double RandU01(); - double U01(); - double U01d(); - void WriteStateFull(std::ostream &)const; - void ReadStateFull (std::istream &); - void fromString(const std::string & str); - void toString(std::string & str)const; - friend std::ostream & operator<<(std::ostream & out,const Random & rng){ - rng.WriteStateFull(out); return out; - } - friend std::istream & operator>>(std::istream & in,Random & rng){ - rng.ReadStateFull(in); return in; - } - double Gaussian(); - void IncreasedPrecis(bool i){incPrec=i;} + explicit Random(const std::string & name=noname); + void setSeed(int idum); + double RandU01(); + double U01(); + double U01d(); + void WriteStateFull(std::ostream &)const; + void ReadStateFull (std::istream &); + void fromString(const std::string & str); + void toString(std::string & str)const; + friend std::ostream & operator<<(std::ostream & out,const Random & rng) { + rng.WriteStateFull(out); return out; + } + friend std::istream & operator>>(std::istream & in,Random & rng) { + rng.ReadStateFull(in); return in; + } + double Gaussian(); + void IncreasedPrecis(bool i) {incPrec=i;} }; } diff --git a/src/tools/RootFindingBase.h b/src/tools/RootFindingBase.h index 5f125a7c1e..b737455605 100644 --- a/src/tools/RootFindingBase.h +++ b/src/tools/RootFindingBase.h @@ -54,20 +54,20 @@ void RootFindingBase::doSearch( const std::vector& dir, std::vec double ax=0.0, xx=1.0; bb.bracket( ax, xx, &F1dim::getEng ); double xmin=bb.search( &F1dim::getEng ); - for(unsigned i=0;i void RootFindingBase::linesearch( const std::vector& dir, std::vector& p, engf_pointer myfunc ) const { - // Construct the object that turns points on a line into vectors + // Construct the object that turns points on a line into vectors F1dim f1dim( p, dir, myclass_func, myfunc, NULL ); // Actually do the search - doSearch( dir, p, f1dim ); + doSearch( dir, p, f1dim ); } template void RootFindingBase::lsearch( const std::vector& dir, std::vector& p, engfnc_pointer myfunc ) const { - // Construct the object that turns points on a line into vectors + // Construct the object that turns points on a line into vectors F1dim f1dim( p, dir, myclass_func, NULL, myfunc ); // Actually do the search doSearch( dir, p, f1dim ); diff --git a/src/tools/Stopwatch.cpp b/src/tools/Stopwatch.cpp index c0d93e0e11..4393a75449 100644 --- a/src/tools/Stopwatch.cpp +++ b/src/tools/Stopwatch.cpp @@ -30,52 +30,52 @@ using namespace std; -namespace PLMD{ +namespace PLMD { // this is needed for friend operators -std::ostream& operator<<(std::ostream&os,const Stopwatch&sw){ +std::ostream& operator<<(std::ostream&os,const Stopwatch&sw) { return sw.log(os); } -void Stopwatch::Watch::start(){ +void Stopwatch::Watch::start() { running++; lastStart=std::chrono::high_resolution_clock::now(); } -void Stopwatch::Watch::stop(){ +void Stopwatch::Watch::stop() { pause(); cycles++; total+=lap; if(lap>max)max=lap; if(min>lap || cycles==1)min=lap; lap=0; -} +} -void Stopwatch::Watch::pause(){ +void Stopwatch::Watch::pause() { plumed_assert(running>0); running--; if(running!=0) return; auto t=std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-lastStart); lap+=t.count(); -} +} -void Stopwatch::start(const std::string & name){ +void Stopwatch::start(const std::string & name) { watches[name].start(); } -void Stopwatch::stop(const std::string & name){ +void Stopwatch::stop(const std::string & name) { watches[name].stop(); } -void Stopwatch::pause(const std::string & name){ +void Stopwatch::pause(const std::string & name) { watches[name].pause(); } -std::ostream& Stopwatch::log(std::ostream&os)const{ +std::ostream& Stopwatch::log(std::ostream&os)const { char buffer[1000]; buffer[0]=0; - for(unsigned i=0;i<40;i++) os<<" "; + for(unsigned i=0; i<40; i++) os<<" "; os<<" Cycles Total Average Minumum Maximum\n"; std::vector names; @@ -84,10 +84,10 @@ std::ostream& Stopwatch::log(std::ostream&os)const{ const double frac=1.0/1000000000.0; - for(const auto & name : names){ + for(const auto & name : names) { const Watch&t(watches.find(name)->second); os< #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -96,10 +96,10 @@ int main(){ */ -class Stopwatch{ +class Stopwatch { /// Class to store a single stopwatch. /// Class Stopwatch contains a collection of them - class Watch{ + class Watch { public: std::chrono::time_point lastStart; long long int total = 0; @@ -129,17 +129,17 @@ class Stopwatch{ }; inline -void Stopwatch::start(){ +void Stopwatch::start() { start(""); } inline -void Stopwatch::stop(){ +void Stopwatch::stop() { stop(""); } inline -void Stopwatch::pause(){ +void Stopwatch::pause() { pause(""); } diff --git a/src/tools/SwitchingFunction.cpp b/src/tools/SwitchingFunction.cpp index fa685d1b0f..fcbe3bb37f 100644 --- a/src/tools/SwitchingFunction.cpp +++ b/src/tools/SwitchingFunction.cpp @@ -30,9 +30,9 @@ #endif using namespace std; -namespace PLMD{ +namespace PLMD { -//+PLUMEDOC INTERNAL switchingfunction +//+PLUMEDOC INTERNAL switchingfunction /* Functions that measure whether values are less than a certain quantity. @@ -40,24 +40,24 @@ Switching functions \f$s(r)\f$ take a minimum of one input parameter \f$d_0\f$. For \f$r \le d_0 \quad s(r)=1.0\f$ while for \f$r > d_0\f$ the function decays smoothly to 0. The various switching functions available in plumed differ in terms of how this decay is performed. -Where there is an accepted convention in the literature (e.g. \ref COORDINATION) on the form of the +Where there is an accepted convention in the literature (e.g. \ref COORDINATION) on the form of the switching function we use the convention as the default. However, the flexibility to use different -switching functions is always present generally through a single keyword. This keyword generally +switching functions is always present generally through a single keyword. This keyword generally takes an input with the following form: \verbatim KEYWORD={TYPE } -\endverbatim +\endverbatim The following table contains a list of the various switching functions that are available in plumed 2 together with an example input. - + @@ -76,9 +76,9 @@ s(r)=\exp\left(-\frac{ r - d_0 }{ r_0 }\right) s(r)=\exp\left(-\frac{ (r - d_0)^2 }{ 2r_0^2 }\right) \f$ - + - + - + - + - +
TYPE FUNCTION EXAMPLE INPUT DEFAULT PARAMETERS
RATIONAL \f$ -s(r)=\frac{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{n} }{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{m} } +s(r)=\frac{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{n} }{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{m} } \f$ {RATIONAL R_0=\f$r_0\f$ D_0=\f$d_0\f$ NN=\f$n\f$ MM=\f$m\f$} @@ -67,7 +67,7 @@ s(r)=\frac{ 1 - \left(\frac{ r - d_0 }{ r_0 }\right)^{n} }{ 1 - \left(\frac{ r - \f$ s(r)=\exp\left(-\frac{ r - d_0 }{ r_0 }\right) \f$ - + {EXP R_0=\f$r_0\f$ D_0=\f$d_0\f$} \f$d_0=0.0\f$
-{GAUSSIAN R_0=\f$r_0\f$ D_0=\f$d_0\f$} +{GAUSSIAN R_0=\f$r_0\f$ D_0=\f$d_0\f$} \f$d_0=0.0\f$
SMAP \f$ s(r) = \left[ 1 + ( 2^{a/b} -1 )\left( \frac{r-d_0}{r_0} \right)^a \right]^{-b/a} @@ -86,7 +86,7 @@ s(r) = \left[ 1 + ( 2^{a/b} -1 )\left( \frac{r-d_0}{r_0} \right)^a \right]^{-b/a {SMAP R_0=\f$r_0\f$ D_0=\f$d_0\f$ A=\f$a\f$ B=\f$b\f$} \f$d_0=0.0\f$
Q \f$ s(r) = \frac{1}{1 + \exp(\beta(r_{ij} - \lambda r_{ij}^0))} @@ -94,7 +94,7 @@ s(r) = \frac{1}{1 + \exp(\beta(r_{ij} - \lambda r_{ij}^0))} {Q REF=\f$r_{ij}^0\f$ BETA=\f$\beta\f$ LAMBDA=\f$\lambda\f$ } \f$\lambda=1.8\f$, \f$\beta=50 nm^-1\f$ (all-atom)
\f$\lambda=1.5\f$, \f$\beta=50 nm^-1\f$ (coarse-grained)
CUBIC \f$ s(r) = (y-1)^2(1+2y) \qquad \textrm{where} \quad y = \frac{r - r_1}{r_0-r_1} @@ -102,15 +102,15 @@ s(r) = (y-1)^2(1+2y) \qquad \textrm{where} \quad y = \frac{r - r_1}{r_0-r_1} {CUBIC D_0=\f$r_1\f$ D_MAX=\f$r_0\f$}
TANH \f$ -s(r) = 1 - \tanh\left( \frac{ r - d_0 }{ r_0 } \right) +s(r) = 1 - \tanh\left( \frac{ r - d_0 }{ r_0 } \right) \f$ {TANH R_0=\f$r_0\f$ D_0=\f$d_0\f$}
MATHEVAL \f$ s(r) = FUNC @@ -122,7 +122,7 @@ s(r) = FUNC
\attention -Similarly to the \ref MATHEVAL function, the MATHEVAL switching function +Similarly to the \ref MATHEVAL function, the MATHEVAL switching function only works if libmatheval is installed on the system and PLUMED has been linked to it Also notice that using MATHEVAL is much slower than using e.g. RATIONAL. @@ -131,7 +131,7 @@ tests on switching functions with arbitrary form before proceeding to their implementation in C++. For all the switching functions in the above table one can also specify a further (optional) parameter using the parameter -keyword D_MAX to assert that for \f$r>d_{\textrm{max}}\f$ the switching function can be assumed equal to zero. +keyword D_MAX to assert that for \f$r>d_{\textrm{max}}\f$ the switching function can be assumed equal to zero. In this case the function is brought smoothly to zero by stretching and shifting it. \verbatim KEYWORD={RATIONAL R_0=1 D_MAX=3} @@ -154,19 +154,19 @@ for backward compatibility. This might change in the future. */ //+ENDPLUMEDOC -void SwitchingFunction::registerKeywords( Keywords& keys ){ +void SwitchingFunction::registerKeywords( Keywords& keys ) { keys.add("compulsory","R_0","the value of R_0 in the switching function"); keys.add("compulsory","D_0","0.0","the value of D_0 in the switching function"); keys.add("optional","D_MAX","the value at which the switching function can be assumed equal to zero"); keys.add("compulsory","NN","6","the value of n in the switching function (only needed for TYPE=RATIONAL)"); keys.add("compulsory","MM","0","the value of m in the switching function (only needed for TYPE=RATIONAL); 0 implies 2*NN"); keys.add("compulsory","A","the value of a in the switching funciton (only needed for TYPE=SMAP)"); - keys.add("compulsory","B","the value of b in the switching funciton (only needed for TYPE=SMAP)"); + keys.add("compulsory","B","the value of b in the switching funciton (only needed for TYPE=SMAP)"); } -void SwitchingFunction::set(const std::string & definition,std::string& errormsg){ +void SwitchingFunction::set(const std::string & definition,std::string& errormsg) { vector data=Tools::getWords(definition); - if( data.size()<1 ) errormsg="missing all input for switching function"; + if( data.size()<1 ) errormsg="missing all input for switching function"; string name=data[0]; data.erase(data.begin()); invr0=0.0; @@ -193,16 +193,16 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg Tools::parseFlag(data,"NOSTRETCH",dontstretch); // this is ignored now if(dontstretch) dostretch=false; double r0; - if(name=="CUBIC"){ - r0 = dmax - d0; + if(name=="CUBIC") { + r0 = dmax - d0; } else { - bool found_r0=Tools::parse(data,"R_0",r0); - if(!found_r0) errormsg="R_0 is required"; + bool found_r0=Tools::parse(data,"R_0",r0); + if(!found_r0) errormsg="R_0 is required"; } invr0=1.0/r0; invr0_2=invr0*invr0; - if(name=="RATIONAL"){ + if(name=="RATIONAL") { type=rational; nn=6; mm=0; @@ -211,17 +211,17 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg present=Tools::findKeyword(data,"MM"); if(present && !Tools::parse(data,"MM",mm)) errormsg="could not parse MM"; if(mm==0) mm=2*nn; - } else if(name=="SMAP"){ + } else if(name=="SMAP") { type=smap; present=Tools::findKeyword(data,"A"); if(present && !Tools::parse(data,"A",a)) errormsg="could not parse A"; present=Tools::findKeyword(data,"B"); if(present && !Tools::parse(data,"B",b)) errormsg="could not parse B"; - c=pow(2., static_cast(a)/static_cast(b) ) - 1; + c=pow(2., static_cast(a)/static_cast(b) ) - 1; d = -static_cast(b) / static_cast(a); - } + } else if(name=="Q") { - type=nativeq; + type=nativeq; beta = 50.0; // nm-1 lambda = 1.8; // unitless present=Tools::findKeyword(data,"BETA"); @@ -237,7 +237,7 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg else if(name=="CUBIC") type=cubic; else if(name=="TANH") type=tanh; #ifdef __PLUMED_HAS_MATHEVAL - else if(name=="MATHEVAL"){ + else if(name=="MATHEVAL") { type=matheval; std::string func; Tools::parse(data,"FUNC",func); @@ -245,11 +245,11 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg char **check_names; int check_count; evaluator_get_variables(evaluator,&check_names,&check_count); - if(check_count!=1){ + if(check_count!=1) { errormsg="wrong number of arguments in MATHEVAL switching function"; return; - } - if(std::string(check_names[0])!="x"){ + } + if(std::string(check_names[0])!="x") { errormsg ="argument should be named 'x'"; return; } @@ -257,12 +257,12 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg } #endif else errormsg="cannot understand switching function type '"+name+"'"; - if( !data.empty() ){ - errormsg="found the following rogue keywords in switching function input : "; - for(unsigned i=0;i::max()){ + if(dostretch && dmax!=std::numeric_limits::max()) { double dummy; double s0=calculate(0.0,dummy); double sd=calculate(dmax,dummy); @@ -274,73 +274,73 @@ void SwitchingFunction::set(const std::string & definition,std::string& errormsg std::string SwitchingFunction::description() const { std::ostringstream ostr; ostr<<1./invr0<<". Using "; - if(type==rational){ - ostr<<"rational"; - } else if(type==exponential){ - ostr<<"exponential"; - } else if(type==nativeq){ - ostr<<"nativeq"; - } else if(type==gaussian){ - ostr<<"gaussian"; - } else if(type==smap){ - ostr<<"smap"; - } else if(type==cubic){ - ostr<<"cubic"; - } else if(type==tanh){ - ostr<<"tanh"; + if(type==rational) { + ostr<<"rational"; + } else if(type==exponential) { + ostr<<"exponential"; + } else if(type==nativeq) { + ostr<<"nativeq"; + } else if(type==gaussian) { + ostr<<"gaussian"; + } else if(type==smap) { + ostr<<"smap"; + } else if(type==cubic) { + ostr<<"cubic"; + } else if(type==tanh) { + ostr<<"tanh"; #ifdef __PLUMED_HAS_MATHEVAL - } else if(type==matheval){ - ostr<<"matheval"; + } else if(type==matheval) { + ostr<<"matheval"; #endif - } else{ - plumed_merror("Unknown switching function type"); + } else { + plumed_merror("Unknown switching function type"); } ostr<<" swiching function with parameters d0="<dmax){ + if(distance>dmax) { dfunc=0.0; return 0.0; } const double rdist = (distance-d0)*invr0; double result; - if(rdist<=0.){ - result=1.; - dfunc=0.0; - }else{ - if(type==smap){ - double sx=c*pow( rdist, a ); - result=pow( 1.0 + sx, d ); - dfunc=-b*sx/rdist*result/(1.0+sx); - } else if(type==rational){ + if(rdist<=0.) { + result=1.; + dfunc=0.0; + } else { + if(type==smap) { + double sx=c*pow( rdist, a ); + result=pow( 1.0 + sx, d ); + dfunc=-b*sx/rdist*result/(1.0+sx); + } else if(type==rational) { result=do_rational(rdist,dfunc,nn,mm); - }else if(type==exponential){ + } else if(type==exponential) { result=exp(-rdist); dfunc=-result; - }else if(type==nativeq){ + } else if(type==nativeq) { double rdist2 = beta*(distance - lambda * ref); double exprdist=exp(rdist2); result=1./(1.+exprdist); dfunc=-exprdist/(1.+exprdist)/(1.+exprdist); - }else if(type==gaussian){ + } else if(type==gaussian) { result=exp(-0.5*rdist*rdist); dfunc=-rdist*result; - }else if(type==cubic){ + } else if(type==cubic) { double tmp1=rdist-1, tmp2=(1+2*rdist); result=tmp1*tmp1*tmp2; dfunc=2*tmp1*tmp2 + 2*tmp1*tmp1; - }else if(type==tanh){ + } else if(type==tanh) { double tmp1=std::tanh(rdist); result = 1.0 - tmp1; dfunc=-(1-tmp1*tmp1); #ifdef __PLUMED_HAS_MATHEVAL - }else if(type==matheval){ + } else if(type==matheval) { result=evaluator_evaluate_x(evaluator,rdist); dfunc=evaluator_evaluate_x(evaluator_deriv,rdist); #endif - }else plumed_merror("Unknown switching function type"); + } else plumed_merror("Unknown switching function type"); // this is for the chain rule: dfunc*=invr0; // this is because calculate() sets dfunc to the derivative divided times the distance. @@ -467,7 +467,7 @@ SwitchingFunction::SwitchingFunction(const SwitchingFunction&sf): #endif } -SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf){ +SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf) { if(&sf==this) return *this; init=sf.init; type=sf.type; @@ -497,7 +497,7 @@ SwitchingFunction & SwitchingFunction::operator=(const SwitchingFunction& sf){ } -void SwitchingFunction::set(int nn,int mm,double r0,double d0){ +void SwitchingFunction::set(int nn,int mm,double r0,double d0) { init=true; type=rational; if(mm==0) mm=2*nn; @@ -526,7 +526,7 @@ double SwitchingFunction::get_dmax2() const { return dmax_2; } -SwitchingFunction::~SwitchingFunction(){ +SwitchingFunction::~SwitchingFunction() { #ifdef __PLUMED_HAS_MATHEVAL if(evaluator) evaluator_destroy(evaluator); if(evaluator_deriv) evaluator_destroy(evaluator_deriv); diff --git a/src/tools/SwitchingFunction.h b/src/tools/SwitchingFunction.h index 4bcf27926a..379280da4a 100644 --- a/src/tools/SwitchingFunction.h +++ b/src/tools/SwitchingFunction.h @@ -37,7 +37,7 @@ class Keywords; /// the second all (calculateSqr()) allows to skip the calculation /// of a square root in some case, thus potentially increasing /// performances. -class SwitchingFunction{ +class SwitchingFunction { /// This is to check that switching function has been initialized bool init; /// Type of function @@ -81,7 +81,7 @@ class SwitchingFunction{ SwitchingFunction & operator=(const SwitchingFunction&); /// Set a "rational" switching function. /// Notice that a d_max is set automatically to a value such that -/// f(d_max)=0.00001. +/// f(d_max)=0.00001. void set(int nn,int mm,double r_0,double d_0); /// Set an arbitrary switching function. /// Parse the string in definition and possibly returns errors @@ -104,7 +104,7 @@ class SwitchingFunction{ double get_d0() const; /// Returns r0 double get_r0() const; -/// Return dmax +/// Return dmax double get_dmax() const; /// Return dmax squared double get_dmax2() const; diff --git a/src/tools/Tensor.cpp b/src/tools/Tensor.cpp index ad8f2ae6d4..d063e28cf9 100644 --- a/src/tools/Tensor.cpp +++ b/src/tools/Tensor.cpp @@ -22,15 +22,15 @@ #include "Tensor.h" #include "Exception.h" -namespace PLMD{ +namespace PLMD { /// Small auxiliary class. /// I use it to test a few things that I am scary of and could introduce bugs. /// It checks at startup that Tensor satifies some requirement so as to allow /// accessing a vector of tensors as a 9 times longer array of doubles. -static class TensorChecks{ +static class TensorChecks { public: - TensorChecks(){ + TensorChecks() { if(sizeof(Tensor)==9*sizeof(double)) return; plumed_merror("sizeof(Tensor)!=9*sizeof(double). PLUMED cannot work properly in these conditions."); } diff --git a/src/tools/Tensor.h b/src/tools/Tensor.h index 8e95e21b93..7cd6515c86 100644 --- a/src/tools/Tensor.h +++ b/src/tools/Tensor.h @@ -30,7 +30,7 @@ #include "Exception.h" #endif -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -182,18 +182,18 @@ class TensorGeneric: }; template -TensorGeneric::TensorGeneric(){ +TensorGeneric::TensorGeneric() { LoopUnroller::_zero(d); } template -TensorGeneric::TensorGeneric(const VectorGeneric&v1,const VectorGeneric&v2){ - for(unsigned i=0;i::TensorGeneric(const VectorGeneric&v1,const VectorGeneric&v2) { + for(unsigned i=0; i inline -TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11){ +TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11) { d[0]=d00; d[1]=d01; d[2]=d10; @@ -202,7 +202,7 @@ TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11){ template<> inline -TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,double d11,double d12,double d20,double d21,double d22){ +TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,double d11,double d12,double d20,double d21,double d22) { d[0]=d00; d[1]=d01; d[2]=d02; @@ -215,12 +215,12 @@ TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,do } template -void TensorGeneric::zero(){ +void TensorGeneric::zero() { LoopUnroller::_zero(d); } template -double & TensorGeneric::operator() (unsigned i,unsigned j){ +double & TensorGeneric::operator() (unsigned i,unsigned j) { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator() (unsigned i,unsigned j){ } template -const double & TensorGeneric::operator() (unsigned i,unsigned j)const{ +const double & TensorGeneric::operator() (unsigned i,unsigned j)const { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator() (unsigned i,unsigned j)const{ } template -TensorGeneric& TensorGeneric::operator +=(const TensorGeneric& b){ +TensorGeneric& TensorGeneric::operator +=(const TensorGeneric& b) { LoopUnroller::_add(d,b.d); return *this; } template -TensorGeneric& TensorGeneric::operator -=(const TensorGeneric& b){ +TensorGeneric& TensorGeneric::operator -=(const TensorGeneric& b) { LoopUnroller::_sub(d,b.d); return *this; } template -TensorGeneric& TensorGeneric::operator *=(double s){ +TensorGeneric& TensorGeneric::operator *=(double s) { LoopUnroller::_mul(d,s); return *this; } template -TensorGeneric& TensorGeneric::operator /=(double s){ +TensorGeneric& TensorGeneric::operator /=(double s) { LoopUnroller::_mul(d,1.0/s); return *this; } template -TensorGeneric TensorGeneric::operator+()const{ +TensorGeneric TensorGeneric::operator+()const { return *this; } template -TensorGeneric TensorGeneric::operator-()const{ +TensorGeneric TensorGeneric::operator-()const { TensorGeneric r; LoopUnroller::_neg(r.d,d); return r; } template -TensorGeneric& TensorGeneric::setCol(unsigned j,const VectorGeneric & c){ - for(unsigned i=0;i& TensorGeneric::setCol(unsigned j,const VectorGeneric & c) { + for(unsigned i=0; i -TensorGeneric& TensorGeneric::setRow(unsigned i,const VectorGeneric & r){ - for(unsigned j=0;j& TensorGeneric::setRow(unsigned i,const VectorGeneric & r) { + for(unsigned j=0; j -VectorGeneric TensorGeneric::getCol(unsigned j)const{ +VectorGeneric TensorGeneric::getCol(unsigned j)const { VectorGeneric v; - for(unsigned i=0;i -VectorGeneric TensorGeneric::getRow(unsigned i)const{ +VectorGeneric TensorGeneric::getRow(unsigned i)const { VectorGeneric v; - for(unsigned j=0;j -TensorGeneric operator+(const TensorGeneric&t1,const TensorGeneric&t2){ +TensorGeneric operator+(const TensorGeneric&t1,const TensorGeneric&t2) { TensorGeneric t(t1); t+=t2; return t; } template -TensorGeneric operator-(const TensorGeneric&t1,const TensorGeneric&t2){ +TensorGeneric operator-(const TensorGeneric&t1,const TensorGeneric&t2) { TensorGeneric t(t1); t-=t2; return t; } template -TensorGeneric operator*(const TensorGeneric&t1,double s){ +TensorGeneric operator*(const TensorGeneric&t1,double s) { TensorGeneric t(t1); t*=s; return t; } template -TensorGeneric operator*(double s,const TensorGeneric&t1){ +TensorGeneric operator*(double s,const TensorGeneric&t1) { return t1*s; } template -TensorGeneric operator/(const TensorGeneric&t1,double s){ +TensorGeneric operator/(const TensorGeneric&t1,double s) { return t1*(1.0/s); } template<> inline -double TensorGeneric<3,3>::determinant()const{ +double TensorGeneric<3,3>::determinant()const { return - d[0]*d[4]*d[8] - + d[1]*d[5]*d[6] - + d[2]*d[3]*d[7] - - d[0]*d[5]*d[7] - - d[1]*d[3]*d[8] - - d[2]*d[4]*d[6]; + d[0]*d[4]*d[8] + + d[1]*d[5]*d[6] + + d[2]*d[3]*d[7] + - d[0]*d[5]*d[7] + - d[1]*d[3]*d[8] + - d[2]*d[4]*d[6]; } template inline -TensorGeneric TensorGeneric::identity(){ +TensorGeneric TensorGeneric::identity() { TensorGeneric t; - for(unsigned i=0;i -TensorGeneric TensorGeneric::transpose()const{ +TensorGeneric TensorGeneric::transpose()const { TensorGeneric t; - for(unsigned i=0;i inline -TensorGeneric<3,3> TensorGeneric<3,3>::inverse()const{ +TensorGeneric<3,3> TensorGeneric<3,3>::inverse()const { TensorGeneric t; double invdet=1.0/determinant(); - for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++) - t(j,i)=invdet*( (*this)((i+1)%3,(j+1)%3)*(*this)((i+2)%3,(j+2)%3) - -(*this)((i+1)%3,(j+2)%3)*(*this)((i+2)%3,(j+1)%3)); + for(unsigned i=0; i<3; i++) for(unsigned j=0; j<3; j++) + t(j,i)=invdet*( (*this)((i+1)%3,(j+1)%3)*(*this)((i+2)%3,(j+2)%3) + -(*this)((i+1)%3,(j+2)%3)*(*this)((i+2)%3,(j+1)%3)); return t; } template -TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b){ +TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b) { TensorGeneric t; - for(unsigned i=0;i -VectorGeneric matmul(const TensorGeneric&a,const VectorGeneric&b){ +VectorGeneric matmul(const TensorGeneric&a,const VectorGeneric&b) { VectorGeneric t; - for(unsigned i=0;i -VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b){ +VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b) { VectorGeneric t; - for(unsigned i=0;i -double matmul(const VectorGeneric&a,const VectorGeneric&b){ +double matmul(const VectorGeneric&a,const VectorGeneric&b) { return dotProduct(a,b); } template -TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const TensorGeneric&c){ +TensorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const TensorGeneric&c) { return matmul(matmul(a,b),c); } template -VectorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const VectorGeneric&c){ +VectorGeneric matmul(const TensorGeneric&a,const TensorGeneric&b,const VectorGeneric&c) { return matmul(matmul(a,b),c); } -template -VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b,const TensorGeneric&c){ +template +VectorGeneric matmul(const VectorGeneric&a,const TensorGeneric&b,const TensorGeneric&c) { return matmul(matmul(a,b),c); } template -double matmul(const VectorGeneric&a,const TensorGeneric&b,const VectorGeneric&c){ +double matmul(const VectorGeneric&a,const TensorGeneric&b,const VectorGeneric&c) { return matmul(matmul(a,b),c); } inline -double determinant(const TensorGeneric<3,3>&t){ +double determinant(const TensorGeneric<3,3>&t) { return t.determinant(); } inline -TensorGeneric<3,3> inverse(const TensorGeneric<3,3>&t){ +TensorGeneric<3,3> inverse(const TensorGeneric<3,3>&t) { return t.inverse(); } template -TensorGeneric transpose(const TensorGeneric&t){ +TensorGeneric transpose(const TensorGeneric&t) { return t.transpose(); } template -TensorGeneric extProduct(const VectorGeneric&v1,const VectorGeneric&v2){ +TensorGeneric extProduct(const VectorGeneric&v1,const VectorGeneric&v2) { return TensorGeneric(v1,v2); } inline -TensorGeneric<3,3> dcrossDv1(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2){ +TensorGeneric<3,3> dcrossDv1(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2) { (void) v1; // this is to avoid warnings. still the syntax of this function is a bit dummy... return TensorGeneric<3,3>( - 0.0, v2[2],-v2[1], - -v2[2], 0.0, v2[0], - v2[1],-v2[0], 0.0); + 0.0, v2[2],-v2[1], + -v2[2], 0.0, v2[0], + v2[1],-v2[0], 0.0); } inline -TensorGeneric<3,3> dcrossDv2(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2){ +TensorGeneric<3,3> dcrossDv2(const VectorGeneric<3>&v1,const VectorGeneric<3>&v2) { (void) v2; // this is to avoid warnings. still the syntax of this function is a bit dummy... return TensorGeneric<3,3>( - 0.0,-v1[2],v1[1], - v1[2],0.0,-v1[0], - -v1[1],v1[0],0.0); + 0.0,-v1[2],v1[1], + v1[2],0.0,-v1[0], + -v1[1],v1[0],0.0); } template -std::ostream & operator<<(std::ostream &os, const TensorGeneric& t){ - for(unsigned i=0;i& t) { + for(unsigned i=0; i Tensor4d; typedef Tensor3d Tensor; inline -TensorGeneric<3,3> VcrossTensor(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2){ +TensorGeneric<3,3> VcrossTensor(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2) { - TensorGeneric<3,3> t; - for(unsigned i=0;i<3;i++){ - t.setRow(i,matmul(dcrossDv2(v1,v1),v2.getRow(i))); - } - return t; + TensorGeneric<3,3> t; + for(unsigned i=0; i<3; i++) { + t.setRow(i,matmul(dcrossDv2(v1,v1),v2.getRow(i))); + } + return t; } inline -TensorGeneric<3,3> VcrossTensor(const TensorGeneric<3,3>&v2,const VectorGeneric<3>&v1){ - TensorGeneric<3,3> t; - for(unsigned i=0;i<3;i++){ - t.setRow(i,-matmul(dcrossDv2(v1,v1),v2.getRow(i))); - } - return t; +TensorGeneric<3,3> VcrossTensor(const TensorGeneric<3,3>&v2,const VectorGeneric<3>&v1) { + TensorGeneric<3,3> t; + for(unsigned i=0; i<3; i++) { + t.setRow(i,-matmul(dcrossDv2(v1,v1),v2.getRow(i))); + } + return t; } inline -TensorGeneric<3,3> deriNorm(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2){ +TensorGeneric<3,3> deriNorm(const VectorGeneric<3>&v1,const TensorGeneric<3,3>&v2) { // delta(v) = delta(v1/v1.norm) = 1/v1.norm*(delta(v1) - (v.delta(v1))cross v; double over_norm = 1./v1.modulo(); return over_norm*(v2 - over_norm*over_norm*(extProduct(matmul(v2,v1),v1))); } - + diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp index 02256a1f11..f5af5a9036 100644 --- a/src/tools/Tools.cpp +++ b/src/tools/Tools.cpp @@ -28,31 +28,31 @@ #include using namespace std; -namespace PLMD{ +namespace PLMD { template -bool Tools::convertToAny(const string & str,T & t){ - istringstream istr(str.c_str()); - bool ok=static_cast(istr>>t); - if(!ok) return false; - string remaining; - istr>>remaining; - return remaining.length()==0; +bool Tools::convertToAny(const string & str,T & t) { + istringstream istr(str.c_str()); + bool ok=static_cast(istr>>t); + if(!ok) return false; + string remaining; + istr>>remaining; + return remaining.length()==0; } -bool Tools::convert(const string & str,int & t){ - return convertToAny(str,t); +bool Tools::convert(const string & str,int & t) { + return convertToAny(str,t); } -bool Tools::convert(const string & str,long int & t){ - return convertToAny(str,t); +bool Tools::convert(const string & str,long int & t) { + return convertToAny(str,t); } -bool Tools::convert(const string & str,unsigned & t){ - return convertToAny(str,t); +bool Tools::convert(const string & str,unsigned & t) { + return convertToAny(str,t); } -bool Tools::convert(const string & str,AtomNumber &a){ +bool Tools::convert(const string & str,AtomNumber &a) { unsigned i; bool r=convert(str,i); if(r) a.setSerial(i); @@ -60,57 +60,57 @@ bool Tools::convert(const string & str,AtomNumber &a){ } template -bool Tools::convertToReal(const string & str,T & t){ - if(str=="PI" || str=="+PI" || str=="+pi" || str=="pi"){ - t=pi; return true; - } else if(str=="-PI" || str=="-pi"){ - t=-pi; return true; - } else if( str.find("PI")!=std::string::npos ){ - std::size_t pi_start=str.find_first_of("PI"); - if(str.substr(pi_start)!="PI") return false; - istringstream nstr(str.substr(0,pi_start)); - T ff=0.0; bool ok=static_cast(nstr>>ff); - if(!ok) return false; - t=ff*pi; - std::string remains; nstr>>remains; - return remains.length()==0; - } else if( str.find("pi")!=std::string::npos ){ - std::size_t pi_start=str.find_first_of("pi"); - if(str.substr(pi_start)!="pi") return false; - istringstream nstr(str.substr(0,pi_start)); - T ff=0.0; bool ok=static_cast(nstr>>ff); - if(!ok) return false; - t=ff*pi; - std::string remains; nstr>>remains; - return remains.length()==0; - } else if(str=="NAN"){ - t=NAN; - return true; - } - return convertToAny(str,t); +bool Tools::convertToReal(const string & str,T & t) { + if(str=="PI" || str=="+PI" || str=="+pi" || str=="pi") { + t=pi; return true; + } else if(str=="-PI" || str=="-pi") { + t=-pi; return true; + } else if( str.find("PI")!=std::string::npos ) { + std::size_t pi_start=str.find_first_of("PI"); + if(str.substr(pi_start)!="PI") return false; + istringstream nstr(str.substr(0,pi_start)); + T ff=0.0; bool ok=static_cast(nstr>>ff); + if(!ok) return false; + t=ff*pi; + std::string remains; nstr>>remains; + return remains.length()==0; + } else if( str.find("pi")!=std::string::npos ) { + std::size_t pi_start=str.find_first_of("pi"); + if(str.substr(pi_start)!="pi") return false; + istringstream nstr(str.substr(0,pi_start)); + T ff=0.0; bool ok=static_cast(nstr>>ff); + if(!ok) return false; + t=ff*pi; + std::string remains; nstr>>remains; + return remains.length()==0; + } else if(str=="NAN") { + t=NAN; + return true; + } + return convertToAny(str,t); } -bool Tools::convert(const string & str,float & t){ - return convertToReal(str,t); +bool Tools::convert(const string & str,float & t) { + return convertToReal(str,t); } -bool Tools::convert(const string & str,double & t){ - return convertToReal(str,t); +bool Tools::convert(const string & str,double & t) { + return convertToReal(str,t); } -bool Tools::convert(const string & str,long double & t){ - return convertToReal(str,t); +bool Tools::convert(const string & str,long double & t) { + return convertToReal(str,t); } -bool Tools::convert(const string & str,string & t){ - t=str; - return true; +bool Tools::convert(const string & str,string & t) { + t=str; + return true; } -vector Tools::getWords(const string & line,const char* separators,int * parlevel,const char* parenthesis){ +vector Tools::getWords(const string & line,const char* separators,int * parlevel,const char* parenthesis) { plumed_massert(strlen(parenthesis)==1,"multiple parenthesis type not available"); plumed_massert(parenthesis[0]=='(' || parenthesis[0]=='[' || parenthesis[0]=='{', - "only ( [ { allowed as parenthesis"); + "only ( [ { allowed as parenthesis"); if(!separators) separators=" \t\n"; const string sep(separators); char openpar=parenthesis[0]; @@ -122,25 +122,25 @@ vector Tools::getWords(const string & line,const char* separators,int * string word; int parenthesisLevel=0; if(parlevel) parenthesisLevel=*parlevel; - for(unsigned i=0;i=0,"Extra closed parenthesis in '" + line + "'"); } - if(parenthesisLevel==0) for(unsigned j=0;j0){ + if(found && word.length()>0) { if(!parlevel) plumed_massert(parenthesisLevel==0,"Unmatching parenthesis in '" + line + "'"); words.push_back(word); word.clear(); } } - if(word.length()>0){ + if(word.length()>0) { if(!parlevel) plumed_massert(parenthesisLevel==0,"Unmatching parenthesis in '" + line + "'"); words.push_back(word); } @@ -148,34 +148,34 @@ vector Tools::getWords(const string & line,const char* separators,int * return words; } -bool Tools::getParsedLine(IFile& ifile,vector & words){ +bool Tools::getParsedLine(IFile& ifile,vector & words) { string line(""); words.clear(); bool stat; bool inside=false; int parlevel=0; bool mergenext=false; - while((stat=ifile.getline(line))){ + while((stat=ifile.getline(line))) { trimComments(line); trim(line); if(line.length()==0) continue; vector w=getWords(line,NULL,&parlevel); if(w.empty()) continue; - if(inside && *(w.begin())=="..."){ + if(inside && *(w.begin())=="...") { inside=false; if(w.size()==2) plumed_massert(w[1]==words[0],"second word in terminating \"...\" lines, if present, should be equal to first word of directive"); plumed_massert(w.size()<=2,"terminating \"...\" lines cannot consist of more than two words"); w.clear(); - }else if(*(w.end()-1)=="..."){ + } else if(*(w.end()-1)=="...") { inside=true; w.erase(w.end()-1); }; int i0=0; - if(mergenext && words.size()>0 && w.size()>0){ + if(mergenext && words.size()>0 && w.size()>0) { words[words.size()-1]+=" "+w[0]; i0=1; } - for(unsigned i=i0;i0); if(!inside)break; } @@ -185,13 +185,13 @@ bool Tools::getParsedLine(IFile& ifile,vector & words){ } -bool Tools::getline(FILE* fp,string & line){ +bool Tools::getline(FILE* fp,string & line) { line=""; const int bufferlength=1024; char buffer[bufferlength]; bool ret; - for(int i=0;i0) if(buffer[ss-1]=='\n') break; @@ -201,28 +201,28 @@ bool Tools::getline(FILE* fp,string & line){ return ret; } -void Tools::trim(string & s){ +void Tools::trim(string & s) { size_t n=s.find_last_not_of(" \t"); s=s.substr(0,n+1); } -void Tools::trimComments(string & s){ +void Tools::trimComments(string & s) { size_t n=s.find_first_of("#"); s=s.substr(0,n); } -bool Tools::getKey(vector& line,const string & key,string & s,int rep){ +bool Tools::getKey(vector& line,const string & key,string & s,int rep) { s.clear(); - for(auto p=line.begin();p!=line.end();++p){ + for(auto p=line.begin(); p!=line.end(); ++p) { if((*p).length()==0) continue; string x=(*p).substr(0,key.length()); - if(x==key){ + if(x==key) { if((*p).length()==key.length())return false; string tmp=(*p).substr(key.length(),(*p).length()); line.erase(p); s=tmp; const std::string multi("@replicas:"); - if(rep>=0 && startWith(s,multi)){ + if(rep>=0 && startWith(s,multi)) { s=s.substr(multi.length(),s.length()); std::vector words=getWords(s,"\t\n ,"); plumed_assert(rep& line,const string & key,string & s,int rep){ return false; } -void Tools::interpretRanges(std::vector&s){ +void Tools::interpretRanges(std::vector&s) { vector news; - for(const auto & p :s){ + for(const auto & p :s) { news.push_back(p); size_t dash=p.find("-"); if(dash==string::npos) continue; @@ -245,23 +245,23 @@ void Tools::interpretRanges(std::vector&s){ int stride=1; int second; size_t colon=p.substr(dash+1).find(":"); - if(colon!=string::npos){ + if(colon!=string::npos) { if(!Tools::convert(p.substr(dash+1).substr(0,colon),second) || - !Tools::convert(p.substr(dash+1).substr(colon+1),stride)) continue; + !Tools::convert(p.substr(dash+1).substr(colon+1),stride)) continue; } else { if(!Tools::convert(p.substr(dash+1),second)) continue; } news.resize(news.size()-1); - if(first<=second){ + if(first<=second) { plumed_massert(stride>0,"interpreting ranges "+ p + ", stride should be positive"); - for(int i=first;i<=second;i+=stride){ + for(int i=first; i<=second; i+=stride) { string ss; convert(i,ss); news.push_back(ss); } } else { plumed_massert(stride<0,"interpreting ranges "+ p + ", stride should be positive"); - for(int i=first;i>=second;i+=stride){ + for(int i=first; i>=second; i+=stride) { string ss; convert(i,ss); news.push_back(ss); @@ -271,25 +271,25 @@ void Tools::interpretRanges(std::vector&s){ s=news; } -void Tools::interpretLabel(vector&s){ +void Tools::interpretLabel(vector&s) { if(s.size()<2)return; string s0=s[0]; unsigned l=s0.length(); if(l<1) return; - if(s0[l-1]==':'){ + if(s0[l-1]==':') { s[0]=s[1]; s[1]="LABEL="+s0.substr(0,l-1); } } -vector Tools::ls(const string&d){ +vector Tools::ls(const string&d) { DIR*dir; vector result; - if ((dir=opendir(d.c_str()))){ + if ((dir=opendir(d.c_str()))) { #if defined(__PLUMED_HAS_READDIR_R) struct dirent ent; #endif - while(true){ + while(true) { struct dirent *res; #if defined(__PLUMED_HAS_READDIR_R) readdir_r(dir,&ent,&res); @@ -309,16 +309,16 @@ vector Tools::ls(const string&d){ return result; } -void Tools::stripLeadingAndTrailingBlanks( std::string& str ){ +void Tools::stripLeadingAndTrailingBlanks( std::string& str ) { std::size_t first=str.find_first_not_of(' '); std::size_t last=str.find_last_not_of(' '); if( first<=last && first!=std::string::npos) str=str.substr(first,last+1); } -std::string Tools::extension(const std::string&s){ +std::string Tools::extension(const std::string&s) { size_t n=s.find_last_of("."); std::string ext; - if(n!=std::string::npos && n+1=s.length()){ + if(n!=std::string::npos && n+1=s.length()) { ext=s.substr(n+1); if(ext.find("/")!=std::string::npos) ext=""; string base=s.substr(0,n); @@ -328,13 +328,13 @@ std::string Tools::extension(const std::string&s){ return ext; } -bool Tools::startWith(const std::string & full,const std::string &start){ +bool Tools::startWith(const std::string & full,const std::string &start) { return (full.substr(0,start.length())==start); } -bool Tools::findKeyword(const std::vector&line,const std::string&key){ +bool Tools::findKeyword(const std::vector&line,const std::string&key) { const std::string search(key+"="); - for(const auto & p : line){ + for(const auto & p : line) { if(startWith(p,search)) return true; } return false; diff --git a/src/tools/Tools.h b/src/tools/Tools.h index 27d894530b..74ca0bec01 100644 --- a/src/tools/Tools.h +++ b/src/tools/Tools.h @@ -31,7 +31,7 @@ #include #include -namespace PLMD{ +namespace PLMD { class IFile; @@ -49,7 +49,7 @@ const double pi(3.14159265358979323846264338327950288419716939937510582097494459 /// \ingroup TOOLBOX /// Empty class which just contains several (static) tools -class Tools{ +class Tools { /// class to convert a string to a generic type T template static bool convertToAny(const std::string & str,T &t); @@ -114,7 +114,7 @@ class Tools{ static bool findKeyword(const std::vector&line,const std::string&key); /// Interpret atom ranges static void interpretRanges(std::vector&); -/// Remove duplicates from a vector of type T +/// Remove duplicates from a vector of type T template static void removeDuplicates(std::vector& vec); /// interpret ":" syntax for labels @@ -127,7 +127,7 @@ class Tools{ /// E.g.: extension("pippo.xyz")="xyz". /// It only returns extensions with a length between 1 and 4 /// E.g.: extension("pippo.12345")="" whereas extenion("pippo.1234")="1234"; -/// It is also smart enough to detect "/", so that +/// It is also smart enough to detect "/", so that /// extension("pippo/.t")="" whereas extension("pippo/a.t")="t" static std::string extension(const std::string&); /// Fast int power @@ -138,7 +138,7 @@ class Tools{ }; template -bool Tools::parse(std::vector&line,const std::string&key,T&val,int rep){ +bool Tools::parse(std::vector&line,const std::string&key,T&val,int rep) { std::string s; if(!getKey(line,key+"=",s,rep)) return false; if(s.length()>0 && !convert(s,val))return false; @@ -146,17 +146,17 @@ bool Tools::parse(std::vector&line,const std::string&key,T&val,int } template -bool Tools::parseVector(std::vector&line,const std::string&key,std::vector&val,int rep){ +bool Tools::parseVector(std::vector&line,const std::string&key,std::vector&val,int rep) { std::string s; if(!getKey(line,key+"=",s,rep)) return false; // if(s.length()==0) return true; val.clear(); std::vector words=getWords(s,"\t\n ,"); - for(unsigned i=0;i=0 && startWith(s,multi)){ + if(rep>=0 && startWith(s,multi)) { s=s.substr(multi.length(),s.length()); std::vector words=getWords(s,"\t\n ,"); plumed_assert(rep&line,const std::string&key,std: template void Tools::removeDuplicates(std::vector& vec) { - std::sort(vec.begin(), vec.end()); - vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); + std::sort(vec.begin(), vec.end()); + vec.erase(std::unique(vec.begin(), vec.end()), vec.end()); } inline -bool Tools::parseFlag(std::vector&line,const std::string&key,bool&val){ - for(auto p=line.begin();p!=line.end();++p){ - if(key==*p){ +bool Tools::parseFlag(std::vector&line,const std::string&key,bool&val) { + for(auto p=line.begin(); p!=line.end(); ++p) { + if(key==*p) { val=true; line.erase(p); return true; @@ -189,7 +189,7 @@ bool Tools::parseFlag(std::vector&line,const std::string&key,bool&v /// beware: this brings any number into a pbc that ranges from -0.5 to 0.5 inline -double Tools::pbc(double x){ +double Tools::pbc(double x) { #ifdef __PLUMED_PBC_WHILE while (x>0.5) x-=1.0; while (x<-0.5) x+=1.0; @@ -207,29 +207,29 @@ double Tools::pbc(double x){ } template -void Tools::convert(T i,std::string & str){ - std::ostringstream ostr; - ostr<>= 1; - base *= base; - } + if(exp<0) { + exp=-exp; + base=1.0/base; + } + double result = 1.0; + while (exp) + { + if (exp & 1) + result *= base; + exp >>= 1; + base *= base; + } - return result; + return result; } } diff --git a/src/tools/Torsion.cpp b/src/tools/Torsion.cpp index d124986007..4464e1bd17 100644 --- a/src/tools/Torsion.cpp +++ b/src/tools/Torsion.cpp @@ -25,18 +25,18 @@ #include #include -namespace PLMD{ - -double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3)const{ - const Vector nv2(v2*(1.0/v2.modulo())); - const Vector a(crossProduct(nv2,v1)); - const Vector b(crossProduct(v3,nv2)); - const double cosangle=dotProduct(a,b); - const double sinangle=dotProduct(crossProduct(a,b),nv2); - return std::atan2(-sinangle,cosangle); +namespace PLMD { + +double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3)const { + const Vector nv2(v2*(1.0/v2.modulo())); + const Vector a(crossProduct(nv2,v1)); + const Vector b(crossProduct(v3,nv2)); + const double cosangle=dotProduct(a,b); + const double sinangle=dotProduct(crossProduct(a,b),nv2); + return std::atan2(-sinangle,cosangle); } -double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3,Vector& d1,Vector& d2,Vector& d3)const{ +double Torsion::compute(const Vector& v1,const Vector& v2,const Vector& v3,Vector& d1,Vector& d2,Vector& d3)const { const double modv2(1./v2.modulo()); const Vector nv2(v2*modv2); diff --git a/src/tools/Torsion.h b/src/tools/Torsion.h index b8ac740412..b898a99ccd 100644 --- a/src/tools/Torsion.h +++ b/src/tools/Torsion.h @@ -24,7 +24,7 @@ #include "Vector.h" -namespace PLMD{ +namespace PLMD { /// \ingroup TOOLBOX /// Class to compute torsional angles. @@ -36,7 +36,7 @@ namespace PLMD{ /// I know it is a bit misleading. If we really do not need to store "options" /// inside the Torsion class, we can remove it later and write compute as /// a static function. -class Torsion{ +class Torsion { // still empty, but may accomodate some options in the future public: /// Compute the angle between the projections of v1 and v3 on the plane orthogonal diff --git a/src/tools/Units.cpp b/src/tools/Units.cpp index 3bb5c8886c..48737c9d08 100644 --- a/src/tools/Units.cpp +++ b/src/tools/Units.cpp @@ -24,7 +24,7 @@ using namespace std; -namespace PLMD{ +namespace PLMD { Units::Units(): energy(1.0), @@ -40,15 +40,15 @@ Units::Units(): { } -void Units::setEnergy(const std::string &s){ +void Units::setEnergy(const std::string &s) { energyString=s; - if(s=="kj/mol"){ + if(s=="kj/mol") { energy=1.0; - } else if(s=="kcal/mol"){ + } else if(s=="kcal/mol") { energy=4.184; - } else if(s=="j/mol"){ + } else if(s=="j/mol") { energy=0.001; - } else if(s=="eV"){ + } else if(s=="eV") { energy=96.48530749925792; } else { energy=-1.0; @@ -58,13 +58,13 @@ void Units::setEnergy(const std::string &s){ } } -void Units::setLength(const std::string &s){ +void Units::setLength(const std::string &s) { lengthString=s; - if(s=="nm"){ + if(s=="nm") { length=1.0; - } else if(s=="A"){ + } else if(s=="A") { length=0.1; - } else if(s=="um"){ + } else if(s=="um") { length=1000.0; } else { length=-1.0; @@ -74,13 +74,13 @@ void Units::setLength(const std::string &s){ } } -void Units::setTime(const std::string &s){ +void Units::setTime(const std::string &s) { timeString=s; - if(s=="ps"){ + if(s=="ps") { time=1.0; - } else if(s=="ns"){ + } else if(s=="ns") { time=1000.0; - } else if(s=="fs"){ + } else if(s=="fs") { time=0.001; } else { time=-1.0; @@ -90,9 +90,9 @@ void Units::setTime(const std::string &s){ } } -void Units::setCharge(const std::string &s){ +void Units::setCharge(const std::string &s) { chargeString=s; - if(s=="e"){ + if(s=="e") { charge=1.0; } else { charge=-1.0; @@ -102,9 +102,9 @@ void Units::setCharge(const std::string &s){ } } -void Units::setMass(const std::string &s){ +void Units::setMass(const std::string &s) { massString=s; - if(s=="amu"){ + if(s=="amu") { mass=1.0; } else { mass=-1.0; @@ -114,27 +114,27 @@ void Units::setMass(const std::string &s){ } } -void Units::setEnergy(const double s){ +void Units::setEnergy(const double s) { energyString=""; energy=s; } -void Units::setLength(const double s){ +void Units::setLength(const double s) { lengthString=""; length=s; } -void Units::setTime(const double s){ +void Units::setTime(const double s) { timeString=""; time=s; } -void Units::setCharge(const double s){ +void Units::setCharge(const double s) { chargeString=""; charge=s; } -void Units::setMass(const double s){ +void Units::setMass(const double s) { massString=""; mass=s; } diff --git a/src/tools/Units.h b/src/tools/Units.h index e7f5c63350..12074cc211 100644 --- a/src/tools/Units.h +++ b/src/tools/Units.h @@ -24,7 +24,7 @@ #include -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -38,7 +38,7 @@ one can also use strings such as kcal/mol. */ -class Units{ +class Units { /// Units for energy, expressed in kj/mol (e.g. 4.184 means kcal/mol) double energy; std::string energyString; @@ -111,52 +111,52 @@ class Units{ }; inline -const double & Units::getEnergy()const{ +const double & Units::getEnergy()const { return energy; } inline -const double & Units::getLength()const{ +const double & Units::getLength()const { return length; } inline -const double & Units::getTime()const{ +const double & Units::getTime()const { return time; } inline -const double & Units::getCharge()const{ +const double & Units::getCharge()const { return charge; } inline -const double & Units::getMass()const{ +const double & Units::getMass()const { return mass; } inline -const std::string & Units::getEnergyString()const{ +const std::string & Units::getEnergyString()const { return energyString; } inline -const std::string & Units::getLengthString()const{ +const std::string & Units::getLengthString()const { return lengthString; } inline -const std::string & Units::getTimeString()const{ +const std::string & Units::getTimeString()const { return timeString; } inline -const std::string & Units::getChargeString()const{ +const std::string & Units::getChargeString()const { return chargeString; } inline -const std::string & Units::getMassString()const{ +const std::string & Units::getMassString()const { return massString; } diff --git a/src/tools/Vector.cpp b/src/tools/Vector.cpp index f868a1aba5..8f2883acb8 100644 --- a/src/tools/Vector.cpp +++ b/src/tools/Vector.cpp @@ -23,18 +23,18 @@ #include "Exception.h" #include -namespace PLMD{ +namespace PLMD { /// Small auxiliary class. /// I use it to test a few things that I am scary of and could introduce bugs. /// It checks at startup that Vector satifies some requirement so as to allow /// accessing a vector of tensors as a 3 times longer array of doubles. -static class VectorChecks{ +static class VectorChecks { public: - VectorChecks(){ + VectorChecks() { if( sizeof(VectorGeneric<2>)==2*sizeof(double) - && sizeof(VectorGeneric<3>)==3*sizeof(double) - && sizeof(VectorGeneric<4>)==4*sizeof(double)) return; + && sizeof(VectorGeneric<3>)==3*sizeof(double) + && sizeof(VectorGeneric<4>)==4*sizeof(double)) return; plumed_merror("sizeof(VectorGeneric)!=x*sizeof(double). PLUMED cannot work properly in these conditions."); } } checks; diff --git a/src/tools/Vector.h b/src/tools/Vector.h index 8c3422c2f0..133ff4a194 100644 --- a/src/tools/Vector.h +++ b/src/tools/Vector.h @@ -31,7 +31,7 @@ #endif -namespace PLMD{ +namespace PLMD { /** \ingroup TOOLBOX @@ -43,7 +43,7 @@ This class implements a vector of doubles with size fixed at compile time. It is useful for small fixed size objects (e.g. 3d vectors) as it does not waste space to store the vector size. Moreover, as the compiler knows the size, it can be completely -opimized inline. +opimized inline. All the methods are inlined for better optimization and all the loops are explicitly unrolled using PLMD::LoopUnroller class. Vector elements are initialized to zero by default. Notice that @@ -80,7 +80,7 @@ int main(){ template -class VectorGeneric{ +class VectorGeneric { double d[n]; public: /// Create it with preassigned components. @@ -155,14 +155,14 @@ class VectorGeneric{ template<> inline -VectorGeneric<2>:: VectorGeneric(double x0,double x1){ +VectorGeneric<2>:: VectorGeneric(double x0,double x1) { d[0]=x0; d[1]=x1; } template<> inline -VectorGeneric<3>:: VectorGeneric(double x0,double x1,double x2){ +VectorGeneric<3>:: VectorGeneric(double x0,double x1,double x2) { d[0]=x0; d[1]=x1; d[2]=x2; @@ -170,7 +170,7 @@ VectorGeneric<3>:: VectorGeneric(double x0,double x1,double x2){ template<> inline -VectorGeneric<4>:: VectorGeneric(double x0,double x1,double x2,double x3){ +VectorGeneric<4>:: VectorGeneric(double x0,double x1,double x2,double x3) { d[0]=x0; d[1]=x1; d[2]=x2; @@ -178,17 +178,17 @@ VectorGeneric<4>:: VectorGeneric(double x0,double x1,double x2,double x3){ } template -void VectorGeneric::zero(){ +void VectorGeneric::zero() { LoopUnroller::_zero(d); } template -VectorGeneric::VectorGeneric(){ +VectorGeneric::VectorGeneric() { LoopUnroller::_zero(d); } template -double & VectorGeneric::operator[](unsigned i){ +double & VectorGeneric::operator[](unsigned i) { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator[](unsigned i){ } template -const double & VectorGeneric::operator[](unsigned i)const{ +const double & VectorGeneric::operator[](unsigned i)const { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator[](unsigned i)const{ } template -double & VectorGeneric::operator()(unsigned i){ +double & VectorGeneric::operator()(unsigned i) { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator()(unsigned i){ } template -const double & VectorGeneric::operator()(unsigned i)const{ +const double & VectorGeneric::operator()(unsigned i)const { #ifdef _GLIBCXX_DEBUG plumed_assert(i::operator()(unsigned i)const{ } template -VectorGeneric& VectorGeneric::operator +=(const VectorGeneric& b){ +VectorGeneric& VectorGeneric::operator +=(const VectorGeneric& b) { LoopUnroller::_add(d,b.d); return *this; } template -VectorGeneric& VectorGeneric::operator -=(const VectorGeneric& b){ +VectorGeneric& VectorGeneric::operator -=(const VectorGeneric& b) { LoopUnroller::_sub(d,b.d); return *this; } template -VectorGeneric& VectorGeneric::operator *=(double s){ +VectorGeneric& VectorGeneric::operator *=(double s) { LoopUnroller::_mul(d,s); return *this; } template -VectorGeneric& VectorGeneric::operator /=(double s){ +VectorGeneric& VectorGeneric::operator /=(double s) { LoopUnroller::_mul(d,1.0/s); return *this; } template -VectorGeneric VectorGeneric::operator +()const{ +VectorGeneric VectorGeneric::operator +()const { return *this; } template -VectorGeneric VectorGeneric::operator -()const{ +VectorGeneric VectorGeneric::operator -()const { VectorGeneric r; LoopUnroller::_neg(r.d,d); return r; } template -VectorGeneric operator+(const VectorGeneric&v1,const VectorGeneric&v2){ +VectorGeneric operator+(const VectorGeneric&v1,const VectorGeneric&v2) { VectorGeneric v(v1); return v+=v2; } template -VectorGeneric operator-(const VectorGeneric&v1,const VectorGeneric&v2){ +VectorGeneric operator-(const VectorGeneric&v1,const VectorGeneric&v2) { VectorGeneric v(v1); return v-=v2; } template -VectorGeneric operator*(double s,const VectorGeneric&v){ +VectorGeneric operator*(double s,const VectorGeneric&v) { VectorGeneric vv(v); return vv*=s; } template -VectorGeneric operator*(const VectorGeneric&v,double s){ +VectorGeneric operator*(const VectorGeneric&v,double s) { return s*v; } template -VectorGeneric operator/(const VectorGeneric&v,double s){ +VectorGeneric operator/(const VectorGeneric&v,double s) { return v*(1.0/s); } template -VectorGeneric delta(const VectorGeneric&v1,const VectorGeneric&v2){ +VectorGeneric delta(const VectorGeneric&v1,const VectorGeneric&v2) { return v2-v1; } template -double VectorGeneric::modulo2()const{ +double VectorGeneric::modulo2()const { return LoopUnroller::_sum2(d); } template -double dotProduct(const VectorGeneric& v1,const VectorGeneric& v2){ +double dotProduct(const VectorGeneric& v1,const VectorGeneric& v2) { return LoopUnroller::_dot(v1.d,v2.d); } inline -VectorGeneric<3> crossProduct(const VectorGeneric<3>& v1,const VectorGeneric<3>& v2){ - return VectorGeneric<3>( - v1[1]*v2[2]-v1[2]*v2[1], - v1[2]*v2[0]-v1[0]*v2[2], - v1[0]*v2[1]-v1[1]*v2[0]); +VectorGeneric<3> crossProduct(const VectorGeneric<3>& v1,const VectorGeneric<3>& v2) { + return VectorGeneric<3>( + v1[1]*v2[2]-v1[2]*v2[1], + v1[2]*v2[0]-v1[0]*v2[2], + v1[0]*v2[1]-v1[1]*v2[0]); } template -double VectorGeneric::modulo()const{ +double VectorGeneric::modulo()const { return sqrt(modulo2()); } template -double modulo2(const VectorGeneric&v){ +double modulo2(const VectorGeneric&v) { return v.modulo2(); } template -double modulo(const VectorGeneric&v){ +double modulo(const VectorGeneric&v) { return v.modulo(); } template -std::ostream & operator<<(std::ostream &os, const VectorGeneric& v){ - for(unsigned i=0;i& v) { + for(unsigned i=0; i deriv(getNumberOfAtoms()); - for(unsigned i=0;i deriv(getNumberOfAtoms()); - for(unsigned i=0;i deriv(getNumberOfAtoms()); - if(scaled_components){ + if(scaled_components) { setPosition(getPbc().scaledToReal(coord)); } else { setPosition(coord); diff --git a/src/vatom/Ghost.cpp b/src/vatom/Ghost.cpp index e14f6db7aa..fcd7893775 100644 --- a/src/vatom/Ghost.cpp +++ b/src/vatom/Ghost.cpp @@ -26,13 +26,13 @@ using namespace std; -namespace PLMD{ -namespace vatom{ +namespace PLMD { +namespace vatom { -//+PLUMEDOC VATOM GHOST +//+PLUMEDOC VATOM GHOST /* Calculate the absolute position of a ghost atom with fixed coordinates -in the local reference frame formed by three atoms. +in the local reference frame formed by three atoms. The computed ghost atom is stored as a virtual atom that can be accessed in an atom list through the the label for the GHOST action that creates it. @@ -63,7 +63,7 @@ class Ghost: PLUMED_REGISTER_ACTION(Ghost,"GHOST") -void Ghost::registerKeywords(Keywords& keys){ +void Ghost::registerKeywords(Keywords& keys) { ActionWithVirtualAtom::registerKeywords(keys); keys.add("atoms","COORDINATES","coordinates of the ghost atom in the local reference frame"); } @@ -81,35 +81,35 @@ Ghost::Ghost(const ActionOptions&ao): checkRead(); log.printf(" of atoms"); - for(unsigned i=0;i deriv(getNumberOfAtoms()); vector n; -// first versor +// first versor Vector n01 = delta(getPosition(0), getPosition(1)); n.push_back(n01/n01.modulo()); // auxiliary vector Vector n02 = delta(getPosition(0), getPosition(2)); -// second versor +// second versor Vector n03 = crossProduct(n[0],n02); double n03_norm = n03.modulo(); n.push_back(n03/n03_norm); -// third versor +// third versor n.push_back(crossProduct(n[0],n[1])); // origin of the reference system pos = getPosition(0); - for(unsigned i=0;i<3;++i){ + for(unsigned i=0; i<3; ++i) { pos += coord[i] * n[i]; } @@ -117,7 +117,7 @@ void Ghost::calculate(){ setMass(1.0); setCharge(0.0); -// some useful tensors for derivatives +// some useful tensors for derivatives Tensor dn0d0 = (-Tensor::identity()+Tensor(n[0],n[0]))/n01.modulo(); Tensor dn0d1 = (+Tensor::identity()-Tensor(n[0],n[0]))/n01.modulo(); Tensor dn02d0 = -Tensor::identity(); @@ -125,50 +125,50 @@ void Ghost::calculate(){ // derivative of n1 = n0 x n02 Tensor dn1d0, dn1d1, dn1d2; - Vector aux0, aux1, aux2; + Vector aux0, aux1, aux2; - for(unsigned j=0;j<3;++j){ + for(unsigned j=0; j<3; ++j) { // derivative of n0 x n02 with respect to point 0, coordinate j - Vector tmp00 = Vector( dn0d0(j,0), dn0d0(j,1), dn0d0(j,2)); - Vector tmp020 = Vector(dn02d0(j,0), dn02d0(j,1), dn02d0(j,2)); - Vector tmp0 = crossProduct(tmp00,n02) + crossProduct(n[0],tmp020); - aux0[j] = dotProduct(tmp0,n[1]); + Vector tmp00 = Vector( dn0d0(j,0), dn0d0(j,1), dn0d0(j,2)); + Vector tmp020 = Vector(dn02d0(j,0), dn02d0(j,1), dn02d0(j,2)); + Vector tmp0 = crossProduct(tmp00,n02) + crossProduct(n[0],tmp020); + aux0[j] = dotProduct(tmp0,n[1]); // derivative of n0 x n02 with respect to point 1, coordinate j - Vector tmp01 = Vector( dn0d1(j,0), dn0d1(j,1), dn0d1(j,2)); - Vector tmp1 = crossProduct(tmp01,n02); - aux1[j] = dotProduct(tmp1,n[1]); + Vector tmp01 = Vector( dn0d1(j,0), dn0d1(j,1), dn0d1(j,2)); + Vector tmp1 = crossProduct(tmp01,n02); + aux1[j] = dotProduct(tmp1,n[1]); // derivative of n0 x n02 with respect to point 2, coordinate j - Vector tmp022 = Vector(dn02d2(j,0), dn02d2(j,1), dn02d2(j,2)); - Vector tmp2 = crossProduct(n[0],tmp022); - aux2[j] = dotProduct(tmp2,n[1]); + Vector tmp022 = Vector(dn02d2(j,0), dn02d2(j,1), dn02d2(j,2)); + Vector tmp2 = crossProduct(n[0],tmp022); + aux2[j] = dotProduct(tmp2,n[1]); // derivative of n1 = (n0 x n02) / || (n0 x n02) || - for(unsigned i=0;i<3;++i) { - dn1d0(j,i) = ( tmp0[i] - aux0[j] * n[1][i] ) / n03_norm; - dn1d1(j,i) = ( tmp1[i] - aux1[j] * n[1][i] ) / n03_norm; - dn1d2(j,i) = ( tmp2[i] - aux2[j] * n[1][i] ) / n03_norm; - } + for(unsigned i=0; i<3; ++i) { + dn1d0(j,i) = ( tmp0[i] - aux0[j] * n[1][i] ) / n03_norm; + dn1d1(j,i) = ( tmp1[i] - aux1[j] * n[1][i] ) / n03_norm; + dn1d2(j,i) = ( tmp2[i] - aux2[j] * n[1][i] ) / n03_norm; + } } // Derivative of the last versor n2 = n0 x n1 = ( n0( n0 n02 ) - n02 ) / || n0 x n02 || // Scalar product and derivatives - double n0_n02 = dotProduct(n[0],n02); + double n0_n02 = dotProduct(n[0],n02); Vector dn0_n02d0, dn0_n02d1, dn0_n02d2; - for(unsigned j=0;j<3;++j){ - for(unsigned i=0;i<3;++i){ - dn0_n02d0[j] += dn0d0(j,i)*n02[i] + n[0][i]*dn02d0(j,i); - dn0_n02d1[j] += dn0d1(j,i)*n02[i]; - dn0_n02d2[j] += n[0][i]*dn02d2(j,i); - } + for(unsigned j=0; j<3; ++j) { + for(unsigned i=0; i<3; ++i) { + dn0_n02d0[j] += dn0d0(j,i)*n02[i] + n[0][i]*dn02d0(j,i); + dn0_n02d1[j] += dn0d1(j,i)*n02[i]; + dn0_n02d2[j] += n[0][i]*dn02d2(j,i); + } } Tensor dn2d0, dn2d1, dn2d2; - for(unsigned j=0;j<3;++j){ - for(unsigned i=0;i<3;++i){ - dn2d0(j,i) = ( dn0d0(j,i) * n0_n02 + n[0][i] * dn0_n02d0[j] - dn02d0(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux0[j] / n03_norm ) / n03_norm; - dn2d1(j,i) = ( dn0d1(j,i) * n0_n02 + n[0][i] * dn0_n02d1[j] - ( n[0][i] * n0_n02 - n02[i] ) * aux1[j] / n03_norm ) / n03_norm; - dn2d2(j,i) = ( n[0][i] * dn0_n02d2[j] - dn02d2(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux2[j] / n03_norm ) / n03_norm; - } + for(unsigned j=0; j<3; ++j) { + for(unsigned i=0; i<3; ++i) { + dn2d0(j,i) = ( dn0d0(j,i) * n0_n02 + n[0][i] * dn0_n02d0[j] - dn02d0(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux0[j] / n03_norm ) / n03_norm; + dn2d1(j,i) = ( dn0d1(j,i) * n0_n02 + n[0][i] * dn0_n02d1[j] - ( n[0][i] * n0_n02 - n02[i] ) * aux1[j] / n03_norm ) / n03_norm; + dn2d2(j,i) = ( n[0][i] * dn0_n02d2[j] - dn02d2(j,i) - ( n[0][i] * n0_n02 - n02[i] ) * aux2[j] / n03_norm ) / n03_norm; + } } // Finally, the derivative tensor diff --git a/src/vesselbase/ActionWithAveraging.cpp b/src/vesselbase/ActionWithAveraging.cpp index e6111a7690..a470f6f5f8 100644 --- a/src/vesselbase/ActionWithAveraging.cpp +++ b/src/vesselbase/ActionWithAveraging.cpp @@ -26,104 +26,104 @@ namespace PLMD { namespace vesselbase { -void ActionWithAveraging::registerKeywords( Keywords& keys ){ - Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); +void ActionWithAveraging::registerKeywords( Keywords& keys ) { + Action::registerKeywords( keys ); ActionPilot::registerKeywords( keys ); ActionAtomistic::registerKeywords( keys ); ActionWithArguments::registerKeywords( keys ); ActionWithValue::registerKeywords( keys ); ActionWithVessel::registerKeywords( keys ); keys.add("compulsory","STRIDE","1","the frequency with which the data should be collected and added to the quantity being averaged"); keys.add("compulsory","CLEAR","0","the frequency with which to clear all the accumulated data. The default value " - "of 0 implies that all the data will be used and that the grid will never be cleared"); + "of 0 implies that all the data will be used and that the grid will never be cleared"); keys.add("optional","LOGWEIGHTS","list of actions that calculates log weights that should be used to weight configurations when calculating averages"); keys.addFlag("UNORMALIZED",false,"output the unaveraged quantity/quantities."); keys.remove("NUMERICAL_DERIVATIVES"); } ActionWithAveraging::ActionWithAveraging( const ActionOptions& ao ): -Action(ao), -ActionPilot(ao), -ActionAtomistic(ao), -ActionWithArguments(ao), -ActionWithValue(ao), -ActionWithVessel(ao), -myaverage(NULL), -useRunAllTasks(false), -clearstride(0), -lweight(0),cweight(0) + Action(ao), + ActionPilot(ao), + ActionAtomistic(ao), + ActionWithArguments(ao), + ActionWithValue(ao), + ActionWithVessel(ao), + myaverage(NULL), + useRunAllTasks(false), + clearstride(0), + lweight(0),cweight(0) { - if( keywords.exists("CLEAR") ){ - parse("CLEAR",clearstride); - if( clearstride>0 ){ - if( clearstride%getStride()!=0 ) error("CLEAR parameter must be a multiple of STRIDE"); - log.printf(" clearing grid every %u steps \n",clearstride); - } + if( keywords.exists("CLEAR") ) { + parse("CLEAR",clearstride); + if( clearstride>0 ) { + if( clearstride%getStride()!=0 ) error("CLEAR parameter must be a multiple of STRIDE"); + log.printf(" clearing grid every %u steps \n",clearstride); + } } - if( keywords.exists("LOGWEIGHTS") ){ - std::vector wwstr; parseVector("LOGWEIGHTS",wwstr); - if( wwstr.size()>0 ) log.printf(" reweighting using weights from "); - std::vector arg( getArguments() ); - for(unsigned i=0;i(wwstr[i]); - if( !val ) error("could not find value named"); - weights.push_back( val->copyOutput(val->getLabel()) ); - arg.push_back( val->copyOutput(val->getLabel()) ); - log.printf("%s ",wwstr[i].c_str() ); - } - if( wwstr.size()>0 ) log.printf("\n"); - else log.printf(" weights are all equal to one\n"); - requestArguments( arg ); + if( keywords.exists("LOGWEIGHTS") ) { + std::vector wwstr; parseVector("LOGWEIGHTS",wwstr); + if( wwstr.size()>0 ) log.printf(" reweighting using weights from "); + std::vector arg( getArguments() ); + for(unsigned i=0; i(wwstr[i]); + if( !val ) error("could not find value named"); + weights.push_back( val->copyOutput(val->getLabel()) ); + arg.push_back( val->copyOutput(val->getLabel()) ); + log.printf("%s ",wwstr[i].c_str() ); + } + if( wwstr.size()>0 ) log.printf("\n"); + else log.printf(" weights are all equal to one\n"); + requestArguments( arg ); } if( keywords.exists("UNORMALIZED") ) parseFlag("UNORMALIZED",unormalised); } -void ActionWithAveraging::setAveragingAction( AveragingVessel* av_vessel, const bool& usetasks ){ - myaverage=av_vessel; addVessel( myaverage ); +void ActionWithAveraging::setAveragingAction( AveragingVessel* av_vessel, const bool& usetasks ) { + myaverage=av_vessel; addVessel( myaverage ); useRunAllTasks=usetasks; resizeFunctions(); } -void ActionWithAveraging::lockRequests(){ +void ActionWithAveraging::lockRequests() { ActionAtomistic::lockRequests(); ActionWithArguments::lockRequests(); } -void ActionWithAveraging::unlockRequests(){ +void ActionWithAveraging::unlockRequests() { ActionAtomistic::unlockRequests(); ActionWithArguments::unlockRequests(); } -void ActionWithAveraging::calculateNumericalDerivatives(PLMD::ActionWithValue*){ +void ActionWithAveraging::calculateNumericalDerivatives(PLMD::ActionWithValue*) { error("not possible to compute numerical derivatives for this action"); } -void ActionWithAveraging::update(){ +void ActionWithAveraging::update() { if( (clearstride!=1 && getStep()==0) || !onStep() ) return; // Clear if it is time to reset - if( myaverage ){ - if( myaverage->wasreset() ) clearAverage(); + if( myaverage ) { + if( myaverage->wasreset() ) clearAverage(); } // Calculate the weight for all reweighting - if ( weights.size()>0 ){ - double sum=0; for(unsigned i=0;iget(); - lweight=sum; cweight = exp( sum ); + if ( weights.size()>0 ) { + double sum=0; for(unsigned i=0; iget(); + lweight=sum; cweight = exp( sum ); } else { - lweight=0; cweight=1.0; + lweight=0; cweight=1.0; } // Prepare to do the averaging prepareForAveraging(); // Run all the tasks (if required - if( useRunAllTasks ) runAllTasks(); + if( useRunAllTasks ) runAllTasks(); // This the averaging if it is not done using task list else performOperations( true ); - // Update the norm + // Update the norm if( myaverage ) myaverage->setNorm( cweight + myaverage->getNorm() ); // Finish the averaging finishAveraging(); // By resetting here we are ensuring that the grid will be cleared at the start of the next step - if( myaverage ){ - if( getStride()==0 || (clearstride>0 && getStep()%clearstride==0) ) myaverage->reset(); + if( myaverage ) { + if( getStride()==0 || (clearstride>0 && getStep()%clearstride==0) ) myaverage->reset(); } } -void ActionWithAveraging::clearAverage(){ plumed_assert( myaverage->wasreset() ); myaverage->clear(); } +void ActionWithAveraging::clearAverage() { plumed_assert( myaverage->wasreset() ); myaverage->clear(); } -void ActionWithAveraging::performOperations( const bool& from_update ){ plumed_error(); } +void ActionWithAveraging::performOperations( const bool& from_update ) { plumed_error(); } } diff --git a/src/vesselbase/ActionWithAveraging.h b/src/vesselbase/ActionWithAveraging.h index fe33827e76..62b5642fb6 100644 --- a/src/vesselbase/ActionWithAveraging.h +++ b/src/vesselbase/ActionWithAveraging.h @@ -35,8 +35,8 @@ namespace vesselbase { /** \ingroup INHERIT -This abstract base class should be used if you are writing some method that calculates an "average" from a set of -trajectory frames. Notice that we use the word average very broadly here and state that even dimensionality +This abstract base class should be used if you are writing some method that calculates an "average" from a set of +trajectory frames. Notice that we use the word average very broadly here and state that even dimensionality reduction algorithms calculate an "average." In other words, what we mean by average is that the method is going to take in data from each trajectory frame and only calculate the final quantity once a certain amount of data has been collected. @@ -49,7 +49,7 @@ class ActionWithAveraging : public ActionWithValue, public ActionWithVessel { -friend class AveragingVessel; + friend class AveragingVessel; private: /// The vessel which is used to compute averages AveragingVessel* myaverage; @@ -74,19 +74,19 @@ friend class AveragingVessel; void lockRequests(); void unlockRequests(); void calculateNumericalDerivatives(PLMD::ActionWithValue*); - virtual unsigned getNumberOfDerivatives(){ return 0; } + virtual unsigned getNumberOfDerivatives() { return 0; } unsigned getNumberOfArguments() const ; /// Overwrite ActionWithArguments getArguments() so that we don't return the bias - std::vector getArguments(); + std::vector getArguments(); void update(); /// This does the clearing of the action virtual void clearAverage(); /// This is done before the averaging comences - virtual void prepareForAveraging(){} + virtual void prepareForAveraging() {} /// This does the averaging operation virtual void performOperations( const bool& from_update ); /// This is done once the averaging is finished - virtual void finishAveraging(){} + virtual void finishAveraging() {} }; inline @@ -95,9 +95,9 @@ unsigned ActionWithAveraging::getNumberOfArguments() const { } inline -std::vector ActionWithAveraging::getArguments(){ +std::vector ActionWithAveraging::getArguments() { std::vector arg_vals( ActionWithArguments::getArguments() ); - for(unsigned i=0;i(mlab); if(!mves) error("action labelled " + mlab + " does not exist or does not have vessels"); addDependency(mves); ActionWithValue* aval=dynamic_cast( this ); - if(aval){ - if( aval->checkNumericalDerivatives() ){ - ActionWithValue* aval2=dynamic_cast( mves ); - plumed_assert( aval2 ); aval2->useNumericalDerivatives(); - } + if(aval) { + if( aval->checkNumericalDerivatives() ) { + ActionWithValue* aval2=dynamic_cast( mves ); + plumed_assert( aval2 ); aval2->useNumericalDerivatives(); + } } - if( type=="bridge" ){ - ActionWithVessel* aves=dynamic_cast( this ); - plumed_assert(aves); myBridgeVessel = mves->addBridgingVessel( aves ); - arguments = dynamic_cast( myBridgeVessel ); - } else if( type=="store" ){ - arguments = dynamic_cast( mves->buildDataStashes( NULL ) ); + if( type=="bridge" ) { + ActionWithVessel* aves=dynamic_cast( this ); + plumed_assert(aves); myBridgeVessel = mves->addBridgingVessel( aves ); + arguments = dynamic_cast( myBridgeVessel ); + } else if( type=="store" ) { + arguments = dynamic_cast( mves->buildDataStashes( NULL ) ); } else { - plumed_error(); + plumed_error(); } } -void ActionWithInputVessel::calculateNumericalDerivatives( ActionWithValue* a ){ - if(!a){ +void ActionWithInputVessel::calculateNumericalDerivatives( ActionWithValue* a ) { + if(!a) { a=dynamic_cast(this); plumed_massert(a,"cannot compute numerical derivatives for an action without values"); } - if( myBridgeVessel ){ - myBridgeVessel->completeNumericalDerivatives(); + if( myBridgeVessel ) { + myBridgeVessel->completeNumericalDerivatives(); } else { - error("numerical derivatives are not implemented"); + error("numerical derivatives are not implemented"); } } -void ActionWithInputVessel::applyBridgeForces( const std::vector& bb ){ - plumed_dbg_assert( myBridgeVessel ); addBridgeForces( bb ); +void ActionWithInputVessel::applyBridgeForces( const std::vector& bb ) { + plumed_dbg_assert( myBridgeVessel ); addBridgeForces( bb ); } } diff --git a/src/vesselbase/ActionWithInputVessel.h b/src/vesselbase/ActionWithInputVessel.h index ac278768d3..09d888f45f 100644 --- a/src/vesselbase/ActionWithInputVessel.h +++ b/src/vesselbase/ActionWithInputVessel.h @@ -48,19 +48,19 @@ class ActionWithInputVessel : public virtual Action { /// Registers the list of keywords static void registerKeywords( Keywords& keys ); explicit ActionWithInputVessel(const ActionOptions&); - virtual ~ActionWithInputVessel(){} + virtual ~ActionWithInputVessel() {} /// Calculate the numerical derivatives -/// N.B. only pass an ActionWithValue to this routine if you know exactly what you +/// N.B. only pass an ActionWithValue to this routine if you know exactly what you /// are doing. The default will be correct for the vast majority of cases virtual void calculateNumericalDerivatives( ActionWithValue* a=NULL ); /// Apply forces from the bridge void applyBridgeForces( const std::vector& bb ); /// Apply forces from the bridge - virtual void addBridgeForces( const std::vector& bb ){} + virtual void addBridgeForces( const std::vector& bb ) {} }; inline -Vessel* ActionWithInputVessel::getPntrToArgument(){ +Vessel* ActionWithInputVessel::getPntrToArgument() { return arguments; } diff --git a/src/vesselbase/ActionWithVessel.cpp b/src/vesselbase/ActionWithVessel.cpp index 02eb060f06..ebbe511a4f 100644 --- a/src/vesselbase/ActionWithVessel.cpp +++ b/src/vesselbase/ActionWithVessel.cpp @@ -32,16 +32,16 @@ #include "tools/Stopwatch.h" using namespace std; -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -void ActionWithVessel::registerKeywords(Keywords& keys){ +void ActionWithVessel::registerKeywords(Keywords& keys) { keys.add("hidden","TOL","this keyword can be used to speed up your calculation. When accumulating sums in which the individual " - "terms are numbers inbetween zero and one it is assumed that terms less than a certain tolerance " - "make only a small contribution to the sum. They can thus be safely ignored as can the the derivatives " - "wrt these small quantities."); + "terms are numbers inbetween zero and one it is assumed that terms less than a certain tolerance " + "make only a small contribution to the sum. They can thus be safely ignored as can the the derivatives " + "wrt these small quantities."); keys.add("hidden","MAXDERIVATIVES","The maximum number of derivatives that can be used when storing data. This controls when " - "we have to start using lowmem"); + "we have to start using lowmem"); keys.addFlag("SERIAL",false,"do the calculation in serial. Do not parallelize"); keys.addFlag("LOWMEM",false,"lower the memory requirements"); keys.addFlag("TIMINGS",false,"output information on the timings of the various parts of the calculation"); @@ -67,77 +67,77 @@ ActionWithVessel::ActionWithVessel(const ActionOptions&ao): if( keywords.exists("SERIAL") ) parseFlag("SERIAL",serial); else serial=true; if(serial)log.printf(" doing calculation in serial\n"); - if( keywords.exists("LOWMEM") ){ - plumed_assert( !keywords.exists("HIGHMEM") ); - parseFlag("LOWMEM",lowmem); - if(lowmem){ - log.printf(" lowering memory requirements\n"); - dertime_can_be_off=true; - } - } - if( keywords.exists("HIGHMEM") ){ - plumed_assert( !keywords.exists("LOWMEM") ); - bool highmem; parseFlag("HIGHMEM",highmem); - lowmem=!highmem; - if(!lowmem) log.printf(" increasing the memory requirements\n"); + if( keywords.exists("LOWMEM") ) { + plumed_assert( !keywords.exists("HIGHMEM") ); + parseFlag("LOWMEM",lowmem); + if(lowmem) { + log.printf(" lowering memory requirements\n"); + dertime_can_be_off=true; + } + } + if( keywords.exists("HIGHMEM") ) { + plumed_assert( !keywords.exists("LOWMEM") ); + bool highmem; parseFlag("HIGHMEM",highmem); + lowmem=!highmem; + if(!lowmem) log.printf(" increasing the memory requirements\n"); } - tolerance=nl_tolerance=epsilon; + tolerance=nl_tolerance=epsilon; if( keywords.exists("TOL") ) parse("TOL",tolerance); - if( tolerance>epsilon){ - log.printf(" Ignoring contributions less than %f \n",tolerance); + if( tolerance>epsilon) { + log.printf(" Ignoring contributions less than %f \n",tolerance); } parseFlag("TIMINGS",timers); stopwatch.start(); stopwatch.pause(); } -ActionWithVessel::~ActionWithVessel(){ - for(unsigned i=0;i(vv); - if( fv ){ - std::string mylabel=Vessel::transformName( name ); - plumed_massert( keywords.outputComponentExists(mylabel,false), "a description of the value calculated by vessel " + name + " has not been added to the manual"); - } + if( fv ) { + std::string mylabel=Vessel::transformName( name ); + plumed_massert( keywords.outputComponentExists(mylabel,false), "a description of the value calculated by vessel " + name + " has not been added to the manual"); + } addVessel(vv); } -void ActionWithVessel::addVessel( Vessel* vv ){ +void ActionWithVessel::addVessel( Vessel* vv ) { ShortcutVessel* sv=dynamic_cast(vv); - if(!sv){ vv->checkRead(); functions.push_back(vv); } + if(!sv) { vv->checkRead(); functions.push_back(vv); } else { delete sv; return; } StoreDataVessel* mm=dynamic_cast( vv ); if( mydata && mm ) error("cannot have more than one StoreDataVessel in one action"); else if( mm ) mydata=mm; - else dertime_can_be_off=false; + else dertime_can_be_off=false; } -BridgeVessel* ActionWithVessel::addBridgingVessel( ActionWithVessel* tome ){ - VesselOptions da("","",0,"",this); +BridgeVessel* ActionWithVessel::addBridgingVessel( ActionWithVessel* tome ) { + VesselOptions da("","",0,"",this); BridgeVessel* bv=new BridgeVessel(da); bv->setOutputAction( tome ); tome->actionIsBridged=true; dertime_can_be_off=false; functions.push_back( dynamic_cast(bv) ); resizeFunctions(); - return bv; + return bv; } -StoreDataVessel* ActionWithVessel::buildDataStashes( ActionWithVessel* actionThatUses ){ - if(mydata){ - if( actionThatUses ) mydata->addActionThatUses( actionThatUses ); - return mydata; - } - +StoreDataVessel* ActionWithVessel::buildDataStashes( ActionWithVessel* actionThatUses ) { + if(mydata) { + if( actionThatUses ) mydata->addActionThatUses( actionThatUses ); + return mydata; + } + VesselOptions da("","",0,"",this); StoreDataVessel* mm=new StoreDataVessel(da); if( actionThatUses ) mm->addActionThatUses( actionThatUses ); @@ -149,86 +149,86 @@ StoreDataVessel* ActionWithVessel::buildDataStashes( ActionWithVessel* actionTha return mydata; } -void ActionWithVessel::addTaskToList( const unsigned& taskCode ){ - fullTaskList.push_back( taskCode ); taskFlags.push_back(0); +void ActionWithVessel::addTaskToList( const unsigned& taskCode ) { + fullTaskList.push_back( taskCode ); taskFlags.push_back(0); plumed_assert( fullTaskList.size()==taskFlags.size() ); } -void ActionWithVessel::readVesselKeywords(){ +void ActionWithVessel::readVesselKeywords() { // Set maxderivatives if it is too big if( maxderivatives>getNumberOfDerivatives() ) maxderivatives=getNumberOfDerivatives(); // Loop over all keywords find the vessels and create appropriate functions - for(unsigned i=0;i0 ) resizeFunctions(); } -void ActionWithVessel::resizeFunctions(){ - for(unsigned i=0;iresize(); +void ActionWithVessel::resizeFunctions() { + for(unsigned i=0; iresize(); } -void ActionWithVessel::needsDerivatives(){ +void ActionWithVessel::needsDerivatives() { // Turn on the derivatives and resize - noderiv=false; resizeFunctions(); + noderiv=false; resizeFunctions(); // Setting contributors unlocked here ensures that link cells are ignored contributorsAreUnlocked=true; contributorsAreUnlocked=false; // And turn on the derivatives in all actions on which we are dependent - for(unsigned i=0;i( getDependencies()[i] ); - if(vv) vv->needsDerivatives(); + for(unsigned i=0; i( getDependencies()[i] ); + if(vv) vv->needsDerivatives(); } } -void ActionWithVessel::lockContributors(){ +void ActionWithVessel::lockContributors() { nactive_tasks = 0; - for(unsigned i=0;i0 ) nactive_tasks++; + for(unsigned i=0; i0 ) nactive_tasks++; } unsigned n=0; partialTaskList.resize( nactive_tasks ); - indexOfTaskInFullList.resize( nactive_tasks ); - for(unsigned i=0;i0 ){ - partialTaskList[n] = fullTaskList[i]; - indexOfTaskInFullList[n]=i; - n++; - } + indexOfTaskInFullList.resize( nactive_tasks ); + for(unsigned i=0; i0 ) { + partialTaskList[n] = fullTaskList[i]; + indexOfTaskInFullList[n]=i; + n++; + } } plumed_dbg_assert( n==nactive_tasks ); - for(unsigned i=0;i( functions[i] ); - if( bb ) bb->copyTaskFlags(); + for(unsigned i=0; i( functions[i] ); + if( bb ) bb->copyTaskFlags(); } // Resize mydata to accomodate all active tasks if( mydata ) mydata->resize(); contributorsAreUnlocked=false; } -void ActionWithVessel::deactivateAllTasks(){ +void ActionWithVessel::deactivateAllTasks() { contributorsAreUnlocked=true; nactive_tasks = 0; taskFlags.assign(taskFlags.size(),0); } @@ -237,26 +237,26 @@ bool ActionWithVessel::taskIsCurrentlyActive( const unsigned& index ) const { plumed_dbg_assert( index0); } -void ActionWithVessel::doJobsRequiredBeforeTaskList(){ +void ActionWithVessel::doJobsRequiredBeforeTaskList() { // Do any preparatory stuff for functions - for(unsigned j=0;jprepare(); + for(unsigned j=0; jprepare(); } -unsigned ActionWithVessel::getSizeOfBuffer( unsigned& bufsize ){ - for(unsigned i=0;isetBufferStart( bufsize ); +unsigned ActionWithVessel::getSizeOfBuffer( unsigned& bufsize ) { + for(unsigned i=0; isetBufferStart( bufsize ); if( buffer.size()!=bufsize ) buffer.resize( bufsize ); - if( mydata ){ - unsigned dsize=mydata->getSizeOfDerivativeList(); - if( der_list.size()!=dsize ) der_list.resize( dsize ); + if( mydata ) { + unsigned dsize=mydata->getSizeOfDerivativeList(); + if( der_list.size()!=dsize ) der_list.resize( dsize ); } return bufsize; } -void ActionWithVessel::runAllTasks(){ +void ActionWithVessel::runAllTasks() { plumed_massert( !contributorsAreUnlocked && functions.size()>0, "you must have a call to readVesselKeywords somewhere" ); unsigned stride=comm.Get_size(); unsigned rank=comm.Get_rank(); - if(serial){ stride=1; rank=0; } + if(serial) { stride=1; rank=0; } // Make sure jobs are done if(timers) stopwatch.start("1 Prepare Tasks"); @@ -269,55 +269,55 @@ void ActionWithVessel::runAllTasks(){ if( nt==0 || !threadSafe() ) nt=1; // Get size for buffer - unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); + unsigned bsize=0, bufsize=getSizeOfBuffer( bsize ); // Clear buffer buffer.assign( buffer.size(), 0.0 ); // Switch off calculation of derivatives in main loop if( dertime_can_be_off ) dertime=false; // std::vector der_list; - // if( mydata ) der_list.resize( mydata->getSizeOfDerivativeList(), 0 ); + // if( mydata ) der_list.resize( mydata->getSizeOfDerivativeList(), 0 ); // Build storage stuff for loop // std::vector buffer( bufsize, 0.0 ); if(timers) stopwatch.start("2 Loop over tasks"); -#pragma omp parallel num_threads(nt) -{ - std::vector omp_buffer; - if( nt>1 ) omp_buffer.resize( bufsize, 0.0 ); - MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); - MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); - myvals.clearAll(); bvals.clearAll(); - -#pragma omp for nowait - for(unsigned i=rank;i omp_buffer; + if( nt>1 ) omp_buffer.resize( bufsize, 0.0 ); + MultiValue myvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + MultiValue bvals( getNumberOfQuantities(), getNumberOfDerivatives() ); + myvals.clearAll(); bvals.clearAll(); + + #pragma omp for nowait + for(unsigned i=rank; i1 ){ - calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, omp_buffer, der_list ); + if( nt>1 ) { + calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, omp_buffer, der_list ); } else { - calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer, der_list ); + calculateAllVessels( indexOfTaskInFullList[i], myvals, bvals, buffer, der_list ); } // Clear the value myvals.clearAll(); + } + #pragma omp critical + if(nt>1) for(unsigned i=0; i1) for(unsigned i=0;i0 ) comm.Sum( buffer ); // MPI Gather index stores - if( mydata && !lowmem && !noderiv ){ - comm.Sum( der_list ); mydata->setActiveValsAndDerivatives( der_list ); + if( mydata && !lowmem && !noderiv ) { + comm.Sum( der_list ); mydata->setActiveValsAndDerivatives( der_list ); } // Update the elements that are makign contributions to the sum here // this causes problems if we do it in prepare @@ -342,22 +342,22 @@ void ActionWithVessel::transformBridgedDerivatives( const unsigned& current, Mul plumed_error(); } -void ActionWithVessel::calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector& buffer, std::vector& der_list ){ - for(unsigned j=0;jcalculate( taskCode, functions[j]->transformDerivatives(taskCode, myvals, bvals), buffer, der_list ); - if( !actionIsBridged ) bvals.clearAll(); +void ActionWithVessel::calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector& buffer, std::vector& der_list ) { + for(unsigned j=0; jcalculate( taskCode, functions[j]->transformDerivatives(taskCode, myvals, bvals), buffer, der_list ); + if( !actionIsBridged ) bvals.clearAll(); } return; } -void ActionWithVessel::finishComputations( const std::vector& buffer ){ +void ActionWithVessel::finishComputations( const std::vector& buffer ) { // Set the final value of the function - for(unsigned j=0;jfinish( buffer ); + for(unsigned j=0; jfinish( buffer ); } -bool ActionWithVessel::getForcesFromVessels( std::vector& forcesToApply ){ +bool ActionWithVessel::getForcesFromVessels( std::vector& forcesToApply ) { #ifndef NDEBUG if( forcesToApply.size()>0 ) plumed_dbg_assert( forcesToApply.size()==getNumberOfDerivatives() ); #endif @@ -365,26 +365,26 @@ bool ActionWithVessel::getForcesFromVessels( std::vector& forcesToApply forcesToApply.assign( forcesToApply.size(),0.0 ); bool wasforced=false; - for(unsigned i=0;iapplyForce( tmpforces )) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforces )) ) { + wasforced=true; + for(unsigned j=0; jgetName().find(mynam)!=std::string::npos ){ - if( target<0 ) target=i; - else error("found more than one " + mynam + " object in action"); - } + for(unsigned i=0; igetName().find(mynam)!=std::string::npos ) { + if( target<0 ) target=i; + else error("found more than one " + mynam + " object in action"); + } } return functions[target]; } diff --git a/src/vesselbase/ActionWithVessel.h b/src/vesselbase/ActionWithVessel.h index a20954804f..8134037649 100644 --- a/src/vesselbase/ActionWithVessel.h +++ b/src/vesselbase/ActionWithVessel.h @@ -29,11 +29,11 @@ #include "tools/MultiValue.h" #include -namespace PLMD{ +namespace PLMD { class Value; class Stopwatch; -namespace vesselbase{ +namespace vesselbase { class Vessel; class BridgeVessel; @@ -46,13 +46,13 @@ times. This is used in PLMD::MultiColvar. */ class ActionWithVessel : public virtual Action { -friend class Vessel; -friend class ShortcutVessel; -friend class FunctionVessel; -friend class StoreDataVessel; -friend class BridgeVessel; -friend class ActionWithInputVessel; -friend class OrderingVessel; + friend class Vessel; + friend class ShortcutVessel; + friend class FunctionVessel; + friend class StoreDataVessel; + friend class BridgeVessel; + friend class ActionWithInputVessel; + friend class OrderingVessel; private: /// Do all calculations in serial bool serial; @@ -64,7 +64,7 @@ friend class OrderingVessel; bool actionIsBridged; /// The maximum number of derivatives we can use before we need to invoke lowmem unsigned maxderivatives; -/// The tolerance on the accumulators +/// The tolerance on the accumulators double tolerance; /// Tolerance for quantities being put in neighbor lists double nl_tolerance; @@ -120,7 +120,7 @@ friend class OrderingVessel; void runAllTasks(); /// Resize all the functions when the number of derivatives change void resizeFunctions(); -/// This loops over all the vessels calculating them and also +/// This loops over all the vessels calculating them and also /// sets all the element derivatives equal to zero void calculateAllVessels( const unsigned& taskCode, MultiValue& myvals, MultiValue& bvals, std::vector& buffer, std::vector& der_list ); /// Retrieve the forces from all the vessels (used in apply) @@ -156,14 +156,14 @@ friend class OrderingVessel; virtual bool isPeriodic()=0; /// What are the domains of the base quantities virtual void retrieveDomain( std::string& min, std::string& max); -/// Get the number of derivatives for final calculated quantity +/// Get the number of derivatives for final calculated quantity virtual unsigned getNumberOfDerivatives()=0; /// Get the number of quantities that are calculated during each task virtual unsigned getNumberOfQuantities() const ; /// Get the number of vessels unsigned getNumberOfVessels() const; /// Get a pointer to the ith vessel - Vessel* getPntrToVessel( const unsigned& i ); + Vessel* getPntrToVessel( const unsigned& i ); /// Do any jobs that are required before the task list is undertaken virtual void doJobsRequiredBeforeTaskList(); /// Get the full size of the taskList dynamic list @@ -175,13 +175,13 @@ friend class OrderingVessel; /// Get the ith of the currently active tasks unsigned getActiveTask( const unsigned& ii ) const ; /// Calculate one of the functions in the distribution - virtual void performTask( const unsigned& , const unsigned& , MultiValue& ) const=0; + virtual void performTask( const unsigned&, const unsigned&, MultiValue& ) const=0; /// Do the task if we have a bridge virtual void transformBridgedDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) const; /// Ensure that data required in other vessels is stored StoreDataVessel* buildDataStashes( ActionWithVessel* actionThatUses ); /// Apply forces from bridge vessel - this is rarely used - currently only in ActionVolume - virtual void applyBridgeForces( const std::vector& bb ){ plumed_error(); } + virtual void applyBridgeForces( const std::vector& bb ) { plumed_error(); } /// These are overwritten in MultiColvarFunction // virtual void activateIndexes( const unsigned&, const unsigned&, const std::vector& ){} /// Return a particular named vessel @@ -216,7 +216,7 @@ unsigned ActionWithVessel::getNumberOfQuantities() const { } inline -Vessel* ActionWithVessel::getPntrToVessel( const unsigned& i ){ +Vessel* ActionWithVessel::getPntrToVessel( const unsigned& i ) { plumed_dbg_assert( iisPeriodic() ) error("MIN is not a meaningful option for periodic variables"); parse("BETA",beta); usetol=true; } -std::string AltMin::value_descriptor(){ +std::string AltMin::value_descriptor() { std::string str_beta; Tools::convert( beta, str_beta ); return "the minimum value. Beta is equal to " + str_beta; } @@ -69,9 +69,9 @@ double AltMin::calcTransform( const double& val, double& dv ) const { double f = exp( -beta*val ); dv = -beta*f; return f; } -double AltMin::finalTransform( const double& val, double& dv ){ - dv = - 1.0 /(beta*val); return -std::log( val ) / beta; -} +double AltMin::finalTransform( const double& val, double& dv ) { + dv = - 1.0 /(beta*val); return -std::log( val ) / beta; +} } } diff --git a/src/vesselbase/AveragingVessel.cpp b/src/vesselbase/AveragingVessel.cpp index 7d8933bd6c..a3bbb4fd79 100644 --- a/src/vesselbase/AveragingVessel.cpp +++ b/src/vesselbase/AveragingVessel.cpp @@ -25,35 +25,35 @@ namespace PLMD { namespace vesselbase { -void AveragingVessel::registerKeywords( Keywords& keys ){ +void AveragingVessel::registerKeywords( Keywords& keys ) { Vessel::registerKeywords( keys ); } AveragingVessel::AveragingVessel( const vesselbase::VesselOptions& vo ): -Vessel(vo), -wascleared(true) + Vessel(vo), + wascleared(true) { ActionWithAveraging* myav = dynamic_cast( getAction() ); plumed_assert( myav ); unormalised = myav->unormalised; } -void AveragingVessel::finish( const std::vector& buffer ){ - wascleared=false; for(unsigned i=1;i& buffer ) { + wascleared=false; for(unsigned i=1; i data; + std::vector data; protected: /// Set the size of the data vector - void setDataSize( const unsigned& size ); + void setDataSize( const unsigned& size ); /// Set an element of the data array - void setDataElement( const unsigned& myelem, const double& value ); + void setDataElement( const unsigned& myelem, const double& value ); /// Add some value to an element of the data array - void addDataElement( const unsigned& myelem, const double& value ); + void addDataElement( const unsigned& myelem, const double& value ); /// Get the value of one of the data element - double getDataElement( const unsigned& myelem ) const ; + double getDataElement( const unsigned& myelem ) const ; /// Are we averaging the data - bool noAverage() const { return unormalised; } + bool noAverage() const { return unormalised; } public: /// keywords - static void registerKeywords( Keywords& keys ); + static void registerKeywords( Keywords& keys ); /// Constructor - explicit AveragingVessel( const vesselbase::VesselOptions& ); + explicit AveragingVessel( const vesselbase::VesselOptions& ); /// Copy data from an accumulated buffer into the grid - virtual void finish( const std::vector& ); + virtual void finish( const std::vector& ); /// Was the grid cleared on the last step - bool wasreset() const ; + bool wasreset() const ; /// Clear all the data stored on the grid - virtual void clear(); + virtual void clear(); /// Reset the grid so that it is cleared at start of next time it is calculated - virtual void reset(); + virtual void reset(); /// Functions for dealing with normalisation constant - void setNorm( const double& snorm ); - double getNorm() const ; - virtual bool applyForce( std::vector& forces ){ return false; } + void setNorm( const double& snorm ); + double getNorm() const ; + virtual bool applyForce( std::vector& forces ) { return false; } }; inline -void AveragingVessel::setDataElement( const unsigned& myelem, const double& value ){ - plumed_dbg_assert( myelem<1+data.size() ); - wascleared=false; data[1+myelem]=value; +void AveragingVessel::setDataElement( const unsigned& myelem, const double& value ) { + plumed_dbg_assert( myelem<1+data.size() ); + wascleared=false; data[1+myelem]=value; } inline -void AveragingVessel::addDataElement( const unsigned& myelem, const double& value ){ - plumed_dbg_assert( myelem<1+data.size() ); - wascleared=false; data[1+myelem]+=value; +void AveragingVessel::addDataElement( const unsigned& myelem, const double& value ) { + plumed_dbg_assert( myelem<1+data.size() ); + wascleared=false; data[1+myelem]+=value; } inline double AveragingVessel::getDataElement( const unsigned& myelem ) const { - plumed_dbg_assert( myelem0 ); data[0]=snorm; } diff --git a/src/vesselbase/Between.cpp b/src/vesselbase/Between.cpp index 3a00b2fa70..ac02823d0f 100644 --- a/src/vesselbase/Between.cpp +++ b/src/vesselbase/Between.cpp @@ -28,52 +28,52 @@ namespace vesselbase { PLUMED_REGISTER_VESSEL(Between,"BETWEEN") -void Between::registerKeywords( Keywords& keys ){ +void Between::registerKeywords( Keywords& keys ) { FunctionVessel::registerKeywords( keys ); HistogramBead::registerKeywords( keys ); keys.addFlag("NORM",false,"calculate the fraction of values rather than the number"); } -void Between::reserveKeyword( Keywords& keys ){ +void Between::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","BETWEEN","calculate the number of values that are within a certain range. " - "These quantities are calculated using kernel density estimation as described on " - "\\ref histogrambead."); + "These quantities are calculated using kernel density estimation as described on " + "\\ref histogrambead."); keys.addOutputComponent("between","BETWEEN","the number/fraction of values within a certain range. This is calculated using one of the " - "formula described in the description of the keyword so as to make it continuous. " - "You can calculate this quantity multiple times using different parameters."); + "formula described in the description of the keyword so as to make it continuous. " + "You can calculate this quantity multiple times using different parameters."); } Between::Between( const VesselOptions& da ) : -FunctionVessel(da) -{ + FunctionVessel(da) +{ usetol=true; bool isPeriodic=getAction()->isPeriodic(); double min, max; std::string str_min, str_max; - if( isPeriodic ){ - getAction()->retrieveDomain( str_min, str_max ); - Tools::convert(str_min,min); Tools::convert(str_max,max); + if( isPeriodic ) { + getAction()->retrieveDomain( str_min, str_max ); + Tools::convert(str_min,min); Tools::convert(str_max,max); } - parseFlag("NORM",norm); std::string errormsg; + parseFlag("NORM",norm); std::string errormsg; hist.set( getAllInput(),errormsg ); if( !isPeriodic ) hist.isNotPeriodic(); - else hist.isPeriodic( min, max ); + else hist.isPeriodic( min, max ); if( errormsg.size()!=0 ) error( errormsg ); } -std::string Between::value_descriptor(){ +std::string Between::value_descriptor() { if(norm) return "the fraction of values " + hist.description(); return "the number of values " + hist.description(); } double Between::calcTransform( const double& val, double& dv ) const { - double f = hist.calculate(val, dv); return f; + double f = hist.calculate(val, dv); return f; } -double Between::getCutoff(){ +double Between::getCutoff() { return std::numeric_limits::max(); -} +} } } diff --git a/src/vesselbase/BridgeVessel.cpp b/src/vesselbase/BridgeVessel.cpp index 18ba59adb8..043f684405 100644 --- a/src/vesselbase/BridgeVessel.cpp +++ b/src/vesselbase/BridgeVessel.cpp @@ -28,31 +28,31 @@ namespace PLMD { namespace vesselbase { BridgeVessel::BridgeVessel( const VesselOptions& da ): -Vessel(da), -inum(0), + Vessel(da), + inum(0), // in_normal_calculate(false) -myOutputAction(NULL), -myOutputValues(NULL), -my_tmp_val(0,0) + myOutputAction(NULL), + myOutputValues(NULL), + my_tmp_val(0,0) { } -void BridgeVessel::resize(){ - if( myOutputAction->checkNumericalDerivatives() ){ - mynumerical_values.resize( getAction()->getNumberOfDerivatives()*myOutputValues->getNumberOfComponents() ); - inum=0; +void BridgeVessel::resize() { + if( myOutputAction->checkNumericalDerivatives() ) { + mynumerical_values.resize( getAction()->getNumberOfDerivatives()*myOutputValues->getNumberOfComponents() ); + inum=0; } // This bit ensures that we can store data in a bridge function if needs be // Notice we need to resize der_list in the underlying action as this is called // from a bridge - if( myOutputAction->mydata ){ - unsigned dsize=(myOutputAction->mydata)->getSizeOfDerivativeList(); - if( getAction()->der_list.size()!=dsize ) getAction()->der_list.resize( dsize ); + if( myOutputAction->mydata ) { + unsigned dsize=(myOutputAction->mydata)->getSizeOfDerivativeList(); + if( getAction()->der_list.size()!=dsize ) getAction()->der_list.resize( dsize ); } unsigned tmp=0; resizeBuffer( myOutputAction->getSizeOfBuffer( tmp ) ); } -void BridgeVessel::setOutputAction( ActionWithVessel* myact ){ +void BridgeVessel::setOutputAction( ActionWithVessel* myact ) { ActionWithValue* checkme=dynamic_cast( getAction() ); plumed_massert( checkme, "vessel in bridge must inherit from ActionWithValue"); @@ -61,22 +61,22 @@ void BridgeVessel::setOutputAction( ActionWithVessel* myact ){ plumed_massert( myOutputValues, "bridging vessel must inherit from ActionWithValue"); } -std::string BridgeVessel::description(){ +std::string BridgeVessel::description() { plumed_merror("I shouldn't end up here"); } -void BridgeVessel::prepare(){ +void BridgeVessel::prepare() { myOutputAction->doJobsRequiredBeforeTaskList(); } -void BridgeVessel::setBufferStart( unsigned& start ){ +void BridgeVessel::setBufferStart( unsigned& start ) { unsigned tmp=myOutputAction->getSizeOfBuffer( start ); } -MultiValue& BridgeVessel::transformDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ){ +MultiValue& BridgeVessel::transformDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ) { if( outvals.getNumberOfValues()!=myOutputAction->getNumberOfQuantities() || - outvals.getNumberOfDerivatives()!=myOutputAction->getNumberOfDerivatives() ){ - outvals.resize( myOutputAction->getNumberOfQuantities(), myOutputAction->getNumberOfDerivatives() ); + outvals.getNumberOfDerivatives()!=myOutputAction->getNumberOfDerivatives() ) { + outvals.resize( myOutputAction->getNumberOfQuantities(), myOutputAction->getNumberOfDerivatives() ); } myOutputAction->transformBridgedDerivatives( current, invals, outvals ); return outvals; @@ -85,64 +85,64 @@ MultiValue& BridgeVessel::transformDerivatives( const unsigned& current, MultiVa void BridgeVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { // in_normal_calculate=true; if( myvals.get(0)getTolerance() ) return; - myOutputAction->calculateAllVessels( current, myvals, myvals, buffer, der_list ); - return; + myOutputAction->calculateAllVessels( current, myvals, myvals, buffer, der_list ); + return; } -void BridgeVessel::finish( const std::vector& buffer ){ +void BridgeVessel::finish( const std::vector& buffer ) { myOutputAction->finishComputations( buffer ); - if( myOutputAction->checkNumericalDerivatives() ){ - if ( inumgetNumberOfComponents();++i){ - mynumerical_values[inum]=myOutputValues->getOutputQuantity(i); - inum++; - } - plumed_dbg_assert( inum<=mynumerical_values.size() ); - } else { - plumed_assert( inum==mynumerical_values.size() ); - } - } + if( myOutputAction->checkNumericalDerivatives() ) { + if ( inumgetNumberOfComponents(); ++i) { + mynumerical_values[inum]=myOutputValues->getOutputQuantity(i); + inum++; + } + plumed_dbg_assert( inum<=mynumerical_values.size() ); + } else { + plumed_assert( inum==mynumerical_values.size() ); + } + } } -void BridgeVessel::completeNumericalDerivatives(){ +void BridgeVessel::completeNumericalDerivatives() { unsigned nextra = myOutputAction->getNumberOfDerivatives() - getAction()->getNumberOfDerivatives(); Matrix tmpder( myOutputValues->getNumberOfComponents(), nextra ); ActionWithVessel* vval=dynamic_cast( myOutputAction ); - for(unsigned i=0;ibridgeVariable=i; getAction()->calculate(); - for(int j=0;jgetNumberOfComponents();++j) tmpder(j,i) = myOutputValues->getOutputQuantity(j); + for(unsigned i=0; ibridgeVariable=i; getAction()->calculate(); + for(int j=0; jgetNumberOfComponents(); ++j) tmpder(j,i) = myOutputValues->getOutputQuantity(j); } - vval->bridgeVariable=nextra; getAction()->calculate(); + vval->bridgeVariable=nextra; getAction()->calculate(); plumed_assert( inum==mynumerical_values.size() ); inum=0; // Reset inum now that we have finished calling calculate std::vector base( myOutputValues->getNumberOfComponents() ); - for(int j=0;jgetNumberOfComponents();++j) base[j] = myOutputValues->getOutputQuantity(j); + for(int j=0; jgetNumberOfComponents(); ++j) base[j] = myOutputValues->getOutputQuantity(j); const double delta=sqrt(epsilon); ActionAtomistic* aa=dynamic_cast( getAction() ); unsigned nvals=myOutputValues->getNumberOfComponents(); - for(unsigned j=0;jcopyOutput(j) )->clearDerivatives(); - - if( aa ){ - ActionWithArguments* aarg=dynamic_cast( getAction() ); - plumed_assert( !aarg ); Tensor box=aa->getBox(); - unsigned natoms=aa->getNumberOfAtoms(); - for(unsigned j=0;jcopyOutput(j) )->get(); - if( ( myOutputValues->copyOutput(j) )->getNumberOfDerivatives()>0 ){ - for(unsigned i=0;i<3*natoms;++i){ - double d=( mynumerical_values[i*nvals+j] - ref)/delta; - ( myOutputValues->copyOutput(j) )->addDerivative(i,d); - } - Tensor virial; - for(int i=0;i<3;i++) for(int k=0;k<3;k++){ - virial(i,k)=( mynumerical_values[ nvals*(3*natoms + 3*i + k) + j ]-ref)/delta; - } - virial=-matmul(box.transpose(),virial); - for(int i=0;i<3;i++) for(int k=0;k<3;k++) ( myOutputValues->copyOutput(j) )->addDerivative(3*natoms+3*k+i,virial(k,i)); + for(unsigned j=0; jcopyOutput(j) )->clearDerivatives(); + + if( aa ) { + ActionWithArguments* aarg=dynamic_cast( getAction() ); + plumed_assert( !aarg ); Tensor box=aa->getBox(); + unsigned natoms=aa->getNumberOfAtoms(); + for(unsigned j=0; jcopyOutput(j) )->get(); + if( ( myOutputValues->copyOutput(j) )->getNumberOfDerivatives()>0 ) { + for(unsigned i=0; i<3*natoms; ++i) { + double d=( mynumerical_values[i*nvals+j] - ref)/delta; + ( myOutputValues->copyOutput(j) )->addDerivative(i,d); + } + Tensor virial; + for(int i=0; i<3; i++) for(int k=0; k<3; k++) { + virial(i,k)=( mynumerical_values[ nvals*(3*natoms + 3*i + k) + j ]-ref)/delta; } + virial=-matmul(box.transpose(),virial); + for(int i=0; i<3; i++) for(int k=0; k<3; k++) ( myOutputValues->copyOutput(j) )->addDerivative(3*natoms+3*k+i,virial(k,i)); } + } } else { - plumed_merror("not implemented or tested yet"); + plumed_merror("not implemented or tested yet"); // unsigned nder=myOutputAction->getNumberOfDerivatives(); // for(unsigned j=0;jcopyOutput(j) )->get(); @@ -154,37 +154,37 @@ void BridgeVessel::completeNumericalDerivatives(){ // } } // Add the derivatives wrt to the local quantities we are working with - for(unsigned j=0;jgetNumberOfDerivatives();igetNumberOfDerivatives();++i){ - ( myOutputValues->copyOutput(j) )->addDerivative( i, (tmpder(j,k)-base[j])/sqrt(epsilon) ); k++; - } + for(unsigned j=0; jgetNumberOfDerivatives(); igetNumberOfDerivatives(); ++i) { + ( myOutputValues->copyOutput(j) )->addDerivative( i, (tmpder(j,k)-base[j])/sqrt(epsilon) ); k++; + } } } -bool BridgeVessel::applyForce( std::vector& outforces ){ +bool BridgeVessel::applyForce( std::vector& outforces ) { bool hasforce=false; outforces.assign(outforces.size(),0.0); unsigned ndertot = myOutputAction->getNumberOfDerivatives(); unsigned nextra = ndertot - getAction()->getNumberOfDerivatives(); std::vector forces( ndertot ), eforces( nextra, 0.0 ); - for(unsigned i=0;igetNumberOfVessels();++i){ - if( ( myOutputAction->getPntrToVessel(i) )->applyForce( forces ) ){ - hasforce=true; - for(unsigned j=0;jgetNumberOfVessels(); ++i) { + if( ( myOutputAction->getPntrToVessel(i) )->applyForce( forces ) ) { + hasforce=true; + for(unsigned j=0; japplyBridgeForces( eforces ); return hasforce; } -void BridgeVessel::copyTaskFlags(){ +void BridgeVessel::copyTaskFlags() { myOutputAction->deactivateAllTasks(); - for(unsigned i=0;inactive_tasks;++i) myOutputAction->taskFlags[ getAction()->indexOfTaskInFullList[i] ] = 1; + for(unsigned i=0; inactive_tasks; ++i) myOutputAction->taskFlags[ getAction()->indexOfTaskInFullList[i] ] = 1; myOutputAction->lockContributors(); } -MultiValue& BridgeVessel::getTemporyMultiValue(){ +MultiValue& BridgeVessel::getTemporyMultiValue() { return my_tmp_val; } diff --git a/src/vesselbase/BridgeVessel.h b/src/vesselbase/BridgeVessel.h index 6e0d4f6856..2ae248c838 100644 --- a/src/vesselbase/BridgeVessel.h +++ b/src/vesselbase/BridgeVessel.h @@ -35,7 +35,7 @@ namespace vesselbase { /** \ingroup TOOLBOX This class allows you to calculate the vessel in one ActionWithVessel. The user thinks -it is created in a different Action however. At the moment this is used for region +it is created in a different Action however. At the moment this is used for region */ class BridgeVessel : public Vessel { @@ -57,13 +57,13 @@ class BridgeVessel : public Vessel { ActionWithVessel* getOutputAction(); /// Setup the action we are outputting to void setOutputAction( ActionWithVessel* myOutputAction ); -/// Apply some force +/// Apply some force bool applyForce( std::vector& forces ); /// Should not be called std::string description(); /// Jobs to do before the task list starts void prepare(); -/// Set the start of the buffer +/// Set the start of the buffer void setBufferStart( unsigned& start ); /// This transforms the derivatives using the output value MultiValue& transformDerivatives( const unsigned& current, MultiValue& invals, MultiValue& outvals ); @@ -76,11 +76,11 @@ class BridgeVessel : public Vessel { /// Set the task flags in the bridged class the same as in the original class void copyTaskFlags(); /// Return a tempory multi value - we do this so as to avoid vector resizing - MultiValue& getTemporyMultiValue(); + MultiValue& getTemporyMultiValue(); }; inline -ActionWithVessel* BridgeVessel::getOutputAction(){ +ActionWithVessel* BridgeVessel::getOutputAction() { return myOutputAction; } diff --git a/src/vesselbase/FunctionVessel.cpp b/src/vesselbase/FunctionVessel.cpp index 11dd055a60..13b84e6156 100644 --- a/src/vesselbase/FunctionVessel.cpp +++ b/src/vesselbase/FunctionVessel.cpp @@ -22,80 +22,80 @@ #include "FunctionVessel.h" #include "core/ActionWithValue.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -void FunctionVessel::registerKeywords( Keywords& keys ){ +void FunctionVessel::registerKeywords( Keywords& keys ) { ValueVessel::registerKeywords( keys ); } FunctionVessel::FunctionVessel( const VesselOptions& da ): -ValueVessel(da), -norm(false), -usetol(false) + ValueVessel(da), + norm(false), + usetol(false) { diffweight=getAction()->weightHasDerivatives; } -void FunctionVessel::resize(){ - if( getAction()->derivativesAreRequired() ){ - unsigned nderivatives=getAction()->getNumberOfDerivatives(); - getFinalValue()->resizeDerivatives( nderivatives ); - resizeBuffer( (1+nderivatives)*2 ); - diffweight=getAction()->weightHasDerivatives; +void FunctionVessel::resize() { + if( getAction()->derivativesAreRequired() ) { + unsigned nderivatives=getAction()->getNumberOfDerivatives(); + getFinalValue()->resizeDerivatives( nderivatives ); + resizeBuffer( (1+nderivatives)*2 ); + diffweight=getAction()->weightHasDerivatives; } else { - resizeBuffer(2); - diffweight=false; // Don't need to worry about differentiable weights if no derivatives + resizeBuffer(2); + diffweight=false; // Don't need to worry about differentiable weights if no derivatives } } void FunctionVessel::calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const { unsigned nderivatives=getFinalValue()->getNumberOfDerivatives(); - double weight=myvals.get(0); - plumed_dbg_assert( weight>=getTolerance() ); + double weight=myvals.get(0); + plumed_dbg_assert( weight>=getTolerance() ); // This deals with the value double dval, f=calcTransform( myvals.get(mycomp), dval ); - if( norm ){ - if( usetol && weightderivativesAreRequired() && fabs(dval)>0.0 ) myvals.chainRule( mycomp, 0, 1, 0, weight*dval, bufstart, buffer ); return; } -double FunctionVessel::calcTransform( const double& , double& ) const { - plumed_error(); return 1.0; +double FunctionVessel::calcTransform( const double&, double& ) const { + plumed_error(); return 1.0; } -void FunctionVessel::finish( const std::vector& buffer ){ +void FunctionVessel::finish( const std::vector& buffer ) { unsigned nderivatives=getFinalValue()->getNumberOfDerivatives(); - if( norm && diffweight ){ - double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; - getFinalValue()->set( val / weight ); - for(unsigned i=0;iaddDerivative( i, buffer[bufstart+1+i]/weight - val*buffer[bufstart+1+nderivatives+1+i]/(weight*weight) ); - } - } else if( norm ){ - double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; - getFinalValue()->set( val / weight ); - for(unsigned i=0;iaddDerivative( i, buffer[bufstart+1+i]/weight ); + if( norm && diffweight ) { + double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; + getFinalValue()->set( val / weight ); + for(unsigned i=0; iaddDerivative( i, buffer[bufstart+1+i]/weight - val*buffer[bufstart+1+nderivatives+1+i]/(weight*weight) ); + } + } else if( norm ) { + double dv, val=finalTransform( buffer[bufstart], dv), weight=buffer[bufstart+1+nderivatives]; + getFinalValue()->set( val / weight ); + for(unsigned i=0; iaddDerivative( i, buffer[bufstart+1+i]/weight ); } else { - double dv, val=finalTransform( buffer[bufstart], dv); getFinalValue()->set( val ); - for(unsigned i=0;iaddDerivative( i, dv*buffer[bufstart+1+i] ); + double dv, val=finalTransform( buffer[bufstart], dv); getFinalValue()->set( val ); + for(unsigned i=0; iaddDerivative( i, dv*buffer[bufstart+1+i] ); } } -double FunctionVessel::finalTransform( const double& val, double& dv ){ +double FunctionVessel::finalTransform( const double& val, double& dv ) { dv=1.0; return val; } diff --git a/src/vesselbase/FunctionVessel.h b/src/vesselbase/FunctionVessel.h index 920d668b4c..b6fd05d559 100644 --- a/src/vesselbase/FunctionVessel.h +++ b/src/vesselbase/FunctionVessel.h @@ -29,13 +29,13 @@ #include "core/Value.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { /** \ingroup TOOLBOX Objects that inherit from FunctionVessel can be used (in tandem with PLMD::vesselbase::ActionWithVessel) to calculate functions of the form \f$\prod_k H_k[ \sum_j \prod_i g_i(x) ]\f$. They should take in a series of values -and return one single value. +and return one single value. */ class FunctionVessel : public ValueVessel { diff --git a/src/vesselbase/Highest.cpp b/src/vesselbase/Highest.cpp index 727a9fd950..437f681ec7 100644 --- a/src/vesselbase/Highest.cpp +++ b/src/vesselbase/Highest.cpp @@ -23,7 +23,7 @@ #include "VesselRegister.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class Highest : public OrderingVessel { public: @@ -31,30 +31,30 @@ class Highest : public OrderingVessel { static void reserveKeyword( Keywords& keys ); explicit Highest( const VesselOptions& da ); std::string value_descriptor(); - bool compare( const double& , const double& ); + bool compare( const double&, const double& ); }; PLUMED_REGISTER_VESSEL(Highest,"HIGHEST") -void Highest::registerKeywords( Keywords& keys ){ +void Highest::registerKeywords( Keywords& keys ) { OrderingVessel::registerKeywords( keys ); } -void Highest::reserveKeyword( Keywords& keys ){ +void Highest::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","HIGHEST","this flag allows you to recover the highest of these variables."); keys.addOutputComponent("highest","HIGHEST","the lowest of the quantitities calculated by this action"); } Highest::Highest( const VesselOptions& da ) : -OrderingVessel(da) + OrderingVessel(da) { } -std::string Highest::value_descriptor(){ +std::string Highest::value_descriptor() { return "the highest of the individual colvar values"; } -bool Highest::compare( const double& val1, const double& val2 ){ +bool Highest::compare( const double& val1, const double& val2 ) { return val1>val2; } diff --git a/src/vesselbase/Histogram.cpp b/src/vesselbase/Histogram.cpp index 2e3fae75d2..eb91f0ce2a 100644 --- a/src/vesselbase/Histogram.cpp +++ b/src/vesselbase/Histogram.cpp @@ -23,8 +23,8 @@ #include "VesselRegister.h" #include "ShortcutVessel.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { class Histogram : public ShortcutVessel { public: @@ -35,25 +35,25 @@ class Histogram : public ShortcutVessel { PLUMED_REGISTER_VESSEL(Histogram,"HISTOGRAM") -void Histogram::registerKeywords( Keywords& keys ){ +void Histogram::registerKeywords( Keywords& keys ) { ShortcutVessel::registerKeywords( keys ); HistogramBead::registerKeywords( keys ); keys.add("compulsory","NBINS","The number of equal width bins you want to divide the range into"); - keys.addFlag("NORM",false,"calculate the fraction of values rather than the number"); + keys.addFlag("NORM",false,"calculate the fraction of values rather than the number"); } -void Histogram::reserveKeyword( Keywords& keys ){ +void Histogram::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","HISTOGRAM","calculate a discretized histogram of the distribution of values. " - "This shortcut allows you to calculates NBIN quantites like BETWEEN."); + "This shortcut allows you to calculates NBIN quantites like BETWEEN."); } Histogram::Histogram( const VesselOptions& da ): -ShortcutVessel(da) + ShortcutVessel(da) { bool norm; parseFlag("NORM",norm); std::string normstr=""; if(norm) normstr=" NORM"; std::vector bins; HistogramBead::generateBins( getAllInput(), bins ); - for(unsigned i=0;iisPeriodic() ) error("LESS_THAN is not a meaningful option for periodic variables"); - std::string errormsg; sf.set( getAllInput(), errormsg ); - if( errormsg.size()!=0 ) error( errormsg ); + std::string errormsg; sf.set( getAllInput(), errormsg ); + if( errormsg.size()!=0 ) error( errormsg ); } -std::string LessThan::value_descriptor(){ +std::string LessThan::value_descriptor() { return "the number of values less than " + sf.description(); } @@ -58,7 +58,7 @@ double LessThan::calcTransform( const double& val, double& dv ) const { double f = sf.calculate(val, dv); dv*=val; return f; } -double LessThan::getCutoff(){ +double LessThan::getCutoff() { return sf.get_dmax(); } diff --git a/src/vesselbase/LessThan.h b/src/vesselbase/LessThan.h index 3a624788e1..f276f6e4a7 100644 --- a/src/vesselbase/LessThan.h +++ b/src/vesselbase/LessThan.h @@ -27,14 +27,14 @@ #include "ActionWithVessel.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class LessThan : public FunctionVessel { private: SwitchingFunction sf; public: static void registerKeywords( Keywords& keys ); - static void reserveKeyword( Keywords& keys ); + static void reserveKeyword( Keywords& keys ); explicit LessThan( const VesselOptions& da ); std::string value_descriptor(); double calcTransform( const double& val, double& dv ) const ; diff --git a/src/vesselbase/Lowest.cpp b/src/vesselbase/Lowest.cpp index bf8c5e63a6..9121543b78 100644 --- a/src/vesselbase/Lowest.cpp +++ b/src/vesselbase/Lowest.cpp @@ -23,7 +23,7 @@ #include "VesselRegister.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class Lowest : public OrderingVessel { public: @@ -31,30 +31,30 @@ class Lowest : public OrderingVessel { static void reserveKeyword( Keywords& keys ); explicit Lowest( const VesselOptions& da ); std::string value_descriptor(); - bool compare( const double& , const double& ); + bool compare( const double&, const double& ); }; PLUMED_REGISTER_VESSEL(Lowest,"LOWEST") -void Lowest::registerKeywords( Keywords& keys ){ +void Lowest::registerKeywords( Keywords& keys ) { OrderingVessel::registerKeywords( keys ); } -void Lowest::reserveKeyword( Keywords& keys ){ +void Lowest::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","LOWEST","this flag allows you to recover the lowest of these variables."); keys.addOutputComponent("lowest","LOWEST","the lowest of the quantitities calculated by this action"); } Lowest::Lowest( const VesselOptions& da ) : -OrderingVessel(da) + OrderingVessel(da) { } -std::string Lowest::value_descriptor(){ +std::string Lowest::value_descriptor() { return "the lowest of the individual colvar values"; } -bool Lowest::compare( const double& val1, const double& val2 ){ +bool Lowest::compare( const double& val1, const double& val2 ) { return val1isPeriodic() ) error("max is not a meaningful option for periodic variables"); parse("BETA",beta); @@ -64,7 +64,7 @@ FunctionVessel(da) if( diffweight ) error("can't calculate max if weight is differentiable"); } -std::string Max::value_descriptor(){ +std::string Max::value_descriptor() { std::string str_beta; Tools::convert( beta, str_beta ); return "the maximum value. Beta is equal to " + str_beta; } @@ -73,7 +73,7 @@ double Max::calcTransform( const double& val, double& dv ) const { double f = exp(val/beta); dv=f/beta; return f; } -double Max::finalTransform( const double& val, double& dv ){ +double Max::finalTransform( const double& val, double& dv ) { double dist=beta*std::log( val ); dv = beta/val; return dist; } diff --git a/src/vesselbase/Mean.cpp b/src/vesselbase/Mean.cpp index 9bcfe1aa79..d2979761b9 100644 --- a/src/vesselbase/Mean.cpp +++ b/src/vesselbase/Mean.cpp @@ -37,24 +37,24 @@ class Mean : public FunctionVessel { PLUMED_REGISTER_VESSEL(Mean,"MEAN") -void Mean::registerKeywords( Keywords& keys ){ +void Mean::registerKeywords( Keywords& keys ) { FunctionVessel::registerKeywords(keys); } -void Mean::reserveKeyword( Keywords& keys ){ +void Mean::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","MEAN","take the mean of these variables."); keys.addOutputComponent("mean","MEAN","the mean value. The output component can be refererred to elsewhere in the input " - "file by using the label.mean"); + "file by using the label.mean"); } Mean::Mean( const vesselbase::VesselOptions& da ) : -FunctionVessel(da) + FunctionVessel(da) { if( getAction()->isPeriodic() ) error("MEAN cannot be used with periodic variables"); norm=true; // Makes sure we calculate the average } -std::string Mean::value_descriptor(){ +std::string Mean::value_descriptor() { return "the mean value"; } diff --git a/src/vesselbase/Min.cpp b/src/vesselbase/Min.cpp index 73230f9c41..989ee34c61 100644 --- a/src/vesselbase/Min.cpp +++ b/src/vesselbase/Min.cpp @@ -24,7 +24,7 @@ #include "ActionWithVessel.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class Min : public FunctionVessel { private: @@ -40,22 +40,22 @@ class Min : public FunctionVessel { PLUMED_REGISTER_VESSEL(Min,"MIN") -void Min::registerKeywords( Keywords& keys ){ +void Min::registerKeywords( Keywords& keys ) { FunctionVessel::registerKeywords( keys ); keys.add("compulsory","BETA","the value of beta for the equation in the manual"); } -void Min::reserveKeyword( Keywords& keys ){ +void Min::reserveKeyword( Keywords& keys ) { keys.reserve("vessel","MIN","calculate the minimum value. " - "To make this quantity continuous the minimum is calculated using " - "\\f$ \\textrm{min} = \\frac{\\beta}{ \\log \\sum_i \\exp\\left( \\frac{\\beta}{s_i} \\right) } \\f$ " - "The value of \\f$\\beta\\f$ in this function is specified using (BETA=\\f$\\beta\\f$)"); + "To make this quantity continuous the minimum is calculated using " + "\\f$ \\textrm{min} = \\frac{\\beta}{ \\log \\sum_i \\exp\\left( \\frac{\\beta}{s_i} \\right) } \\f$ " + "The value of \\f$\\beta\\f$ in this function is specified using (BETA=\\f$\\beta\\f$)"); keys.addOutputComponent("min","MIN","the minimum value. This is calculated using the formula described in the description of the " - "keyword so as to make it continuous."); + "keyword so as to make it continuous."); } Min::Min( const VesselOptions& da ) : -FunctionVessel(da) + FunctionVessel(da) { if( getAction()->isPeriodic() ) error("min is not a meaningful option for periodic variables"); parse("BETA",beta); @@ -63,17 +63,17 @@ FunctionVessel(da) if( diffweight ) error("can't calculate min if weight is differentiable"); } -std::string Min::value_descriptor(){ +std::string Min::value_descriptor() { std::string str_beta; Tools::convert( beta, str_beta ); return "the minimum value. Beta is equal to " + str_beta; } double Min::calcTransform( const double& val, double& dv ) const { double f = exp(beta/val); dv=f/(val*val); - return f; + return f; } -double Min::finalTransform( const double& val, double& dv ){ +double Min::finalTransform( const double& val, double& dv ) { double dist=beta/std::log( val ); dv = dist*dist/val; return dist; } diff --git a/src/vesselbase/Moments.cpp b/src/vesselbase/Moments.cpp index dc449b57f9..84d7e39190 100644 --- a/src/vesselbase/Moments.cpp +++ b/src/vesselbase/Moments.cpp @@ -24,10 +24,10 @@ #include "ActionWithVessel.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { -// This is not the most efficient implementation -// The calculation of all the colvars is parallelized +// This is not the most efficient implementation +// The calculation of all the colvars is parallelized // but the loops for calculating moments are not // Feel free to reimplement this if you know how class Moments : public StoreDataVessel { @@ -46,109 +46,109 @@ class Moments : public StoreDataVessel { PLUMED_REGISTER_VESSEL(Moments,"MOMENTS") -void Moments::registerKeywords( Keywords& keys ){ +void Moments::registerKeywords( Keywords& keys ) { StoreDataVessel::registerKeywords( keys ); } -void Moments::reserveKeyword( Keywords& keys ){ - keys.reserve("optional","MOMENTS","calculate the moments of the distribution of collective variables. " - "The \\f$m\\f$th moment of a distribution is calculated using \\f$\\frac{1}{N} \\sum_{i=1}^N ( s_i - \\overline{s} )^m \\f$, where \\f$\\overline{s}\\f$ is " - "the average for the distribution. The moments keyword takes a lists of integers as input or a range. Each integer is a value of \\f$m\\f$. The final " - "calculated values can be referenced using moment-\\f$m\\f$."); +void Moments::reserveKeyword( Keywords& keys ) { + keys.reserve("optional","MOMENTS","calculate the moments of the distribution of collective variables. " + "The \\f$m\\f$th moment of a distribution is calculated using \\f$\\frac{1}{N} \\sum_{i=1}^N ( s_i - \\overline{s} )^m \\f$, where \\f$\\overline{s}\\f$ is " + "the average for the distribution. The moments keyword takes a lists of integers as input or a range. Each integer is a value of \\f$m\\f$. The final " + "calculated values can be referenced using moment-\\f$m\\f$."); keys.reset_style("MOMENTS","vessel"); keys.addOutputComponent("moment","MOMENTS","the central moments of the distribution of values. The second moment " - "would be referenced elsewhere in the input file using " - "label.moment-2, the third as label.moment-3, etc."); + "would be referenced elsewhere in the input file using " + "label.moment-2, the third as label.moment-3, etc."); } Moments::Moments( const vesselbase::VesselOptions& da) : -StoreDataVessel(da) + StoreDataVessel(da) { - ActionWithValue* a=dynamic_cast( getAction() ); - plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); - - std::vector moments=Tools::getWords(getAllInput(),"\t\n ,"); - Tools::interpretRanges(moments); unsigned nn; - for(unsigned i=0;iaddComponentWithDerivatives( "moment-" + moments[i] ); - a->componentIsNotPeriodic( "moment-" + moments[i] ); - value_out.push_back( a->copyOutput( a->getNumberOfComponents()-1 ) ); - Tools::convert( moments[i], nn ); - if( nn<2 ) error("moments are only possible for m>=2" ); - powers.push_back( nn ); std::string num; Tools::convert(powers[i],num); - } + ActionWithValue* a=dynamic_cast( getAction() ); + plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); + + std::vector moments=Tools::getWords(getAllInput(),"\t\n ,"); + Tools::interpretRanges(moments); unsigned nn; + for(unsigned i=0; iaddComponentWithDerivatives( "moment-" + moments[i] ); + a->componentIsNotPeriodic( "moment-" + moments[i] ); + value_out.push_back( a->copyOutput( a->getNumberOfComponents()-1 ) ); + Tools::convert( moments[i], nn ); + if( nn<2 ) error("moments are only possible for m>=2" ); + powers.push_back( nn ); std::string num; Tools::convert(powers[i],num); + } } -void Moments::resize(){ - StoreDataVessel::resize(); +void Moments::resize() { + StoreDataVessel::resize(); } -std::string Moments::description(){ - std::string descri, num; - Tools::convert(powers[0],num); - descri = "value " + getAction()->getLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; - for(unsigned i=1;igetLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; - } - return descri; +std::string Moments::description() { + std::string descri, num; + Tools::convert(powers[0],num); + descri = "value " + getAction()->getLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; + for(unsigned i=1; igetLabel() + "." + "moment-" + num + " contains the " + num + "th moment of the distribution"; + } + return descri; } -void Moments::finish( const std::vector& buffer ){ +void Moments::finish( const std::vector& buffer ) { StoreDataVessel::finish( buffer ); const double pi=3.141592653589793238462643383279502884197169399375105820974944592307; - unsigned nvals=getAction()->getFullNumberOfTasks(); + unsigned nvals=getAction()->getFullNumberOfTasks(); double mean=0; Value myvalue; - if( getAction()->isPeriodic() ){ - std::string str_min, str_max; getAction()->retrieveDomain( str_min, str_max ); - double pfactor, min, max; Tools::convert(str_min,min); Tools::convert(str_max,max); - pfactor = 2*pi / ( max-min ); myvalue.setDomain( str_min, str_max ); - double sinsum=0, cossum=0, val; - for(unsigned i=0;i( nvals ) , cossum / static_cast( nvals ) ) / (2*pi); - mean = min + (max-min)*mean; + if( getAction()->isPeriodic() ) { + std::string str_min, str_max; getAction()->retrieveDomain( str_min, str_max ); + double pfactor, min, max; Tools::convert(str_min,min); Tools::convert(str_max,max); + pfactor = 2*pi / ( max-min ); myvalue.setDomain( str_min, str_max ); + double sinsum=0, cossum=0, val; + for(unsigned i=0; i( nvals ), cossum / static_cast( nvals ) ) / (2*pi); + mean = min + (max-min)*mean; } else { - for(unsigned i=0;i( nvals ); myvalue.setNotPeriodic(); + for(unsigned i=0; i( nvals ); myvalue.setNotPeriodic(); } - for(unsigned npow=0;npowgetNumberOfDerivatives()>0 ){ - for(unsigned i=0;i( nvals ); - } - - double moment=0; - MultiValue myvals( getNumberOfComponents(), getAction()->getNumberOfDerivatives() ); myvals.clearAll(); - for(unsigned i=0;igetNumberOfDerivatives() ){ - double pref=pow( tmp, powers[npow] - 1 ) - dev1; - retrieveDerivatives( i, false, myvals ); - for(unsigned j=0;jaddDerivative(jatom, pref*myvals.getDerivative( 1, jatom ) ); - } - myvals.clearAll(); - } - } - if( value_out[npow]->getNumberOfDerivatives()>0 ) value_out[npow]->chainRule( powers[npow] / static_cast( nvals ) ); - value_out[npow]->set( moment / static_cast( nvals ) ); + for(unsigned npow=0; npowgetNumberOfDerivatives()>0 ) { + for(unsigned i=0; i( nvals ); + } + + double moment=0; + MultiValue myvals( getNumberOfComponents(), getAction()->getNumberOfDerivatives() ); myvals.clearAll(); + for(unsigned i=0; igetNumberOfDerivatives() ) { + double pref=pow( tmp, powers[npow] - 1 ) - dev1; + retrieveDerivatives( i, false, myvals ); + for(unsigned j=0; jaddDerivative(jatom, pref*myvals.getDerivative( 1, jatom ) ); + } + myvals.clearAll(); + } + } + if( value_out[npow]->getNumberOfDerivatives()>0 ) value_out[npow]->chainRule( powers[npow] / static_cast( nvals ) ); + value_out[npow]->set( moment / static_cast( nvals ) ); } } -bool Moments::applyForce( std::vector& forces ){ +bool Moments::applyForce( std::vector& forces ) { std::vector tmpforce( forces.size() ); forces.assign(forces.size(),0.0); bool wasforced=false; - for(unsigned i=0;iapplyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; jisPeriodic() ) error("more than is not a meaningful option for periodic variables"); std::string errormsg; sf.set( getAllInput(), errormsg ); if( errormsg.size()!=0 ) error( errormsg ); } -std::string MoreThan::value_descriptor(){ +std::string MoreThan::value_descriptor() { return "the number of values more than " + sf.description(); } double MoreThan::calcTransform( const double& val, double& dv ) const { - double f = 1.0 - sf.calculate(val, dv); dv*=-val; return f; + double f = 1.0 - sf.calculate(val, dv); dv*=-val; return f; } } diff --git a/src/vesselbase/OrderingVessel.cpp b/src/vesselbase/OrderingVessel.cpp index 952dcb85d8..4eab917887 100644 --- a/src/vesselbase/OrderingVessel.cpp +++ b/src/vesselbase/OrderingVessel.cpp @@ -23,47 +23,47 @@ #include "core/ActionWithValue.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { -void OrderingVessel::registerKeywords( Keywords& keys ){ +void OrderingVessel::registerKeywords( Keywords& keys ) { ValueVessel::registerKeywords( keys ); } OrderingVessel::OrderingVessel( const VesselOptions& da ) : -ValueVessel(da) + ValueVessel(da) { mydata = getAction()->buildDataStashes( NULL ); - for(unsigned i=0;igetNumberOfVessels();++i){ - if( getAction()->getPntrToVessel(i)->getName()==getName() ) - error("calculating lowest/highest value multiple times serves no purpose"); + for(unsigned i=0; igetNumberOfVessels(); ++i) { + if( getAction()->getPntrToVessel(i)->getName()==getName() ) + error("calculating lowest/highest value multiple times serves no purpose"); } } -void OrderingVessel::resize(){ - resizeBuffer( 0 ); +void OrderingVessel::resize() { + resizeBuffer( 0 ); if( getAction()->derivativesAreRequired() ) getFinalValue()->resizeDerivatives( getAction()->getNumberOfDerivatives() ); } -void OrderingVessel::finish( const std::vector& buffer ){ +void OrderingVessel::finish( const std::vector& buffer ) { std::vector values( getAction()->getNumberOfQuantities() ); mydata->retrieveSequentialValue( 0, false, values ); double min=values[mycomp]; unsigned mini=getAction()->getPositionInFullTaskList(0); - for(unsigned i=1;igetNumberOfStoredValues();++i){ - mydata->retrieveSequentialValue( i, false, values ); - double newval = values[mycomp]; - if( compare( newval, min ) ){ min=newval; mini=getAction()->getPositionInFullTaskList(i); } + for(unsigned i=1; igetNumberOfStoredValues(); ++i) { + mydata->retrieveSequentialValue( i, false, values ); + double newval = values[mycomp]; + if( compare( newval, min ) ) { min=newval; mini=getAction()->getPositionInFullTaskList(i); } } setOutputValue( min ); - if( getAction()->derivativesAreRequired() ){ - MultiValue myvals( getAction()->getNumberOfQuantities(), getAction()->getNumberOfDerivatives() ); - mydata->retrieveDerivatives( mini, false, myvals ); Value* fval=getFinalValue(); - for(unsigned i=0;isetDerivative( ider, myvals.getDerivative(mycomp,ider) ); - } + if( getAction()->derivativesAreRequired() ) { + MultiValue myvals( getAction()->getNumberOfQuantities(), getAction()->getNumberOfDerivatives() ); + mydata->retrieveDerivatives( mini, false, myvals ); Value* fval=getFinalValue(); + for(unsigned i=0; isetDerivative( ider, myvals.getDerivative(mycomp,ider) ); + } } } diff --git a/src/vesselbase/OrderingVessel.h b/src/vesselbase/OrderingVessel.h index c3ec6d13c0..6e8fb93cc5 100644 --- a/src/vesselbase/OrderingVessel.h +++ b/src/vesselbase/OrderingVessel.h @@ -30,7 +30,7 @@ #include "core/Value.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class OrderingVessel : public ValueVessel { private: @@ -41,7 +41,7 @@ class OrderingVessel : public ValueVessel { void resize(); void calculate( const unsigned& current, MultiValue& myvals, std::vector& buffer, std::vector& der_list ) const {} void finish( const std::vector& buffer ); - virtual bool compare( const double& , const double& )=0; + virtual bool compare( const double&, const double& )=0; }; } diff --git a/src/vesselbase/ShortcutVessel.cpp b/src/vesselbase/ShortcutVessel.cpp index 41e64a5490..fc3be38c6f 100644 --- a/src/vesselbase/ShortcutVessel.cpp +++ b/src/vesselbase/ShortcutVessel.cpp @@ -22,23 +22,23 @@ #include "ShortcutVessel.h" #include "ActionWithVessel.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -void ShortcutVessel::registerKeywords( Keywords& keys ){ +void ShortcutVessel::registerKeywords( Keywords& keys ) { Vessel::registerKeywords( keys ); keys.remove("LABEL"); plumed_assert( keys.size()==0 ); } ShortcutVessel::ShortcutVessel( const VesselOptions& da): -Vessel(da) + Vessel(da) { } -void ShortcutVessel::addVessel( const std::string& name, const std::string& input ){ +void ShortcutVessel::addVessel( const std::string& name, const std::string& input ) { unsigned numlab=1; - for(unsigned i=0;i<(getAction()->functions).size();++i){ - if( (getAction()->functions[i])->getName()==name ) numlab++; + for(unsigned i=0; i<(getAction()->functions).size(); ++i) { + if( (getAction()->functions[i])->getName()==name ) numlab++; } getAction()->addVessel( name, input, numlab ); } diff --git a/src/vesselbase/ShortcutVessel.h b/src/vesselbase/ShortcutVessel.h index f84555205e..c6e66d76cf 100644 --- a/src/vesselbase/ShortcutVessel.h +++ b/src/vesselbase/ShortcutVessel.h @@ -29,19 +29,19 @@ #include "core/Value.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { class ShortcutVessel : public Vessel { protected: - void addVessel( const std::string& name, const std::string& intput ); + void addVessel( const std::string& name, const std::string& intput ); public: static void registerKeywords( Keywords& keys ); explicit ShortcutVessel( const VesselOptions& ); - std::string description(){ return ""; } - void resize(){ plumed_error(); } + std::string description() { return ""; } + void resize() { plumed_error(); } void calculate( const unsigned& taskCode, MultiValue& myvals, std::vector& buffer, std::vector& der_index ) const { plumed_error(); } - void finish( const std::vector& buffer ){ plumed_error(); } - bool applyForce( std::vector& forces ){ plumed_error(); } + void finish( const std::vector& buffer ) { plumed_error(); } + bool applyForce( std::vector& forces ) { plumed_error(); } }; } diff --git a/src/vesselbase/StoreDataVessel.cpp b/src/vesselbase/StoreDataVessel.cpp index 13f4c9ab6f..a89c50d149 100644 --- a/src/vesselbase/StoreDataVessel.cpp +++ b/src/vesselbase/StoreDataVessel.cpp @@ -24,38 +24,38 @@ namespace PLMD { namespace vesselbase { -void StoreDataVessel::registerKeywords( Keywords& keys ){ +void StoreDataVessel::registerKeywords( Keywords& keys ) { Vessel::registerKeywords(keys); keys.remove("LABEL"); } StoreDataVessel::StoreDataVessel( const VesselOptions& da ): -Vessel(da), -max_lowmem_stash(3), -vecsize(0), -nspace(0) + Vessel(da), + max_lowmem_stash(3), + vecsize(0), + nspace(0) { ActionWithValue* myval=dynamic_cast( getAction() ); if( !myval ) hasderiv=false; else hasderiv=!myval->doNotCalculateDerivatives(); } -void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ){ +void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) { userActions.push_back( actionThatUses ); } -void StoreDataVessel::resize(){ +void StoreDataVessel::resize() { vecsize=getAction()->getNumberOfQuantities(); plumed_dbg_assert( vecsize>0 ); - if( getAction()->lowmem || !getAction()->derivativesAreRequired() ){ - nspace = 1; - active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); + if( getAction()->lowmem || !getAction()->derivativesAreRequired() ) { + nspace = 1; + active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); } else { - if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ){ - error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option"); - } - nspace = 1 + getAction()->maxderivatives; - active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); + if( getAction()->getNumberOfDerivatives()>getAction()->maxderivatives ) { + error("not enough memory to store derivatives for action " + getAction()->getLabel() + " use LOWMEM option"); + } + nspace = 1 + getAction()->maxderivatives; + active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); } resizeBuffer( getNumberOfStoredValues()*vecsize*nspace ); local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace ); @@ -64,9 +64,9 @@ void StoreDataVessel::resize(){ void StoreDataVessel::storeValues( const unsigned& myelem, MultiValue& myvals, std::vector& buffer ) const { plumed_dbg_assert( vecsize>0 ); unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); plumed_dbg_assert( jelem0 && getAction()->derivativesAreRequired() && myelemgetFullNumberOfTasks() ); unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); - if( getAction()->getFullNumberOfTasks()==getNumberOfStoredValues() ){ - der_list[jelem]=myvals.getNumberActive(); - unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); - for(unsigned j=0;jgetFullNumberOfTasks()==getNumberOfStoredValues() ) { + der_list[jelem]=myvals.getNumberActive(); + unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); + for(unsigned j=0; j& values ) const { plumed_assert( values.size()==vecsize ); unsigned ibuf = jelem * vecsize * nspace; - for(unsigned i=0;i2 ) getAction()->normalizeVector( values ); + for(unsigned i=0; i2 ) getAction()->normalizeVector( values ); } void StoreDataVessel::retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector& values ) const { @@ -119,60 +119,60 @@ double StoreDataVessel::retrieveWeightWithIndex( const unsigned& myelem ) const unsigned jelem = getStoreIndex( myelem ); unsigned ibuf = jelem * vecsize * nspace; return local_buffer[ibuf]; } -void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ){ +void StoreDataVessel::retrieveDerivatives( const unsigned& myelem, const bool& normed, MultiValue& myvals ) { plumed_dbg_assert( myvals.getNumberOfValues()==vecsize && myvals.getNumberOfDerivatives()==getAction()->getNumberOfDerivatives() ); myvals.clearAll(); - if( getAction()->lowmem ){ - recalculateStoredQuantity( myelem, myvals ); - if( normed ) getAction()->normalizeVectorDerivatives( myvals ); + if( getAction()->lowmem ) { + recalculateStoredQuantity( myelem, myvals ); + if( normed ) getAction()->normalizeVectorDerivatives( myvals ); } else { - unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); - // Retrieve the derivatives for elements 0 and 1 - weight and norm - for(unsigned icomp=0;icompnormalizeVectorDerivatives( myvals ); - // Now ensure appropriate parts of list are activated - myvals.emptyActiveMembers(); + unsigned jelem = getAction()->getPositionInCurrentTaskList( myelem ); + // Retrieve the derivatives for elements 0 and 1 - weight and norm + for(unsigned icomp=0; icompnormalizeVectorDerivatives( myvals ); + // Now ensure appropriate parts of list are activated + myvals.emptyActiveMembers(); + unsigned kder = getNumberOfStoredValues() + jelem * ( nspace - 1 ); + for(unsigned j=0; j& buffer, std::vector& der_list ) const { - if( myvals.get(0)>epsilon ){ - storeValues( current, myvals, buffer ); - if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer, der_list ); - } + if( myvals.get(0)>epsilon ) { + storeValues( current, myvals, buffer ); + if( !(getAction()->lowmem) && getAction()->derivativesAreRequired() ) storeDerivatives( current, myvals, buffer, der_list ); + } return; } -void StoreDataVessel::finish( const std::vector& buffer ){ +void StoreDataVessel::finish( const std::vector& buffer ) { // Store the buffer locally - for(unsigned i=0;i& der_index ){ - if( !getAction()->lowmem && getAction()->derivativesAreRequired() ){ - for(unsigned i=0;i& der_index ) { + if( !getAction()->lowmem && getAction()->derivativesAreRequired() ) { + for(unsigned i=0; i active_val; /// The active derivative elements std::vector active_der; /// The buffer - std::vector local_buffer; + std::vector local_buffer; /// The actions that are going to use the stored data - std::vector userActions; -/// We create a vector of tempory MultiValues here so as to avoid + std::vector userActions; +/// We create a vector of tempory MultiValues here so as to avoid /// lots of vector resizing - unsigned tmp_index; - std::vector my_tmp_vals; + unsigned tmp_index; + std::vector my_tmp_vals; protected: /// Is the weight differentiable bool weightHasDerivatives(); @@ -69,13 +69,13 @@ friend class Moments; bool usingLowMem(); /// Finish the setup of the storage object by setting how much /// data has to be stored - void completeSetup( const unsigned& , const unsigned& ); + void completeSetup( const unsigned&, const unsigned& ); /// Return value of nspace unsigned getNumberOfDerivativeSpacesPerComponent() const ; /// Retrieve the values from the underlying ActionWithVessel - void storeValues( const unsigned& , MultiValue& , std::vector& ) const ; + void storeValues( const unsigned&, MultiValue&, std::vector& ) const ; /// This stores the data we get from the calculation - void storeDerivatives( const unsigned& , MultiValue& myvals, std::vector&, std::vector& ) const ; + void storeDerivatives( const unsigned&, MultiValue& myvals, std::vector&, std::vector& ) const ; /// Get the ibuf'th local derivative value double getLocalDerivative( const unsigned& ibuf ); /// Set the ibuf'th local derivative value @@ -93,7 +93,7 @@ friend class Moments; void recalculateStoredQuantity( const unsigned& myelm, MultiValue& myvals ); /// Set a hard cutoff on the weight of an element void setHardCutoffOnWeight( const double& mytol ); -/// Add an action that uses this data +/// Add an action that uses this data void addActionThatUses( ActionWithVessel* actionThatUses ); /// Return the number of components in the vector unsigned getNumberOfComponents() const { return vecsize; } @@ -106,7 +106,7 @@ friend class Moments; /// Do all resizing of data virtual void resize(); /// - virtual std::string description(){ return ""; } + virtual std::string description() { return ""; } /// Get the number of derivatives for the ith value unsigned getNumberOfDerivatives( const unsigned& ); /// Get the size of the derivative list @@ -116,13 +116,13 @@ friend class Moments; /// Final step in gathering data virtual void finish( const std::vector& buffer ); /// Is a particular stored value active at the present time - bool storedValueIsActive( const unsigned& iatom ) const ; + bool storedValueIsActive( const unsigned& iatom ) const ; /// Set the active values void setActiveValsAndDerivatives( const std::vector& der_index ); /// Activate indexes (this is used at end of chain rule) - virtual void activateIndices( ActionWithVessel* ){} + virtual void activateIndices( ActionWithVessel* ) {} /// Forces on vectors should always be applied elsewhere - virtual bool applyForce(std::vector&){ return false; } + virtual bool applyForce(std::vector&) { return false; } /// Get the number of data users unsigned getNumberOfDataUsers() const ; /// Get one of the ith data user @@ -134,12 +134,12 @@ friend class Moments; }; inline -bool StoreDataVessel::weightHasDerivatives(){ +bool StoreDataVessel::weightHasDerivatives() { return getAction()->weightHasDerivatives; } inline -bool StoreDataVessel::usingLowMem(){ +bool StoreDataVessel::usingLowMem() { return getAction()->lowmem; } @@ -153,7 +153,7 @@ bool StoreDataVessel::storedValueIsActive( const unsigned& iatom ) const { if( !getAction()->taskIsCurrentlyActive( iatom ) ) return false; unsigned jatom = getStoreIndex( iatom ); plumed_dbg_assert( jatomepsilon; + return local_buffer[jatom*vecsize*nspace]>epsilon; } inline @@ -172,12 +172,12 @@ unsigned StoreDataVessel::getStoreIndex( const unsigned& ind ) const { // Binary search for required element - faster scaling than sequential search unsigned l=0, r=getAction()->nactive_tasks-1; - for(unsigned i=0;inactive_tasks;++i){ - plumed_assert( l<=r ); - unsigned m = std::floor( (l + r)/2 ); - if( ind==getAction()->indexOfTaskInFullList[m] ) return m; - else if( getAction()->indexOfTaskInFullList[m]indexOfTaskInFullList[m]>ind ) r=m-1; + for(unsigned i=0; inactive_tasks; ++i) { + plumed_assert( l<=r ); + unsigned m = std::floor( (l + r)/2 ); + if( ind==getAction()->indexOfTaskInFullList[m] ) return m; + else if( getAction()->indexOfTaskInFullList[m]indexOfTaskInFullList[m]>ind ) r=m-1; } plumed_merror("requested task is not active"); } @@ -188,7 +188,7 @@ unsigned StoreDataVessel::getTrueIndex( const unsigned& ind ) const { } inline -void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ){ +void StoreDataVessel::recalculateStoredQuantity( const unsigned& myelem, MultiValue& myvals ) { getAction()->performTask( myelem, getAction()->getTaskCode(myelem), myvals ); } @@ -198,7 +198,7 @@ unsigned StoreDataVessel::getNumberOfDataUsers() const { } inline -ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ){ +ActionWithVessel* StoreDataVessel::getDataUser( const unsigned& idata ) { plumed_dbg_assert( idata( getAction() ); plumed_massert(a,"cannot create passable values as base action does not inherit from ActionWithValue"); int numval = getNumericalLabel(); - if( numval<0 && a->getNumberOfComponents()==0 ){ // This allows us to make multicolvars pretend to be colvars - this is used in AlphaRMSD etc - a->addValueWithDerivatives(); - a->setNotPeriodic(); - final_value=a->copyOutput( a->getNumberOfComponents()-1 ); - } else if( numval<0 ){ - no_output_value=true; final_value=new Value(); final_value->setNotPeriodic(); + if( numval<0 && a->getNumberOfComponents()==0 ) { // This allows us to make multicolvars pretend to be colvars - this is used in AlphaRMSD etc + a->addValueWithDerivatives(); + a->setNotPeriodic(); + final_value=a->copyOutput( a->getNumberOfComponents()-1 ); + } else if( numval<0 ) { + no_output_value=true; final_value=new Value(); final_value->setNotPeriodic(); } else { - plumed_massert( !a->exists(getAction()->getLabel() + "." + getLabel() ), "you can't create the name multiple times"); - a->addComponentWithDerivatives( getLabel() ); - a->componentIsNotPeriodic( getLabel() ); - final_value=a->copyOutput( a->getNumberOfComponents()-1 ); + plumed_massert( !a->exists(getAction()->getLabel() + "." + getLabel() ), "you can't create the name multiple times"); + a->addComponentWithDerivatives( getLabel() ); + a->componentIsNotPeriodic( getLabel() ); + final_value=a->copyOutput( a->getNumberOfComponents()-1 ); } } -ValueVessel::~ValueVessel(){ +ValueVessel::~ValueVessel() { if( no_output_value ) delete final_value; } -std::string ValueVessel::description(){ +std::string ValueVessel::description() { if( final_value->getName()==getAction()->getLabel() ) return "value " + getAction()->getLabel() + " contains " + value_descriptor(); return "value " + getAction()->getLabel() + "." + getLabel() + " contains " + value_descriptor(); } -bool ValueVessel::applyForce( std::vector& forces ){ +bool ValueVessel::applyForce( std::vector& forces ) { std::vector tmpforce( forces.size() ); forces.assign(forces.size(),0.0); bool wasforced=false; - if( final_value->applyForce( tmpforce ) ){ - wasforced=true; - for(unsigned j=0;japplyForce( tmpforce ) ) { + wasforced=true; + for(unsigned j=0; j& forces ); @@ -63,7 +63,7 @@ double ValueVessel::getOutputValue() const { } inline -void ValueVessel::setOutputValue( const double& val ){ +void ValueVessel::setOutputValue( const double& val ) { final_value->set( val ); } diff --git a/src/vesselbase/Vessel.cpp b/src/vesselbase/Vessel.cpp index deec8b036d..4ce9e10a05 100644 --- a/src/vesselbase/Vessel.cpp +++ b/src/vesselbase/Vessel.cpp @@ -26,66 +26,66 @@ #include "tools/Log.h" namespace PLMD { -namespace vesselbase{ +namespace vesselbase { Keywords VesselOptions::emptyKeys; VesselOptions::VesselOptions(const std::string& thisname, const std::string& thislab, const unsigned& nlab, const std::string& params, ActionWithVessel* aa ): -myname(thisname), -mylabel(thislab), -numlab(nlab), -action(aa), -keywords(emptyKeys), -parameters(params) + myname(thisname), + mylabel(thislab), + numlab(nlab), + action(aa), + keywords(emptyKeys), + parameters(params) { } VesselOptions::VesselOptions(const VesselOptions& da, const Keywords& keys ): -myname(da.myname), -mylabel(da.mylabel), -numlab(da.numlab), -action(da.action), -keywords(keys), -parameters(da.parameters) + myname(da.myname), + mylabel(da.mylabel), + numlab(da.numlab), + action(da.action), + keywords(keys), + parameters(da.parameters) { } -void Vessel::registerKeywords( Keywords& keys ){ +void Vessel::registerKeywords( Keywords& keys ) { plumed_assert( keys.size()==0 ); keys.add("optional","LABEL","the label used to reference this particular quantity"); } -std::string Vessel::transformName( const std::string& name ){ - std::string tlabel=name; - // Convert to lower case - std::transform( tlabel.begin(), tlabel.end(), tlabel.begin(), tolower ); - // Remove any underscore characters (as these are reserved) - for(unsigned i=0;;++i){ - std::size_t num=tlabel.find_first_of("_"); - if( num==std::string::npos ) break; - tlabel.erase( tlabel.begin() + num, tlabel.begin() + num + 1 ); - } - return tlabel; +std::string Vessel::transformName( const std::string& name ) { + std::string tlabel=name; + // Convert to lower case + std::transform( tlabel.begin(), tlabel.end(), tlabel.begin(), tolower ); + // Remove any underscore characters (as these are reserved) + for(unsigned i=0;; ++i) { + std::size_t num=tlabel.find_first_of("_"); + if( num==std::string::npos ) break; + tlabel.erase( tlabel.begin() + num, tlabel.begin() + num + 1 ); + } + return tlabel; } Vessel::Vessel( const VesselOptions& da ): -myname(da.myname), -numlab(da.numlab), -action(da.action), -line(Tools::getWords( da.parameters )), -keywords(da.keywords), -finished_read(false), -comm(da.action->comm), -log((da.action)->log) + myname(da.myname), + numlab(da.numlab), + action(da.action), + line(Tools::getWords( da.parameters )), + keywords(da.keywords), + finished_read(false), + comm(da.action->comm), + log((da.action)->log) { - if( da.mylabel.length()>0){ - mylabel=da.mylabel; + if( da.mylabel.length()>0) { + mylabel=da.mylabel; } else { - if( keywords.exists("LABEL") ) parse("LABEL",mylabel); - if( mylabel.length()==0 && numlab>=0 ){ - mylabel=transformName( myname ); std::string nn; - if(numlab>0){ Tools::convert( numlab, nn ); mylabel = mylabel + "-" + nn; } - } + if( keywords.exists("LABEL") ) parse("LABEL",mylabel); + if( mylabel.length()==0 && numlab>=0 ) { + mylabel=transformName( myname ); std::string nn; + if(numlab>0) { Tools::convert( numlab, nn ); mylabel = mylabel + "-" + nn; } + } } } @@ -97,37 +97,37 @@ std::string Vessel::getLabel() const { return mylabel; } -std::string Vessel::getAllInput(){ +std::string Vessel::getAllInput() { std::string fullstring; - for(unsigned i=0;i0 ) log.printf(" %s\n", describe.c_str() ); } -void Vessel::error( const std::string& msg ){ +void Vessel::error( const std::string& msg ) { action->log.printf("ERROR for keyword %s in action %s with label %s : %s \n \n",myname.c_str(), (action->getName()).c_str(), (action->getLabel()).c_str(), msg.c_str() ); if(finished_read) keywords.print( log ); plumed_merror("ERROR for keyword " + myname + " in action " + action->getName() + " with label " + action->getLabel() + " : " + msg ); diff --git a/src/vesselbase/Vessel.h b/src/vesselbase/Vessel.h index f193e264c0..ab96f3f41a 100644 --- a/src/vesselbase/Vessel.h +++ b/src/vesselbase/Vessel.h @@ -30,26 +30,26 @@ #include "tools/Keywords.h" #include "ActionWithVessel.h" -namespace PLMD{ +namespace PLMD { class Communicator; class Log; -namespace vesselbase{ +namespace vesselbase { /** \ingroup TOOLBOX Vessels are an important component of class PLMD::ActionWithVessel. This class contains a large buffer array of doubles. The various elements of this array can be accessed through vessels which are used to structure the elements of the -double array. As the buffer array is just a vector of doubles it can be easily -mpi gathered or passed to another node. +double array. As the buffer array is just a vector of doubles it can be easily +mpi gathered or passed to another node. */ //class ActionWithVessel; class Vessel; -/// This class is used to pass the input to Vessels +/// This class is used to pass the input to Vessels class VesselOptions { friend class Vessel; private: @@ -67,13 +67,13 @@ class VesselOptions { public: /// The parameters that are read into the function std::string parameters; -/// The constructor +/// The constructor VesselOptions( const std::string& thisname, const std::string& thislab, const unsigned& nlab, const std::string& params, ActionWithVessel* aa ); VesselOptions(const VesselOptions& da, const Keywords& keys ); }; class Vessel { -friend class ActionWithVessel; + friend class ActionWithVessel; private: /// The keyword for the vessel in the input file std::string myname; @@ -100,7 +100,7 @@ friend class ActionWithVessel; Communicator& comm; /// Return the numerical label int getNumericalLabel() const ; -/// Report an error +/// Report an error void error(const std::string& errmsg); /// Parse something from the input template @@ -111,7 +111,7 @@ friend class ActionWithVessel; /// Parse one keyword as boolean flag void parseFlag(const std::string&key,bool&t); /// This returns the whole input line (it is used for less_than/more_than/between) - std::string getAllInput(); + std::string getAllInput(); /// Return a pointer to the action we are working in ActionWithVessel* getAction() const ; /// Return the value of the tolerance @@ -125,14 +125,14 @@ friend class ActionWithVessel; public: /// Reference to the log on which to output details Log& log; -/// Reserve any keywords for this particular vessel +/// Reserve any keywords for this particular vessel static void registerKeywords( Keywords& keys ); /// Convert the name to the label of the component static std::string transformName( const std::string& name ); /// The constructor explicit Vessel( const VesselOptions& da ); /// Virtual destructor needed for proper inheritance - virtual ~Vessel(){} + virtual ~Vessel() {} /// Return the name std::string getName() const ; /// Return the label @@ -142,9 +142,9 @@ friend class ActionWithVessel; /// Return a description of the vessel contents virtual std::string description()=0; /// Set the start of the buffer - virtual void setBufferStart( unsigned& start ); + virtual void setBufferStart( unsigned& start ); /// Do something before the loop - virtual void prepare(){} + virtual void prepare() {} /// This is replaced in bridges so we can transform the derivatives virtual MultiValue& transformDerivatives( const unsigned& current, MultiValue& myvals, MultiValue& bvals ); /// Calculate the part of the vessel that is done in the loop @@ -158,22 +158,22 @@ friend class ActionWithVessel; }; template -void Vessel::parse(const std::string&key, T&t ){ +void Vessel::parse(const std::string&key, T&t ) { plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); // Now try to read the keyword bool found=Tools::parse(line,key,t); std::string def; - if ( !found && keywords.style(key,"compulsory") ){ - if( keywords.getDefaultValue(key,def) ){ - plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious"); - } else { - error("keyword " + key + " is comulsory for this vessel"); - } + if ( !found && keywords.style(key,"compulsory") ) { + if( keywords.getDefaultValue(key,def) ) { + plumed_massert( def.length()!=0 && Tools::convert(def,t), "default value is dubious"); + } else { + error("keyword " + key + " is comulsory for this vessel"); + } } } template -void Vessel::parseVector(const std::string&key,std::vector&t){ +void Vessel::parseVector(const std::string&key,std::vector&t) { // Check keyword has been registered plumed_massert(keywords.exists(key), "keyword " + key + " has not been registered"); unsigned size=t.size(); bool skipcheck=false; @@ -184,23 +184,23 @@ void Vessel::parseVector(const std::string&key,std::vector&t){ found=Tools::parseVector(line,key,t); // Check vectors size is correct (not if this is atoms or ARG) - if( !keywords.style(key,"atoms") && found ){ - if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); + if( !keywords.style(key,"atoms") && found ) { + if( !skipcheck && t.size()!=size ) error("vector read in for keyword " + key + " has the wrong size"); } - // If it isn't read and it is compulsory see if a default value was specified - if ( !found && keywords.style(key,"compulsory") ){ - if( keywords.getDefaultValue(key,def) ){ - if( def.length()==0 || !Tools::convert(def,val) ){ - plumed_merror("weird default value for keyword " + key ); - } else { - for(unsigned i=0;i -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { -VesselRegister::~VesselRegister(){ - if(m.size()>0){ +VesselRegister::~VesselRegister() { + if(m.size()>0) { std::string names=""; for(const auto & p : m) names+=p.first+" "; std::cerr<<"WARNING: Vessel "+ names +" has not been properly unregistered. This might lead to memory leak!!\n"; } } -VesselRegister& vesselRegister(){ +VesselRegister& vesselRegister() { static VesselRegister ans; return ans; } -void VesselRegister::remove(creator_pointer f){ - for(auto p=m.begin();p!=m.end();++p){ - if((*p).second==f){ +void VesselRegister::remove(creator_pointer f) { + for(auto p=m.begin(); p!=m.end(); ++p) { + if((*p).second==f) { m.erase(p); break; } } } -void VesselRegister::add(std::string keyword,creator_pointer f,keyword_pointer k,keyword_pointer ik){ +void VesselRegister::add(std::string keyword,creator_pointer f,keyword_pointer k,keyword_pointer ik) { plumed_massert(m.count(keyword)==0,"keyword has already been registered"); m.insert(std::pair(keyword,f)); k( keywords ); // Store the keywords for all the things @@ -57,24 +57,24 @@ void VesselRegister::add(std::string keyword,creator_pointer f,keyword_pointer k mk.insert(std::pair(keyword,ik)); } -bool VesselRegister::check(std::string key){ +bool VesselRegister::check(std::string key) { if( m.count(key)>0 ) return true; return false; } -Vessel* VesselRegister::create(std::string keyword, const VesselOptions&da){ +Vessel* VesselRegister::create(std::string keyword, const VesselOptions&da) { Vessel* df; - if(check(keyword)){ - Keywords keys; mk[keyword](keys); - VesselOptions nda( da,keys ); - df=m[keyword](nda); - keys.destroyData(); + if(check(keyword)) { + Keywords keys; mk[keyword](keys); + VesselOptions nda( da,keys ); + df=m[keyword](nda); + keys.destroyData(); } else df=NULL; return df; } -Keywords VesselRegister::getKeywords(){ +Keywords VesselRegister::getKeywords() { return keywords; } diff --git a/src/vesselbase/VesselRegister.h b/src/vesselbase/VesselRegister.h index 4aea38e0b9..a2bd24a20c 100644 --- a/src/vesselbase/VesselRegister.h +++ b/src/vesselbase/VesselRegister.h @@ -29,13 +29,13 @@ #include "tools/Exception.h" #include "tools/Keywords.h" -namespace PLMD{ -namespace vesselbase{ +namespace PLMD { +namespace vesselbase { class Vessel; class VesselOptions; -class VesselRegister{ +class VesselRegister { private: /// Pointer to a function which, given the keyword for a distribution function, creates it typedef Vessel*(*creator_pointer)(const VesselOptions&); diff --git a/src/wrapper/Plumed.c b/src/wrapper/Plumed.c index 7aa2b20eb1..75d9a9280b 100644 --- a/src/wrapper/Plumed.c +++ b/src/wrapper/Plumed.c @@ -32,7 +32,7 @@ /* DECLARATION USED ONLY IN THIS FILE */ #ifdef __cplusplus - extern "C" { +extern "C" { #endif /** @@ -62,7 +62,7 @@ void plumed_dummy_finalize(void*); #endif #ifdef __cplusplus - } +} #endif /* END OF DECLARATION USED ONLY IN THIS FILE */ @@ -79,11 +79,11 @@ static int installed=0; static int dummy; -void*plumed_dummy_create(void){ +void*plumed_dummy_create(void) { return (void*)&dummy; } -void plumed_dummy_cmd(void*p,const char*key,const void*val){ +void plumed_dummy_cmd(void*p,const char*key,const void*val) { (void) p; /* avoid warning on unused parameter */ (void) key; /* avoid warning on unused parameter */ (void) val; /* avoid warning on unused parameter */ @@ -92,59 +92,59 @@ void plumed_dummy_cmd(void*p,const char*key,const void*val){ exit(1); } -void plumed_dummy_finalize(void*p){ +void plumed_dummy_finalize(void*p) { (void) p; /* avoid warning on unused parameter */ } #endif -plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f){ +plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmain_function_holder* f) { #ifdef __PLUMED_STATIC_KERNEL -/* - When __PLUMED_STATIC_KERNEL is defined, the function holder is initialized - to statically bound plumedmain_create,plumedmain_cmd,plumedmain_finalize and - cannot be changed. This saves from mis-set values for PLUMED_KERNEL -*/ - static plumed_plumedmain_function_holder g={plumedmain_create,plumedmain_cmd,plumedmain_finalize}; + /* + When __PLUMED_STATIC_KERNEL is defined, the function holder is initialized + to statically bound plumedmain_create,plumedmain_cmd,plumedmain_finalize and + cannot be changed. This saves from mis-set values for PLUMED_KERNEL + */ + static plumed_plumedmain_function_holder g= {plumedmain_create,plumedmain_cmd,plumedmain_finalize}; (void) f; /* avoid warning on unused parameter */ return &g; #else -/* - On the other hand, for runtime binding, we allow to reset the function holder on the - first call to plumed_kernel_register. - Notice that in principle plumed_kernel_register is entered *twice*: one for the first - plumed usage, and then from the PlumedMainInitializer object of the shared library. - This is why we set "first=0" only *after* loading the shared library. - Also notice that we should put some guard here for safe multithread calculations. -*/ - static plumed_plumedmain_function_holder g={plumed_dummy_create,plumed_dummy_cmd,plumed_dummy_finalize}; + /* + On the other hand, for runtime binding, we allow to reset the function holder on the + first call to plumed_kernel_register. + Notice that in principle plumed_kernel_register is entered *twice*: one for the first + plumed usage, and then from the PlumedMainInitializer object of the shared library. + This is why we set "first=0" only *after* loading the shared library. + Also notice that we should put some guard here for safe multithread calculations. + */ + static plumed_plumedmain_function_holder g= {plumed_dummy_create,plumed_dummy_cmd,plumed_dummy_finalize}; static int first=1; #ifdef __PLUMED_HAS_DLOPEN char* path; void* p; - if(first && f==NULL){ + if(first && f==NULL) { path=getenv("PLUMED_KERNEL"); #ifdef __PLUMED_DEFAULT_KERNEL -/* - This variable allows a default path for the kernel to be hardcoded. - Can be useful for hardcoding the predefined plumed location - still allowing the user to override this choice setting PLUMED_KERNEL. - The path should be chosen at compile time adding e.g. - -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib -*/ -/* This is required to add quotes */ + /* + This variable allows a default path for the kernel to be hardcoded. + Can be useful for hardcoding the predefined plumed location + still allowing the user to override this choice setting PLUMED_KERNEL. + The path should be chosen at compile time adding e.g. + -D__PLUMED_DEFAULT_KERNEL=/opt/local/lib/libplumed.dylib + */ + /* This is required to add quotes */ #define PLUMED_QUOTE_DIRECT(name) #name #define PLUMED_QUOTE(macro) PLUMED_QUOTE_DIRECT(macro) if(! (path && (*path) )) path=PLUMED_QUOTE(__PLUMED_DEFAULT_KERNEL); #endif - if(path && (*path)){ + if(path && (*path)) { fprintf(stderr,"+++ Loading the PLUMED kernel runtime +++\n"); fprintf(stderr,"+++ PLUMED_KERNEL=\"%s\" +++\n",path); p=dlopen(path,RTLD_NOW|RTLD_GLOBAL); - if(p){ + if(p) { fprintf(stderr,"+++ PLUMED kernel successfully loaded +++\n"); installed=1; - } else{ + } else { fprintf(stderr,"+++ PLUMED kernel not found ! +++\n"); fprintf(stderr,"+++ error message from dlopen(): %s\n",dlerror()); } @@ -159,7 +159,7 @@ plumed_plumedmain_function_holder* plumed_kernel_register(const plumed_plumedmai /* C wrappers: */ -plumed plumed_create(void){ +plumed plumed_create(void) { plumed p; plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL); assert(h); @@ -169,7 +169,7 @@ plumed plumed_create(void){ return p; } -void plumed_cmd(plumed p,const char*key,const void*val){ +void plumed_cmd(plumed p,const char*key,const void*val) { plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL); assert(p.p); assert(h); @@ -177,7 +177,7 @@ void plumed_cmd(plumed p,const char*key,const void*val){ (*(h->cmd))(p.p,key,val); } -void plumed_finalize(plumed p){ +void plumed_finalize(plumed p) { plumed_plumedmain_function_holder*h=plumed_kernel_register(NULL); assert(p.p); assert(h); @@ -186,63 +186,63 @@ void plumed_finalize(plumed p){ p.p=NULL; } -int plumed_installed(void){ +int plumed_installed(void) { plumed_kernel_register(NULL); return installed; } /* we declare a Plumed_g_main object here, in such a way that it is always available */ -static plumed gmain={NULL}; +static plumed gmain= {NULL}; -plumed plumed_global(void){ +plumed plumed_global(void) { return gmain; } -void plumed_gcreate(void){ +void plumed_gcreate(void) { assert(gmain.p==NULL); gmain=plumed_create(); } -void plumed_gcmd(const char*key,const void*val){ +void plumed_gcmd(const char*key,const void*val) { assert(gmain.p); plumed_cmd(gmain,key,val); } -void plumed_gfinalize(void){ +void plumed_gfinalize(void) { assert(gmain.p); plumed_finalize(gmain); gmain.p=NULL; } -int plumed_ginitialized(void){ +int plumed_ginitialized(void) { if(gmain.p) return 1; else return 0; } -void plumed_c2f(plumed p,char*c){ +void plumed_c2f(plumed p,char*c) { unsigned i; unsigned char* cc; -/* - Convert the address stored in p.p into a proper FORTRAN string - made of only ASCII characters. For this to work, the two following - assertions should be satisfied: -*/ + /* + Convert the address stored in p.p into a proper FORTRAN string + made of only ASCII characters. For this to work, the two following + assertions should be satisfied: + */ assert(CHAR_BIT<=12); assert(sizeof(p.p)<=16); assert(c); cc=(unsigned char*)&p.p; - for(i=0;i 199711L - but not supporting move semantics. Hopefully will not happen! -*/ + /* + PLUMED 2.4 requires a C++11 compiler. + Anyway, since Plumed.h file might be redistributed with other codes + and it should be possible to combine it with earlier PLUMED versions, + we here explicitly check if C+11 is available before enabling move semantics. + This could still create problems if a compiler 'cheats', setting __cplusplus > 199711L + but not supporting move semantics. Hopefully will not happen! + */ #if __cplusplus > 199711L -/** Move constructor. - Only if move semantics is enabled. - It allows storing PLMD::Plumed objects in STL containers. -*/ + /** Move constructor. + Only if move semantics is enabled. + It allows storing PLMD::Plumed objects in STL containers. + */ Plumed(Plumed&&); -/** Move assignment. - Only if move semantics is enabled. -*/ + /** Move assignment. + Only if move semantics is enabled. + */ Plumed& operator=(Plumed&&); #endif -/** - Retrieve the C plumed structure for this object -*/ + /** + Retrieve the C plumed structure for this object + */ operator plumed()const; -/** - Retrieve a FORTRAN handler for this object - \param c The FORTRAN handler (a char[32]). -*/ + /** + Retrieve a FORTRAN handler for this object + \param c The FORTRAN handler (a char[32]). + */ void toFortran(char*c)const; -/** - Send a command to this plumed object - \param key The name of the command to be executed - \param val The argument. It is declared as const to allow calls like p.cmd("A","B"), - but for some choice of key it can change the content - \note Equivalent to plumed_cmd() -*/ + /** + Send a command to this plumed object + \param key The name of the command to be executed + \param val The argument. It is declared as const to allow calls like p.cmd("A","B"), + but for some choice of key it can change the content + \note Equivalent to plumed_cmd() + */ void cmd(const char*key,const void*val=NULL); -/** - Destructor - - Destructor is virtual so as to allow correct inheritance from Plumed object. - To avoid linking problems with g++, I specify "inline" also here (in principle - it should be enough to specify it down in the definition of the function, but - for some reason that I do not understand g++ does not inline it properly in that - case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the - way it is done here seems to work properly). -*/ + /** + Destructor + + Destructor is virtual so as to allow correct inheritance from Plumed object. + To avoid linking problems with g++, I specify "inline" also here (in principle + it should be enough to specify it down in the definition of the function, but + for some reason that I do not understand g++ does not inline it properly in that + case and complains when Plumed.h is included but Plumed.o is not linked. Anyway, the + way it is done here seems to work properly). + */ inline virtual ~Plumed(); }; /* All methods are inlined so as to avoid the compilation of an extra c++ file */ inline -bool Plumed::installed(){ +bool Plumed::installed() { return plumed_installed(); } @@ -517,7 +517,7 @@ Plumed::Plumed(Plumed&& p): {} inline -Plumed& Plumed::operator=(Plumed&& p){ +Plumed& Plumed::operator=(Plumed&& p) { main=p.main; reference=p.reference; return *this; @@ -525,47 +525,47 @@ Plumed& Plumed::operator=(Plumed&& p){ #endif inline -Plumed::operator plumed()const{ +Plumed::operator plumed()const { return main; } inline -void Plumed::toFortran(char*c)const{ +void Plumed::toFortran(char*c)const { plumed_c2f(main,c); } inline -void Plumed::cmd(const char*key,const void*val){ +void Plumed::cmd(const char*key,const void*val) { plumed_cmd(main,key,val); } inline -Plumed::~Plumed(){ +Plumed::~Plumed() { if(!reference)plumed_finalize(main); } inline -bool Plumed::ginitialized(){ +bool Plumed::ginitialized() { return plumed_ginitialized(); } inline -void Plumed::gcreate(){ +void Plumed::gcreate() { plumed_gcreate(); } inline -void Plumed::gcmd(const char* key,const void* val){ +void Plumed::gcmd(const char* key,const void* val) { plumed_gcmd(key,val); } inline -void Plumed::gfinalize(){ +void Plumed::gfinalize() { plumed_gfinalize(); } inline -Plumed Plumed::global(){ +Plumed Plumed::global() { return plumed_global(); } From 840efb5862679ed5aabc6c411db827778b0ca182 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 21 Apr 2017 17:24:12 +0200 Subject: [PATCH 17/62] Fixed some examples to use label: syntax --- src/colvar/Energy.cpp | 2 +- src/colvar/Volume.cpp | 2 +- src/vatom/COM.cpp | 6 +++--- src/vatom/Ghost.cpp | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/colvar/Energy.cpp b/src/colvar/Energy.cpp index 11e2532e0e..6f79eb8831 100644 --- a/src/colvar/Energy.cpp +++ b/src/colvar/Energy.cpp @@ -49,7 +49,7 @@ using GROMACS with lambda replica exchange of with plumed-hrex branch. \par Examples The following input instructs plumed to print the energy of the system \verbatim -ENERGY LABEL=ene +ene: ENERGY PRINT ARG=ene \endverbatim (See also \ref PRINT). diff --git a/src/colvar/Volume.cpp b/src/colvar/Volume.cpp index 7b4fb9aacf..993dc802af 100644 --- a/src/colvar/Volume.cpp +++ b/src/colvar/Volume.cpp @@ -37,7 +37,7 @@ Calculate the volume of the simulation box. \par Examples The following input tells plumed to print the volume of the system \verbatim -VOLUME LABEL=vol +vol: VOLUME PRINT ARG=vol \endverbatim (See also \ref PRINT). diff --git a/src/vatom/COM.cpp b/src/vatom/COM.cpp index f9334eb6b6..8eb60b64d6 100644 --- a/src/vatom/COM.cpp +++ b/src/vatom/COM.cpp @@ -55,9 +55,9 @@ periodic image. The following input instructs plumed to print the distance between the center of mass for atoms 1,2,3,4,5,6,7 and that for atoms 15,20: \verbatim -COM ATOMS=1-7 LABEL=c1 -COM ATOMS=15,20 LABEL=c2 -DISTANCE ATOMS=c1,c2 LABEL=d1 +c1: COM ATOMS=1-7 +c2: COM ATOMS=15,20 +d1: DISTANCE ATOMS=c1,c2 PRINT ARG=d1 \endverbatim (See also \ref DISTANCE and \ref PRINT). diff --git a/src/vatom/Ghost.cpp b/src/vatom/Ghost.cpp index fcd7893775..b2c7837172 100644 --- a/src/vatom/Ghost.cpp +++ b/src/vatom/Ghost.cpp @@ -40,9 +40,9 @@ an atom list through the the label for the GHOST action that creates it. The following input instructs plumed to print the distance between the ghost atom and the center of mass for atoms 15,20: \verbatim -GHOST ATOMS=1,5,10 COORDINATES=10.0,10.0,10.0 LABEL=c1 -COM ATOMS=15,20 LABEL=c2 -DISTANCE ATOMS=c1,c2 LABEL=d1 +c1: GHOST ATOMS=1,5,10 COORDINATES=10.0,10.0,10.0 +c2: COM ATOMS=15,20 +d1: DISTANCE ATOMS=c1,c2 PRINT ARG=d1 \endverbatim (See also \ref DISTANCE and \ref PRINT). From c7f6d9bac31b4c840f98835d1763e89621959051 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 21 Apr 2017 18:37:28 +0200 Subject: [PATCH 18/62] Improved doxygen I added a primitive syntax highlighter for plumed examples. It links to manual as well. --- user-doc/Doxyfile | 10 +++++-- user-doc/go-doxygen | 4 +-- user-doc/plumed-syntax.awk | 54 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) create mode 100755 user-doc/plumed-syntax.awk diff --git a/user-doc/Doxyfile b/user-doc/Doxyfile index fdcd5c4771..7a884face6 100644 --- a/user-doc/Doxyfile +++ b/user-doc/Doxyfile @@ -228,11 +228,17 @@ TAB_SIZE = 8 # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. -ALIASES = "hidden=\htmlonly
To learn more
\endhtmlonly" \ +ALIASES = \ + "hidden=\htmlonly
To learn more
\endhtmlonly" \ "hidden{1}=\htmlonly
To learn more: \1
\endhtmlonly" \ "endhidden=\htmlonly
\endhtmlonly" \ "issue{1}=#\1" \ - "branch{1}=\1" + "branch{1}=\1" \ + "highlight{1}=\htmlonly\endhtmlonly\1\htmlonly\endhtmlonly" \ + "tarball{1}= TARBALL " \ + "plumedfile=\verbatim BEGIN_PLUMED_FILE" \ + "endplumedfile=\endverbatim" + # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" diff --git a/user-doc/go-doxygen b/user-doc/go-doxygen index aff6debd19..a3d87e2011 100755 --- a/user-doc/go-doxygen +++ b/user-doc/go-doxygen @@ -36,7 +36,8 @@ awk -v version="$version" '{ print "
  • Tutorials
  • " print "
  • Index of Actions
  • " } else print -}' $file > $file.tmp +}' $file | +awk -f plumed-syntax.awk > $file.tmp mv $file.tmp $file done # end of DOXYGEN <=1.8.10 @@ -51,7 +52,6 @@ var menudata={children:[ EOF # end of DOXYGEN >=1.8.12 - cat html/doxygen.css plumed.css > html/doxygen.css.tmp mv html/doxygen.css.tmp html/doxygen.css diff --git a/user-doc/plumed-syntax.awk b/user-doc/plumed-syntax.awk new file mode 100755 index 0000000000..7d261bca4f --- /dev/null +++ b/user-doc/plumed-syntax.awk @@ -0,0 +1,54 @@ +{ + if(match($0,"BEGIN_PLUMED_FILE")){ + inside=1; + sub("BEGIN_PLUMED_FILE",""); + print; + next; + } + if(inside && match($0,"")){ + inside=0; + print; + next; + } + if(!inside){ + print; + next; + } + +# DRAFT LINK TO DOC: + copy=$0 + sub("#.*","",copy); + nw=split(copy,words); + if(match(words[1],".*:$")){ + action=words[2]; + } else { + action=words[1]; + } + if(action=="__FILL__") action="" + actionx=""; + for(i=1;i<=length(action);i++){ + letter=substr(action,i,1); + if(match(letter,"[A-Z]")) letter = "_" tolower(letter); + actionx=actionx letter; + } + if(incontinuation) action=""; + if(incontinuation && words[1]=="...") incontinuation=0; + else if(!incontinuation && words[nw]=="...") incontinuation=1; + + if(length(action)>0){ + actionfile="html/" actionx ".html"; + if(getline tmp < actionfile < 0) print "WARNING: file " actionfile " does not exist" > "/dev/stderr"; + else { + p=match($0,action); + $0=substr($0,1,p-1) "" action "" substr($0,p+length(action)); + } + } + + gsub("__FILL__","__FILL__"); + +# comments: +# sub("#","#"); +# if(match($0,"span style=")) $0=$0 ""; + sub("#.*$","&"); + print +} From 8c0b1386be6c5afbb5238f1dc26a87dbb3d55cce Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Mon, 24 Apr 2017 11:12:10 +0200 Subject: [PATCH 19/62] Syntax highlight in doc I replaced verbatim endverbatim with plumedfile endplumedfile in (hopefully) all the places where it was appropriate. --- src/adjmat/ClusterDiameter.cpp | 4 +- src/adjmat/ClusterDistribution.cpp | 4 +- src/adjmat/ClusterProperties.cpp | 4 +- src/adjmat/ClusterSize.cpp | 4 +- src/adjmat/ClusterWithSurface.cpp | 4 +- src/adjmat/ContactAlignedMatrix.cpp | 4 +- src/adjmat/ContactMatrix.cpp | 4 +- src/adjmat/DFSClustering.cpp | 4 +- src/adjmat/HbondMatrix.cpp | 4 +- src/adjmat/MatrixColumnSums.cpp | 8 +-- src/adjmat/MatrixRowSums.cpp | 8 +-- src/adjmat/OutputCluster.cpp | 4 +- src/adjmat/SMACMatrix.cpp | 4 +- src/adjmat/Sprint.cpp | 8 +-- src/analysis/Average.cpp | 12 ++-- .../ClassicalMultiDimensionalScaling.cpp | 4 +- src/analysis/Commit.cpp | 4 +- src/analysis/Histogram.cpp | 16 ++--- src/analysis/PCA.cpp | 8 +-- src/bias/ABMD.cpp | 5 +- src/bias/BiasValue.cpp | 11 ++-- src/bias/ExtendedLagrangian.cpp | 10 ++- src/bias/External.cpp | 9 ++- src/bias/LWalls.cpp | 4 +- src/bias/MetaD.cpp | 36 +++++----- src/bias/Metainference.cpp | 10 ++- src/bias/MovingRestraint.cpp | 12 ++-- src/bias/PBMetaD.cpp | 16 ++--- src/bias/Restraint.cpp | 5 +- src/bias/ReweightBias.cpp | 4 +- src/bias/ReweightMetad.cpp | 5 +- src/bias/UWalls.cpp | 5 +- src/colvar/Angle.cpp | 5 +- src/colvar/CS2Backbone.cpp | 8 +-- src/colvar/Cell.cpp | 5 +- src/colvar/Constant.cpp | 9 ++- src/colvar/ContactMap.cpp | 15 ++--- src/colvar/Coordination.cpp | 13 ++-- src/colvar/DHEnergy.cpp | 5 +- src/colvar/DRMSD.cpp | 8 +-- src/colvar/Dimer.cpp | 20 +++--- src/colvar/Dipole.cpp | 5 +- src/colvar/Distance.cpp | 23 +++---- src/colvar/ERMSD.cpp | 4 +- src/colvar/Energy.cpp | 5 +- src/colvar/Fake.cpp | 5 +- src/colvar/FretEfficiency.cpp | 10 ++- src/colvar/Gyration.cpp | 5 +- src/colvar/Implicit.cpp | 5 +- src/colvar/Jcoupling.cpp | 8 +-- src/colvar/MultiRMSD.cpp | 8 +-- src/colvar/NOE.cpp | 5 +- src/colvar/PCARMSD.cpp | 4 +- src/colvar/PRE.cpp | 4 +- src/colvar/PathMSD.cpp | 4 +- src/colvar/Position.cpp | 6 +- src/colvar/PropertyMap.cpp | 4 +- src/colvar/Puckering.cpp | 4 +- src/colvar/RDC.cpp | 5 +- src/colvar/RMSD.cpp | 4 +- src/colvar/Template.cpp | 4 +- src/colvar/Torsion.cpp | 8 +-- src/colvar/Volume.cpp | 5 +- src/crystallization/Fccubic.cpp | 4 +- src/crystallization/Gradient.cpp | 8 +-- .../InterMolecularTorsions.cpp | 4 +- src/crystallization/MoleculeOrientation.cpp | 4 +- src/crystallization/Q3.cpp | 24 +++---- src/crystallization/Q4.cpp | 24 +++---- src/crystallization/Q6.cpp | 24 +++---- src/crystallization/SMAC.cpp | 8 +-- src/crystallization/SimpleCubic.cpp | 8 +-- src/crystallization/Tetrahedral.cpp | 8 +-- src/eds/EDS.cpp | 12 ++-- src/function/Combine.cpp | 8 +-- src/function/Ensemble.cpp | 5 +- src/function/FuncPathMSD.cpp | 8 +-- src/function/LocalEnsemble.cpp | 4 +- src/function/Matheval.cpp | 16 ++--- src/function/Piecewise.cpp | 5 +- src/function/Sort.cpp | 5 +- src/function/Stats.cpp | 4 +- src/function/Target.cpp | 4 +- src/generic/Debug.cpp | 4 +- src/generic/DumpAtoms.cpp | 10 ++- src/generic/DumpDerivatives.cpp | 4 +- src/generic/DumpForces.cpp | 6 +- src/generic/DumpMassCharge.cpp | 9 ++- src/generic/DumpProjections.cpp | 4 +- src/generic/EffectiveEnergyDrift.cpp | 8 +-- src/generic/FitToTemplate.cpp | 5 +- src/generic/Flush.cpp | 4 +- src/generic/Group.cpp | 24 +++---- src/generic/Include.cpp | 12 ++-- src/generic/Print.cpp | 5 +- src/generic/RandomExchanges.cpp | 12 ++-- src/generic/Read.cpp | 4 +- src/generic/ResetCell.cpp | 5 +- src/generic/Time.cpp | 5 +- src/generic/UpdateIf.cpp | 5 +- src/generic/WholeMolecules.cpp | 15 ++--- src/generic/WrapAround.cpp | 20 +++--- src/gridtools/ConvertToFES.cpp | 4 +- src/gridtools/DumpCube.cpp | 4 +- src/gridtools/DumpGrid.cpp | 16 ++--- src/gridtools/FindContour.cpp | 4 +- src/gridtools/FindSphericalContour.cpp | 4 +- src/gridtools/FourierTransform.cpp | 4 +- src/gridtools/InterpolateGrid.cpp | 4 +- src/maketools/plumedcheck | 6 ++ src/manyrestraints/LWalls.cpp | 4 +- src/manyrestraints/UWalls.cpp | 4 +- src/mapping/PCAVars.cpp | 4 +- src/mapping/Path.cpp | 16 ++--- src/mapping/PropertyMap.cpp | 4 +- src/multicolvar/AlphaBeta.cpp | 12 ++-- src/multicolvar/Angles.cpp | 12 ++-- src/multicolvar/Bridge.cpp | 4 +- src/multicolvar/CenterOfMultiColvar.cpp | 8 +-- src/multicolvar/CoordinationNumbers.cpp | 8 +-- src/multicolvar/Density.cpp | 4 +- src/multicolvar/DihedralCorrelation.cpp | 8 +-- src/multicolvar/DistanceFromContour.cpp | 4 +- src/multicolvar/Distances.cpp | 24 +++---- src/multicolvar/DumpMultiColvar.cpp | 4 +- src/multicolvar/FilterBetween.cpp | 16 ++--- src/multicolvar/FilterLessThan.cpp | 12 ++-- src/multicolvar/FilterMoreThan.cpp | 16 ++--- src/multicolvar/InPlaneDistances.cpp | 4 +- src/multicolvar/LocalAverage.cpp | 8 +-- src/multicolvar/MultiColvarDensity.cpp | 8 +-- src/multicolvar/NumberOfLinks.cpp | 8 +-- src/multicolvar/Torsions.cpp | 8 +-- src/multicolvar/VolumeAround.cpp | 4 +- src/multicolvar/VolumeCavity.cpp | 8 +-- src/multicolvar/VolumeInCylinder.cpp | 4 +- src/multicolvar/VolumeInSphere.cpp | 4 +- src/multicolvar/VolumeTetrapore.cpp | 8 +-- src/multicolvar/XAngle.cpp | 12 ++-- src/multicolvar/XDistances.cpp | 48 +++++++------- src/multicolvar/XYDistances.cpp | 12 ++-- src/multicolvar/XYTorsion.cpp | 24 +++---- src/secondarystructure/AlphaRMSD.cpp | 5 +- src/secondarystructure/AntibetaRMSD.cpp | 5 +- src/secondarystructure/ParabetaRMSD.cpp | 5 +- src/setup/Load.cpp | 12 ++-- src/setup/MolInfo.cpp | 10 ++- src/setup/Restart.cpp | 15 ++--- src/setup/Units.cpp | 9 ++- src/vatom/COM.cpp | 5 +- src/vatom/Center.cpp | 5 +- src/vatom/FixedAtom.cpp | 10 ++- src/vatom/Ghost.cpp | 5 +- user-doc/Analysis.txt | 8 +-- user-doc/Colvar.txt | 8 +-- user-doc/Files.txt | 10 ++- user-doc/Functions.txt | 4 +- user-doc/Group.txt | 16 ++--- user-doc/Misc.txt | 65 +++++++++---------- user-doc/Performances.txt | 12 ++-- user-doc/Regex.txt | 16 ++--- user-doc/Syntax.txt | 14 ++-- 162 files changed, 675 insertions(+), 749 deletions(-) diff --git a/src/adjmat/ClusterDiameter.cpp b/src/adjmat/ClusterDiameter.cpp index ec26f2eeb9..8bebeab928 100644 --- a/src/adjmat/ClusterDiameter.cpp +++ b/src/adjmat/ClusterDiameter.cpp @@ -40,7 +40,7 @@ than 2.0 and if they are within 6.0 nm of each other. Depth first search cluste between every pair of atoms that are within the largest of the clusters found is then calculated and the largest of these distances is output to a file named colvar. -\verbatim +\plumedfile # Calculate coordination numbers c1: COORDINATIONNUMBER SPECIES=1-512 SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} # Select coordination numbers that are more than 2.0 @@ -52,7 +52,7 @@ dfs: DFSCLUSTERING MATRIX=mat clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 dia: CLUSTER_DIAMETER CLUSTERS=dfs CLUSTER=1 PRINT ARG=dia FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/ClusterDistribution.cpp b/src/adjmat/ClusterDistribution.cpp index 93f12fb04c..afd7c956e5 100644 --- a/src/adjmat/ClusterDistribution.cpp +++ b/src/adjmat/ClusterDistribution.cpp @@ -44,7 +44,7 @@ algorithm on the corresponding graph. The number of componets in this graph that As discussed in \cite tribello-clustering this input was used to analyse the formation of a polycrystal of GeTe from amorphous GeTe. -\verbatim +\plumedfile q6: Q6 SPECIES=1-32768 SWITCH={GAUSSIAN D_0=5.29 R_0=0.01 D_MAX=5.3} LOWMEM lq6: LOCAL_Q6 SPECIES=q6 SWITCH={GAUSSIAN D_0=5.29 R_0=0.01 D_MAX=5.3} LOWMEM flq6: MFILTER_MORE DATA=lq6 SWITCH={GAUSSIAN D_0=0.19 R_0=0.01 D_MAX=0.2} @@ -54,7 +54,7 @@ mat: CONTACT_MATRIX ATOMS=fcc SWITCH={GAUSSIAN D_0=3.59 R_0=0.01 D_MAX=3.6} dfs: DFSCLUSTERING MATRIX=mat nclust: CLUSTER_DISTRIBUTION CLUSTERS=dfs TRANSFORM={GAUSSIAN D_0=5.99 R_0=0.01 D_MAX=6.0} MORE_THAN={GAUSSIAN D_0=26.99 R_0=0.01 D_MAX=27} PRINT ARG=nclust.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/ClusterProperties.cpp b/src/adjmat/ClusterProperties.cpp index 9a0d38e5be..b1d891fe06 100644 --- a/src/adjmat/ClusterProperties.cpp +++ b/src/adjmat/ClusterProperties.cpp @@ -42,13 +42,13 @@ a graph. This dfs action then finds the largest connected component in this gra numbers for the atoms in this largest connected component are then computed and this quantity is output to a colvar file. The way this input can be used is described in detail in \cite tribello-clustering. -\verbatim +\plumedfile lq: COORDINATIONNUMBER SPECIES=1-100 SWITCH={CUBIC D_0=0.45 D_MAX=0.55} LOWMEM cm: CONTACT_MATRIX ATOMS=lq SWITCH={CUBIC D_0=0.45 D_MAX=0.55} dfs: DFSCLUSTERING MATRIX=cm clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM PRINT ARG=clust1.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/ClusterSize.cpp b/src/adjmat/ClusterSize.cpp index b0b22621d6..4ae18bb491 100644 --- a/src/adjmat/ClusterSize.cpp +++ b/src/adjmat/ClusterSize.cpp @@ -39,7 +39,7 @@ The following input uses PLUMED to calculate a adjacency matrix that connects a than 2.0 and if they are within 6.0 nm of each other. Depth first search clustering is used to find the connected components in this matrix and then the number of atoms in the largest cluster is found. This quantity is then output to a file called colvar -\verbatim +\plumedfile # Calculate coordination numbers c1: COORDINATIONNUMBER SPECIES=1-512 SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} # Select coordination numbers that are more than 2.0 @@ -51,7 +51,7 @@ dfs: DFSCLUSTERING MATRIX=mat clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 nat: CLUSTER_NATOMS CLUSTERS=dfs CLUSTER=1 PRINT ARG=nat FILE=COLVAR -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/ClusterWithSurface.cpp b/src/adjmat/ClusterWithSurface.cpp index ab472eee50..1042accd05 100644 --- a/src/adjmat/ClusterWithSurface.cpp +++ b/src/adjmat/ClusterWithSurface.cpp @@ -44,7 +44,7 @@ number of atoms with indices that are between 1 and 1996 and that are either in atoms within the the second largest cluster are then counted and this number of atoms is output to a file called size. In addition the indices of the atoms that were counted are output to a file called dfs2.dat. -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-1996 SWITCH={CUBIC D_0=0.34 D_MAX=0.38} cf: MFILTER_LESS DATA=c1 SWITCH={CUBIC D_0=13 D_MAX=13.5} mat: CONTACT_MATRIX ATOMS=cf SWITCH={CUBIC D_0=0.34 D_MAX=0.38} @@ -53,7 +53,7 @@ clust2a: CLUSTER_WITHSURFACE CLUSTERS=dfs RCUT_SURF=0.3 size2a: CLUSTER_NATOMS CLUSTERS=clust2a CLUSTER=2 PRINT ARG=size2a FILE=size FMT=%8.4f OUTPUT_CLUSTER CLUSTERS=clust2a CLUSTER=2 FILE=dfs2.dat -\endverbatim +\endplumedfile */ diff --git a/src/adjmat/ContactAlignedMatrix.cpp b/src/adjmat/ContactAlignedMatrix.cpp index e1bdfcdba0..d00542aea1 100644 --- a/src/adjmat/ContactAlignedMatrix.cpp +++ b/src/adjmat/ContactAlignedMatrix.cpp @@ -57,12 +57,12 @@ is greater than 0.5. The sum of the rows of this matrix are then computed. The many of the molecules that are within the first coordination sphere of molecule \f$i\f$ have an orientation that is similar to that of molecule \f$i\f$. We thus calculate the number of these "coordination numbers" that are greater than 1.0 and output this quantity to a file. -\verbatim +\plumedfile m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 mat: ALIGNED_MATRIX ATOMS=m1 SWITCH={RATIONAL R_0=0.1} ORIENTATION_SWITCH={RATIONAL R_0=0.1 D_MAX=0.5} rr: ROWSUMS MATRIX=mat MORE_THAN={RATIONAL D_0=1.0 R_0=0.1} PRINT ARG=rr.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/ContactMatrix.cpp b/src/adjmat/ContactMatrix.cpp index 1105a1aa23..e1a332a2af 100644 --- a/src/adjmat/ContactMatrix.cpp +++ b/src/adjmat/ContactMatrix.cpp @@ -48,11 +48,11 @@ The input shown below calculates a \f$6 \times 6\f$ matrix whose elements are eq of each other and which is zero otherwise. The columns in this matrix are then summed so as to give the coordination number for each atom. The final quantity output in the colvar file is thus the average coordination number. -\verbatim +\plumedfile aa: CONTACT_MATRIX ATOMS=1-6 SWITCH={EXP D_0=0.2 R_0=0.1 D_MAX=0.66} COLUMNSUMS MATRIX=mat MEAN LABEL=csums PRINT ARG=csums.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/DFSClustering.cpp b/src/adjmat/DFSClustering.cpp index af0dc327e8..23bf5c592c 100644 --- a/src/adjmat/DFSClustering.cpp +++ b/src/adjmat/DFSClustering.cpp @@ -53,13 +53,13 @@ a graph. This dfs action then finds the largest connected component in this gra numbers for the atoms in this largest connected component are then computed and this quantity is output to a colvar file. The way this input can be used is described in detail in \cite tribello-clustering. -\verbatim +\plumedfile lq: COORDINATIONNUMBER SPECIES=1-100 SWITCH={CUBIC D_0=0.45 D_MAX=0.55} LOWMEM cm: CONTACT_MATRIX ATOMS=lq SWITCH={CUBIC D_0=0.45 D_MAX=0.55} dfs: DFSCLUSTERING MATRIX=cm clust1: CLUSTER_PROPERTIES CLUSTERS=dfs CLUSTER=1 SUM PRINT ARG=clust1.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/HbondMatrix.cpp b/src/adjmat/HbondMatrix.cpp index f75e95754b..32e7989dee 100644 --- a/src/adjmat/HbondMatrix.cpp +++ b/src/adjmat/HbondMatrix.cpp @@ -66,13 +66,13 @@ on the number of hydrogen bonds each of the water molecules donates and accepts. five columns of data. The first four of these columns are a label for the atom and the x, y and z position of the oxygen. The last column is then the number of accepted/donated hydrogen bonds. -\verbatim +\plumedfile mat: HBOND_MATRIX ATOMS=1-192:3 HYDROGENS=2-192:3,3-192:3 SWITCH={RATIONAL R_0=3.20} HSWITCH={RATIONAL R_0=2.30} ASWITCH={RATIONAL R_0=0.167pi} SUM rsums: ROWSUMS MATRIX=mat MEAN csums: COLUMNSUMS MATRIX=mat MEAN DUMPMULTICOLVAR DATA=rsums FILE=donors.xyz DUMPMULTICOLVAR DATA=csums FILE=acceptors.x -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/MatrixColumnSums.cpp b/src/adjmat/MatrixColumnSums.cpp index 7735023490..cae24fcec8 100644 --- a/src/adjmat/MatrixColumnSums.cpp +++ b/src/adjmat/MatrixColumnSums.cpp @@ -43,21 +43,21 @@ tells you whether atoms \f$i\f$ and \f$j\f$ are within 1.0 nm of each other. Th and the average value is computed. As such the following input provides an alternative method for calculating the coordination numbers of atoms 1 to 10. -\verbatim +\plumedfile mat: CONTACT_MATRIX ATOMS=1-10 SWITCH={RATIONAL R_0=1.0} rsums: COLUMNSUMS MATRIX=mat MEAN PRINT ARG=rsums.* FILE=colvar -\endverbatim +\endplumedfile The following input demonstrates another way that an average coordination number can be computed. This input calculates the number of atoms with indices between 1 and 5 that are within the first coordination spheres of each of the atoms within indices between 6 and 15. The average coordination number is then calculated from these fifteen coordination numbers and this quantity is output to a file. -\verbatim +\plumedfile mat2: CONTACT_MATRIX ATOMSA=1-5 ATOMSB=6-15 SWITCH={RATIONAL R_0=1.0} rsums: COLUMNSUMS MATRIX=mat2 MEAN PRINT ARG=rsums.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/MatrixRowSums.cpp b/src/adjmat/MatrixRowSums.cpp index 038aa89a71..6ef15fb282 100644 --- a/src/adjmat/MatrixRowSums.cpp +++ b/src/adjmat/MatrixRowSums.cpp @@ -43,21 +43,21 @@ tells you whether atoms \f$i\f$ and \f$j\f$ are within 1.0 nm of each other. Th and the average value is computed. As such the following input provides an alternative method for calculating the coordination numbers of atoms 1 to 10. -\verbatim +\plumedfile mat: CONTACT_MATRIX ATOMS=1-10 SWITCH={RATIONAL R_0=1.0} rsums: ROWSUMS MATRIX=mat MEAN PRINT ARG=rsums.* FILE=colvar -\endverbatim +\endplumedfile The following input demonstrates another way that an average coordination number can be computed. This input calculates the number of atoms with indices between 6 and 15 that are within the first coordination spheres of each of the atoms within indices between 1 and 5. The average coordination number is then calculated from these five coordination numbers and this quantity is output to a file. -\verbatim +\plumedfile mat2: CONTACT_MATRIX ATOMSA=1-5 ATOMSB=6-15 SWITCH={RATIONAL R_0=1.0} rsums: ROWSUMS MATRIX=mat2 MEAN PRINT ARG=rsums.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/OutputCluster.cpp b/src/adjmat/OutputCluster.cpp index c2b752f0d0..4dd430f3c7 100644 --- a/src/adjmat/OutputCluster.cpp +++ b/src/adjmat/OutputCluster.cpp @@ -47,13 +47,13 @@ that satisfy this criteria. The DFS algorithm is then used to find the connecte in this matrix and the indices of the atoms in the largest connected component are then output to a file. -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-1996 SWITCH={CUBIC D_0=0.34 D_MAX=0.38} cf: MFILTER_LESS DATA=c1 SWITCH={CUBIC D_0=13 D_MAX=13.5} mat: CONTACT_MATRIX ATOMS=cf SWITCH={CUBIC D_0=0.34 D_MAX=0.38} dfs: DFSCLUSTERING MATRIX=mat OUTPUT_CLUSTER CLUSTERS=dfs CLUSTER=1 FILE=dfs.dat -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/SMACMatrix.cpp b/src/adjmat/SMACMatrix.cpp index ac433076bd..a4e8288f49 100644 --- a/src/adjmat/SMACMatrix.cpp +++ b/src/adjmat/SMACMatrix.cpp @@ -49,7 +49,7 @@ molecules \f$i\f$ and \f$j\f$ are within 6 angstroms of each other and if the to of these molecules is close to 0 or \f$\pi\f$. The various connected components of this matrix are determined using the \ref DFSCLUSTERING algorithm and then the size of the largest cluster of connectes molecules is output to a colvar file -\verbatim +\plumedfile UNITS LENGTH=A MOLECULES ... @@ -70,7 +70,7 @@ SMAC_MATRIX ... dfs1: DFSCLUSTERING MATRIX=smacm cc2: CLUSTER_NATOMS CLUSTERS=dfs1 CLUSTER=1 PRINT ARG=smac.*,cc1.*,cc2 FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/adjmat/Sprint.cpp b/src/adjmat/Sprint.cpp index f7e0a0da8f..3e90100e8e 100644 --- a/src/adjmat/Sprint.cpp +++ b/src/adjmat/Sprint.cpp @@ -46,17 +46,17 @@ This example input calculates the 7 SPRINT coordinates for a 7 atom cluster of L atoms and prints their values to a file. In this input the SPRINT coordinates are calculated in the manner described in ?? so two atoms are adjacent if they are within a cutoff: -\verbatim +\plumedfile DENSITY SPECIES=1-7 LABEL=d1 CONTACT_MATRIX ATOMS=d1 SWITCH={RATIONAL R_0=0.1} LABEL=mat SPRINT MATRIX=mat LABEL=ss PRINT ARG=ss.* FILE=colvar -\endverbatim +\endplumedfile This example input calculates the 14 SPRINT coordinates foa a molecule composed of 7 hydrogen and 7 carbon atoms. Once again two atoms are adjacent if they are within a cutoff: -\verbatim +\plumedfile DENSITY SPECIES=1-7 LABEL=c DENSITY SPECIES=8-14 LABEL=h @@ -71,7 +71,7 @@ CONTACT_MATRIX ... SPRINT MATRIX=mat LABEL=ss PRINT ARG=ss.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/analysis/Average.cpp b/src/analysis/Average.cpp index c96b2556bb..9d0566da8e 100644 --- a/src/analysis/Average.cpp +++ b/src/analysis/Average.cpp @@ -51,11 +51,11 @@ and output this to a file called COLVAR. In this example it is assumed that no on the system and that the weights, \f$w(t')\f$ in the formulae above can thus all be set equal to one. -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,2 d1a: AVERAGE ARG=d1 PRINT ARG=d1a FILE=colvar STRIDE=100 -\endverbatim +\endplumedfile The following example calculates the ensemble average for the torsional angle involving atoms 1, 2, 3 and 4. At variance with the previous example this quantity is periodic so the second formula in the above introduction @@ -65,23 +65,23 @@ forgotten and the process of averaging is begun again. The quantities output in block averages taken over the first 100 frames of the trajectory, the block average over the second 100 frames of trajectory and so on. -\verbatim +\plumedfile t1: TORSION ATOMS=1,2,3,4 t1a: AVERAGE ARG=t1 CLEAR=100 PRINT ARG=t1a FILE=colvar STRIDE=100 -\endverbatim +\endplumedfile This third example incorporates a bias. Notice that the effect the bias has on the ensemble average is removed by taking advantage of the \ref REWEIGHT_BIAS method. The final ensemble averages output to the file are thus block ensemble averages for the unbiased canononical ensemble at a temperature of 300 K. -\verbatim +\plumedfile t1: TORSION ATOMS=1,2,3,4 RESTRAINT ARG=t1 AT=pi KAPPA=100. ww: REWEIGHT_BIAS TEMP=300 t1a: AVERAGE ARG=t1 LOGWEIGHTS=ww CLEAR=100 PRINT ARG=t1a FILE=colvar STRIDE=100 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/analysis/ClassicalMultiDimensionalScaling.cpp b/src/analysis/ClassicalMultiDimensionalScaling.cpp index 93bb25f1d4..68ac6aeae3 100644 --- a/src/analysis/ClassicalMultiDimensionalScaling.cpp +++ b/src/analysis/ClassicalMultiDimensionalScaling.cpp @@ -55,7 +55,7 @@ can be found in the tutorial \ref belfast-3 and in the following -\verbatim +\plumedfile # This should be a sample input. t: TEMPLATE ATOMS=1,2 PRINT ARG=t STRIDE=100 FILE=COLVAR -\endverbatim +\endplumedfile (see also \ref PRINT) diff --git a/src/colvar/Torsion.cpp b/src/colvar/Torsion.cpp index 274d0565a4..4b697b0697 100644 --- a/src/colvar/Torsion.cpp +++ b/src/colvar/Torsion.cpp @@ -43,23 +43,23 @@ orthogonal to an axis. This input tells plumed to print the torsional angle between atoms 1, 2, 3 and 4 on file COLVAR. -\verbatim +\plumedfile t: TORSION ATOMS=1,2,3,4 # this is an alternative, equivalent, definition: # t: TORSION VECTOR1=2,1 AXIS=2,3 VECTOR2=3,4 PRINT ARG=t FILE=COLVAR -\endverbatim +\endplumedfile If you are working with a protein you can specify the special named torsion angles \f$\phi\f$, \f$\psi\f$, \f$\omega\f$ and \f$\chi_1\f$ by using TORSION in combination with the \ref MOLINFO command. This can be done by using the following syntax. -\verbatim +\plumedfile MOLINFO MOLTYPE=protein STRUCTURE=myprotein.pdb t1: TORSION ATOMS=@phi-3 t2: TORSION ATOMS=@psi-4 PRINT ARG=t1,t2 FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle in the third residue of the protein. Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the 4th residue of the protein. diff --git a/src/colvar/Volume.cpp b/src/colvar/Volume.cpp index 993dc802af..837f6ce758 100644 --- a/src/colvar/Volume.cpp +++ b/src/colvar/Volume.cpp @@ -36,11 +36,10 @@ Calculate the volume of the simulation box. \par Examples The following input tells plumed to print the volume of the system -\verbatim +\plumedfile vol: VOLUME PRINT ARG=vol -\endverbatim -(See also \ref PRINT). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/Fccubic.cpp b/src/crystallization/Fccubic.cpp index fc1793ab39..47154f4c6f 100644 --- a/src/crystallization/Fccubic.cpp +++ b/src/crystallization/Fccubic.cpp @@ -63,10 +63,10 @@ so on. Notice also that you can rotate the reference frame if you are using a n The following input calculates the FCCUBIC parameter for the 64 atoms in the system and then calculates and prints the average value for this quantity. -\verbatim +\plumedfile FCCUBIC SPECIES=1-64 SWITCH={RATIONAL D_0=3.0 R_0=1.5} MEAN LABEL=d PRINT ARG=d.* FILE=colv -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/Gradient.cpp b/src/crystallization/Gradient.cpp index 173d9e5adb..e3af25856d 100644 --- a/src/crystallization/Gradient.cpp +++ b/src/crystallization/Gradient.cpp @@ -39,22 +39,22 @@ The input below calculates the gradient of the density of atoms in the manner described in \cite fede-grad in order to detect whether or not atoms are distributed uniformly along the x-axis of the simulation cell. -\verbatim +\plumedfile d1: DENSITY SPECIES=1-50 s1: GRADIENT ORIGIN=1 DATA=d1 DIR=x NBINS=4 SIGMA=1.0 PRINT ARG=s1 FILE=colvar -\endverbatim +\endplumedfile The input below calculates the coordination numbers of the 50 atoms in the simulation cell. The gradient of this quantity is then evaluated in the manner described using the equation above to detect whether the average values of the coordination number are uniformly distributed along the x-axis of the simulation cell. -\verbatim +\plumedfile d2: COORDINATIONNUMBER SPECIES=1-50 SWITCH={RATIONAL R_0=2.0} MORE_THAN={EXP R_0=4.0} s2: GRADIENT ORIGIN=1 DATA=d2 DIR=x NBINS=4 SIGMA=1.0 PRINT ARG=s2 FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/InterMolecularTorsions.cpp b/src/crystallization/InterMolecularTorsions.cpp index 3839e094d6..58294492f6 100644 --- a/src/crystallization/InterMolecularTorsions.cpp +++ b/src/crystallization/InterMolecularTorsions.cpp @@ -64,12 +64,12 @@ between the two molecules. As such the torsional angles between molecules that histogram while the torsional angles between molecules that are far apart does not contribute to the histogram. The histogram is averaged over the whole trajectory and output once all the trajectory frames have been read. -\verbatim +\plumedfile m1: MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 tt_p: INTERMOLECULARTORSIONS MOLS=m1 SWITCH={RATIONAL R_0=0.25 D_0=2.0 D_MAX=3.0} htt_p: HISTOGRAM DATA=tt_p GRID_MIN=-pi GRID_MAX=pi BANDWIDTH=0.1 GRID_BIN=200 STRIDE=1 DUMPGRID GRID=htt_p FILE=myhist.out -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/MoleculeOrientation.cpp b/src/crystallization/MoleculeOrientation.cpp index 5bade7022c..6001f6f095 100644 --- a/src/crystallization/MoleculeOrientation.cpp +++ b/src/crystallization/MoleculeOrientation.cpp @@ -39,10 +39,10 @@ The following input tells plumed to calculate the distances between two of the a This is done for the same set of atoms four different molecules and the average separation is then calculated. -\verbatim +\plumedfile MOLECULES MOL1=1,2 MOL2=3,4 MOL3=5,6 MOL4=7,8 MEAN LABEL=mm PRINT ARG=mm.mean FILE=colvar -\endverbatim +\endplumedfile */ diff --git a/src/crystallization/Q3.cpp b/src/crystallization/Q3.cpp index 6c3aeedc2f..038115a921 100644 --- a/src/crystallization/Q3.cpp +++ b/src/crystallization/Q3.cpp @@ -60,28 +60,28 @@ the \f$q_{3}\f$ vectors on adjacent atoms. More information on these variables The following command calculates the average Q3 parameter for the 64 atoms in a box of Lennard Jones and prints this quantity to a file called colvar: -\verbatim +\plumedfile Q3 SPECIES=1-64 D_0=1.3 R_0=0.2 MEAN LABEL=q3 PRINT ARG=q3.mean FILE=colvar -\endverbatim +\endplumedfile The following command calculates the histogram of Q3 parameters for the 64 atoms in a box of Lennard Jones and prints these quantities to a file called colvar: -\verbatim +\plumedfile Q3 SPECIES=1-64 D_0=1.3 R_0=0.2 HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=1.0 NBINS=20 SMEAR=0.1} LABEL=q3 PRINT ARG=q3.* FILE=colvar -\endverbatim +\endplumedfile The following command could be used to measure the Q3 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q3 paramter is calculated and output to a file called colvar -\verbatim +\plumedfile Q3 SPECIESA=1-64 SPECIESB=65-128 D_0=1.3 R_0=0.2 MEAN LABEL=q3 PRINT ARG=q3.mean FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC @@ -136,30 +136,30 @@ adjacent atoms is correlated. The following command calculates the average value of the LOCAL_Q3 parameter for the 64 Lennard Jones atoms in the system under study and prints this quantity to a file called colvar. -\verbatim +\plumedfile Q3 SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=q3 LOCAL_Q3 ARG=q3 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LABEL=lq3 PRINT ARG=lq3.mean FILE=colvar -\endverbatim +\endplumedfile The following input calculates the distribution of LOCAL_Q3 parameters at any given time and outputs this information to a file. -\verbatim +\plumedfile Q3 SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=q3 LOCAL_Q3 ARG=q3 SWITCH={RATIONAL D_0=1.3 R_0=0.2} HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=1.0 NBINS=20 SMEAR=0.1} LABEL=lq3 PRINT ARG=lq3.* FILE=colvar -\endverbatim +\endplumedfile The following calculates the LOCAL_Q3 parameters for atoms 1-5 only. For each of these atoms comparisons of the geometry of the coordination sphere are done with those of all the other atoms in the system. The final quantity is the average and is outputted to a file -\verbatim +\plumedfile Q3 SPECIESA=1-5 SPECIESB=1-64 D_0=1.3 R_0=0.2 LABEL=q3a Q3 SPECIESA=6-64 SPECIESB=1-64 D_0=1.3 R_0=0.2 LABEL=q3b LOCAL_Q3 ARG=q3a,q3b SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LOWMEM LABEL=w3 PRINT ARG=w3.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/Q4.cpp b/src/crystallization/Q4.cpp index fa76b0d10e..a4f7d327b2 100644 --- a/src/crystallization/Q4.cpp +++ b/src/crystallization/Q4.cpp @@ -60,28 +60,28 @@ the \f$q_{4}\f$ vectors on adjacent atoms. More information on these variables The following command calculates the average Q4 parameter for the 64 atoms in a box of Lennard Jones and prints this quantity to a file called colvar: -\verbatim +\plumedfile Q4 SPECIES=1-64 D_0=1.3 R_0=0.2 MEAN LABEL=q4 PRINT ARG=q4.mean FILE=colvar -\endverbatim +\endplumedfile The following command calculates the histogram of Q4 parameters for the 64 atoms in a box of Lennard Jones and prints these quantities to a file called colvar: -\verbatim +\plumedfile Q4 SPECIES=1-64 D_0=1.3 R_0=0.2 HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=1.0 NBINS=20 SMEAR=0.1} LABEL=q4 PRINT ARG=q4.* FILE=colvar -\endverbatim +\endplumedfile The following command could be used to measure the Q4 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q4 paramter is calculated and output to a file called colvar -\verbatim +\plumedfile Q4 SPECIESA=1-64 SPECIESB=65-128 D_0=1.3 R_0=0.2 MEAN LABEL=q4 PRINT ARG=q4.mean FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC @@ -136,30 +136,30 @@ adjacent atoms is correlated. The following command calculates the average value of the LOCAL_Q4 parameter for the 64 Lennard Jones atoms in the system under study and prints this quantity to a file called colvar. -\verbatim +\plumedfile Q4 SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=q4 LOCAL_Q4 ARG=q4 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LABEL=lq4 PRINT ARG=lq4.mean FILE=colvar -\endverbatim +\endplumedfile The following input calculates the distribution of LOCAL_Q4 parameters at any given time and outputs this information to a file. -\verbatim +\plumedfile Q4 SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=q4 LOCAL_Q4 ARG=q4 SWITCH={RATIONAL D_0=1.3 R_0=0.2} HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=1.0 NBINS=20 SMEAR=0.1} LABEL=lq4 PRINT ARG=lq4.* FILE=colvar -\endverbatim +\endplumedfile The following calculates the LOCAL_Q4 parameters for atoms 1-5 only. For each of these atoms comparisons of the geometry of the coordination sphere are done with those of all the other atoms in the system. The final quantity is the average and is outputted to a file -\verbatim +\plumedfile Q4 SPECIESA=1-5 SPECIESB=1-64 D_0=1.3 R_0=0.2 LABEL=q4a Q4 SPECIESA=6-64 SPECIESB=1-64 D_0=1.3 R_0=0.2 LABEL=q4b LOCAL_Q4 ARG=q4a,q4b SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LOWMEM LABEL=w4 PRINT ARG=w4.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/Q6.cpp b/src/crystallization/Q6.cpp index 447b0e1cb4..a848174ab8 100644 --- a/src/crystallization/Q6.cpp +++ b/src/crystallization/Q6.cpp @@ -60,28 +60,28 @@ the \f$q_{6}\f$ vectors on adjacent atoms. More information on these variables The following command calculates the average Q6 parameter for the 64 atoms in a box of Lennard Jones and prints this quantity to a file called colvar: -\verbatim +\plumedfile Q6 SPECIES=1-64 D_0=1.3 R_0=0.2 MEAN LABEL=q6 PRINT ARG=q6.mean FILE=colvar -\endverbatim +\endplumedfile The following command calculates the histogram of Q6 parameters for the 64 atoms in a box of Lennard Jones and prints these quantities to a file called colvar: -\verbatim +\plumedfile Q6 SPECIES=1-64 D_0=1.3 R_0=0.2 HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=1.0 NBINS=20 SMEAR=0.1} LABEL=q6 PRINT ARG=q6.* FILE=colvar -\endverbatim +\endplumedfile The following command could be used to measure the Q6 paramters that describe the arrangement of chlorine ions around the sodium atoms in NaCl. The imagined system here is composed of 64 NaCl formula units and the atoms are arranged in the input with the 64 Na\f$^+\f$ ions followed by the 64 Cl\f$-\f$ ions. Once again the average Q6 paramter is calculated and output to a file called colvar -\verbatim +\plumedfile Q6 SPECIESA=1-64 SPECIESB=65-128 D_0=1.3 R_0=0.2 MEAN LABEL=q6 PRINT ARG=q6.mean FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC @@ -136,30 +136,30 @@ adjacent atoms is correlated. The following command calculates the average value of the LOCAL_Q6 parameter for the 64 Lennard Jones atoms in the system under study and prints this quantity to a file called colvar. -\verbatim +\plumedfile Q6 SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=q6 LOCAL_Q6 ARG=q6 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LABEL=lq6 PRINT ARG=lq6.mean FILE=colvar -\endverbatim +\endplumedfile The following input calculates the distribution of LOCAL_Q6 parameters at any given time and outputs this information to a file. -\verbatim +\plumedfile Q6 SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=q6 LOCAL_Q6 ARG=q6 SWITCH={RATIONAL D_0=1.3 R_0=0.2} HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=1.0 NBINS=20 SMEAR=0.1} LABEL=lq6 PRINT ARG=lq6.* FILE=colvar -\endverbatim +\endplumedfile The following calculates the LOCAL_Q6 parameters for atoms 1-5 only. For each of these atoms comparisons of the geometry of the coordination sphere are done with those of all the other atoms in the system. The final quantity is the average and is outputted to a file -\verbatim +\plumedfile Q6 SPECIESA=1-5 SPECIESB=1-64 D_0=1.3 R_0=0.2 LABEL=q6a Q6 SPECIESA=6-64 SPECIESB=1-64 D_0=1.3 R_0=0.2 LABEL=q6b LOCAL_Q6 ARG=q4a,q4b SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LOWMEM LABEL=w4 PRINT ARG=w6.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/SMAC.cpp b/src/crystallization/SMAC.cpp index ce83df7380..3d7085a979 100644 --- a/src/crystallization/SMAC.cpp +++ b/src/crystallization/SMAC.cpp @@ -65,7 +65,7 @@ the indices of three atoms for each of the MOL keywords below we are telling PLU numbers to determine the orientation of the molecule that will ultimately be used when calculating the \f$\theta_{ij}\f$ terms in the formula above. The atom with the third index meanwhile is used when we calculate \f$r_{ij}\f$. -\verbatim +\plumedfile MOLECULES ... MOL1=9,10,9 MOL2=89,90,89 @@ -86,13 +86,13 @@ SMAC ... ... SMAC PRINT ARG=s2.* FILE=colvar -\endverbatim +\endplumedfile This second example works in a way that is very similar to the previous command. Now, however, the orientation of the molecules is determined by finding the plane that contains the positions of three atoms. -\verbatim +\plumedfile PLANES ... MOL1=9,10,11 MOL2=89,90,91 @@ -114,7 +114,7 @@ SMAC ... ... SMAC PRINT ARG=s2.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/SimpleCubic.cpp b/src/crystallization/SimpleCubic.cpp index 4d50cc7d59..2c15767c27 100644 --- a/src/crystallization/SimpleCubic.cpp +++ b/src/crystallization/SimpleCubic.cpp @@ -55,15 +55,15 @@ so on. Notice also that you can rotate the reference frame if you are using a n The following input tells plumed to calculate the simple cubic parameter for the atoms 1-100 with themselves. The mean value is then calculated. -\verbatim +\plumedfile SIMPLECUBIC SPECIES=1-100 R_0=1.0 MEAN -\endverbatim +\endplumedfile The following input tells plumed to look at the ways atoms 1-100 are within 3.0 are arranged about atoms from 101-110. The number of simple cubic parameters that are greater than 0.8 is then output -\verbatim +\plumedfile SIMPLECUBIC SPECIESA=101-110 SPECIESB=1-100 R_0=3.0 MORE_THAN={RATIONAL R_0=0.8 NN=6 MM=12 D_0=0} -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/crystallization/Tetrahedral.cpp b/src/crystallization/Tetrahedral.cpp index 616cf766bf..87c6e33ae8 100644 --- a/src/crystallization/Tetrahedral.cpp +++ b/src/crystallization/Tetrahedral.cpp @@ -54,20 +54,20 @@ when atom \f$j\f$ is in the first coordination sphere of atom \f$i\f$ and is zer The following command calculates the average value of the tetrahedrality parameter for a set of 64 atoms all of the same type and outputs this quantity to a file called colvar. -\verbatim +\plumedfile tt: TETRAHEDRAL SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN PRINT ARG=tt.mean FILE=colvar -\endverbatim +\endplumedfile The following command calculates the number of tetrahedrality parameters that are greater than 0.8 in a set of 10 atoms. In this calculation it is assumed that there are two atom types A and B and that the first coordination sphere of the 10 atoms of type A contains atoms of type B. The formula above is thus calculated for ten different A atoms and within it the sum over \f$j\f$ runs over 40 atoms of type B that could be in the first coordination sphere. -\verbatim +\plumedfile tt: TETRAHEDRAL SPECIESA=1-10 SPECIESB=11-40 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MORE_THAN={RATIONAL R_0=0.8} PRINT ARG=tt.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/eds/EDS.cpp b/src/eds/EDS.cpp index e5e575abe1..e7e0e4331d 100644 --- a/src/eds/EDS.cpp +++ b/src/eds/EDS.cpp @@ -63,7 +63,7 @@ It is not possible to set the target value of the observable to zero with the de The following input for a harmonic oscillator of two beads will adaptively find a linear bias to change the mean and variance to the target values. The PRINT line shows how to access the value of the coupling constants. -\verbatim +\plumedfile dist: DISTANCE ATOMS=1,2 # this is the squared of the distance dist2: COMBINE ARG=dist POWERS=2 PERIODIC=NO @@ -71,19 +71,19 @@ dist2: COMBINE ARG=dist POWERS=2 PERIODIC=NO #bias mean and variance eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 PRINT ARG=dist,dist2,eds.dist_coupling,eds.dist2_coupling,eds.bias,eds.force2 FILE=colvars.dat STRIDE=100 -\endverbatim +\endplumedfile Rather than trying to find the coupling constants adaptively, can ramp up to a constant value. -\verbatim +\plumedfile #ramp couplings from 0,0 to -1,1 over 50000 steps eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 FIXED=-1,1 RAMP PERIOD=50000 TEMP=1.0 #same as above, except starting at -0.5,0.5 rather than default of 0,0 eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 FIXED=-1,1 INIT=-0.5,0.5 RAMP PERIOD=50000 TEMP=1.0 -\endverbatim +\endplumedfile A restart file can be added to dump information needed to restart/continue simulation using these parameters every STRIDE. -\verbatim +\plumedfile #add the option to write to a restart file eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 OUT_RESTART=restart.dat @@ -98,7 +98,7 @@ eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 IN_RESTART=restart. #add the option to read in a previous restart file and continue the bias, but use the mean from the previous run as the starting point eds: EDS ARG=dist,dist2 CENTER=2.0,1.0 PERIOD=50000 TEMP=1.0 IN_RESTART=restart.dat MEAN -\endverbatim +\endplumedfile */ diff --git a/src/function/Combine.cpp b/src/function/Combine.cpp index e76ed7b8bb..62f66e35d8 100644 --- a/src/function/Combine.cpp +++ b/src/function/Combine.cpp @@ -52,23 +52,23 @@ is periodic. The following input tells plumed to print the distance between atoms 3 and 5 its square (as computed from the x,y,z components) and the distance again as computed from the square root of the square. -\verbatim +\plumedfile DISTANCE LABEL=dist ATOMS=3,5 COMPONENTS COMBINE LABEL=distance2 ARG=dist.x,dist.y,dist.z POWERS=2,2,2 PERIODIC=NO COMBINE LABEL=distance ARG=distance2 POWERS=0.5 PERIODIC=NO PRINT ARG=distance,distance2 -\endverbatim +\endplumedfile (See also \ref PRINT and \ref DISTANCE). The following input tells plumed to add a restraint on the cube of a dihedral angle. Notice that since the angle has a periodic domain -pi,pi its cube has a domain -pi**3,pi**3. -\verbatim +\plumedfile t: TORSION ATOMS=1,3,5,7 c: COMBINE ARG=t POWERS=3 PERIODIC=-31.0062766802998,31.0062766802998 RESTRAINT ARG=c KAPPA=10 AT=0 -\endverbatim +\endplumedfile diff --git a/src/function/Ensemble.cpp b/src/function/Ensemble.cpp index 9976c25015..bc1e05fb28 100644 --- a/src/function/Ensemble.cpp +++ b/src/function/Ensemble.cpp @@ -38,12 +38,11 @@ Each collective variable is averaged separately and stored in a component labell \par Examples The following input tells plumed to calculate the distance between atoms 3 and 5 and the average it over the available replicas. -\verbatim +\plumedfile dist: DISTANCE ATOMS=3,5 ens: ENSEMBLE ARG=dist PRINT ARG=dist,ens.dist -\endverbatim -(See also \ref PRINT and \ref DISTANCE). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/function/FuncPathMSD.cpp b/src/function/FuncPathMSD.cpp index f4d481d733..25a87e7182 100644 --- a/src/function/FuncPathMSD.cpp +++ b/src/function/FuncPathMSD.cpp @@ -49,17 +49,17 @@ It is a function of MSD that are obtained by the joint use of MSD variable and S Here below is a case where you have defined three frames and you want to calculate the progress alng the path and the distance from it in p1 -\verbatim +\plumedfile t1: RMSD REFERENCE=frame_1.dat TYPE=OPTIMAL SQUARED t2: RMSD REFERENCE=frame_21.dat TYPE=OPTIMAL SQUARED t3: RMSD REFERENCE=frame_42.dat TYPE=OPTIMAL SQUARED p1: FUNCPATHMSD ARG=t1,t2,t3 LAMBDA=500.0 PRINT ARG=t1,t2,t3,p1.s,p1.z STRIDE=1 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile In this second example is shown how to define a PATH in the \ref CONTACTMAP space: -\verbatim +\plumedfile CONTACTMAP ... ATOMS1=1,2 REFERENCE1=0.1 ATOMS2=3,4 REFERENCE2=0.5 @@ -92,7 +92,7 @@ CMDIST p1: FUNCPATHMSD ARG=c1,c2,c3 LAMBDA=500.0 PRINT ARG=c1,c2,c3,p1.s,p1.z STRIDE=1 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/function/LocalEnsemble.cpp b/src/function/LocalEnsemble.cpp index 6e3bd96f68..429a5a1436 100644 --- a/src/function/LocalEnsemble.cpp +++ b/src/function/LocalEnsemble.cpp @@ -40,7 +40,7 @@ The following input tells plumed to calculate the chemical shifts for four different proteins in the same simulation box then average them, calcualated the sum of the squared deviation with respect to the experiemntal values and applies a linear restraint. -\verbatim +\plumedfile MOLINFO STRUCTURE=data/template.pdb chaina: GROUP ATOMS=1-1640 @@ -68,7 +68,7 @@ sthn: STATS ARG=(enshn\.csa\.hn_.*) PARARG=(csa\.exphn_.*) SQDEVSUM stnh: STATS ARG=(ensnh\.csa\.nh_.*) PARARG=(csa\.expnh_.*) SQDEVSUM res: RESTRAINT ARG=stca.*,stcb.*,stco.*,sthn.*,stnh.* AT=0.,0.,0.,0.,0. KAPPA=0.,0.,0.,0.,0 SLOPE=16.,16.,12.,24.,0.5 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp index 59e6e9bf05..d21907e68e 100644 --- a/src/function/Matheval.cpp +++ b/src/function/Matheval.cpp @@ -54,14 +54,14 @@ PLUMED has been linked to it The following input tells plumed to perform a metadynamics using as a CV the difference between two distances. -\verbatim +\plumedfile dAB: DISTANCE ARG=10,12 dAC: DISTANCE ARG=10,15 diff: MATHEVAL ARG=dAB,dAC FUNC=y-x PERIODIC=NO # notice: the previous line could be replaced with the following # diff: COMBINE ARG=dAB,dAC COEFFICIENTS=-1,1 METAD ARG=diff WIDTH=0.1 HEIGHT=0.5 BIASFACTOR=10 PACE=100 -\endverbatim +\endplumedfile (see also \ref DISTANCE, \ref COMBINE, and \ref METAD). Notice that forces applied to diff will be correctly propagated to atoms 10, 12, and 15. @@ -75,7 +75,7 @@ The following input tells plumed to print the angle between vectors identified by atoms 1,2 and atoms 2,3 its square (as computed from the x,y,z components) and the distance again as computed from the square root of the square. -\verbatim +\plumedfile DISTANCE LABEL=d1 ATOMS=1,2 COMPONENTS DISTANCE LABEL=d2 ATOMS=2,3 COMPONENTS MATHEVAL ... @@ -86,7 +86,7 @@ MATHEVAL ... PERIODIC=NO ... MATHEVAL PRINT ARG=theta -\endverbatim +\endplumedfile (See also \ref PRINT and \ref DISTANCE). Notice that the matheval library implements a large number of functions (trigonometric, exp, log, etc). @@ -96,13 +96,13 @@ a straightforward implementation of if clauses. For example, imagine that you want to implement a restraint that only acts when a distance is larger than 0.5. You can do it with -\verbatim +\plumedfile d: DISTANCE ATOMS=10,15 m: MATHEVAL ARG=d FUNC=0.5*step(0.5-x)+x*step(x-0.5) PERIODIC=NO # check the function you are applying: PRINT ARG=d,n FILE=checkme RESTRAINT ARG=d AT=0.5 KAPPA=10.0 -\endverbatim +\endplumedfile (see also \ref DISTANCE, \ref PRINT, and \ref RESTRAINT) The meaning of the function `0.5*step(0.5-x)+x*step(x-0.5)` is: @@ -133,7 +133,7 @@ MATHEVAL can be used in combination with \ref DISTANCE to implement variants of DISTANCE keyword that were present in PLUMED 1.3 and that allowed to compute the distance of a point from a line defined by two other points, or the progression along that line. -\verbatim +\plumedfile # take center of atoms 1 to 10 as reference point 1 p1: CENTER ATOMS=1-10 # take center of atoms 11 to 20 as reference point 2 @@ -156,7 +156,7 @@ fromaxis: MATHEVAL ARG=d13,d23,d12,onaxis VAR=x,y,z,o FUNC=(0.5*(y^2+x^2)-o^2-0. PRINT ARG=onaxis,fromaxis -\endverbatim +\endplumedfile Notice that these equations have been used to combine \ref RMSD from different snapshots of a protein so as to define diff --git a/src/function/Piecewise.cpp b/src/function/Piecewise.cpp index e0f4bbd52a..ebd886de09 100644 --- a/src/function/Piecewise.cpp +++ b/src/function/Piecewise.cpp @@ -55,15 +55,14 @@ in a vector of values. Each value will be named as the name of the original argument with suffix _pfunc. \par Examples -\verbatim +\plumedfile dist1: DISTANCE ATOMS=1,10 dist2: DISTANCE ATOMS=2,11 pw: PIECEWISE POINT0=1,10 POINT1=1,PI POINT2=3,10 ARG=dist1 ppww: PIECEWISE POINT0=1,10 POINT1=1,PI POINT2=3,10 ARG=dist1,dist2 PRINT ARG=pw,ppww.dist1_pfunc,ppww.dist2_pfunc -\endverbatim -(See also \ref PRINT and \ref DISTANCE). +\endplumedfile */ diff --git a/src/function/Sort.cpp b/src/function/Sort.cpp index f1e9b2a717..fc8e4ca233 100644 --- a/src/function/Sort.cpp +++ b/src/function/Sort.cpp @@ -43,15 +43,14 @@ labelled label.1, the second lowest will be labelled label.2 a \par Examples The following input tells plumed to print the distance of the closest and of the farthest atoms to atom 1, chosen among atoms from 2 to 5 -\verbatim +\plumedfile d12: DISTANCE ATOMS=1,2 d13: DISTANCE ATOMS=1,3 d14: DISTANCE ATOMS=1,4 d15: DISTANCE ATOMS=1,5 sort: SORT ARG=d12,d13,d14,d15 PRINT ARG=sort.1,sort.4 -\endverbatim -(See also \ref PRINT and \ref DISTANCE). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/function/Stats.cpp b/src/function/Stats.cpp index 429442e6d8..438d8f98b8 100644 --- a/src/function/Stats.cpp +++ b/src/function/Stats.cpp @@ -41,13 +41,13 @@ from other actions using PARARG (for example using experimental values from coll The following input tells plumed to print the distance between three couple of atoms and compare them with three reference distances. -\verbatim +\plumedfile d1: DISTANCE ATOMS=10,50 d2: DISTANCE ATOMS=1,100 d3: DISTANCE ATOMS=45,75 st: STATS ARG=d1,d2,d3 PARAMETERS=1.5,4.0,2.0 PRINT ARG=d1,d2,d3,st.* -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/function/Target.cpp b/src/function/Target.cpp index 5ce9124956..1724cf3ff8 100644 --- a/src/function/Target.cpp +++ b/src/function/Target.cpp @@ -75,12 +75,12 @@ specified in the input. The following input calculates the distance between a reference configuration and the instaneous position of the system in the trajectory. The position of the reference configuration is specified by providing the values of the distance between atoms 1 and 2 and atoms 3 and 4. -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,2 d2: DISTANCE ATOMS=3,4 t1: TARGET REFERENCE=myref.pdb TYPE=EUCLIDEAN PRINT ARG=t1 FILE=colvar -\endverbatim +\endplumedfile The contents of the file containing the reference structure (myref.pdb) is shown below. As you can see you must provide information on the labels of the CVs that are being used to define the position of the reference configuration in this file together with the values that these diff --git a/src/generic/Debug.cpp b/src/generic/Debug.cpp index 742b3b8542..36654b0d90 100644 --- a/src/generic/Debug.cpp +++ b/src/generic/Debug.cpp @@ -37,12 +37,12 @@ Can be used while debugging or optimizing plumed. \par Examples -\verbatim +\plumedfile # print detailed (action-by-action) timers at the end of simulation DEBUG DETAILED_TIMERS # dump every two steps which are the atoms required from the MD code DEBUG logRequestedAtoms STRIDE=2 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/DumpAtoms.cpp b/src/generic/DumpAtoms.cpp index d6ee377488..c144b5f078 100644 --- a/src/generic/DumpAtoms.cpp +++ b/src/generic/DumpAtoms.cpp @@ -70,15 +70,14 @@ Notice that gro/xtc/trr files can only contain coordinates in nm. The following input instructs plumed to print out the positions of atoms 1-10 together with the position of the center of mass of atoms 11-20 every 10 steps to a file called file.xyz. -\verbatim +\plumedfile COM ATOMS=11-20 LABEL=c1 DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1 -\endverbatim -(see also \ref COM) +\endplumedfile The following input is very similar but dumps a .gro (gromacs) file, which also contains atom and residue names. -\verbatim +\plumedfile # this is required to have proper atom names: MOLINFO STRUCTURE=reference.pdb # if omitted, atoms will have "X" name... @@ -87,8 +86,7 @@ COM ATOMS=11-20 LABEL=c1 DUMPATOMS STRIDE=10 FILE=file.gro ATOMS=1-10,c1 # notice that last atom is a virtual one and will not have # a correct name in the resulting gro file -\endverbatim -(see also \ref COM and \ref MOLINFO) +\endplumedfile */ diff --git a/src/generic/DumpDerivatives.cpp b/src/generic/DumpDerivatives.cpp index c74343aca0..38c686d7b4 100644 --- a/src/generic/DumpDerivatives.cpp +++ b/src/generic/DumpDerivatives.cpp @@ -42,11 +42,11 @@ can be done by outputting the derivatives calculated analytically and numericall \par Examples The following input instructs plumed to write a file called deriv that contains both the analytical and numerical derivatives of the distance between atoms 1 and 2. -\verbatim +\plumedfile DISTANCE ATOM=1,2 LABEL=distance DISTANCE ATOM=1,2 LABEL=distanceN NUMERICAL_DERIVATIVES DUMPDERIVATIVES ARG=distance,distanceN STRIDE=1 FILE=deriv -\endverbatim +\endplumedfile (See also \ref DISTANCE) diff --git a/src/generic/DumpForces.cpp b/src/generic/DumpForces.cpp index f5e204d65b..a376de281a 100644 --- a/src/generic/DumpForces.cpp +++ b/src/generic/DumpForces.cpp @@ -43,12 +43,10 @@ by specifying more than one argument. You can control the buffering of output us \par Examples The following input instructs plumed to write a file called forces that contains the force acting on the distance between atoms 1 and 2. -\verbatim +\plumedfile DISTANCE ATOM=1,2 LABEL=distance DUMPFORCES ARG=distance STRIDE=1 FILE=forces -\endverbatim - -(See also \ref DISTANCE) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/DumpMassCharge.cpp b/src/generic/DumpMassCharge.cpp index 4153bc8384..25224f3b3c 100644 --- a/src/generic/DumpMassCharge.cpp +++ b/src/generic/DumpMassCharge.cpp @@ -49,14 +49,13 @@ masses for all atoms are written. You can add the DUMPMASSCHARGE action at the end of the plumed.dat file that you use during an MD simulations: -\verbatim +\plumedfile c1: COM ATOMS=1-10 c2: COM ATOMS=11-20 PRINT ARG=c1,c2 FILE=colvar STRIDE=100 DUMPMASSCHARGE FILE=mcfile -\endverbatim -(see also \ref COM and \ref PRINT) +\endplumedfile In this way, you will be able to use the same masses while processing a trajectory from the \ref driver . To do so, you need to @@ -67,11 +66,11 @@ plumed driver --mc mcfile --plumed plumed.dat --ixyz traj.xyz With the following input you can dump only the charges for a specific group. -\verbatim +\plumedfile solute_ions: GROUP ATOMS=1-121,200-2012 DUMPATOMS FILE=traj.gro ATOMS=solute_ions STRIDE=100 DUMPMASSCHARGE FILE=mcfile ATOMS=solute_ions -\endverbatim +\endplumedfile Notice however that if you want to process the charges with the driver (e.g. reading traj.gro) you have to fix atom numbers first, e.g. with the script diff --git a/src/generic/DumpProjections.cpp b/src/generic/DumpProjections.cpp index 3f0d404297..c3a0ca7509 100644 --- a/src/generic/DumpProjections.cpp +++ b/src/generic/DumpProjections.cpp @@ -39,12 +39,12 @@ Dump the derivatives with respect to the input parameters for one or more object Compute the distance between two groups and write on a file the derivatives of this distance with respect to all the atoms of the two groups -\verbatim +\plumedfile x1: CENTER ATOMS=1-10 x2: CENTER ATOMS=11-20 d: DISTANCE ATOMS=x1,x2 DUMPPROJECTIONS ARG=d FILE=proj STRIDE=20 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/EffectiveEnergyDrift.cpp b/src/generic/EffectiveEnergyDrift.cpp index 1c3961390a..a9ca15e6c8 100644 --- a/src/generic/EffectiveEnergyDrift.cpp +++ b/src/generic/EffectiveEnergyDrift.cpp @@ -55,18 +55,18 @@ Print the effective energy drift described in Ref \cite Ferrarotti2015 This is to monitor the effective energy drift for a metadynamics simulation on the Debye-Huckel energy. Since this variable is very expensive, it could be conveniently computed every second step. -\verbatim +\plumedfile dh: DHENERGY GROUPA=1-10 GROUPB=11-20 EPSILON=80.0 I=0.1 TEMP=300.0 METAD ARG=dh HEIGHT=0.5 SIGMA=0.1 PACE=500 STRIDE=2 EFFECTIVE_ENERGY_DRIFT PRINT_STRIDE=100 FILE=eff -\endverbatim +\endplumedfile This is to monitor if a restraint is too stiff -\verbatim +\plumedfile d: DISTANCE ATOMS=10,20 RESTRAINT ARG=d KAPPA=100000 AT=0.6 EFFECTIVE_ENERGY_DRIFT PRINT_STRIDE=100 FILE=eff -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/FitToTemplate.cpp b/src/generic/FitToTemplate.cpp index 37e38333f6..6fa379e1fd 100644 --- a/src/generic/FitToTemplate.cpp +++ b/src/generic/FitToTemplate.cpp @@ -78,13 +78,12 @@ this action is performed at every MD step. \par Examples Align the atomic position to a template then print them -\verbatim +\plumedfile # to see the effect, one could dump the atoms before alignment DUMPATOMS FILE=dump-before.xyz ATOMS=1-20 FIT_TO_TEMPLATE STRIDE=1 REFERENCE=ref.pdb TYPE=SIMPLE DUMPATOMS FILE=dump-after.xyz ATOMS=1-20 -\endverbatim -(see also \ref DUMPATOMS) +\endplumedfile diff --git a/src/generic/Flush.cpp b/src/generic/Flush.cpp index 78c00f87d5..71e9a06d3e 100644 --- a/src/generic/Flush.cpp +++ b/src/generic/Flush.cpp @@ -41,7 +41,7 @@ plumed input file, it will flush all the open files. \par Examples A command like this in the input will instruct plumed to flush all the output files every 100 steps -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,10 PRINT ARG=d1 STRIDE=5 FILE=colvar1 @@ -50,7 +50,7 @@ FLUSH STRIDE=100 d2: DISTANCE ATOMS=2,11 # also this print is flushed every 100 steps: PRINT ARG=d2 STRIDE=10 FILE=colvar2 -\endverbatim +\endplumedfile (see also \ref DISTANCE and \ref PRINT). */ //+ENDPLUMEDOC diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index 80393a9ce3..0f04cf75fd 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -65,7 +65,7 @@ the \ref INCLUDE command so as to store long group definitions in a separate fil This command create a group of atoms containing atoms 1,4,7,11 and 14 (labeled 'o'), and another containing atoms 2,3,5,6,8,9,12,13 (labeled 'h'): -\verbatim +\plumedfile o: GROUP ATOMS=1,4,7,11,14 h: GROUP ATOMS=2,3,5,6,8,9,12,13 # compute the coordination among the two groups @@ -75,45 +75,41 @@ c: COORDINATION GROUPA=o GROUPB=h R_0=0.3 # print the coordination on file 'colvar' PRINT ARG=c FILE=colvar -\endverbatim -(see also \ref COORDINATION and \ref PRINT) +\endplumedfile Groups can be conveniently stored in a separate file. E.g. one could create a file named 'groups.dat' which reads -\verbatim +\plumedfile o: GROUP ATOMS=1,4,7,11,14 h: GROUP ATOMS=2,3,5,6,8,9,12,13 -\endverbatim +\endplumedfile and then include it in the main 'plumed.dat' file -\verbatim +\plumedfile INCLUDE FILE=groups.dat # compute the coordination among the two groups c: COORDINATION GROUPA=o GROUPB=h R_0=0.3 # print the coordination on file 'colvar' PRINT ARG=c FILE=colvar -\endverbatim -(see also \ref INCLUDE, \ref COORDINATION, and \ref PRINT). +\endplumedfile The groups.dat file could be very long and include lists of thousand atoms without cluttering the main plumed.dat file. A GROMACS index file can also be imported -\verbatim +\plumedfile # import group named 'protein' from file index.ndx pro: GROUP NDX_FILE=index.ndx NDX_GROUP=protein # dump all the atoms of the protein on a trajectory file DUMPATOMS ATOMS=pro FILE=traj.gro -\endverbatim -(see also \ref DUMPATOMS) +\endplumedfile A list can be edited with REMOVE -\verbatim +\plumedfile # take one atom every three ox: GROUP ATOMS=1-90:3 # take the remaining atoms hy: GROUP ATOMS=1-90 REMOVE=ox DUMPATOMS ATOMS=ox FILE=ox.gro DUMPATOMS ATOMS=hy FILE=hy.gro -\endverbatim -(see also \ref DUMPATOMS) +\endplumedfile */ diff --git a/src/generic/Include.cpp b/src/generic/Include.cpp index 664c84ba67..30539f0bb0 100644 --- a/src/generic/Include.cpp +++ b/src/generic/Include.cpp @@ -38,25 +38,25 @@ Useful to split very large plumed.dat files. \par Examples This input -\verbatim +\plumedfile c1: COM ATOMS=1-100 c2: COM ATOMS=101-202 d: DISTANCE ARG=c1,c2 PRINT ARG=d -\endverbatim +\endplumedfile can be replaced with -\verbatim +\plumedfile INCLUDE FILE=pippo.dat d: DISTANCE ARG=c1,c2 PRINT ARG=d -\endverbatim +\endplumedfile where the content of file pippo.dat is -\verbatim +\plumedfile c1: COM ATOMS=1-100 c2: COM ATOMS=101-202 -\endverbatim +\endplumedfile (see also \ref COM, \ref DISTANCE, and \ref PRINT). diff --git a/src/generic/Print.cpp b/src/generic/Print.cpp index 2a87d1f7ba..74245cf99a 100644 --- a/src/generic/Print.cpp +++ b/src/generic/Print.cpp @@ -40,13 +40,12 @@ to different files. You can control the buffering of output using the \subpage The following input instructs plumed to print the distance between atoms 3 and 5 on a file called COLVAR every 10 steps, and the distance and total energy on a file called COLVAR_ALL every 1000 steps. -\verbatim +\plumedfile DISTANCE ATOMS=2,5 LABEL=distance ENERGY LABEL=energy PRINT ARG=distance STRIDE=10 FILE=COLVAR PRINT ARG=distance,energy STRIDE=1000 FILE=COLVAR_ALL -\endverbatim -(See also \ref DISTANCE and \ref ENERGY). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/RandomExchanges.cpp b/src/generic/RandomExchanges.cpp index be36873bcc..60d2071207 100644 --- a/src/generic/RandomExchanges.cpp +++ b/src/generic/RandomExchanges.cpp @@ -44,25 +44,25 @@ metadynamics simulation using a different angle in each replica. Exchanges will be randomly tried between replicas 0-1, 0-2 and 1-2 Here is plumed.0.dat -\verbatim +\plumedfile RANDOM_EXCHANGES t: TORSION ATOMS=1,2,3,4 METAD ARG=t HEIGHT=0.1 PACE=100 SIGMA=0.3 -\endverbatim +\endplumedfile Here is plumed.1.dat -\verbatim +\plumedfile RANDOM_EXCHANGES t: TORSION ATOMS=2,3,4,5 METAD ARG=t HEIGHT=0.1 PACE=100 SIGMA=0.3 -\endverbatim +\endplumedfile Here is plumed.2.dat -\verbatim +\plumedfile RANDOM_EXCHANGES t: TORSION ATOMS=3,4,5,6 METAD ARG=t HEIGHT=0.1 PACE=100 SIGMA=0.3 -\endverbatim +\endplumedfile \warning Multi replica simulations are presently only working with gromacs. diff --git a/src/generic/Read.cpp b/src/generic/Read.cpp index 88c2796300..63b8f8fc80 100644 --- a/src/generic/Read.cpp +++ b/src/generic/Read.cpp @@ -52,11 +52,11 @@ This input reads in data from a file called input_colvar.data that was generated in a calculation that involved PLUMED. The first command reads in the data from the column headed phi1 while the second reads in the data from the column headed phi2. -\verbatim +\plumedfile rphi1: READ FILE=input_colvar.data VALUES=phi1 rphi2: READ FILE=input_colvar.data VALUES=phi2 PRINT ARG=rphi1,rphi2 STRIDE=500 FILE=output_colvar.data -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/ResetCell.cpp b/src/generic/ResetCell.cpp index fd14c1fe10..5268d52de3 100644 --- a/src/generic/ResetCell.cpp +++ b/src/generic/ResetCell.cpp @@ -71,14 +71,13 @@ this action is performed at every MD step. \par Examples Reset cell to be triangular after a rototranslational fit -\verbatim +\plumedfile DUMPATOMS FILE=dump-original.xyz ATOMS=1-20 FIT_TO_TEMPLATE STRIDE=1 REFERENCE=ref.pdb TYPE=OPTIMAL DUMPATOMS FILE=dump-fit.xyz ATOMS=1-20 RESET_CELL TYPE=TRIANGULAR DUMPATOMS FILE=dump-reset.xyz ATOMS=1-20 -\endverbatim -(see also \ref DUMPATOMS) +\endplumedfile */ diff --git a/src/generic/Time.cpp b/src/generic/Time.cpp index 3512cb53da..9a821f0b65 100644 --- a/src/generic/Time.cpp +++ b/src/generic/Time.cpp @@ -35,11 +35,10 @@ retrieve the time of the simulation to be used elsewere \par Examples -\verbatim +\plumedfile TIME LABEL=t1 PRINT ARG=t1 -\endverbatim -(See also \ref PRINT). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/UpdateIf.cpp b/src/generic/UpdateIf.cpp index 2d067fcf3d..696e66c20f 100644 --- a/src/generic/UpdateIf.cpp +++ b/src/generic/UpdateIf.cpp @@ -62,7 +62,7 @@ can lead to unexpected results. \par Examples The following input instructs plumed dump all the snapshots where an atom is in touch with the solute. -\verbatim +\plumedfile solute: GROUP ATOMS=1-124 coord: COORDINATION GROUPA=solute GROUPB=500 R_0=0.5 @@ -72,8 +72,7 @@ coord: COORDINATION GROUPA=solute GROUPB=500 R_0=0.5 UPDATE_IF ARG=coord MORE_THAN=0.5 DUMPATOMS ATOMS=solute,500 FILE=output.xyz UPDATE_IF ARG=coord END -\endverbatim -(See also \ref GROUP, \ref COORDINATION, and \ref DUMPATOMS) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/WholeMolecules.cpp b/src/generic/WholeMolecules.cpp index 12e9c82813..e43c0aa07b 100644 --- a/src/generic/WholeMolecules.cpp +++ b/src/generic/WholeMolecules.cpp @@ -74,30 +74,27 @@ to skip some atoms, provided consecute chosen atoms are close enough. This command instructs plumed to reconstruct the molecule containing atoms 1-20 at every step of the calculation and dump them on a file. -\verbatim +\plumedfile # to see the effect, one could dump the atoms as they were before molecule reconstruction: # DUMPATOMS FILE=dump-broken.xyz ATOMS=1-20 WHOLEMOLECULES ENTITY0=1-20 DUMPATOMS FILE=dump.xyz ATOMS=1-20 -\endverbatim -(see also \ref DUMPATOMS) +\endplumedfile This command instructs plumed to reconstruct two molecules containing atoms 1-20 and 30-40 -\verbatim +\plumedfile WHOLEMOLECULES ENTITY0=1-20 ENTITY1=30-40 DUMPATOMS FILE=dump.xyz ATOMS=1-20,30-40 -\endverbatim -(see also \ref DUMPATOMS) +\endplumedfile This command instructs plumed to reconstruct the chain of backbone atoms in a protein -\verbatim +\plumedfile MOLINFO STRUCTURE=helix.pdb WHOLEMOLECULES RESIDUES=all MOLTYPE=protein -\endverbatim -(See also \ref MOLINFO) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/generic/WrapAround.cpp b/src/generic/WrapAround.cpp index 946a060fde..6320ee4bbc 100644 --- a/src/generic/WrapAround.cpp +++ b/src/generic/WrapAround.cpp @@ -69,20 +69,19 @@ consider the possibility of using the STRIDE keyword here (with great care). This command instructs plumed to move all the ions to their periodic image that is as close as possible to the rna group. -\verbatim +\plumedfile rna: GROUP ATOMS=1-100 ions: GROUP ATOMS=101-110 # first make the rna molecule whole WHOLEMOLECULES ENTITY0=rna WRAPAROUND ATOMS=ions AROUND=rna DUMPATOMS FILE=dump.xyz ATOMS=rna,ions -\endverbatim -(see also \ref WHOLEMOLECULES, \ref GROUP and \ref DUMPATOMS) +\endplumedfile In case you want to do it during a simulation and you only care about wrapping the ions in the `dump.xyz` file, you can use the following: -\verbatim +\plumedfile # add some restraint that do not require molecules to be whole: a: TORSION ATOMS=1,2,10,11 RESTRAINT ARG=a AT=0.0 KAPPA=5 @@ -98,15 +97,14 @@ ions: GROUP ATOMS=101-110 WHOLEMOLECULES ENTITY0=rna STRIDE=100 WRAPAROUND ATOMS=ions AROUND=rna STRIDE=100 DUMPATOMS FILE=dump.xyz ATOMS=rna,ions STRIDE=100 -\endverbatim -(see also \ref TORSION, \ref GROUP, \ref WHOLEMOLECULES and \ref DUMPATOMS) +\endplumedfile Notice that if the biased variable requires a molecule to be whole, you might have to put just the \ref WHOLEMOLECULES command before computing that variable and leave the default STRIDE=1. This command instructs plumed to center all atoms around the center of mass of a solute molecule. -\verbatim +\plumedfile solute: GROUP ATOMS=1-100 all: GROUP ATOMS=1-1000 # center of the solute: @@ -116,8 +114,7 @@ com: COM ATOMS=solute # notice that we wrap around a single atom. this should be fast WRAPAROUND ATOMS=all AROUND=com DUMPATOMS FILE=dump.xyz ATOMS=all -\endverbatim -(see also \ref GROUP \ref COM \ref DUMPATOMS) +\endplumedfile Notice that whereas \ref WHOLEMOLECULES is designed to make molecules whole, \ref WRAPAROUND can easily break molecules. In the last example, @@ -136,7 +133,7 @@ in the following examples all the water oxygens will be brought close to the solute, and all the hydrogens will be kept close to their related oxygen. -\verbatim +\plumedfile solute: GROUP ATOMS=1-100 water: GROUP ATOMS=101-1000 com: COM ATOMS=solute @@ -145,8 +142,7 @@ WRAPAROUND ATOMS=solute AROUND=com # notice that we wrap around a single atom. this should be fast WRAPAROUND ATOMS=water AROUND=com GROUPBY=3 DUMPATOMS FILE=dump.xyz ATOMS=solute,water -\endverbatim -(see also \ref GROUP \ref COM \ref DUMPATOMS) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/ConvertToFES.cpp b/src/gridtools/ConvertToFES.cpp index 4e3bbdf170..661aa2bde9 100644 --- a/src/gridtools/ConvertToFES.cpp +++ b/src/gridtools/ConvertToFES.cpp @@ -46,12 +46,12 @@ and the HISTOGRAM action. All the data within this trajectory is used in the co HISTOGRAM. Finally, once all the data has been read in, the histogram is converted to a free energy using the formula above and the free energy is output to a file called fes.dat -\verbatim +\plumedfile x: DISTANCE ATOMS=1,2 hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 ff: CONVERT_TO_FES GRID=hA1 TEMP=300 DUMPGRID GRID=ff FILE=fes.dat -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/DumpCube.cpp b/src/gridtools/DumpCube.cpp index 0fbc47f566..f1df7406e7 100644 --- a/src/gridtools/DumpCube.cpp +++ b/src/gridtools/DumpCube.cpp @@ -46,14 +46,14 @@ between atoms 1 and 2, the distance between atom 1 and 3 and the angle between t all the kernels have been added the resulting histogram is output to a file called histoA1.cube. This file has the Gaussian cube file format. The histogram can thus be visualized using tools such as VMD. -\verbatim +\plumedfile x1: DISTANCE ATOMS=1,2 x2: DISTANCE ATOMS=1,3 x3: ANGLE ATOMS=1,2,3 hA1: HISTOGRAM ARG=x1,x2,x3 GRID_MIN=0.0,0.0,0.0 GRID_MAX=3.0,3.0,3.0 GRID_BIN=10,10,10 BANDWIDTH=1.0,1.0,1.0 DUMPCUBE GRID=hA1 FILE=histoA1.cube -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/DumpGrid.cpp b/src/gridtools/DumpGrid.cpp index 608742a8bf..e3524d563d 100644 --- a/src/gridtools/DumpGrid.cpp +++ b/src/gridtools/DumpGrid.cpp @@ -67,7 +67,7 @@ for y. This block is then followed by a blank line again and this pattern conti The following input monitors two torsional angles during a simulation and outputs a continuos histogram as a function of them at the end of the simulation. -\verbatim +\plumedfile TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... @@ -80,11 +80,11 @@ HISTOGRAM ... ... HISTOGRAM DUMPGRID GRID=hh FILE=histo -\endverbatim +\endplumedfile The following input monitors two torsional angles during a simulation and outputs a discrete histogram as a function of them at the end of the simulation. -\verbatim +\plumedfile TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... @@ -98,11 +98,11 @@ HISTOGRAM ... ... HISTOGRAM DUMPGRID GRID=hh FILE=histo -\endverbatim +\endplumedfile The following input monitors two torsional angles during a simulation and outputs the histogram accumulated thus far every 100000 steps. -\verbatim +\plumedfile TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... @@ -115,14 +115,14 @@ HISTOGRAM ... ... HISTOGRAM DUMPGRID GRID=hh FILE=histo STRIDE=100000 -\endverbatim +\endplumedfile The following input monitors two torsional angles during a simulation and outputs a separate histogram for each 100000 steps worth of trajectory. Notice how the CLEAR keyword is used here and how it is not used in the previous example. -\verbatim +\plumedfile TORSION ATOMS=1,2,3,4 LABEL=r1 TORSION ATOMS=2,3,4,5 LABEL=r2 HISTOGRAM ... @@ -136,7 +136,7 @@ HISTOGRAM ... ... HISTOGRAM DUMPGRID GRID=hh FILE=histo STRIDE=100000 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/FindContour.cpp b/src/gridtools/FindContour.cpp index a58e4f650e..1bae86d431 100644 --- a/src/gridtools/FindContour.cpp +++ b/src/gridtools/FindContour.cpp @@ -67,7 +67,7 @@ solidness at each point in the simulation cell. The Willard-Chandler dividing s at which the value of this phase field is equal to 0.5. This set of points is output to file called mycontour.dat. A new contour is found on every single step for each frame that is read in. -\verbatim +\plumedfile UNITS NATURAL FCCUBIC ... SPECIES=1-96000 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} @@ -84,7 +84,7 @@ MULTICOLVARDENS ... ... MULTICOLVARDENS FIND_CONTOUR GRID=dens CONTOUR=0.5 FILE=mycontour.dat -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/FindSphericalContour.cpp b/src/gridtools/FindSphericalContour.cpp index a2ee2aa862..7d36e818c8 100644 --- a/src/gridtools/FindSphericalContour.cpp +++ b/src/gridtools/FindSphericalContour.cpp @@ -81,7 +81,7 @@ by exploiting the functionality within \ref CENTER_OF_MULTICOLVAR. We can then cluster and the values of the coordination numbers of these atoms. The final line in the input then finds the a set of points on the dividing surface that separates teh droplet from the surrounding gas. The value of the phase field on this isocontour is equal to 0.75. -\verbatim +\plumedfile # Calculate coordination numbers c1: COORDINATIONNUMBER SPECIES=1-512 SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} # Select coordination numbers that are more than 2.0 @@ -98,7 +98,7 @@ cent: CENTER_OF_MULTICOLVAR DATA=trans1 dens: MULTICOLVARDENS DATA=trans1 ORIGIN=cent DIR=xyz NBINS=30,30,30 BANDWIDTH=2.0,2.0,2.0 # Find the isocontour around the nucleus FIND_SPHERICAL_CONTOUR GRID=dens CONTOUR=0.85 INNER_RADIUS=10.0 OUTER_RADIUS=40.0 FILE=mysurface.xyz UNITS=A PRECISION=4 NPOINTS=100 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/FourierTransform.cpp b/src/gridtools/FourierTransform.cpp index 5a53b390de..87a078336e 100644 --- a/src/gridtools/FourierTransform.cpp +++ b/src/gridtools/FourierTransform.cpp @@ -57,9 +57,9 @@ The default values of these parameters are: \f$a=1\f$ and \f$b=1\f$. \par Examples The following example tells Plumed to compute the complex 2D 'backward' Discrete Fourier Transform by taking the data saved on a grid called 'density', and normalizing the output by \f$ \frac{1}{\sqrt{N_x\, N_y}}\f$, where \f$N_x\f$ and \f$N_y\f$ are the number of data on the grid (it can be the case that \f$N_x \neq N_y\f$): -\verbatim +\plumedfile FOURIER_TRANSFORM STRIDE=1 GRID=density FT_TYPE=complex FOURIER_PARAMETERS=0,-1 FILE=fourier.dat -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/gridtools/InterpolateGrid.cpp b/src/gridtools/InterpolateGrid.cpp index e8f97c0d4a..7fbc1d65d3 100644 --- a/src/gridtools/InterpolateGrid.cpp +++ b/src/gridtools/InterpolateGrid.cpp @@ -38,12 +38,12 @@ distance between atoms 1 and 2 using kernel density estimation. During the calc are evaluated at 100 points on a uniform grid between 0.0 and 3.0. Prior to outputting this function at the end of the simulation this function is interpolated onto a finer grid of 200 points between 0.0 and 3.0. -\verbatim +\plumedfile x: DISTANCE ATOMS=1,2 hA1: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 ii: INTERPOLATE_GRID GRID=hA1 GRID_BIN=200 DUMPGRID GRID=ii FILE=histo.dat -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/maketools/plumedcheck b/src/maketools/plumedcheck index 120808decb..5886ec0863 100755 --- a/src/maketools/plumedcheck +++ b/src/maketools/plumedcheck @@ -354,6 +354,12 @@ BEGINFILE{ if(in_plumed_doc && (in_plumed_doc in provide_examples) && match($0,"^ *\\\\verbatim *$")){ provide_verbatim[in_plumed_doc]=1 } +# check if, besides the \par Examples text, there is a plumedfile command +# now it is considered equivalent to a verbatim +# later on we might make plumedfile compulsory instead of verbatim + if(in_plumed_doc && (in_plumed_doc in provide_examples) && match($0,"^ *\\\\plumedfile *$")){ + provide_verbatim[in_plumed_doc]=1 + } #print match($0,"^ *\\\\verbatim *$"),"X" $0 "X" # take note of actions or cltools that provide examples diff --git a/src/manyrestraints/LWalls.cpp b/src/manyrestraints/LWalls.cpp index 7c0ad569ec..c98405d04e 100644 --- a/src/manyrestraints/LWalls.cpp +++ b/src/manyrestraints/LWalls.cpp @@ -45,10 +45,10 @@ The following set of commands can be used to stop any of the 800 atoms in group in the z direction from atom 34137. This is done by adding a lower wall on the z-distance between all the atoms in group A and the position of 34137. -\verbatim +\plumedfile l: ZDISTANCES GROUPA=1-800 GROUPB=34137 NOPBC LWALLS DATA=l AT=2.46465 KAPPA=150.0 EXP=2 EPS=1 OFFSET=0 LABEL=lwall -\endverbatim +\endplumedfile */ diff --git a/src/manyrestraints/UWalls.cpp b/src/manyrestraints/UWalls.cpp index f4c75f0d89..2c0f75367d 100644 --- a/src/manyrestraints/UWalls.cpp +++ b/src/manyrestraints/UWalls.cpp @@ -48,11 +48,11 @@ and the center of mass of the cluster. These distances are then passed to the U a \ref UPPER_WALLS restraint on each of them and thereby prevents each of them from moving very far from the centre of mass of the cluster. -\verbatim +\plumedfile COM ATOMS=1-20 LABEL=c1 DISTANCES GROUPA=c1 GROUPB=1-20 LABEL=d1 UWALLS DATA=d1 AT=2.5 KAPPA=0.2 LABEL=sr -\endverbatim +\endplumedfile */ diff --git a/src/mapping/PCAVars.cpp b/src/mapping/PCAVars.cpp index d029720ed8..20ae003016 100644 --- a/src/mapping/PCAVars.cpp +++ b/src/mapping/PCAVars.cpp @@ -76,10 +76,10 @@ frame are removed from these displacements. The matrix \f$A\f$ and the referenc configuration \f$R^{ref}\f$ are specified in the pdb input file reference.pdb and the value of all projections (and the residual) are output to a file called colvar2. -\verbatim +\plumedfile PCAVARS REFERENCE=reference.pdb TYPE=OPTIMAL LABEL=pca2 PRINT ARG=pca2.* FILE=colvar2 -\endverbatim +\endplumedfile The reference configurations can be specified using a pdb file. The first configuration that you provide is the reference configuration, which is refered to in the above as \f$X^{ref}\f$ subsequent configurations give the directions of row vectors that are contained in diff --git a/src/mapping/Path.cpp b/src/mapping/Path.cpp index 37db777d2e..4808fad15d 100644 --- a/src/mapping/Path.cpp +++ b/src/mapping/Path.cpp @@ -73,21 +73,21 @@ In the example below the path is defined using RMSD distance from frames. The reference frames in the path are defined in the pdb file. In this frame each configuration in the path is separated by a line containing just the word END. -\verbatim +\plumedfile p1: PATH REFERENCE=file.pdb TYPE=OPTIMAL LAMBDA=500.0 PRINT ARG=p1.sss,p1.zzz STRIDE=1 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile In the example below the path is defined using the values of two torsional angles (t1 and t2). In addition, the \f$s\f$ and \f$z\f$ are calculated using the geometric expressions described above rather than the alegebraic expressions that are used by default. -\verbatim +\plumedfile t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 pp: PATH TYPE=EUCLIDEAN REFERENCE=epath.pdb GPATH NOSPATH NOZPATH PRINT ARG=pp.* FILE=colvar -\endverbatim +\endplumedfile Notice that the LAMBDA parameter is not required here as we are not calculating \f$s\f$ and \f$s\f$ using the algebraic formulae defined earlier. The positions of the frames in the path are defined @@ -109,19 +109,19 @@ The following input instructs PLUMED to calculate the values of the path collect path are defined in the file all.pdb and all distances are measured using the OPTIMAL metric that is discussed in the manual page on \ref RMSD. -\verbatim +\plumedfile p2: PATH REFERENCE=all.pdb LAMBDA=69087 PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar -\endverbatim +\endplumedfile If you wish to use collective variable values in the definition of your path you would use an input file with something like this: -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,2 d2: DISTANCE ATOMS=3,4a p2: PATH REFERENCE=mypath.pdb LAMBDA=2 TYPE=EUCLIDEAN PRINT ARG=p2.spath,p2.zpath STRIDE=1 FILE=colvar -\endverbatim +\endplumedfile The corresponding pdb file containing the definitions of the frames in the path would then look like this: diff --git a/src/mapping/PropertyMap.cpp b/src/mapping/PropertyMap.cpp index 9da32b47bb..91c96f4dd6 100644 --- a/src/mapping/PropertyMap.cpp +++ b/src/mapping/PropertyMap.cpp @@ -47,10 +47,10 @@ that these properties take at a set of reference configurations and using the fo between the reference configurations and the instantaneous configurations are calculated using the OPTIMAL metric that is discussed at length in the manual pages on \ref RMSD. -\verbatim +\plumedfile p2: GPROPERTYMAP REFERENCE=allv.pdb PROPERTY=X,Y LAMBDA=69087 PRINT ARG=p2.X,p2.Y,p2.zpath STRIDE=1 FILE=colvar -\endverbatim +\endplumedfile The additional input file for this calculation, which contains the reference frames and the values of X and Y at these reference points has the following format. diff --git a/src/multicolvar/AlphaBeta.cpp b/src/multicolvar/AlphaBeta.cpp index 01379c5837..aea79fc2ea 100644 --- a/src/multicolvar/AlphaBeta.cpp +++ b/src/multicolvar/AlphaBeta.cpp @@ -49,7 +49,7 @@ The \f$\phi_i^{\textrm{Ref}}\f$ values are the user-specified reference values f The following provides an example of the input for an alpha beta similarity. -\verbatim +\plumedfile ALPHABETA ... ATOMS1=168,170,172,188 REFERENCE1=3.14 ATOMS2=170,172,188,190 REFERENCE2=3.14 @@ -57,11 +57,11 @@ ATOMS3=188,190,192,230 REFERENCE3=3.14 LABEL=ab ... ALPHABETA PRINT ARG=ab FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Because all the reference values are the same we can calculate the same quantity using -\verbatim +\plumedfile ALPHABETA ... ATOMS1=168,170,172,188 REFERENCE=3.14 ATOMS2=170,172,188,190 @@ -69,13 +69,13 @@ ATOMS3=188,190,192,230 LABEL=ab ... ALPHABETA PRINT ARG=ab FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Writing out the atoms involved in all the torsions in this way can be rather tedious. Thankfully if you are working with protein you can avoid this by using the \ref MOLINFO command. PLUMED uses the pdb file that you provide to this command to learn about the topology of the protein molecule. This means that you can specify torsion angles using the following syntax: -\verbatim +\plumedfile MOLINFO MOLTYPE=protein STRUCTURE=myprotein.pdb ALPHABETA ... ATOMS1=@phi-3 REFERENCE=3.14 @@ -84,7 +84,7 @@ ATOMS3=@phi-4 LABEL=ab ... ALPHABETA PRINT ARG=ab FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle in the third residue of the protein. Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the 4th residue of the protein. diff --git a/src/multicolvar/Angles.cpp b/src/multicolvar/Angles.cpp index a42233cbd4..cdc0625799 100644 --- a/src/multicolvar/Angles.cpp +++ b/src/multicolvar/Angles.cpp @@ -58,28 +58,28 @@ an atom / molecule \cite lj-recon. The following example instructs plumed to find the average of two angles and to print it to a file -\verbatim +\plumedfile ANGLES ATOMS1=1,2,3 ATOMS2=4,5,6 MEAN LABEL=a1 PRINT ARG=a1.mean FILE=colvar -\endverbatim +\endplumedfile The following example tells plumed to calculate all angles involving at least one atom from GROUPA and two atoms from GROUPB in which the distances are less than 1.0. The number of angles between \f$\frac{\pi}{4}\f$ and \f$\frac{3\pi}{4}\f$ is then output -\verbatim +\plumedfile ANGLES GROUPA=1-10 GROUPB=11-100 BETWEEN={GAUSSIAN LOWER=0.25pi UPPER=0.75pi} SWITCH={GAUSSIAN R_0=1.0} LABEL=a1 PRINT ARG=a1.between FILE=colvar -\endverbatim +\endplumedfile This final example instructs plumed to calculate all the angles in the first coordination spheres of the atoms. A discretized-normalized histogram of the distribution is then output -\verbatim +\plumedfile ANGLES GROUP=1-38 HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=pi NBINS=20} SWITCH={GAUSSIAN R_0=1.0} LABEL=a1 PRINT ARG=a1.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/Bridge.cpp b/src/multicolvar/Bridge.cpp index 42198ffa1e..53e76158b5 100644 --- a/src/multicolvar/Bridge.cpp +++ b/src/multicolvar/Bridge.cpp @@ -51,10 +51,10 @@ The following example instructs plumed to calculate the number of water molecule that are bridging betweeen atoms 1-10 and atoms 11-20 and to print the value to a file -\verbatim +\plumedfile BRIDGE BRIDGING_ATOMS=100-200 GROUPA=1-10 GROUPB=11-20 LABEL=w1 PRINT ARG=a1.mean FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/CenterOfMultiColvar.cpp b/src/multicolvar/CenterOfMultiColvar.cpp index f8b5be6600..0708bd4025 100644 --- a/src/multicolvar/CenterOfMultiColvar.cpp +++ b/src/multicolvar/CenterOfMultiColvar.cpp @@ -55,10 +55,10 @@ As you want to calculate the position of the droplets you thus recognise that th numbers should have a high weight in the weighted average you are using to calculate the position of the droplet. You can thus calculate the position of the droplet using an input like the one shown below: -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-512 SWITCH={EXP D_0=4.0 R_0=0.5} cc: CENTER_OF_MULTICOLVAR DATA=c1 -\endverbatim +\endplumedfile The first line here calclates the coordination numbers of all the atoms in the system. The virtual atom then uses the values of the coordination numbers calculated by the action labelled c1 when it calculates the Berry Phase average described above. @@ -66,11 +66,11 @@ of the coordination numbers calculated by the action labelled c1 when it calcula The above input is fine we can, however, refine this somewhat by making use of a multicolvar transform action as shown below: -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-512 SWITCH={EXP D_0=4.0 R_0=0.5} cf: MTRANSFORM_MORE DATA=c1 SWITCH={RATIONAL D_0=2.0 R_0=0.1} LOWMEM cc: CENTER_OF_MULTICOLVAR DATA=cf -\endverbatim +\endplumedfile This input once again calculates the coordination numbers of all the atoms in the system. The middle line then transforms these coordinations numbers to numbers between 0 and 1. Essentially any atom with a coordination number larger than 2.0 is given a weight diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp index a3823b4887..38c26d348b 100644 --- a/src/multicolvar/CoordinationNumbers.cpp +++ b/src/multicolvar/CoordinationNumbers.cpp @@ -48,16 +48,16 @@ s = \frac{ 1 - \left(\frac{r-d_0}{r_0}\right)^n } { 1 - \left(\frac{r-d_0}{r_0}\ The following input tells plumed to calculate the coordination numbers of atoms 1-100 with themselves. The minimum coordination number is then calculated. -\verbatim +\plumedfile COORDINATIONNUMBER SPECIES=1-100 R_0=1.0 MIN={BETA=0.1} -\endverbatim +\endplumedfile The following input tells plumed to calculate how many atoms from 1-100 are within 3.0 of each of the atoms from 101-110. In the first 101 is the central atom, in the second 102 is the central atom and so on. The number of coordination numbers more than 6 is then computed. -\verbatim +\plumedfile COORDINATIONNUMBER SPECIESA=101-110 SPECIESB=1-100 R_0=3.0 MORE_THAN={RATIONAL R_0=6.0 NN=6 MM=12 D_0=0} -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/Density.cpp b/src/multicolvar/Density.cpp index 0351140a3f..598e16b309 100644 --- a/src/multicolvar/Density.cpp +++ b/src/multicolvar/Density.cpp @@ -40,11 +40,11 @@ the number of atoms in half the box. The following example calculates the number of atoms in one half of the simulation box. -\verbatim +\plumedfile DENSITY SPECIES=1-100 LABEL=d AROUND ARG=d XLOWER=0.0 XUPPER=0.5 LABEL=d1 PRINT ARG=d1.* FILE=colvar1 FMT=%8.4f -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/DihedralCorrelation.cpp b/src/multicolvar/DihedralCorrelation.cpp index e75bde6680..a1f5ea8729 100644 --- a/src/multicolvar/DihedralCorrelation.cpp +++ b/src/multicolvar/DihedralCorrelation.cpp @@ -48,14 +48,14 @@ where the \f$\phi_i\f$ and \f$\psi\f$ values and the instantaneous values for th The following provides an example input for the dihcor action -\verbatim +\plumedfile DIHCOR ... ATOMS1=1,2,3,4,5,6,7,8 ATOMS2=5,6,7,8,9,10,11,12 LABEL=dih ... DIHCOR PRINT ARG=dih FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile In the above input we are calculating the correation between the torsion angle involving atoms 1, 2, 3 and 4 and the torsion angle involving atoms 5, 6, 7 and 8. This is then added to the correlation betwene the torsion angle involving atoms 5, 6, 7 and 8 and the @@ -65,7 +65,7 @@ Writing out the atoms involved in all the torsions in this way can be rather ted can avoid this by using the \ref MOLINFO command. PLUMED uses the pdb file that you provide to this command to learn about the topology of the protein molecule. This means that you can specify torsion angles using the following syntax: -\verbatim +\plumedfile MOLINFO MOLTYPE=protein STRUCTURE=myprotein.pdb DIHCOR ... ATOMS1=@phi-3,@psi-3 @@ -73,7 +73,7 @@ ATOMS2=@psi-3,@phi-4 ATOMS4=@phi-4,@psi-4 ... DIHCOR PRINT ARG=dih FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle in the third residue of the protein. Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the 4th residue of the protein. diff --git a/src/multicolvar/DistanceFromContour.cpp b/src/multicolvar/DistanceFromContour.cpp index 214930392e..6f99e214a4 100644 --- a/src/multicolvar/DistanceFromContour.cpp +++ b/src/multicolvar/DistanceFromContour.cpp @@ -58,10 +58,10 @@ In this example atoms 2-100 are assumed to be concentraed along some part of the an interface between a liquid/solid and the vapour. The quantity dc measures the distance between the surface at which the density of 2-100 atoms is equal to 0.2 and the position of the test particle atom 1. -\verbatim +\plumedfile dens: DENSITY SPECIES=2-100 dc: DISTANCE_FROM_CONTOUR DATA=dens ATOM=1 BANDWIDTH=0.5,0.5,0.5 DIR=z CONTOUR=0.2 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp index d5cb8fde00..579668b880 100644 --- a/src/multicolvar/Distances.cpp +++ b/src/multicolvar/Distances.cpp @@ -42,36 +42,36 @@ distances such as the minimum, the number less than a certain quantity and so on The following input tells plumed to calculate the distances between atoms 3 and 5 and between atoms 1 and 2 and to print the minimum for these two distances. -\verbatim +\plumedfile DISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). The following input tells plumed to calculate the distances between atoms 3 and 5 and between atoms 1 and 2 and then to calculate the number of these distances that are less than 0.1 nm. The number of distances less than 0.1nm is then printed to a file. -\verbatim +\plumedfile DISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.lt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction). The following input tells plumed to calculate all the distances between atoms 1, 2 and 3 (i.e. the distances between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these distances is then calculated. -\verbatim +\plumedfile DISTANCES GROUP=1-3 MEAN LABEL=d1 PRINT ARG=d1.mean -\endverbatim +\endplumedfile (See also \ref PRINT) The following input tells plumed to calculate all the distances between the atoms in GROUPA and the atoms in GROUPB. In other words the distances between atoms 1 and 2 and the distance between atoms 1 and 3. The number of distances more than 0.1 is then printed to a file. -\verbatim +\plumedfile DISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.gt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction) @@ -79,10 +79,10 @@ PRINT ARG=d1.gt0.1 To calculate and print the minimum distance between two groups of atoms you use the following commands -\verbatim +\plumedfile d1: DISTANCES GROUPA=1-10 GROUPB=11-20 MIN={BETA=500.} PRINT ARG=d1.min FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile (see \ref DISTANCES and \ref PRINT) In order to ensure differentiability the minimum is calculated using the following function: @@ -102,7 +102,7 @@ allow you to calculate multiple functions of a distribution of simple collective can calculate the number of distances less than 1.0, the minimum distance, the number of distances more than 2.0 and the number of distances between 1.0 and 2.0 by using the following command: -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 LESS_THAN={RATIONAL R_0=1.0} @@ -111,7 +111,7 @@ DISTANCES ... MIN={BETA=500.} ... DISTANCES PRINT ARG=d1.lessthan,d1.morethan,d1.between,d1.min FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile (see \ref DISTANCES and \ref PRINT) A calculation performed this way is fast because the expensive part of the calculation - the calculation of all the distances - is only diff --git a/src/multicolvar/DumpMultiColvar.cpp b/src/multicolvar/DumpMultiColvar.cpp index 27029a4369..fb08af5b44 100644 --- a/src/multicolvar/DumpMultiColvar.cpp +++ b/src/multicolvar/DumpMultiColvar.cpp @@ -49,13 +49,13 @@ In this examples we calculate the distances between the atoms of the first and group and we write them in the file MULTICOLVAR.xyz. For each couple it writes the coordinates of their geometric center and their distance. -\verbatim +\plumedfile pos: GROUP ATOMS=220,221,235,236,247,248,438,439,450,451,534,535 neg: GROUP ATOMS=65,68,138,182,185,267,270,291,313,316,489,583,621,711 DISTANCES GROUPA=pos GROUPB=neg LABEL=slt DUMPMULTICOLVAR DATA=slt FILE=MULTICOLVAR.xyz -\endverbatim +\endplumedfile (see also \ref DISTANCES) diff --git a/src/multicolvar/FilterBetween.cpp b/src/multicolvar/FilterBetween.cpp index d6a4187118..17ad0be9e5 100644 --- a/src/multicolvar/FilterBetween.cpp +++ b/src/multicolvar/FilterBetween.cpp @@ -59,22 +59,22 @@ In other words, you are calculating the mean for the transformed colvar. The following input gives an example of how a MTRANSFORM_BETWEEN action can be used to duplicate functionality that is elsehwere in PLUMED. -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 LABEL=d1 ... DISTANCES MTRANSFORM_BETWEEN DATA=d1 LOWER=1.0 UPPER=2.0 SMEAR=0.5 -\endverbatim +\endplumedfile In this case you can achieve the same result by using: -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 BETWEEN={GAUSSIAN LOWER=1.0 UPPER=2.0} ... DISTANCES -\endverbatim +\endplumedfile (see \ref DISTANCES) The advantage of MTRANSFORM_BETWEEN comes, however, if you want to use transformed colvars as input @@ -112,10 +112,10 @@ One is thus calculating the mean for those colvars that are within the range of The example shown below calculates the mean for those distances that are between 0 and 3 nm in length -\verbatim +\plumedfile DISTANCES GROUPA=1 GROUPB=2-50 MEAN LABEL=d1 MFILTER_BETWEEN DATA=d1 LOWER=0 UPPER=3.0 SMEAR=0.0001 MEAN LABEL=d4 -\endverbatim +\endplumedfile More complicated things can be done by using the label of a filter as input to a new multicolvar as shown in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination @@ -123,11 +123,11 @@ number between 4 and 6 are then identified using the filter. This reduced list to a second coordination number calculation. This second coordination number thus measures the number of atoms 4-6 coordinated atoms each of the 4-6 coordination atoms is bound to. -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-150 SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} cf: MFILTER_BETWEEN DATA=c1 LOWER=4 UPPER=6 SMEAR=0.5 LOWMEM c2: COORDINATIONNUMBER SPECIES=cf SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} MORE_THAN={RATIONAL D_0=2.0 R_0=0.1} -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/FilterLessThan.cpp b/src/multicolvar/FilterLessThan.cpp index 6363bcbb43..e65d5fcd18 100644 --- a/src/multicolvar/FilterLessThan.cpp +++ b/src/multicolvar/FilterLessThan.cpp @@ -51,22 +51,22 @@ In other words, you are calculating the mean for the transformed colvar. The following input gives an example of how a MTRANSFORM_LESS action can be used to duplicate functionality that is elsehwere in PLUMED. -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 LABEL=d1 ... DISTANCES MTRANSFORM_LESS DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} -\endverbatim +\endplumedfile In this case you can achieve the same result by using: -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 LESS_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} ... DISTANCES -\endverbatim +\endplumedfile (see \ref DISTANCES) The advantage of MTRANSFORM_LESS comes, however, if you want to use transformed colvars as input @@ -99,10 +99,10 @@ One is thus calculating the mean for those colvars that are less than the target The example shown below calculates the mean for those distances that less than 1.5 nm in length -\verbatim +\plumedfile DISTANCES GROUPA=1 GROUPB=2-50 MEAN LABEL=d1 MFILTER_LESS DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} MEAN LABEL=d4 -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/FilterMoreThan.cpp b/src/multicolvar/FilterMoreThan.cpp index 961c33d016..50c1dc59b5 100644 --- a/src/multicolvar/FilterMoreThan.cpp +++ b/src/multicolvar/FilterMoreThan.cpp @@ -51,22 +51,22 @@ In other words, you are calculating the mean for the transformed colvar. The following input gives an example of how a MTRANSFORM_MORE action can be used to duplicate functionality that is elsehwere in PLUMED. -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 LABEL=d1 ... DISTANCES MTRANSFORM_MORE DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} -\endverbatim +\endplumedfile In this case you can achieve the same result by using: -\verbatim +\plumedfile DISTANCES ... GROUPA=1-10 GROUPB=11-20 MORE_THAN={GAUSSIAN D_0=1.5 R_0=0.00001} ... DISTANCES -\endverbatim +\endplumedfile (see \ref DISTANCES) The advantage of MTRANSFORM_MORE comes, however, if you want to use transformed colvars as input @@ -104,10 +104,10 @@ One is thus calculating the mean for those colvars that are greater than the tar The example shown below calculates the mean for those distances that greater than 1.5 nm in length -\verbatim +\plumedfile DISTANCES GROUPA=1 GROUPB=2-50 MEAN LABEL=d1 MFILTER_MORE DATA=d1 SWITCH={GAUSSIAN D_0=1.5 R_0=0.00001} MEAN LABEL=d4 -\endverbatim +\endplumedfile More complicated things can be done by using the label of a filter as input to a new multicolvar as shown in the example below. Here the coordination numbers of all atoms are computed. The atoms with a coordination @@ -115,11 +115,11 @@ number greater than 2 are then identified using the filter. This reduced list o to a second coordination number calculation. This second coordination number thus measures the number of two-coordinated atoms that each of the two-coordinated atoms is bound to. -\verbatim +\plumedfile 1: COORDINATIONNUMBER SPECIES=1-150 SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} cf: MFILTER_MORE DATA=c1 SWITCH={RATIONAL D_0=2.0 R_0=0.1} LOWMEM c2: COORDINATIONNUMBER SPECIES=cf SWITCH={EXP D_0=4.0 R_0=0.5 D_MAX=6.0} MORE_THAN={RATIONAL D_0=2.0 R_0=0.1} -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/InPlaneDistances.cpp b/src/multicolvar/InPlaneDistances.cpp index d041fa1e02..ef9f4a55f5 100644 --- a/src/multicolvar/InPlaneDistances.cpp +++ b/src/multicolvar/InPlaneDistances.cpp @@ -53,10 +53,10 @@ Keywords such as MORE_THAN and LESS_THAN can then be used to calculate the numbe The following input can be used to calculate the number of atoms that have indices greater than 3 and less than 101 that are within a cylinder with a radius of 0.3 nm that has its long axis aligned with the vector connecting atoms 1 and 2. -\verbatim +\plumedfile d1: INPLANEDISTANCES VECTORSTART=1 VECTOREND=2 GROUP=3-100 LESS_THAN={RATIONAL D_0=0.2 R_0=0.1} PRINT ARG=d1.lessthan FILE=colvar -\endverbatim +\endplumedfile */ diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index fdc3e09c4f..c8bae1d56e 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -59,21 +59,21 @@ and so on. You can also probe the value of these averaged variables in regions This example input calculates the coordination numbers for all the atoms in the system. These coordination numbers are then averaged over spherical regions. The number of averaged coordination numbers that are greater than 4 is then output to a file. -\verbatim +\plumedfile COORDINATIONNUMBER SPECIES=1-64 D_0=1.3 R_0=0.2 LABEL=d1 LOCAL_AVERAGE ARG=d1 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MORE_THAN={RATIONAL R_0=4} LABEL=la PRINT ARG=la.* FILE=colvar -\endverbatim +\endplumedfile This example input calculates the \f$q_4\f$ (see \ref Q4) vectors for each of the atoms in the system. These vectors are then averaged component by component over a spherical region. The average value for this quantity is then outputeed to a file. This calculates the quantities that were used in the paper by Lechner and Dellago \cite dellago-q6 -\verbatim +\plumedfile Q4 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q4 LOCAL_AVERAGE ARG=q4 SWITCH={RATIONAL D_0=1.3 R_0=0.2} MEAN LABEL=la PRINT ARG=la.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/MultiColvarDensity.cpp b/src/multicolvar/MultiColvarDensity.cpp index 7ea3dc0096..8e63b6e513 100644 --- a/src/multicolvar/MultiColvarDensity.cpp +++ b/src/multicolvar/MultiColvarDensity.cpp @@ -58,11 +58,11 @@ The following example shows perhaps the simplest way in which this action can be input computes the density of atoms at each point on the grid and ouptuts this quantity to a file. In other words this input instructs plumed to calculate \f$\rho(\mathbf{r}) = \sum_i K(\mathbf{r} - \mathbf{r}_i )\f$ -\verbatim +\plumedfile dens: DENSITY SPECIES=1-100 grid: MULTICOLVARDENS DATA=dens ORIGIN=1 DIR=xyz NBINS=100,100,100 BANDWIDTH=0.05,0.05,0.05 STRIDE=1 DUMPGRID GRID=grid STRIDE=500 FILE=density -\endverbatim +\endplumedfile In the above example density is added to the grid on every step. The PRINT_GRID instruction thus tells PLUMED to output the average density at each point on the grid every 500 steps of simulation. Notice that the that grid output @@ -72,11 +72,11 @@ of data separately you must use the CLEAR flag. This second example computes an order parameter (in this case \ref FCCUBIC) and constructs a phase field model for this order parameter using the equation above. -\verbatim +\plumedfile fcc: FCCUBIC SPECIES=1-5184 SWITCH={CUBIC D_0=1.2 D_MAX=1.5} ALPHA=27 dens: MULTICOLVARDENS DATA=fcc ORIGIN=1 DIR=xyz NBINS=14,14,28 BANDWIDTH=1.0,1.0,1.0 STRIDE=1 CLEAR=1 DUMPCUBE GRID=dens STRIDE=1 FILE=dens.cube -\endverbatim +\endplumedfile In this example the phase field model is computed and output to a file on every step of the simulation. Furthermore, because the CLEAR=1 keyword is set on the MULTICOLVARDENS line each Gaussian cube file output is a phase field diff --git a/src/multicolvar/NumberOfLinks.cpp b/src/multicolvar/NumberOfLinks.cpp index b8257c5e4b..c8850755bd 100644 --- a/src/multicolvar/NumberOfLinks.cpp +++ b/src/multicolvar/NumberOfLinks.cpp @@ -43,22 +43,22 @@ similar orientations. The vectors on individual atoms could be Steinhardt param The following calculates how many bonds there are in a system containing 64 atoms and outputs this quantity to a file. -\verbatim +\plumedfile DENSITY SPECIES=1-64 LABEL=d1 NLINKS ARG=d1 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=dd PRINT ARG=dd FILE=colvar -\endverbatim +\endplumedfile The following calculates how many pairs of neighbouring atoms in a system containg 64 atoms have similar dispositions for the atoms in their coordination sphere. This calculation uses the dot product of the Q6 vectors on adjacent atoms to measure whether or not two atoms have the same ``orientation" -\verbatim +\plumedfile Q6 SPECIES=1-64 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=q6 NLINKS ARG=q6 SWITCH={RATIONAL D_0=1.3 R_0=0.2} LABEL=dd PRINT ARG=dd FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/Torsions.cpp b/src/multicolvar/Torsions.cpp index 59d02cbfd7..4e3fcfbb2d 100644 --- a/src/multicolvar/Torsions.cpp +++ b/src/multicolvar/Torsions.cpp @@ -40,7 +40,7 @@ Calculate whether or not a set of torsional angles are within a particular range The following provides an example of the input for the torsions command -\verbatim +\plumedfile TORSIONS ... ATOMS1=168,170,172,188 ATOMS2=170,172,188,190 @@ -48,13 +48,13 @@ ATOMS3=188,190,192,230 LABEL=ab ... TORSIONS PRINT ARG=ab.* FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Writing out the atoms involved in all the torsions in this way can be rather tedious. Thankfully if you are working with protein you can avoid this by using the \ref MOLINFO command. PLUMED uses the pdb file that you provide to this command to learn about the topology of the protein molecule. This means that you can specify torsion angles using the following syntax: -\verbatim +\plumedfile MOLINFO MOLTYPE=protein STRUCTURE=myprotein.pdb TORSIONS ... ATOMS1=@phi-3 @@ -63,7 +63,7 @@ ATOMS3=@phi-4 LABEL=ab ... TORSIONS PRINT ARG=ab FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Here, \@phi-3 tells plumed that you would like to calculate the \f$\phi\f$ angle in the third residue of the protein. Similarly \@psi-4 tells plumed that you want to calculate the \f$\psi\f$ angle of the 4th residue of the protein. diff --git a/src/multicolvar/VolumeAround.cpp b/src/multicolvar/VolumeAround.cpp index bab79d8e0a..d44f36d4b2 100644 --- a/src/multicolvar/VolumeAround.cpp +++ b/src/multicolvar/VolumeAround.cpp @@ -55,11 +55,11 @@ When AROUND is used with the \ref DENSITY action the number of atoms in the spec The following commands tell plumed to calculate the average coordination number for the atoms that have x (in fractional coordinates) within 2.0 nm of the com of mass c1. The final value will be labeled s.mean. -\verbatim +\plumedfile COM ATOMS=1-100 LABEL=c1 COORDINATIONNUMBER SPECIES=1-100 R_0=1.0 LABEL=c AROUND DATA=c ORIGIN=c1 XLOWER=-2.0 XUPPER=2.0 SIGMA=0.1 MEAN LABEL=s -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/VolumeCavity.cpp b/src/multicolvar/VolumeCavity.cpp index af14a2be05..70d8254f32 100644 --- a/src/multicolvar/VolumeCavity.cpp +++ b/src/multicolvar/VolumeCavity.cpp @@ -86,19 +86,19 @@ described above and the resulting projections determine the \f$u'\f$, \f$v'\f$ a The following commands tell plumed to calculate the number of atoms in an ion chanel in a protein. The extent of the chanel is calculated from the positions of atoms 1, 4, 5 and 11. The final value will be labeled cav. -\verbatim +\plumedfile d1: DENSITY SPECIES=20-500 CAVITY DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 LABEL=cav -\endverbatim +\endplumedfile The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water molecules in the protein channel described above. The average coordination number and the number of coordination numbers more than 4 is then calculated. The values of these two quantities are given the labels cav.mean and cav.morethan -\verbatim +\plumedfile d1: COORDINATIONNUMBER SPECIES=20-500 CAVITY DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 MEAN MORE_THAN={RATIONAL R_0=4} LABEL=cav -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/VolumeInCylinder.cpp b/src/multicolvar/VolumeInCylinder.cpp index eb6bc611e4..3e8acfb226 100644 --- a/src/multicolvar/VolumeInCylinder.cpp +++ b/src/multicolvar/VolumeInCylinder.cpp @@ -59,11 +59,11 @@ When INCYLINDER is used with the \ref DENSITY action the number of atoms in the The input below can be use to calculate the average coordination numbers for those atoms that are within a cylindrical tube of radius 1.5 nm that is centered on the position of atom 101 and that has its long axis parallel to the z-axis. -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} d2: INCYLINDER ATOM=101 DATA=d1 DIRECTION=Z RADIUS={TANH R_0=1.5} SIGMA=0.1 LOWER=-0.1 UPPER=0.1 MEAN PRINT ARG=d2.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/VolumeInSphere.cpp b/src/multicolvar/VolumeInSphere.cpp index 632af88df5..937e067dd8 100644 --- a/src/multicolvar/VolumeInSphere.cpp +++ b/src/multicolvar/VolumeInSphere.cpp @@ -58,11 +58,11 @@ When INCYLINDER is used with the \ref DENSITY action the number of atoms in the The input below can be use to calculate the average coordination numbers for those atoms that are within a sphere of radius 1.5 nm that is centered on the position of atom 101. -\verbatim +\plumedfile c1: COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=0.1} d2: INSPHERE ATOM=101 DATA=d1 RADIUS={TANH R_0=1.5} SIGMA=0.1 LOWER=-0.1 UPPER=0.1 MEAN PRINT ARG=d2.* FILE=colvar -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/VolumeTetrapore.cpp b/src/multicolvar/VolumeTetrapore.cpp index 98fe915c33..c7dcd66d04 100644 --- a/src/multicolvar/VolumeTetrapore.cpp +++ b/src/multicolvar/VolumeTetrapore.cpp @@ -94,19 +94,19 @@ This is in fact the only point of difference between these two actions. The following commands tell plumed to calculate the number of atom inside a tetrahedral cavity. The extent of the tetrahedral cavity is calculated from the positions of atoms 1, 4, 5, and 11, The final value will be labeled cav. -\verbatim +\plumedfile d1: DENSITY SPECIES=20-500 TETRAHEDRALPORE DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 LABEL=cav -\endverbatim +\endplumedfile The following command tells plumed to calculate the coordination numbers (with other water molecules) for the water molecules in the tetrahedral cavity described above. The average coordination number and the number of coordination numbers more than 4 is then calculated. The values of these two quantities are given the labels cav.mean and cav.morethan -\verbatim +\plumedfile d1: COORDINATIONNUMBER SPECIES=20-500 CAVITY DATA=d1 ATOMS=1,4,5,11 SIGMA=0.1 MEAN MORE_THAN={RATIONAL R_0=4} LABEL=cav -\endverbatim +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/multicolvar/XAngle.cpp b/src/multicolvar/XAngle.cpp index fbc2ab1d71..dd90c187f6 100644 --- a/src/multicolvar/XAngle.cpp +++ b/src/multicolvar/XAngle.cpp @@ -41,10 +41,10 @@ Calculate the angles between the vector connecting two atoms and the x axis. The following input tells plumed to calculate the angles between the x-axis and the vector connecting atom 3 to atom 5 and between the x-axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -\verbatim +\plumedfile XANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -57,10 +57,10 @@ Calculate the angles between the vector connecting two atoms and the y axis. The following input tells plumed to calculate the angles between the y-axis and the vector connecting atom 3 to atom 5 and between the y-axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -\verbatim +\plumedfile YANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -73,10 +73,10 @@ Calculate the angles between the vector connecting two atoms and the z axis. The following input tells plumed to calculate the angles between the z-axis and the vector connecting atom 3 to atom 5 and between the z-axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then -\verbatim +\plumedfile ZANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC diff --git a/src/multicolvar/XDistances.cpp b/src/multicolvar/XDistances.cpp index 009b04de59..fe29a8b650 100644 --- a/src/multicolvar/XDistances.cpp +++ b/src/multicolvar/XDistances.cpp @@ -42,38 +42,38 @@ values such as the minimum, the number less than a certain quantity and so on. The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and the x-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then printed -\verbatim +\plumedfile XDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). The following input tells plumed to calculate the x-component of the vector connecting atom 3 to atom 5 and the x-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. -\verbatim +\plumedfile XDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.lt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction). The following input tells plumed to calculate the x-components of all the distinct vectors that can be created between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. -\verbatim +\plumedfile XDISTANCES GROUP=1-3 AVERAGE LABEL=d1 PRINT ARG=d1.average -\endverbatim +\endplumedfile (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. -\verbatim +\plumedfile XDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.gt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction) */ //+ENDPLUMEDOC @@ -89,38 +89,38 @@ values such as the minimum, the number less than a certain quantity and so on. The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and the y-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then printed -\verbatim +\plumedfile YDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). The following input tells plumed to calculate the y-component of the vector connecting atom 3 to atom 5 and the y-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. -\verbatim +\plumedfile YDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.lt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction). The following input tells plumed to calculate the y-components of all the distinct vectors that can be created between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. -\verbatim +\plumedfile YDISTANCES GROUP=1-3 AVERAGE LABEL=d1 PRINT ARG=d1.average -\endverbatim +\endplumedfile (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. -\verbatim +\plumedfile YDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.gt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction) */ @@ -137,38 +137,38 @@ values such as the minimum, the number less than a certain quantity and so on. The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and the z-component of the vector connecting atom 1 to atom 2. The minimum of these two quantities is then printed -\verbatim +\plumedfile ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). The following input tells plumed to calculate the z-component of the vector connecting atom 3 to atom 5 and the z-component of the vector connecting atom 1 to atom 2. The number of values that are less than 0.1nm is then printed to a file. -\verbatim +\plumedfile ZDISTANCES ATOMS1=3,5 ATOMS2=1,2 LABEL=d1 LESS_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.lt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction). The following input tells plumed to calculate the z-components of all the distinct vectors that can be created between atoms 1, 2 and 3 (i.e. the vectors between atoms 1 and 2, atoms 1 and 3 and atoms 2 and 3). The average of these quantities is then calculated. -\verbatim +\plumedfile ZDISTANCES GROUP=1-3 AVERAGE LABEL=d1 PRINT ARG=d1.average -\endverbatim +\endplumedfile (See also \ref PRINT) The following input tells plumed to calculate all the vectors connecting the the atoms in GROUPA to the atoms in GROUPB. In other words the vector between atoms 1 and 2 and the vector between atoms 1 and 3. The number of values more than 0.1 is then printed to a file. -\verbatim +\plumedfile ZDISTANCES GROUPA=1 GROUPB=2,3 MORE_THAN={RATIONAL R_0=0.1} PRINT ARG=d1.gt0.1 -\endverbatim +\endplumedfile (See also \ref PRINT \ref switchingfunction) */ diff --git a/src/multicolvar/XYDistances.cpp b/src/multicolvar/XYDistances.cpp index 767c64a86a..c0c8d4aa52 100644 --- a/src/multicolvar/XYDistances.cpp +++ b/src/multicolvar/XYDistances.cpp @@ -43,10 +43,10 @@ The following input tells plumed to calculate the projection of the length of th to atom 5 projected in the xy-plane and the projection of the length of the vector the vector connecting atom 1 to atom 2 in the xy-plane. The minimum of these two quantities is then printed -\verbatim +\plumedfile XYDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ @@ -64,10 +64,10 @@ The following input tells plumed to calculate the projection of the length of th to atom 5 projected in the xz-plane and the projection of the length of the vector the vector connecting atom 1 to atom 2 in the xz-plane. The minimum of these two quantities is then printed -\verbatim +\plumedfile XZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ @@ -85,10 +85,10 @@ The following input tells plumed to calculate the projection of the length of th to atom 5 in the yz-plane and the projection of the length of the vector the vector connecting atom 1 to atom 2 in the yz-plane. The minimum of these two quantities is then printed -\verbatim +\plumedfile YZDISTANCES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ diff --git a/src/multicolvar/XYTorsion.cpp b/src/multicolvar/XYTorsion.cpp index fd512799a4..4e0804a508 100644 --- a/src/multicolvar/XYTorsion.cpp +++ b/src/multicolvar/XYTorsion.cpp @@ -41,10 +41,10 @@ Calculate the torsional angle around the x axis from the positive y direction. The following input tells plumed to calculate the angle around the x direction between the positive y-axis and the vector connecting atom 3 to atom 5 and the angle around the x direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output -\verbatim +\plumedfile XYTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -57,10 +57,10 @@ Calculate the torsional angle around the x axis from the positive z direction. The following input tells plumed to calculate the angle around the x direction between the positive z-axis and the vector connecting atom 3 to atom 5 and the angle around the x direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output -\verbatim +\plumedfile XZTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -73,10 +73,10 @@ Calculate the torsional angle around the y axis from the positive x direction. The following input tells plumed to calculate the angle around the y direction between the positive x-direction and the vector connecting atom 3 to atom 5 and the angle around the y direction between the positive x axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output -\verbatim +\plumedfile YXTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -89,10 +89,10 @@ Calculate the torsional angle around the y axis from the positive z direction. The following input tells plumed to calculate the angle around the y direction between the positive z-direction and the vector connecting atom 3 to atom 5 and the angle around the y direction between the positive z direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output -\verbatim +\plumedfile YZTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -105,10 +105,10 @@ Calculate the torsional angle around the z axis from the positive x direction. The following input tells plumed to calculate the angle around the z direction between the positive x-direction and the vector connecting atom 3 to atom 5 and the angle around the z direction between the positive x-direction and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output -\verbatim +\plumedfile ZXTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC @@ -121,10 +121,10 @@ Calculate the torsional angle around the z axis from the positive y direction. The following input tells plumed to calculate the angle around the z direction between the positive y-axis and the vector connecting atom 3 to atom 5 and the angle around the z direction between the positive y axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then output -\verbatim +\plumedfile ZYTORSIONS ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min -\endverbatim +\endplumedfile (See also \ref PRINT). */ //+ENDPLUMEDOC diff --git a/src/secondarystructure/AlphaRMSD.cpp b/src/secondarystructure/AlphaRMSD.cpp index 6c9b49083e..ecf10eacb3 100644 --- a/src/secondarystructure/AlphaRMSD.cpp +++ b/src/secondarystructure/AlphaRMSD.cpp @@ -68,11 +68,10 @@ anthing other than TYPE=DRMSD. For more details as to how to do this see \ref W The following input calculates the number of six residue segments of protein that are in an alpha helical configuration. -\verbatim +\plumedfile MOLINFO STRUCTURE=helix.pdb ALPHARMSD RESIDUES=all TYPE=DRMSD LESS_THAN={RATIONAL R_0=0.08 NN=8 MM=12} LABEL=a -\endverbatim -(see also \ref MOLINFO) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/secondarystructure/AntibetaRMSD.cpp b/src/secondarystructure/AntibetaRMSD.cpp index 6e60d54454..637e4c0b38 100644 --- a/src/secondarystructure/AntibetaRMSD.cpp +++ b/src/secondarystructure/AntibetaRMSD.cpp @@ -70,11 +70,10 @@ anthing other than TYPE=DRMSD. For more details as to how to do this see \ref W The following input calculates the number of six residue segments of protein that are in an antiparallel beta sheet configuration. -\verbatim +\plumedfile MOLINFO STRUCTURE=helix.pdb ANTIBETARMSD RESIDUES=all TYPE=DRMSD LESS_THAN={RATIONAL R_0=0.08 NN=8 MM=12} LABEL=a -\endverbatim -(see also \ref MOLINFO) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/secondarystructure/ParabetaRMSD.cpp b/src/secondarystructure/ParabetaRMSD.cpp index fe87408643..1a67ec8afc 100644 --- a/src/secondarystructure/ParabetaRMSD.cpp +++ b/src/secondarystructure/ParabetaRMSD.cpp @@ -70,11 +70,10 @@ anthing other than TYPE=DRMSD. For more details as to how to do this see \ref W The following input calculates the number of six residue segments of protein that are in an parallel beta sheet configuration. -\verbatim +\plumedfile MOLINFO STRUCTURE=helix.pdb PARABETARMSD RESIDUES=all TYPE=DRMSD LESS_THAN={RATIONAL R_0=0.08 NN=8 MM=12} LABEL=a -\endverbatim -(see also \ref MOLINFO) +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/setup/Load.cpp b/src/setup/Load.cpp index 93f9d39b88..4002ed0f0f 100644 --- a/src/setup/Load.cpp +++ b/src/setup/Load.cpp @@ -43,9 +43,9 @@ If you have a shared object named extensions.so and want to use the functionalities implemented in it within PLUMED you can load it with the following syntax -\verbatim +\plumedfile LOAD FILE=extensions.so -\endverbatim +\endplumedfile As a more practical example, imagine that you want to make a small change to one collective variable that is already implemented @@ -61,7 +61,7 @@ with different names. Then you can compile it into a shared object using This will generate a file `Distance2.so` (or `Distance2.dylib` on a mac) that can be loaded. Now you can use your new implementation with the following input -\verbatim +\plumedfile # load the new library LOAD FILE=Distance2.so # compute standard distance @@ -70,11 +70,11 @@ d: DISTANCE ATOMS=1,10 d2: DISTANCE2 ATOMS=1,10 # print them on a file PRINT ARG=d,d2 FILE=compare-them -\endverbatim +\endplumedfile You can even skip the initial step and directly feed PLUMED with the `Distance2.cpp` file: it will be compiled on the fly. -\verbatim +\plumedfile # load the new definition # this is a cpp file so it will be compiled LOAD FILE=Distance2.cpp @@ -84,7 +84,7 @@ d: DISTANCE ATOMS=1,10 d2: DISTANCE2 ATOMS=1,10 # print them on a file PRINT ARG=d,d2 FILE=compare-them -\endverbatim +\endplumedfile This will allow to make quick tests while developing your own variables. Of course, after your implementation is ready you might diff --git a/src/setup/MolInfo.cpp b/src/setup/MolInfo.cpp index 03a0012f97..24f2cb6892 100644 --- a/src/setup/MolInfo.cpp +++ b/src/setup/MolInfo.cpp @@ -111,23 +111,21 @@ interpret terminal residue 1. In the following example the MOLINFO command is used to provide the information on which atoms are in the backbone of a protein to the ALPHARMSD CV. -\verbatim +\plumedfile MOLINFO STRUCTURE=reference.pdb ALPHARMSD RESIDUES=all TYPE=DRMSD LESS_THAN={RATIONAL R_0=0.08 NN=8 MM=12} LABEL=a -\endverbatim -(see also \ref ALPHARMSD) +\endplumedfile The following example prints the distance corresponding to the hydrogen bonds in a GC Watson-Crick pair. -\verbatim +\plumedfile MOLINFO STRUCTURE=reference.pdb hb1: DISTANCE ATOMS=@N2-1,@O2-14 hb2: DISTANCE ATOMS=@N1-1,@N3-14 hb3: DISTANCE ATOMS=@O6-1,@N4-14 PRINT ARG=hb1,hb2,hb3 -\endverbatim -(see also \ref DISTANCE). +\endplumedfile */ diff --git a/src/setup/Restart.cpp b/src/setup/Restart.cpp index ffa4f46b1b..4cfb03ef03 100644 --- a/src/setup/Restart.cpp +++ b/src/setup/Restart.cpp @@ -51,31 +51,28 @@ and \ref PBMETAD and on some analysis action. \par Examples Using the following input: -\verbatim +\plumedfile d: DISTANCE ATOMS=1,2 PRINT ARG=d FILE=out -\endverbatim -(See also \ref DISTANCE and \ref PRINT). +\endplumedfile a new 'out' file will be created. If an old one is on the way, it will be automatically backed up. On the other hand, using the following input: -\verbatim +\plumedfile RESTART d: DISTANCE ATOMS=1,2 PRINT ARG=d FILE=out -\endverbatim +\endplumedfile the file 'out' will be appended. -(See also \ref DISTANCE and \ref PRINT). In the following case, file out1 will be backed up and file out2 will be concatenated -\verbatim +\plumedfile RESTART d1: DISTANCE ATOMS=1,2 d2: DISTANCE ATOMS=1,2 PRINT ARG=d1 FILE=out1 RESTART=NO PRINT ARG=d2 FILE=out2 -\endverbatim -(See also \ref DISTANCE and \ref PRINT). +\endplumedfile diff --git a/src/setup/Units.cpp b/src/setup/Units.cpp index 1b4225d244..617e8c0a6f 100644 --- a/src/setup/Units.cpp +++ b/src/setup/Units.cpp @@ -44,16 +44,15 @@ the units. For example, trajectories written in .gro format (with \ref DUMPATOMS are going to be always in nm. \par Examples -\verbatim +\plumedfile # this is using nm - kj/mol - fs UNITS LENGTH=nm TIME=fs -\endverbatim +\endplumedfile If a number, x, is found, the new unit is equal to x (default units) -\verbatim +\plumedfile # this is using nm - kj/mol - fs UNITS LENGTH=nm TIME=0.001 -\endverbatim - +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/vatom/COM.cpp b/src/vatom/COM.cpp index 8eb60b64d6..d0cfd0b1fe 100644 --- a/src/vatom/COM.cpp +++ b/src/vatom/COM.cpp @@ -54,13 +54,12 @@ periodic image. The following input instructs plumed to print the distance between the center of mass for atoms 1,2,3,4,5,6,7 and that for atoms 15,20: -\verbatim +\plumedfile c1: COM ATOMS=1-7 c2: COM ATOMS=15,20 d1: DISTANCE ATOMS=c1,c2 PRINT ARG=d1 -\endverbatim -(See also \ref DISTANCE and \ref PRINT). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/vatom/Center.cpp b/src/vatom/Center.cpp index 7e4cdd4402..64eea7d741 100644 --- a/src/vatom/Center.cpp +++ b/src/vatom/Center.cpp @@ -54,7 +54,7 @@ periodic image. \par Examples -\verbatim +\plumedfile # a point which is on the line connecting atoms 1 and 10, so that its distance # from 10 is twice its distance from 1: c1: CENTER ATOMS=1,1,10 @@ -67,8 +67,7 @@ c2: CENTER ATOMS=2,3,4,5 MASS d1: DISTANCE ATOMS=c1,c2 PRINT ARG=d1 -\endverbatim -(See also \ref DISTANCE, \ref COM and \ref PRINT). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/src/vatom/FixedAtom.cpp b/src/vatom/FixedAtom.cpp index ccf7eb52ca..3baf40379a 100644 --- a/src/vatom/FixedAtom.cpp +++ b/src/vatom/FixedAtom.cpp @@ -51,24 +51,22 @@ then it is safe to add further fixed atoms without breaking translational invari The following input instructs plumed to compute the angle between distance of atoms 15 and 20 and the z axis and keeping it close to zero. -\verbatim +\plumedfile a: FIXEDATOM AT=0,0,0 b: FIXEDATOM AT=0,0,1 an: ANGLE ATOMS=a,b,15,20 RESTRAINT ARG=an AT=0.0 KAPPA=100.0 -\endverbatim -(See also \ref ANGLE and \ref RESTRAINT). +\endplumedfile The following input instructs plumed to align a protein on a template and then compute the distance of one of its atom from the point (10,20,30). -\verbatim +\plumedfile FIT_TO_TEMPLATE STRIDE=1 REFERENCE=ref.pdb TYPE=SIMPLE a: FIXEDATOM AT=10,20,30 d: DISTANCE ARG=a,20 PRINT ARG=d FILE=colvar -\endverbatim -(See also \ref FIT_TO_TEMPLATE and \ref DISTANCE). +\endplumedfile */ diff --git a/src/vatom/Ghost.cpp b/src/vatom/Ghost.cpp index b2c7837172..7c57cee4ff 100644 --- a/src/vatom/Ghost.cpp +++ b/src/vatom/Ghost.cpp @@ -39,13 +39,12 @@ an atom list through the the label for the GHOST action that creates it. \par Examples The following input instructs plumed to print the distance between the ghost atom and the center of mass for atoms 15,20: -\verbatim +\plumedfile c1: GHOST ATOMS=1,5,10 COORDINATES=10.0,10.0,10.0 c2: COM ATOMS=15,20 d1: DISTANCE ATOMS=c1,c2 PRINT ARG=d1 -\endverbatim -(See also \ref DISTANCE and \ref PRINT). +\endplumedfile */ //+ENDPLUMEDOC diff --git a/user-doc/Analysis.txt b/user-doc/Analysis.txt index a5a0e55729..ef3a005893 100644 --- a/user-doc/Analysis.txt +++ b/user-doc/Analysis.txt @@ -45,11 +45,11 @@ As an example the following set of commands instructs PLUMED to calculate the di atoms 1 and 2 for every 5th frame in the trajectory and to accumulate a histogram from this data which will be output every 100 steps (i.e. when 20 distances have been added to the histogram). -\verbatim +\plumedfile x: DISTANCE ATOMS=1,2 h: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 STRIDE=5 DUMPGRID GRID=h FILE=histo STRIDE=100 -\endverbatim +\endplumedfile It is important to note when using commands such as the above the first frame in the trajectory is assumed to be the initial configuration that was input to the MD code. It is thus ignored. Furthermore, if you are @@ -57,11 +57,11 @@ running with driver and you would like to analyse the whole trajectory (without and then print the result you simply call \ref DUMPGRID (or any of the commands above) without a STRIDE keyword as shown in the example below. -\verbatim +\plumedfile x: DISTANCE ATOMS=1,2 h: HISTOGRAM ARG=x GRID_MIN=0.0 GRID_MAX=3.0 GRID_BIN=100 BANDWIDTH=0.1 STRIDE=5 DUMPGRID GRID=h FILE=histo -\endverbatim +\endplumedfile Please note that even with this calculation the first frame in the trajectory is ignored when computing the histogram. diff --git a/user-doc/Colvar.txt b/user-doc/Colvar.txt index 7c6557796d..e3e20d2a1b 100644 --- a/user-doc/Colvar.txt +++ b/user-doc/Colvar.txt @@ -92,9 +92,9 @@ Oftentimes the simplest way to specify the atoms involved is to use multiple ins i.e. ATOMS1, ATOMS2, ATOMS3,... Separate instances of the quantity specified by NAME are then calculated for each of the sets of atoms. For example if the command issued contains the following: -\verbatim +\plumedfile DISTANCES ATOMS1=1,2 ATOMS2=3,4 ATOMS3=5,6 -\endverbatim +\endplumedfile The distances between atoms 1 and 2, atoms 3 and 4, and atoms 5 and 6 are calculated. Obviously, generating this sort of input is rather tedious so short cuts are also available many of the collective variables. @@ -163,11 +163,11 @@ prevent the cluster subliming. Alternatively, you may wish to insist that a par coordination number greater than 2. You can add these sorts of restraints by employing the following biases, which all act on the set of collective variable values calculated by a multicolvar. So for example the following set of commands: -\verbatim +\plumedfile COM ATOMS=1-20 LABEL=c1 DISTANCES GROUPA=c1 GROUPB=1-20 LABEL=d1 UWALLS DATA=d1 AT=2.5 KAPPA=0.2 LABEL=sr -\endverbatim +\endplumedfile creates the aforementioned set of restraints on the distances between the 20 atoms in a cluster and the center of mass of the cluster. diff --git a/user-doc/Files.txt b/user-doc/Files.txt index f360af5d28..2ed8f21ee8 100644 --- a/user-doc/Files.txt +++ b/user-doc/Files.txt @@ -34,11 +34,10 @@ since your disk might fill up quickly with this setting. When running with multiple replicas (e.g., with GROMACS, -multi option) PLUMED adds the replica index as a suffix to all the files. The following command will thus print files named COLVAR.0, COLVAR.1, etc for the different replicas. -\verbatim +\plumedfile d: DISTANCE ATOMS=1,2 PRINT ARG=d FILE=COLVAR -\endverbatim -(see also \ref DISTANCE and \ref PRINT). +\endplumedfile When reading a file, PLUMED will try to add the suffix. If the file is not found, it will fall back to the name without suffix. The most important case is the reading of the plumed input file. @@ -51,12 +50,11 @@ extension. Before PLUMED 2.2, the only recognized suffix was ".gz". Since 2.2, a less or equal to five letters is recognized. This means that using in a multireplica context an input such as -\verbatim +\plumedfile d: DISTANCE ATOMS=1,2 PRINT ARG=d FILE=COLVAR.gz METAD ARG=d FILE=test.HILLS SIGMA=0.1 HEIGHT=0.1 -\endverbatim -(see \ref DISTANCE, \ref PRINT, and \ref METAD) +\endplumedfile PLUMED will write files named COLVAR.0.gz, COLVAR.1.gz, test.0.HILLS, test.1.HILLS, etc etc. This is useful since the preserved extension makes it easy to process the files later. diff --git a/user-doc/Functions.txt b/user-doc/Functions.txt index 8bf37c42db..53de40f365 100644 --- a/user-doc/Functions.txt +++ b/user-doc/Functions.txt @@ -23,7 +23,7 @@ is the smallest value and `B` is the largest value. In case the answer is that t values at the discontinuity are not always the same, then you cannot construct a variable that can be biased with PLUMED. Consider the following examples: -\verbatim +\plumedfile t: TORSION ATOMS=1,2,3,4 # When atoms are moved, t could jump suddenly from -pi to +pi @@ -39,7 +39,7 @@ d: DISTANCE ATOMS=1,10 COMPONENTS # make a new variable equal to d.z but with the correct periodicity dz: COMBINE ARG=d.z PERIODIC=-10,10 # here we assumed the system is in a orthorhombic box with z side = 20 -\endverbatim +\endplumedfile @FUNCTION@ diff --git a/user-doc/Group.txt b/user-doc/Group.txt index 6365d9f7dd..6edc0225b5 100644 --- a/user-doc/Group.txt +++ b/user-doc/Group.txt @@ -56,12 +56,12 @@ See http://en.wikipedia.org/wiki/Ramachandran_plot The following example shows how to use \ref MOLINFO with \ref TORSION to calculate the torsion angles phi and psi for the first and fourth residue of the protein: -\verbatim +\plumedfile MOLINFO MOLTYPE=protein STRUCTURE=myprotein.pdb t1: TORSION ATOMS=@phi-3 t2: TORSION ATOMS=@psi-4 PRINT ARG=t1,t2 FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile \subsection pbc Broken Molecules and PBC @@ -76,11 +76,11 @@ using the ALIGN_ATOMS keyword. In PLUMED 2 the same effect can be achieved usin The following input computes the end-to-end distance for a polymer of 100 atoms and keeps it at a value around 5. -\verbatim +\plumedfile WHOLEMOLECULES ENTITY0=1-100 e2e: DISTANCE ATOMS=1,100 NOPBC RESTRAINT ARG=e2e KAPPA=1 AT=5 -\endverbatim +\endplumedfile Notice that NOPBC is used to be sure in \ref DISTANCE that if the end-to-end distance is larger than half the simulation box the distance is compute properly. Also notice that, since many MD codes break molecules across cell boundary, it might be necessary to use the @@ -90,12 +90,12 @@ Notice that most expressions are invariant with respect to a change in the order but some of them depend on that order. E.g., with \ref WHOLEMOLECULES it could be useful to specify atom lists in a reversed order. -\verbatim +\plumedfile # to see the effect, one could dump the atoms as they were before molecule reconstruction: # DUMPATOMS FILE=dump-broken.xyz ATOMS=1-20 WHOLEMOLECULES STRIDE=1 ENTITY0=1-20 DUMPATOMS FILE=dump.xyz ATOMS=1-20 -\endverbatim +\endplumedfile Notice that there are other ways to manipulate the coordinates stored within PLUMED: - Using the \subpage FIT_TO_TEMPLATE they can be aligned to a template structure. @@ -116,10 +116,10 @@ To specify to a colvar that you want to use the position of a virtual atom to ca in your system you simply use the label for your virtual atom in place of the usual numerical index. Virtual atoms and normal atoms can be mixed together in the input to colvars as shown below: -\verbatim +\plumedfile COM ATOMS=1,10 LABEL=com1 DISTANCE ATOMS=11,com1 -\endverbatim +\endplumedfile If you don't want to calculate CVs from the virtual atom. That is to say you just want to monitor the position of a virtual atom (or any set of atoms) over the course of your trajectory you can do this using \ref DUMPATOMS. diff --git a/user-doc/Misc.txt b/user-doc/Misc.txt index 284a2a6e9b..4fceb133df 100644 --- a/user-doc/Misc.txt +++ b/user-doc/Misc.txt @@ -19,12 +19,12 @@ particular simulation you might find it useful to put comments in your input fil comments can be added using a # sign. On any given line everything after the # sign is ignored so erm... yes add lines of comments or trailing comments to your hearts content as shown below (using Shakespeare is optional): -\verbatim +\plumedfile # This is the distance between two atoms: DISTANCE ATOM=1,2 LABEL=d1 UPPER_WALLS ARG=d1 AT=3.0 KAPPA=3.0 LABEL=Snout # In this same interlude it doth befall. # That I, one Snout by name, present a wall. -\endverbatim +\endplumedfile (see \ref DISTANCE and \ref UPPER_WALLS) An alternative to including comments in this way is to use line starting ENDPLUMED. Everything in the PLUMED input after this @@ -37,14 +37,14 @@ We at PLUMED are aware of this fact and thus have provided a way of doing line c easier - aren't we kind? Well no not really, we have to use this code too. Anyway, you can do continuations by using the "..." syntax as this makes this: -\verbatim +\plumedfile DISTANCES ATOMS1=1,300 ATOMS2=1,400 ATOMS3=1,500 LABEL=dist -\endverbatim +\endplumedfile (see \ref DISTANCES) equivalent to this: -\verbatim +\plumedfile DISTANCES ... LABEL=dist # we can also insert comments here @@ -54,11 +54,11 @@ DISTANCES ... #empty lines are also allowed ... DISTANCES -\endverbatim +\endplumedfile Notice that the closing `...` is followed by the word `DISTANCES`. This is optional, but might be useful to find more easily which is the matching start of the statement. The following is equally correct -\verbatim +\plumedfile DISTANCES ... LABEL=dist # we can also insert comments here @@ -68,12 +68,12 @@ DISTANCES ... #empty lines are also allowed ... -\endverbatim +\endplumedfile Notice that PLUMED makes a check that the word following the closing `...` is actually identical to the first word in the line with the first `...`. If not, it will throw an error. Also notice that you might put more than one word in the first line. E.g. -\verbatim +\plumedfile DISTANCES LABEL=dist ... # we can also insert comments here ATOMS1=1,300 @@ -81,9 +81,9 @@ DISTANCES LABEL=dist ... ATOMS2=1,400 ATOMS3=1,500 #empty lines are also allowed ... -\endverbatim +\endplumedfile or, equivalently, -\verbatim +\plumedfile dist: DISTANCES ... # we can also insert comments here ATOMS1=1,300 @@ -91,7 +91,7 @@ dist: DISTANCES ... ATOMS2=1,400 ATOMS3=1,500 #empty lines are also allowed ... -\endverbatim +\endplumedfile \page VimSyntax Using VIM syntax file @@ -171,11 +171,11 @@ Add to your `.vimrc` file the following commands :set modelines=5 \endverbatim Then, at the beginning of your PLUMED input file, put the following comment: -\verbatim +\plumedfile # vim:ft=plumed d: DISTANCE ATOMS=1,2 RESTRAINT ARG=d AT=0.0 KAPPA=1.0 -\endverbatim +\endplumedfile Now, every time you open this file, you will see it highlighted. \par Syntax highlighting @@ -220,27 +220,27 @@ Folded lines can be expanded with `zo` and folded with `zc`. Look at VIM documen learn more. In case you want to use this feature, we suggest you to put both label and action type on the first line of multi-line statements. E.g. -\verbatim +\plumedfile m: METAD ... ARG=d HEIGHT=1.0 SIGMA=0.5 PACE=100 ... -\endverbatim +\endplumedfile will be folded to \verbatim +-- 6 lines: m: METAD ...------------------------------------------------------ \endverbatim and -\verbatim +\plumedfile METAD LABEL=m ... ARG=d HEIGHT=1.0 SIGMA=0.5 PACE=100 ... -\endverbatim +\endplumedfile will be folded to \verbatim +-- 6 lines: METAD LABEL=m ...------------------------------------------------- @@ -293,9 +293,9 @@ Try to do the following. Enable plumed syntax: :set ft=plumed \endverbatim Then add the following line -\verbatim +\plumedfile DISTANCE -\endverbatim +\endplumedfile Now, in normal mode, go with the cursor on the `DISTANCE` line and type \verbatim :PHelp @@ -365,38 +365,37 @@ vimrc file. If, for some reason, you want to spread your PLUMED input over a number of files you can use \subpage INCLUDE as shown below: -\verbatim +\plumedfile INCLUDE FILE=filename -\endverbatim +\endplumedfile So, for example, a single "plumed.dat" file: -\verbatim +\plumedfile DISTANCE ATOMS=0,1 LABEL=dist RESTRAINT ARG=dist -\endverbatim -(see \ref DISTANCE and \ref RESTRAINT) +\endplumedfile could be split up into two files as shown below: -\verbatim +\plumedfile DISTANCE ATOMS=0,1 LABEL=dist INCLUDE FILE=toBeIncluded.dat -\endverbatim +\endplumedfile plus a "toBeIncluded.dat" file -\verbatim +\plumedfile RESTRAINT ARG=dist -\endverbatim +\endplumedfile However, when you do this it is important to recognise that \ref INCLUDE is a real directive that is only resolved after all the \ref comments have been stripped and the \ref ContinuationLines have been unrolled. This means it is not possible to do things like: -\verbatim +\plumedfile # this is wrong: DISTANCE INCLUDE FILE=options.dat RESTRAINT ARG=dist -\endverbatim +\endplumedfile \page load Loading shared libraries @@ -405,9 +404,9 @@ PLUMED libraries. Alternatively, if you want to keep your code independent from so you can release it independely - we won't be offended), then you can create your own dynamic library. To use this in conjuction with PLUMED you can then load it at runtime by using the \subpage LOAD keyword as shown below: -\verbatim +\plumedfile LOAD FILE=library.so -\endverbatim +\endplumedfile N.B. If your system uses a different suffix for dynamic libraries (e.g. macs use .dylib) then PLUMED will try to automatically adjust the suffix accordingly. diff --git a/user-doc/Performances.txt b/user-doc/Performances.txt index 57bc2c66a5..00fc973acc 100644 --- a/user-doc/Performances.txt +++ b/user-doc/Performances.txt @@ -105,12 +105,12 @@ a factor equal to STRIDE. This technique can allow your simulation to run faster if you need the apply a bias potential on some very expensive collective variable. Consider the following input: -\verbatim +\plumedfile c1: COM ATOMS=1-1000 c2: COM ATOMS=1001-2000 d: DISTANCE ATOMS=c1,c2 METAD ARG=d HEIGHT=1 SIGMA=0.1 BIASFACTOR=5 PACE=500 -\endverbatim +\endplumedfile This performs a \ref METAD simulation biasing the distance between two centers of mass. Since computing these centers requires a lot of atoms to be imported from the MD engine, it could slow down significantly the @@ -118,12 +118,12 @@ simulation. Notice that whereas the bias is changed every PACE=500 steps, it is applied every STRIDE step, where STRIDE=1 by default. The following input could lead to a significantly faster simulation at the price of a negligible systematic error -\verbatim +\plumedfile c1: COM ATOMS=1-1000 c2: COM ATOMS=1001-2000 d: DISTANCE ATOMS=c1,c2 METAD ARG=d HEIGHT=1 SIGMA=0.1 BIASFACTOR=5 PACE=500 STRIDE=2 -\endverbatim +\endplumedfile Similarly, the STRIDE keyword can be used with other biases (e.g. \ref RESTRAINT). The technique is discussed in details here \cite Ferrarotti2015. @@ -133,9 +133,9 @@ See also \subpage EFFECTIVE_ENERGY_DRIFT. Whenever you have a multicolvar action such as: -\verbatim +\plumedfile COORDINATIONNUMBER SPECIES=1-100 SWITCH={RATIONAL R_0=1. D_MAX=3.0} MORE_THAN={RATIONAL R_0=6.0 NN=6 MM=12 D_0=0} -\endverbatim +\endplumedfile You will get a collosal speedup by specifying the D_MAX keyword in all switching functions that act on distances. D_MAX tells PLUMED that the switching function is strictly zero if the distance is greater than this value. As a result diff --git a/user-doc/Regex.txt b/user-doc/Regex.txt index b24524a0f8..93561f6322 100644 --- a/user-doc/Regex.txt +++ b/user-doc/Regex.txt @@ -14,14 +14,14 @@ Regular expressions are enclosed in round braces and must not contain spaces (th names have no spaces indeed, so why use them?). As an example then command -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,2 COMPONENTS PRINT ARG=(d1\.[xy]) STRIDE=100 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile will cause both the d1.x and d1.y components of the DISTANCE action to be printed out in the order that they are created by plumed. The "." character must be escaped in order to interpret it as a literal ".". An unescaped dot is a wildcard which is matched by any character, So as an example -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,2 COMPONENTS dxy: DISTANCE ATOMS=1,3 @@ -30,26 +30,26 @@ PRINT ARG=(d1.[xy]) STRIDE=100 FILE=colvar FMT=%8.4f # while this will match d1.x,d1.y only PRINT ARG=(d1\.[xy]) STRIDE=100 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile You can include more than one regular expression by using comma separated regular expressions -\verbatim +\plumedfile t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 d1: DISTANCE ATOMS=7,17 COMPONENTS PRINT ARG=(d1\.[xy]),(t[0-9]) STRIDE=100 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile (this selects t1,t2,d1.x and d2.x) Be aware that if you have overlapping selection they will be duplicated so it a better alternative is to use the "or" operator "|". -\verbatim +\plumedfile t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 d1: DISTANCE ATOMS=7,17 COMPONENTS PRINT ARG=(d1\.[xy]|t[0-9]) STRIDE=100 FILE=colvar FMT=%8.4f -\endverbatim +\endplumedfile this selects the same set of arguments as the previous example. diff --git a/user-doc/Syntax.txt b/user-doc/Syntax.txt index 47c73c1f2f..277d339e9e 100644 --- a/user-doc/Syntax.txt +++ b/user-doc/Syntax.txt @@ -25,18 +25,16 @@ is enclosed in curly braces (e.g. ATOMS={1 2 3 4}). Please note that you can sp The most important of these keywords is the label keyword as it is only by using these labels that we can pass data from one action to another. As an example if you do: -\verbatim +\plumedfile DISTANCE ATOMS=1,2 -\endverbatim -(see \ref DISTANCE) +\endplumedfile Then PLUMED will do nothing other than read in your input file. In contrast if you do: -\verbatim +\plumedfile DISTANCE ATOMS=1,2 LABEL=d1 PRINT ARG=d1 FILE=colvar STRIDE=10 -\endverbatim -(see \ref PRINT) +\endplumedfile then PLUMED will print out the value of the distance between atoms 1 and 2 every 10 steps to the file colvar as you have told PLUMED to take the value calculated by the action d1 and to print it. You can use any character string to label your actions @@ -46,10 +44,10 @@ code-generated groups of atoms and to give labels to any Actions for which the u Notice that if a word followed by a column is added at the beginning of the line (e.g. pippo:), PLUMED automatically removes it and adds an equivalent label (LABEL=pippo). Thus, a completely equivalent result can be obtained with the following shortcut: -\verbatim +\plumedfile d1: DISTANCE ATOMS=1,2 PRINT ARG=d1 FILE=colvar STRIDE=10 -\endverbatim +\endplumedfile Also notice that all the actions can be labeled, and that many actions besides normal collective variables can define one or more value, which can be then referred using the corresponding label. From c840343f5371e151b8f34d154a826da4a749b1d1 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Mon, 24 Apr 2017 14:42:10 +0200 Subject: [PATCH 20/62] Some clarification in doc --- src/colvar/Coordination.cpp | 15 +++++++++++---- src/generic/DumpAtoms.cpp | 27 ++++++++++++++++++++++++++ src/generic/Group.cpp | 38 +++++++++++++++++++------------------ src/setup/Restart.cpp | 10 ++++++++++ src/setup/Units.cpp | 29 ++++++++++++++++++++++++---- 5 files changed, 93 insertions(+), 26 deletions(-) diff --git a/src/colvar/Coordination.cpp b/src/colvar/Coordination.cpp index fe0a8b08d3..cf96455589 100644 --- a/src/colvar/Coordination.cpp +++ b/src/colvar/Coordination.cpp @@ -74,13 +74,20 @@ c: COORDINATION GROUPA=1 GROUPB=1 R_0=0.3 PRINT ARG=c STRIDE=10 \endplumedfile +Here's an example that shows what happens when providing COORDINATION with +a single group: \plumedfile -c1: COORDINATION GROUPA=1-10 GROUPB=1-10 R_0=0.3 -x: COORDINATION GROUPA=1-10 R_0=0.3 +# define some huge group: +group: GROUP ATOMS=1-1000 +# Here's coordination of a group against itself: +c1: COORDINATION GROUPA=group GROUPB=group R_0=0.3 +# Here's coordination within a single group: +x: COORDINATION GROUPA=group R_0=0.3 +# This is just multiplying times 2 the variable x: c2: COMBINE ARG=x COEFFICIENTS=2 + # the two variables c1 and c2 should be identical, but the calculation of c2 is twice faster -# since it runs on half of the pairs. Notice that to get the same result you -# should double it +# since it runs on half of the pairs. PRINT ARG=c1,c2 STRIDE=10 \endplumedfile diff --git a/src/generic/DumpAtoms.cpp b/src/generic/DumpAtoms.cpp index c144b5f078..5e613cf9a9 100644 --- a/src/generic/DumpAtoms.cpp +++ b/src/generic/DumpAtoms.cpp @@ -74,6 +74,15 @@ The following input instructs plumed to print out the positions of atoms COM ATOMS=11-20 LABEL=c1 DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1 \endplumedfile +Notice that the coordinates in the xyz file will be expressed in nm, since these +are the defaults units in PLUMED. If you want the xyz file to be expressed in A, you should use the +following input +\plumedfile +COM ATOMS=11-20 LABEL=c1 +DUMPATOMS STRIDE=10 FILE=file.xyz ATOMS=1-10,c1 UNITS=A +\endplumedfile +As an alternative, you might want to set all the lentght used by PLUMED to Angstrom using the \ref UNITS +action. However, this latter choice will affect all your input and output. The following input is very similar but dumps a .gro (gromacs) file, which also contains atom and residue names. @@ -88,6 +97,24 @@ DUMPATOMS STRIDE=10 FILE=file.gro ATOMS=1-10,c1 # a correct name in the resulting gro file \endplumedfile +The `file.gro` will contain coordinates expressed in nm, since this is the convention for gro files. + +In case you have compiled PLUMED with `xdrfile` library, you might even write xtc or trr files as follows +\plumedfile +COM ATOMS=11-20 LABEL=c1 +DUMPATOMS STRIDE=10 FILE=file.xtc ATOMS=1-10,c1 +\endplumedfile +Notice that xtc files are significantly smaller than gro and xyz files. + +Finally, consider that gro and xtc file store coordinates with limited precision set by the +`PRECISION` keyword. Default value is 3, which means "3 digits after dot" in nm (1/1000 of a nm). +The following will write a larger xtc file with high resolution coordinates: +\plumedfile +COM ATOMS=11-20 LABEL=c1 +DUMPATOMS STRIDE=10 FILE=file.xtc ATOMS=1-10,c1 PRECISION=7 +\endplumedfile + + */ //+ENDPLUMEDOC diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index 0f04cf75fd..234a01c282 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -39,21 +39,21 @@ namespace generic { Define a group of atoms so that a particular list of atoms can be referenced with a single label in definitions of CVs or virtual atoms. -Atoms can be listed as comma separated numbers (i.e. 1,2,3,10,45,7,9,..) , simple positive ranges -(i.e. 20-40), ranges with a stride either positive or negative (i.e. 20-40:2 or 80-50:-2) or as -combinations of all the former methods (1,2,4,5,10-20,21-40:2,80-50:-2). +Atoms can be listed as comma separated numbers (i.e. `1,2,3,10,45,7,9`) , simple positive ranges +(i.e. `20-40`), ranges with a stride either positive or negative (i.e. `20-40:2` or `80-50:-2`) or as +comma separated combinations of all the former methods (`1,2,4,5,10-20,21-40:2,80-50:-2`). -Moreover, lists can be imported from ndx files (GROMACS format). Use NDX_FILE to set the name of -the index file and NDX_GROUP to set the name of the group to be imported (default is first one). +Moreover, lists can be imported from ndx files (GROMACS format). Use `NDX_FILE` to set the name of +the index file and `NDX_GROUP` to set the name of the group to be imported (default is first one). -It is also possible to remove atoms from a list and or sort them using keywords REMOVE, SORT, and UNIQUE. +It is also possible to remove atoms from a list and or sort them using keywords `REMOVE`, `SORT`, and `UNIQUE`. The flow is the following: -- If ATOMS is present take the ordered list of atoms from the ATOMS keyword. -- If NDX_FILE is present append the list from the the gromacs group. -- If REMOVE is present remove the first occurence of each of these atoms from the list. +- If `ATOMS` is present take the ordered list of atoms from the `ATOMS` keyword. +- If `NDX_FILE` is present append the list from the the gromacs group. +- If `REMOVE` is present remove the first occurence of each of these atoms from the list. If one tries to remove an atom that was not listed plumed adds a notice in the output. -- If SORT is present resulting list is sorted. -- If UNIQUE is present the resuling list is sorted and duplicate elements are removed. +- If `SORT` is present resulting list is sorted. +- If `UNIQUE` is present the resuling list is sorted and duplicate elements are removed. Notice that this command just creates a shortcut, and does not imply any real calculation. So, having a huge group defined does not slow down your calculation in any way. @@ -63,8 +63,8 @@ the \ref INCLUDE command so as to store long group definitions in a separate fil \par Examples -This command create a group of atoms containing atoms 1,4,7,11 and 14 (labeled 'o'), and another containing -atoms 2,3,5,6,8,9,12,13 (labeled 'h'): +This command create a group of atoms containing atoms 1, 4, 7, 11 and 14 (labeled 'o'), and another containing +atoms 2, 3, 5, 6, 8, 9, 12, and 13 (labeled 'h'): \plumedfile o: GROUP ATOMS=1,4,7,11,14 h: GROUP ATOMS=2,3,5,6,8,9,12,13 @@ -78,7 +78,7 @@ PRINT ARG=c FILE=colvar \endplumedfile Groups can be conveniently stored in a separate file. -E.g. one could create a file named 'groups.dat' which reads +E.g. one could create a file named `groups.dat` which reads \plumedfile o: GROUP ATOMS=1,4,7,11,14 h: GROUP ATOMS=2,3,5,6,8,9,12,13 @@ -91,7 +91,7 @@ c: COORDINATION GROUPA=o GROUPB=h R_0=0.3 # print the coordination on file 'colvar' PRINT ARG=c FILE=colvar \endplumedfile -The groups.dat file could be very long and include lists of thousand atoms without cluttering the main plumed.dat file. +The `groups.dat` file could be very long and include lists of thousand atoms without cluttering the main plumed.dat file. A GROMACS index file can also be imported \plumedfile @@ -101,11 +101,13 @@ pro: GROUP NDX_FILE=index.ndx NDX_GROUP=protein DUMPATOMS ATOMS=pro FILE=traj.gro \endplumedfile -A list can be edited with REMOVE +A list can be edited with `REMOVE`. For instance, if you +are using a water model with three atoms per molecule, you can +easily construct the list of hydrogens in this manner \plumedfile -# take one atom every three +# take one atom every three, that is oxygens ox: GROUP ATOMS=1-90:3 -# take the remaining atoms +# take the remaining atoms, that is hydrogens hy: GROUP ATOMS=1-90 REMOVE=ox DUMPATOMS ATOMS=ox FILE=ox.gro DUMPATOMS ATOMS=hy FILE=hy.gro diff --git a/src/setup/Restart.cpp b/src/setup/Restart.cpp index 4cfb03ef03..c33bbe1a4f 100644 --- a/src/setup/Restart.cpp +++ b/src/setup/Restart.cpp @@ -74,6 +74,16 @@ PRINT ARG=d1 FILE=out1 RESTART=NO PRINT ARG=d2 FILE=out2 \endplumedfile +In the following case, file out will backed up even if the MD code thinks that we +are restarting. Notice that not all the MD code send to PLUMED information about restarts. +If you are not sure, always put `RESTART` when you are restarting and nothing when you aren't +\plumedfile +RESTART NO +d1: DISTANCE ATOMS=1,2 +PRINT ARG=d1 FILE=out1 +\endplumedfile + + diff --git a/src/setup/Units.cpp b/src/setup/Units.cpp index 617e8c0a6f..edd45fe4f9 100644 --- a/src/setup/Units.cpp +++ b/src/setup/Units.cpp @@ -44,14 +44,35 @@ the units. For example, trajectories written in .gro format (with \ref DUMPATOMS are going to be always in nm. \par Examples + + \plumedfile # this is using nm - kj/mol - fs -UNITS LENGTH=nm TIME=fs +UNITS LENGTH=A TIME=fs + +# compute distance between atoms 1 and 4 +d: DISTANCE ATOMS=1,4 + +# print time and distance on a COLVAR file +PRINT ARG=d FILE=COLVAR + +# dump atoms 1 to 100 on a 'out.gro' file +DUMPATOMS FILE=out.gro STRIDE=10 ATOMS=1-100 + +# dump atoms 1 to 100 on a 'out.xyz' file +DUMPATOMS FILE=out.xyz STRIDE=10 ATOMS=1-100 \endplumedfile -If a number, x, is found, the new unit is equal to x (default units) + +In the `COLVAR` file, time and distance will appear in fs and A respectively, *irrespectively* of which units +you are using the the host MD code. The coordinates in the `out.gro` file will be expressed in nm, +since `gro` files are by convention written in nm. The coordinates in the `out.xyz` file +will be written in Angstrom *since we used the UNITS command setting Angstrom units*. +Indeed, within PLUMED xyz files are using internal PLUMED units and not necessarily Angstrom! + +If a number, x, is found instead of a string, the new unit is equal to x times the default units. +Using the following command as first line of the previous example would have lead to an identical result: \plumedfile -# this is using nm - kj/mol - fs -UNITS LENGTH=nm TIME=0.001 +UNITS LENGTH=0.1 TIME=0.001 \endplumedfile */ From 3f20f6b465bf1555fe7b12c117672693ca3e7767 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Wed, 26 Apr 2017 16:33:25 +0200 Subject: [PATCH 21/62] changelog [makedoc] --- CHANGES/v2.4.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES/v2.4.txt b/CHANGES/v2.4.txt index 1e476f4896..a7d60ac3d0 100644 --- a/CHANGES/v2.4.txt +++ b/CHANGES/v2.4.txt @@ -29,6 +29,7 @@ Changes from version 2.3 which are relevant for users: - \ref METAD : BIASFACTOR=1 is allowed and performs unbiased sampling. HILLS file can be used to recover free energy also in this case. - Internal molfile implementation has been updated to VMD 1.9.3. + - Examples in the documentation now have syntax highlighting and links to the documentation of used actions. Changes from version 2.3 which are relevant for developers: - A few fixes has been made to improve exception safety. Although we still cannot declare From efdf1daaac011d5d7d38925055dad663f53ccc19 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 10:37:39 +0200 Subject: [PATCH 22/62] Comments on PDB format [makedoc] --- src/colvar/RMSD.cpp | 1 + src/generic/FitToTemplate.cpp | 5 ++- src/setup/MolInfo.cpp | 4 +- src/tools/PDB.cpp | 70 +++++++++++++++++++++++++++++++++++ user-doc/Colvar.txt | 2 + 5 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/colvar/RMSD.cpp b/src/colvar/RMSD.cpp index 8801dfeed2..bca340c78f 100644 --- a/src/colvar/RMSD.cpp +++ b/src/colvar/RMSD.cpp @@ -105,6 +105,7 @@ you really know what you are doing however as the results can be rather strange. In PDB files the atomic coordinates and box lengths should be in Angstroms unless you are working with natural units. If you are working with natural units then the coordinates should be in your natural length unit. For more details on the PDB file format visit http://www.wwpdb.org/docs.html. +Make sure your PDB file is correclty formatted as explained \ref pdbreader "in this page". A different method is used to calculate the RMSD distance when you use TYPE=OPTIMAL on the input line. In this case the root mean square deviation is calculated after the positions of geometric centers in the reference and instantaneous configurations are aligned AND after diff --git a/src/generic/FitToTemplate.cpp b/src/generic/FitToTemplate.cpp index 37e38333f6..106a2bb140 100644 --- a/src/generic/FitToTemplate.cpp +++ b/src/generic/FitToTemplate.cpp @@ -48,8 +48,9 @@ namespace generic { This action is used to align a molecule to a template. This can be used to move the coordinates stored in plumed -so as to be aligned with a provided template in pdb format. Pdb should contain -also weights for alignment (see the format of pdb files used e.g. for \ref RMSD). +so as to be aligned with a provided template in PDB format. Pdb should contain +also weights for alignment (see the format of PDB files used e.g. for \ref RMSD). +Make sure your PDB file is correclty formatted as explained \ref pdbreader "in this page". Weights for displacement are ignored, since no displacement is computed here. Notice that all atoms (not only those in the template) are aligned. To see what effect try diff --git a/src/setup/MolInfo.cpp b/src/setup/MolInfo.cpp index 03a0012f97..33f0cffb26 100644 --- a/src/setup/MolInfo.cpp +++ b/src/setup/MolInfo.cpp @@ -37,12 +37,14 @@ then use this information in later commands to specify atom lists in terms resid using this command you can find the backbone atoms in your structure automatically. \warning -Please be aware that the pdb parser in plumed is far from perfect. You should thus check the log file +Please be aware that the PDB parser in plumed is far from perfect. You should thus check the log file and examine what plumed is actually doing whenenver you use the MOLINFO action. Also make sure that the atoms are listed in the pdb with the correct order. If you are using gromacs, the safest way is to use reference pdb file generated with `gmx editconf -f topol.tpr -o reference.pdb`. +More information of the PDB parser implemented in PLUMED can be found \ref pdbreader "at this page". + Using MOLINFO with a protein's or nucleic acid's pdb extends the possibility of atoms selection using the @ special symbol. diff --git a/src/tools/PDB.cpp b/src/tools/PDB.cpp index 97f48e8e21..5aa30f4360 100644 --- a/src/tools/PDB.cpp +++ b/src/tools/PDB.cpp @@ -26,6 +26,76 @@ using namespace std; +//+PLUMEDOC INTERNAL pdbreader +/* + +PLUMED use PDB formats in several places, including +- To read molecular structure (\ref MOLINFO). +- To read reference conformations (\ref RMSD, but also many other methods in \ref dists, \ref FIT_TO_TEMPLATE, etc). + +The implemented PDB reader expects a file formatted correctly according to the +[PDB standard](http://www.wwpdb.org/documentation/file-format-content/format33/v3.3.html). +In particular, the following columns are read from ATOM records +\verbatim +columns | content +1-6 | record name (ATOM or HETATM) +7-11 | serial number of the atom (starting from 1) +13-16 | atom name +18-20 | residue name +22 | chain id +23-26 | residue number +31-38 | x coordinate +39-46 | y coordinate +47-54 | z coordinate +55-60 | occupancy +61-66 | beta factor +\endverbatim +PLUMED parser is slightly more permissive than the official PDB format +in the fact that the format of real numbers is not fixed. In other words, +any parsable real number is ok and the dot can be placed anywhere. However, +__columns are interpret strictly__. A sample PDB should look like the following +\verbatim +ATOM 2 CH3 ACE 1 12.932 -14.718 -6.016 1.00 1.00 +ATOM 5 C ACE 1 21.312 -9.928 -5.946 1.00 1.00 +ATOM 9 CA ALA 2 19.462 -11.088 -8.986 1.00 1.00 +\endverbatim + +Notice that serial numbers need not to be consecutive. In the three-line example above, +only the coordinates of three atoms are provided. This is perfectly legal and indicates PLUMED +that information about these atoms only is available. This could be both for structural +information in \ref MOLINFO, where the other atoms would have no name assigned, and for +reference structures used in \ref RMSD, where only the provided atoms would be used to compute RMSD. + +\par Occupancy and beta factors + +PLUMED reads also occupancy and beta factors that however are given a very special meaning. +In cases where the PDB structure is used as a reference for an alignment (that's the case +for instance in \ref RMSD and in \ref FIT_TO_TEMPLATE), the occupancy column is used +to provide the weight of each atom in the alignment. In cases where, perhaps after alignment, +the displacement between running coordinates and the provided PDB is computed, the beta factors +are used as weight for the displacement. +Since setting the weights to zero is the same as __not__ including an atom in the alignement or +displacement calculation, the two following reference files would be equivalent when used in an \ref RMSD +calculation. First file: +\verbatim +ATOM 2 CH3 ACE 1 12.932 -14.718 -6.016 1.00 1.00 +ATOM 5 C ACE 1 21.312 -9.928 -5.946 1.00 1.00 +ATOM 9 CA ALA 2 19.462 -11.088 -8.986 0.00 0.00 +\endverbatim +Second file: +\verbatim +ATOM 2 CH3 ACE 1 12.932 -14.718 -6.016 1.00 1.00 +ATOM 5 C ACE 1 21.312 -9.928 -5.946 1.00 1.00 +\endverbatim +However notice that many extra atoms with zero weight might slow down the calculation, so +removing lines is better than setting their weights to zero. +In addition, weights for alignment need not to be equivalent to weights for displacement. + + +*/ +//+ENDPLUMEDOC + + namespace PLMD { unsigned PDB::getNumberOfAtomBlocks()const { diff --git a/user-doc/Colvar.txt b/user-doc/Colvar.txt index 7c6557796d..52200181f0 100644 --- a/user-doc/Colvar.txt +++ b/user-doc/Colvar.txt @@ -58,6 +58,8 @@ with the ammount the collective variables change. A full list of the ways dista These options for calculating distances are re-used in a number of places in the code. For instance they are used in some of the analysis algorithms that are implemented in PLUMED and in \ref PATH collective variables. +Notice that most of these actions read the reference configuration from a PDB file. Be sure +you understand how to format properly a PDB file to use used in PLUMED (see \ref pdbreader). \page mcolv MultiColvar From 06a919e576c06de053510c7e475a015d293d0757 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 10:38:06 +0200 Subject: [PATCH 23/62] Added doc for >100k atoms --- src/tools/PDB.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/tools/PDB.cpp b/src/tools/PDB.cpp index cb90135ab5..11e7c4e5d1 100644 --- a/src/tools/PDB.cpp +++ b/src/tools/PDB.cpp @@ -92,6 +92,30 @@ However notice that many extra atoms with zero weight might slow down the calcul removing lines is better than setting their weights to zero. In addition, weights for alignment need not to be equivalent to weights for displacement. +\par Systems with more than 100k atoms + +Notice that it very likely does not make any sense to compute the \ref RMSD or any other structural +deviation __using__ so many atoms. However, if the protein for which you want to compute \ref RMSD +has atoms with large serial numbers (e.g. because it is located __after__ solvent in the sorted list of atoms) +you might end up with troubles with the limitations of the PDB format. Indeed, since there are 5 +columns available for atom serial number, this number cannot be larger than 99999. +In addition, providing \ref MOLINFO with names associated to atoms with a serial larger than 99999 would be impossible. + +Since PLUMED 2.4 we allow [hybrid 36](http://cci.lbl.gov/hybrid_36/) format to be used to specify atom numbers. +This format is not particularly widespread, but has the nice feature that it provides a one-to-one mapping +between numbers up to approximately 80 millions and strings with 5 characters, plus it is backward compatible +for numbers smaller than 100000. This is not true for notations like the hex notation exported by VMD. +Using the hybrid 36 format, the ATOM records for atom ranging from 99997 to 100002 would read like these: +\verbatim +ATOM 99997 Ar X 1 45.349 38.631 15.116 1.00 1.00 +ATOM 99998 Ar X 1 46.189 38.631 15.956 1.00 1.00 +ATOM 99999 Ar X 1 46.189 39.471 15.116 1.00 1.00 +ATOM A0000 Ar X 1 45.349 39.471 15.956 1.00 1.00 +ATOM A0000 Ar X 1 45.349 38.631 16.796 1.00 1.00 +ATOM A0001 Ar X 1 46.189 38.631 17.636 1.00 1.00 +\endverbatim +There are tools that can be found to translate from integers to strings and back using hybrid 36 format +(a simple python script can be found [here](https://sourceforge.net/p/cctbx/code/HEAD/tree/trunk/iotbx/pdb/hybrid_36.py)). */ //+ENDPLUMEDOC From 348a943e7221667f22dde2244f04a0d016dd9a4c Mon Sep 17 00:00:00 2001 From: Carlo Camilloni Date: Thu, 27 Apr 2017 12:12:23 +0200 Subject: [PATCH 24/62] Manual: updated installing with almost [makedoc] --- user-doc/Installation.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/user-doc/Installation.txt b/user-doc/Installation.txt index ef961ead8d..b6fe1ac726 100644 --- a/user-doc/Installation.txt +++ b/user-doc/Installation.txt @@ -486,13 +486,24 @@ Compile it: \warning ALMOST needs SQLITE3 and GZIP installed on your computer. \warning ALMOST cannot be installed in the same folder of the source code, use --prefix to install it in a different folder +On Linux: + \verbatim > ./configure --prefix="wherever you want it" CXXFLAGS="-O3 -fPIC" CFLAGS="-O3 -fPIC" LIBS=-llapack > make > make install \endverbatim -Configure can complain about lapack and RDCs but it doesn't matter. + +On OSX: +\verbatim +> ./configure --prefix="wherever you want it" CXXFLAGS="-O3" CFLAGS="-O3" +> make +> make install +\endverbatim + +The configuration can complain about lapack and RDCs but it doesn't matter. Sometimes ALMOST can give errors related to the automake tools. To fix them it is often enough to execute + \verbatim > autoreconf -fi > automake From 3748165ecfb176bf1e6d1d4a61bafd10c81e7504 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 16:30:30 +0200 Subject: [PATCH 25/62] changelog [makedoc] --- CHANGES/v2.4.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES/v2.4.txt b/CHANGES/v2.4.txt index a7d60ac3d0..9efa21813c 100644 --- a/CHANGES/v2.4.txt +++ b/CHANGES/v2.4.txt @@ -28,6 +28,7 @@ Changes from version 2.3 which are relevant for users: - \ref IMPLICIT : EEF1-SB implicit solvent solvation energy - \ref METAD : BIASFACTOR=1 is allowed and performs unbiased sampling. HILLS file can be used to recover free energy also in this case. + - PDB files with more than 100k atoms can now be read using [hybrid 36](http://cci.lbl.gov/hybrid_36/) format. - Internal molfile implementation has been updated to VMD 1.9.3. - Examples in the documentation now have syntax highlighting and links to the documentation of used actions. From 22f1e4a2abf1ada202c62bf5d8eae5c5e196b958 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 16:31:57 +0200 Subject: [PATCH 26/62] changelog [makedoc] --- CHANGES/v2.4.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES/v2.4.txt b/CHANGES/v2.4.txt index 9efa21813c..7476ed435f 100644 --- a/CHANGES/v2.4.txt +++ b/CHANGES/v2.4.txt @@ -28,7 +28,8 @@ Changes from version 2.3 which are relevant for users: - \ref IMPLICIT : EEF1-SB implicit solvent solvation energy - \ref METAD : BIASFACTOR=1 is allowed and performs unbiased sampling. HILLS file can be used to recover free energy also in this case. - - PDB files with more than 100k atoms can now be read using [hybrid 36](http://cci.lbl.gov/hybrid_36/) format. + - PDB files with more than 100k atoms can now be read using [hybrid 36](http://cci.lbl.gov/hybrid_36/) format, + see \issue{226}. - Internal molfile implementation has been updated to VMD 1.9.3. - Examples in the documentation now have syntax highlighting and links to the documentation of used actions. From 6af49920b894ab49b49b529ef2e1b03fd6936026 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 18:06:34 +0200 Subject: [PATCH 27/62] Comment on replica suffix exceptions [makedoc] --- user-doc/Files.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/user-doc/Files.txt b/user-doc/Files.txt index f360af5d28..55415587e9 100644 --- a/user-doc/Files.txt +++ b/user-doc/Files.txt @@ -46,6 +46,10 @@ If you provide a file for each replica (e.g. plumed.0.dat, plumed.1.dat, etc) yo setup plumed differently on each replica. On the other hand, using a single plumed.dat will make all the replicas read the same file. +\warning This rule is true for almost all the files read by PLUMED. Current exceptions + are PDB files, where the replica suffix is not added, and trajectories read by \ref driver, + for which the replica suffix is always added. + Notice that when PLUMED adds the replica suffix, it recognizes the file extension and add the suffix _before_ the extension. Before PLUMED 2.2, the only recognized suffix was ".gz". Since 2.2, any suffix with length less or equal to five letters is recognized. @@ -61,4 +65,5 @@ PLUMED will write files named COLVAR.0.gz, COLVAR.1.gz, test.0.HILLS, test.1.HIL etc. This is useful since the preserved extension makes it easy to process the files later. + */ From 07b6dd3a0c2bbd09773eefc2de4e03bf060a0f38 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 17:05:55 +0200 Subject: [PATCH 28/62] Implemented replica suffix trick for trajectories Allow passing a single trajectory to driver --multi. The same logic is implemented as in IFile tool, that is: - look for file.##.ext - if it does not exist, look for file.ext Here ## is the replica index and .ext the extension of the file Fixed #228 --- src/cltools/Driver.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cltools/Driver.cpp b/src/cltools/Driver.cpp index 02435ea656..1a3bf513d3 100644 --- a/src/cltools/Driver.cpp +++ b/src/cltools/Driver.cpp @@ -471,13 +471,6 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc) { p.cmd("setPlumedDat",plumedFile.c_str()); p.cmd("setLog",out); - if(multi) { - string n; - Tools::convert(intercomm.Get_rank(),n); - trajectoryFile=FileBase::appendSuffix(trajectoryFile,"."+n); - } - - int natoms; FILE* fp=NULL; FILE* fp_forces=NULL; OFile fp_dforces; @@ -488,6 +481,13 @@ int Driver::main(FILE* in,FILE*out,Communicator& pc) { if (trajectoryFile=="-") fp=in; else { + if(multi) { + string n; + Tools::convert(intercomm.Get_rank(),n); + std::string testfile=FileBase::appendSuffix(trajectoryFile,"."+n); + FILE* tmp_fp=fopen(testfile.c_str(),"r"); + if(tmp_fp) { fclose(tmp_fp); trajectoryFile=testfile.c_str();} + } if(use_molfile==true) { #ifdef __PLUMED_HAS_MOLFILE_PLUGINS h_in = api->open_file_read(trajectoryFile.c_str(), trajectory_fmt.c_str(), &natoms); From 5869d03feeecf785fbacfacd669059f10ea0e5dc Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 18:00:36 +0200 Subject: [PATCH 29/62] regtest addresses #228 --- regtest/basic/rt-fix-228/COLVAR.0.reference | 2 ++ regtest/basic/rt-fix-228/COLVAR.1.reference | 2 ++ regtest/basic/rt-fix-228/Makefile | 1 + regtest/basic/rt-fix-228/config | 4 ++++ regtest/basic/rt-fix-228/plumed.0.dat | 2 ++ regtest/basic/rt-fix-228/plumed.1.dat | 2 ++ regtest/basic/rt-fix-228/traj.xyz | 5 +++++ 7 files changed, 18 insertions(+) create mode 100644 regtest/basic/rt-fix-228/COLVAR.0.reference create mode 100644 regtest/basic/rt-fix-228/COLVAR.1.reference create mode 100644 regtest/basic/rt-fix-228/Makefile create mode 100644 regtest/basic/rt-fix-228/config create mode 100644 regtest/basic/rt-fix-228/plumed.0.dat create mode 100644 regtest/basic/rt-fix-228/plumed.1.dat create mode 100644 regtest/basic/rt-fix-228/traj.xyz diff --git a/regtest/basic/rt-fix-228/COLVAR.0.reference b/regtest/basic/rt-fix-228/COLVAR.0.reference new file mode 100644 index 0000000000..02d36ac86a --- /dev/null +++ b/regtest/basic/rt-fix-228/COLVAR.0.reference @@ -0,0 +1,2 @@ +#! FIELDS time d + 0.000000 1.732051 diff --git a/regtest/basic/rt-fix-228/COLVAR.1.reference b/regtest/basic/rt-fix-228/COLVAR.1.reference new file mode 100644 index 0000000000..48952e8492 --- /dev/null +++ b/regtest/basic/rt-fix-228/COLVAR.1.reference @@ -0,0 +1,2 @@ +#! FIELDS time d + 0.000000 6.928203 diff --git a/regtest/basic/rt-fix-228/Makefile b/regtest/basic/rt-fix-228/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/basic/rt-fix-228/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/basic/rt-fix-228/config b/regtest/basic/rt-fix-228/config new file mode 100644 index 0000000000..4ae6da5caf --- /dev/null +++ b/regtest/basic/rt-fix-228/config @@ -0,0 +1,4 @@ +mpiprocs=2 +type=driver +# this is to test a different name +arg="--plumed plumed.dat --ixyz traj.xyz --multi 2" diff --git a/regtest/basic/rt-fix-228/plumed.0.dat b/regtest/basic/rt-fix-228/plumed.0.dat new file mode 100644 index 0000000000..e74e380096 --- /dev/null +++ b/regtest/basic/rt-fix-228/plumed.0.dat @@ -0,0 +1,2 @@ +d: DISTANCE ATOMS=1,2 +PRINT ARG=d FILE=COLVAR diff --git a/regtest/basic/rt-fix-228/plumed.1.dat b/regtest/basic/rt-fix-228/plumed.1.dat new file mode 100644 index 0000000000..b16f2d7a09 --- /dev/null +++ b/regtest/basic/rt-fix-228/plumed.1.dat @@ -0,0 +1,2 @@ +d: DISTANCE ATOMS=1,3 +PRINT ARG=d FILE=COLVAR diff --git a/regtest/basic/rt-fix-228/traj.xyz b/regtest/basic/rt-fix-228/traj.xyz new file mode 100644 index 0000000000..6a43046ec4 --- /dev/null +++ b/regtest/basic/rt-fix-228/traj.xyz @@ -0,0 +1,5 @@ +3 +0 0 0 +Ar 1 2 3 +Ar 2 3 4 +Ar 5 6 7 From d86dd6531642685c4dfd5f8ffe0edcea2d12f019 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 18:08:56 +0200 Subject: [PATCH 30/62] doc --- user-doc/Files.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/user-doc/Files.txt b/user-doc/Files.txt index dac3ebe472..3c1c4c8afb 100644 --- a/user-doc/Files.txt +++ b/user-doc/Files.txt @@ -45,9 +45,8 @@ If you provide a file for each replica (e.g. plumed.0.dat, plumed.1.dat, etc) yo setup plumed differently on each replica. On the other hand, using a single plumed.dat will make all the replicas read the same file. -\warning This rule is true for almost all the files read by PLUMED. Current exceptions - are PDB files, where the replica suffix is not added, and trajectories read by \ref driver, - for which the replica suffix is always added. +\warning This rule is true for almost all the files read by PLUMED. As of + PLUMED version 2.4, the only exception is PDB files, where the replica suffix is not added. Notice that when PLUMED adds the replica suffix, it recognizes the file extension and add the suffix _before_ the extension. Before PLUMED 2.2, the only recognized suffix was ".gz". Since 2.2, any suffix with length From 14c57ab0f47dd27919fbd5cfe6166b7ecac30107 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 27 Apr 2017 18:03:36 +0200 Subject: [PATCH 31/62] changelog --- CHANGES/v2.4.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES/v2.4.txt b/CHANGES/v2.4.txt index 7476ed435f..3a2f658fac 100644 --- a/CHANGES/v2.4.txt +++ b/CHANGES/v2.4.txt @@ -30,6 +30,8 @@ Changes from version 2.3 which are relevant for users: to recover free energy also in this case. - PDB files with more than 100k atoms can now be read using [hybrid 36](http://cci.lbl.gov/hybrid_36/) format, see \issue{226}. + - Trajectories read in \ref driver also support the usual replica convention, that is if + trajectory with replica suffix is not found the driver will look for a trajectory without the replica suffix. - Internal molfile implementation has been updated to VMD 1.9.3. - Examples in the documentation now have syntax highlighting and links to the documentation of used actions. From cdec228a6a7fe83358e96979b688f6898ff98fde Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Thu, 27 Apr 2017 19:32:27 +0100 Subject: [PATCH 32/62] Small fix to steinhardt parameters This ensures that steinhardt parameters are calculated correctly even if bond vectors run parallel to the z axis --- src/crystallization/Steinhardt.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp index 0cfeb44757..c920fdb107 100644 --- a/src/crystallization/Steinhardt.cpp +++ b/src/crystallization/Steinhardt.cpp @@ -102,8 +102,9 @@ void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { for(unsigned m=1; m<=tmom; ++m) { // Calculate Legendre Polynomial poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass ); - // Calculate powe of complex number - powered=pow(com1,m-1); md=static_cast(m); + // Calculate power of complex number + if(std::abs(com1)>epsilon) powered=pow(com1,m-1); + else powered = std::complex(0.,0.); // Real and imaginary parts of z real_z = real(com1*powered); imag_z = imag(com1*powered ); @@ -112,6 +113,7 @@ void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { itq6=poly_ass*imag_z; // Imaginary part of steinhardt parameter // Derivatives wrt ( x/r + iy )^m + md=static_cast(m); dp_x = md*powered*( (1.0/dlen)-(distance[0]*distance[0])/dlen3-ii*(distance[0]*distance[1])/dlen3 ); dp_y = md*powered*( ii*(1.0/dlen)-(distance[0]*distance[1])/dlen3-ii*(distance[1]*distance[1])/dlen3 ); dp_z = md*powered*( -(distance[0]*distance[2])/dlen3-ii*(distance[1]*distance[2])/dlen3 ); From 3cfe5d86abb241c464c35bb4b19a7b87dbfd9ec6 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 28 Apr 2017 09:55:25 +0200 Subject: [PATCH 33/62] Fixed parser bug Fixed #229 --- src/tools/Tools.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp index ccc93a2744..bdb2bc0399 100644 --- a/src/tools/Tools.cpp +++ b/src/tools/Tools.cpp @@ -133,6 +133,7 @@ vector Tools::getWords(const string & line,const char* separators,int * if(parenthesisLevel==0) for(unsigned j=0; j0) { if(!parlevel) plumed_massert(parenthesisLevel==0,"Unmatching parenthesis in '" + line + "'"); @@ -160,22 +161,23 @@ bool Tools::getParsedLine(IFile& ifile,vector & words) { trim(line); if(line.length()==0) continue; vector w=getWords(line,NULL,&parlevel); - if(w.empty()) continue; - if(inside && *(w.begin())=="...") { - inside=false; - if(w.size()==2) plumed_massert(w[1]==words[0],"second word in terminating \"...\" lines, if present, should be equal to first word of directive"); - plumed_massert(w.size()<=2,"terminating \"...\" lines cannot consist of more than two words"); - w.clear(); - } else if(*(w.end()-1)=="...") { - inside=true; - w.erase(w.end()-1); - }; - int i0=0; - if(mergenext && words.size()>0 && w.size()>0) { - words[words.size()-1]+=" "+w[0]; - i0=1; + if(!w.empty()) { + if(inside && *(w.begin())=="...") { + inside=false; + if(w.size()==2) plumed_massert(w[1]==words[0],"second word in terminating \"...\" lines, if present, should be equal to first word of directive"); + plumed_massert(w.size()<=2,"terminating \"...\" lines cannot consist of more than two words"); + w.clear(); + } else if(*(w.end()-1)=="...") { + inside=true; + w.erase(w.end()-1); + }; + int i0=0; + if(mergenext && words.size()>0 && w.size()>0) { + words[words.size()-1]+=" "+w[0]; + i0=1; + } + for(unsigned i=i0; i0); if(!inside)break; } From 7298c91260dfc02dc1d227a3c268eb473aa1a934 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 28 Apr 2017 09:57:32 +0200 Subject: [PATCH 34/62] Added test to stress parser Related to #229 --- regtest/basic/rt-fix-229/COLVAR.reference | 2 + regtest/basic/rt-fix-229/Makefile | 1 + regtest/basic/rt-fix-229/config | 2 + regtest/basic/rt-fix-229/plumed.dat | 60 +++++++++++++++++++++++ regtest/basic/rt-fix-229/traj.xyz | 5 ++ 5 files changed, 70 insertions(+) create mode 100644 regtest/basic/rt-fix-229/COLVAR.reference create mode 100644 regtest/basic/rt-fix-229/Makefile create mode 100644 regtest/basic/rt-fix-229/config create mode 100644 regtest/basic/rt-fix-229/plumed.dat create mode 100644 regtest/basic/rt-fix-229/traj.xyz diff --git a/regtest/basic/rt-fix-229/COLVAR.reference b/regtest/basic/rt-fix-229/COLVAR.reference new file mode 100644 index 0000000000..1456d79b0a --- /dev/null +++ b/regtest/basic/rt-fix-229/COLVAR.reference @@ -0,0 +1,2 @@ +#! FIELDS time average diff + 0.000000 0.080094 0.000000 diff --git a/regtest/basic/rt-fix-229/Makefile b/regtest/basic/rt-fix-229/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/basic/rt-fix-229/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/basic/rt-fix-229/config b/regtest/basic/rt-fix-229/config new file mode 100644 index 0000000000..2893c90964 --- /dev/null +++ b/regtest/basic/rt-fix-229/config @@ -0,0 +1,2 @@ +type=driver +arg="--plumed plumed.dat --ixyz traj.xyz" diff --git a/regtest/basic/rt-fix-229/plumed.dat b/regtest/basic/rt-fix-229/plumed.dat new file mode 100644 index 0000000000..fb4d9864cb --- /dev/null +++ b/regtest/basic/rt-fix-229/plumed.dat @@ -0,0 +1,60 @@ +# vim: ft=plumed +# this regtest is here to stress a bit the parser. + +# here is a reference calculation +c0: COORDINATION GROUPA=1,1,2,3 R_0=1 + +# then I redoit with many different choices for line +# splitting. At the end, all of them should be equal + +c1: COORDINATION ... # comment + GROUPA=1,1,2,3 + R_0=1 +... #comment + +c2: COORDINATION GROUPA=1,1,2,3 R_0=1 ... +... + +c3: COORDINATION ... +GROUPA={1 1 2 3} R_0=1 + ... + +c4: COORDINATION ... +GROUPA={ +1 + 1 +## comment in the middle +2 +3 +} +R_0=1 +... + +c5: COORDINATION ... +GROUPA={ + 1 1 + 2 3 } +R_0=1 +... + +c6: COORDINATION ... +GROUPA={ 1 1 2 3 + } R_0=1 +... + +c7: COORDINATION GROUPA=1,1,2,3 ... +R_0=1 +... + + +# here are the final checks. +# this is just designed to check that all the c are identical + +# average c +average: COMBINE ARG=(c.*) NORMALIZE PERIODIC=NO +# s.1 is smallest c +s: SORT ARG=(c.*) +# s.1 and average are only equal if all c.* are identical +diff: COMBINE ARG=s.1,average COEFFICIENTS=1,-1 PERIODIC=NO +PRINT ARG=average,diff FILE=COLVAR + diff --git a/regtest/basic/rt-fix-229/traj.xyz b/regtest/basic/rt-fix-229/traj.xyz new file mode 100644 index 0000000000..088ed92393 --- /dev/null +++ b/regtest/basic/rt-fix-229/traj.xyz @@ -0,0 +1,5 @@ +3 +0 0 0 +Ar 0 1 2 +Ar 1 2 3 +Ar 3 3 3 From 6ce57777415514e05698bdb530912611ff1b0a35 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 28 Apr 2017 10:16:24 +0200 Subject: [PATCH 35/62] changelog --- CHANGES/v2.3.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES/v2.3.txt b/CHANGES/v2.3.txt index 3ca2505ba2..a3c1e87a32 100644 --- a/CHANGES/v2.3.txt +++ b/CHANGES/v2.3.txt @@ -159,6 +159,7 @@ See branch \branch{v2.3} on git repository. - Fixed bug in \ref DISTANCES that appears when using BETWEEN and link cells. - Prevented users from causing segfaults by storing derivatives without LOWMEM flag. In these caess PLUMED crashes with meaningful errors. - Fixed bug in \ref HISTOGRAM that causes nans when using KERNEL=DISCRETE option +- Fixed a bug in the parser related to braces, see \issue{229} For developers: - plumedcheck validation has been made stricter. All the checks are now described in the developer manual. From 7d6415cbc3353e8976c56e89dda5782b8a74f2c5 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Fri, 28 Apr 2017 09:28:29 +0100 Subject: [PATCH 36/62] Astyled after change to Steinhardt.cpp --- src/crystallization/Steinhardt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp index c920fdb107..b1d085bb04 100644 --- a/src/crystallization/Steinhardt.cpp +++ b/src/crystallization/Steinhardt.cpp @@ -103,8 +103,8 @@ void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { // Calculate Legendre Polynomial poly_ass=deriv_poly( m, distance[2]/dlen, dpoly_ass ); // Calculate power of complex number - if(std::abs(com1)>epsilon) powered=pow(com1,m-1); - else powered = std::complex(0.,0.); + if(std::abs(com1)>epsilon) powered=pow(com1,m-1); + else powered = std::complex(0.,0.); // Real and imaginary parts of z real_z = real(com1*powered); imag_z = imag(com1*powered ); From ea63721b223a8036ad6d41e3165620fdca26dd9a Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 28 Apr 2017 16:43:59 +0200 Subject: [PATCH 37/62] Improved INCLUDE documentation I added several examples with plumedfile, so I only push this on master branch. --- src/generic/Include.cpp | 87 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 5 deletions(-) diff --git a/src/generic/Include.cpp b/src/generic/Include.cpp index 30539f0bb0..70f41716c8 100644 --- a/src/generic/Include.cpp +++ b/src/generic/Include.cpp @@ -37,28 +37,105 @@ Useful to split very large plumed.dat files. \par Examples -This input +This input: \plumedfile c1: COM ATOMS=1-100 c2: COM ATOMS=101-202 d: DISTANCE ARG=c1,c2 PRINT ARG=d \endplumedfile - -can be replaced with +can be replaced with this input: \plumedfile INCLUDE FILE=pippo.dat d: DISTANCE ARG=c1,c2 PRINT ARG=d \endplumedfile - where the content of file pippo.dat is \plumedfile c1: COM ATOMS=1-100 c2: COM ATOMS=101-202 \endplumedfile -(see also \ref COM, \ref DISTANCE, and \ref PRINT). +The files in this example are rather short, but imagine a case like this one: +\plumedfile +INCLUDE FILE=groups.dat +c: COORDINATION GROUPA=groupa GROUPB=groupb R_0=0.5 +METAD ARG=c HEIGHT=0.2 PACE=100 SIGMA=0.2 BIASFACTOR=5 +\endplumedfile +Here `groups.dat` could be huge file containing group definitions such as +\plumedfile +groupa: GROUP ... + ATOMS={ + 10 + 50 + 60 +## imagine a long list here + 70 + 80 + 120 + } +... +groupb: GROUP ... + ATOMS={ + 11 + 51 + 61 +## imagine a long list here + 71 + 81 + 121 + } +... +\endplumedfile +So, included files are the best place where one can store long definitions. + +Another case where INCLUDE is very useful is when running multi-replica simulations. +Here different replicas might have different input files, but perhaps a large part of the +input is shared. This part can be put in a common included file. For instance you could have +`common.dat`: +\plumedfile +# this is common.dat +t: TORSION ATOMS=1,2,3,4 +\endplumedfile +Then `plumed.0.dat`: +\plumedfile +# this is plumed.0.dat +INCLUDE FILE=common.dat +RESTRAINT ARG=t AT=1.0 KAPPA=10 +\endplumedfile +And `plumed.1.dat`: +\plumedfile +# this is plumed.1.dat +INCLUDE FILE=common.dat +RESTRAINT ARG=t AT=1.2 KAPPA=10 +\endplumedfile + +\warning +Remember that when using multi replica simulations whenever plumed tried to open +a file for reading it looks for a file with the replica suffix first. +This is true also for files opened by INCLUDE! + +As an example, the same result of the inputs above could have been obtained using +`plumed.dat`: +\plumedfile +# this is plumed.dat +t: TORSION ATOMS=1,2,3,4 +INCLUDE FILE=other.dat +\endplumedfile +Then `other.0.dat`: +\plumedfile +# this is other.0.dat +RESTRAINT ARG=t AT=1.0 KAPPA=10 +\endplumedfile +And `other.1.dat`: +\plumedfile +# this is other.1.dat +RESTRAINT ARG=t AT=1.2 KAPPA=10 +\endplumedfile + + + + */ //+ENDPLUMEDOC From d2029ad4e53772761e170dbe4e9f65b58702f39e Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 28 Apr 2017 18:44:24 +0200 Subject: [PATCH 38/62] Small fixes in doc (v2.3) [makedoc] --- CHANGES/v2.3.txt | 2 +- src/analysis/PCA.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES/v2.3.txt b/CHANGES/v2.3.txt index a3c1e87a32..d5aa9352d2 100644 --- a/CHANGES/v2.3.txt +++ b/CHANGES/v2.3.txt @@ -155,7 +155,7 @@ See branch \branch{v2.3} on git repository. - Fixed bug in if condition in \ref PCAVARS so that you can run with only one eigenvector defined in input - Fixed bug with timers in \ref sum_hills \issue{194}. - Fixed bug when using \ref MOVINGRESTRAINT with periodic variables such as \ref TORSION \issue{225}. -- Fixed bug in \ref HBONDS that used to apear when you used DONORNS and ACCEPTORS with same numbers of atoms +- Fixed bug in \ref HBOND_MATRIX that used to apear when you used DONORS and ACCEPTORS with same numbers of atoms - Fixed bug in \ref DISTANCES that appears when using BETWEEN and link cells. - Prevented users from causing segfaults by storing derivatives without LOWMEM flag. In these caess PLUMED crashes with meaningful errors. - Fixed bug in \ref HISTOGRAM that causes nans when using KERNEL=DISCRETE option diff --git a/src/analysis/PCA.cpp b/src/analysis/PCA.cpp index 5b31a04faa..7bb5dc4149 100644 --- a/src/analysis/PCA.cpp +++ b/src/analysis/PCA.cpp @@ -79,7 +79,7 @@ the current value of the instantaneous bias (see \ref REWEIGHT_BIAS). d1: DISTANCE ATOMS=1,2 d2: DISTANCE ATOMS=1,3 d3: DISTANCE ATOMS=1,4 -d4: DISTNACE ATOMS=2,3 +d4: DISTANCE ATOMS=2,3 d5: DISTANCE ATOMS=2,4 d6: DISTANCE ATOMS=3,4 From 93a87da36bd5d0afbe5f80fcccc95bfff4515575 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 28 Apr 2017 18:53:10 +0200 Subject: [PATCH 39/62] Small fixed in doc (master only) [makedoc] --- src/crystallization/InterMolecularTorsions.cpp | 2 +- src/multicolvar/XAngle.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crystallization/InterMolecularTorsions.cpp b/src/crystallization/InterMolecularTorsions.cpp index 58294492f6..a5a1bc2514 100644 --- a/src/crystallization/InterMolecularTorsions.cpp +++ b/src/crystallization/InterMolecularTorsions.cpp @@ -37,7 +37,7 @@ it can be used to compute quantities like this: \f[ s = \frac{ \sum_{i \ne j} \sigma(r_{ij}) \theta_{ij} }{ \sum_{i \ne j} \sigma(r_{ij}) } -f\] +\f] Here the sums run over all pairs of molecules. \f$\sigma(r_{ij})\f$ is a \ref switchingfunction that action on the distance between the centers of molecules \f$i\f$ and \f$j\f$. \f$\theta_{ij}\f$ is then diff --git a/src/multicolvar/XAngle.cpp b/src/multicolvar/XAngle.cpp index dd90c187f6..fdbfff158c 100644 --- a/src/multicolvar/XAngle.cpp +++ b/src/multicolvar/XAngle.cpp @@ -42,7 +42,7 @@ Calculate the angles between the vector connecting two atoms and the x axis. The following input tells plumed to calculate the angles between the x-axis and the vector connecting atom 3 to atom 5 and between the x-axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \plumedfile -XANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 +XANGLES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min \endplumedfile (See also \ref PRINT). @@ -58,7 +58,7 @@ Calculate the angles between the vector connecting two atoms and the y axis. The following input tells plumed to calculate the angles between the y-axis and the vector connecting atom 3 to atom 5 and between the y-axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \plumedfile -YANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 +YANGLES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min \endplumedfile (See also \ref PRINT). @@ -74,7 +74,7 @@ Calculate the angles between the vector connecting two atoms and the z axis. The following input tells plumed to calculate the angles between the z-axis and the vector connecting atom 3 to atom 5 and between the z-axis and the vector connecting atom 1 to atom 2. The minimum of these two quantities is then \plumedfile -ZANLGES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 +ZANGLES ATOMS1=3,5 ATOMS2=1,2 MIN={BETA=0.1} LABEL=d1 PRINT ARG=d1.min \endplumedfile (See also \ref PRINT). From 7e988faa58a87d7eec7525c38c909b83d09ad6c9 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Tue, 2 May 2017 08:59:37 +0100 Subject: [PATCH 40/62] Added trieste tutorial on block averaging --- user-doc/figs/trieste-2-autocorrelation.png | Bin 0 -> 23980 bytes user-doc/figs/trieste-2-block-averages.png | Bin 0 -> 25962 bytes user-doc/figs/trieste-2-confidence.png | Bin 0 -> 16115 bytes user-doc/figs/trieste-2-histogram-errors.png | Bin 0 -> 30388 bytes .../figs/trieste-2-mc-autocorrelation.png | Bin 0 -> 19270 bytes user-doc/tutorials/trieste-2.txt | 739 ++++++++++++++++++ 6 files changed, 739 insertions(+) create mode 100644 user-doc/figs/trieste-2-autocorrelation.png create mode 100644 user-doc/figs/trieste-2-block-averages.png create mode 100644 user-doc/figs/trieste-2-confidence.png create mode 100644 user-doc/figs/trieste-2-histogram-errors.png create mode 100644 user-doc/figs/trieste-2-mc-autocorrelation.png create mode 100644 user-doc/tutorials/trieste-2.txt diff --git a/user-doc/figs/trieste-2-autocorrelation.png b/user-doc/figs/trieste-2-autocorrelation.png new file mode 100644 index 0000000000000000000000000000000000000000..033167aca2bffdbda681060b666fbe650f829627 GIT binary patch literal 23980 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³Im*|Q23B7`rbi2ku@A0Wu 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 literal 0 HcmV?d00001 diff --git a/user-doc/figs/trieste-2-confidence.png b/user-doc/figs/trieste-2-confidence.png new file mode 100644 index 0000000000000000000000000000000000000000..56f49a8309dfe74ef978997cd1cca2ec1c33e399 GIT binary patch literal 16115 zcmc(`cUaR)*Djn8igaTE=^8;csDN~&=_ZPRfCd5SQADJJbV3QD5(^+mQL1h!B2|$Z zN)QC8QF5HS50T$u$FQPBwlv z2n52Za|MZlKp6VKU+DwPpv3^0n-2bA^!!uj#sTmr@W34$_?gxHikT+_!hMVS7y4c^ z%K-v84$(ngyy2Hj9`;YRG)`GxBuZ}&gdRN3`sbZ!yP@OI8;p$Jf|lCQl0YN-1ht9k+SC_*=FASRdS&0ub+Q3hkZdGhkD$yVTgeodZW7CGqpMHr7xXrVCvhO zH)yr$Ut_&)TuK}cu63HS5T8mFkPs8qi4pB?eE5m|1^8d$6R1UusLqFzuoCdo4Q*y; z@Z0Q2jy}+c65=Zq(}_txFN@X#KYHIG#DhLF->_$?Gepw|zRP6qgM0WP1Emmq2jR1b z+jdAxLAc?E#SIm>$3>*tkmru{$)AOP&4RHgPh2djU!ltwX~`hSWXUkZ(aJKy*2<6? zjoRuoh~y+G5sX4TLlp?G2^xf-u^m=lO{Bs17xVdGYjU9iDBZ!W&q9zL;WE(-uNi~L zpraHQQhIF1dceRWv=pYPBawo-w+JNVUr&@mbDu)ELQuNXxD>MIIrpo&4rACgX@&yk z$;{Xi9*bmb3_}#hN8&BQQ^~m&EFU3sRZ17k(Uu{`;DbzNAYT&R`zXhb z?KU1b?ZTep{1Ob@Gwoy{@H>cvPE<_`48AVi3DJjz`0TkvwI3L!-zV@|y-fkFII{S%3dg*CDgw=&Ne7Y5~t7g{$f{XBy9WIB#dw!R(@%6$Cy%(ZMn?So!Wfem>IiWE+$#QAxTMo45d z%S3u&jhe>Y=Vu-8NBmUXZz0uQtL2Tpo(R9FdBbarx^4T3=g^udI~RWHVd6t2p{mf~ zAf@!!ijzMd5yYDcOw$ZfVcT7?9YT+c&w$0t{NV*v&F~70*iK^zwI&qHwOAZ_m(xs zT5P27Y*Ztv#adxc=VL{7-;*W5irrv_`9SXyALr+P$^k(E#mCXdbk8ZQ*r_G|Pp~g` zGHBj6d2PZVG^Cr@5u~tMNHEAe0g8uk!NH0}^A3@vGE zw?X767N$+#o)%dLf`Fqs=-n3vVn|m-qAXgwz7@COj@*$)^dOPG$Yk^Jj|J2HA*4_0 zh_&~>1mmzS+#oWcW?$d%fik^jsT8@%I>acb)H-fNTwLe67g8A?#z_rUc{ygVHA!@^ z?(`V$CWEEs15e9nl=-=sXQmBkRU{I~v?~AWV03IpPi#lsJ9R^3>r>pVeWgT&(;)*i zVFG|Ky%!;-P%FY?+{Q(u;I-M>!{U=KT&PjcQN8Uv@{YVBgqNWP!9o@zsD?TrZhPoX zhngGwob3Qn()=Y9gN^MFBZvhh1|Ng(b6RpHGbNj~_y<~50QsHnrLS9~8 zD^9ayvh%m%lNntv*yA#Y@<9dq5?7c@K>oxA!Z#rUd>r~Y{Lo7T*$91vT;RsTDsVJ$YG0W zNJgE^Lcn>L zElDZC>IoRm--NY#(OPXoaRwb`~~{gZ3$8@=w3r@qwhWNihpK#Q&OUa6wUZ_ z8u%0H9gt5RXebAulNNrdDw+#Q5>%A

    3)BkAoYr_ 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 xXMK`O3E~vUO^e literal 0 HcmV?d00001 diff --git a/user-doc/figs/trieste-2-histogram-errors.png b/user-doc/figs/trieste-2-histogram-errors.png new file mode 100644 index 0000000000000000000000000000000000000000..6b2947347e98dac963cfe0546cddabb5f4d779e1 GIT binary patch literal 30388 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 z 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 literal 0 HcmV?d00001 diff --git a/user-doc/figs/trieste-2-mc-autocorrelation.png b/user-doc/figs/trieste-2-mc-autocorrelation.png new file mode 100644 index 0000000000000000000000000000000000000000..7957cea27d3b502116ffb047a5493ae4c4af9107 GIT binary patch literal 19270 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 literal 0 HcmV?d00001 diff --git a/user-doc/tutorials/trieste-2.txt b/user-doc/tutorials/trieste-2.txt new file mode 100644 index 0000000000..7173b95d05 --- /dev/null +++ b/user-doc/tutorials/trieste-2.txt @@ -0,0 +1,739 @@ +/** +\page trieste-2 Trieste tutorial: Averaging, histograms and block analysis + +\section trieste-2-aim Introduction + +The aim of this tutorial is for you to understand how we analyse trajectory data by calculating ensemble averages. One key point we try to +make in this tutorial is that you must always calculate averaged quantities from our simulation trajectories. Consequently, in order +to understand the analysis that is done when we perform molecular dynamics and Monte Carlo simulations, we will need to understand some things about +probability and statistics. In fact, the things that we need to understand about probability and statistics are going to be the main subject of this +tutorial. Therefore, in order to make our lives easier, we are not going to work with simulation trajectories in this tutorial. We are going to use +model data instead. + +\section trieste-2-lo Objectives + +Once this tutorial is completed students will: + +- Be able to explain the role played by the central limit theorem in many of the analyses we perform on simulation trajectories. +- Be able to use PLUMED to calculate ensemble averages and histograms using the keywords \ref AVERAGE and \ref HISTOGRAM. +- Be able to use PLUMED to perform block analyses of trajectory data using the keywords \ref AVERAGE and \ref HISTOGRAM. +- Be able to use PLUMED to calculate unbiased ensemble averages and histograms from biased trajectories by using the keywords \ref AVERAGE, \ref HISTOGRAM and \ref REWEIGHT_BIAS. +- Be able to explain how block analysis can be used to detect problems with error bar underestimation in correlated data. + +\section trieste-2-introduction Background + +Let's begin by thinking about what is actually output by a simulation trajectory. You probably know by now that molecular dynamics gives us a trajectory +that provides us with information on how the positions and velocities of the all the atoms in the system change with time. Furthermore, you should by now +understand that we can use PLUMED to reduce the ammount of information contained in each of the trajectory frames to a single number or a low-dimensional vector +by calculating a collective variable or a set of collective variables. As we saw in \ref belfast-1 this process of lowering the dimensionality of the data +contained in a simulation trajectory was vital as we understand very little by watching the motions of the hundreds of atoms that the system we are simulating +contains. If we monitor the appropriate key variables, however, we can determine whether a chemical reaction has taken place, whether the system has undergone a +phase transition to a more ordered form or if a protein has folded. Even so if all we do is monitor the values the the collective variables take during the simulation +our result can only ever be qualitative and we can only say that we observed this process to take place under these particular conditions on one particular occasion. +Obviously, we would like to be able to do more - we would like to be able to make quantiative predictions based on the outcomes of our simulations. + +The first step in moving towards making these quantitative predictions involves rethinking what precisely our simulation trajectory has provided us with. +We know from rudimentary statistical mechanics that when we perform a molecular dynamics simulation in the NVT ensemble the values of the collective variables +that we obtain for each of our trajectory frames, \f$X\f$, are samples from the following probability distribution: + +\f[ +P(s') = \frac{ \int \textrm{d}x \textrm{d}p \delta( s(x) - s') e^{-\frac{H(x,p)}{k_B T}} }{ \int \textrm{d}x\textrm{d}p e^{-\frac{H(x,p)}{k_B T}} } +\f] + +In this expression the integral signs are used to represent \f$6N\f$-dimensional integrals that run over all the possible positions and momenta that the \f$N\f$ atoms +in our system can take. \f$H(x,p)\f$ is the Hamiltonian and \f$k_B\f$ and \f$T\f$ are Boltzmann's constant and the temperature respectively. The quantity calculated +by this quotient is the probability that our CV will take a value \f$s'\f$. The quantity in the denominator of the above expression is the canonical partition function +while the \f$\delta\f$ function in the integral in the numerator ensures that only those configurations that have a CV value, \f$s(x)\f$, equal to \f$s'\f$ contribute +to the integral in the numerator. + +The fact that we know what distribution the \f$X\f$-values obtained from our trajectory frames are taken from is not particularly helpful as it is impossible to calculate +the integrals in the expression above analytically. The fact that we know that our trajectory frames represent samples from a distribution is helpful, however, because of a +result know as the Central Limit Thoerem. This theorem states the following: +\f[ +\lim_{n \rightarrow \infty} P\left( \frac{\frac{S_n}{n} - \langle Y \rangle}{ \sqrt{\frac{\langle(\delta Y)^2\rangle}{n}} } \le z \right) = \Phi(z) +\f] +In this expression \f$\Phi(z)\f$ is the cumulative probability distribution function for a standard normal distribution and \f$S_n\f$ is a sum of \f$n\f$ independent samples +from a probability distribution - in our case the probability distribution that we introduced in the previous equation. \f$\langle Y \rangle\f$ is the ensemble average +for the quantity \f$Y(x)\f$, which, in our case, we can calculate as follows: +\f[ +\langle Y \rangle = \frac{ \int \textrm{d}x \textrm{d}p Y(x) e^{-\frac{H(x,p)}{k_B T}} }{ \int \textrm{d}x\textrm{d}p e^{-\frac{H(x,p)}{k_B T}} } +\f] +Lastly, the quantity \f$\langle(\delta Y)^2\rangle\f$ is a measure of the extent of the fluctuations we will observe in the \f$Y\f$ values that we samples. This +quantity is calculated using: +\f[ +\langle(\delta Y)^2\rangle = \langle Y^2 \rangle - \langle Y \rangle^2 +\f] + +The statement of the theorem provided above is compact way of stating the formal theorem. This is undoubtedly pleasing to mathematicians but to understand why this idea is +so important in the context of molecular simulation it is useful to think about this in a slightly less formal way. The central limit theorem essentially tells us that if +we take the set of random variables we extract from a simulation trajectory, which we know represent samples from the complicated distribution in the first equation above, +and we add all these random variables together and divide by \f$n\f$ we can think of the final number we obtain as a random variable that is taken from a Gaussian distribution. In other words, the probabiilty density function for the sample mean, \f$\frac{S_n}{n}\f$, that we get from our trajectory frames is given by: +\f[ +P(S_n) = \frac{1}{\sqrt{\frac{2\pi \langle(\delta Y)^2\rangle}{n}}} \exp\left( - \frac{\frac{S_n}{n} - \langle Y \rangle}{ 2\frac{\langle(\delta Y)^2\rangle}{n} } \right) +\f] +This function is shown plotted for various values of \f$n\f$ in the movie at https://www.youtube.com/watch?v=-7hlP-2dG_o&feature=youtu.be. +You can see clearly that this distribution becomes more strongly peaked around \f$\langle Y\rangle\f$ (which I set equal to 0 in the movie) as \f$n\f$ increases. +This observation is important as it ensures that the probability that \f$\frac{S_n}{n}\f$ lies close to the true value of the expectation value of our +distribution, \f$\langle Y\rangle\f$, increases as we increase the value of \f$n\f$. The central limit theorem therefore allows us to get an estimate +for the ensemble average for a particular quantity \f$Y\f$ by taking repeated samples of \f$Y\f$ from our distribution. These samples can be taken by, for example, +performing a molecular dynamics simulation. Furthermore, and as we will see in the exercises that follow, we can also get an estimate of how much we might expect the +system to fluctuate about this average. + +\section trieste-2-instructions Instructions + +\subsection trieste-2-average Calculating an ensemble average + +As discussed in the introduction we are going to be using model data in this exercise so we must begin by generating some model data to analyse +using PLUMED. The following short python script will generate 10000 (pseudo) random variables between 0 and 1 from a uniform disribution in a format that +PLUMED can understand: + +\verbatim +import random + +print("#! FIELDS time rand") +for i in range(0,10001): + print(i, random.uniform(0,1) ) +\endverbatim + +Copy the contents of the box above to a plain text file called generate_data.py, save the file and then execute the script within it by running: + +\verbatim +python generate_data.py > mydata +\endverbatim + +This will generate a file called mydata that contains 10001 uniform random variables. PLUMED will ignore the first number in the colvar file as it assumes +this is the initial configuration you provided for the trajectory. The sample mean will thus be calculated from 10000 random variables. Plot this data now +using gnuplot and the command: + +\verbatim +p 'mydata' u 1:2 w p +\endverbatim + +The probability distribution that we generated these random variables is considerably simpler than the probability distribution that we would typically +sample from during an MD simulation. Consequently, we can calculate the exact values for the ensemble average and the fluctuations for this distribution. +These are: + +\f[ +\begin{aligned} + \langle X \rangle &= \int_0^1 x \textrm{d}x = \left[ \frac{x^2}{2} \right]_0^1 = \frac{1}{2} \\ + \langle X^2 \rangle &= \int_0^1 x^2 \textrm{d}x = \left[ \frac{x^3}{3} \right]_0^1 = \frac{1}{3} \\ + \langle (\delta X)^2 \rangle & = \langle X^2 \rangle - \langle X \rangle^2 = \frac{1}{12} +\end{aligned} +\f] + +Lets now try estimating these quantieis by calculating \f$\frac{S_n}{n}\f$ from the points we generated and exploting the central limit theorem. +We can do this calculation by writing a PLUMED input file that reads: + +\verbatim +data: READ FILE=mydata VALUES=rand +d2: MATHEVAL ARG=data VAR=a FUNC=a*a PERIODIC=NO +av: AVERAGE ARG=data STRIDE=1 +av2: AVERAGE ARG=d2 STRIDE=1 +PRINT ARG=av,av2 STRIDE=10000 FILE=colvar +\endverbatim + +If you copy this input to a file called plumed.dat you can then run the calculation by executing: + +\verbatim +plumed driver --noatoms +\endverbatim + +When the calculation is finished you should have a file called colvar that contains the estimate of the ensemble averages \f$\langle X \rangle\f$ and \f$\langle X^2 \rangle\f$. +To be clear, the quantities output in this file are: + +\f[ +\langle X \rangle = \frac{1}{N} \sum_{i=1}^N X_i \qquad \textrm{and} \qquad \langle X^2 \rangle \frac{1}{N} \sum_{i=1}^N X_i^2 +\f] + +We can calculate the flucutations, \f$(\delta X)^2\f$, from them using: + +\f[ +(\delta X)^2 = \langle X^2 \rangle - \langle X \rangle^2 +\f] + +We can then compare the values that we got for these estimated values with those that we got for the true values. You should find that the agreement +is reasonable but not perfect. + +\subsection trieste-2-histo Calculating a histogram + +We can use what we have learnt about calculating an ensemble average to calculate an estimate for the probability density function or probability mass function +for our random variable. The theory behind what we do here is explained in this video http://gtribello.github.io/mathNET/histogram-video.html + +To do such a calculation with PLUMED on the random variables we generated from the uniform distribution in the previous section we would use an input like the one +below: + +\verbatim +data: READ FILE=mydata VALUES=rand +hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE +DUMPGRID GRID=hh FILE=myhist.dat +\endverbatim + +Once again you can run this calculation by using the command: + +\verbatim +plumed driver --noatoms +\endverbatim + +Once this calculation is completed you can then plot the output using gnuplot and the command: + +\verbatim +p 'myhist.dat' u 1:2 w l +\endverbatim + +In the previous section we compared the estimates we got for the ensemble average with the exact analytical values, which we could determine +because we know that the data was sampled from a uniform distribution between 0 and 1. We can do a similar thing with the histogram. Can +you determine what the true (analytic) values for the probabilities in the histogram above should be? +Also notice that the probability estimate for the first and last points in our histogram are lower than the probability estimates for the other points. + Can you determine why these two points have a lower probability? + +\subsection trieste-2-blocks Problem I: Making the best use of the data + +As discussed in previous sections the sample mean of the CV values from our trajectory frames is a random variable and the central limit theorem tells us something about the +the distribution from which this random variable is drawn. The fact that we know what distribution the sample mean is drawn from is what allows +us to estimate the ensemble average and the fluctuations. The fact that this recipe is only estimating the ensemble average is critical and +this realisation should always be at the forefront of our minds whenever we analyse our simulation data. The point, once again, is that the sample mean for CV values +from the simulation is random. As is explained in this video http://gtribello.github.io/mathNET/central-limit-theorem-video.html, however, we can use the +central limit theorem to calculate a range, \f$\{\langle X \rangle-\epsilon,\langle X \rangle+\epsilon\}\f$, that the sample mean for the CV values, \f$\frac{S_n}{n}\f$, +will fall into with a probability \f$p_c\f$ using: +\f[ +\epsilon = \sqrt{ \frac{\langle ( \delta X )^2 \rangle }{n} } \Phi^{-1}\left( \frac{p_c + 1}{2} \right) +\f] +Here \f$\Phi^{-1}\f$ is the inverse of the cumulative probability distribution function for a normal distribution with mean 0 and variance 1. As you can see +this range gets smaller as the number of samples from which you calculate the mean, \f$n\f$, increases. As is shown in the figure below, however, the rate +at which this range narrows in size is relatively small. + +\anchor triest-2-confidence +\image html trieste-2-confidence.png "A figure showing how the width of the 90% confidence limit changes with number of samples. Two lines are shown - one at plus epsilon and one at minus epsilon. This figure shows clearly that simply averaging over more random variables will not get us markedly closer to the true value of the ensemble average, which is 0 for this particular example. For this random variable average fluctuation is equal to one." + +This graph hopefully illustrates to you that an estimate of the ensemble average that is taken over 500 trajectory frames is not guaranteed +to lie significantly closer to the true ensemble average than an estimate taken from 100 trajectory frames. For this reason, we might choose to split the +data into blocks that all have equal length. Will will then estimate the average for each of these blocks separately. As we will see in the remainder of +this exercise this process of block averaging has a number of other advantages. For now though we are just going to use it to test that the results from the +various parts of the trajectory are all consistent. + +We can perform a block averaging on the data we generated at the start of the first exercise above by using PLUMED and the input file below: + +\verbatim +data: READ FILE=mydata VALUES=rand +av: AVERAGE ARG=data STRIDE=1 CLEAR=1000 +PRINT ARG=av STRIDE=1000 FILE=colvar +\endverbatim + +Once again this calculation can be executed by running the command: + +\verbatim +plumed driver --noatoms +\endverbatim + +The key differences between this input and the ones that we have seen previously is the CLEAR keyword on the line AVERAGE. The intruction CLEAR=1000 tells PLUMED +that the data that has been accumulated for averaging should be reset to zero (cleared) every 1000 steps. If you look at the subsequent PRINT command in the above +input you see the instruction STRIDE=1000. The above input thus accumulates an average over 1000 trajectory frames. This average is then output to the file colvar +on step 1000 and the accumulated data is immediately cleared after printing so that a new average over the next 1000 steps can be accumulated. We can plot the averages +that were output from the calculation above by using gnuplot and the following command: + +\verbatim +p 'colvar' u 1:2:3 w e +\endverbatim + +If you try this now you should see that all the average values that were calculated are relatively consistent but that there are differences between them. Try to +calculate the size of \f$\epsilon\f$ for a 90 % confidence limit around this random variable using the formula that was provided above. How many of the averages that +you exptracted using PLUMED lie within this range? Is this behavior inline with your expectations based on your understanding of what a confidence limit is? + +We can also perform block averaging when we estimate histograms using PLUMED. The following input will calculate these block averaged histograms for the data we +generated at the start of this exercise using PLUMED. + +\verbatim +data: READ FILE=mydata VALUES=rand +hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE CLEAR=1000 +DUMPGRID GRID=hh FILE=myhist.dat STRIDE=1000 +\endverbatim + +Notice that the input here has the same structure as the input for the \ref AVERAGE. Once again we have a CLEAR=1000 keyword that tells PLUMED that the data that has been +accumulated for calculating the histogram should be deleted every 1000 steps. In addition, we can set a STRIDE for \ref DUMPGRID and thus output the histogram from each of +these blocks of trajectory data separately. The difference between the output from this input and the output from the input above is that in this case we have multiple +output files. In particular, the input above should give you 10 output files which will be called: + +- analysis.0.myhist.dat = analysis of data in first 1000 frames +- analysis.1.myhist.dat = analysis of data in second 1000 frames +- analysis.2.myhist.dat = analysis of data in third 1000 frames +- analysis.3.myhist.dat = analysis of data in fourth 1000 frames +- analysis.4.myhist.dat = analysis of data in fifth 1000 frames +- analysis.5.myhist.dat = analysis of data in sixth 1000 frames +- analysis.6.myhist.dat = analysis of data in seventh 1000 frames +- analysis.7.myhist.dat = analysis of data in eigth 1000 frames +- analysis.8.myhist.dat = analysis of data in ninth 1000 frames +- myhist.dat = analysis of data in tenth 1000 frames + +We can plot all of these histograms using gnuplot and the command: + +\verbatim +p 'analysis.0.myhist.dat' u 1:2:3 w e, 'analysis.1.myhist.dat' u 1:2:3 w e, 'analysis.2.myhist.dat' u 1:2:3 w e, 'analysis.3.myhist.dat' u 1:2:3 w e, 'analysis.4.myhist.dat' u 1:2:3 w e, 'analysis.5.myhist.dat' u 1:2:3 w e, 'analysis.6.myhist.dat' u 1:2:3 w e, 'analysis.7.myhist.dat' u 1:2:3 w e, 'analysis.8.myhist.dat' u 1:2:3 w e, 'myhist.dat' u 1:2:3 w e +\endverbatim + +Performing a comparison between the results from each of these blocks of data is more involved than the analysis we performed when comparing the ensemble averages as we have +more data. The essential idea is the same, however, and, if you have time at the end of the session, you might like to see if you can write a script that determines what +fraction of the many averages we have calculated here lie within the confidence limits. + +\subsection trieste-2-biases Problem II: Dealing with rare events and simulation biases + +As is discussed in many of the tutorials that are provided here one of PLUMED's primary purposes is to use simulation biases to resolve the rare events problem. +When we use these technique we modify the Hamiltonian, \f$H(x,p)\f$, and add to it some bias, \f$V(x)\f$. The modified Hamiltonian thus becomes: +\f[ +H'(x,p) = H(x,p) + V(x) +\f] +and as such the values of the collective variables that we obtain from each of our trajectory frames are samples from the following distribution: +\f[ +P(s') = \frac{ \int \textrm{d}x \textrm{d}p \delta( s(x) - s') e^{-\frac{H(x,p)}{k_B T}}e^{-\frac{V(x)}{k_B T}} }{ \int \textrm{d}x\textrm{d}p e^{-\frac{H(x,p)}{k_B T}}e^{-\frac{V(x)}{k_B T}} } +\f] +Using a bias in this way is enormously helpful as we can ensure that we sample from a particular part of configuration space. +We appear to have sacrificed, however, the ability to extract estimates of ensemble averages for the unbiased distribution using the central +limit theorem. If we calculate the mean from a set of trajectory frames that are sampled from the distribution above we will get an estimate +for the ensemble average in this biased distribution. As we will see in this exercise, however, this is not really a problem as we can use +reweighting techniques to extract ensemble averages for the unbiased distribution. + +Lets begin by generating some new trajectory data. The following python script generates a set of random variables from a (truncated) normal +distribution with \f$\sigma=0.5\f$ and \f$\mu=0.6\f$. In other words, points are generated from the following probability distribution but if +they don't fall in a range between 0 and 1 they are discarded: + +\f[ +P(x) = \frac{1}{\sqrt{2\pi}\sigma} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) +\f] + +\verbatim +import random + +n = 0 +print("#! FIELDS time rand") +while True : + x = random.gauss( 0.6, 0.1732 ) + if (x>=0) & (x<=1) : + print(n, x ) + n = n + 1 + if n==10001 : break +\endverbatim + +Copy the script above to a file called gen-normal.py and then execute the python script within it using the command: + +\verbatim +python gen-normal.py > mynormal +\endverbatim + + +Use what you have learnt from the exercises above to estimate the ensemble average from these generated data points using PLUMED. If you want +you can use block averaging but it doenst matter if you do it by just considering all the data in the input file. What would you expect the ensemble average +to be and how does the estimate you get from PLUMED compare with the true value? + + +You should have found that the ensemble average that you get when you perform the experiment described in the previous paragraph +is different from the ensemble average that you get when you considered the uniform distribution. This makes sense as the distribution we sampled from +here is approximately: + +\f[ +P(x) = \frac{1}{0.03*\sqrt{2\pi}} \exp\left( - \frac{ x - 0.6}{ 2(0.03)^2} \right) +\f] + +This is different from the distribution we sampled from in the previous exercises. A question we might therefore ask is: can we extract the ensemble average +for the uniform distribution that we sampled in previous exercises by sampling from this different distribution? In the context of the experiment we are +performing here with the random variables this question perhaps feels somewhat absurd and pointless. In the context of molecular simulation, however, answering +this question is essential as our ability to extract the true, unbiased distribution from a simulation run with a bias relies on being able to perform this +sort of reweighting. + +The true value of the ensemble average, which we estimated when we analysed the data generated from the Gaussin using the python script above is given by: + +\f[ +\langle X \rangle = \frac{ \int_0^1 x e^{-V(x)} \textrm{d}x }{\int_0^1 e^{-V(x)} \textrm{d}x } \qquad \textrm{where} \qquad +V(x) = \frac{ (x - x)^2}{2\sigma^2} +\f] + +By contrast the ensemble average in the exercises involving the uniform distribution is given by: + +\f[ +\langle Y \rangle = \frac{ \int_0^1 y \textrm{d}y }{ \int_0^1 \textrm{d}y } = \frac{ \int_0^1 y e^{-V(y)}e^{+V(y)} \textrm{d}y }{\int_0^1 e^{-V(y)}e^{+V(y)} \textrm{d}y } +\f] + +We can use the final expression here to reweight the data that we sampled from the Gaussian. By doing so can thus extract ensemble averages for the +uniform distribution. The trick here is calculate the following weighted mean rather than the unweighted mean that we calculated previously: + +\f[ +\langle Y \rangle \approx \frac{\sum_i Y_i e^{+V(Y_i)}}{ \sum_i e^{+V(Y_i)} } +\f] + +where here the sums run over all the random variables, the \f$Y_i\f$s, that we sampled from the Gaussian distribution. If you used the script above the \f$V(Y_i)\f$ +values were output for you so you can calculate this estimate of the ensemble average for the unbiased distribution in this case using the following PLUMED input. + +\verbatim +UNITS NATURAL # This ensures that Boltzmann's constant is one +data: READ FILE=mynormal VALUES=rand +mm: RESTRAINT ARG=data AT=0.6 KAPPA=33.333 +rw: REWEIGHT_BIAS TEMP=1 +av: AVERAGE ARG=data STRIDE=1 LOGWEIGHTS=rw +PRINT ARG=av STRIDE=10000 FILE=colvar +\endverbatim + +Try to run this calculation now using: + +\verbatim +plumed driver --noatoms +\endverbatim + +and see how close you get to the ensemble average for the uniform distribution. Once you have done this try the following input, which allows you to compute the +reweighted histogram. + +\verbatim +UNITS NATURAL # This ensures that Boltzmann's constant is one +data: READ FILE=mynormal VALUES=rand +mm: RESTRAINT ARG=data AT=0.6 KAPPA=33.333 +rw: REWEIGHT_BIAS TEMP=1 +hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE LOGWEIGHTS=rw +DUMPGRID GRID=hh FILE=myhist.dat +\endverbatim + +Plot the histogram that you obtain from this calculation using the command: + +\verbatim +p 'myhist.dat' w l +\endverbatim + + +Now suppose that the data we generated for this exercise had come from an MD simulation. What would the unbiased Hamiltonian in this MD simulation +have looked like and what functional form would our simulation bias have taken? + + +\subsection triete-2-correlation Problem III: Dealing with correlated variables + +As a good scientist you have probably noticed that we have failed to provide error bars around our estimates for the ensemble average in previous sections. Furthermore, +you may have found that rather odd given that I showed you how to estimate the variance in the data in the very first exericse. This ignoring of the error bars has been +deliberate, however, as there is a further problem with the data that comes from molecular dynamics trajectories that we have to learn to deal with and that will affect our +ability to esimtate the error bars. This problem is connected to the fact that the central limit theorem only holds when we take a sum of uncorrelated and identical +random variables. Random variables that are generated from simulation trajectories will contain correlations simply because the system will most likely not diffuse +from one edge of CV space to the other during a single timestep. In other words, the random CV value that we calcuate from the \f$(i+1)\f$th frame of the trajectory +will be similar to the value obtained from the \f$i\f$th trajectory frame. This problem can be resolved, however, and to show how we will thus use the following python +script to generate some correlated model data: + +\verbatim +import random + +prev = 0.; +print("#! FIELDS time rand") +for i in range(0,10001): + new = 0.95*prev + 2*random.uniform(0,1) - 1 + print( i, new/2. + 0.5 ) + prev = new +\endverbatim + +Copy the python script above to a filled called correlated-data.py and then execute the script using the command: + +\verbatim +python correlated-data.py > mycorr +\endverbatim + +The autocorrelation function, \f$R(\tau)\f$ provides a simple method for determining whether or not there are correlations between the random variables, \f$X\f$, +in our time series. This function is defined as follows: + +\f[ +R(\tau) = \frac{ \langle (X_t - \langle X \rangle )(X_{t+\tau} - \langle X \rangle ) \rangle }{ \langle (\delta X)^2 \rangle } +\f] + +At present it is not possible to calculate this function using PLUMED. If we were to do so for the samples taken from the uniform distribution and the correlated +samples that were taken from the distribution the python script above we would find that the auto correlation functions for these random variables look +something like the figures shown below: + +\anchor triest-2-autocorrelation +\image html trieste-2-autocorrelation.png "The autocorrelation functions for the data that was generated by taking samples from a uniform distribution (left panel) and the autocorrelation function for the correlated data that was generated using the python script in this section (right panel)" + +To understand what these functions are telling us lets deal with the samples from the uniform distribution first. The autocorrelation function in this case has a +value of 1 when \f$\tau\f$ is equal to 0 and a value of 0 in all other cases. This function thus tells us that each random variable is perfectly correlated with +itself but that there are no correlations between the distributions we sampled adjacent variables from. In other words, each of the random variables we generate are +independent. If we now look at the autocorrelation function for the distribution that is sampled by the python script above we see that the autocorrelation function +slowly decays to zero. There are, therefore, correlations between the random variables that we generate that we must account for when we perform our analysis. + +We account for the correlations in the data when we do our analysis by performing a block analysis. To understand what precisely this involves we are going to perform +the analysis with PLUMED and explain the results that we get at each stage of the process. We wil begin by analysing the data we generated by sampling from the uniform +distribution using the following PLUMED input: + +\verbatim +data: READ FILE=mydata VALUES=rand +av5: AVERAGE ARG=data STRIDE=1 CLEAR=5 +PRINT ARG=av5 FILE=colvar5 STRIDE=5 +av10: AVERAGE ARG=data STRIDE=1 CLEAR=10 +PRINT ARG=av10 FILE=colvar10 STRIDE=10 +av15: AVERAGE ARG=data STRIDE=1 CLEAR=15 +PRINT ARG=av15 FILE=colvar15 STRIDE=15 +av20: AVERAGE ARG=data STRIDE=1 CLEAR=20 +PRINT ARG=av20 FILE=colvar20 STRIDE=20 +av25: AVERAGE ARG=data STRIDE=1 CLEAR=25 +PRINT ARG=av25 FILE=colvar25 STRIDE=25 +av30: AVERAGE ARG=data STRIDE=1 CLEAR=30 +PRINT ARG=av30 FILE=colvar30 STRIDE=30 +av35: AVERAGE ARG=data STRIDE=1 CLEAR=35 +PRINT ARG=av35 FILE=colvar35 STRIDE=35 +av40: AVERAGE ARG=data STRIDE=1 CLEAR=40 +PRINT ARG=av40 FILE=colvar40 STRIDE=40 +av45: AVERAGE ARG=data STRIDE=1 CLEAR=45 +PRINT ARG=av45 FILE=colvar45 STRIDE=45 +av50: AVERAGE ARG=data STRIDE=1 CLEAR=50 +PRINT ARG=av50 FILE=colvar50 STRIDE=50 +av55: AVERAGE ARG=data STRIDE=1 CLEAR=55 +PRINT ARG=av55 FILE=colvar55 STRIDE=55 +av60: AVERAGE ARG=data STRIDE=1 CLEAR=60 +PRINT ARG=av60 FILE=colvar60 STRIDE=60 +av65: AVERAGE ARG=data STRIDE=1 CLEAR=65 +PRINT ARG=av65 FILE=colvar65 STRIDE=65 +av70: AVERAGE ARG=data STRIDE=1 CLEAR=70 +PRINT ARG=av70 FILE=colvar70 STRIDE=70 +\endverbatim + +Copy the input above to a file called plumed.dat and run the calculation using the command: + +\verbatim +plumed driver --noatoms +\endverbatim + +This calculation should output 14 colvar files, which should then be further analysed using the following python script: + +\verbatim +import numpy as np +import math + +for i in range(1,15): + # Read in each colvar file + fmult = 5*i + dat = np.loadtxt( 'colvar' + str(fmult) ) + # Compute the square of all the average values in the colvar + sq = dat[1:,1]**2 + # Now compute the average over all the averages + mean = np.sum( dat[1:,1] ) / len( dat[1:,1] ) + # Compute the average of the squares of the individual averages + mean2 = np.sum( sq ) / len( sq ) + # Compute the population variance amongst the block averages + population_variance = mean2 - mean*mean + # Convert the population variance into a sample variance by multiplying by the bessel factor + sample_variance = ( len( sq ) / ( len(sq) - 1 ) )*population_variance + # Print out the length of the blocks, the final average taken over all blocks and the square + # root of the sample variance divided by the number of data points that this estimate was + # calcualted from. This last term is a measure of the eror bar + print( fmult, mean, math.sqrt( sample_variance / len(sq) ) ) +\endverbatim + +Copy this script to a file called block-average-script.py and then execute the contents using the command: + +\verbatim +python block-average-script.py > myaverages.dat +\endverbatim + +This will output a single file called myaverages.dat that can be plotted using gnuplot and the command: + +\verbatim +p 'myaverages.dat' u 1:2:3 w e, 'myaverages.dat' w l +\endverbatim + +The final result should be a graph like that shown in the left panel of the figure below. The figure on the right shows what you should obtain when you repeat the same +analysis on the correlated data that we generated using the python script in this section. + +\anchor triest-2-block-average +\image html trieste-2-block-averages.png "The ensemble average and an estimate of the associated error bars calculated for different lengths of block average. The left panel shows the output obtained when the uncorrelated samples taken from uniform distribution are analysed in this way. The right panel shows the output obtained when the correlated samples that are generated using the python script in this section are analysed." + + +The output that you obtain from these two calculations is explained in the video at: +Before wathcing this explanation though take some time to note down the differences between the two graphs above. Try to look through the scripts +above and to understand what is being done in the PLUMED inputs and the python scripts above so as to work out what the data in these two figures +are telling you. + + +\subsection triete-2-alltogether Putting it all together + +In this final exercise we are going to try to combine everything we have seen in the previous sections. We are going to sample from the distribution +that was introduced in \ref trieste-2-biases. This time though we are not going to generate random variables from the Gaussian directly. We are instead going to +use Monte Carlo sampling. This sampling method is going to give us correlated data so we will need to use ideas from \ref triete-2-correlation in order to +get a proper estimate of the error bars. Furthermore, we are not going to try to extract ensemble averages that tell us about the distribution we sampled from. +Instead we are going to reweight using the ideas from \ref trieste-2-biases and extract the unbiased distribution. + +The first step in doing all this is, as always, to generate some data. The python script below will generate this data: + +\verbatim +import math +import random + +# Energy given by a harmonic potential centered at 0.6 +# This ensures that our data represent samples from a Gaussian with +# mean 0.6 and variance 0.1732 +def calc_eng( x ) : + return 0.5*33.333*pow((x-0.6),2) + +x = 0.5 +eng = calc_eng( x ) +print("#! FIELDS time rand") +for i in range(0,100010): + # Generate new random position from old position + newx = x + 0.1*random.uniform(0,1) - 0.05 + # Apply periodic boundary conditions + if( newx > 1.0 ) : newx = newx - 1.0 + if( newx < 0.0 ) : newx = newx + 1.0 + # Monte Carlo criterion + new_eng = calc_eng( newx ) + if( new_eng mcdata +\endverbatim + +This will run a short Monte Carlo simulation that generates (time-correlated) random data from a (roughly) Gaussian distribution by attempting +random translational moves of up to 0.1 units. An autocorrelation function that was calculated +using data generated using this script is shown below. You can clearly see from this figure that there are correlations between +the adjacent data points in the time series and that we have to do block averaging as a result. + +\anchor triest-2-mc-autocorr +\image html trieste-2-mc-autocorrelation.png "The autocorrelation function for the data that was generated using the Monte Carlo sampler in the script above" + +We can use the following PLUMED input to calculate block averages for the unbiased histogram from the data we generated: + +\verbatim +UNITS NATURAL # This ensures that Boltzmann's constant is one +data: READ FILE=mcdata VALUES=rand +mm: READ FILE=mcdata VALUES=cv.* +rw: REWEIGHT_BIAS TEMP=1 +hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE LOGWEIGHTS=rw CLEAR=500 +DUMPGRID GRID=hh FILE=myhist.dat STRIDE=500 +\endverbatim + +Notice that this input instructs PLUMED to calculate block averages for the histogram from each set of 500 consecutive frames in the trajectory. +I have worked out that this is an appropriate length of time to average over by performing the analysis described in \ref triete-2-correlation. +We will come back to how precisely I did this momentarily, however. For the time being though you can execute this input using: + +\verbatim +plumed driver --noatoms +\endverbatim + +Executing this command will generate a number of files containing histograms. The following python script will merge all this data and calculate +the final histogram together with the appropriate error bars. + +\verbatim +import math +import glob +import numpy as np + +# Here are some numbers you will need to change if you run this script on grids generated in different contexts +nquantities = 1 # Number of quanities that have been evaluated on the grid +grid_dimension = 1 # Number of collective variables that you provided using the ARG keyword +filename = "myhist.dat" # The name you specified the data to output to in the DUMPGRID command + +# Function to read in histogram data and normalization +def readhistogram( fname ) : + # Read in the histogram data + data = np.loadtxt( fname ) + with open( filename, "r" ) as myfile : + for line in myfile : + if line.startswith("#! SET normalisation") : norm = line.split()[3] + return float(norm), data + + +# Read in the grid file header to work out what fields we have +with open( filename, "r" ) as myfile : + for line in myfile : + if line.startswith("#! FIELDS") : fieldnames = line.split() + +# Check if derivatives have been output in the grid by investigating the header +nextg = 1 +if len(fieldnames)>(2+grid_dimension+nquantities) : + nextg = 1 + grid_dimension + assert len(fieldnames)==(2+grid_dimension + nquantities*nextg) + +# Read in a grid +norm, griddata = readhistogram( filename ) +norm2 = norm*norm +# Create two np array that will be used to accumulate the average grid and the average grid squared +average = np.zeros((nquantities, len(griddata[:,0]))) +average_sq = np.zeros((nquantities, len(griddata[:,0]))) +for i in range(0,nquantities) : + average[i,:] = norm*griddata[:,nquantities+i*nextg] + average_sq[i,:] = norm*griddata[:,nquantities+i*nextg]*griddata[:,nquantities+i*nextg] + +# Now sum the grids from all all the analysis files you have +for filen in glob.glob( "analysis.*." + filename ) : + tnorm, newgrid = readhistogram( filen ) + norm = norm + tnorm + norm2 = norm2 + tnorm*tnorm + for i in range(0,nquantities) : + average[i,:] = average[i,:] + tnorm*newgrid[:,nquantities+i*nextg] + average_sq[i,:] = average_sq[i,:] + tnorm*newgrid[:,nquantities+i*nextg]*newgrid[:,nquantities+i*nextg] + +# Compte the final average grid +average = average / norm +# Compute the sample variance for all grid points +variance = (average_sq / norm) - average*average +# Now multiply by bessel correction to unbias the sample variance and get the population variance +variance = ( norm /(norm-(norm2/norm)) ) * variance +# And lastly divide by number of grids and square root to get an error bar for each grid point +ngrid = 1 + len( glob.glob( "analysis.*." + filename ) ) +errors = np.sqrt( variance / ngrid ) +# Calcualte average error over grid and output in header +for i in range(0,nquantities) : + mean_error = sum(errors[i,:]) / len(errors[i,:]) + print("# Average error for " + str(i+1) + "th averaged function on grid equals ", mean_error ) + +# Output the final average grid +for i in range(0,len(griddata[:,0])) : + for j in range(0,grid_dimension) : print( griddata[i,j], end=" " ) + for j in range(0,nquantities) : print( average[j,i], errors[j,i], end=" " ) + print() +\endverbatim + +Copy this script to a file called merge-histograms.py and then run its contents by executing the command: + +\verbatim +python merge-histograms.py > final-histogram.dat +\endverbatim + +This will output the final average histogram together with some error bars. You can plot this function using gnuplot by executing the command: + +\verbatim +p 'final-histogram.dat' u 1:2:3 w e, '' u 1:2 w l +\endverbatim + + +Where are the error bars in our estimate of the histogram the largest? Why are the errors large in these regions? + + +Notice that the file output by the script above also contains information on the average error per grid point in the header. The quantity that +is calculated here is: + +\f[ +\textrm{average error} = \frac{1}{N} \sum_{i=1}^N \sigma_i +\f] + +In this expression \f$N\f$ is the total number of grid points at which the function was evaluated and \f$\sigma_i\f$ is the error bar for the estimate +of the function that was calculated for the \f$i\f$th grid point. The average error is a useful quantity as we can plot it and thus check that our blocks +are large enough to correct for the correlation between our data points. In other words, we can use this quantity in the same way that we used the +error around the average in \ref triete-2-correlation. A plot of the average error versus the size of the blocks that were used in for the block averaging +is shown below. This figure demonstrates that a block average length of 500 is certainly long enough to correct for the problems due to the correlations +in the values produced at different times: + +\anchor triest-2-ebdata +\image html trieste-2-histogram-errors.png "The size of the error bars calculated with different lengths of block average. From this figure it is clear that taking block averages over 500 data points allows us to account for the correlations in the data and extract reasonable error bars." + + +If you have sufficient time try to see if you can reproduce this plot using the data you generated + + +\section trieste-2-extensions Extensions + +The exercises in the previous sections have shown you how we can calculate ensemble averages from trajectory data. You should have seen that performing block averaging +is vital as this technique allows us to deal with the artefacts that we get because of the correlations in the data that we obtain from simulation trajectories. +What we have seen is that when this technique is used correctly we get reasonable error bars. If block averaging is not performed, however, we can underestimate the +errors in our data and thus express a false confidence in the reliability of our simulation results. + +The next step for you will be to use this technique when analysing the data from your own simulations. + +*/ + +link: @subpage trieste-2 + +description: Averaging, histograms and block averaging + From 4c10df8c5775e816468a75c7e1674da4b880ca10 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Tue, 2 May 2017 11:42:45 +0200 Subject: [PATCH 41/62] Renamed txt for Trieste-2 @gtribello in this manner it should appear at the beginning of the list --- user-doc/tutorials/{trieste-2.txt => a-trieste-2.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename user-doc/tutorials/{trieste-2.txt => a-trieste-2.txt} (100%) diff --git a/user-doc/tutorials/trieste-2.txt b/user-doc/tutorials/a-trieste-2.txt similarity index 100% rename from user-doc/tutorials/trieste-2.txt rename to user-doc/tutorials/a-trieste-2.txt From 68e90cb69ca7362b684e7fc7dbafc6b371176b80 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 21 Apr 2017 17:25:36 +0200 Subject: [PATCH 42/62] Draft Trieste tutorial 1 [makedoc] --- user-doc/tutorials/a-trieste-1.txt | 556 ++ user-doc/tutorials/trieste-1/ref.pdb | 6586 ++++++++++++++++++ user-doc/tutorials/trieste-1/traj-broken.xtc | Bin 0 -> 117620 bytes user-doc/tutorials/trieste-1/traj-whole.xtc | Bin 0 -> 116036 bytes 4 files changed, 7142 insertions(+) create mode 100644 user-doc/tutorials/a-trieste-1.txt create mode 100644 user-doc/tutorials/trieste-1/ref.pdb create mode 100644 user-doc/tutorials/trieste-1/traj-broken.xtc create mode 100644 user-doc/tutorials/trieste-1/traj-whole.xtc diff --git a/user-doc/tutorials/a-trieste-1.txt b/user-doc/tutorials/a-trieste-1.txt new file mode 100644 index 0000000000..db7454ac05 --- /dev/null +++ b/user-doc/tutorials/a-trieste-1.txt @@ -0,0 +1,556 @@ +/** +\page trieste-1 Trieste tutorial: Analyzing trajectories using PLUMED + +\section trieste-1-aims Aims + +The aim of this tutorial is to introduce the users to the PLUMED syntax. We will go through the writing of +simple collective variable and we will use them to analyze existing trajectories. + +\section trieste-1-objectives Objectives + +Once this tutorial is completed students will be able to: + +- Write a simple PLUMED input file and use it with the PLUMED \ref driver to analyse a trajectory. +- Use the \ref GROUP keyword to make the input file compact and easy to read and to quickly build complex atom groups. +- Print collective variables such as distances + (\ref DISTANCE), torsional angles (\ref TORSION), gyration radius (\ref GYRATION), + and coordination numbers (\ref COORDINATION) using the \ref PRINT action. +- Computing the geometric center of a group of atoms using \ref CENTER. +- Know how to take care of periodic boundary conditions within PLUMED using \ref WHOLEMOLECULES and \ref WRAPAROUND, + and be able to verify the result with \ref DUMPATOMS. +- Extract from a trajectory snapshots satisfying specific conditions using \ref UPDATE_IF. + +\section trieste-1-resources Resources + +The \tarball{trieste-1} for this project contains the following files: +- ref.pdb : A PDB file with a RNA duplex solvated in a water box and a Mg ion. +- traj-whole.xtc: A trajectory for the same system in GROMACS xtc format. To make the exercise easier, RNA duplex has been made whole already. +- traj-broken.xtc: The same trajectory as it was originally produced by GROMACS. Here the RNA duplex is broken and should be fixed. + +\section trieste-1-intro Introduction + +This tutorial asks you to compute a variety of different collective variables using PLUMED for a particular trajectory and to compare the files and graphs that you obtain with the correct ones that are shown online. Compared to some of the other tutorials that are available here this tutorial contains considerably less guidance so in doing this tutorial you will have to +learn how to consult the manual. If you would like a more guided introduction to PLUMED it might be better to start with the tutorials \ref belfast-1 or \ref lugano-1. +Also notice that, whereas this tutorial was tested using a pre-release +version of PLUMED 2.4, it should be completely feasible using +PLUMED 2.3. + +\section trieste-1-cl Using PLUMED from the command line + +As we will see later, PLUMED provides a library that can be combined with multiple MD codes. However, +in this tutorial we will only use PLUMED to analyze trajectories that have been produced already. +Once PLUMED is installed you can run a `plumed` executable that can be used for multiple purposes: + +\verbatim +> plumed --help +\endverbatim + +Here we will use the \ref driver tool, that allows you to process an already existing trajectory. + +\verbatim +> plumed driver --help +\endverbatim + +What we will need is: +- A trajectory to be analyzed (provided). +- A PLUMED input file (you do it!). + +The syntax of the PLUMED input file is the same that we will use later to run enhanced sampling simulations, +so all the things that you will learn now will be useful later when you will run PLUMED coupled to an MD code. +In the following we are going to see how to write an input file for PLUMED. + +\section trieste-1-structure The structure of a PLUMED input file + +The main goal of PLUMED is to compute collective variables, which are complex descriptors than can be used +to analyze a conformational change or a chemical reaction. This can be done either on the fly, that is during +molecular dynamics, or a posteriori, using PLUMED as a post-processing tool. In both cases +one should create an input file with a specific PLUMED syntax. A sample input file is below: + +\plumedfile +# Compute distance between atoms 1 and 10. +# Atoms are ordered as in the trajectory files and their numbering starts from 1. +# The distance is called "d" for future reference. +d: DISTANCE ATOMS=1,10 + +# Create a virtual atom in the center between atoms 20 and 30. +# The virtual atom only exists within PLUMED and is called "center" for future reference. +center: CENTER ATOMS=20,30 + +# Compute the torsional angle between atoms 1, 10, 20, and center. +# Notice that virtual atoms can be used as real atoms here. +# The angle is called "phi" for future reference. +phi: TORSION ATOMS=1,10,20,center + +# Compute some function of previously computed variables. +# In this case we compute the cosine of angle phi and we call it "d2" +d2: MATHEVAL ... + ARG=phi FUNC=cos(x) + PERIODIC=NO +... +# The previous command has been split in multiple lines. +# It could have been equivalently written in a single line: +# d2: MATHEVAL ARG=phi FUNC=cos(x) PERIODIC=NO + +# Print d and d2 every 10 step on a file named "COLVAR1". +PRINT ARG=d,d2 STRIDE=10 FILE=COLVAR1 + +# Print phi on another file names "COLVAR2" every 100 steps. +PRINT ARG=phi STRIDE=100 FILE=COLVAR2 +\endplumedfile + +\note If you are a VIM user, you might find convenient configuring PLUMED syntax files, see \ref VimSyntax. + Syntax highlighting is particularly useful for beginners since it allows you to identify simple + mistakes without the need to run PLUMED. In addition, VIM has a full dictionary of available + keywords and can help you autocompleting your commands. + +In the input file above, each line defines a so-called action. An action could either compute a distance, +or the center between two or more atoms, or print some value on a file. Each action supports a number of keywords, +whose value is specified. Action names are highlighted in green and, clicking on them, you can go to the +corresponding page in the manual that contains a detailed description for each keyword. +Actions that support the keyword `STRIDE` are those that determine how frequently things are to be done. +Notice that the default value for `STRIDE` is always 1. In the example above, omitting `STRIDE` keywords +the corresponding COLVAR files would have been written for every frame of the analyzed trajectory. +All the other actions in the example above do not +support the `STRIDE` keyword and are only calculated when requested. That is, `d` and `d2` will be computed +every 10 frames, and `phi` every 100 frames. +In short, you can think that for every snapshot in the trajectory that you are analyzing PLUMED +is going to execute all the listed actions, though some of them are optimized out when `STRIDE` is different from 1. + +Also notice that PLUMED works using kJ/nm/ps as energy/length/time units. This can be personalized using \ref UNITS, +but we will here stay with default values. + +Variables should be given a name (in the example above, `d`, `phi`, and `d2`), which is +then used to refer to these variables. +Instead of `a: DISTANCE ATOMS=1,2` you might equivalently use `DISTANCE ATOMS=1,2 LABEL=a`. +Lists of atoms should be provided as +comma separated numbers, with no space. Virtual atoms can be created and assigned a name for later use. + +You can find more information on the PLUMED syntax +at \ref Syntax page of the manual. The complete documentation for all the supported +collective variables can be found at the \ref colvarintro page. + +To analyze the trajectory provided here, you should: +- Create a PLUMED input file with a text editor (let us call it `plumed.dat`) similar to the one above. +- Run the command `plumed driver --mf_xtc traj.xtc --plumed plumed.dat`. + +Here `traj.xtc` is the trajectory that you want to analyze. Notice that \ref driver +can read multpliple file formats using embedded molfile plugins from VMD (that's where the `mf` letters come from). + +Notice that you can also visualize trajectories with VMD directly. Trajectory `traj.xtc` can be visualized with +the command `vmd ref.pdb traj-whole.xtc`. + +In the following we will make practice with computing and printing collective variables. + +\subsection trieste-1-ex-1 Exercize 1: Computing and printing collective variables + +Analyze the `traj-whole.xtc` trajectory and produce a colvar file with the following collective variables. + +- The gyration radius of the solute RNA molecule (\ref GYRATION). Look in the `ref.pdb` file + which are the atoms that are part of RNA (search for the first occurrence of a water molecule, residue name `SOL`). + Remember that you don't need to list all the atoms: instead of `ATOMS=1,2,3,4,5` you can write `ATOMS=1-5`. +- The torsional angle (\ref TORSION) corresponding to the glycosidic chi angle \f$\chi\f$ of the first nucleotide. + Since this nucleotide is a purine (guanine), the proper atoms to compute the torsion are O4' C1 N9 C4. Find their serial number + in the `ref.pdb` file or learn how to select a special angle reading the \ref MOLINFO documentation. +- The total number of contacts (\ref COORDINATION) between all RNA atoms and all water oxygens. + For \ref COORDINATION, set reference distance `R_0` to 2.5 A (be careful with units!!). + Try to be smart in selecting the water oxygens without listing all of them explicitly. +- Same as before but against water hydrogen. + Also in this case you should be smart to select water hydrogens. Documentation of \ref GROUP might help. +- Distance between the Mg ion and the geometric center of the RNA duplex (use \ref CENTER and \ref DISTANCE). + +Notice that some of the atom selections can be made in a easier manner by using the \ref MOLINFO keyword with +a proper reference PDB file. Also read carefully the \ref Group page before starting. +Here you can find a sample `plumed.dat` file that you can use as a template. +Whenever you see an highlighted \highlight{FILL} string, this is a string that you should replace. + +\plumedfile +# First load information about the molecule. +MOLINFO __FILL__ + +# Define some group that will make the rest of the input more readable +# Here are the atoms belonging to RNA. +rna: GROUP ATOMS=1-258 +# This is the Mg ion. A group with atom is also useful! +mg: GROUP ATOMS=6580 +# This group should contain all the atoms belonging to water molecules. +wat: GROUP ATOMS=__FILL__ +# Select water oxygens only: +owat: GROUP __FILL__ +# Select water hydrogens only: +hwat: GROUP __FILL__ + +# Compute gyration radius: +r: GYRATION ATOMS=__FILL__ +# Compute the Chi torsional angle: +c: TORSION ATOMS=__FILL__ +# Compute coordination of RNA with water oxygens +co: COORDINATION GROUPA=rna GROUPB=owat R_0=__FILL__ +# Compute coordination of RNA with water hydrogens +ch: COORDINATION GROUPA=rna GROUPB=hwat __FILL__ + +# Compute the geometric center of the RNA molecule: +ce: CENTER ATOMS=__FILL__ +# Compute the distance between the Mg ion and the RNA center: +d: DISTANCE ATOMS=__FILL__ + +# Print the collective variables on COLVAR file +# No STRIDE means "print for every step" +PRINT ARG=r,c,co,ch,d FILE=COLVAR +\endplumedfile + +Once your `plumed.dat` file is complete, you can use it with the following command +\verbatim +> plumed driver --plumed plumed.dat --mf_xtc whole.xtc +\endverbatim + +Scroll in your terminal to read the PLUMED log. As you can see, +PLUMED gives a lot of feedbacks about the input that he is reading. There's the +place where you can check if PLUMED understood correctly your input. + +The command above will create a file `COLVAR` like this one: +\verbatim +#! FIELDS time r c co ch d +#! SET min_c -pi +#! SET max_c pi + 0.000000 0.788694 -2.963150 207.795793 502.029431 0.595611 + 1.000000 0.804101 -2.717302 208.021688 499.770382 0.951945 + 2.000000 0.788769 -2.939333 208.347867 500.555764 1.014850 + 3.000000 0.790232 -2.940726 211.274315 514.748191 1.249502 + 4.000000 0.796395 3.050949 212.352810 507.888856 2.270682 +\endverbatim +Notice that the first line informs you about the content of each column and +the second and third lines tell you that variable `c` (the \f$\chi\f$ torsion) is +defined between \f$-pi\f$ and \f$+pi\f$. + +__In case you obtain different numbers, check your input, you might have made some mistake!__ + +This file can then be shown with `gnuplot` +\verbatim +gnuplot> p "COLVAR" u 1:2, "" u 1:3 +\endverbatim + +As a final note, look at what happens if you run the exercise twice. The second time, PLUMED +will *back up* the previously produced file so as not to overwrite it. +You can also *concatenate* your files by using the action \ref RESTART at the beginning +of your input file. + +\hidden{Combining collective variables} + + +In this first exercize we only computed simple functions of the atomic coordinates. +PLUMED is very flexible and allows you to also combine these functions to create more complicated +variables. These variables can be useful when you want to describe a complex conformational change. +PLUMED implements a number of functions that can be used to this aim that are described in the +page \ref Function. Look at the following example: +\plumedfile +# Distance between atoms 1 and 2: +d1: DISTANCE ATOMS=1,2 +# Distance between atoms 1 and 3: +d2: DISTANCE ATOMS=1,3 +# Distance between atoms 1 and 4: +d3: DISTANCE ATOMS=1,4 + +# Compute the sum of the squares of those three distances: +c: COMBINE ARG=d1,d2,d3 POWERS=2 PERIODIC=NO + +# Sort the three distances: +s: SORT ARG=d1,d2,d3 +# Notice that SORT creates a compund object with three components: +# s.1: the smallest distance +# s.2: the middle distance +# s.3: the largest distance + +p: MATHEVAL ARG=d1,d2,d3 FUNC=x*y*z PERIODIC=NO + +# Print the sum of the squares and the largest among the three distances: +PRINT FILE=COLVAR ARG=c,s.3 +\endplumedfile + +In case you have many distances to combine you can also use regular expressions to select them +using `ARG=(d.)`, see \ref Regex. + +Notice for many functions you should say to PLUMED if the function is periodic. +See \ref Function for a detailed explanation of how to choose this keyword. + +You might think that it is easier to combine the variables after you have written them +already, using e.g. and awk or python script. That's fine if you are analyzing a trajectory. +However, as we will learn later, computing variables within PLUMED you will be able to +add bias potentials on those combinations, influencing their dynamics. Actually, you could implement +any arbitrarily complex collective variable using just \ref DISTANCE and \ref MATHEVAL! + +\subsection trieste-1-ex-1b Exercize 1b: Combining collective variables + +As an optional exercize, create a file with the following quantities: +- The sum of the distances between Mg and each of the phosphorous atoms. +- The distance between Mg and the closest phosphorous atom. + +Notice that the serial numbers of the phosphorous atoms can be easily extracted using the following command +\verbatim +grep ATOM ref.pdb | grep " P " | awk '{print $2}' +\endverbatim + +Here's a template input file to be completed by you. +\plumedfile +# First load information about the molecule. +MOLINFO __FILL__ + +# Define some group that will make the rest of the input more readable +mg: GROUP ATOMS=6580 # a group with one atom is also useful! + +# Distances between Mg and phosphorous atoms: +d1: DISTANCE ATOMS=mg,33 +d2: DISTANCE __FILL__ +__FILL__ +d6: DISTANCE __FILL__ + +# Compute the sum of these distances +c: COMBINE __FILL__ + +# Compute the distance between Mg and the closest phosphorous atom +s: SORT __FILL__ + +# Print the required variables +PRINT FILE=COLVAR __FILL__ + +\endplumedfile + +Notice that using the collective variable \ref DISTANCES you might be able to do the same with a significantly simpler input file! + +The resulting `COLVAR` file should look like this one: + +\verbatim +#! FIELDS time c s.1 + 0.000000 6.655622 0.768704 + 1.000000 7.264049 0.379416 + 2.000000 7.876489 0.817820 + 3.000000 8.230621 0.380191 + 4.000000 13.708759 2.046935 +\endverbatim + +\endhidden + +\section trieste-1-pbc Solving periodic-boundary conditions issues + +While running PLUMED can also dump the coordinate of the internally stored atoms using \ref DUMPATOMS. +This might seem useless (coordinates are already contained in the original trajectory) but can +be used in the following cases: +- To dump coordinates of virtual atoms that only exist within PLUMED (e.g. a \ref CENTER). +- To dump snapshots of our molecule conditioned to some value of some collective variable (see \ref UPDATE_IF). +- To dump coordinates of atoms that have been moved by PLUMED. + +The last point is perhaps the most surpising one. Some of the PLUMED actions can indeed move the stored atoms to +positions better suitable for the calculation of collective variables. + +The previous exercize was done on a trajectory where the RNA was already whole. For the next exercize you will use the +`traj-broken.xtc` file instead, which is a real trajectory produced by GROMACS. Open it with VMD to understand +what we mean with broken +\verbatim +> vmd ref.pdb traj-broken.xtc +\endverbatim +Select `Graphics`, then `Representations`, then type `nucleic` in the box `Selected Atoms`. +You will see that your RNA duplex is not whole. +This is not a problem during MD because of periodic boundary conditions. However, it is difficult +to analyze this trajectory. In addition, some collective variables that you might want to compute +could require the molecules to be whole (an example of such variables is \ref RMSD). + +You might think that there are alternative programs that can be used to reconstruct PBCs correctly +in your trajectory *before* analyzing it. However, you should keep in mind that if you need to +compute CVs on the fly to add a bias potential on those (as we will to in the next tutorials) you will +have to learn how to reconstruct PBCs within PLUMED. + + +\subsection trieste-1-ex-2 Exercise 2: Solving PBC issues and dump atomic coordinates + +Analyze the provided trajectory `traj-broken.xtc` and use the \ref DUMPATOMS action to produce new trajectories in `gro` format that contain: +- The RNA duplex made whole (not broken by periodic boundary conditions). You should read carefully the documentation of \ref WHOLEMOLECULES. +- The whole RNA duplex aligned to a provided template (structure `reference.pdb`). See \ref FIT_TO_TEMPLATE, using `TYPE=OPTIMAL`. + Notice that you should provide to \ref FIT_TO_TEMPLATE a pdb file with only the atoms that you wish to align. + Use the `ref.pdb` file as a starting point and remove the lines non containing RNA atoms. + More details on PDB files in PLUMED can be found \ref pdbreader "here". +- The whole RNA duplex and Mg ion, but only including the snapshots where Mg is at a distance equal to at most 3 A from phosphorous atom + of residue 2. Search for the serial number of the proper phosphorous atom in the PDB file and use the \ref UPDATE_IF action + to select the frames. +- The whole RNA duplex plus water molecules and mg ion wrapped around the center of the duplex. Compute first the center of the duplex with \ref CENTER then + wrap the molecules with \ref WRAPAROUND. Make sure that individual water molecules are not broken after the move! + +Here you can find a template input file to be completed by you. +\plumedfile +# First load information about the molecule. +MOLINFO __FILL__ + +# Define here the groups that you need. +# Same as in the previous exercise. +rna: GROUP ATOMS=__FILL__ +mg: GROUP ATOMS=__FILL__ +wat: GROUP ATOMS=__FILL__ + +# Make RNA duplex whole. +WHOLEMOLECULES __FILL__ + +# Dump first trajectory in gro format. +# Notice that PLUMED understands the format based on the file extension +DUMPATOMS ATOMS=rna FILE=rna-whole.gro + +# Align RNA duplex to a reference structure +# This should not be the ref.pdb file but a new file with only RNA atoms. +FIT_TO_TEMPLATE REFERENCE=__FILL__ TYPE=OPTIMAL +# Notice that before using FIT_TO_TEMPLATE we used WHOLEMOLECULES to make RNA whole +# This is necessary otherwise you would align a broken molecule! + +# Dump the aligned RNA on a separate file +DUMPATOMS ATOMS=rna FILE=rna-aligned.gro + +# Compute the distance between the Mg and the Phosphorous from residue 2 +d: DISTANCE ATOMS=mg,__FILL__ ## put the serial number of the correct phosphorous here + +# here we only dump frames conditioned to the value of d +UPDATE_IF ARG=d __FILL__ +DUMPATOMS ATOMS=rna,mg FILE=rna-select.gro +UPDATE_IF ARG=d # this command is required to close the UPDATE_IF above + +# compute the center of the RNA molecule +center: CENTER ATOMS=rna + +# Wrap atoms correctly +WRAPAROUND ATOMS=mg AROUND=__FILL__ +WRAPAROUND ATOMS=water AROUND=center __FILL__ # anything missing here? + +# Dump the last trajectory +DUMPATOMS ATOMS=rna,wat,mg FILE=rna-wrap.gro +\endplumedfile + +After you have prepared a proper `plumed.dat` file, you can use it with the following command +\verbatim +> plumed driver --plumed plumed.dat --mf_xtc broken.xtc +\endverbatim + +Visualize the resulting trajectories using VMD. Since the `gro` files already contain atom names, +you do not need to load the `pdb` file first. For instance, the first trajectory can be shown with + +\verbatim +> vmd rna-whole.gro +\endverbatim + +\highlight{TODO: I should perhaps add reference plots} + +\hidden{Mastering WHOLEMOLECULES} + +If you just simulate a single solute molecule in water it is easy to understand +how to pick the right options for \ref WHOLEMOLECULES. However, if you have multiple +molecules it can be rather tricky. In the example above, we used \ref WHOLEMOLECULES +on the RNA molecule which is actually a duplex, that is two separated chains. This +was correct for the following reasons: +- the two chains are kept together by hydrogen bonds, and +- the last atom of the first chain is always close to the first atom of the second chain. + +In case the two molecules can separate from each other this would be rather problematic. + +We will now see what happens when using \ref WHOLEMOLECULES on multiple molecules *incorrectly*. + +\subsection trieste-1-ex-2b Exercize 2b: Mistakes with WHOLEMOLECULES + +Prepare a PLUMED input file that makes all the water molecules whole. Use the following template +\plumedfile +# First load information about the molecule. +MOLINFO __FILL__ + +# Define here the groups that you need +rna: GROUP ATOMS=__FILL__ +mg: GROUP ATOMS=__FILL__ +wat: GROUP ATOMS=__FILL__ + +# Make RNA whole +WHOLEMOLECULES ENTITY0=rna + +# Now make water whole as if it was a single molecule +WHOLEMOLECULES ENTITY0=wat + +# And dump the resulting trajectory +DUMPATOMS ATOMS=rna,wat,mg FILE=wrong.gro +\endplumedfile + +Now look at the resulting file with `vmd wrong.gro`. Can you understand which is the problem? + +The important take-home message here is that when you want to reconstruct periodic boundary conditions +correctly in systems with multiple molecules you should be careful and always verify with \ref DUMPATOMS +that the system is doing what you expect. + +\endhidden + +\hidden{Mastering FIT_TO_TEMPLATE} + +In an exercize above we used \ref FIT_TO_TEMPLATE. This action uses as a reference a PDB file +which typically contains a subset of atoms (those that are fitted). However, +when you apply \ref FIT_TO_TEMPLATE with `TYPE=OPTIMAL`, the whole system +is translated and rotated. +The whole system here means all atoms plus the vectors defining the periodic box. + +\subsection trieste-1-ex-2c Exercize 2c: Mastering FIT_TO_TEMPLATE + +Check how the periodic box rotates when using \ref FIT_TO_TEMPLATE. +Use the following template +\plumedfile +# First load information about the molecule. +MOLINFO __FILL__ + +# Define here the groups that you need +rna: GROUP ATOMS=__FILL__ +mg: GROUP ATOMS=__FILL__ +wat: GROUP ATOMS=__FILL__ + +# Make RNA whole +WHOLEMOLECULES ENTITY0=rna + +# Here's a compund variable with the box vectors +# computed before aligning RNA +cell_before: CELL + +# Now we align RNA +FIT_TO_TEMPLATE __FILL__ TYPE=OPTIMAL + +# Here's a compund variable with the box vectors +# computed after aligning RNA +cell_after: CELL +PRINT ARG=cell_before.* FILE=CELL_BEFORE +PRINT ARG=cell_after.* FILE=CELL_AFTER +\endplumedfile + +You should obtains files like the ones reported below. + +`CELL_BEFORE` should be +\verbatim +#! FIELDS time cell_before.ax cell_before.ay cell_before.az cell_before.bx cell_before.by cell_before.bz cell_before.cx cell_before.cy cell_before.cz + 0.000000 4.533710 0.000000 0.000000 0.000000 4.533710 0.000000 2.266860 2.266860 3.205821 + 1.000000 4.533710 0.000000 0.000000 0.000000 4.533710 0.000000 2.266860 2.266860 3.205821 + 2.000000 4.533710 0.000000 0.000000 0.000000 4.533710 0.000000 2.266860 2.266860 3.205821 + 3.000000 4.533710 0.000000 0.000000 0.000000 4.533710 0.000000 2.266860 2.266860 3.205821 + 4.000000 4.533710 0.000000 0.000000 0.000000 4.533710 0.000000 2.266860 2.266860 3.205821 +\endverbatim + +`CELL_AFTER` should be +\verbatim +#! FIELDS time cell_after.ax cell_after.ay cell_after.az cell_after.bx cell_after.by cell_after.bz cell_after.cx cell_after.cy cell_after.cz + 0.000000 4.532612 -0.054817 0.083377 0.053329 4.532675 0.080890 2.233341 2.182443 3.286902 + 1.000000 -0.648906 -2.868906 -3.450047 2.674989 2.551396 -2.624755 3.560387 -1.863791 -2.098695 + 2.000000 -3.817881 -1.642277 -1.811420 2.010018 -4.020529 -0.591352 -1.888348 -3.751409 1.707531 + 3.000000 2.239255 1.142120 -3.773040 0.048153 -4.346863 -1.287241 -1.643585 -1.181143 -4.056861 + 4.000000 2.081897 3.894322 1.026881 -2.781014 2.226201 -2.804375 -2.409439 3.525462 1.523258 +\endverbatim + +As you can see, the generating vectors of the periodic lattice *before* fitting are constant. +On the other hand, *after* fitting these vectors change so as to keep RNA correctly aligned to its reference structure. + +Later on you will learn how to add a bias potential on a give collective variable. In principle, you could +also add a \ref RESTRAINT ro the `cell_after.*` variables of the last example. This would allow you to +force your molecule to a specific orientation. + +\endhidden + + +*/ + +link: @subpage trieste-1 + +description: This tutorial explains how to use PLUMED to analyze trajectories + +additional-files: trieste-1 diff --git a/user-doc/tutorials/trieste-1/ref.pdb b/user-doc/tutorials/trieste-1/ref.pdb new file mode 100644 index 0000000000..901461510f --- /dev/null +++ b/user-doc/tutorials/trieste-1/ref.pdb @@ -0,0 +1,6586 @@ +TITLE Protein in water +REMARK THIS IS A SIMULATION BOX +CRYST1 45.337 45.337 45.337 60.00 60.00 90.00 P 1 1 +MODEL 1 +ATOM 1 H5T RG5 1 37.870 34.810 23.520 1.00 0.00 +ATOM 2 O5' RG5 1 38.340 35.010 22.710 1.00 0.00 +ATOM 3 C5' RG5 1 37.540 34.840 21.560 1.00 0.00 +ATOM 4 1H5' RG5 1 36.500 35.150 21.670 1.00 0.00 +ATOM 5 2H5' RG5 1 37.520 33.780 21.300 1.00 0.00 +ATOM 6 C4' RG5 1 38.080 35.610 20.360 1.00 0.00 +ATOM 7 H4' RG5 1 37.490 35.430 19.460 1.00 0.00 +ATOM 8 O4' RG5 1 38.030 37.010 20.540 1.00 0.00 +ATOM 9 C1' RG5 1 39.300 37.560 20.260 1.00 0.00 +ATOM 10 H1' RG5 1 39.110 38.440 19.650 1.00 0.00 +ATOM 11 N9 RG5 1 40.040 37.930 21.480 1.00 0.00 +ATOM 12 C8 RG5 1 39.650 37.790 22.790 1.00 0.00 +ATOM 13 H8 RG5 1 38.690 37.410 23.100 1.00 0.00 +ATOM 14 N7 RG5 1 40.460 38.320 23.660 1.00 0.00 +ATOM 15 C5 RG5 1 41.460 38.830 22.840 1.00 0.00 +ATOM 16 C6 RG5 1 42.670 39.490 23.190 1.00 0.00 +ATOM 17 O6 RG5 1 43.140 39.670 24.310 1.00 0.00 +ATOM 18 N1 RG5 1 43.410 39.910 22.090 1.00 0.00 +ATOM 19 H1 RG5 1 44.230 40.460 22.310 1.00 0.00 +ATOM 20 C2 RG5 1 43.040 39.720 20.780 1.00 0.00 +ATOM 21 N2 RG5 1 43.790 40.430 19.920 1.00 0.00 +ATOM 22 H21 RG5 1 44.450 41.040 20.380 1.00 0.00 +ATOM 23 H22 RG5 1 43.670 40.440 18.920 1.00 0.00 +ATOM 24 N3 RG5 1 41.950 39.020 20.440 1.00 0.00 +ATOM 25 C4 RG5 1 41.200 38.660 21.510 1.00 0.00 +ATOM 26 C3' RG5 1 39.500 35.160 20.060 1.00 0.00 +ATOM 27 H3' RG5 1 40.040 34.920 20.980 1.00 0.00 +ATOM 28 C2' RG5 1 40.080 36.470 19.530 1.00 0.00 +ATOM 29 1H2' RG5 1 41.150 36.500 19.710 1.00 0.00 +ATOM 30 O2' RG5 1 39.930 36.550 18.130 1.00 0.00 +ATOM 31 2HO' RG5 1 39.480 35.750 17.850 1.00 0.00 +ATOM 32 O3' RG5 1 39.530 34.100 19.130 1.00 0.00 +ATOM 33 P RG 2 40.740 33.040 19.120 1.00 0.00 +ATOM 34 O1P RG 2 40.450 32.130 17.980 1.00 0.00 +ATOM 35 O2P RG 2 40.940 32.500 20.480 1.00 0.00 +ATOM 36 O5' RG 2 42.060 33.910 18.790 1.00 0.00 +ATOM 37 C5' RG 2 42.540 34.230 17.500 1.00 0.00 +ATOM 38 1H5' RG 2 41.750 34.700 16.910 1.00 0.00 +ATOM 39 2H5' RG 2 42.810 33.300 17.000 1.00 0.00 +ATOM 40 C4' RG 2 43.670 35.250 17.590 1.00 0.00 +ATOM 41 H4' RG 2 43.990 35.610 16.610 1.00 0.00 +ATOM 42 O4' RG 2 43.470 36.410 18.360 1.00 0.00 +ATOM 43 C1' RG 2 44.760 36.760 18.830 1.00 0.00 +ATOM 44 H1' RG 2 45.060 37.750 18.480 1.00 0.00 +ATOM 45 N9 RG 2 44.690 36.900 20.300 1.00 0.00 +ATOM 46 C8 RG 2 43.870 36.170 21.130 1.00 0.00 +ATOM 47 H8 RG 2 43.070 35.580 20.720 1.00 0.00 +ATOM 48 N7 RG 2 44.220 36.230 22.390 1.00 0.00 +ATOM 49 C5 RG 2 45.260 37.150 22.380 1.00 0.00 +ATOM 50 C6 RG 2 46.020 37.650 23.470 1.00 0.00 +ATOM 51 O6 RG 2 45.910 37.450 24.680 1.00 0.00 +ATOM 52 N1 RG 2 47.100 38.430 23.080 1.00 0.00 +ATOM 53 H1 RG 2 47.690 38.870 23.770 1.00 0.00 +ATOM 54 C2 RG 2 47.360 38.780 21.770 1.00 0.00 +ATOM 55 N2 RG 2 48.330 39.670 21.520 1.00 0.00 +ATOM 56 H21 RG 2 49.030 39.890 22.210 1.00 0.00 +ATOM 57 H22 RG 2 48.390 40.060 20.590 1.00 0.00 +ATOM 58 N3 RG 2 46.640 38.300 20.740 1.00 0.00 +ATOM 59 C4 RG 2 45.640 37.470 21.110 1.00 0.00 +ATOM 60 C3' RG 2 44.850 34.520 18.220 1.00 0.00 +ATOM 61 H3' RG 2 44.630 34.120 19.210 1.00 0.00 +ATOM 62 C2' RG 2 45.780 35.730 18.370 1.00 0.00 +ATOM 63 1H2' RG 2 46.530 35.510 19.130 1.00 0.00 +ATOM 64 O2' RG 2 46.390 36.110 17.160 1.00 0.00 +ATOM 65 2HO' RG 2 47.280 36.440 17.340 1.00 0.00 +ATOM 66 O3' RG 2 45.400 33.560 17.350 1.00 0.00 +ATOM 67 P RG 3 46.280 32.300 17.830 1.00 0.00 +ATOM 68 O1P RG 3 46.460 31.500 16.600 1.00 0.00 +ATOM 69 O2P RG 3 45.670 31.650 19.010 1.00 0.00 +ATOM 70 O5' RG 3 47.650 33.050 18.220 1.00 0.00 +ATOM 71 C5' RG 3 48.720 33.240 17.320 1.00 0.00 +ATOM 72 1H5' RG 3 48.390 33.730 16.400 1.00 0.00 +ATOM 73 2H5' RG 3 49.130 32.270 17.040 1.00 0.00 +ATOM 74 C4' RG 3 49.830 34.060 17.970 1.00 0.00 +ATOM 75 H4' RG 3 50.500 34.420 17.190 1.00 0.00 +ATOM 76 O4' RG 3 49.360 35.210 18.650 1.00 0.00 +ATOM 77 C1' RG 3 50.150 35.480 19.780 1.00 0.00 +ATOM 78 H1' RG 3 50.560 36.490 19.760 1.00 0.00 +ATOM 79 N9 RG 3 49.350 35.280 21.010 1.00 0.00 +ATOM 80 C8 RG 3 48.130 34.690 21.210 1.00 0.00 +ATOM 81 H8 RG 3 47.480 34.270 20.460 1.00 0.00 +ATOM 82 N7 RG 3 47.790 34.750 22.460 1.00 0.00 +ATOM 83 C5 RG 3 48.830 35.400 23.130 1.00 0.00 +ATOM 84 C6 RG 3 49.030 35.730 24.500 1.00 0.00 +ATOM 85 O6 RG 3 48.250 35.610 25.440 1.00 0.00 +ATOM 86 N1 RG 3 50.230 36.380 24.740 1.00 0.00 +ATOM 87 H1 RG 3 50.310 36.720 25.690 1.00 0.00 +ATOM 88 C2 RG 3 51.170 36.620 23.760 1.00 0.00 +ATOM 89 N2 RG 3 52.330 37.230 24.060 1.00 0.00 +ATOM 90 H21 RG 3 52.520 37.530 25.000 1.00 0.00 +ATOM 91 H22 RG 3 53.010 37.370 23.330 1.00 0.00 +ATOM 92 N3 RG 3 50.980 36.330 22.470 1.00 0.00 +ATOM 93 C4 RG 3 49.760 35.800 22.210 1.00 0.00 +ATOM 94 C3' RG 3 50.630 33.310 19.030 1.00 0.00 +ATOM 95 H3' RG 3 49.890 32.960 19.750 1.00 0.00 +ATOM 96 C2' RG 3 51.300 34.480 19.740 1.00 0.00 +ATOM 97 1H2' RG 3 51.540 34.120 20.740 1.00 0.00 +ATOM 98 O2' RG 3 52.410 34.950 19.010 1.00 0.00 +ATOM 99 2HO' RG 3 53.110 35.170 19.640 1.00 0.00 +ATOM 100 O3' RG 3 51.440 32.300 18.470 1.00 0.00 +ATOM 101 P RG3 4 51.740 30.940 19.280 1.00 0.00 +ATOM 102 O1P RG3 4 52.710 30.170 18.470 1.00 0.00 +ATOM 103 O2P RG3 4 50.520 30.340 19.860 1.00 0.00 +ATOM 104 O5' RG3 4 52.570 31.460 20.560 1.00 0.00 +ATOM 105 C5' RG3 4 53.800 32.130 20.470 1.00 0.00 +ATOM 106 1H5' RG3 4 53.820 32.830 19.640 1.00 0.00 +ATOM 107 2H5' RG3 4 54.510 31.370 20.150 1.00 0.00 +ATOM 108 C4' RG3 4 54.340 32.900 21.680 1.00 0.00 +ATOM 109 H4' RG3 4 55.260 33.390 21.350 1.00 0.00 +ATOM 110 O4' RG3 4 53.400 33.820 22.180 1.00 0.00 +ATOM 111 C1' RG3 4 53.560 33.910 23.580 1.00 0.00 +ATOM 112 H1' RG3 4 53.750 34.960 23.810 1.00 0.00 +ATOM 113 N9 RG3 4 52.300 33.510 24.240 1.00 0.00 +ATOM 114 C8 RG3 4 51.150 32.990 23.700 1.00 0.00 +ATOM 115 H8 RG3 4 51.060 32.840 22.630 1.00 0.00 +ATOM 116 N7 RG3 4 50.180 32.860 24.550 1.00 0.00 +ATOM 117 C5 RG3 4 50.750 33.220 25.760 1.00 0.00 +ATOM 118 C6 RG3 4 50.220 33.310 27.070 1.00 0.00 +ATOM 119 O6 RG3 4 49.060 33.170 27.460 1.00 0.00 +ATOM 120 N1 RG3 4 51.150 33.640 28.050 1.00 0.00 +ATOM 121 H1 RG3 4 50.800 33.610 29.000 1.00 0.00 +ATOM 122 C2 RG3 4 52.420 34.120 27.770 1.00 0.00 +ATOM 123 N2 RG3 4 53.250 34.490 28.750 1.00 0.00 +ATOM 124 H21 RG3 4 52.820 34.560 29.660 1.00 0.00 +ATOM 125 H22 RG3 4 54.230 34.680 28.580 1.00 0.00 +ATOM 126 N3 RG3 4 52.860 34.200 26.510 1.00 0.00 +ATOM 127 C4 RG3 4 52.040 33.650 25.580 1.00 0.00 +ATOM 128 C3' RG3 4 54.520 31.900 22.820 1.00 0.00 +ATOM 129 H3' RG3 4 53.550 31.420 22.940 1.00 0.00 +ATOM 130 C2' RG3 4 54.640 32.900 23.960 1.00 0.00 +ATOM 131 1H2' RG3 4 54.400 32.360 24.870 1.00 0.00 +ATOM 132 O2' RG3 4 55.920 33.490 24.040 1.00 0.00 +ATOM 133 2HO' RG3 4 56.480 32.850 24.490 1.00 0.00 +ATOM 134 O3' RG3 4 55.620 31.010 22.820 1.00 0.00 +ATOM 135 H3T RG3 4 56.400 31.550 22.660 1.00 0.00 +ATOM 136 H5T RC5 5 48.940 36.700 37.120 1.00 0.00 +ATOM 137 O5' RC5 5 49.550 36.770 36.390 1.00 0.00 +ATOM 138 C5' RC5 5 50.840 36.500 36.900 1.00 0.00 +ATOM 139 1H5' RC5 5 50.770 35.660 37.600 1.00 0.00 +ATOM 140 2H5' RC5 5 51.160 37.440 37.360 1.00 0.00 +ATOM 141 C4' RC5 5 51.890 36.040 35.900 1.00 0.00 +ATOM 142 H4' RC5 5 52.810 35.950 36.480 1.00 0.00 +ATOM 143 O4' RC5 5 51.550 34.810 35.310 1.00 0.00 +ATOM 144 C1' RC5 5 52.080 34.790 34.000 1.00 0.00 +ATOM 145 H1' RC5 5 52.740 33.930 33.850 1.00 0.00 +ATOM 146 N1 RC5 5 51.030 34.790 32.970 1.00 0.00 +ATOM 147 C6 RC5 5 49.780 35.220 33.310 1.00 0.00 +ATOM 148 H6 RC5 5 49.570 35.750 34.220 1.00 0.00 +ATOM 149 C5 RC5 5 48.680 34.980 32.560 1.00 0.00 +ATOM 150 H5 RC5 5 47.730 35.330 32.920 1.00 0.00 +ATOM 151 C4 RC5 5 48.950 34.330 31.310 1.00 0.00 +ATOM 152 N4 RC5 5 48.000 34.250 30.370 1.00 0.00 +ATOM 153 H41 RC5 5 48.220 33.790 29.490 1.00 0.00 +ATOM 154 H42 RC5 5 47.070 34.630 30.480 1.00 0.00 +ATOM 155 N3 RC5 5 50.140 33.830 30.960 1.00 0.00 +ATOM 156 C2 RC5 5 51.200 34.200 31.730 1.00 0.00 +ATOM 157 O2 RC5 5 52.340 33.960 31.340 1.00 0.00 +ATOM 158 C3' RC5 5 52.110 37.040 34.770 1.00 0.00 +ATOM 159 H3' RC5 5 51.170 37.380 34.320 1.00 0.00 +ATOM 160 C2' RC5 5 52.870 36.090 33.850 1.00 0.00 +ATOM 161 1H2' RC5 5 52.840 36.500 32.840 1.00 0.00 +ATOM 162 O2' RC5 5 54.210 35.900 34.240 1.00 0.00 +ATOM 163 2HO' RC5 5 54.460 36.510 34.930 1.00 0.00 +ATOM 164 O3' RC5 5 52.890 38.120 35.240 1.00 0.00 +ATOM 165 P RC 6 52.710 39.620 34.660 1.00 0.00 +ATOM 166 O1P RC 6 53.710 40.520 35.260 1.00 0.00 +ATOM 167 O2P RC 6 51.260 39.920 34.690 1.00 0.00 +ATOM 168 O5' RC 6 53.100 39.330 33.130 1.00 0.00 +ATOM 169 C5' RC 6 54.390 39.580 32.620 1.00 0.00 +ATOM 170 1H5' RC 6 55.030 38.870 33.150 1.00 0.00 +ATOM 171 2H5' RC 6 54.610 40.640 32.770 1.00 0.00 +ATOM 172 C4' RC 6 54.490 39.320 31.110 1.00 0.00 +ATOM 173 H4' RC 6 55.560 39.410 30.900 1.00 0.00 +ATOM 174 O4' RC 6 53.940 38.140 30.580 1.00 0.00 +ATOM 175 C1' RC 6 53.710 38.280 29.190 1.00 0.00 +ATOM 176 H1' RC 6 54.350 37.570 28.650 1.00 0.00 +ATOM 177 N1 RC 6 52.280 37.970 28.980 1.00 0.00 +ATOM 178 C6 RC 6 51.370 37.940 29.990 1.00 0.00 +ATOM 179 H6 RC 6 51.590 38.390 30.950 1.00 0.00 +ATOM 180 C5 RC 6 50.120 37.460 29.800 1.00 0.00 +ATOM 181 H5 RC 6 49.490 37.320 30.670 1.00 0.00 +ATOM 182 C4 RC 6 49.840 36.920 28.510 1.00 0.00 +ATOM 183 N4 RC 6 48.660 36.340 28.230 1.00 0.00 +ATOM 184 H41 RC 6 48.530 35.750 27.410 1.00 0.00 +ATOM 185 H42 RC 6 48.040 36.330 29.020 1.00 0.00 +ATOM 186 N3 RC 6 50.740 36.830 27.520 1.00 0.00 +ATOM 187 C2 RC 6 51.880 37.530 27.730 1.00 0.00 +ATOM 188 O2 RC 6 52.650 37.810 26.810 1.00 0.00 +ATOM 189 C3' RC 6 53.710 40.340 30.290 1.00 0.00 +ATOM 190 H3' RC 6 52.630 40.250 30.410 1.00 0.00 +ATOM 191 C2' RC 6 54.010 39.750 28.920 1.00 0.00 +ATOM 192 1H2' RC 6 53.270 40.090 28.200 1.00 0.00 +ATOM 193 O2' RC 6 55.240 39.920 28.250 1.00 0.00 +ATOM 194 2HO' RC 6 55.200 39.470 27.400 1.00 0.00 +ATOM 195 O3' RC 6 54.060 41.710 30.250 1.00 0.00 +ATOM 196 P RC 7 52.860 42.760 30.050 1.00 0.00 +ATOM 197 O1P RC 7 53.430 44.090 30.380 1.00 0.00 +ATOM 198 O2P RC 7 51.670 42.370 30.840 1.00 0.00 +ATOM 199 O5' RC 7 52.610 42.650 28.460 1.00 0.00 +ATOM 200 C5' RC 7 53.620 43.070 27.570 1.00 0.00 +ATOM 201 1H5' RC 7 54.600 42.750 27.940 1.00 0.00 +ATOM 202 2H5' RC 7 53.750 44.150 27.640 1.00 0.00 +ATOM 203 C4' RC 7 53.350 42.640 26.130 1.00 0.00 +ATOM 204 H4' RC 7 54.310 42.770 25.620 1.00 0.00 +ATOM 205 O4' RC 7 53.010 41.280 26.180 1.00 0.00 +ATOM 206 C1' RC 7 51.970 41.030 25.260 1.00 0.00 +ATOM 207 H1' RC 7 52.270 40.250 24.550 1.00 0.00 +ATOM 208 N1 RC 7 50.720 40.520 25.840 1.00 0.00 +ATOM 209 C6 RC 7 50.510 40.480 27.190 1.00 0.00 +ATOM 210 H6 RC 7 51.210 40.940 27.870 1.00 0.00 +ATOM 211 C5 RC 7 49.320 40.040 27.650 1.00 0.00 +ATOM 212 H5 RC 7 49.060 40.060 28.700 1.00 0.00 +ATOM 213 C4 RC 7 48.390 39.530 26.690 1.00 0.00 +ATOM 214 N4 RC 7 47.210 39.010 27.080 1.00 0.00 +ATOM 215 H41 RC 7 46.820 38.450 26.340 1.00 0.00 +ATOM 216 H42 RC 7 47.060 38.910 28.070 1.00 0.00 +ATOM 217 N3 RC 7 48.580 39.490 25.370 1.00 0.00 +ATOM 218 C2 RC 7 49.790 39.970 24.980 1.00 0.00 +ATOM 219 O2 RC 7 49.940 39.910 23.760 1.00 0.00 +ATOM 220 C3' RC 7 52.220 43.420 25.470 1.00 0.00 +ATOM 221 H3' RC 7 51.500 43.800 26.200 1.00 0.00 +ATOM 222 C2' RC 7 51.720 42.340 24.510 1.00 0.00 +ATOM 223 1H2' RC 7 50.680 42.530 24.250 1.00 0.00 +ATOM 224 O2' RC 7 52.500 42.300 23.340 1.00 0.00 +ATOM 225 2HO' RC 7 53.050 43.090 23.300 1.00 0.00 +ATOM 226 O3' RC 7 52.910 44.420 24.770 1.00 0.00 +ATOM 227 P RC3 8 52.200 45.810 24.370 1.00 0.00 +ATOM 228 O1P RC3 8 53.260 46.690 23.820 1.00 0.00 +ATOM 229 O2P RC3 8 51.550 46.330 25.590 1.00 0.00 +ATOM 230 O5' RC3 8 51.150 45.360 23.230 1.00 0.00 +ATOM 231 C5' RC3 8 51.410 45.280 21.850 1.00 0.00 +ATOM 232 1H5' RC3 8 52.210 44.590 21.600 1.00 0.00 +ATOM 233 2H5' RC3 8 51.890 46.160 21.430 1.00 0.00 +ATOM 234 C4' RC3 8 50.190 44.830 21.050 1.00 0.00 +ATOM 235 H4' RC3 8 50.440 44.870 19.990 1.00 0.00 +ATOM 236 O4' RC3 8 49.770 43.530 21.380 1.00 0.00 +ATOM 237 C1' RC3 8 48.400 43.460 21.050 1.00 0.00 +ATOM 238 H1' RC3 8 48.330 42.920 20.110 1.00 0.00 +ATOM 239 N1 RC3 8 47.650 42.910 22.200 1.00 0.00 +ATOM 240 C6 RC3 8 48.110 43.110 23.470 1.00 0.00 +ATOM 241 H6 RC3 8 48.940 43.780 23.660 1.00 0.00 +ATOM 242 C5 RC3 8 47.570 42.380 24.470 1.00 0.00 +ATOM 243 H5 RC3 8 47.890 42.550 25.490 1.00 0.00 +ATOM 244 C4 RC3 8 46.380 41.640 24.190 1.00 0.00 +ATOM 245 N4 RC3 8 45.650 40.960 25.090 1.00 0.00 +ATOM 246 H41 RC3 8 44.820 40.500 24.750 1.00 0.00 +ATOM 247 H42 RC3 8 45.960 40.880 26.050 1.00 0.00 +ATOM 248 N3 RC3 8 45.780 41.620 22.990 1.00 0.00 +ATOM 249 C2 RC3 8 46.470 42.230 21.990 1.00 0.00 +ATOM 250 O2 RC3 8 45.790 42.330 20.970 1.00 0.00 +ATOM 251 C3' RC3 8 49.020 45.800 21.240 1.00 0.00 +ATOM 252 H3' RC3 8 48.910 46.010 22.300 1.00 0.00 +ATOM 253 C2' RC3 8 47.950 44.870 20.670 1.00 0.00 +ATOM 254 1H2' RC3 8 46.980 45.030 21.140 1.00 0.00 +ATOM 255 O2' RC3 8 47.910 44.970 19.260 1.00 0.00 +ATOM 256 2HO' RC3 8 48.130 45.870 19.020 1.00 0.00 +ATOM 257 O3' RC3 8 49.030 46.970 20.460 1.00 0.00 +ATOM 258 H3T RC3 8 48.330 47.570 20.730 1.00 0.00 +ATOM 259 OW SOL 9 19.540 30.790 6.250 1.00 0.00 +ATOM 260 HW1 SOL 9 19.480 30.810 5.290 1.00 0.00 +ATOM 261 HW2 SOL 9 19.300 29.900 6.490 1.00 0.00 +ATOM 262 OW SOL 10 34.590 14.460 27.600 1.00 0.00 +ATOM 263 HW1 SOL 10 34.550 13.590 28.000 1.00 0.00 +ATOM 264 HW2 SOL 10 35.360 14.870 28.000 1.00 0.00 +ATOM 265 OW SOL 11 33.360 44.320 14.300 1.00 0.00 +ATOM 266 HW1 SOL 11 33.020 44.340 13.410 1.00 0.00 +ATOM 267 HW2 SOL 11 34.250 43.980 14.220 1.00 0.00 +ATOM 268 OW SOL 12 21.770 36.920 24.710 1.00 0.00 +ATOM 269 HW1 SOL 12 21.290 36.350 25.320 1.00 0.00 +ATOM 270 HW2 SOL 12 21.530 36.610 23.840 1.00 0.00 +ATOM 271 OW SOL 13 42.290 32.910 31.210 1.00 0.00 +ATOM 272 HW1 SOL 13 42.020 32.300 31.900 1.00 0.00 +ATOM 273 HW2 SOL 13 42.430 32.350 30.440 1.00 0.00 +ATOM 274 OW SOL 14 42.520 26.020 9.030 1.00 0.00 +ATOM 275 HW1 SOL 14 41.950 26.620 8.550 1.00 0.00 +ATOM 276 HW2 SOL 14 42.600 26.410 9.900 1.00 0.00 +ATOM 277 OW SOL 15 14.290 13.100 18.160 1.00 0.00 +ATOM 278 HW1 SOL 15 13.780 12.450 18.650 1.00 0.00 +ATOM 279 HW2 SOL 15 13.740 13.880 18.160 1.00 0.00 +ATOM 280 OW SOL 16 23.970 8.100 18.990 1.00 0.00 +ATOM 281 HW1 SOL 16 23.630 7.570 18.280 1.00 0.00 +ATOM 282 HW2 SOL 16 24.260 8.910 18.570 1.00 0.00 +ATOM 283 OW SOL 17 40.820 6.320 11.360 1.00 0.00 +ATOM 284 HW1 SOL 17 41.150 6.530 12.240 1.00 0.00 +ATOM 285 HW2 SOL 17 41.070 5.410 11.220 1.00 0.00 +ATOM 286 OW SOL 18 27.600 5.390 12.640 1.00 0.00 +ATOM 287 HW1 SOL 18 26.780 5.110 12.250 1.00 0.00 +ATOM 288 HW2 SOL 18 27.970 4.600 13.020 1.00 0.00 +ATOM 289 OW SOL 19 32.350 44.360 3.340 1.00 0.00 +ATOM 290 HW1 SOL 19 32.820 44.640 2.550 1.00 0.00 +ATOM 291 HW2 SOL 19 32.920 44.620 4.060 1.00 0.00 +ATOM 292 OW SOL 20 32.300 47.747 10.830 1.00 0.00 +ATOM 293 HW1 SOL 20 32.970 48.427 10.850 1.00 0.00 +ATOM 294 HW2 SOL 20 31.810 47.927 10.030 1.00 0.00 +ATOM 295 OW SOL 21 38.630 13.750 21.500 1.00 0.00 +ATOM 296 HW1 SOL 21 37.910 13.330 21.020 1.00 0.00 +ATOM 297 HW2 SOL 21 38.960 13.060 22.070 1.00 0.00 +ATOM 298 OW SOL 22 14.450 20.620 5.540 1.00 0.00 +ATOM 299 HW1 SOL 22 14.830 21.250 4.940 1.00 0.00 +ATOM 300 HW2 SOL 22 13.610 20.380 5.140 1.00 0.00 +ATOM 301 OW SOL 23 11.460 35.850 32.060 1.00 0.00 +ATOM 302 HW1 SOL 23 11.520 36.510 31.360 1.00 0.00 +ATOM 303 HW2 SOL 23 10.660 36.090 32.540 1.00 0.00 +ATOM 304 OW SOL 24 27.600 14.030 10.610 1.00 0.00 +ATOM 305 HW1 SOL 24 26.960 14.630 10.980 1.00 0.00 +ATOM 306 HW2 SOL 24 28.450 14.440 10.790 1.00 0.00 +ATOM 307 OW SOL 25 6.310 24.120 17.290 1.00 0.00 +ATOM 308 HW1 SOL 25 5.810 24.460 16.550 1.00 0.00 +ATOM 309 HW2 SOL 25 7.030 23.630 16.880 1.00 0.00 +ATOM 310 OW SOL 26 44.810 35.220 30.660 1.00 0.00 +ATOM 311 HW1 SOL 26 44.570 34.320 30.870 1.00 0.00 +ATOM 312 HW2 SOL 26 44.510 35.740 31.410 1.00 0.00 +ATOM 313 OW SOL 27 34.580 18.400 9.150 1.00 0.00 +ATOM 314 HW1 SOL 27 34.970 17.580 9.470 1.00 0.00 +ATOM 315 HW2 SOL 27 34.620 18.320 8.200 1.00 0.00 +ATOM 316 OW SOL 28 5.810 37.750 14.140 1.00 0.00 +ATOM 317 HW1 SOL 28 6.450 37.510 14.800 1.00 0.00 +ATOM 318 HW2 SOL 28 5.100 37.120 14.250 1.00 0.00 +ATOM 319 OW SOL 29 41.150 33.260 14.080 1.00 0.00 +ATOM 320 HW1 SOL 29 41.670 34.050 13.960 1.00 0.00 +ATOM 321 HW2 SOL 29 40.550 33.470 14.800 1.00 0.00 +ATOM 322 OW SOL 30 15.810 36.830 12.260 1.00 0.00 +ATOM 323 HW1 SOL 30 15.450 36.220 11.620 1.00 0.00 +ATOM 324 HW2 SOL 30 16.090 37.590 11.740 1.00 0.00 +ATOM 325 OW SOL 31 13.860 29.530 5.950 1.00 0.00 +ATOM 326 HW1 SOL 31 13.690 30.450 6.180 1.00 0.00 +ATOM 327 HW2 SOL 31 14.710 29.340 6.360 1.00 0.00 +ATOM 328 OW SOL 32 32.570 6.870 16.640 1.00 0.00 +ATOM 329 HW1 SOL 32 32.630 6.530 15.750 1.00 0.00 +ATOM 330 HW2 SOL 32 31.690 6.640 16.930 1.00 0.00 +ATOM 331 OW SOL 33 2.840 37.830 14.920 1.00 0.00 +ATOM 332 HW1 SOL 33 3.430 38.440 14.480 1.00 0.00 +ATOM 333 HW2 SOL 33 2.930 38.040 15.850 1.00 0.00 +ATOM 334 OW SOL 34 27.320 37.250 26.910 1.00 0.00 +ATOM 335 HW1 SOL 34 28.070 36.910 26.420 1.00 0.00 +ATOM 336 HW2 SOL 34 26.560 36.850 26.490 1.00 0.00 +ATOM 337 OW SOL 35 32.490 5.310 6.860 1.00 0.00 +ATOM 338 HW1 SOL 35 31.530 5.230 6.920 1.00 0.00 +ATOM 339 HW2 SOL 35 32.810 4.420 7.000 1.00 0.00 +ATOM 340 OW SOL 36 24.430 28.100 0.230 1.00 0.00 +ATOM 341 HW1 SOL 36 23.660 28.130 -0.350 1.00 0.00 +ATOM 342 HW2 SOL 36 24.990 28.810 -0.080 1.00 0.00 +ATOM 343 OW SOL 37 22.860 11.720 15.370 1.00 0.00 +ATOM 344 HW1 SOL 37 22.690 11.420 14.470 1.00 0.00 +ATOM 345 HW2 SOL 37 22.560 12.630 15.370 1.00 0.00 +ATOM 346 OW SOL 38 18.650 33.100 2.370 1.00 0.00 +ATOM 347 HW1 SOL 38 18.990 32.380 1.840 1.00 0.00 +ATOM 348 HW2 SOL 38 18.110 32.670 3.040 1.00 0.00 +ATOM 349 OW SOL 39 11.180 25.890 3.660 1.00 0.00 +ATOM 350 HW1 SOL 39 10.340 26.040 3.230 1.00 0.00 +ATOM 351 HW2 SOL 39 11.110 26.350 4.490 1.00 0.00 +ATOM 352 OW SOL 40 12.000 4.540 11.640 1.00 0.00 +ATOM 353 HW1 SOL 40 12.460 4.400 10.810 1.00 0.00 +ATOM 354 HW2 SOL 40 12.580 4.180 12.310 1.00 0.00 +ATOM 355 OW SOL 41 32.470 20.960 6.110 1.00 0.00 +ATOM 356 HW1 SOL 41 31.570 21.190 6.340 1.00 0.00 +ATOM 357 HW2 SOL 41 32.400 20.590 5.230 1.00 0.00 +ATOM 358 OW SOL 42 14.090 12.830 28.350 1.00 0.00 +ATOM 359 HW1 SOL 42 14.890 13.220 28.700 1.00 0.00 +ATOM 360 HW2 SOL 42 14.350 12.440 27.520 1.00 0.00 +ATOM 361 OW SOL 43 12.380 31.650 11.600 1.00 0.00 +ATOM 362 HW1 SOL 43 11.890 32.130 12.270 1.00 0.00 +ATOM 363 HW2 SOL 43 12.430 30.750 11.940 1.00 0.00 +ATOM 364 OW SOL 44 3.400 25.000 10.970 1.00 0.00 +ATOM 365 HW1 SOL 44 3.730 24.160 11.310 1.00 0.00 +ATOM 366 HW2 SOL 44 2.470 24.850 10.820 1.00 0.00 +ATOM 367 OW SOL 45 36.680 41.520 8.410 1.00 0.00 +ATOM 368 HW1 SOL 45 37.520 41.310 8.000 1.00 0.00 +ATOM 369 HW2 SOL 45 36.630 42.470 8.380 1.00 0.00 +ATOM 370 OW SOL 46 39.990 17.990 16.680 1.00 0.00 +ATOM 371 HW1 SOL 46 39.060 18.010 16.470 1.00 0.00 +ATOM 372 HW2 SOL 46 40.310 18.860 16.420 1.00 0.00 +ATOM 373 OW SOL 47 28.530 43.260 28.050 1.00 0.00 +ATOM 374 HW1 SOL 47 29.460 43.220 28.250 1.00 0.00 +ATOM 375 HW2 SOL 47 28.180 42.420 28.350 1.00 0.00 +ATOM 376 OW SOL 48 42.910 40.530 29.320 1.00 0.00 +ATOM 377 HW1 SOL 48 42.330 39.810 29.080 1.00 0.00 +ATOM 378 HW2 SOL 48 42.330 41.300 29.350 1.00 0.00 +ATOM 379 OW SOL 49 39.040 9.440 2.690 1.00 0.00 +ATOM 380 HW1 SOL 49 38.530 9.750 1.940 1.00 0.00 +ATOM 381 HW2 SOL 49 38.600 9.790 3.460 1.00 0.00 +ATOM 382 OW SOL 50 6.760 6.300 13.820 1.00 0.00 +ATOM 383 HW1 SOL 50 6.990 5.750 13.080 1.00 0.00 +ATOM 384 HW2 SOL 50 6.430 5.690 14.490 1.00 0.00 +ATOM 385 OW SOL 51 15.000 44.680 28.450 1.00 0.00 +ATOM 386 HW1 SOL 51 15.210 45.340 27.790 1.00 0.00 +ATOM 387 HW2 SOL 51 15.840 44.490 28.870 1.00 0.00 +ATOM 388 OW SOL 52 12.600 14.120 21.620 1.00 0.00 +ATOM 389 HW1 SOL 52 13.200 13.390 21.420 1.00 0.00 +ATOM 390 HW2 SOL 52 11.750 13.700 21.770 1.00 0.00 +ATOM 391 OW SOL 53 25.400 39.780 25.140 1.00 0.00 +ATOM 392 HW1 SOL 53 26.310 40.080 25.220 1.00 0.00 +ATOM 393 HW2 SOL 53 24.880 40.540 25.400 1.00 0.00 +ATOM 394 OW SOL 54 24.900 25.430 15.190 1.00 0.00 +ATOM 395 HW1 SOL 54 23.970 25.380 15.390 1.00 0.00 +ATOM 396 HW2 SOL 54 24.930 25.550 14.240 1.00 0.00 +ATOM 397 OW SOL 55 35.330 7.640 4.110 1.00 0.00 +ATOM 398 HW1 SOL 55 35.870 7.270 3.410 1.00 0.00 +ATOM 399 HW2 SOL 55 35.180 8.550 3.850 1.00 0.00 +ATOM 400 OW SOL 56 40.010 16.450 6.720 1.00 0.00 +ATOM 401 HW1 SOL 56 40.720 16.550 7.340 1.00 0.00 +ATOM 402 HW2 SOL 56 39.220 16.690 7.210 1.00 0.00 +ATOM 403 OW SOL 57 8.440 26.950 15.670 1.00 0.00 +ATOM 404 HW1 SOL 57 8.250 26.190 15.120 1.00 0.00 +ATOM 405 HW2 SOL 57 9.140 26.660 16.250 1.00 0.00 +ATOM 406 OW SOL 58 22.410 32.910 10.500 1.00 0.00 +ATOM 407 HW1 SOL 58 23.230 32.990 10.010 1.00 0.00 +ATOM 408 HW2 SOL 58 21.780 32.570 9.870 1.00 0.00 +ATOM 409 OW SOL 59 12.700 42.100 21.750 1.00 0.00 +ATOM 410 HW1 SOL 59 12.900 41.280 21.300 1.00 0.00 +ATOM 411 HW2 SOL 59 13.560 42.500 21.900 1.00 0.00 +ATOM 412 OW SOL 60 11.750 35.100 14.820 1.00 0.00 +ATOM 413 HW1 SOL 60 12.300 35.830 14.540 1.00 0.00 +ATOM 414 HW2 SOL 60 11.710 35.190 15.770 1.00 0.00 +ATOM 415 OW SOL 61 40.590 11.640 10.900 1.00 0.00 +ATOM 416 HW1 SOL 61 41.080 10.820 10.950 1.00 0.00 +ATOM 417 HW2 SOL 61 39.730 11.390 10.580 1.00 0.00 +ATOM 418 OW SOL 62 20.990 22.520 10.870 1.00 0.00 +ATOM 419 HW1 SOL 62 21.760 22.130 10.460 1.00 0.00 +ATOM 420 HW2 SOL 62 20.740 21.900 11.560 1.00 0.00 +ATOM 421 OW SOL 63 10.870 14.040 10.940 1.00 0.00 +ATOM 422 HW1 SOL 63 10.400 13.530 11.600 1.00 0.00 +ATOM 423 HW2 SOL 63 11.420 13.400 10.480 1.00 0.00 +ATOM 424 OW SOL 64 20.940 40.930 7.790 1.00 0.00 +ATOM 425 HW1 SOL 64 20.250 41.270 7.220 1.00 0.00 +ATOM 426 HW2 SOL 64 21.690 40.800 7.210 1.00 0.00 +ATOM 427 OW SOL 65 34.540 32.610 23.910 1.00 0.00 +ATOM 428 HW1 SOL 65 34.120 32.140 23.200 1.00 0.00 +ATOM 429 HW2 SOL 65 34.040 33.420 23.990 1.00 0.00 +ATOM 430 OW SOL 66 24.510 35.910 18.400 1.00 0.00 +ATOM 431 HW1 SOL 66 25.440 35.710 18.510 1.00 0.00 +ATOM 432 HW2 SOL 66 24.130 35.770 19.260 1.00 0.00 +ATOM 433 OW SOL 67 4.090 44.560 6.960 1.00 0.00 +ATOM 434 HW1 SOL 67 3.890 43.730 7.380 1.00 0.00 +ATOM 435 HW2 SOL 67 5.030 44.530 6.780 1.00 0.00 +ATOM 436 OW SOL 68 6.680 12.450 20.630 1.00 0.00 +ATOM 437 HW1 SOL 68 6.300 12.400 19.760 1.00 0.00 +ATOM 438 HW2 SOL 68 6.650 13.390 20.850 1.00 0.00 +ATOM 439 OW SOL 69 34.110 13.460 14.500 1.00 0.00 +ATOM 440 HW1 SOL 69 33.490 13.210 15.180 1.00 0.00 +ATOM 441 HW2 SOL 69 34.720 14.060 14.940 1.00 0.00 +ATOM 442 OW SOL 70 38.820 28.330 1.670 1.00 0.00 +ATOM 443 HW1 SOL 70 39.370 28.200 0.900 1.00 0.00 +ATOM 444 HW2 SOL 70 38.600 29.260 1.640 1.00 0.00 +ATOM 445 OW SOL 71 25.570 21.530 9.160 1.00 0.00 +ATOM 446 HW1 SOL 71 25.550 21.730 8.220 1.00 0.00 +ATOM 447 HW2 SOL 71 26.490 21.380 9.350 1.00 0.00 +ATOM 448 OW SOL 72 25.690 12.770 15.750 1.00 0.00 +ATOM 449 HW1 SOL 72 25.130 12.350 15.100 1.00 0.00 +ATOM 450 HW2 SOL 72 26.450 13.070 15.250 1.00 0.00 +ATOM 451 OW SOL 73 14.120 25.750 23.120 1.00 0.00 +ATOM 452 HW1 SOL 73 13.860 25.250 23.900 1.00 0.00 +ATOM 453 HW2 SOL 73 13.450 25.540 22.470 1.00 0.00 +ATOM 454 OW SOL 74 20.400 34.650 8.600 1.00 0.00 +ATOM 455 HW1 SOL 74 19.990 35.310 8.050 1.00 0.00 +ATOM 456 HW2 SOL 74 20.040 34.810 9.470 1.00 0.00 +ATOM 457 OW SOL 75 30.080 0.270 11.920 1.00 0.00 +ATOM 458 HW1 SOL 75 30.360 0.290 12.840 1.00 0.00 +ATOM 459 HW2 SOL 75 30.890 0.150 11.420 1.00 0.00 +ATOM 460 OW SOL 76 32.420 26.000 20.480 1.00 0.00 +ATOM 461 HW1 SOL 76 31.870 25.340 20.900 1.00 0.00 +ATOM 462 HW2 SOL 76 32.760 25.560 19.700 1.00 0.00 +ATOM 463 OW SOL 77 25.910 39.720 12.260 1.00 0.00 +ATOM 464 HW1 SOL 77 26.080 38.780 12.300 1.00 0.00 +ATOM 465 HW2 SOL 77 25.980 39.930 11.330 1.00 0.00 +ATOM 466 OW SOL 78 37.150 1.800 17.240 1.00 0.00 +ATOM 467 HW1 SOL 78 37.160 2.530 17.860 1.00 0.00 +ATOM 468 HW2 SOL 78 36.280 1.400 17.360 1.00 0.00 +ATOM 469 OW SOL 79 9.460 28.220 29.450 1.00 0.00 +ATOM 470 HW1 SOL 79 8.540 28.500 29.480 1.00 0.00 +ATOM 471 HW2 SOL 79 9.650 27.920 30.330 1.00 0.00 +ATOM 472 OW SOL 80 29.810 3.140 25.020 1.00 0.00 +ATOM 473 HW1 SOL 80 28.960 2.980 24.600 1.00 0.00 +ATOM 474 HW2 SOL 80 29.590 3.500 25.880 1.00 0.00 +ATOM 475 OW SOL 81 17.740 -0.717 22.710 1.00 0.00 +ATOM 476 HW1 SOL 81 18.100 0.123 22.430 1.00 0.00 +ATOM 477 HW2 SOL 81 17.330 -1.087 21.930 1.00 0.00 +ATOM 478 OW SOL 82 1.310 11.120 5.300 1.00 0.00 +ATOM 479 HW1 SOL 82 0.800 11.050 4.490 1.00 0.00 +ATOM 480 HW2 SOL 82 1.550 12.050 5.350 1.00 0.00 +ATOM 481 OW SOL 83 0.890 37.170 29.580 1.00 0.00 +ATOM 482 HW1 SOL 83 0.400 37.410 28.800 1.00 0.00 +ATOM 483 HW2 SOL 83 0.360 36.490 30.000 1.00 0.00 +ATOM 484 OW SOL 84 38.150 24.350 17.510 1.00 0.00 +ATOM 485 HW1 SOL 84 38.730 24.590 18.240 1.00 0.00 +ATOM 486 HW2 SOL 84 38.270 23.410 17.410 1.00 0.00 +ATOM 487 OW SOL 85 34.890 27.540 21.530 1.00 0.00 +ATOM 488 HW1 SOL 85 35.050 26.800 22.110 1.00 0.00 +ATOM 489 HW2 SOL 85 34.190 27.240 20.950 1.00 0.00 +ATOM 490 OW SOL 86 33.540 17.050 4.350 1.00 0.00 +ATOM 491 HW1 SOL 86 32.620 17.220 4.130 1.00 0.00 +ATOM 492 HW2 SOL 86 34.020 17.240 3.550 1.00 0.00 +ATOM 493 OW SOL 87 9.980 1.680 7.120 1.00 0.00 +ATOM 494 HW1 SOL 87 9.530 2.080 6.370 1.00 0.00 +ATOM 495 HW2 SOL 87 10.270 2.430 7.650 1.00 0.00 +ATOM 496 OW SOL 88 7.160 3.740 12.780 1.00 0.00 +ATOM 497 HW1 SOL 88 6.700 3.100 13.340 1.00 0.00 +ATOM 498 HW2 SOL 88 6.590 3.830 12.020 1.00 0.00 +ATOM 499 OW SOL 89 4.870 3.950 11.150 1.00 0.00 +ATOM 500 HW1 SOL 89 4.180 3.790 11.800 1.00 0.00 +ATOM 501 HW2 SOL 89 4.440 4.470 10.470 1.00 0.00 +ATOM 502 OW SOL 90 27.870 36.780 9.160 1.00 0.00 +ATOM 503 HW1 SOL 90 28.720 37.130 8.910 1.00 0.00 +ATOM 504 HW2 SOL 90 27.690 36.090 8.530 1.00 0.00 +ATOM 505 OW SOL 91 14.180 9.530 28.250 1.00 0.00 +ATOM 506 HW1 SOL 91 14.890 9.610 27.610 1.00 0.00 +ATOM 507 HW2 SOL 91 14.600 9.710 29.090 1.00 0.00 +ATOM 508 OW SOL 92 35.650 32.790 28.120 1.00 0.00 +ATOM 509 HW1 SOL 92 35.030 33.380 27.680 1.00 0.00 +ATOM 510 HW2 SOL 92 36.110 32.350 27.410 1.00 0.00 +ATOM 511 OW SOL 93 26.890 26.160 0.500 1.00 0.00 +ATOM 512 HW1 SOL 93 26.560 25.290 0.730 1.00 0.00 +ATOM 513 HW2 SOL 93 27.840 26.050 0.490 1.00 0.00 +ATOM 514 OW SOL 94 35.880 5.560 28.180 1.00 0.00 +ATOM 515 HW1 SOL 94 35.550 4.700 28.420 1.00 0.00 +ATOM 516 HW2 SOL 94 36.320 5.880 28.970 1.00 0.00 +ATOM 517 OW SOL 95 32.930 33.990 14.200 1.00 0.00 +ATOM 518 HW1 SOL 95 33.390 33.700 13.410 1.00 0.00 +ATOM 519 HW2 SOL 95 32.100 34.350 13.880 1.00 0.00 +ATOM 520 OW SOL 96 25.130 4.890 21.080 1.00 0.00 +ATOM 521 HW1 SOL 96 24.790 3.990 21.090 1.00 0.00 +ATOM 522 HW2 SOL 96 24.450 5.400 21.510 1.00 0.00 +ATOM 523 OW SOL 97 19.140 36.570 7.090 1.00 0.00 +ATOM 524 HW1 SOL 97 19.880 36.850 6.550 1.00 0.00 +ATOM 525 HW2 SOL 97 18.380 36.990 6.690 1.00 0.00 +ATOM 526 OW SOL 98 2.150 24.110 29.720 1.00 0.00 +ATOM 527 HW1 SOL 98 1.470 24.770 29.670 1.00 0.00 +ATOM 528 HW2 SOL 98 2.500 24.050 28.830 1.00 0.00 +ATOM 529 OW SOL 99 38.820 35.060 5.950 1.00 0.00 +ATOM 530 HW1 SOL 99 38.890 35.810 5.370 1.00 0.00 +ATOM 531 HW2 SOL 99 37.920 34.750 5.840 1.00 0.00 +ATOM 532 OW SOL 100 40.940 2.840 19.440 1.00 0.00 +ATOM 533 HW1 SOL 100 40.770 2.940 20.370 1.00 0.00 +ATOM 534 HW2 SOL 100 40.670 3.680 19.060 1.00 0.00 +ATOM 535 OW SOL 101 36.190 40.030 15.710 1.00 0.00 +ATOM 536 HW1 SOL 101 35.430 39.500 15.940 1.00 0.00 +ATOM 537 HW2 SOL 101 36.940 39.500 15.970 1.00 0.00 +ATOM 538 OW SOL 102 12.850 7.870 22.130 1.00 0.00 +ATOM 539 HW1 SOL 102 13.330 8.680 21.950 1.00 0.00 +ATOM 540 HW2 SOL 102 12.520 7.590 21.280 1.00 0.00 +ATOM 541 OW SOL 103 33.050 13.600 31.370 1.00 0.00 +ATOM 542 HW1 SOL 103 33.720 13.100 31.840 1.00 0.00 +ATOM 543 HW2 SOL 103 32.280 13.030 31.370 1.00 0.00 +ATOM 544 OW SOL 104 32.550 6.230 9.480 1.00 0.00 +ATOM 545 HW1 SOL 104 32.680 7.160 9.320 1.00 0.00 +ATOM 546 HW2 SOL 104 32.340 5.870 8.620 1.00 0.00 +ATOM 547 OW SOL 105 8.860 18.670 19.910 1.00 0.00 +ATOM 548 HW1 SOL 105 7.950 18.620 19.620 1.00 0.00 +ATOM 549 HW2 SOL 105 8.910 19.490 20.400 1.00 0.00 +ATOM 550 OW SOL 106 26.550 41.710 29.310 1.00 0.00 +ATOM 551 HW1 SOL 106 26.300 40.800 29.150 1.00 0.00 +ATOM 552 HW2 SOL 106 26.160 41.910 30.160 1.00 0.00 +ATOM 553 OW SOL 107 35.290 40.550 29.170 1.00 0.00 +ATOM 554 HW1 SOL 107 35.430 39.610 29.030 1.00 0.00 +ATOM 555 HW2 SOL 107 34.380 40.690 28.910 1.00 0.00 +ATOM 556 OW SOL 108 26.120 31.130 14.090 1.00 0.00 +ATOM 557 HW1 SOL 108 25.770 30.270 14.340 1.00 0.00 +ATOM 558 HW2 SOL 108 26.280 31.060 13.150 1.00 0.00 +ATOM 559 OW SOL 109 27.190 7.420 18.740 1.00 0.00 +ATOM 560 HW1 SOL 109 26.860 6.550 18.980 1.00 0.00 +ATOM 561 HW2 SOL 109 27.790 7.250 18.020 1.00 0.00 +ATOM 562 OW SOL 110 11.770 41.690 29.660 1.00 0.00 +ATOM 563 HW1 SOL 110 11.850 42.580 29.320 1.00 0.00 +ATOM 564 HW2 SOL 110 11.010 41.330 29.210 1.00 0.00 +ATOM 565 OW SOL 111 37.550 14.430 7.910 1.00 0.00 +ATOM 566 HW1 SOL 111 37.000 14.750 7.190 1.00 0.00 +ATOM 567 HW2 SOL 111 38.300 14.020 7.470 1.00 0.00 +ATOM 568 OW SOL 112 6.580 14.250 10.560 1.00 0.00 +ATOM 569 HW1 SOL 112 6.860 13.660 11.250 1.00 0.00 +ATOM 570 HW2 SOL 112 6.010 14.880 10.990 1.00 0.00 +ATOM 571 OW SOL 113 3.200 38.570 12.020 1.00 0.00 +ATOM 572 HW1 SOL 113 3.790 38.940 11.360 1.00 0.00 +ATOM 573 HW2 SOL 113 3.110 37.650 11.780 1.00 0.00 +ATOM 574 OW SOL 114 15.170 0.960 0.520 1.00 0.00 +ATOM 575 HW1 SOL 114 15.050 1.910 0.420 1.00 0.00 +ATOM 576 HW2 SOL 114 16.030 0.870 0.910 1.00 0.00 +ATOM 577 OW SOL 115 0.910 41.400 3.770 1.00 0.00 +ATOM 578 HW1 SOL 115 0.960 41.910 4.580 1.00 0.00 +ATOM 579 HW2 SOL 115 0.090 41.660 3.370 1.00 0.00 +ATOM 580 OW SOL 116 16.170 41.400 16.850 1.00 0.00 +ATOM 581 HW1 SOL 116 15.410 41.760 16.400 1.00 0.00 +ATOM 582 HW2 SOL 116 16.760 42.140 16.960 1.00 0.00 +ATOM 583 OW SOL 117 27.330 26.310 16.150 1.00 0.00 +ATOM 584 HW1 SOL 117 27.030 27.070 16.650 1.00 0.00 +ATOM 585 HW2 SOL 117 26.520 25.920 15.810 1.00 0.00 +ATOM 586 OW SOL 118 31.870 12.270 20.320 1.00 0.00 +ATOM 587 HW1 SOL 118 32.020 11.320 20.260 1.00 0.00 +ATOM 588 HW2 SOL 118 30.980 12.390 20.010 1.00 0.00 +ATOM 589 OW SOL 119 11.720 26.660 6.380 1.00 0.00 +ATOM 590 HW1 SOL 119 12.350 26.940 7.040 1.00 0.00 +ATOM 591 HW2 SOL 119 11.430 25.790 6.680 1.00 0.00 +ATOM 592 OW SOL 120 36.910 22.640 14.840 1.00 0.00 +ATOM 593 HW1 SOL 120 37.260 21.760 14.690 1.00 0.00 +ATOM 594 HW2 SOL 120 37.680 23.210 14.870 1.00 0.00 +ATOM 595 OW SOL 121 26.130 19.380 14.890 1.00 0.00 +ATOM 596 HW1 SOL 121 27.050 19.140 14.960 1.00 0.00 +ATOM 597 HW2 SOL 121 26.070 20.230 15.330 1.00 0.00 +ATOM 598 OW SOL 122 27.800 36.650 15.160 1.00 0.00 +ATOM 599 HW1 SOL 122 26.950 37.010 15.420 1.00 0.00 +ATOM 600 HW2 SOL 122 27.610 35.740 14.950 1.00 0.00 +ATOM 601 OW SOL 123 11.880 20.910 4.740 1.00 0.00 +ATOM 602 HW1 SOL 123 12.250 21.720 4.400 1.00 0.00 +ATOM 603 HW2 SOL 123 11.410 20.530 3.990 1.00 0.00 +ATOM 604 OW SOL 124 21.620 39.450 18.880 1.00 0.00 +ATOM 605 HW1 SOL 124 21.130 38.750 18.450 1.00 0.00 +ATOM 606 HW2 SOL 124 22.450 39.490 18.400 1.00 0.00 +ATOM 607 OW SOL 125 0.930 34.400 12.000 1.00 0.00 +ATOM 608 HW1 SOL 125 0.830 35.340 11.860 1.00 0.00 +ATOM 609 HW2 SOL 125 0.650 34.260 12.910 1.00 0.00 +ATOM 610 OW SOL 126 29.720 26.520 7.690 1.00 0.00 +ATOM 611 HW1 SOL 126 29.810 25.600 7.930 1.00 0.00 +ATOM 612 HW2 SOL 126 29.000 26.530 7.060 1.00 0.00 +ATOM 613 OW SOL 127 42.660 23.230 9.210 1.00 0.00 +ATOM 614 HW1 SOL 127 42.390 24.110 8.960 1.00 0.00 +ATOM 615 HW2 SOL 127 42.580 22.720 8.410 1.00 0.00 +ATOM 616 OW SOL 128 29.270 13.060 19.870 1.00 0.00 +ATOM 617 HW1 SOL 128 28.870 13.580 20.560 1.00 0.00 +ATOM 618 HW2 SOL 128 28.590 12.980 19.200 1.00 0.00 +ATOM 619 OW SOL 129 24.950 28.680 11.750 1.00 0.00 +ATOM 620 HW1 SOL 129 24.080 29.080 11.820 1.00 0.00 +ATOM 621 HW2 SOL 129 25.210 28.510 12.650 1.00 0.00 +ATOM 622 OW SOL 130 33.130 36.780 6.970 1.00 0.00 +ATOM 623 HW1 SOL 130 32.230 37.000 7.180 1.00 0.00 +ATOM 624 HW2 SOL 130 33.340 36.040 7.540 1.00 0.00 +ATOM 625 OW SOL 131 43.620 22.280 12.750 1.00 0.00 +ATOM 626 HW1 SOL 131 43.260 22.340 13.640 1.00 0.00 +ATOM 627 HW2 SOL 131 44.560 22.460 12.860 1.00 0.00 +ATOM 628 OW SOL 132 14.520 9.510 13.440 1.00 0.00 +ATOM 629 HW1 SOL 132 14.740 8.710 13.940 1.00 0.00 +ATOM 630 HW2 SOL 132 14.690 10.220 14.060 1.00 0.00 +ATOM 631 OW SOL 133 38.780 5.600 3.140 1.00 0.00 +ATOM 632 HW1 SOL 133 38.260 6.020 2.450 1.00 0.00 +ATOM 633 HW2 SOL 133 39.640 6.010 3.060 1.00 0.00 +ATOM 634 OW SOL 134 12.890 4.550 5.770 1.00 0.00 +ATOM 635 HW1 SOL 134 13.040 4.900 6.650 1.00 0.00 +ATOM 636 HW2 SOL 134 12.850 3.600 5.890 1.00 0.00 +ATOM 637 OW SOL 135 41.770 6.490 27.800 1.00 0.00 +ATOM 638 HW1 SOL 135 42.060 7.400 27.870 1.00 0.00 +ATOM 639 HW2 SOL 135 41.050 6.520 27.160 1.00 0.00 +ATOM 640 OW SOL 136 14.940 40.660 24.370 1.00 0.00 +ATOM 641 HW1 SOL 136 15.560 40.970 25.030 1.00 0.00 +ATOM 642 HW2 SOL 136 15.440 40.650 23.560 1.00 0.00 +ATOM 643 OW SOL 137 37.110 30.510 21.960 1.00 0.00 +ATOM 644 HW1 SOL 137 37.880 30.100 22.350 1.00 0.00 +ATOM 645 HW2 SOL 137 36.900 29.950 21.210 1.00 0.00 +ATOM 646 OW SOL 138 21.670 14.580 10.180 1.00 0.00 +ATOM 647 HW1 SOL 138 20.910 14.020 10.010 1.00 0.00 +ATOM 648 HW2 SOL 138 22.280 14.000 10.650 1.00 0.00 +ATOM 649 OW SOL 139 23.380 24.570 28.120 1.00 0.00 +ATOM 650 HW1 SOL 139 22.990 24.420 28.980 1.00 0.00 +ATOM 651 HW2 SOL 139 22.660 24.880 27.580 1.00 0.00 +ATOM 652 OW SOL 140 34.180 27.240 24.870 1.00 0.00 +ATOM 653 HW1 SOL 140 34.560 28.120 24.950 1.00 0.00 +ATOM 654 HW2 SOL 140 33.370 27.290 25.370 1.00 0.00 +ATOM 655 OW SOL 141 17.940 3.150 9.080 1.00 0.00 +ATOM 656 HW1 SOL 141 18.770 2.910 9.480 1.00 0.00 +ATOM 657 HW2 SOL 141 17.990 2.780 8.190 1.00 0.00 +ATOM 658 OW SOL 142 30.490 30.430 9.090 1.00 0.00 +ATOM 659 HW1 SOL 142 30.500 29.840 9.840 1.00 0.00 +ATOM 660 HW2 SOL 142 30.740 29.880 8.350 1.00 0.00 +ATOM 661 OW SOL 143 21.900 18.000 13.110 1.00 0.00 +ATOM 662 HW1 SOL 143 22.680 17.910 13.650 1.00 0.00 +ATOM 663 HW2 SOL 143 21.620 18.900 13.240 1.00 0.00 +ATOM 664 OW SOL 144 10.040 14.420 15.250 1.00 0.00 +ATOM 665 HW1 SOL 144 10.980 14.250 15.350 1.00 0.00 +ATOM 666 HW2 SOL 144 9.950 14.720 14.350 1.00 0.00 +ATOM 667 OW SOL 145 22.230 12.310 1.980 1.00 0.00 +ATOM 668 HW1 SOL 145 21.300 12.420 1.750 1.00 0.00 +ATOM 669 HW2 SOL 145 22.580 13.200 1.990 1.00 0.00 +ATOM 670 OW SOL 146 35.160 31.490 9.000 1.00 0.00 +ATOM 671 HW1 SOL 146 35.120 32.070 9.760 1.00 0.00 +ATOM 672 HW2 SOL 146 36.040 31.640 8.640 1.00 0.00 +ATOM 673 OW SOL 147 11.710 40.920 4.490 1.00 0.00 +ATOM 674 HW1 SOL 147 12.190 40.800 5.310 1.00 0.00 +ATOM 675 HW2 SOL 147 12.260 41.510 3.970 1.00 0.00 +ATOM 676 OW SOL 148 26.070 1.340 0.020 1.00 0.00 +ATOM 677 HW1 SOL 148 25.670 1.330 -0.850 1.00 0.00 +ATOM 678 HW2 SOL 148 25.510 1.920 0.530 1.00 0.00 +ATOM 679 OW SOL 149 15.370 12.420 25.600 1.00 0.00 +ATOM 680 HW1 SOL 149 15.740 11.720 26.140 1.00 0.00 +ATOM 681 HW2 SOL 149 16.140 12.870 25.240 1.00 0.00 +ATOM 682 OW SOL 150 19.340 2.370 17.730 1.00 0.00 +ATOM 683 HW1 SOL 150 18.900 3.070 18.210 1.00 0.00 +ATOM 684 HW2 SOL 150 19.640 1.770 18.410 1.00 0.00 +ATOM 685 OW SOL 151 0.500 10.510 29.870 1.00 0.00 +ATOM 686 HW1 SOL 151 1.440 10.340 29.910 1.00 0.00 +ATOM 687 HW2 SOL 151 0.090 9.660 30.000 1.00 0.00 +ATOM 688 OW SOL 152 21.250 1.380 7.540 1.00 0.00 +ATOM 689 HW1 SOL 152 21.310 0.860 8.340 1.00 0.00 +ATOM 690 HW2 SOL 152 22.130 1.320 7.150 1.00 0.00 +ATOM 691 OW SOL 153 5.630 22.120 19.100 1.00 0.00 +ATOM 692 HW1 SOL 153 5.830 23.020 18.850 1.00 0.00 +ATOM 693 HW2 SOL 153 6.480 21.730 19.330 1.00 0.00 +ATOM 694 OW SOL 154 12.500 35.100 6.360 1.00 0.00 +ATOM 695 HW1 SOL 154 11.720 35.530 6.710 1.00 0.00 +ATOM 696 HW2 SOL 154 13.230 35.490 6.840 1.00 0.00 +ATOM 697 OW SOL 155 7.600 19.600 2.230 1.00 0.00 +ATOM 698 HW1 SOL 155 6.810 19.270 1.790 1.00 0.00 +ATOM 699 HW2 SOL 155 7.320 19.780 3.130 1.00 0.00 +ATOM 700 OW SOL 156 40.550 42.090 10.910 1.00 0.00 +ATOM 701 HW1 SOL 156 40.620 42.820 11.530 1.00 0.00 +ATOM 702 HW2 SOL 156 40.440 42.510 10.060 1.00 0.00 +ATOM 703 OW SOL 157 4.770 26.080 0.980 1.00 0.00 +ATOM 704 HW1 SOL 157 5.050 25.850 0.100 1.00 0.00 +ATOM 705 HW2 SOL 157 4.830 25.250 1.470 1.00 0.00 +ATOM 706 OW SOL 158 12.260 14.770 29.410 1.00 0.00 +ATOM 707 HW1 SOL 158 12.710 13.930 29.420 1.00 0.00 +ATOM 708 HW2 SOL 158 11.410 14.600 29.820 1.00 0.00 +ATOM 709 OW SOL 159 41.790 22.430 2.350 1.00 0.00 +ATOM 710 HW1 SOL 159 42.210 22.340 3.210 1.00 0.00 +ATOM 711 HW2 SOL 159 41.400 21.570 2.190 1.00 0.00 +ATOM 712 OW SOL 160 4.650 5.640 23.580 1.00 0.00 +ATOM 713 HW1 SOL 160 4.080 4.900 23.390 1.00 0.00 +ATOM 714 HW2 SOL 160 5.200 5.720 22.800 1.00 0.00 +ATOM 715 OW SOL 161 3.260 28.900 18.410 1.00 0.00 +ATOM 716 HW1 SOL 161 3.810 28.200 18.760 1.00 0.00 +ATOM 717 HW2 SOL 161 3.750 29.710 18.580 1.00 0.00 +ATOM 718 OW SOL 162 7.500 14.650 24.190 1.00 0.00 +ATOM 719 HW1 SOL 162 7.540 15.230 23.430 1.00 0.00 +ATOM 720 HW2 SOL 162 8.410 14.390 24.340 1.00 0.00 +ATOM 721 OW SOL 163 36.750 2.420 9.280 1.00 0.00 +ATOM 722 HW1 SOL 163 37.550 2.880 9.530 1.00 0.00 +ATOM 723 HW2 SOL 163 36.920 1.500 9.500 1.00 0.00 +ATOM 724 OW SOL 164 11.550 5.950 28.010 1.00 0.00 +ATOM 725 HW1 SOL 164 10.630 6.000 27.760 1.00 0.00 +ATOM 726 HW2 SOL 164 11.810 5.060 27.770 1.00 0.00 +ATOM 727 OW SOL 165 4.600 14.660 15.200 1.00 0.00 +ATOM 728 HW1 SOL 165 4.500 13.910 14.600 1.00 0.00 +ATOM 729 HW2 SOL 165 4.910 15.370 14.640 1.00 0.00 +ATOM 730 OW SOL 166 45.130 32.710 4.860 1.00 0.00 +ATOM 731 HW1 SOL 166 45.850 33.210 5.230 1.00 0.00 +ATOM 732 HW2 SOL 166 45.470 32.380 4.030 1.00 0.00 +ATOM 733 OW SOL 167 18.510 1.720 21.920 1.00 0.00 +ATOM 734 HW1 SOL 167 18.090 2.300 22.570 1.00 0.00 +ATOM 735 HW2 SOL 167 19.280 2.210 21.630 1.00 0.00 +ATOM 736 OW SOL 168 3.630 11.760 21.160 1.00 0.00 +ATOM 737 HW1 SOL 168 3.200 11.290 21.870 1.00 0.00 +ATOM 738 HW2 SOL 168 4.240 11.130 20.790 1.00 0.00 +ATOM 739 OW SOL 169 4.220 43.460 17.160 1.00 0.00 +ATOM 740 HW1 SOL 169 3.620 43.650 16.440 1.00 0.00 +ATOM 741 HW2 SOL 169 3.710 43.660 17.950 1.00 0.00 +ATOM 742 OW SOL 170 37.350 6.870 16.840 1.00 0.00 +ATOM 743 HW1 SOL 170 38.110 7.130 17.350 1.00 0.00 +ATOM 744 HW2 SOL 170 36.600 7.060 17.420 1.00 0.00 +ATOM 745 OW SOL 171 3.120 0.400 25.140 1.00 0.00 +ATOM 746 HW1 SOL 171 4.020 0.650 24.910 1.00 0.00 +ATOM 747 HW2 SOL 171 2.570 0.930 24.550 1.00 0.00 +ATOM 748 OW SOL 172 10.300 25.590 17.490 1.00 0.00 +ATOM 749 HW1 SOL 172 11.100 26.070 17.700 1.00 0.00 +ATOM 750 HW2 SOL 172 9.880 25.430 18.330 1.00 0.00 +ATOM 751 OW SOL 173 37.660 40.180 27.100 1.00 0.00 +ATOM 752 HW1 SOL 173 37.990 40.470 26.250 1.00 0.00 +ATOM 753 HW2 SOL 173 37.360 40.990 27.530 1.00 0.00 +ATOM 754 OW SOL 174 30.910 35.740 12.850 1.00 0.00 +ATOM 755 HW1 SOL 174 31.430 35.430 12.110 1.00 0.00 +ATOM 756 HW2 SOL 174 30.640 36.620 12.590 1.00 0.00 +ATOM 757 OW SOL 175 0.520 33.150 23.770 1.00 0.00 +ATOM 758 HW1 SOL 175 0.980 32.360 23.470 1.00 0.00 +ATOM 759 HW2 SOL 175 1.000 33.870 23.370 1.00 0.00 +ATOM 760 OW SOL 176 7.230 5.530 20.120 1.00 0.00 +ATOM 761 HW1 SOL 176 6.750 5.040 20.790 1.00 0.00 +ATOM 762 HW2 SOL 176 7.080 5.040 19.310 1.00 0.00 +ATOM 763 OW SOL 177 33.870 16.700 15.850 1.00 0.00 +ATOM 764 HW1 SOL 177 34.660 16.160 15.740 1.00 0.00 +ATOM 765 HW2 SOL 177 33.400 16.280 16.580 1.00 0.00 +ATOM 766 OW SOL 178 12.740 1.340 17.200 1.00 0.00 +ATOM 767 HW1 SOL 178 13.410 0.650 17.240 1.00 0.00 +ATOM 768 HW2 SOL 178 12.300 1.300 18.040 1.00 0.00 +ATOM 769 OW SOL 179 19.820 32.740 28.440 1.00 0.00 +ATOM 770 HW1 SOL 179 18.930 33.100 28.370 1.00 0.00 +ATOM 771 HW2 SOL 179 20.380 33.410 28.060 1.00 0.00 +ATOM 772 OW SOL 180 26.000 28.310 9.260 1.00 0.00 +ATOM 773 HW1 SOL 180 25.650 28.350 10.150 1.00 0.00 +ATOM 774 HW2 SOL 180 26.400 29.170 9.110 1.00 0.00 +ATOM 775 OW SOL 181 39.710 11.560 32.000 1.00 0.00 +ATOM 776 HW1 SOL 181 38.920 12.040 32.240 1.00 0.00 +ATOM 777 HW2 SOL 181 39.960 11.110 32.810 1.00 0.00 +ATOM 778 OW SOL 182 0.360 35.120 25.830 1.00 0.00 +ATOM 779 HW1 SOL 182 1.270 35.430 25.810 1.00 0.00 +ATOM 780 HW2 SOL 182 -0.160 35.880 25.580 1.00 0.00 +ATOM 781 OW SOL 183 15.120 2.600 15.600 1.00 0.00 +ATOM 782 HW1 SOL 183 15.690 2.530 14.830 1.00 0.00 +ATOM 783 HW2 SOL 183 14.230 2.570 15.250 1.00 0.00 +ATOM 784 OW SOL 184 4.820 3.690 26.130 1.00 0.00 +ATOM 785 HW1 SOL 184 5.520 3.190 25.720 1.00 0.00 +ATOM 786 HW2 SOL 184 4.880 3.460 27.060 1.00 0.00 +ATOM 787 OW SOL 185 39.010 39.020 2.010 1.00 0.00 +ATOM 788 HW1 SOL 185 38.100 38.740 2.110 1.00 0.00 +ATOM 789 HW2 SOL 185 39.130 39.680 2.700 1.00 0.00 +ATOM 790 OW SOL 186 27.690 9.430 21.160 1.00 0.00 +ATOM 791 HW1 SOL 186 28.100 8.620 20.840 1.00 0.00 +ATOM 792 HW2 SOL 186 26.820 9.160 21.440 1.00 0.00 +ATOM 793 OW SOL 187 34.670 4.130 4.900 1.00 0.00 +ATOM 794 HW1 SOL 187 34.010 4.200 5.590 1.00 0.00 +ATOM 795 HW2 SOL 187 35.410 3.710 5.330 1.00 0.00 +ATOM 796 OW SOL 188 20.120 17.520 27.300 1.00 0.00 +ATOM 797 HW1 SOL 188 19.940 17.280 26.390 1.00 0.00 +ATOM 798 HW2 SOL 188 19.280 17.790 27.650 1.00 0.00 +ATOM 799 OW SOL 189 6.590 3.910 18.160 1.00 0.00 +ATOM 800 HW1 SOL 189 7.210 3.220 17.930 1.00 0.00 +ATOM 801 HW2 SOL 189 5.760 3.630 17.770 1.00 0.00 +ATOM 802 OW SOL 190 20.690 29.420 4.120 1.00 0.00 +ATOM 803 HW1 SOL 190 20.770 29.280 3.180 1.00 0.00 +ATOM 804 HW2 SOL 190 21.520 29.810 4.380 1.00 0.00 +ATOM 805 OW SOL 191 4.620 10.700 17.370 1.00 0.00 +ATOM 806 HW1 SOL 191 5.460 10.490 16.950 1.00 0.00 +ATOM 807 HW2 SOL 191 4.720 10.360 18.260 1.00 0.00 +ATOM 808 OW SOL 192 26.100 28.960 2.560 1.00 0.00 +ATOM 809 HW1 SOL 192 25.460 28.890 3.270 1.00 0.00 +ATOM 810 HW2 SOL 192 25.600 28.800 1.770 1.00 0.00 +ATOM 811 OW SOL 193 38.130 1.070 12.950 1.00 0.00 +ATOM 812 HW1 SOL 193 38.360 1.490 13.780 1.00 0.00 +ATOM 813 HW2 SOL 193 37.310 1.490 12.690 1.00 0.00 +ATOM 814 OW SOL 194 40.420 -1.337 19.770 1.00 0.00 +ATOM 815 HW1 SOL 194 39.890 -1.277 20.560 1.00 0.00 +ATOM 816 HW2 SOL 194 40.200 -2.197 19.410 1.00 0.00 +ATOM 817 OW SOL 195 27.950 3.150 9.450 1.00 0.00 +ATOM 818 HW1 SOL 195 27.520 2.870 10.260 1.00 0.00 +ATOM 819 HW2 SOL 195 27.630 4.040 9.310 1.00 0.00 +ATOM 820 OW SOL 196 22.650 5.610 26.690 1.00 0.00 +ATOM 821 HW1 SOL 196 23.360 5.910 26.120 1.00 0.00 +ATOM 822 HW2 SOL 196 21.860 6.020 26.340 1.00 0.00 +ATOM 823 OW SOL 197 40.720 32.740 27.970 1.00 0.00 +ATOM 824 HW1 SOL 197 41.250 33.530 27.910 1.00 0.00 +ATOM 825 HW2 SOL 197 39.980 32.910 27.390 1.00 0.00 +ATOM 826 OW SOL 198 5.470 12.850 25.280 1.00 0.00 +ATOM 827 HW1 SOL 198 5.920 12.030 25.070 1.00 0.00 +ATOM 828 HW2 SOL 198 6.000 13.530 24.870 1.00 0.00 +ATOM 829 OW SOL 199 30.680 18.690 18.610 1.00 0.00 +ATOM 830 HW1 SOL 199 30.370 19.110 19.410 1.00 0.00 +ATOM 831 HW2 SOL 199 30.450 17.770 18.720 1.00 0.00 +ATOM 832 OW SOL 200 38.130 2.650 26.890 1.00 0.00 +ATOM 833 HW1 SOL 200 37.790 2.480 26.010 1.00 0.00 +ATOM 834 HW2 SOL 200 37.790 3.510 27.120 1.00 0.00 +ATOM 835 OW SOL 201 30.030 17.200 10.440 1.00 0.00 +ATOM 836 HW1 SOL 201 30.960 17.440 10.470 1.00 0.00 +ATOM 837 HW2 SOL 201 29.910 16.860 9.550 1.00 0.00 +ATOM 838 OW SOL 202 41.550 0.140 15.210 1.00 0.00 +ATOM 839 HW1 SOL 202 40.930 0.170 15.940 1.00 0.00 +ATOM 840 HW2 SOL 202 42.390 0.400 15.590 1.00 0.00 +ATOM 841 OW SOL 203 36.430 37.040 17.480 1.00 0.00 +ATOM 842 HW1 SOL 203 35.830 37.480 18.080 1.00 0.00 +ATOM 843 HW2 SOL 203 37.200 37.610 17.450 1.00 0.00 +ATOM 844 OW SOL 204 10.980 8.900 0.760 1.00 0.00 +ATOM 845 HW1 SOL 204 11.070 8.100 0.250 1.00 0.00 +ATOM 846 HW2 SOL 204 10.380 9.450 0.260 1.00 0.00 +ATOM 847 OW SOL 205 23.430 44.470 6.820 1.00 0.00 +ATOM 848 HW1 SOL 205 23.490 44.150 7.720 1.00 0.00 +ATOM 849 HW2 SOL 205 24.270 44.260 6.430 1.00 0.00 +ATOM 850 OW SOL 206 45.080 29.770 5.600 1.00 0.00 +ATOM 851 HW1 SOL 206 44.990 30.670 5.280 1.00 0.00 +ATOM 852 HW2 SOL 206 45.530 29.310 4.890 1.00 0.00 +ATOM 853 OW SOL 207 25.100 1.820 14.280 1.00 0.00 +ATOM 854 HW1 SOL 207 25.500 1.810 13.400 1.00 0.00 +ATOM 855 HW2 SOL 207 25.740 2.280 14.820 1.00 0.00 +ATOM 856 OW SOL 208 28.090 2.090 11.920 1.00 0.00 +ATOM 857 HW1 SOL 208 28.280 2.410 12.800 1.00 0.00 +ATOM 858 HW2 SOL 208 28.880 1.620 11.660 1.00 0.00 +ATOM 859 OW SOL 209 34.840 38.470 8.130 1.00 0.00 +ATOM 860 HW1 SOL 209 34.330 38.070 7.420 1.00 0.00 +ATOM 861 HW2 SOL 209 35.710 38.580 7.760 1.00 0.00 +ATOM 862 OW SOL 210 7.170 28.880 12.110 1.00 0.00 +ATOM 863 HW1 SOL 210 7.350 29.410 11.330 1.00 0.00 +ATOM 864 HW2 SOL 210 7.030 27.990 11.770 1.00 0.00 +ATOM 865 OW SOL 211 8.800 7.130 1.320 1.00 0.00 +ATOM 866 HW1 SOL 211 8.560 8.050 1.300 1.00 0.00 +ATOM 867 HW2 SOL 211 8.310 6.760 2.050 1.00 0.00 +ATOM 868 OW SOL 212 6.450 0.450 10.870 1.00 0.00 +ATOM 869 HW1 SOL 212 7.370 0.170 10.840 1.00 0.00 +ATOM 870 HW2 SOL 212 6.460 1.330 10.510 1.00 0.00 +ATOM 871 OW SOL 213 17.520 32.830 13.410 1.00 0.00 +ATOM 872 HW1 SOL 213 16.810 33.270 13.890 1.00 0.00 +ATOM 873 HW2 SOL 213 18.180 33.500 13.290 1.00 0.00 +ATOM 874 OW SOL 214 35.210 21.250 10.610 1.00 0.00 +ATOM 875 HW1 SOL 214 35.360 20.340 10.330 1.00 0.00 +ATOM 876 HW2 SOL 214 34.380 21.490 10.210 1.00 0.00 +ATOM 877 OW SOL 215 22.440 11.010 29.320 1.00 0.00 +ATOM 878 HW1 SOL 215 21.520 10.800 29.480 1.00 0.00 +ATOM 879 HW2 SOL 215 22.860 10.910 30.180 1.00 0.00 +ATOM 880 OW SOL 216 14.210 13.320 3.260 1.00 0.00 +ATOM 881 HW1 SOL 216 13.740 13.890 3.870 1.00 0.00 +ATOM 882 HW2 SOL 216 14.310 13.850 2.470 1.00 0.00 +ATOM 883 OW SOL 217 19.160 30.700 1.150 1.00 0.00 +ATOM 884 HW1 SOL 217 18.930 30.380 0.280 1.00 0.00 +ATOM 885 HW2 SOL 217 19.920 30.170 1.410 1.00 0.00 +ATOM 886 OW SOL 218 7.230 7.790 5.130 1.00 0.00 +ATOM 887 HW1 SOL 218 6.340 7.930 5.440 1.00 0.00 +ATOM 888 HW2 SOL 218 7.540 8.660 4.890 1.00 0.00 +ATOM 889 OW SOL 219 14.080 19.000 1.310 1.00 0.00 +ATOM 890 HW1 SOL 219 13.790 19.910 1.190 1.00 0.00 +ATOM 891 HW2 SOL 219 14.960 19.070 1.660 1.00 0.00 +ATOM 892 OW SOL 220 30.090 3.120 18.670 1.00 0.00 +ATOM 893 HW1 SOL 220 30.830 2.990 18.080 1.00 0.00 +ATOM 894 HW2 SOL 220 30.090 2.350 19.240 1.00 0.00 +ATOM 895 OW SOL 221 31.070 0.390 26.120 1.00 0.00 +ATOM 896 HW1 SOL 221 30.350 -0.210 25.890 1.00 0.00 +ATOM 897 HW2 SOL 221 31.250 0.860 25.310 1.00 0.00 +ATOM 898 OW SOL 222 2.700 38.530 5.750 1.00 0.00 +ATOM 899 HW1 SOL 222 2.100 39.110 6.220 1.00 0.00 +ATOM 900 HW2 SOL 222 2.710 37.730 6.280 1.00 0.00 +ATOM 901 OW SOL 223 39.930 1.430 3.040 1.00 0.00 +ATOM 902 HW1 SOL 223 39.870 1.980 3.820 1.00 0.00 +ATOM 903 HW2 SOL 223 40.430 1.950 2.410 1.00 0.00 +ATOM 904 OW SOL 224 1.720 5.700 21.720 1.00 0.00 +ATOM 905 HW1 SOL 224 2.000 5.250 20.930 1.00 0.00 +ATOM 906 HW2 SOL 224 1.850 5.060 22.430 1.00 0.00 +ATOM 907 OW SOL 225 0.980 28.030 3.350 1.00 0.00 +ATOM 908 HW1 SOL 225 1.410 27.750 2.550 1.00 0.00 +ATOM 909 HW2 SOL 225 1.580 27.780 4.050 1.00 0.00 +ATOM 910 OW SOL 226 10.750 18.660 31.490 1.00 0.00 +ATOM 911 HW1 SOL 226 11.160 18.380 30.670 1.00 0.00 +ATOM 912 HW2 SOL 226 10.940 17.960 32.110 1.00 0.00 +ATOM 913 OW SOL 227 18.210 37.580 26.120 1.00 0.00 +ATOM 914 HW1 SOL 227 18.790 38.050 26.720 1.00 0.00 +ATOM 915 HW2 SOL 227 17.680 38.270 25.710 1.00 0.00 +ATOM 916 OW SOL 228 5.590 3.500 4.350 1.00 0.00 +ATOM 917 HW1 SOL 228 4.920 3.160 3.760 1.00 0.00 +ATOM 918 HW2 SOL 228 6.250 2.810 4.400 1.00 0.00 +ATOM 919 OW SOL 229 0.430 11.440 9.260 1.00 0.00 +ATOM 920 HW1 SOL 229 1.070 11.130 9.890 1.00 0.00 +ATOM 921 HW2 SOL 229 0.010 12.180 9.690 1.00 0.00 +ATOM 922 OW SOL 230 17.130 2.070 4.720 1.00 0.00 +ATOM 923 HW1 SOL 230 17.140 2.900 4.240 1.00 0.00 +ATOM 924 HW2 SOL 230 16.600 2.250 5.500 1.00 0.00 +ATOM 925 OW SOL 231 17.040 37.190 29.390 1.00 0.00 +ATOM 926 HW1 SOL 231 17.170 36.690 30.190 1.00 0.00 +ATOM 927 HW2 SOL 231 17.540 38.000 29.530 1.00 0.00 +ATOM 928 OW SOL 232 20.102 49.189 32.238 1.00 0.00 +ATOM 929 HW1 SOL 232 20.172 48.659 33.038 1.00 0.00 +ATOM 930 HW2 SOL 232 20.011 50.089 32.558 1.00 0.00 +ATOM 931 OW SOL 233 31.680 31.470 26.210 1.00 0.00 +ATOM 932 HW1 SOL 233 30.880 31.070 25.870 1.00 0.00 +ATOM 933 HW2 SOL 233 31.380 32.260 26.660 1.00 0.00 +ATOM 934 OW SOL 234 2.040 26.680 1.090 1.00 0.00 +ATOM 935 HW1 SOL 234 2.980 26.550 1.250 1.00 0.00 +ATOM 936 HW2 SOL 234 1.780 25.920 0.560 1.00 0.00 +ATOM 937 OW SOL 235 4.160 25.330 25.140 1.00 0.00 +ATOM 938 HW1 SOL 235 4.550 24.780 24.460 1.00 0.00 +ATOM 939 HW2 SOL 235 3.860 26.110 24.670 1.00 0.00 +ATOM 940 OW SOL 236 17.820 20.270 17.930 1.00 0.00 +ATOM 941 HW1 SOL 236 18.270 20.410 18.770 1.00 0.00 +ATOM 942 HW2 SOL 236 17.700 19.320 17.870 1.00 0.00 +ATOM 943 OW SOL 237 36.860 25.050 12.170 1.00 0.00 +ATOM 944 HW1 SOL 237 36.080 24.700 12.590 1.00 0.00 +ATOM 945 HW2 SOL 237 36.540 25.770 11.620 1.00 0.00 +ATOM 946 OW SOL 238 13.820 5.890 31.000 1.00 0.00 +ATOM 947 HW1 SOL 238 13.750 6.840 31.100 1.00 0.00 +ATOM 948 HW2 SOL 238 14.690 5.750 30.630 1.00 0.00 +ATOM 949 OW SOL 239 7.260 12.590 12.610 1.00 0.00 +ATOM 950 HW1 SOL 239 7.710 12.280 13.390 1.00 0.00 +ATOM 951 HW2 SOL 239 7.030 11.790 12.140 1.00 0.00 +ATOM 952 OW SOL 240 18.020 28.030 30.280 1.00 0.00 +ATOM 953 HW1 SOL 240 17.550 28.090 31.120 1.00 0.00 +ATOM 954 HW2 SOL 240 18.170 28.940 30.020 1.00 0.00 +ATOM 955 OW SOL 241 10.000 41.470 7.690 1.00 0.00 +ATOM 956 HW1 SOL 241 9.980 42.410 7.870 1.00 0.00 +ATOM 957 HW2 SOL 241 9.340 41.350 7.000 1.00 0.00 +ATOM 958 OW SOL 242 25.050 22.570 25.990 1.00 0.00 +ATOM 959 HW1 SOL 242 25.230 22.150 26.830 1.00 0.00 +ATOM 960 HW2 SOL 242 25.680 23.280 25.930 1.00 0.00 +ATOM 961 OW SOL 243 12.100 31.010 8.810 1.00 0.00 +ATOM 962 HW1 SOL 243 11.920 30.070 8.890 1.00 0.00 +ATOM 963 HW2 SOL 243 12.310 31.280 9.700 1.00 0.00 +ATOM 964 OW SOL 244 16.960 18.940 2.680 1.00 0.00 +ATOM 965 HW1 SOL 244 17.850 19.280 2.770 1.00 0.00 +ATOM 966 HW2 SOL 244 16.920 18.190 3.270 1.00 0.00 +ATOM 967 OW SOL 245 32.240 34.480 24.240 1.00 0.00 +ATOM 968 HW1 SOL 245 31.530 33.880 24.450 1.00 0.00 +ATOM 969 HW2 SOL 245 32.220 34.540 23.280 1.00 0.00 +ATOM 970 OW SOL 246 3.450 35.600 11.640 1.00 0.00 +ATOM 971 HW1 SOL 246 2.540 35.310 11.600 1.00 0.00 +ATOM 972 HW2 SOL 246 3.960 34.790 11.580 1.00 0.00 +ATOM 973 OW SOL 247 14.320 42.180 27.970 1.00 0.00 +ATOM 974 HW1 SOL 247 15.200 41.970 27.660 1.00 0.00 +ATOM 975 HW2 SOL 247 14.370 43.100 28.240 1.00 0.00 +ATOM 976 OW SOL 248 27.470 5.960 9.060 1.00 0.00 +ATOM 977 HW1 SOL 248 27.540 6.580 9.790 1.00 0.00 +ATOM 978 HW2 SOL 248 26.740 6.290 8.540 1.00 0.00 +ATOM 979 OW SOL 249 26.280 22.310 12.700 1.00 0.00 +ATOM 980 HW1 SOL 249 26.300 22.280 13.660 1.00 0.00 +ATOM 981 HW2 SOL 249 27.050 21.800 12.440 1.00 0.00 +ATOM 982 OW SOL 250 2.240 44.190 15.520 1.00 0.00 +ATOM 983 HW1 SOL 250 2.400 45.130 15.390 1.00 0.00 +ATOM 984 HW2 SOL 250 1.840 43.900 14.700 1.00 0.00 +ATOM 985 OW SOL 251 17.640 17.540 17.910 1.00 0.00 +ATOM 986 HW1 SOL 251 17.110 16.920 17.420 1.00 0.00 +ATOM 987 HW2 SOL 251 18.510 17.150 17.930 1.00 0.00 +ATOM 988 OW SOL 252 19.470 20.960 22.970 1.00 0.00 +ATOM 989 HW1 SOL 252 19.050 20.180 23.320 1.00 0.00 +ATOM 990 HW2 SOL 252 20.330 20.970 23.380 1.00 0.00 +ATOM 991 OW SOL 253 29.290 9.520 18.460 1.00 0.00 +ATOM 992 HW1 SOL 253 28.770 10.210 18.870 1.00 0.00 +ATOM 993 HW2 SOL 253 28.840 9.350 17.630 1.00 0.00 +ATOM 994 OW SOL 254 13.620 9.210 10.510 1.00 0.00 +ATOM 995 HW1 SOL 254 14.190 9.910 10.200 1.00 0.00 +ATOM 996 HW2 SOL 254 13.660 9.270 11.460 1.00 0.00 +ATOM 997 OW SOL 255 35.950 34.840 9.650 1.00 0.00 +ATOM 998 HW1 SOL 255 36.690 34.440 10.110 1.00 0.00 +ATOM 999 HW2 SOL 255 35.920 35.740 9.970 1.00 0.00 +ATOM 1000 OW SOL 256 18.470 13.560 7.990 1.00 0.00 +ATOM 1001 HW1 SOL 256 17.610 13.960 7.870 1.00 0.00 +ATOM 1002 HW2 SOL 256 18.960 13.800 7.200 1.00 0.00 +ATOM 1003 OW SOL 257 34.250 32.970 1.310 1.00 0.00 +ATOM 1004 HW1 SOL 257 34.970 33.190 1.900 1.00 0.00 +ATOM 1005 HW2 SOL 257 34.190 33.720 0.710 1.00 0.00 +ATOM 1006 OW SOL 258 4.830 12.020 13.990 1.00 0.00 +ATOM 1007 HW1 SOL 258 5.450 12.420 13.380 1.00 0.00 +ATOM 1008 HW2 SOL 258 4.850 11.090 13.770 1.00 0.00 +ATOM 1009 OW SOL 259 17.690 39.590 30.180 1.00 0.00 +ATOM 1010 HW1 SOL 259 16.830 40.020 30.140 1.00 0.00 +ATOM 1011 HW2 SOL 259 18.130 39.870 29.380 1.00 0.00 +ATOM 1012 OW SOL 260 21.780 29.660 11.120 1.00 0.00 +ATOM 1013 HW1 SOL 260 21.150 28.940 11.110 1.00 0.00 +ATOM 1014 HW2 SOL 260 21.880 29.900 10.200 1.00 0.00 +ATOM 1015 OW SOL 261 10.590 31.900 27.260 1.00 0.00 +ATOM 1016 HW1 SOL 261 11.290 32.110 26.640 1.00 0.00 +ATOM 1017 HW2 SOL 261 10.770 31.000 27.520 1.00 0.00 +ATOM 1018 OW SOL 262 1.380 28.850 16.540 1.00 0.00 +ATOM 1019 HW1 SOL 262 1.170 29.730 16.230 1.00 0.00 +ATOM 1020 HW2 SOL 262 2.040 28.980 17.220 1.00 0.00 +ATOM 1021 OW SOL 263 0.900 28.890 0.080 1.00 0.00 +ATOM 1022 HW1 SOL 263 0.350 28.550 -0.630 1.00 0.00 +ATOM 1023 HW2 SOL 263 1.490 28.160 0.280 1.00 0.00 +ATOM 1024 OW SOL 264 40.510 26.450 27.590 1.00 0.00 +ATOM 1025 HW1 SOL 264 39.890 27.170 27.480 1.00 0.00 +ATOM 1026 HW2 SOL 264 40.840 26.550 28.480 1.00 0.00 +ATOM 1027 OW SOL 265 7.180 16.270 15.450 1.00 0.00 +ATOM 1028 HW1 SOL 265 7.480 15.920 14.610 1.00 0.00 +ATOM 1029 HW2 SOL 265 7.800 15.900 16.090 1.00 0.00 +ATOM 1030 OW SOL 266 6.360 27.380 24.950 1.00 0.00 +ATOM 1031 HW1 SOL 266 6.070 26.980 25.770 1.00 0.00 +ATOM 1032 HW2 SOL 266 6.880 28.130 25.220 1.00 0.00 +ATOM 1033 OW SOL 267 39.090 40.870 4.070 1.00 0.00 +ATOM 1034 HW1 SOL 267 38.340 41.470 4.050 1.00 0.00 +ATOM 1035 HW2 SOL 267 39.760 41.330 4.570 1.00 0.00 +ATOM 1036 OW SOL 268 15.400 2.180 22.740 1.00 0.00 +ATOM 1037 HW1 SOL 268 15.190 2.310 21.810 1.00 0.00 +ATOM 1038 HW2 SOL 268 15.780 3.010 23.020 1.00 0.00 +ATOM 1039 OW SOL 269 11.300 4.040 8.200 1.00 0.00 +ATOM 1040 HW1 SOL 269 12.020 3.560 8.610 1.00 0.00 +ATOM 1041 HW2 SOL 269 10.810 4.410 8.930 1.00 0.00 +ATOM 1042 OW SOL 270 33.090 9.540 17.510 1.00 0.00 +ATOM 1043 HW1 SOL 270 32.820 8.670 17.210 1.00 0.00 +ATOM 1044 HW2 SOL 270 33.800 9.790 16.910 1.00 0.00 +ATOM 1045 OW SOL 271 16.040 25.570 28.670 1.00 0.00 +ATOM 1046 HW1 SOL 271 16.760 25.420 29.280 1.00 0.00 +ATOM 1047 HW2 SOL 271 15.380 24.910 28.900 1.00 0.00 +ATOM 1048 OW SOL 272 20.100 28.670 26.470 1.00 0.00 +ATOM 1049 HW1 SOL 272 19.240 28.750 26.860 1.00 0.00 +ATOM 1050 HW2 SOL 272 20.460 29.560 26.470 1.00 0.00 +ATOM 1051 OW SOL 273 36.060 44.050 14.070 1.00 0.00 +ATOM 1052 HW1 SOL 273 36.730 43.400 14.280 1.00 0.00 +ATOM 1053 HW2 SOL 273 36.540 44.870 13.980 1.00 0.00 +ATOM 1054 OW SOL 274 35.240 15.720 9.810 1.00 0.00 +ATOM 1055 HW1 SOL 274 35.700 15.380 10.580 1.00 0.00 +ATOM 1056 HW2 SOL 274 35.930 15.870 9.170 1.00 0.00 +ATOM 1057 OW SOL 275 23.010 16.300 24.820 1.00 0.00 +ATOM 1058 HW1 SOL 275 22.780 16.580 25.700 1.00 0.00 +ATOM 1059 HW2 SOL 275 23.590 15.550 24.950 1.00 0.00 +ATOM 1060 OW SOL 276 27.530 10.370 31.840 1.00 0.00 +ATOM 1061 HW1 SOL 276 27.990 10.780 32.570 1.00 0.00 +ATOM 1062 HW2 SOL 276 26.810 9.890 32.250 1.00 0.00 +ATOM 1063 OW SOL 277 59.049 11.021 35.008 1.00 0.00 +ATOM 1064 HW1 SOL 277 58.819 11.461 35.828 1.00 0.00 +ATOM 1065 HW2 SOL 277 59.449 10.191 35.288 1.00 0.00 +ATOM 1066 OW SOL 278 23.600 43.120 23.040 1.00 0.00 +ATOM 1067 HW1 SOL 278 23.450 42.780 22.160 1.00 0.00 +ATOM 1068 HW2 SOL 278 23.710 42.330 23.580 1.00 0.00 +ATOM 1069 OW SOL 279 24.800 33.140 1.410 1.00 0.00 +ATOM 1070 HW1 SOL 279 23.940 33.540 1.270 1.00 0.00 +ATOM 1071 HW2 SOL 279 24.800 32.370 0.840 1.00 0.00 +ATOM 1072 OW SOL 280 29.520 16.050 18.940 1.00 0.00 +ATOM 1073 HW1 SOL 280 29.500 15.100 19.020 1.00 0.00 +ATOM 1074 HW2 SOL 280 29.580 16.370 19.840 1.00 0.00 +ATOM 1075 OW SOL 281 2.640 9.720 13.690 1.00 0.00 +ATOM 1076 HW1 SOL 281 3.050 8.900 13.410 1.00 0.00 +ATOM 1077 HW2 SOL 281 2.320 9.540 14.570 1.00 0.00 +ATOM 1078 OW SOL 282 31.560 35.460 27.730 1.00 0.00 +ATOM 1079 HW1 SOL 282 31.620 35.680 28.650 1.00 0.00 +ATOM 1080 HW2 SOL 282 30.850 34.810 27.680 1.00 0.00 +ATOM 1081 OW SOL 283 4.320 23.830 6.120 1.00 0.00 +ATOM 1082 HW1 SOL 283 3.790 23.750 5.320 1.00 0.00 +ATOM 1083 HW2 SOL 283 4.820 24.640 6.000 1.00 0.00 +ATOM 1084 OW SOL 284 10.670 43.590 22.910 1.00 0.00 +ATOM 1085 HW1 SOL 284 11.290 43.080 22.400 1.00 0.00 +ATOM 1086 HW2 SOL 284 10.320 42.970 23.550 1.00 0.00 +ATOM 1087 OW SOL 285 31.240 25.800 23.950 1.00 0.00 +ATOM 1088 HW1 SOL 285 31.350 26.470 24.630 1.00 0.00 +ATOM 1089 HW2 SOL 285 30.310 25.590 23.980 1.00 0.00 +ATOM 1090 OW SOL 286 27.150 3.330 19.520 1.00 0.00 +ATOM 1091 HW1 SOL 286 26.440 3.650 20.080 1.00 0.00 +ATOM 1092 HW2 SOL 286 27.830 3.050 20.130 1.00 0.00 +ATOM 1093 OW SOL 287 21.340 17.260 20.890 1.00 0.00 +ATOM 1094 HW1 SOL 287 21.860 17.490 21.660 1.00 0.00 +ATOM 1095 HW2 SOL 287 21.970 16.900 20.280 1.00 0.00 +ATOM 1096 OW SOL 288 8.250 15.260 13.180 1.00 0.00 +ATOM 1097 HW1 SOL 288 7.830 14.570 12.670 1.00 0.00 +ATOM 1098 HW2 SOL 288 8.710 15.790 12.520 1.00 0.00 +ATOM 1099 OW SOL 289 38.460 37.720 9.830 1.00 0.00 +ATOM 1100 HW1 SOL 289 38.310 37.980 8.920 1.00 0.00 +ATOM 1101 HW2 SOL 289 38.200 38.480 10.350 1.00 0.00 +ATOM 1102 OW SOL 290 9.080 44.260 7.750 1.00 0.00 +ATOM 1103 HW1 SOL 290 8.700 44.520 8.590 1.00 0.00 +ATOM 1104 HW2 SOL 290 9.630 45.000 7.490 1.00 0.00 +ATOM 1105 OW SOL 291 43.370 34.310 24.440 1.00 0.00 +ATOM 1106 HW1 SOL 291 42.430 34.100 24.480 1.00 0.00 +ATOM 1107 HW2 SOL 291 43.440 34.930 23.720 1.00 0.00 +ATOM 1108 OW SOL 292 44.940 6.100 1.470 1.00 0.00 +ATOM 1109 HW1 SOL 292 44.840 6.510 0.610 1.00 0.00 +ATOM 1110 HW2 SOL 292 44.720 6.800 2.090 1.00 0.00 +ATOM 1111 OW SOL 293 8.380 12.210 15.050 1.00 0.00 +ATOM 1112 HW1 SOL 293 8.730 13.080 15.250 1.00 0.00 +ATOM 1113 HW2 SOL 293 9.120 11.620 15.180 1.00 0.00 +ATOM 1114 OW SOL 294 14.340 34.090 29.730 1.00 0.00 +ATOM 1115 HW1 SOL 294 13.690 34.800 29.770 1.00 0.00 +ATOM 1116 HW2 SOL 294 15.170 34.510 29.990 1.00 0.00 +ATOM 1117 OW SOL 295 24.630 32.500 16.350 1.00 0.00 +ATOM 1118 HW1 SOL 295 23.950 32.060 15.840 1.00 0.00 +ATOM 1119 HW2 SOL 295 25.430 32.410 15.830 1.00 0.00 +ATOM 1120 OW SOL 296 31.480 20.430 3.460 1.00 0.00 +ATOM 1121 HW1 SOL 296 31.040 19.580 3.460 1.00 0.00 +ATOM 1122 HW2 SOL 296 31.280 20.810 2.600 1.00 0.00 +ATOM 1123 OW SOL 297 4.840 20.470 2.470 1.00 0.00 +ATOM 1124 HW1 SOL 297 5.560 21.040 2.750 1.00 0.00 +ATOM 1125 HW2 SOL 297 4.300 20.380 3.250 1.00 0.00 +ATOM 1126 OW SOL 298 31.830 24.830 6.020 1.00 0.00 +ATOM 1127 HW1 SOL 298 32.610 24.760 6.570 1.00 0.00 +ATOM 1128 HW2 SOL 298 31.120 24.500 6.580 1.00 0.00 +ATOM 1129 OW SOL 299 5.590 8.330 7.350 1.00 0.00 +ATOM 1130 HW1 SOL 299 4.940 7.630 7.390 1.00 0.00 +ATOM 1131 HW2 SOL 299 5.110 9.120 7.590 1.00 0.00 +ATOM 1132 OW SOL 300 43.940 33.570 27.400 1.00 0.00 +ATOM 1133 HW1 SOL 300 44.160 33.140 28.220 1.00 0.00 +ATOM 1134 HW2 SOL 300 43.200 34.150 27.620 1.00 0.00 +ATOM 1135 OW SOL 301 43.270 10.810 24.780 1.00 0.00 +ATOM 1136 HW1 SOL 301 43.300 10.240 24.020 1.00 0.00 +ATOM 1137 HW2 SOL 301 43.490 11.680 24.440 1.00 0.00 +ATOM 1138 OW SOL 302 26.310 16.160 22.420 1.00 0.00 +ATOM 1139 HW1 SOL 302 26.260 17.110 22.530 1.00 0.00 +ATOM 1140 HW2 SOL 302 26.280 16.030 21.470 1.00 0.00 +ATOM 1141 OW SOL 303 15.000 9.990 22.940 1.00 0.00 +ATOM 1142 HW1 SOL 303 14.150 10.430 22.930 1.00 0.00 +ATOM 1143 HW2 SOL 303 15.570 10.560 22.410 1.00 0.00 +ATOM 1144 OW SOL 304 30.610 21.390 1.240 1.00 0.00 +ATOM 1145 HW1 SOL 304 30.730 21.590 0.310 1.00 0.00 +ATOM 1146 HW2 SOL 304 29.920 20.730 1.260 1.00 0.00 +ATOM 1147 OW SOL 305 35.280 38.740 4.000 1.00 0.00 +ATOM 1148 HW1 SOL 305 35.640 37.970 3.570 1.00 0.00 +ATOM 1149 HW2 SOL 305 35.520 38.640 4.920 1.00 0.00 +ATOM 1150 OW SOL 306 27.240 24.050 31.020 1.00 0.00 +ATOM 1151 HW1 SOL 306 27.390 24.260 30.100 1.00 0.00 +ATOM 1152 HW2 SOL 306 28.100 24.140 31.430 1.00 0.00 +ATOM 1153 OW SOL 307 55.979 62.569 34.618 1.00 0.00 +ATOM 1154 HW1 SOL 307 56.619 62.379 35.298 1.00 0.00 +ATOM 1155 HW2 SOL 307 55.919 61.759 34.118 1.00 0.00 +ATOM 1156 OW SOL 308 32.019 61.609 36.148 1.00 0.00 +ATOM 1157 HW1 SOL 308 32.049 61.519 35.198 1.00 0.00 +ATOM 1158 HW2 SOL 308 32.749 62.199 36.348 1.00 0.00 +ATOM 1159 OW SOL 309 4.100 26.430 8.150 1.00 0.00 +ATOM 1160 HW1 SOL 309 3.680 27.150 8.610 1.00 0.00 +ATOM 1161 HW2 SOL 309 3.690 25.640 8.520 1.00 0.00 +ATOM 1162 OW SOL 310 12.390 8.850 16.130 1.00 0.00 +ATOM 1163 HW1 SOL 310 12.510 9.000 17.070 1.00 0.00 +ATOM 1164 HW2 SOL 310 13.280 8.760 15.790 1.00 0.00 +ATOM 1165 OW SOL 311 8.060 2.310 30.150 1.00 0.00 +ATOM 1166 HW1 SOL 311 7.930 2.270 29.200 1.00 0.00 +ATOM 1167 HW2 SOL 311 7.530 1.580 30.490 1.00 0.00 +ATOM 1168 OW SOL 312 41.310 -2.597 26.090 1.00 0.00 +ATOM 1169 HW1 SOL 312 40.810 -1.997 26.640 1.00 0.00 +ATOM 1170 HW2 SOL 312 42.220 -2.407 26.280 1.00 0.00 +ATOM 1171 OW SOL 313 41.600 9.250 13.770 1.00 0.00 +ATOM 1172 HW1 SOL 313 40.670 9.400 13.590 1.00 0.00 +ATOM 1173 HW2 SOL 313 41.690 8.300 13.780 1.00 0.00 +ATOM 1174 OW SOL 314 24.870 36.300 23.140 1.00 0.00 +ATOM 1175 HW1 SOL 314 24.200 35.740 22.750 1.00 0.00 +ATOM 1176 HW2 SOL 314 25.650 36.160 22.590 1.00 0.00 +ATOM 1177 OW SOL 315 24.090 19.910 12.490 1.00 0.00 +ATOM 1178 HW1 SOL 315 24.510 20.760 12.390 1.00 0.00 +ATOM 1179 HW2 SOL 315 24.580 19.470 13.180 1.00 0.00 +ATOM 1180 OW SOL 316 15.840 33.280 8.320 1.00 0.00 +ATOM 1181 HW1 SOL 316 15.590 33.450 9.230 1.00 0.00 +ATOM 1182 HW2 SOL 316 16.740 32.960 8.360 1.00 0.00 +ATOM 1183 OW SOL 317 1.280 32.550 26.290 1.00 0.00 +ATOM 1184 HW1 SOL 317 1.340 31.600 26.240 1.00 0.00 +ATOM 1185 HW2 SOL 317 2.110 32.820 26.700 1.00 0.00 +ATOM 1186 OW SOL 318 4.590 44.900 27.660 1.00 0.00 +ATOM 1187 HW1 SOL 318 5.410 45.230 27.290 1.00 0.00 +ATOM 1188 HW2 SOL 318 3.940 45.040 26.960 1.00 0.00 +ATOM 1189 OW SOL 319 37.090 8.260 14.590 1.00 0.00 +ATOM 1190 HW1 SOL 319 36.420 7.680 14.220 1.00 0.00 +ATOM 1191 HW2 SOL 319 37.300 7.870 15.440 1.00 0.00 +ATOM 1192 OW SOL 320 34.420 4.230 10.800 1.00 0.00 +ATOM 1193 HW1 SOL 320 33.830 4.970 10.640 1.00 0.00 +ATOM 1194 HW2 SOL 320 35.300 4.600 10.700 1.00 0.00 +ATOM 1195 OW SOL 321 29.010 8.540 1.620 1.00 0.00 +ATOM 1196 HW1 SOL 321 29.490 8.880 2.380 1.00 0.00 +ATOM 1197 HW2 SOL 321 29.660 8.070 1.110 1.00 0.00 +ATOM 1198 OW SOL 322 41.360 38.490 8.460 1.00 0.00 +ATOM 1199 HW1 SOL 322 41.430 37.530 8.400 1.00 0.00 +ATOM 1200 HW2 SOL 322 41.860 38.710 9.250 1.00 0.00 +ATOM 1201 OW SOL 323 41.750 37.710 29.500 1.00 0.00 +ATOM 1202 HW1 SOL 323 41.370 37.650 30.380 1.00 0.00 +ATOM 1203 HW2 SOL 323 41.080 38.140 28.970 1.00 0.00 +ATOM 1204 OW SOL 324 27.430 18.130 10.400 1.00 0.00 +ATOM 1205 HW1 SOL 324 27.340 19.070 10.540 1.00 0.00 +ATOM 1206 HW2 SOL 324 28.350 17.950 10.560 1.00 0.00 +ATOM 1207 OW SOL 325 19.570 26.410 24.940 1.00 0.00 +ATOM 1208 HW1 SOL 325 19.520 26.400 23.990 1.00 0.00 +ATOM 1209 HW2 SOL 325 19.750 27.320 25.170 1.00 0.00 +ATOM 1210 OW SOL 326 42.830 40.270 3.720 1.00 0.00 +ATOM 1211 HW1 SOL 326 43.010 40.430 4.650 1.00 0.00 +ATOM 1212 HW2 SOL 326 42.450 39.390 3.690 1.00 0.00 +ATOM 1213 OW SOL 327 19.760 39.940 10.030 1.00 0.00 +ATOM 1214 HW1 SOL 327 20.170 39.090 9.960 1.00 0.00 +ATOM 1215 HW2 SOL 327 20.340 40.530 9.550 1.00 0.00 +ATOM 1216 OW SOL 328 35.330 9.720 19.360 1.00 0.00 +ATOM 1217 HW1 SOL 328 35.250 8.860 18.950 1.00 0.00 +ATOM 1218 HW2 SOL 328 36.050 10.150 18.900 1.00 0.00 +ATOM 1219 OW SOL 329 8.450 41.160 5.350 1.00 0.00 +ATOM 1220 HW1 SOL 329 9.200 41.540 4.890 1.00 0.00 +ATOM 1221 HW2 SOL 329 8.110 40.500 4.750 1.00 0.00 +ATOM 1222 OW SOL 330 3.560 11.030 28.920 1.00 0.00 +ATOM 1223 HW1 SOL 330 3.780 10.110 28.770 1.00 0.00 +ATOM 1224 HW2 SOL 330 3.930 11.230 29.780 1.00 0.00 +ATOM 1225 OW SOL 331 10.130 42.910 3.340 1.00 0.00 +ATOM 1226 HW1 SOL 331 10.890 42.500 2.920 1.00 0.00 +ATOM 1227 HW2 SOL 331 9.780 43.490 2.670 1.00 0.00 +ATOM 1228 OW SOL 332 22.950 45.617 13.110 1.00 0.00 +ATOM 1229 HW1 SOL 332 23.640 46.287 13.200 1.00 0.00 +ATOM 1230 HW2 SOL 332 22.690 45.417 14.010 1.00 0.00 +ATOM 1231 OW SOL 333 18.610 24.010 7.260 1.00 0.00 +ATOM 1232 HW1 SOL 333 18.670 23.590 6.400 1.00 0.00 +ATOM 1233 HW2 SOL 333 18.920 23.340 7.870 1.00 0.00 +ATOM 1234 OW SOL 334 24.400 37.210 31.550 1.00 0.00 +ATOM 1235 HW1 SOL 334 23.810 36.970 32.260 1.00 0.00 +ATOM 1236 HW2 SOL 334 24.310 36.500 30.910 1.00 0.00 +ATOM 1237 OW SOL 335 22.450 5.750 11.320 1.00 0.00 +ATOM 1238 HW1 SOL 335 23.310 6.060 11.610 1.00 0.00 +ATOM 1239 HW2 SOL 335 22.220 6.350 10.610 1.00 0.00 +ATOM 1240 OW SOL 336 42.950 23.330 4.960 1.00 0.00 +ATOM 1241 HW1 SOL 336 43.150 24.160 5.380 1.00 0.00 +ATOM 1242 HW2 SOL 336 42.550 22.800 5.650 1.00 0.00 +ATOM 1243 OW SOL 337 19.120 18.030 8.340 1.00 0.00 +ATOM 1244 HW1 SOL 337 18.800 18.380 9.170 1.00 0.00 +ATOM 1245 HW2 SOL 337 19.710 18.700 8.010 1.00 0.00 +ATOM 1246 OW SOL 338 31.770 24.310 1.850 1.00 0.00 +ATOM 1247 HW1 SOL 338 32.720 24.260 1.920 1.00 0.00 +ATOM 1248 HW2 SOL 338 31.460 23.450 2.140 1.00 0.00 +ATOM 1249 OW SOL 339 9.170 26.530 0.730 1.00 0.00 +ATOM 1250 HW1 SOL 339 8.790 27.320 0.340 1.00 0.00 +ATOM 1251 HW2 SOL 339 10.000 26.410 0.270 1.00 0.00 +ATOM 1252 OW SOL 340 38.950 43.490 22.040 1.00 0.00 +ATOM 1253 HW1 SOL 340 39.280 42.900 22.720 1.00 0.00 +ATOM 1254 HW2 SOL 340 38.360 44.080 22.510 1.00 0.00 +ATOM 1255 OW SOL 341 3.380 45.717 11.330 1.00 0.00 +ATOM 1256 HW1 SOL 341 4.270 45.897 11.010 1.00 0.00 +ATOM 1257 HW2 SOL 341 3.500 45.007 11.960 1.00 0.00 +ATOM 1258 OW SOL 342 23.710 34.690 30.320 1.00 0.00 +ATOM 1259 HW1 SOL 342 23.800 35.020 29.430 1.00 0.00 +ATOM 1260 HW2 SOL 342 24.280 33.920 30.360 1.00 0.00 +ATOM 1261 OW SOL 343 27.840 1.310 21.970 1.00 0.00 +ATOM 1262 HW1 SOL 343 27.480 0.510 21.590 1.00 0.00 +ATOM 1263 HW2 SOL 343 28.760 1.120 22.130 1.00 0.00 +ATOM 1264 OW SOL 344 11.550 1.070 19.400 1.00 0.00 +ATOM 1265 HW1 SOL 344 11.710 1.310 20.310 1.00 0.00 +ATOM 1266 HW2 SOL 344 11.200 0.180 19.450 1.00 0.00 +ATOM 1267 OW SOL 345 17.820 12.710 24.110 1.00 0.00 +ATOM 1268 HW1 SOL 345 17.640 12.380 23.230 1.00 0.00 +ATOM 1269 HW2 SOL 345 18.760 12.900 24.120 1.00 0.00 +ATOM 1270 OW SOL 346 24.780 8.090 29.100 1.00 0.00 +ATOM 1271 HW1 SOL 346 24.320 7.280 28.880 1.00 0.00 +ATOM 1272 HW2 SOL 346 25.700 7.830 29.210 1.00 0.00 +ATOM 1273 OW SOL 347 14.810 38.380 28.120 1.00 0.00 +ATOM 1274 HW1 SOL 347 15.550 37.970 28.560 1.00 0.00 +ATOM 1275 HW2 SOL 347 14.480 39.020 28.760 1.00 0.00 +ATOM 1276 OW SOL 348 22.570 25.000 18.800 1.00 0.00 +ATOM 1277 HW1 SOL 348 22.370 25.110 17.870 1.00 0.00 +ATOM 1278 HW2 SOL 348 23.420 25.420 18.920 1.00 0.00 +ATOM 1279 OW SOL 349 15.480 11.100 9.580 1.00 0.00 +ATOM 1280 HW1 SOL 349 16.440 11.120 9.480 1.00 0.00 +ATOM 1281 HW2 SOL 349 15.150 11.230 8.690 1.00 0.00 +ATOM 1282 OW SOL 350 42.990 34.870 2.910 1.00 0.00 +ATOM 1283 HW1 SOL 350 42.420 34.880 3.680 1.00 0.00 +ATOM 1284 HW2 SOL 350 42.800 34.030 2.480 1.00 0.00 +ATOM 1285 OW SOL 351 28.490 30.300 2.610 1.00 0.00 +ATOM 1286 HW1 SOL 351 28.860 29.960 1.790 1.00 0.00 +ATOM 1287 HW2 SOL 351 27.590 29.970 2.610 1.00 0.00 +ATOM 1288 OW SOL 352 10.860 19.910 23.220 1.00 0.00 +ATOM 1289 HW1 SOL 352 10.560 19.810 24.120 1.00 0.00 +ATOM 1290 HW2 SOL 352 10.640 19.080 22.800 1.00 0.00 +ATOM 1291 OW SOL 353 0.190 19.690 15.210 1.00 0.00 +ATOM 1292 HW1 SOL 353 0.660 20.500 15.390 1.00 0.00 +ATOM 1293 HW2 SOL 353 -0.540 19.690 15.820 1.00 0.00 +ATOM 1294 OW SOL 354 15.280 29.150 17.800 1.00 0.00 +ATOM 1295 HW1 SOL 354 15.190 30.000 17.360 1.00 0.00 +ATOM 1296 HW2 SOL 354 16.170 29.160 18.150 1.00 0.00 +ATOM 1297 OW SOL 355 11.870 10.610 2.850 1.00 0.00 +ATOM 1298 HW1 SOL 355 11.790 10.580 1.890 1.00 0.00 +ATOM 1299 HW2 SOL 355 12.800 10.770 3.000 1.00 0.00 +ATOM 1300 OW SOL 356 24.590 20.850 5.220 1.00 0.00 +ATOM 1301 HW1 SOL 356 24.430 19.930 5.430 1.00 0.00 +ATOM 1302 HW2 SOL 356 25.230 21.140 5.870 1.00 0.00 +ATOM 1303 OW SOL 357 40.790 39.350 11.200 1.00 0.00 +ATOM 1304 HW1 SOL 357 40.490 39.210 10.300 1.00 0.00 +ATOM 1305 HW2 SOL 357 40.680 40.290 11.340 1.00 0.00 +ATOM 1306 OW SOL 358 35.310 22.180 6.040 1.00 0.00 +ATOM 1307 HW1 SOL 358 35.150 22.910 5.440 1.00 0.00 +ATOM 1308 HW2 SOL 358 34.440 21.930 6.340 1.00 0.00 +ATOM 1309 OW SOL 359 40.970 12.000 27.070 1.00 0.00 +ATOM 1310 HW1 SOL 359 41.650 12.430 26.540 1.00 0.00 +ATOM 1311 HW2 SOL 359 40.570 11.370 26.470 1.00 0.00 +ATOM 1312 OW SOL 360 31.980 32.610 8.690 1.00 0.00 +ATOM 1313 HW1 SOL 360 32.530 32.820 9.450 1.00 0.00 +ATOM 1314 HW2 SOL 360 31.720 31.700 8.830 1.00 0.00 +ATOM 1315 OW SOL 361 15.070 6.390 17.640 1.00 0.00 +ATOM 1316 HW1 SOL 361 14.680 6.390 18.510 1.00 0.00 +ATOM 1317 HW2 SOL 361 14.370 6.070 17.070 1.00 0.00 +ATOM 1318 OW SOL 362 9.020 32.920 6.310 1.00 0.00 +ATOM 1319 HW1 SOL 362 9.730 32.660 5.740 1.00 0.00 +ATOM 1320 HW2 SOL 362 9.440 33.110 7.150 1.00 0.00 +ATOM 1321 OW SOL 363 15.310 16.430 25.500 1.00 0.00 +ATOM 1322 HW1 SOL 363 16.140 15.970 25.430 1.00 0.00 +ATOM 1323 HW2 SOL 363 14.730 15.820 25.940 1.00 0.00 +ATOM 1324 OW SOL 364 10.460 11.950 12.860 1.00 0.00 +ATOM 1325 HW1 SOL 364 11.380 11.730 12.970 1.00 0.00 +ATOM 1326 HW2 SOL 364 9.990 11.160 13.120 1.00 0.00 +ATOM 1327 OW SOL 365 20.550 27.000 16.840 1.00 0.00 +ATOM 1328 HW1 SOL 365 20.310 26.760 17.740 1.00 0.00 +ATOM 1329 HW2 SOL 365 19.820 27.530 16.530 1.00 0.00 +ATOM 1330 OW SOL 366 1.470 8.720 0.310 1.00 0.00 +ATOM 1331 HW1 SOL 366 1.610 9.520 0.800 1.00 0.00 +ATOM 1332 HW2 SOL 366 2.270 8.600 -0.200 1.00 0.00 +ATOM 1333 OW SOL 367 42.140 37.290 12.350 1.00 0.00 +ATOM 1334 HW1 SOL 367 41.930 38.180 12.080 1.00 0.00 +ATOM 1335 HW2 SOL 367 41.300 36.860 12.460 1.00 0.00 +ATOM 1336 OW SOL 368 36.920 15.720 5.380 1.00 0.00 +ATOM 1337 HW1 SOL 368 36.240 15.320 4.840 1.00 0.00 +ATOM 1338 HW2 SOL 368 37.000 16.610 5.040 1.00 0.00 +ATOM 1339 OW SOL 369 2.170 15.470 31.190 1.00 0.00 +ATOM 1340 HW1 SOL 369 2.010 14.870 30.460 1.00 0.00 +ATOM 1341 HW2 SOL 369 2.130 14.920 31.970 1.00 0.00 +ATOM 1342 OW SOL 370 37.760 30.100 29.060 1.00 0.00 +ATOM 1343 HW1 SOL 370 36.910 29.740 28.800 1.00 0.00 +ATOM 1344 HW2 SOL 370 37.730 30.120 30.010 1.00 0.00 +ATOM 1345 OW SOL 371 32.820 14.820 12.390 1.00 0.00 +ATOM 1346 HW1 SOL 371 33.320 15.620 12.280 1.00 0.00 +ATOM 1347 HW2 SOL 371 33.420 14.220 12.840 1.00 0.00 +ATOM 1348 OW SOL 372 20.210 6.010 20.330 1.00 0.00 +ATOM 1349 HW1 SOL 372 20.030 5.860 19.410 1.00 0.00 +ATOM 1350 HW2 SOL 372 19.600 6.700 20.590 1.00 0.00 +ATOM 1351 OW SOL 373 11.930 20.440 7.910 1.00 0.00 +ATOM 1352 HW1 SOL 373 12.020 20.810 7.030 1.00 0.00 +ATOM 1353 HW2 SOL 373 12.550 20.940 8.440 1.00 0.00 +ATOM 1354 OW SOL 374 37.620 29.930 25.210 1.00 0.00 +ATOM 1355 HW1 SOL 374 36.770 29.510 25.310 1.00 0.00 +ATOM 1356 HW2 SOL 374 38.030 29.470 24.480 1.00 0.00 +ATOM 1357 OW SOL 375 27.260 16.600 15.620 1.00 0.00 +ATOM 1358 HW1 SOL 375 27.730 15.770 15.720 1.00 0.00 +ATOM 1359 HW2 SOL 375 27.820 17.130 15.060 1.00 0.00 +ATOM 1360 OW SOL 376 10.690 29.330 27.350 1.00 0.00 +ATOM 1361 HW1 SOL 376 10.920 28.420 27.190 1.00 0.00 +ATOM 1362 HW2 SOL 376 10.120 29.310 28.120 1.00 0.00 +ATOM 1363 OW SOL 377 23.250 27.980 29.090 1.00 0.00 +ATOM 1364 HW1 SOL 377 22.490 27.400 29.130 1.00 0.00 +ATOM 1365 HW2 SOL 377 23.140 28.560 29.840 1.00 0.00 +ATOM 1366 OW SOL 378 24.620 3.830 24.030 1.00 0.00 +ATOM 1367 HW1 SOL 378 24.400 4.760 23.940 1.00 0.00 +ATOM 1368 HW2 SOL 378 24.160 3.400 23.310 1.00 0.00 +ATOM 1369 OW SOL 379 8.160 19.590 8.690 1.00 0.00 +ATOM 1370 HW1 SOL 379 8.210 19.770 7.750 1.00 0.00 +ATOM 1371 HW2 SOL 379 8.640 20.310 9.100 1.00 0.00 +ATOM 1372 OW SOL 380 10.490 6.110 30.830 1.00 0.00 +ATOM 1373 HW1 SOL 380 11.210 6.100 30.190 1.00 0.00 +ATOM 1374 HW2 SOL 380 10.590 6.950 31.280 1.00 0.00 +ATOM 1375 OW SOL 381 48.659 39.649 34.208 1.00 0.00 +ATOM 1376 HW1 SOL 381 49.619 39.689 34.168 1.00 0.00 +ATOM 1377 HW2 SOL 381 48.399 39.309 33.348 1.00 0.00 +ATOM 1378 OW SOL 382 20.070 4.830 29.800 1.00 0.00 +ATOM 1379 HW1 SOL 382 20.950 5.200 29.760 1.00 0.00 +ATOM 1380 HW2 SOL 382 20.110 4.190 30.510 1.00 0.00 +ATOM 1381 OW SOL 383 1.390 34.370 14.750 1.00 0.00 +ATOM 1382 HW1 SOL 383 1.620 35.290 14.650 1.00 0.00 +ATOM 1383 HW2 SOL 383 0.880 34.330 15.560 1.00 0.00 +ATOM 1384 OW SOL 384 5.700 44.490 14.030 1.00 0.00 +ATOM 1385 HW1 SOL 384 5.760 44.010 14.850 1.00 0.00 +ATOM 1386 HW2 SOL 384 6.080 43.910 13.380 1.00 0.00 +ATOM 1387 OW SOL 385 41.670 13.960 9.750 1.00 0.00 +ATOM 1388 HW1 SOL 385 41.300 13.080 9.780 1.00 0.00 +ATOM 1389 HW2 SOL 385 40.930 14.540 9.910 1.00 0.00 +ATOM 1390 OW SOL 386 17.570 18.070 20.620 1.00 0.00 +ATOM 1391 HW1 SOL 386 18.070 18.800 20.260 1.00 0.00 +ATOM 1392 HW2 SOL 386 17.340 17.540 19.850 1.00 0.00 +ATOM 1393 OW SOL 387 23.610 23.160 12.720 1.00 0.00 +ATOM 1394 HW1 SOL 387 23.720 23.090 13.670 1.00 0.00 +ATOM 1395 HW2 SOL 387 24.420 22.810 12.360 1.00 0.00 +ATOM 1396 OW SOL 388 26.860 42.930 24.370 1.00 0.00 +ATOM 1397 HW1 SOL 388 27.010 42.640 23.480 1.00 0.00 +ATOM 1398 HW2 SOL 388 25.980 42.610 24.590 1.00 0.00 +ATOM 1399 OW SOL 389 30.130 16.080 7.990 1.00 0.00 +ATOM 1400 HW1 SOL 389 30.350 16.580 7.210 1.00 0.00 +ATOM 1401 HW2 SOL 389 29.800 15.240 7.660 1.00 0.00 +ATOM 1402 OW SOL 390 13.450 42.420 15.870 1.00 0.00 +ATOM 1403 HW1 SOL 390 12.530 42.300 16.120 1.00 0.00 +ATOM 1404 HW2 SOL 390 13.490 42.150 14.950 1.00 0.00 +ATOM 1405 OW SOL 391 32.590 7.400 5.110 1.00 0.00 +ATOM 1406 HW1 SOL 391 33.510 7.580 4.940 1.00 0.00 +ATOM 1407 HW2 SOL 391 32.600 6.670 5.730 1.00 0.00 +ATOM 1408 OW SOL 392 16.150 28.550 7.370 1.00 0.00 +ATOM 1409 HW1 SOL 392 16.500 28.900 8.190 1.00 0.00 +ATOM 1410 HW2 SOL 392 16.890 28.060 6.990 1.00 0.00 +ATOM 1411 OW SOL 393 44.610 29.620 31.920 1.00 0.00 +ATOM 1412 HW1 SOL 393 45.140 29.220 31.230 1.00 0.00 +ATOM 1413 HW2 SOL 393 43.750 29.750 31.520 1.00 0.00 +ATOM 1414 OW SOL 394 25.230 19.270 25.790 1.00 0.00 +ATOM 1415 HW1 SOL 394 25.490 19.440 24.880 1.00 0.00 +ATOM 1416 HW2 SOL 394 24.480 19.860 25.940 1.00 0.00 +ATOM 1417 OW SOL 395 15.880 33.040 11.130 1.00 0.00 +ATOM 1418 HW1 SOL 395 15.100 33.370 11.580 1.00 0.00 +ATOM 1419 HW2 SOL 395 16.470 32.770 11.830 1.00 0.00 +ATOM 1420 OW SOL 396 3.140 13.770 11.320 1.00 0.00 +ATOM 1421 HW1 SOL 396 2.950 14.410 10.640 1.00 0.00 +ATOM 1422 HW2 SOL 396 2.880 14.210 12.130 1.00 0.00 +ATOM 1423 OW SOL 397 22.850 1.290 27.490 1.00 0.00 +ATOM 1424 HW1 SOL 397 22.830 0.740 26.700 1.00 0.00 +ATOM 1425 HW2 SOL 397 22.410 0.760 28.160 1.00 0.00 +ATOM 1426 OW SOL 398 27.400 19.420 27.530 1.00 0.00 +ATOM 1427 HW1 SOL 398 26.830 19.450 26.760 1.00 0.00 +ATOM 1428 HW2 SOL 398 26.800 19.310 28.270 1.00 0.00 +ATOM 1429 OW SOL 399 21.250 42.400 13.970 1.00 0.00 +ATOM 1430 HW1 SOL 399 21.150 41.730 14.650 1.00 0.00 +ATOM 1431 HW2 SOL 399 20.410 42.400 13.510 1.00 0.00 +ATOM 1432 OW SOL 400 30.160 32.090 3.560 1.00 0.00 +ATOM 1433 HW1 SOL 400 29.490 31.460 3.300 1.00 0.00 +ATOM 1434 HW2 SOL 400 30.970 31.770 3.150 1.00 0.00 +ATOM 1435 OW SOL 401 24.800 9.290 2.040 1.00 0.00 +ATOM 1436 HW1 SOL 401 24.900 10.070 2.590 1.00 0.00 +ATOM 1437 HW2 SOL 401 24.650 8.570 2.660 1.00 0.00 +ATOM 1438 OW SOL 402 12.781 -3.269 -0.248 1.00 0.00 +ATOM 1439 HW1 SOL 402 12.671 -2.399 -0.628 1.00 0.00 +ATOM 1440 HW2 SOL 402 11.941 -3.699 -0.408 1.00 0.00 +ATOM 1441 OW SOL 403 5.960 28.840 0.960 1.00 0.00 +ATOM 1442 HW1 SOL 403 5.730 27.920 1.070 1.00 0.00 +ATOM 1443 HW2 SOL 403 6.120 28.930 0.020 1.00 0.00 +ATOM 1444 OW SOL 404 34.810 19.590 0.130 1.00 0.00 +ATOM 1445 HW1 SOL 404 35.320 20.350 -0.150 1.00 0.00 +ATOM 1446 HW2 SOL 404 34.540 19.170 -0.690 1.00 0.00 +ATOM 1447 OW SOL 405 37.230 20.320 6.800 1.00 0.00 +ATOM 1448 HW1 SOL 405 37.270 19.700 6.070 1.00 0.00 +ATOM 1449 HW2 SOL 405 36.540 20.930 6.550 1.00 0.00 +ATOM 1450 OW SOL 406 34.950 10.110 15.720 1.00 0.00 +ATOM 1451 HW1 SOL 406 35.140 10.480 14.860 1.00 0.00 +ATOM 1452 HW2 SOL 406 35.790 10.170 16.190 1.00 0.00 +ATOM 1453 OW SOL 407 25.550 38.840 18.720 1.00 0.00 +ATOM 1454 HW1 SOL 407 25.040 38.040 18.550 1.00 0.00 +ATOM 1455 HW2 SOL 407 26.460 38.560 18.640 1.00 0.00 +ATOM 1456 OW SOL 408 27.090 30.850 19.580 1.00 0.00 +ATOM 1457 HW1 SOL 408 27.460 30.660 18.720 1.00 0.00 +ATOM 1458 HW2 SOL 408 27.840 30.940 20.160 1.00 0.00 +ATOM 1459 OW SOL 409 26.580 0.510 26.790 1.00 0.00 +ATOM 1460 HW1 SOL 409 25.990 1.270 26.760 1.00 0.00 +ATOM 1461 HW2 SOL 409 27.130 0.600 26.010 1.00 0.00 +ATOM 1462 OW SOL 410 30.220 13.010 10.830 1.00 0.00 +ATOM 1463 HW1 SOL 410 29.900 12.140 11.090 1.00 0.00 +ATOM 1464 HW2 SOL 410 30.170 13.540 11.620 1.00 0.00 +ATOM 1465 OW SOL 411 30.550 14.700 13.810 1.00 0.00 +ATOM 1466 HW1 SOL 411 30.960 14.650 14.670 1.00 0.00 +ATOM 1467 HW2 SOL 411 31.280 14.740 13.190 1.00 0.00 +ATOM 1468 OW SOL 412 18.900 5.960 6.320 1.00 0.00 +ATOM 1469 HW1 SOL 412 18.920 6.260 7.230 1.00 0.00 +ATOM 1470 HW2 SOL 412 18.670 6.730 5.810 1.00 0.00 +ATOM 1471 OW SOL 413 5.490 24.850 30.330 1.00 0.00 +ATOM 1472 HW1 SOL 413 4.880 24.530 30.990 1.00 0.00 +ATOM 1473 HW2 SOL 413 5.160 25.720 30.100 1.00 0.00 +ATOM 1474 OW SOL 414 16.430 24.120 2.040 1.00 0.00 +ATOM 1475 HW1 SOL 414 16.630 24.850 2.620 1.00 0.00 +ATOM 1476 HW2 SOL 414 16.240 24.540 1.190 1.00 0.00 +ATOM 1477 OW SOL 415 -9.879 4.021 -0.868 1.00 0.00 +ATOM 1478 HW1 SOL 415 -9.689 3.801 -1.788 1.00 0.00 +ATOM 1479 HW2 SOL 415 -9.859 4.971 -0.838 1.00 0.00 +ATOM 1480 OW SOL 416 1.670 34.770 5.630 1.00 0.00 +ATOM 1481 HW1 SOL 416 2.230 35.060 4.910 1.00 0.00 +ATOM 1482 HW2 SOL 416 2.280 34.530 6.330 1.00 0.00 +ATOM 1483 OW SOL 417 0.780 7.500 27.150 1.00 0.00 +ATOM 1484 HW1 SOL 417 1.720 7.690 27.120 1.00 0.00 +ATOM 1485 HW2 SOL 417 0.370 8.280 26.760 1.00 0.00 +ATOM 1486 OW SOL 418 4.470 14.850 21.250 1.00 0.00 +ATOM 1487 HW1 SOL 418 4.390 13.900 21.170 1.00 0.00 +ATOM 1488 HW2 SOL 418 4.420 15.170 20.350 1.00 0.00 +ATOM 1489 OW SOL 419 18.970 34.620 25.690 1.00 0.00 +ATOM 1490 HW1 SOL 419 18.400 35.250 26.140 1.00 0.00 +ATOM 1491 HW2 SOL 419 19.010 34.950 24.790 1.00 0.00 +ATOM 1492 OW SOL 420 10.360 1.770 24.380 1.00 0.00 +ATOM 1493 HW1 SOL 420 9.500 1.450 24.100 1.00 0.00 +ATOM 1494 HW2 SOL 420 10.670 1.120 25.010 1.00 0.00 +ATOM 1495 OW SOL 421 7.610 25.460 2.710 1.00 0.00 +ATOM 1496 HW1 SOL 421 8.060 25.760 1.920 1.00 0.00 +ATOM 1497 HW2 SOL 421 7.030 24.770 2.400 1.00 0.00 +ATOM 1498 OW SOL 422 15.830 2.290 11.020 1.00 0.00 +ATOM 1499 HW1 SOL 422 16.670 2.230 10.550 1.00 0.00 +ATOM 1500 HW2 SOL 422 15.540 3.190 10.880 1.00 0.00 +ATOM 1501 OW SOL 423 4.350 6.050 31.240 1.00 0.00 +ATOM 1502 HW1 SOL 423 5.280 5.940 31.040 1.00 0.00 +ATOM 1503 HW2 SOL 423 4.130 5.290 31.790 1.00 0.00 +ATOM 1504 OW SOL 424 0.310 36.950 14.230 1.00 0.00 +ATOM 1505 HW1 SOL 424 1.120 37.410 14.440 1.00 0.00 +ATOM 1506 HW2 SOL 424 0.240 37.010 13.270 1.00 0.00 +ATOM 1507 OW SOL 425 23.450 1.530 16.340 1.00 0.00 +ATOM 1508 HW1 SOL 425 23.960 1.740 15.560 1.00 0.00 +ATOM 1509 HW2 SOL 425 22.770 0.930 16.030 1.00 0.00 +ATOM 1510 OW SOL 426 29.930 12.770 16.690 1.00 0.00 +ATOM 1511 HW1 SOL 426 30.840 12.490 16.670 1.00 0.00 +ATOM 1512 HW2 SOL 426 29.760 12.980 17.610 1.00 0.00 +ATOM 1513 OW SOL 427 5.130 11.300 5.680 1.00 0.00 +ATOM 1514 HW1 SOL 427 4.340 11.230 6.220 1.00 0.00 +ATOM 1515 HW2 SOL 427 5.840 11.430 6.310 1.00 0.00 +ATOM 1516 OW SOL 428 40.570 24.440 25.710 1.00 0.00 +ATOM 1517 HW1 SOL 428 40.610 25.030 26.470 1.00 0.00 +ATOM 1518 HW2 SOL 428 40.510 25.030 24.960 1.00 0.00 +ATOM 1519 OW SOL 429 32.920 9.440 12.670 1.00 0.00 +ATOM 1520 HW1 SOL 429 33.870 9.480 12.580 1.00 0.00 +ATOM 1521 HW2 SOL 429 32.620 8.950 11.900 1.00 0.00 +ATOM 1522 OW SOL 430 18.900 44.640 8.880 1.00 0.00 +ATOM 1523 HW1 SOL 430 18.690 45.560 8.690 1.00 0.00 +ATOM 1524 HW2 SOL 430 18.050 44.190 8.850 1.00 0.00 +ATOM 1525 OW SOL 431 18.550 47.207 6.880 1.00 0.00 +ATOM 1526 HW1 SOL 431 18.310 46.947 5.990 1.00 0.00 +ATOM 1527 HW2 SOL 431 19.500 47.167 6.900 1.00 0.00 +ATOM 1528 OW SOL 432 15.740 27.620 0.720 1.00 0.00 +ATOM 1529 HW1 SOL 432 15.880 28.280 1.400 1.00 0.00 +ATOM 1530 HW2 SOL 432 15.020 27.080 1.050 1.00 0.00 +ATOM 1531 OW SOL 433 17.590 31.680 25.880 1.00 0.00 +ATOM 1532 HW1 SOL 433 18.400 32.150 26.100 1.00 0.00 +ATOM 1533 HW2 SOL 433 16.980 32.380 25.630 1.00 0.00 +ATOM 1534 OW SOL 434 39.390 35.650 26.130 1.00 0.00 +ATOM 1535 HW1 SOL 434 38.650 35.560 26.730 1.00 0.00 +ATOM 1536 HW2 SOL 434 39.310 36.540 25.780 1.00 0.00 +ATOM 1537 OW SOL 435 41.840 32.560 1.750 1.00 0.00 +ATOM 1538 HW1 SOL 435 42.200 31.720 2.040 1.00 0.00 +ATOM 1539 HW2 SOL 435 41.100 32.320 1.190 1.00 0.00 +ATOM 1540 OW SOL 436 34.650 9.320 0.510 1.00 0.00 +ATOM 1541 HW1 SOL 436 34.350 8.690 -0.150 1.00 0.00 +ATOM 1542 HW2 SOL 436 34.150 10.120 0.330 1.00 0.00 +ATOM 1543 OW SOL 437 11.740 4.600 3.080 1.00 0.00 +ATOM 1544 HW1 SOL 437 12.370 4.140 3.630 1.00 0.00 +ATOM 1545 HW2 SOL 437 11.190 5.090 3.690 1.00 0.00 +ATOM 1546 OW SOL 438 12.310 15.840 23.900 1.00 0.00 +ATOM 1547 HW1 SOL 438 12.240 15.010 23.420 1.00 0.00 +ATOM 1548 HW2 SOL 438 13.130 15.760 24.390 1.00 0.00 +ATOM 1549 OW SOL 439 5.700 8.350 22.500 1.00 0.00 +ATOM 1550 HW1 SOL 439 6.370 7.690 22.650 1.00 0.00 +ATOM 1551 HW2 SOL 439 4.880 7.910 22.720 1.00 0.00 +ATOM 1552 OW SOL 440 14.730 27.590 25.980 1.00 0.00 +ATOM 1553 HW1 SOL 440 15.480 27.000 25.890 1.00 0.00 +ATOM 1554 HW2 SOL 440 13.980 27.010 26.120 1.00 0.00 +ATOM 1555 OW SOL 441 25.990 31.360 11.310 1.00 0.00 +ATOM 1556 HW1 SOL 441 26.290 30.490 11.040 1.00 0.00 +ATOM 1557 HW2 SOL 441 26.420 31.960 10.690 1.00 0.00 +ATOM 1558 OW SOL 442 22.040 33.070 7.010 1.00 0.00 +ATOM 1559 HW1 SOL 442 22.620 33.750 6.660 1.00 0.00 +ATOM 1560 HW2 SOL 442 21.560 33.500 7.710 1.00 0.00 +ATOM 1561 OW SOL 443 11.330 37.870 16.020 1.00 0.00 +ATOM 1562 HW1 SOL 443 10.400 37.730 16.210 1.00 0.00 +ATOM 1563 HW2 SOL 443 11.740 37.940 16.880 1.00 0.00 +ATOM 1564 OW SOL 444 7.340 15.510 20.230 1.00 0.00 +ATOM 1565 HW1 SOL 444 6.750 16.260 20.160 1.00 0.00 +ATOM 1566 HW2 SOL 444 7.990 15.770 20.880 1.00 0.00 +ATOM 1567 OW SOL 445 31.310 14.710 29.610 1.00 0.00 +ATOM 1568 HW1 SOL 445 31.180 14.090 28.900 1.00 0.00 +ATOM 1569 HW2 SOL 445 32.080 14.390 30.080 1.00 0.00 +ATOM 1570 OW SOL 446 19.980 0.480 24.750 1.00 0.00 +ATOM 1571 HW1 SOL 446 19.330 -0.160 24.460 1.00 0.00 +ATOM 1572 HW2 SOL 446 19.530 1.010 25.400 1.00 0.00 +ATOM 1573 OW SOL 447 32.230 40.810 15.610 1.00 0.00 +ATOM 1574 HW1 SOL 447 32.470 41.090 14.730 1.00 0.00 +ATOM 1575 HW2 SOL 447 32.580 39.920 15.680 1.00 0.00 +ATOM 1576 OW SOL 448 23.520 12.830 19.430 1.00 0.00 +ATOM 1577 HW1 SOL 448 23.520 12.090 18.820 1.00 0.00 +ATOM 1578 HW2 SOL 448 24.000 12.510 20.200 1.00 0.00 +ATOM 1579 OW SOL 449 8.410 30.660 2.720 1.00 0.00 +ATOM 1580 HW1 SOL 449 8.590 29.840 3.160 1.00 0.00 +ATOM 1581 HW2 SOL 449 7.460 30.640 2.560 1.00 0.00 +ATOM 1582 OW SOL 450 30.980 11.480 8.390 1.00 0.00 +ATOM 1583 HW1 SOL 450 30.060 11.240 8.260 1.00 0.00 +ATOM 1584 HW2 SOL 450 31.040 11.710 9.320 1.00 0.00 +ATOM 1585 OW SOL 451 26.320 22.530 6.690 1.00 0.00 +ATOM 1586 HW1 SOL 451 27.190 22.540 6.300 1.00 0.00 +ATOM 1587 HW2 SOL 451 25.870 23.270 6.280 1.00 0.00 +ATOM 1588 OW SOL 452 18.720 2.530 26.260 1.00 0.00 +ATOM 1589 HW1 SOL 452 19.620 2.790 26.460 1.00 0.00 +ATOM 1590 HW2 SOL 452 18.340 3.310 25.850 1.00 0.00 +ATOM 1591 OW SOL 453 15.220 2.130 7.100 1.00 0.00 +ATOM 1592 HW1 SOL 453 14.330 1.970 6.790 1.00 0.00 +ATOM 1593 HW2 SOL 453 15.130 2.260 8.040 1.00 0.00 +ATOM 1594 OW SOL 454 43.570 16.700 5.790 1.00 0.00 +ATOM 1595 HW1 SOL 454 43.330 15.870 6.180 1.00 0.00 +ATOM 1596 HW2 SOL 454 43.800 17.260 6.530 1.00 0.00 +ATOM 1597 OW SOL 455 19.680 43.650 27.550 1.00 0.00 +ATOM 1598 HW1 SOL 455 19.090 43.360 28.250 1.00 0.00 +ATOM 1599 HW2 SOL 455 19.100 44.090 26.920 1.00 0.00 +ATOM 1600 OW SOL 456 32.790 40.860 27.640 1.00 0.00 +ATOM 1601 HW1 SOL 456 33.200 40.440 26.890 1.00 0.00 +ATOM 1602 HW2 SOL 456 32.190 40.210 27.990 1.00 0.00 +ATOM 1603 OW SOL 457 13.920 26.860 4.830 1.00 0.00 +ATOM 1604 HW1 SOL 457 13.290 26.560 5.480 1.00 0.00 +ATOM 1605 HW2 SOL 457 13.980 27.810 4.970 1.00 0.00 +ATOM 1606 OW SOL 458 18.210 14.610 0.090 1.00 0.00 +ATOM 1607 HW1 SOL 458 18.860 13.900 0.050 1.00 0.00 +ATOM 1608 HW2 SOL 458 18.130 14.810 1.020 1.00 0.00 +ATOM 1609 OW SOL 459 0.540 2.760 2.480 1.00 0.00 +ATOM 1610 HW1 SOL 459 -0.130 2.080 2.540 1.00 0.00 +ATOM 1611 HW2 SOL 459 0.660 2.900 1.540 1.00 0.00 +ATOM 1612 OW SOL 460 31.500 41.600 12.880 1.00 0.00 +ATOM 1613 HW1 SOL 460 30.610 41.790 13.190 1.00 0.00 +ATOM 1614 HW2 SOL 460 31.540 40.650 12.850 1.00 0.00 +ATOM 1615 OW SOL 461 6.460 33.110 12.390 1.00 0.00 +ATOM 1616 HW1 SOL 461 5.640 32.730 12.090 1.00 0.00 +ATOM 1617 HW2 SOL 461 6.460 32.970 13.340 1.00 0.00 +ATOM 1618 OW SOL 462 4.500 25.360 15.120 1.00 0.00 +ATOM 1619 HW1 SOL 462 5.020 25.240 14.330 1.00 0.00 +ATOM 1620 HW2 SOL 462 4.460 26.300 15.250 1.00 0.00 +ATOM 1621 OW SOL 463 15.980 24.010 20.360 1.00 0.00 +ATOM 1622 HW1 SOL 463 16.700 23.450 20.050 1.00 0.00 +ATOM 1623 HW2 SOL 463 15.940 23.850 21.300 1.00 0.00 +ATOM 1624 OW SOL 464 17.090 28.050 24.010 1.00 0.00 +ATOM 1625 HW1 SOL 464 16.140 28.000 23.880 1.00 0.00 +ATOM 1626 HW2 SOL 464 17.200 27.980 24.960 1.00 0.00 +ATOM 1627 OW SOL 465 24.500 24.420 31.380 1.00 0.00 +ATOM 1628 HW1 SOL 465 24.040 25.230 31.150 1.00 0.00 +ATOM 1629 HW2 SOL 465 25.420 24.670 31.460 1.00 0.00 +ATOM 1630 OW SOL 466 16.010 24.820 7.260 1.00 0.00 +ATOM 1631 HW1 SOL 466 16.180 25.270 6.430 1.00 0.00 +ATOM 1632 HW2 SOL 466 16.870 24.710 7.650 1.00 0.00 +ATOM 1633 OW SOL 467 15.590 14.120 20.990 1.00 0.00 +ATOM 1634 HW1 SOL 467 15.340 14.760 21.650 1.00 0.00 +ATOM 1635 HW2 SOL 467 15.400 14.540 20.150 1.00 0.00 +ATOM 1636 OW SOL 468 26.700 13.060 18.240 1.00 0.00 +ATOM 1637 HW1 SOL 468 26.410 12.920 17.340 1.00 0.00 +ATOM 1638 HW2 SOL 468 26.130 12.500 18.770 1.00 0.00 +ATOM 1639 OW SOL 469 29.960 6.800 19.840 1.00 0.00 +ATOM 1640 HW1 SOL 469 29.640 6.560 18.970 1.00 0.00 +ATOM 1641 HW2 SOL 469 30.510 7.570 19.690 1.00 0.00 +ATOM 1642 OW SOL 470 12.530 31.780 25.040 1.00 0.00 +ATOM 1643 HW1 SOL 470 13.100 31.940 25.790 1.00 0.00 +ATOM 1644 HW2 SOL 470 13.080 31.330 24.400 1.00 0.00 +ATOM 1645 OW SOL 471 35.960 26.000 26.570 1.00 0.00 +ATOM 1646 HW1 SOL 471 36.640 25.340 26.410 1.00 0.00 +ATOM 1647 HW2 SOL 471 35.600 26.180 25.700 1.00 0.00 +ATOM 1648 OW SOL 472 30.170 1.200 31.530 1.00 0.00 +ATOM 1649 HW1 SOL 472 29.360 1.360 31.040 1.00 0.00 +ATOM 1650 HW2 SOL 472 30.770 1.880 31.250 1.00 0.00 +ATOM 1651 OW SOL 473 8.420 1.940 21.360 1.00 0.00 +ATOM 1652 HW1 SOL 473 8.900 1.190 21.020 1.00 0.00 +ATOM 1653 HW2 SOL 473 8.160 1.690 22.240 1.00 0.00 +ATOM 1654 OW SOL 474 37.050 38.670 6.280 1.00 0.00 +ATOM 1655 HW1 SOL 474 37.560 39.160 6.920 1.00 0.00 +ATOM 1656 HW2 SOL 474 37.700 38.310 5.670 1.00 0.00 +ATOM 1657 OW SOL 475 3.040 23.080 21.590 1.00 0.00 +ATOM 1658 HW1 SOL 475 3.490 23.860 21.240 1.00 0.00 +ATOM 1659 HW2 SOL 475 2.990 22.490 20.840 1.00 0.00 +ATOM 1660 OW SOL 476 28.660 39.550 1.460 1.00 0.00 +ATOM 1661 HW1 SOL 476 29.360 40.200 1.450 1.00 0.00 +ATOM 1662 HW2 SOL 476 28.550 39.300 0.540 1.00 0.00 +ATOM 1663 OW SOL 477 41.440 2.280 13.520 1.00 0.00 +ATOM 1664 HW1 SOL 477 40.530 2.480 13.740 1.00 0.00 +ATOM 1665 HW2 SOL 477 41.600 1.410 13.890 1.00 0.00 +ATOM 1666 OW SOL 478 41.210 24.900 15.370 1.00 0.00 +ATOM 1667 HW1 SOL 478 41.340 24.700 14.440 1.00 0.00 +ATOM 1668 HW2 SOL 478 40.680 25.690 15.360 1.00 0.00 +ATOM 1669 OW SOL 479 33.320 38.660 10.380 1.00 0.00 +ATOM 1670 HW1 SOL 479 33.530 38.270 9.540 1.00 0.00 +ATOM 1671 HW2 SOL 479 33.400 39.610 10.240 1.00 0.00 +ATOM 1672 OW SOL 480 32.870 16.790 26.930 1.00 0.00 +ATOM 1673 HW1 SOL 480 32.080 16.260 26.930 1.00 0.00 +ATOM 1674 HW2 SOL 480 33.580 16.170 27.070 1.00 0.00 +ATOM 1675 OW SOL 481 9.790 13.590 25.190 1.00 0.00 +ATOM 1676 HW1 SOL 481 10.290 12.770 25.220 1.00 0.00 +ATOM 1677 HW2 SOL 481 10.460 14.270 25.150 1.00 0.00 +ATOM 1678 OW SOL 482 2.470 6.330 1.920 1.00 0.00 +ATOM 1679 HW1 SOL 482 1.890 5.750 2.410 1.00 0.00 +ATOM 1680 HW2 SOL 482 1.900 7.030 1.620 1.00 0.00 +ATOM 1681 OW SOL 483 20.910 7.730 15.470 1.00 0.00 +ATOM 1682 HW1 SOL 483 20.910 7.000 14.860 1.00 0.00 +ATOM 1683 HW2 SOL 483 20.390 8.410 15.030 1.00 0.00 +ATOM 1684 OW SOL 484 18.380 10.650 19.420 1.00 0.00 +ATOM 1685 HW1 SOL 484 18.100 10.110 18.680 1.00 0.00 +ATOM 1686 HW2 SOL 484 19.320 10.780 19.270 1.00 0.00 +ATOM 1687 OW SOL 485 42.720 8.460 6.390 1.00 0.00 +ATOM 1688 HW1 SOL 485 43.240 8.800 5.670 1.00 0.00 +ATOM 1689 HW2 SOL 485 43.170 8.770 7.180 1.00 0.00 +ATOM 1690 OW SOL 486 26.660 41.810 16.420 1.00 0.00 +ATOM 1691 HW1 SOL 486 26.080 41.700 15.670 1.00 0.00 +ATOM 1692 HW2 SOL 486 26.630 42.750 16.610 1.00 0.00 +ATOM 1693 OW SOL 487 13.780 38.540 0.300 1.00 0.00 +ATOM 1694 HW1 SOL 487 14.480 39.070 -0.090 1.00 0.00 +ATOM 1695 HW2 SOL 487 13.100 38.510 -0.360 1.00 0.00 +ATOM 1696 OW SOL 488 44.220 42.860 13.190 1.00 0.00 +ATOM 1697 HW1 SOL 488 45.170 42.900 13.310 1.00 0.00 +ATOM 1698 HW2 SOL 488 43.860 42.800 14.070 1.00 0.00 +ATOM 1699 OW SOL 489 10.610 41.210 24.650 1.00 0.00 +ATOM 1700 HW1 SOL 489 11.330 41.590 25.170 1.00 0.00 +ATOM 1701 HW2 SOL 489 10.250 40.530 25.210 1.00 0.00 +ATOM 1702 OW SOL 490 26.140 22.020 15.440 1.00 0.00 +ATOM 1703 HW1 SOL 490 26.740 22.600 15.900 1.00 0.00 +ATOM 1704 HW2 SOL 490 25.400 21.920 16.040 1.00 0.00 +ATOM 1705 OW SOL 491 16.650 21.140 8.400 1.00 0.00 +ATOM 1706 HW1 SOL 491 17.490 21.580 8.490 1.00 0.00 +ATOM 1707 HW2 SOL 491 16.700 20.690 7.560 1.00 0.00 +ATOM 1708 OW SOL 492 22.980 18.500 29.860 1.00 0.00 +ATOM 1709 HW1 SOL 492 22.290 18.950 30.350 1.00 0.00 +ATOM 1710 HW2 SOL 492 23.790 18.780 30.280 1.00 0.00 +ATOM 1711 OW SOL 493 26.620 39.030 28.720 1.00 0.00 +ATOM 1712 HW1 SOL 493 25.670 38.930 28.700 1.00 0.00 +ATOM 1713 HW2 SOL 493 26.950 38.290 28.210 1.00 0.00 +ATOM 1714 OW SOL 494 37.060 11.460 4.760 1.00 0.00 +ATOM 1715 HW1 SOL 494 36.350 11.020 4.300 1.00 0.00 +ATOM 1716 HW2 SOL 494 36.940 12.390 4.570 1.00 0.00 +ATOM 1717 OW SOL 495 6.010 39.950 21.420 1.00 0.00 +ATOM 1718 HW1 SOL 495 5.690 40.040 22.310 1.00 0.00 +ATOM 1719 HW2 SOL 495 6.750 39.350 21.490 1.00 0.00 +ATOM 1720 OW SOL 496 39.030 7.800 18.890 1.00 0.00 +ATOM 1721 HW1 SOL 496 39.770 8.390 19.030 1.00 0.00 +ATOM 1722 HW2 SOL 496 38.550 7.820 19.710 1.00 0.00 +ATOM 1723 OW SOL 497 15.550 16.420 22.390 1.00 0.00 +ATOM 1724 HW1 SOL 497 15.800 16.550 23.300 1.00 0.00 +ATOM 1725 HW2 SOL 497 15.260 17.280 22.090 1.00 0.00 +ATOM 1726 OW SOL 498 12.150 31.290 19.830 1.00 0.00 +ATOM 1727 HW1 SOL 498 12.280 32.030 20.430 1.00 0.00 +ATOM 1728 HW2 SOL 498 11.970 31.700 18.980 1.00 0.00 +ATOM 1729 OW SOL 499 27.090 17.150 4.850 1.00 0.00 +ATOM 1730 HW1 SOL 499 27.620 16.940 4.080 1.00 0.00 +ATOM 1731 HW2 SOL 499 26.180 17.050 4.540 1.00 0.00 +ATOM 1732 OW SOL 500 2.000 15.920 9.620 1.00 0.00 +ATOM 1733 HW1 SOL 500 2.110 16.830 9.320 1.00 0.00 +ATOM 1734 HW2 SOL 500 1.640 15.470 8.860 1.00 0.00 +ATOM 1735 OW SOL 501 14.250 5.030 20.220 1.00 0.00 +ATOM 1736 HW1 SOL 501 14.070 4.590 21.050 1.00 0.00 +ATOM 1737 HW2 SOL 501 15.020 5.570 20.400 1.00 0.00 +ATOM 1738 OW SOL 502 36.790 18.200 4.440 1.00 0.00 +ATOM 1739 HW1 SOL 502 37.110 18.860 3.830 1.00 0.00 +ATOM 1740 HW2 SOL 502 36.010 18.590 4.830 1.00 0.00 +ATOM 1741 OW SOL 503 7.790 22.580 8.320 1.00 0.00 +ATOM 1742 HW1 SOL 503 7.480 23.430 8.630 1.00 0.00 +ATOM 1743 HW2 SOL 503 8.520 22.370 8.900 1.00 0.00 +ATOM 1744 OW SOL 504 4.340 37.190 8.350 1.00 0.00 +ATOM 1745 HW1 SOL 504 3.570 37.720 8.580 1.00 0.00 +ATOM 1746 HW2 SOL 504 3.980 36.340 8.110 1.00 0.00 +ATOM 1747 OW SOL 505 11.180 41.570 19.570 1.00 0.00 +ATOM 1748 HW1 SOL 505 10.810 41.150 20.350 1.00 0.00 +ATOM 1749 HW2 SOL 505 12.130 41.450 19.660 1.00 0.00 +ATOM 1750 OW SOL 506 40.070 7.460 22.570 1.00 0.00 +ATOM 1751 HW1 SOL 506 39.930 8.030 21.820 1.00 0.00 +ATOM 1752 HW2 SOL 506 39.310 7.620 23.140 1.00 0.00 +ATOM 1753 OW SOL 507 1.400 29.570 20.300 1.00 0.00 +ATOM 1754 HW1 SOL 507 2.110 29.190 19.790 1.00 0.00 +ATOM 1755 HW2 SOL 507 1.160 30.360 19.830 1.00 0.00 +ATOM 1756 OW SOL 508 34.770 12.050 29.420 1.00 0.00 +ATOM 1757 HW1 SOL 508 34.460 12.130 30.320 1.00 0.00 +ATOM 1758 HW2 SOL 508 35.670 11.740 29.510 1.00 0.00 +ATOM 1759 OW SOL 509 40.980 21.270 13.810 1.00 0.00 +ATOM 1760 HW1 SOL 509 40.650 20.720 13.110 1.00 0.00 +ATOM 1761 HW2 SOL 509 40.600 22.130 13.650 1.00 0.00 +ATOM 1762 OW SOL 510 14.130 32.730 6.270 1.00 0.00 +ATOM 1763 HW1 SOL 510 14.600 32.710 7.100 1.00 0.00 +ATOM 1764 HW2 SOL 510 13.540 33.490 6.340 1.00 0.00 +ATOM 1765 OW SOL 511 8.450 23.120 5.810 1.00 0.00 +ATOM 1766 HW1 SOL 511 9.390 23.300 5.730 1.00 0.00 +ATOM 1767 HW2 SOL 511 8.320 22.900 6.730 1.00 0.00 +ATOM 1768 OW SOL 512 10.240 6.190 16.700 1.00 0.00 +ATOM 1769 HW1 SOL 512 11.140 6.390 16.430 1.00 0.00 +ATOM 1770 HW2 SOL 512 9.800 5.930 15.890 1.00 0.00 +ATOM 1771 OW SOL 513 0.130 20.540 27.980 1.00 0.00 +ATOM 1772 HW1 SOL 513 -0.240 19.810 27.490 1.00 0.00 +ATOM 1773 HW2 SOL 513 1.060 20.330 28.050 1.00 0.00 +ATOM 1774 OW SOL 514 6.570 9.990 11.750 1.00 0.00 +ATOM 1775 HW1 SOL 514 6.430 9.590 12.610 1.00 0.00 +ATOM 1776 HW2 SOL 514 6.060 9.460 11.150 1.00 0.00 +ATOM 1777 OW SOL 515 2.140 17.540 16.740 1.00 0.00 +ATOM 1778 HW1 SOL 515 1.450 18.150 16.980 1.00 0.00 +ATOM 1779 HW2 SOL 515 1.690 16.840 16.260 1.00 0.00 +ATOM 1780 OW SOL 516 36.780 37.610 0.190 1.00 0.00 +ATOM 1781 HW1 SOL 516 35.850 37.610 0.420 1.00 0.00 +ATOM 1782 HW2 SOL 516 37.010 38.540 0.110 1.00 0.00 +ATOM 1783 OW SOL 517 26.420 9.870 17.590 1.00 0.00 +ATOM 1784 HW1 SOL 517 26.500 9.020 18.010 1.00 0.00 +ATOM 1785 HW2 SOL 517 27.160 9.910 16.980 1.00 0.00 +ATOM 1786 OW SOL 518 12.940 8.740 31.580 1.00 0.00 +ATOM 1787 HW1 SOL 518 12.440 9.270 30.960 1.00 0.00 +ATOM 1788 HW2 SOL 518 12.590 8.970 32.440 1.00 0.00 +ATOM 1789 OW SOL 519 10.630 30.900 29.960 1.00 0.00 +ATOM 1790 HW1 SOL 519 10.020 30.180 29.820 1.00 0.00 +ATOM 1791 HW2 SOL 519 10.120 31.570 30.410 1.00 0.00 +ATOM 1792 OW SOL 520 18.370 34.190 19.180 1.00 0.00 +ATOM 1793 HW1 SOL 520 18.070 33.290 19.220 1.00 0.00 +ATOM 1794 HW2 SOL 520 18.090 34.500 18.320 1.00 0.00 +ATOM 1795 OW SOL 521 3.720 31.100 3.380 1.00 0.00 +ATOM 1796 HW1 SOL 521 3.240 31.230 2.560 1.00 0.00 +ATOM 1797 HW2 SOL 521 3.830 30.150 3.440 1.00 0.00 +ATOM 1798 OW SOL 522 37.130 26.540 5.260 1.00 0.00 +ATOM 1799 HW1 SOL 522 37.570 26.510 6.110 1.00 0.00 +ATOM 1800 HW2 SOL 522 37.840 26.520 4.620 1.00 0.00 +ATOM 1801 OW SOL 523 33.170 38.000 29.590 1.00 0.00 +ATOM 1802 HW1 SOL 523 32.960 37.970 30.530 1.00 0.00 +ATOM 1803 HW2 SOL 523 34.100 37.810 29.550 1.00 0.00 +ATOM 1804 OW SOL 524 28.900 38.040 6.870 1.00 0.00 +ATOM 1805 HW1 SOL 524 27.970 37.880 6.710 1.00 0.00 +ATOM 1806 HW2 SOL 524 29.110 38.820 6.360 1.00 0.00 +ATOM 1807 OW SOL 525 34.330 42.260 16.660 1.00 0.00 +ATOM 1808 HW1 SOL 525 33.650 41.680 16.310 1.00 0.00 +ATOM 1809 HW2 SOL 525 35.140 41.750 16.600 1.00 0.00 +ATOM 1810 OW SOL 526 24.150 38.830 8.950 1.00 0.00 +ATOM 1811 HW1 SOL 526 23.690 39.240 9.690 1.00 0.00 +ATOM 1812 HW2 SOL 526 23.700 37.980 8.840 1.00 0.00 +ATOM 1813 OW SOL 527 19.200 30.800 14.120 1.00 0.00 +ATOM 1814 HW1 SOL 527 18.970 30.210 14.830 1.00 0.00 +ATOM 1815 HW2 SOL 527 18.570 31.510 14.170 1.00 0.00 +ATOM 1816 OW SOL 528 22.050 38.730 1.810 1.00 0.00 +ATOM 1817 HW1 SOL 528 22.430 39.510 1.410 1.00 0.00 +ATOM 1818 HW2 SOL 528 21.130 38.750 1.540 1.00 0.00 +ATOM 1819 OW SOL 529 2.051 42.439 -0.408 1.00 0.00 +ATOM 1820 HW1 SOL 529 2.841 42.909 -0.138 1.00 0.00 +ATOM 1821 HW2 SOL 529 2.231 41.529 -0.198 1.00 0.00 +ATOM 1822 OW SOL 530 36.660 30.720 3.260 1.00 0.00 +ATOM 1823 HW1 SOL 530 36.470 29.920 3.740 1.00 0.00 +ATOM 1824 HW2 SOL 530 36.100 30.680 2.490 1.00 0.00 +ATOM 1825 OW SOL 531 9.720 4.990 10.110 1.00 0.00 +ATOM 1826 HW1 SOL 531 8.840 5.070 10.480 1.00 0.00 +ATOM 1827 HW2 SOL 531 10.300 4.910 10.870 1.00 0.00 +ATOM 1828 OW SOL 532 34.700 31.410 12.320 1.00 0.00 +ATOM 1829 HW1 SOL 532 34.710 31.090 13.220 1.00 0.00 +ATOM 1830 HW2 SOL 532 35.600 31.700 12.160 1.00 0.00 +ATOM 1831 OW SOL 533 17.200 5.680 8.460 1.00 0.00 +ATOM 1832 HW1 SOL 533 17.210 5.800 9.410 1.00 0.00 +ATOM 1833 HW2 SOL 533 17.420 4.760 8.330 1.00 0.00 +ATOM 1834 OW SOL 534 9.840 9.790 5.920 1.00 0.00 +ATOM 1835 HW1 SOL 534 9.700 9.970 4.990 1.00 0.00 +ATOM 1836 HW2 SOL 534 9.810 8.830 5.990 1.00 0.00 +ATOM 1837 OW SOL 535 17.030 25.780 25.880 1.00 0.00 +ATOM 1838 HW1 SOL 535 16.820 25.490 26.760 1.00 0.00 +ATOM 1839 HW2 SOL 535 17.950 26.040 25.920 1.00 0.00 +ATOM 1840 OW SOL 536 37.650 4.630 23.360 1.00 0.00 +ATOM 1841 HW1 SOL 536 38.600 4.690 23.480 1.00 0.00 +ATOM 1842 HW2 SOL 536 37.450 3.700 23.450 1.00 0.00 +ATOM 1843 OW SOL 537 16.510 21.670 31.160 1.00 0.00 +ATOM 1844 HW1 SOL 537 17.140 21.960 31.820 1.00 0.00 +ATOM 1845 HW2 SOL 537 15.960 22.440 31.000 1.00 0.00 +ATOM 1846 OW SOL 538 29.500 23.820 7.850 1.00 0.00 +ATOM 1847 HW1 SOL 538 29.240 23.380 7.040 1.00 0.00 +ATOM 1848 HW2 SOL 538 28.730 23.760 8.420 1.00 0.00 +ATOM 1849 OW SOL 539 24.460 13.580 6.180 1.00 0.00 +ATOM 1850 HW1 SOL 539 23.570 13.840 6.420 1.00 0.00 +ATOM 1851 HW2 SOL 539 24.900 13.410 7.010 1.00 0.00 +ATOM 1852 OW SOL 540 3.410 20.870 4.810 1.00 0.00 +ATOM 1853 HW1 SOL 540 3.740 21.430 5.510 1.00 0.00 +ATOM 1854 HW2 SOL 540 2.590 20.520 5.160 1.00 0.00 +ATOM 1855 OW SOL 541 20.470 42.760 22.050 1.00 0.00 +ATOM 1856 HW1 SOL 541 21.280 42.650 21.540 1.00 0.00 +ATOM 1857 HW2 SOL 541 20.390 43.700 22.180 1.00 0.00 +ATOM 1858 OW SOL 542 38.020 26.890 7.840 1.00 0.00 +ATOM 1859 HW1 SOL 542 37.510 27.650 8.130 1.00 0.00 +ATOM 1860 HW2 SOL 542 38.860 26.970 8.300 1.00 0.00 +ATOM 1861 OW SOL 543 17.990 4.570 18.970 1.00 0.00 +ATOM 1862 HW1 SOL 543 18.330 5.240 18.370 1.00 0.00 +ATOM 1863 HW2 SOL 543 17.580 5.070 19.680 1.00 0.00 +ATOM 1864 OW SOL 544 34.270 19.700 12.700 1.00 0.00 +ATOM 1865 HW1 SOL 544 33.860 20.070 13.480 1.00 0.00 +ATOM 1866 HW2 SOL 544 34.610 20.460 12.220 1.00 0.00 +ATOM 1867 OW SOL 545 21.020 21.170 16.650 1.00 0.00 +ATOM 1868 HW1 SOL 545 21.030 21.970 16.130 1.00 0.00 +ATOM 1869 HW2 SOL 545 20.930 21.480 17.560 1.00 0.00 +ATOM 1870 OW SOL 546 14.370 17.440 15.050 1.00 0.00 +ATOM 1871 HW1 SOL 546 14.650 17.480 14.140 1.00 0.00 +ATOM 1872 HW2 SOL 546 14.740 16.620 15.380 1.00 0.00 +ATOM 1873 OW SOL 547 40.140 22.920 29.270 1.00 0.00 +ATOM 1874 HW1 SOL 547 40.740 23.560 29.630 1.00 0.00 +ATOM 1875 HW2 SOL 547 40.600 22.560 28.510 1.00 0.00 +ATOM 1876 OW SOL 548 38.740 20.940 31.000 1.00 0.00 +ATOM 1877 HW1 SOL 548 39.300 21.490 30.440 1.00 0.00 +ATOM 1878 HW2 SOL 548 38.090 21.550 31.350 1.00 0.00 +ATOM 1879 OW SOL 549 17.810 4.630 3.630 1.00 0.00 +ATOM 1880 HW1 SOL 549 18.150 4.550 4.520 1.00 0.00 +ATOM 1881 HW2 SOL 549 17.190 5.360 3.680 1.00 0.00 +ATOM 1882 OW SOL 550 13.860 33.920 3.830 1.00 0.00 +ATOM 1883 HW1 SOL 550 13.730 33.330 4.570 1.00 0.00 +ATOM 1884 HW2 SOL 550 13.000 33.970 3.410 1.00 0.00 +ATOM 1885 OW SOL 551 36.730 24.690 20.760 1.00 0.00 +ATOM 1886 HW1 SOL 551 36.310 24.610 21.620 1.00 0.00 +ATOM 1887 HW2 SOL 551 36.490 23.880 20.310 1.00 0.00 +ATOM 1888 OW SOL 552 25.610 41.860 3.140 1.00 0.00 +ATOM 1889 HW1 SOL 552 24.820 42.040 3.650 1.00 0.00 +ATOM 1890 HW2 SOL 552 25.970 42.730 2.950 1.00 0.00 +ATOM 1891 OW SOL 553 39.950 35.730 12.620 1.00 0.00 +ATOM 1892 HW1 SOL 553 39.870 35.340 11.750 1.00 0.00 +ATOM 1893 HW2 SOL 553 39.050 35.970 12.850 1.00 0.00 +ATOM 1894 OW SOL 554 42.760 44.690 7.840 1.00 0.00 +ATOM 1895 HW1 SOL 554 43.620 44.420 8.170 1.00 0.00 +ATOM 1896 HW2 SOL 554 42.800 44.500 6.910 1.00 0.00 +ATOM 1897 OW SOL 555 18.460 31.020 20.540 1.00 0.00 +ATOM 1898 HW1 SOL 555 18.200 30.730 21.420 1.00 0.00 +ATOM 1899 HW2 SOL 555 19.420 31.060 20.580 1.00 0.00 +ATOM 1900 OW SOL 556 39.060 11.020 23.010 1.00 0.00 +ATOM 1901 HW1 SOL 556 38.300 11.440 23.430 1.00 0.00 +ATOM 1902 HW2 SOL 556 39.600 10.720 23.740 1.00 0.00 +ATOM 1903 OW SOL 557 1.450 19.070 5.820 1.00 0.00 +ATOM 1904 HW1 SOL 557 1.470 18.780 6.730 1.00 0.00 +ATOM 1905 HW2 SOL 557 0.540 19.330 5.670 1.00 0.00 +ATOM 1906 OW SOL 558 19.440 34.720 10.950 1.00 0.00 +ATOM 1907 HW1 SOL 558 19.270 33.780 11.040 1.00 0.00 +ATOM 1908 HW2 SOL 558 19.210 35.080 11.810 1.00 0.00 +ATOM 1909 OW SOL 559 36.010 14.410 24.930 1.00 0.00 +ATOM 1910 HW1 SOL 559 35.490 14.430 25.730 1.00 0.00 +ATOM 1911 HW2 SOL 559 35.790 13.580 24.510 1.00 0.00 +ATOM 1912 OW SOL 560 9.450 5.430 14.100 1.00 0.00 +ATOM 1913 HW1 SOL 560 8.530 5.620 13.900 1.00 0.00 +ATOM 1914 HW2 SOL 560 9.560 4.510 13.890 1.00 0.00 +ATOM 1915 OW SOL 561 22.850 27.600 2.900 1.00 0.00 +ATOM 1916 HW1 SOL 561 23.520 27.950 3.480 1.00 0.00 +ATOM 1917 HW2 SOL 561 23.160 26.720 2.680 1.00 0.00 +ATOM 1918 OW SOL 562 17.900 29.080 18.630 1.00 0.00 +ATOM 1919 HW1 SOL 562 17.750 28.160 18.810 1.00 0.00 +ATOM 1920 HW2 SOL 562 18.250 29.440 19.450 1.00 0.00 +ATOM 1921 OW SOL 563 40.840 33.690 24.810 1.00 0.00 +ATOM 1922 HW1 SOL 563 40.170 34.250 25.210 1.00 0.00 +ATOM 1923 HW2 SOL 563 40.380 33.220 24.110 1.00 0.00 +ATOM 1924 OW SOL 564 40.640 39.820 17.990 1.00 0.00 +ATOM 1925 HW1 SOL 564 41.190 39.350 18.620 1.00 0.00 +ATOM 1926 HW2 SOL 564 41.250 40.350 17.490 1.00 0.00 +ATOM 1927 OW SOL 565 13.730 25.090 14.500 1.00 0.00 +ATOM 1928 HW1 SOL 565 13.090 24.610 15.030 1.00 0.00 +ATOM 1929 HW2 SOL 565 14.520 25.100 15.050 1.00 0.00 +ATOM 1930 OW SOL 566 34.580 34.040 7.440 1.00 0.00 +ATOM 1931 HW1 SOL 566 34.050 33.260 7.620 1.00 0.00 +ATOM 1932 HW2 SOL 566 35.150 34.120 8.200 1.00 0.00 +ATOM 1933 OW SOL 567 10.800 2.110 31.060 1.00 0.00 +ATOM 1934 HW1 SOL 567 9.870 2.350 31.020 1.00 0.00 +ATOM 1935 HW2 SOL 567 10.980 1.960 31.980 1.00 0.00 +ATOM 1936 OW SOL 568 1.870 22.330 10.440 1.00 0.00 +ATOM 1937 HW1 SOL 568 1.050 22.520 9.980 1.00 0.00 +ATOM 1938 HW2 SOL 568 1.770 22.760 11.290 1.00 0.00 +ATOM 1939 OW SOL 569 2.320 10.960 11.260 1.00 0.00 +ATOM 1940 HW1 SOL 569 2.470 10.650 12.150 1.00 0.00 +ATOM 1941 HW2 SOL 569 2.430 11.910 11.320 1.00 0.00 +ATOM 1942 OW SOL 570 0.360 7.790 29.940 1.00 0.00 +ATOM 1943 HW1 SOL 570 0.210 7.650 29.010 1.00 0.00 +ATOM 1944 HW2 SOL 570 -0.260 7.190 30.370 1.00 0.00 +ATOM 1945 OW SOL 571 11.870 12.150 15.900 1.00 0.00 +ATOM 1946 HW1 SOL 571 12.720 12.040 16.330 1.00 0.00 +ATOM 1947 HW2 SOL 571 11.840 11.450 15.250 1.00 0.00 +ATOM 1948 OW SOL 572 40.180 27.970 8.820 1.00 0.00 +ATOM 1949 HW1 SOL 572 40.120 28.910 8.980 1.00 0.00 +ATOM 1950 HW2 SOL 572 39.950 27.570 9.660 1.00 0.00 +ATOM 1951 OW SOL 573 10.270 9.610 14.330 1.00 0.00 +ATOM 1952 HW1 SOL 573 10.770 9.300 15.080 1.00 0.00 +ATOM 1953 HW2 SOL 573 10.070 8.810 13.830 1.00 0.00 +ATOM 1954 OW SOL 574 4.590 28.530 3.580 1.00 0.00 +ATOM 1955 HW1 SOL 574 5.170 28.680 2.830 1.00 0.00 +ATOM 1956 HW2 SOL 574 4.940 27.740 4.000 1.00 0.00 +ATOM 1957 OW SOL 575 3.240 5.540 9.660 1.00 0.00 +ATOM 1958 HW1 SOL 575 2.320 5.540 9.910 1.00 0.00 +ATOM 1959 HW2 SOL 575 3.250 6.010 8.820 1.00 0.00 +ATOM 1960 OW SOL 576 33.980 28.050 6.850 1.00 0.00 +ATOM 1961 HW1 SOL 576 33.060 28.230 6.660 1.00 0.00 +ATOM 1962 HW2 SOL 576 34.050 27.090 6.820 1.00 0.00 +ATOM 1963 OW SOL 577 24.500 14.130 27.180 1.00 0.00 +ATOM 1964 HW1 SOL 577 24.710 14.930 27.660 1.00 0.00 +ATOM 1965 HW2 SOL 577 24.750 14.330 26.280 1.00 0.00 +ATOM 1966 OW SOL 578 37.390 39.880 11.340 1.00 0.00 +ATOM 1967 HW1 SOL 578 36.850 39.710 12.110 1.00 0.00 +ATOM 1968 HW2 SOL 578 36.810 40.340 10.730 1.00 0.00 +ATOM 1969 OW SOL 579 27.310 1.690 30.800 1.00 0.00 +ATOM 1970 HW1 SOL 579 26.680 1.550 30.090 1.00 0.00 +ATOM 1971 HW2 SOL 579 27.300 0.870 31.290 1.00 0.00 +ATOM 1972 OW SOL 580 24.200 8.550 25.350 1.00 0.00 +ATOM 1973 HW1 SOL 580 24.520 9.390 25.030 1.00 0.00 +ATOM 1974 HW2 SOL 580 23.370 8.750 25.780 1.00 0.00 +ATOM 1975 OW SOL 581 44.450 25.870 13.880 1.00 0.00 +ATOM 1976 HW1 SOL 581 43.870 26.530 14.250 1.00 0.00 +ATOM 1977 HW2 SOL 581 45.300 26.040 14.280 1.00 0.00 +ATOM 1978 OW SOL 582 9.410 27.140 8.180 1.00 0.00 +ATOM 1979 HW1 SOL 582 9.200 26.860 7.290 1.00 0.00 +ATOM 1980 HW2 SOL 582 9.550 26.310 8.650 1.00 0.00 +ATOM 1981 OW SOL 583 18.570 28.640 15.960 1.00 0.00 +ATOM 1982 HW1 SOL 583 17.710 28.240 15.810 1.00 0.00 +ATOM 1983 HW2 SOL 583 18.510 29.010 16.840 1.00 0.00 +ATOM 1984 OW SOL 584 19.380 38.830 1.370 1.00 0.00 +ATOM 1985 HW1 SOL 584 19.320 38.140 0.710 1.00 0.00 +ATOM 1986 HW2 SOL 584 18.730 38.590 2.030 1.00 0.00 +ATOM 1987 OW SOL 585 42.550 24.180 29.450 1.00 0.00 +ATOM 1988 HW1 SOL 585 42.620 24.560 28.570 1.00 0.00 +ATOM 1989 HW2 SOL 585 42.850 23.280 29.350 1.00 0.00 +ATOM 1990 OW SOL 586 11.590 21.280 11.710 1.00 0.00 +ATOM 1991 HW1 SOL 586 11.170 20.430 11.880 1.00 0.00 +ATOM 1992 HW2 SOL 586 11.970 21.520 12.550 1.00 0.00 +ATOM 1993 OW SOL 587 6.020 23.890 22.970 1.00 0.00 +ATOM 1994 HW1 SOL 587 5.670 24.300 22.180 1.00 0.00 +ATOM 1995 HW2 SOL 587 5.560 23.050 23.030 1.00 0.00 +ATOM 1996 OW SOL 588 34.020 4.570 18.360 1.00 0.00 +ATOM 1997 HW1 SOL 588 34.190 4.680 17.430 1.00 0.00 +ATOM 1998 HW2 SOL 588 33.400 3.840 18.400 1.00 0.00 +ATOM 1999 OW SOL 589 2.440 7.470 24.760 1.00 0.00 +ATOM 2000 HW1 SOL 589 3.190 7.800 25.260 1.00 0.00 +ATOM 2001 HW2 SOL 589 2.500 6.520 24.840 1.00 0.00 +ATOM 2002 OW SOL 590 26.350 23.310 0.050 1.00 0.00 +ATOM 2003 HW1 SOL 590 25.470 23.270 -0.330 1.00 0.00 +ATOM 2004 HW2 SOL 590 26.900 23.640 -0.670 1.00 0.00 +ATOM 2005 OW SOL 591 17.140 22.620 26.420 1.00 0.00 +ATOM 2006 HW1 SOL 591 18.010 22.280 26.640 1.00 0.00 +ATOM 2007 HW2 SOL 591 16.600 21.830 26.350 1.00 0.00 +ATOM 2008 OW SOL 592 1.180 33.630 9.430 1.00 0.00 +ATOM 2009 HW1 SOL 592 1.110 33.710 10.380 1.00 0.00 +ATOM 2010 HW2 SOL 592 0.870 32.740 9.250 1.00 0.00 +ATOM 2011 OW SOL 593 6.590 16.710 8.840 1.00 0.00 +ATOM 2012 HW1 SOL 593 6.670 15.870 9.300 1.00 0.00 +ATOM 2013 HW2 SOL 593 6.420 17.340 9.540 1.00 0.00 +ATOM 2014 OW SOL 594 30.400 29.060 28.160 1.00 0.00 +ATOM 2015 HW1 SOL 594 30.490 29.460 29.030 1.00 0.00 +ATOM 2016 HW2 SOL 594 29.470 28.880 28.080 1.00 0.00 +ATOM 2017 OW SOL 595 14.640 16.970 10.610 1.00 0.00 +ATOM 2018 HW1 SOL 595 13.890 16.480 10.940 1.00 0.00 +ATOM 2019 HW2 SOL 595 14.640 16.800 9.670 1.00 0.00 +ATOM 2020 OW SOL 596 17.120 44.970 11.400 1.00 0.00 +ATOM 2021 HW1 SOL 596 16.640 45.790 11.410 1.00 0.00 +ATOM 2022 HW2 SOL 596 18.040 45.230 11.280 1.00 0.00 +ATOM 2023 OW SOL 597 13.210 33.000 27.600 1.00 0.00 +ATOM 2024 HW1 SOL 597 13.530 32.140 27.900 1.00 0.00 +ATOM 2025 HW2 SOL 597 13.650 33.620 28.170 1.00 0.00 +ATOM 2026 OW SOL 598 31.330 9.350 22.650 1.00 0.00 +ATOM 2027 HW1 SOL 598 31.280 9.360 21.700 1.00 0.00 +ATOM 2028 HW2 SOL 598 30.770 8.610 22.910 1.00 0.00 +ATOM 2029 OW SOL 599 19.750 23.610 1.950 1.00 0.00 +ATOM 2030 HW1 SOL 599 18.810 23.440 1.890 1.00 0.00 +ATOM 2031 HW2 SOL 599 19.960 24.110 1.160 1.00 0.00 +ATOM 2032 OW SOL 600 8.060 19.960 12.460 1.00 0.00 +ATOM 2033 HW1 SOL 600 8.950 19.660 12.260 1.00 0.00 +ATOM 2034 HW2 SOL 600 7.910 19.690 13.360 1.00 0.00 +ATOM 2035 OW SOL 601 32.370 3.780 23.710 1.00 0.00 +ATOM 2036 HW1 SOL 601 31.500 3.430 23.880 1.00 0.00 +ATOM 2037 HW2 SOL 601 32.220 4.510 23.100 1.00 0.00 +ATOM 2038 OW SOL 602 1.080 22.010 3.550 1.00 0.00 +ATOM 2039 HW1 SOL 602 1.550 21.970 2.720 1.00 0.00 +ATOM 2040 HW2 SOL 602 1.470 22.760 4.010 1.00 0.00 +ATOM 2041 OW SOL 603 16.740 40.490 2.060 1.00 0.00 +ATOM 2042 HW1 SOL 603 16.340 40.510 1.190 1.00 0.00 +ATOM 2043 HW2 SOL 603 16.060 40.810 2.640 1.00 0.00 +ATOM 2044 OW SOL 604 -20.319 43.599 -0.468 1.00 0.00 +ATOM 2045 HW1 SOL 604 -21.269 43.498 -0.428 1.00 0.00 +ATOM 2046 HW2 SOL 604 -20.179 44.519 -0.668 1.00 0.00 +ATOM 2047 OW SOL 605 7.790 28.020 22.660 1.00 0.00 +ATOM 2048 HW1 SOL 605 7.360 27.880 21.820 1.00 0.00 +ATOM 2049 HW2 SOL 605 7.190 27.620 23.300 1.00 0.00 +ATOM 2050 OW SOL 606 24.300 40.590 1.030 1.00 0.00 +ATOM 2051 HW1 SOL 606 24.530 39.850 0.470 1.00 0.00 +ATOM 2052 HW2 SOL 606 25.040 40.680 1.630 1.00 0.00 +ATOM 2053 OW SOL 607 11.540 3.070 28.490 1.00 0.00 +ATOM 2054 HW1 SOL 607 11.560 2.950 29.440 1.00 0.00 +ATOM 2055 HW2 SOL 607 10.940 2.380 28.180 1.00 0.00 +ATOM 2056 OW SOL 608 34.970 20.530 18.680 1.00 0.00 +ATOM 2057 HW1 SOL 608 35.130 21.410 18.330 1.00 0.00 +ATOM 2058 HW2 SOL 608 34.870 19.980 17.900 1.00 0.00 +ATOM 2059 OW SOL 609 20.230 6.450 25.820 1.00 0.00 +ATOM 2060 HW1 SOL 609 20.070 5.610 25.400 1.00 0.00 +ATOM 2061 HW2 SOL 609 20.420 7.050 25.090 1.00 0.00 +ATOM 2062 OW SOL 610 35.460 41.360 20.010 1.00 0.00 +ATOM 2063 HW1 SOL 610 34.530 41.320 20.200 1.00 0.00 +ATOM 2064 HW2 SOL 610 35.510 41.670 19.110 1.00 0.00 +ATOM 2065 OW SOL 611 22.240 25.720 0.430 1.00 0.00 +ATOM 2066 HW1 SOL 611 22.680 25.110 1.020 1.00 0.00 +ATOM 2067 HW2 SOL 611 21.350 25.380 0.370 1.00 0.00 +ATOM 2068 OW SOL 612 2.890 22.010 19.000 1.00 0.00 +ATOM 2069 HW1 SOL 612 3.840 21.920 19.030 1.00 0.00 +ATOM 2070 HW2 SOL 612 2.730 22.840 18.570 1.00 0.00 +ATOM 2071 OW SOL 613 5.390 28.240 14.030 1.00 0.00 +ATOM 2072 HW1 SOL 613 5.970 28.470 13.310 1.00 0.00 +ATOM 2073 HW2 SOL 613 5.820 28.570 14.810 1.00 0.00 +ATOM 2074 OW SOL 614 36.790 20.760 3.110 1.00 0.00 +ATOM 2075 HW1 SOL 614 37.180 21.410 3.690 1.00 0.00 +ATOM 2076 HW2 SOL 614 35.910 21.090 2.940 1.00 0.00 +ATOM 2077 OW SOL 615 44.480 20.570 5.240 1.00 0.00 +ATOM 2078 HW1 SOL 615 44.910 21.220 4.680 1.00 0.00 +ATOM 2079 HW2 SOL 615 43.740 21.040 5.620 1.00 0.00 +ATOM 2080 OW SOL 616 22.890 6.380 21.000 1.00 0.00 +ATOM 2081 HW1 SOL 616 21.950 6.320 20.810 1.00 0.00 +ATOM 2082 HW2 SOL 616 23.220 7.000 20.350 1.00 0.00 +ATOM 2083 OW SOL 617 1.300 26.470 15.090 1.00 0.00 +ATOM 2084 HW1 SOL 617 1.910 26.660 14.370 1.00 0.00 +ATOM 2085 HW2 SOL 617 1.250 27.290 15.580 1.00 0.00 +ATOM 2086 OW SOL 618 20.860 27.850 6.830 1.00 0.00 +ATOM 2087 HW1 SOL 618 21.430 27.230 7.300 1.00 0.00 +ATOM 2088 HW2 SOL 618 21.240 27.920 5.960 1.00 0.00 +ATOM 2089 OW SOL 619 18.310 27.080 6.810 1.00 0.00 +ATOM 2090 HW1 SOL 619 19.160 27.490 6.960 1.00 0.00 +ATOM 2091 HW2 SOL 619 18.500 26.140 6.750 1.00 0.00 +ATOM 2092 OW SOL 620 41.450 42.280 2.430 1.00 0.00 +ATOM 2093 HW1 SOL 620 41.870 41.480 2.730 1.00 0.00 +ATOM 2094 HW2 SOL 620 40.860 41.990 1.730 1.00 0.00 +ATOM 2095 OW SOL 621 6.250 18.960 10.510 1.00 0.00 +ATOM 2096 HW1 SOL 621 6.810 19.250 9.790 1.00 0.00 +ATOM 2097 HW2 SOL 621 6.750 19.170 11.300 1.00 0.00 +ATOM 2098 OW SOL 622 7.330 35.320 15.030 1.00 0.00 +ATOM 2099 HW1 SOL 622 7.160 34.390 15.180 1.00 0.00 +ATOM 2100 HW2 SOL 622 7.110 35.750 15.850 1.00 0.00 +ATOM 2101 OW SOL 623 10.580 18.810 12.340 1.00 0.00 +ATOM 2102 HW1 SOL 623 11.150 18.290 12.900 1.00 0.00 +ATOM 2103 HW2 SOL 623 10.400 18.240 11.590 1.00 0.00 +ATOM 2104 OW SOL 624 43.430 11.490 7.190 1.00 0.00 +ATOM 2105 HW1 SOL 624 43.840 10.790 7.710 1.00 0.00 +ATOM 2106 HW2 SOL 624 42.490 11.310 7.250 1.00 0.00 +ATOM 2107 OW SOL 625 43.120 1.430 19.070 1.00 0.00 +ATOM 2108 HW1 SOL 625 42.980 0.820 19.790 1.00 0.00 +ATOM 2109 HW2 SOL 625 42.350 2.000 19.080 1.00 0.00 +ATOM 2110 OW SOL 626 22.860 31.460 4.940 1.00 0.00 +ATOM 2111 HW1 SOL 626 22.430 31.920 5.660 1.00 0.00 +ATOM 2112 HW2 SOL 626 22.670 31.990 4.160 1.00 0.00 +ATOM 2113 OW SOL 627 30.790 35.470 7.540 1.00 0.00 +ATOM 2114 HW1 SOL 627 30.000 35.560 7.020 1.00 0.00 +ATOM 2115 HW2 SOL 627 31.300 34.790 7.100 1.00 0.00 +ATOM 2116 OW SOL 628 20.850 37.430 9.680 1.00 0.00 +ATOM 2117 HW1 SOL 628 20.910 37.150 8.760 1.00 0.00 +ATOM 2118 HW2 SOL 628 20.840 36.610 10.180 1.00 0.00 +ATOM 2119 OW SOL 629 6.500 33.130 5.760 1.00 0.00 +ATOM 2120 HW1 SOL 629 6.020 32.970 6.570 1.00 0.00 +ATOM 2121 HW2 SOL 629 7.420 32.970 5.990 1.00 0.00 +ATOM 2122 OW SOL 630 43.470 17.620 0.950 1.00 0.00 +ATOM 2123 HW1 SOL 630 43.140 16.730 0.800 1.00 0.00 +ATOM 2124 HW2 SOL 630 43.490 17.710 1.910 1.00 0.00 +ATOM 2125 OW SOL 631 47.827 4.550 25.180 1.00 0.00 +ATOM 2126 HW1 SOL 631 48.677 4.190 25.440 1.00 0.00 +ATOM 2127 HW2 SOL 631 47.347 4.660 26.000 1.00 0.00 +ATOM 2128 OW SOL 632 20.260 12.130 11.350 1.00 0.00 +ATOM 2129 HW1 SOL 632 19.790 12.970 11.410 1.00 0.00 +ATOM 2130 HW2 SOL 632 19.590 11.500 11.080 1.00 0.00 +ATOM 2131 OW SOL 633 39.880 11.150 18.940 1.00 0.00 +ATOM 2132 HW1 SOL 633 40.050 10.790 19.810 1.00 0.00 +ATOM 2133 HW2 SOL 633 40.160 12.070 19.010 1.00 0.00 +ATOM 2134 OW SOL 634 29.620 37.660 31.860 1.00 0.00 +ATOM 2135 HW1 SOL 634 30.260 36.950 31.810 1.00 0.00 +ATOM 2136 HW2 SOL 634 30.120 38.450 31.650 1.00 0.00 +ATOM 2137 OW SOL 635 61.699 56.839 33.438 1.00 0.00 +ATOM 2138 HW1 SOL 635 62.369 56.729 34.108 1.00 0.00 +ATOM 2139 HW2 SOL 635 60.869 56.729 33.898 1.00 0.00 +ATOM 2140 OW SOL 636 41.150 19.630 30.350 1.00 0.00 +ATOM 2141 HW1 SOL 636 40.430 20.080 30.810 1.00 0.00 +ATOM 2142 HW2 SOL 636 41.670 19.240 31.050 1.00 0.00 +ATOM 2143 OW SOL 637 41.380 29.270 23.970 1.00 0.00 +ATOM 2144 HW1 SOL 637 41.520 29.720 24.810 1.00 0.00 +ATOM 2145 HW2 SOL 637 41.030 29.940 23.390 1.00 0.00 +ATOM 2146 OW SOL 638 40.180 14.180 12.420 1.00 0.00 +ATOM 2147 HW1 SOL 638 39.650 14.700 11.810 1.00 0.00 +ATOM 2148 HW2 SOL 638 40.360 13.370 11.950 1.00 0.00 +ATOM 2149 OW SOL 639 37.930 44.270 25.110 1.00 0.00 +ATOM 2150 HW1 SOL 639 38.000 44.170 26.060 1.00 0.00 +ATOM 2151 HW2 SOL 639 38.760 44.660 24.850 1.00 0.00 +ATOM 2152 OW SOL 640 36.750 48.697 6.630 1.00 0.00 +ATOM 2153 HW1 SOL 640 36.880 48.417 7.540 1.00 0.00 +ATOM 2154 HW2 SOL 640 37.000 47.937 6.110 1.00 0.00 +ATOM 2155 OW SOL 641 4.310 21.850 27.840 1.00 0.00 +ATOM 2156 HW1 SOL 641 3.910 20.990 27.670 1.00 0.00 +ATOM 2157 HW2 SOL 641 3.720 22.470 27.410 1.00 0.00 +ATOM 2158 OW SOL 642 37.270 31.470 11.090 1.00 0.00 +ATOM 2159 HW1 SOL 642 37.730 31.990 11.750 1.00 0.00 +ATOM 2160 HW2 SOL 642 37.550 31.860 10.260 1.00 0.00 +ATOM 2161 OW SOL 643 17.880 43.860 25.240 1.00 0.00 +ATOM 2162 HW1 SOL 643 18.570 43.200 25.170 1.00 0.00 +ATOM 2163 HW2 SOL 643 17.610 44.020 24.340 1.00 0.00 +ATOM 2164 OW SOL 644 17.530 38.230 3.590 1.00 0.00 +ATOM 2165 HW1 SOL 644 16.850 38.660 3.070 1.00 0.00 +ATOM 2166 HW2 SOL 644 17.210 38.280 4.490 1.00 0.00 +ATOM 2167 OW SOL 645 0.640 0.070 10.820 1.00 0.00 +ATOM 2168 HW1 SOL 645 -0.000 0.780 10.910 1.00 0.00 +ATOM 2169 HW2 SOL 645 1.490 0.510 10.890 1.00 0.00 +ATOM 2170 OW SOL 646 29.330 1.280 28.080 1.00 0.00 +ATOM 2171 HW1 SOL 646 30.020 1.210 27.420 1.00 0.00 +ATOM 2172 HW2 SOL 646 28.620 0.730 27.740 1.00 0.00 +ATOM 2173 OW SOL 647 14.260 25.110 11.850 1.00 0.00 +ATOM 2174 HW1 SOL 647 13.920 25.100 12.740 1.00 0.00 +ATOM 2175 HW2 SOL 647 14.570 26.000 11.720 1.00 0.00 +ATOM 2176 OW SOL 648 42.230 2.630 31.670 1.00 0.00 +ATOM 2177 HW1 SOL 648 42.330 3.300 30.990 1.00 0.00 +ATOM 2178 HW2 SOL 648 41.390 2.210 31.460 1.00 0.00 +ATOM 2179 OW SOL 649 4.850 15.480 4.140 1.00 0.00 +ATOM 2180 HW1 SOL 649 4.870 15.950 3.310 1.00 0.00 +ATOM 2181 HW2 SOL 649 4.080 15.830 4.590 1.00 0.00 +ATOM 2182 OW SOL 650 14.540 31.630 17.220 1.00 0.00 +ATOM 2183 HW1 SOL 650 13.630 31.640 17.500 1.00 0.00 +ATOM 2184 HW2 SOL 650 14.570 32.220 16.460 1.00 0.00 +ATOM 2185 OW SOL 651 13.480 34.450 12.290 1.00 0.00 +ATOM 2186 HW1 SOL 651 13.810 35.050 11.620 1.00 0.00 +ATOM 2187 HW2 SOL 651 12.540 34.400 12.110 1.00 0.00 +ATOM 2188 OW SOL 652 38.040 29.000 13.430 1.00 0.00 +ATOM 2189 HW1 SOL 652 37.490 28.400 13.930 1.00 0.00 +ATOM 2190 HW2 SOL 652 37.490 29.290 12.710 1.00 0.00 +ATOM 2191 OW SOL 653 28.230 33.670 5.350 1.00 0.00 +ATOM 2192 HW1 SOL 653 29.000 33.550 4.790 1.00 0.00 +ATOM 2193 HW2 SOL 653 27.650 34.230 4.840 1.00 0.00 +ATOM 2194 OW SOL 654 21.470 0.390 9.930 1.00 0.00 +ATOM 2195 HW1 SOL 654 21.650 0.680 10.830 1.00 0.00 +ATOM 2196 HW2 SOL 654 20.840 -0.320 10.040 1.00 0.00 +ATOM 2197 OW SOL 655 9.170 29.270 14.420 1.00 0.00 +ATOM 2198 HW1 SOL 655 9.110 28.480 14.960 1.00 0.00 +ATOM 2199 HW2 SOL 655 8.690 29.060 13.620 1.00 0.00 +ATOM 2200 OW SOL 656 13.730 21.920 19.250 1.00 0.00 +ATOM 2201 HW1 SOL 656 14.030 22.410 18.490 1.00 0.00 +ATOM 2202 HW2 SOL 656 13.490 22.580 19.900 1.00 0.00 +ATOM 2203 OW SOL 657 30.450 23.730 17.420 1.00 0.00 +ATOM 2204 HW1 SOL 657 30.200 24.650 17.470 1.00 0.00 +ATOM 2205 HW2 SOL 657 31.320 23.700 17.820 1.00 0.00 +ATOM 2206 OW SOL 658 15.580 39.030 10.310 1.00 0.00 +ATOM 2207 HW1 SOL 658 16.230 38.870 9.620 1.00 0.00 +ATOM 2208 HW2 SOL 658 14.740 38.880 9.890 1.00 0.00 +ATOM 2209 OW SOL 659 36.690 26.320 31.830 1.00 0.00 +ATOM 2210 HW1 SOL 659 36.370 26.570 30.960 1.00 0.00 +ATOM 2211 HW2 SOL 659 37.490 26.830 31.950 1.00 0.00 +ATOM 2212 OW SOL 660 26.040 12.550 8.120 1.00 0.00 +ATOM 2213 HW1 SOL 660 26.940 12.280 8.280 1.00 0.00 +ATOM 2214 HW2 SOL 660 25.620 12.500 8.990 1.00 0.00 +ATOM 2215 OW SOL 661 32.090 29.310 14.400 1.00 0.00 +ATOM 2216 HW1 SOL 661 32.660 29.590 13.680 1.00 0.00 +ATOM 2217 HW2 SOL 661 32.220 29.970 15.080 1.00 0.00 +ATOM 2218 OW SOL 662 18.900 4.620 14.000 1.00 0.00 +ATOM 2219 HW1 SOL 662 18.900 5.430 13.480 1.00 0.00 +ATOM 2220 HW2 SOL 662 19.660 4.710 14.570 1.00 0.00 +ATOM 2221 OW SOL 663 37.650 23.710 26.110 1.00 0.00 +ATOM 2222 HW1 SOL 663 38.580 23.690 25.900 1.00 0.00 +ATOM 2223 HW2 SOL 663 37.590 23.350 27.000 1.00 0.00 +ATOM 2224 OW SOL 664 25.050 43.760 27.840 1.00 0.00 +ATOM 2225 HW1 SOL 664 25.640 44.330 27.340 1.00 0.00 +ATOM 2226 HW2 SOL 664 25.630 43.250 28.410 1.00 0.00 +ATOM 2227 OW SOL 665 33.830 37.820 0.590 1.00 0.00 +ATOM 2228 HW1 SOL 665 33.430 37.600 -0.240 1.00 0.00 +ATOM 2229 HW2 SOL 665 33.490 37.170 1.210 1.00 0.00 +ATOM 2230 OW SOL 666 35.980 38.040 22.660 1.00 0.00 +ATOM 2231 HW1 SOL 666 35.110 38.290 22.350 1.00 0.00 +ATOM 2232 HW2 SOL 666 36.370 37.560 21.940 1.00 0.00 +ATOM 2233 OW SOL 667 35.030 29.300 28.280 1.00 0.00 +ATOM 2234 HW1 SOL 667 34.340 29.350 28.940 1.00 0.00 +ATOM 2235 HW2 SOL 667 34.620 29.640 27.480 1.00 0.00 +ATOM 2236 OW SOL 668 28.600 24.320 12.530 1.00 0.00 +ATOM 2237 HW1 SOL 668 28.470 25.170 12.940 1.00 0.00 +ATOM 2238 HW2 SOL 668 28.140 23.700 13.100 1.00 0.00 +ATOM 2239 OW SOL 669 25.880 43.800 18.190 1.00 0.00 +ATOM 2240 HW1 SOL 669 26.110 43.020 18.680 1.00 0.00 +ATOM 2241 HW2 SOL 669 26.060 44.530 18.780 1.00 0.00 +ATOM 2242 OW SOL 670 39.920 46.337 7.020 1.00 0.00 +ATOM 2243 HW1 SOL 670 39.030 46.217 6.680 1.00 0.00 +ATOM 2244 HW2 SOL 670 40.470 45.817 6.440 1.00 0.00 +ATOM 2245 OW SOL 671 40.560 16.200 26.950 1.00 0.00 +ATOM 2246 HW1 SOL 671 39.690 16.520 26.750 1.00 0.00 +ATOM 2247 HW2 SOL 671 40.680 16.400 27.880 1.00 0.00 +ATOM 2248 OW SOL 672 36.790 15.720 28.710 1.00 0.00 +ATOM 2249 HW1 SOL 672 36.100 15.770 29.370 1.00 0.00 +ATOM 2250 HW2 SOL 672 37.570 15.470 29.210 1.00 0.00 +ATOM 2251 OW SOL 673 10.670 26.910 23.950 1.00 0.00 +ATOM 2252 HW1 SOL 673 10.930 27.500 23.240 1.00 0.00 +ATOM 2253 HW2 SOL 673 10.260 26.160 23.500 1.00 0.00 +ATOM 2254 OW SOL 674 25.470 18.680 21.670 1.00 0.00 +ATOM 2255 HW1 SOL 674 25.070 19.120 20.920 1.00 0.00 +ATOM 2256 HW2 SOL 674 26.410 18.790 21.530 1.00 0.00 +ATOM 2257 OW SOL 675 42.850 29.540 11.470 1.00 0.00 +ATOM 2258 HW1 SOL 675 43.450 30.170 11.880 1.00 0.00 +ATOM 2259 HW2 SOL 675 42.000 29.700 11.870 1.00 0.00 +ATOM 2260 OW SOL 676 4.360 12.450 3.200 1.00 0.00 +ATOM 2261 HW1 SOL 676 4.530 11.890 3.960 1.00 0.00 +ATOM 2262 HW2 SOL 676 4.460 13.340 3.540 1.00 0.00 +ATOM 2263 OW SOL 677 0.830 4.560 27.790 1.00 0.00 +ATOM 2264 HW1 SOL 677 1.200 5.360 28.180 1.00 0.00 +ATOM 2265 HW2 SOL 677 1.150 3.850 28.350 1.00 0.00 +ATOM 2266 OW SOL 678 -0.997 23.550 21.780 1.00 0.00 +ATOM 2267 HW1 SOL 678 -0.627 22.700 22.030 1.00 0.00 +ATOM 2268 HW2 SOL 678 -1.707 23.330 21.180 1.00 0.00 +ATOM 2269 OW SOL 679 32.960 23.380 18.730 1.00 0.00 +ATOM 2270 HW1 SOL 679 33.880 23.350 18.440 1.00 0.00 +ATOM 2271 HW2 SOL 679 32.850 22.590 19.260 1.00 0.00 +ATOM 2272 OW SOL 680 22.860 26.350 8.680 1.00 0.00 +ATOM 2273 HW1 SOL 680 22.940 25.490 8.280 1.00 0.00 +ATOM 2274 HW2 SOL 680 22.510 26.190 9.560 1.00 0.00 +ATOM 2275 OW SOL 681 23.410 29.570 24.470 1.00 0.00 +ATOM 2276 HW1 SOL 681 24.340 29.510 24.260 1.00 0.00 +ATOM 2277 HW2 SOL 681 22.980 29.060 23.780 1.00 0.00 +ATOM 2278 OW SOL 682 0.130 22.640 26.000 1.00 0.00 +ATOM 2279 HW1 SOL 682 0.050 22.190 25.160 1.00 0.00 +ATOM 2280 HW2 SOL 682 0.070 21.950 26.650 1.00 0.00 +ATOM 2281 OW SOL 683 15.170 0.450 19.790 1.00 0.00 +ATOM 2282 HW1 SOL 683 14.660 -0.020 19.140 1.00 0.00 +ATOM 2283 HW2 SOL 683 15.410 1.270 19.360 1.00 0.00 +ATOM 2284 OW SOL 684 33.030 31.400 21.690 1.00 0.00 +ATOM 2285 HW1 SOL 684 32.830 30.590 22.160 1.00 0.00 +ATOM 2286 HW2 SOL 684 32.610 31.280 20.830 1.00 0.00 +ATOM 2287 OW SOL 685 25.090 10.660 28.550 1.00 0.00 +ATOM 2288 HW1 SOL 685 24.200 10.980 28.690 1.00 0.00 +ATOM 2289 HW2 SOL 685 25.060 9.740 28.810 1.00 0.00 +ATOM 2290 OW SOL 686 23.850 8.100 8.610 1.00 0.00 +ATOM 2291 HW1 SOL 686 24.020 8.760 7.940 1.00 0.00 +ATOM 2292 HW2 SOL 686 24.260 7.300 8.270 1.00 0.00 +ATOM 2293 OW SOL 687 7.220 1.150 4.240 1.00 0.00 +ATOM 2294 HW1 SOL 687 7.510 0.370 4.720 1.00 0.00 +ATOM 2295 HW2 SOL 687 8.010 1.680 4.150 1.00 0.00 +ATOM 2296 OW SOL 688 43.390 4.070 4.820 1.00 0.00 +ATOM 2297 HW1 SOL 688 43.220 4.520 3.990 1.00 0.00 +ATOM 2298 HW2 SOL 688 44.340 4.090 4.910 1.00 0.00 +ATOM 2299 OW SOL 689 29.940 29.590 0.550 1.00 0.00 +ATOM 2300 HW1 SOL 689 30.510 28.940 0.970 1.00 0.00 +ATOM 2301 HW2 SOL 689 30.370 30.430 0.710 1.00 0.00 +ATOM 2302 OW SOL 690 27.000 40.310 9.350 1.00 0.00 +ATOM 2303 HW1 SOL 690 26.430 39.610 9.050 1.00 0.00 +ATOM 2304 HW2 SOL 690 27.210 40.810 8.550 1.00 0.00 +ATOM 2305 OW SOL 691 19.960 10.820 30.350 1.00 0.00 +ATOM 2306 HW1 SOL 691 19.220 11.050 29.800 1.00 0.00 +ATOM 2307 HW2 SOL 691 19.570 10.360 31.100 1.00 0.00 +ATOM 2308 OW SOL 692 33.860 43.850 18.820 1.00 0.00 +ATOM 2309 HW1 SOL 692 32.950 43.750 19.100 1.00 0.00 +ATOM 2310 HW2 SOL 692 33.930 43.300 18.040 1.00 0.00 +ATOM 2311 OW SOL 693 6.110 47.817 1.120 1.00 0.00 +ATOM 2312 HW1 SOL 693 6.910 48.337 1.130 1.00 0.00 +ATOM 2313 HW2 SOL 693 5.400 48.457 1.090 1.00 0.00 +ATOM 2314 OW SOL 694 25.590 13.720 13.060 1.00 0.00 +ATOM 2315 HW1 SOL 694 26.350 14.020 13.560 1.00 0.00 +ATOM 2316 HW2 SOL 694 25.380 14.440 12.470 1.00 0.00 +ATOM 2317 OW SOL 695 41.230 13.000 14.870 1.00 0.00 +ATOM 2318 HW1 SOL 695 41.250 13.450 14.030 1.00 0.00 +ATOM 2319 HW2 SOL 695 42.140 12.810 15.080 1.00 0.00 +ATOM 2320 OW SOL 696 6.700 9.040 0.450 1.00 0.00 +ATOM 2321 HW1 SOL 696 6.680 9.990 0.520 1.00 0.00 +ATOM 2322 HW2 SOL 696 5.830 8.750 0.730 1.00 0.00 +ATOM 2323 OW SOL 697 42.500 43.920 5.140 1.00 0.00 +ATOM 2324 HW1 SOL 697 42.540 44.820 4.790 1.00 0.00 +ATOM 2325 HW2 SOL 697 42.890 43.380 4.450 1.00 0.00 +ATOM 2326 OW SOL 698 40.080 4.900 15.500 1.00 0.00 +ATOM 2327 HW1 SOL 698 39.440 5.070 14.810 1.00 0.00 +ATOM 2328 HW2 SOL 698 39.630 5.160 16.310 1.00 0.00 +ATOM 2329 OW SOL 699 21.540 39.040 12.580 1.00 0.00 +ATOM 2330 HW1 SOL 699 22.240 38.430 12.820 1.00 0.00 +ATOM 2331 HW2 SOL 699 21.940 39.610 11.920 1.00 0.00 +ATOM 2332 OW SOL 700 30.980 19.080 28.860 1.00 0.00 +ATOM 2333 HW1 SOL 700 31.750 19.480 28.440 1.00 0.00 +ATOM 2334 HW2 SOL 700 31.340 18.390 29.420 1.00 0.00 +ATOM 2335 OW SOL 701 43.820 20.810 10.390 1.00 0.00 +ATOM 2336 HW1 SOL 701 44.090 21.410 9.700 1.00 0.00 +ATOM 2337 HW2 SOL 701 43.540 21.390 11.110 1.00 0.00 +ATOM 2338 OW SOL 702 46.957 2.240 23.820 1.00 0.00 +ATOM 2339 HW1 SOL 702 46.727 2.570 22.950 1.00 0.00 +ATOM 2340 HW2 SOL 702 47.337 3.000 24.270 1.00 0.00 +ATOM 2341 OW SOL 703 45.737 36.870 7.160 1.00 0.00 +ATOM 2342 HW1 SOL 703 45.687 35.920 7.060 1.00 0.00 +ATOM 2343 HW2 SOL 703 45.427 37.210 6.320 1.00 0.00 +ATOM 2344 OW SOL 704 43.550 13.520 26.590 1.00 0.00 +ATOM 2345 HW1 SOL 704 44.030 13.010 25.940 1.00 0.00 +ATOM 2346 HW2 SOL 704 43.930 13.260 27.430 1.00 0.00 +ATOM 2347 OW SOL 705 15.550 43.310 3.440 1.00 0.00 +ATOM 2348 HW1 SOL 705 16.160 43.020 4.120 1.00 0.00 +ATOM 2349 HW2 SOL 705 15.890 44.170 3.170 1.00 0.00 +ATOM 2350 OW SOL 706 9.250 30.800 10.060 1.00 0.00 +ATOM 2351 HW1 SOL 706 9.110 31.670 10.420 1.00 0.00 +ATOM 2352 HW2 SOL 706 10.110 30.840 9.640 1.00 0.00 +ATOM 2353 OW SOL 707 31.030 34.480 21.510 1.00 0.00 +ATOM 2354 HW1 SOL 707 30.740 34.300 22.410 1.00 0.00 +ATOM 2355 HW2 SOL 707 30.560 33.840 20.970 1.00 0.00 +ATOM 2356 OW SOL 708 6.660 36.880 17.140 1.00 0.00 +ATOM 2357 HW1 SOL 708 6.220 37.640 17.510 1.00 0.00 +ATOM 2358 HW2 SOL 708 6.590 36.200 17.810 1.00 0.00 +ATOM 2359 OW SOL 709 28.250 27.080 10.080 1.00 0.00 +ATOM 2360 HW1 SOL 709 27.530 27.620 9.750 1.00 0.00 +ATOM 2361 HW2 SOL 709 28.690 26.770 9.290 1.00 0.00 +ATOM 2362 OW SOL 710 32.760 35.510 4.570 1.00 0.00 +ATOM 2363 HW1 SOL 710 32.580 34.690 5.020 1.00 0.00 +ATOM 2364 HW2 SOL 710 32.920 36.140 5.270 1.00 0.00 +ATOM 2365 OW SOL 711 33.660 22.820 27.130 1.00 0.00 +ATOM 2366 HW1 SOL 711 34.090 23.150 27.920 1.00 0.00 +ATOM 2367 HW2 SOL 711 34.110 23.250 26.410 1.00 0.00 +ATOM 2368 OW SOL 712 19.090 38.010 12.220 1.00 0.00 +ATOM 2369 HW1 SOL 712 19.970 38.380 12.230 1.00 0.00 +ATOM 2370 HW2 SOL 712 19.000 37.640 11.340 1.00 0.00 +ATOM 2371 OW SOL 713 37.230 6.340 30.420 1.00 0.00 +ATOM 2372 HW1 SOL 713 37.360 7.150 30.920 1.00 0.00 +ATOM 2373 HW2 SOL 713 37.880 5.740 30.780 1.00 0.00 +ATOM 2374 OW SOL 714 39.600 13.950 6.190 1.00 0.00 +ATOM 2375 HW1 SOL 714 40.320 13.690 5.610 1.00 0.00 +ATOM 2376 HW2 SOL 714 39.810 14.850 6.430 1.00 0.00 +ATOM 2377 OW SOL 715 2.780 38.130 17.890 1.00 0.00 +ATOM 2378 HW1 SOL 715 3.700 38.360 18.000 1.00 0.00 +ATOM 2379 HW2 SOL 715 2.320 38.620 18.570 1.00 0.00 +ATOM 2380 OW SOL 716 4.450 31.340 8.850 1.00 0.00 +ATOM 2381 HW1 SOL 716 5.190 30.730 8.920 1.00 0.00 +ATOM 2382 HW2 SOL 716 4.190 31.290 7.930 1.00 0.00 +ATOM 2383 OW SOL 717 5.810 40.330 13.380 1.00 0.00 +ATOM 2384 HW1 SOL 717 4.910 40.540 13.630 1.00 0.00 +ATOM 2385 HW2 SOL 717 5.850 39.380 13.360 1.00 0.00 +ATOM 2386 OW SOL 718 19.920 16.460 17.760 1.00 0.00 +ATOM 2387 HW1 SOL 718 20.510 15.700 17.800 1.00 0.00 +ATOM 2388 HW2 SOL 718 20.510 17.200 17.600 1.00 0.00 +ATOM 2389 OW SOL 719 2.640 8.730 31.270 1.00 0.00 +ATOM 2390 HW1 SOL 719 1.860 8.300 30.910 1.00 0.00 +ATOM 2391 HW2 SOL 719 3.210 8.010 31.540 1.00 0.00 +ATOM 2392 OW SOL 720 23.480 36.900 12.580 1.00 0.00 +ATOM 2393 HW1 SOL 720 23.510 36.190 13.220 1.00 0.00 +ATOM 2394 HW2 SOL 720 23.960 36.570 11.830 1.00 0.00 +ATOM 2395 OW SOL 721 43.890 28.720 1.670 1.00 0.00 +ATOM 2396 HW1 SOL 721 44.640 28.780 1.080 1.00 0.00 +ATOM 2397 HW2 SOL 721 44.130 28.030 2.290 1.00 0.00 +ATOM 2398 OW SOL 722 19.430 8.770 4.360 1.00 0.00 +ATOM 2399 HW1 SOL 722 20.260 9.120 4.030 1.00 0.00 +ATOM 2400 HW2 SOL 722 18.800 9.010 3.680 1.00 0.00 +ATOM 2401 OW SOL 723 0.130 27.170 25.670 1.00 0.00 +ATOM 2402 HW1 SOL 723 0.300 26.540 24.970 1.00 0.00 +ATOM 2403 HW2 SOL 723 -0.810 27.340 25.610 1.00 0.00 +ATOM 2404 OW SOL 724 39.730 24.090 2.220 1.00 0.00 +ATOM 2405 HW1 SOL 724 40.430 23.450 2.320 1.00 0.00 +ATOM 2406 HW2 SOL 724 39.630 24.190 1.270 1.00 0.00 +ATOM 2407 OW SOL 725 6.410 28.410 16.610 1.00 0.00 +ATOM 2408 HW1 SOL 725 6.850 29.140 17.030 1.00 0.00 +ATOM 2409 HW2 SOL 725 7.090 27.740 16.500 1.00 0.00 +ATOM 2410 OW SOL 726 20.460 13.060 23.920 1.00 0.00 +ATOM 2411 HW1 SOL 726 21.260 12.790 24.380 1.00 0.00 +ATOM 2412 HW2 SOL 726 20.760 13.720 23.300 1.00 0.00 +ATOM 2413 OW SOL 727 16.040 5.860 29.340 1.00 0.00 +ATOM 2414 HW1 SOL 727 16.870 6.290 29.130 1.00 0.00 +ATOM 2415 HW2 SOL 727 15.440 6.140 28.650 1.00 0.00 +ATOM 2416 OW SOL 728 13.000 38.840 9.220 1.00 0.00 +ATOM 2417 HW1 SOL 728 12.850 37.980 9.600 1.00 0.00 +ATOM 2418 HW2 SOL 728 12.600 38.800 8.350 1.00 0.00 +ATOM 2419 OW SOL 729 32.810 37.050 24.780 1.00 0.00 +ATOM 2420 HW1 SOL 729 33.740 36.980 24.980 1.00 0.00 +ATOM 2421 HW2 SOL 729 32.450 36.190 25.000 1.00 0.00 +ATOM 2422 OW SOL 730 25.720 29.870 30.550 1.00 0.00 +ATOM 2423 HW1 SOL 730 26.620 29.590 30.390 1.00 0.00 +ATOM 2424 HW2 SOL 730 25.180 29.200 30.140 1.00 0.00 +ATOM 2425 OW SOL 731 3.920 5.550 15.850 1.00 0.00 +ATOM 2426 HW1 SOL 731 4.060 4.650 16.150 1.00 0.00 +ATOM 2427 HW2 SOL 731 3.070 5.800 16.230 1.00 0.00 +ATOM 2428 OW SOL 732 3.590 16.130 6.610 1.00 0.00 +ATOM 2429 HW1 SOL 732 4.490 16.210 6.920 1.00 0.00 +ATOM 2430 HW2 SOL 732 3.110 16.820 7.070 1.00 0.00 +ATOM 2431 OW SOL 733 7.600 44.020 4.720 1.00 0.00 +ATOM 2432 HW1 SOL 733 8.470 43.850 4.360 1.00 0.00 +ATOM 2433 HW2 SOL 733 7.350 43.190 5.130 1.00 0.00 +ATOM 2434 OW SOL 734 17.870 15.410 24.920 1.00 0.00 +ATOM 2435 HW1 SOL 734 18.720 15.710 24.600 1.00 0.00 +ATOM 2436 HW2 SOL 734 17.970 14.470 25.020 1.00 0.00 +ATOM 2437 OW SOL 735 35.200 44.920 25.350 1.00 0.00 +ATOM 2438 HW1 SOL 735 34.630 44.710 24.610 1.00 0.00 +ATOM 2439 HW2 SOL 735 36.050 44.560 25.110 1.00 0.00 +ATOM 2440 OW SOL 736 14.290 23.550 26.230 1.00 0.00 +ATOM 2441 HW1 SOL 736 15.230 23.580 26.430 1.00 0.00 +ATOM 2442 HW2 SOL 736 13.870 23.320 27.060 1.00 0.00 +ATOM 2443 OW SOL 737 39.250 41.540 19.200 1.00 0.00 +ATOM 2444 HW1 SOL 737 39.060 41.060 20.000 1.00 0.00 +ATOM 2445 HW2 SOL 737 39.580 40.870 18.600 1.00 0.00 +ATOM 2446 OW SOL 738 44.710 9.080 8.450 1.00 0.00 +ATOM 2447 HW1 SOL 738 45.240 9.760 8.860 1.00 0.00 +ATOM 2448 HW2 SOL 738 45.200 8.270 8.590 1.00 0.00 +ATOM 2449 OW SOL 739 8.070 25.940 5.330 1.00 0.00 +ATOM 2450 HW1 SOL 739 8.070 25.090 5.760 1.00 0.00 +ATOM 2451 HW2 SOL 739 8.000 25.730 4.400 1.00 0.00 +ATOM 2452 OW SOL 740 19.540 6.640 17.630 1.00 0.00 +ATOM 2453 HW1 SOL 740 18.920 7.310 17.900 1.00 0.00 +ATOM 2454 HW2 SOL 740 19.970 7.010 16.860 1.00 0.00 +ATOM 2455 OW SOL 741 30.310 6.250 26.150 1.00 0.00 +ATOM 2456 HW1 SOL 741 31.140 5.800 26.290 1.00 0.00 +ATOM 2457 HW2 SOL 741 29.640 5.590 26.380 1.00 0.00 +ATOM 2458 OW SOL 742 22.620 35.340 5.080 1.00 0.00 +ATOM 2459 HW1 SOL 742 21.870 35.540 4.530 1.00 0.00 +ATOM 2460 HW2 SOL 742 23.300 35.040 4.470 1.00 0.00 +ATOM 2461 OW SOL 743 17.950 20.700 15.270 1.00 0.00 +ATOM 2462 HW1 SOL 743 18.010 21.660 15.240 1.00 0.00 +ATOM 2463 HW2 SOL 743 17.890 20.500 16.210 1.00 0.00 +ATOM 2464 OW SOL 744 14.840 30.420 24.060 1.00 0.00 +ATOM 2465 HW1 SOL 744 14.750 29.750 23.380 1.00 0.00 +ATOM 2466 HW2 SOL 744 14.900 29.920 24.880 1.00 0.00 +ATOM 2467 OW SOL 745 42.840 28.120 5.560 1.00 0.00 +ATOM 2468 HW1 SOL 745 43.340 28.940 5.650 1.00 0.00 +ATOM 2469 HW2 SOL 745 42.020 28.290 6.010 1.00 0.00 +ATOM 2470 OW SOL 746 44.060 30.110 22.740 1.00 0.00 +ATOM 2471 HW1 SOL 746 44.140 30.840 22.130 1.00 0.00 +ATOM 2472 HW2 SOL 746 43.410 29.540 22.340 1.00 0.00 +ATOM 2473 OW SOL 747 30.710 42.620 22.020 1.00 0.00 +ATOM 2474 HW1 SOL 747 30.990 43.230 22.700 1.00 0.00 +ATOM 2475 HW2 SOL 747 29.990 42.130 22.420 1.00 0.00 +ATOM 2476 OW SOL 748 18.700 14.690 10.770 1.00 0.00 +ATOM 2477 HW1 SOL 748 18.420 15.080 9.940 1.00 0.00 +ATOM 2478 HW2 SOL 748 19.050 15.430 11.270 1.00 0.00 +ATOM 2479 OW SOL 749 21.560 30.670 19.730 1.00 0.00 +ATOM 2480 HW1 SOL 749 21.510 30.170 18.920 1.00 0.00 +ATOM 2481 HW2 SOL 749 21.350 31.570 19.480 1.00 0.00 +ATOM 2482 OW SOL 750 1.050 21.680 16.910 1.00 0.00 +ATOM 2483 HW1 SOL 750 1.510 21.500 17.730 1.00 0.00 +ATOM 2484 HW2 SOL 750 0.470 22.410 17.120 1.00 0.00 +ATOM 2485 OW SOL 751 16.960 26.760 10.330 1.00 0.00 +ATOM 2486 HW1 SOL 751 17.700 27.300 10.060 1.00 0.00 +ATOM 2487 HW2 SOL 751 16.290 27.380 10.590 1.00 0.00 +ATOM 2488 OW SOL 752 23.480 42.950 12.400 1.00 0.00 +ATOM 2489 HW1 SOL 752 22.760 42.660 12.960 1.00 0.00 +ATOM 2490 HW2 SOL 752 23.360 43.900 12.330 1.00 0.00 +ATOM 2491 OW SOL 753 23.580 10.590 31.890 1.00 0.00 +ATOM 2492 HW1 SOL 753 24.120 11.380 31.890 1.00 0.00 +ATOM 2493 HW2 SOL 753 23.020 10.690 32.670 1.00 0.00 +ATOM 2494 OW SOL 754 18.080 11.300 9.490 1.00 0.00 +ATOM 2495 HW1 SOL 754 18.310 12.000 8.890 1.00 0.00 +ATOM 2496 HW2 SOL 754 18.560 10.530 9.170 1.00 0.00 +ATOM 2497 OW SOL 755 23.440 35.320 15.030 1.00 0.00 +ATOM 2498 HW1 SOL 755 23.500 34.640 15.700 1.00 0.00 +ATOM 2499 HW2 SOL 755 22.790 34.980 14.410 1.00 0.00 +ATOM 2500 OW SOL 756 37.090 7.310 21.130 1.00 0.00 +ATOM 2501 HW1 SOL 756 36.430 8.000 21.100 1.00 0.00 +ATOM 2502 HW2 SOL 756 37.100 7.030 22.050 1.00 0.00 +ATOM 2503 OW SOL 757 34.630 42.530 2.740 1.00 0.00 +ATOM 2504 HW1 SOL 757 33.790 42.090 2.640 1.00 0.00 +ATOM 2505 HW2 SOL 757 34.690 43.110 1.980 1.00 0.00 +ATOM 2506 OW SOL 758 6.030 10.270 24.370 1.00 0.00 +ATOM 2507 HW1 SOL 758 6.400 9.630 24.980 1.00 0.00 +ATOM 2508 HW2 SOL 758 6.030 9.830 23.520 1.00 0.00 +ATOM 2509 OW SOL 759 10.620 13.230 18.520 1.00 0.00 +ATOM 2510 HW1 SOL 759 10.840 12.650 17.790 1.00 0.00 +ATOM 2511 HW2 SOL 759 10.030 13.880 18.140 1.00 0.00 +ATOM 2512 OW SOL 760 4.860 12.030 8.940 1.00 0.00 +ATOM 2513 HW1 SOL 760 5.340 12.820 8.650 1.00 0.00 +ATOM 2514 HW2 SOL 760 4.710 12.170 9.880 1.00 0.00 +ATOM 2515 OW SOL 761 30.380 30.140 30.690 1.00 0.00 +ATOM 2516 HW1 SOL 761 31.000 29.770 31.320 1.00 0.00 +ATOM 2517 HW2 SOL 761 29.850 30.750 31.210 1.00 0.00 +ATOM 2518 OW SOL 762 43.290 39.890 6.660 1.00 0.00 +ATOM 2519 HW1 SOL 762 44.220 39.810 6.860 1.00 0.00 +ATOM 2520 HW2 SOL 762 42.870 39.230 7.210 1.00 0.00 +ATOM 2521 OW SOL 763 30.640 25.510 28.510 1.00 0.00 +ATOM 2522 HW1 SOL 763 31.590 25.590 28.470 1.00 0.00 +ATOM 2523 HW2 SOL 763 30.480 24.960 29.280 1.00 0.00 +ATOM 2524 OW SOL 764 2.630 1.410 14.690 1.00 0.00 +ATOM 2525 HW1 SOL 764 3.350 1.950 14.990 1.00 0.00 +ATOM 2526 HW2 SOL 764 2.540 1.610 13.760 1.00 0.00 +ATOM 2527 OW SOL 765 28.430 20.310 4.550 1.00 0.00 +ATOM 2528 HW1 SOL 765 27.970 19.750 5.180 1.00 0.00 +ATOM 2529 HW2 SOL 765 28.590 19.750 3.790 1.00 0.00 +ATOM 2530 OW SOL 766 25.410 26.280 12.770 1.00 0.00 +ATOM 2531 HW1 SOL 766 25.330 25.980 11.860 1.00 0.00 +ATOM 2532 HW2 SOL 766 26.330 26.520 12.850 1.00 0.00 +ATOM 2533 OW SOL 767 44.810 8.350 17.570 1.00 0.00 +ATOM 2534 HW1 SOL 767 44.880 8.770 18.420 1.00 0.00 +ATOM 2535 HW2 SOL 767 43.900 8.070 17.510 1.00 0.00 +ATOM 2536 OW SOL 768 18.200 8.580 26.020 1.00 0.00 +ATOM 2537 HW1 SOL 768 17.720 8.450 25.210 1.00 0.00 +ATOM 2538 HW2 SOL 768 18.840 7.870 26.040 1.00 0.00 +ATOM 2539 OW SOL 769 43.500 3.930 15.170 1.00 0.00 +ATOM 2540 HW1 SOL 769 42.700 3.640 14.740 1.00 0.00 +ATOM 2541 HW2 SOL 769 43.230 4.140 16.070 1.00 0.00 +ATOM 2542 OW SOL 770 17.430 1.160 28.590 1.00 0.00 +ATOM 2543 HW1 SOL 770 17.080 1.140 27.700 1.00 0.00 +ATOM 2544 HW2 SOL 770 18.370 1.340 28.470 1.00 0.00 +ATOM 2545 OW SOL 771 3.310 42.070 7.700 1.00 0.00 +ATOM 2546 HW1 SOL 771 3.440 41.640 8.540 1.00 0.00 +ATOM 2547 HW2 SOL 771 3.510 41.390 7.050 1.00 0.00 +ATOM 2548 OW SOL 772 36.120 1.930 21.510 1.00 0.00 +ATOM 2549 HW1 SOL 772 36.150 1.160 20.950 1.00 0.00 +ATOM 2550 HW2 SOL 772 36.820 2.490 21.180 1.00 0.00 +ATOM 2551 OW SOL 773 14.070 36.740 14.580 1.00 0.00 +ATOM 2552 HW1 SOL 773 13.570 37.550 14.510 1.00 0.00 +ATOM 2553 HW2 SOL 773 14.690 36.790 13.850 1.00 0.00 +ATOM 2554 OW SOL 774 11.480 6.700 20.050 1.00 0.00 +ATOM 2555 HW1 SOL 774 10.850 6.270 20.640 1.00 0.00 +ATOM 2556 HW2 SOL 774 11.980 5.980 19.670 1.00 0.00 +ATOM 2557 OW SOL 775 5.950 41.520 17.900 1.00 0.00 +ATOM 2558 HW1 SOL 775 6.290 41.550 17.000 1.00 0.00 +ATOM 2559 HW2 SOL 775 5.160 42.060 17.870 1.00 0.00 +ATOM 2560 OW SOL 776 29.950 33.010 24.520 1.00 0.00 +ATOM 2561 HW1 SOL 776 29.770 32.110 24.260 1.00 0.00 +ATOM 2562 HW2 SOL 776 29.110 33.330 24.850 1.00 0.00 +ATOM 2563 OW SOL 777 3.390 34.530 8.100 1.00 0.00 +ATOM 2564 HW1 SOL 777 4.110 33.970 8.400 1.00 0.00 +ATOM 2565 HW2 SOL 777 2.630 34.250 8.600 1.00 0.00 +ATOM 2566 OW SOL 778 41.210 29.860 20.860 1.00 0.00 +ATOM 2567 HW1 SOL 778 40.850 29.660 20.000 1.00 0.00 +ATOM 2568 HW2 SOL 778 41.080 30.800 20.960 1.00 0.00 +ATOM 2569 OW SOL 779 29.240 20.550 30.130 1.00 0.00 +ATOM 2570 HW1 SOL 779 29.990 20.080 29.780 1.00 0.00 +ATOM 2571 HW2 SOL 779 29.170 21.330 29.580 1.00 0.00 +ATOM 2572 OW SOL 780 21.130 8.280 28.560 1.00 0.00 +ATOM 2573 HW1 SOL 780 20.280 8.050 28.930 1.00 0.00 +ATOM 2574 HW2 SOL 780 21.640 8.600 29.300 1.00 0.00 +ATOM 2575 OW SOL 781 40.950 35.200 7.460 1.00 0.00 +ATOM 2576 HW1 SOL 781 40.040 35.260 7.170 1.00 0.00 +ATOM 2577 HW2 SOL 781 41.370 34.630 6.820 1.00 0.00 +ATOM 2578 OW SOL 782 34.360 1.160 17.670 1.00 0.00 +ATOM 2579 HW1 SOL 782 33.610 0.680 17.320 1.00 0.00 +ATOM 2580 HW2 SOL 782 34.490 0.810 18.550 1.00 0.00 +ATOM 2581 OW SOL 783 22.080 34.380 12.810 1.00 0.00 +ATOM 2582 HW1 SOL 783 22.200 33.590 12.280 1.00 0.00 +ATOM 2583 HW2 SOL 783 21.320 34.810 12.440 1.00 0.00 +ATOM 2584 OW SOL 784 17.190 32.280 4.840 1.00 0.00 +ATOM 2585 HW1 SOL 784 17.650 32.250 5.680 1.00 0.00 +ATOM 2586 HW2 SOL 784 16.670 33.080 4.880 1.00 0.00 +ATOM 2587 OW SOL 785 0.410 41.310 9.750 1.00 0.00 +ATOM 2588 HW1 SOL 785 -0.230 40.780 10.230 1.00 0.00 +ATOM 2589 HW2 SOL 785 1.090 41.490 10.400 1.00 0.00 +ATOM 2590 OW SOL 786 30.950 42.200 3.880 1.00 0.00 +ATOM 2591 HW1 SOL 786 31.510 42.970 3.790 1.00 0.00 +ATOM 2592 HW2 SOL 786 30.640 42.030 2.990 1.00 0.00 +ATOM 2593 OW SOL 787 0.450 5.640 10.260 1.00 0.00 +ATOM 2594 HW1 SOL 787 0.210 4.890 10.800 1.00 0.00 +ATOM 2595 HW2 SOL 787 0.460 6.380 10.880 1.00 0.00 +ATOM 2596 OW SOL 788 17.600 29.950 9.510 1.00 0.00 +ATOM 2597 HW1 SOL 788 17.720 30.870 9.290 1.00 0.00 +ATOM 2598 HW2 SOL 788 18.240 29.790 10.210 1.00 0.00 +ATOM 2599 OW SOL 789 35.970 1.690 1.180 1.00 0.00 +ATOM 2600 HW1 SOL 789 35.670 2.500 0.770 1.00 0.00 +ATOM 2601 HW2 SOL 789 35.300 1.040 0.950 1.00 0.00 +ATOM 2602 OW SOL 790 31.980 3.050 16.500 1.00 0.00 +ATOM 2603 HW1 SOL 790 32.470 2.230 16.540 1.00 0.00 +ATOM 2604 HW2 SOL 790 31.580 3.040 15.620 1.00 0.00 +ATOM 2605 OW SOL 791 14.840 16.620 7.700 1.00 0.00 +ATOM 2606 HW1 SOL 791 14.680 15.690 7.540 1.00 0.00 +ATOM 2607 HW2 SOL 791 14.010 17.050 7.480 1.00 0.00 +ATOM 2608 OW SOL 792 25.900 20.930 1.050 1.00 0.00 +ATOM 2609 HW1 SOL 792 26.170 21.800 0.750 1.00 0.00 +ATOM 2610 HW2 SOL 792 26.730 20.450 1.160 1.00 0.00 +ATOM 2611 OW SOL 793 6.400 43.110 7.680 1.00 0.00 +ATOM 2612 HW1 SOL 793 7.340 43.300 7.670 1.00 0.00 +ATOM 2613 HW2 SOL 793 6.340 42.170 7.510 1.00 0.00 +ATOM 2614 OW SOL 794 22.080 12.100 25.990 1.00 0.00 +ATOM 2615 HW1 SOL 794 23.020 12.000 25.820 1.00 0.00 +ATOM 2616 HW2 SOL 794 22.040 12.530 26.850 1.00 0.00 +ATOM 2617 OW SOL 795 19.350 16.860 12.090 1.00 0.00 +ATOM 2618 HW1 SOL 795 20.200 17.310 12.020 1.00 0.00 +ATOM 2619 HW2 SOL 795 19.120 16.920 13.010 1.00 0.00 +ATOM 2620 OW SOL 796 7.900 14.550 17.740 1.00 0.00 +ATOM 2621 HW1 SOL 796 7.220 13.920 17.490 1.00 0.00 +ATOM 2622 HW2 SOL 796 7.640 14.850 18.610 1.00 0.00 +ATOM 2623 OW SOL 797 5.300 6.730 25.990 1.00 0.00 +ATOM 2624 HW1 SOL 797 5.400 5.820 26.270 1.00 0.00 +ATOM 2625 HW2 SOL 797 5.090 6.670 25.060 1.00 0.00 +ATOM 2626 OW SOL 798 36.140 37.680 29.520 1.00 0.00 +ATOM 2627 HW1 SOL 798 36.870 38.170 29.900 1.00 0.00 +ATOM 2628 HW2 SOL 798 36.420 36.770 29.550 1.00 0.00 +ATOM 2629 OW SOL 799 31.350 43.130 28.160 1.00 0.00 +ATOM 2630 HW1 SOL 799 31.920 42.370 28.270 1.00 0.00 +ATOM 2631 HW2 SOL 799 31.810 43.840 28.610 1.00 0.00 +ATOM 2632 OW SOL 800 21.440 48.117 13.890 1.00 0.00 +ATOM 2633 HW1 SOL 800 21.570 47.917 12.960 1.00 0.00 +ATOM 2634 HW2 SOL 800 20.630 47.667 14.130 1.00 0.00 +ATOM 2635 OW SOL 801 22.750 51.687 17.190 1.00 0.00 +ATOM 2636 HW1 SOL 801 22.180 52.277 16.690 1.00 0.00 +ATOM 2637 HW2 SOL 801 22.290 50.847 17.180 1.00 0.00 +ATOM 2638 OW SOL 802 18.650 19.500 10.680 1.00 0.00 +ATOM 2639 HW1 SOL 802 19.290 19.010 11.210 1.00 0.00 +ATOM 2640 HW2 SOL 802 17.840 19.440 11.180 1.00 0.00 +ATOM 2641 OW SOL 803 0.910 40.280 6.980 1.00 0.00 +ATOM 2642 HW1 SOL 803 0.810 40.780 7.790 1.00 0.00 +ATOM 2643 HW2 SOL 803 0.790 40.920 6.280 1.00 0.00 +ATOM 2644 OW SOL 804 -2.257 11.270 12.860 1.00 0.00 +ATOM 2645 HW1 SOL 804 -1.617 11.440 13.550 1.00 0.00 +ATOM 2646 HW2 SOL 804 -2.817 10.580 13.210 1.00 0.00 +ATOM 2647 OW SOL 805 1.580 43.520 12.780 1.00 0.00 +ATOM 2648 HW1 SOL 805 1.850 42.850 12.150 1.00 0.00 +ATOM 2649 HW2 SOL 805 1.180 44.210 12.240 1.00 0.00 +ATOM 2650 OW SOL 806 12.270 17.650 7.360 1.00 0.00 +ATOM 2651 HW1 SOL 806 12.140 18.560 7.630 1.00 0.00 +ATOM 2652 HW2 SOL 806 11.540 17.170 7.750 1.00 0.00 +ATOM 2653 OW SOL 807 5.520 3.550 28.640 1.00 0.00 +ATOM 2654 HW1 SOL 807 5.970 4.370 28.850 1.00 0.00 +ATOM 2655 HW2 SOL 807 5.440 3.110 29.490 1.00 0.00 +ATOM 2656 OW SOL 808 12.910 23.540 3.630 1.00 0.00 +ATOM 2657 HW1 SOL 808 13.340 23.520 4.480 1.00 0.00 +ATOM 2658 HW2 SOL 808 12.340 24.300 3.660 1.00 0.00 +ATOM 2659 OW SOL 809 27.130 20.870 31.730 1.00 0.00 +ATOM 2660 HW1 SOL 809 27.340 21.790 31.850 1.00 0.00 +ATOM 2661 HW2 SOL 809 27.680 20.580 31.010 1.00 0.00 +ATOM 2662 OW SOL 810 19.240 6.290 11.370 1.00 0.00 +ATOM 2663 HW1 SOL 810 19.530 7.200 11.220 1.00 0.00 +ATOM 2664 HW2 SOL 810 20.030 5.760 11.210 1.00 0.00 +ATOM 2665 OW SOL 811 35.270 28.720 4.630 1.00 0.00 +ATOM 2666 HW1 SOL 811 34.700 28.810 5.390 1.00 0.00 +ATOM 2667 HW2 SOL 811 35.840 27.990 4.850 1.00 0.00 +ATOM 2668 OW SOL 812 35.200 10.170 3.260 1.00 0.00 +ATOM 2669 HW1 SOL 812 34.350 10.470 3.580 1.00 0.00 +ATOM 2670 HW2 SOL 812 35.030 9.920 2.350 1.00 0.00 +ATOM 2671 OW SOL 813 21.610 44.610 15.550 1.00 0.00 +ATOM 2672 HW1 SOL 813 21.890 44.260 16.390 1.00 0.00 +ATOM 2673 HW2 SOL 813 21.510 43.840 14.990 1.00 0.00 +ATOM 2674 OW SOL 814 8.880 19.750 6.040 1.00 0.00 +ATOM 2675 HW1 SOL 814 8.770 20.680 5.890 1.00 0.00 +ATOM 2676 HW2 SOL 814 9.800 19.580 5.850 1.00 0.00 +ATOM 2677 OW SOL 815 8.650 17.970 29.150 1.00 0.00 +ATOM 2678 HW1 SOL 815 7.890 17.660 28.640 1.00 0.00 +ATOM 2679 HW2 SOL 815 8.570 18.920 29.140 1.00 0.00 +ATOM 2680 OW SOL 816 44.580 21.070 30.390 1.00 0.00 +ATOM 2681 HW1 SOL 816 44.530 20.130 30.570 1.00 0.00 +ATOM 2682 HW2 SOL 816 44.910 21.130 29.500 1.00 0.00 +ATOM 2683 OW SOL 817 23.750 10.680 17.580 1.00 0.00 +ATOM 2684 HW1 SOL 817 23.490 11.110 16.770 1.00 0.00 +ATOM 2685 HW2 SOL 817 24.640 10.380 17.420 1.00 0.00 +ATOM 2686 OW SOL 818 37.910 18.770 0.650 1.00 0.00 +ATOM 2687 HW1 SOL 818 38.560 19.420 0.370 1.00 0.00 +ATOM 2688 HW2 SOL 818 37.370 19.240 1.290 1.00 0.00 +ATOM 2689 OW SOL 819 38.740 44.450 28.260 1.00 0.00 +ATOM 2690 HW1 SOL 819 39.350 43.830 28.670 1.00 0.00 +ATOM 2691 HW2 SOL 819 37.980 43.930 28.030 1.00 0.00 +ATOM 2692 OW SOL 820 19.650 15.950 14.820 1.00 0.00 +ATOM 2693 HW1 SOL 820 20.520 15.680 14.530 1.00 0.00 +ATOM 2694 HW2 SOL 820 19.790 16.350 15.680 1.00 0.00 +ATOM 2695 OW SOL 821 3.160 18.730 30.490 1.00 0.00 +ATOM 2696 HW1 SOL 821 2.720 19.440 30.950 1.00 0.00 +ATOM 2697 HW2 SOL 821 2.470 18.100 30.300 1.00 0.00 +ATOM 2698 OW SOL 822 24.060 43.630 9.380 1.00 0.00 +ATOM 2699 HW1 SOL 822 24.050 44.590 9.410 1.00 0.00 +ATOM 2700 HW2 SOL 822 24.470 43.370 10.200 1.00 0.00 +ATOM 2701 OW SOL 823 37.500 16.640 25.850 1.00 0.00 +ATOM 2702 HW1 SOL 823 37.700 16.310 26.730 1.00 0.00 +ATOM 2703 HW2 SOL 823 36.940 15.960 25.460 1.00 0.00 +ATOM 2704 OW SOL 824 20.850 6.900 8.950 1.00 0.00 +ATOM 2705 HW1 SOL 824 21.630 6.820 8.400 1.00 0.00 +ATOM 2706 HW2 SOL 824 20.440 7.710 8.670 1.00 0.00 +ATOM 2707 OW SOL 825 15.320 10.330 1.280 1.00 0.00 +ATOM 2708 HW1 SOL 825 14.650 10.870 0.860 1.00 0.00 +ATOM 2709 HW2 SOL 825 15.880 10.040 0.560 1.00 0.00 +ATOM 2710 OW SOL 826 42.570 27.210 25.690 1.00 0.00 +ATOM 2711 HW1 SOL 826 41.880 27.260 26.360 1.00 0.00 +ATOM 2712 HW2 SOL 826 42.180 27.630 24.920 1.00 0.00 +ATOM 2713 OW SOL 827 12.470 36.900 3.450 1.00 0.00 +ATOM 2714 HW1 SOL 827 11.840 37.220 2.810 1.00 0.00 +ATOM 2715 HW2 SOL 827 12.130 36.040 3.710 1.00 0.00 +ATOM 2716 OW SOL 828 5.980 1.700 14.470 1.00 0.00 +ATOM 2717 HW1 SOL 828 5.870 1.330 15.340 1.00 0.00 +ATOM 2718 HW2 SOL 828 5.930 0.950 13.880 1.00 0.00 +ATOM 2719 OW SOL 829 2.410 23.720 26.950 1.00 0.00 +ATOM 2720 HW1 SOL 829 2.590 24.240 26.160 1.00 0.00 +ATOM 2721 HW2 SOL 829 1.600 23.270 26.750 1.00 0.00 +ATOM 2722 OW SOL 830 8.590 43.790 10.490 1.00 0.00 +ATOM 2723 HW1 SOL 830 8.980 42.920 10.370 1.00 0.00 +ATOM 2724 HW2 SOL 830 7.880 43.650 11.120 1.00 0.00 +ATOM 2725 OW SOL 831 20.510 35.660 22.610 1.00 0.00 +ATOM 2726 HW1 SOL 831 20.040 34.840 22.440 1.00 0.00 +ATOM 2727 HW2 SOL 831 19.820 36.320 22.650 1.00 0.00 +ATOM 2728 OW SOL 832 9.760 33.310 31.510 1.00 0.00 +ATOM 2729 HW1 SOL 832 8.830 33.520 31.420 1.00 0.00 +ATOM 2730 HW2 SOL 832 10.190 33.800 30.820 1.00 0.00 +ATOM 2731 OW SOL 833 41.890 37.710 15.690 1.00 0.00 +ATOM 2732 HW1 SOL 833 40.980 37.860 15.410 1.00 0.00 +ATOM 2733 HW2 SOL 833 41.810 37.180 16.490 1.00 0.00 +ATOM 2734 OW SOL 834 26.740 34.410 17.120 1.00 0.00 +ATOM 2735 HW1 SOL 834 26.870 34.210 16.190 1.00 0.00 +ATOM 2736 HW2 SOL 834 26.480 33.580 17.510 1.00 0.00 +ATOM 2737 OW SOL 835 26.800 19.120 6.560 1.00 0.00 +ATOM 2738 HW1 SOL 835 27.010 18.260 6.190 1.00 0.00 +ATOM 2739 HW2 SOL 835 26.190 18.930 7.270 1.00 0.00 +ATOM 2740 OW SOL 836 37.300 4.240 19.250 1.00 0.00 +ATOM 2741 HW1 SOL 836 37.590 4.540 20.120 1.00 0.00 +ATOM 2742 HW2 SOL 836 36.400 4.560 19.170 1.00 0.00 +ATOM 2743 OW SOL 837 15.080 37.060 2.560 1.00 0.00 +ATOM 2744 HW1 SOL 837 14.670 37.690 1.960 1.00 0.00 +ATOM 2745 HW2 SOL 837 14.360 36.760 3.110 1.00 0.00 +ATOM 2746 OW SOL 838 3.730 4.260 6.140 1.00 0.00 +ATOM 2747 HW1 SOL 838 4.340 4.220 5.410 1.00 0.00 +ATOM 2748 HW2 SOL 838 3.960 3.500 6.680 1.00 0.00 +ATOM 2749 OW SOL 839 25.470 25.370 22.590 1.00 0.00 +ATOM 2750 HW1 SOL 839 24.530 25.200 22.500 1.00 0.00 +ATOM 2751 HW2 SOL 839 25.540 25.970 23.330 1.00 0.00 +ATOM 2752 OW SOL 840 38.790 2.380 15.190 1.00 0.00 +ATOM 2753 HW1 SOL 840 39.610 2.810 15.430 1.00 0.00 +ATOM 2754 HW2 SOL 840 38.310 2.290 16.020 1.00 0.00 +ATOM 2755 OW SOL 841 7.690 6.440 23.040 1.00 0.00 +ATOM 2756 HW1 SOL 841 7.260 5.640 23.340 1.00 0.00 +ATOM 2757 HW2 SOL 841 8.270 6.680 23.760 1.00 0.00 +ATOM 2758 OW SOL 842 37.570 43.480 17.770 1.00 0.00 +ATOM 2759 HW1 SOL 842 38.110 44.260 17.680 1.00 0.00 +ATOM 2760 HW2 SOL 842 38.070 42.910 18.360 1.00 0.00 +ATOM 2761 OW SOL 843 17.010 24.010 11.220 1.00 0.00 +ATOM 2762 HW1 SOL 843 16.620 24.860 11.030 1.00 0.00 +ATOM 2763 HW2 SOL 843 17.420 23.740 10.400 1.00 0.00 +ATOM 2764 OW SOL 844 21.830 20.690 28.240 1.00 0.00 +ATOM 2765 HW1 SOL 844 22.700 21.030 28.030 1.00 0.00 +ATOM 2766 HW2 SOL 844 21.930 19.740 28.190 1.00 0.00 +ATOM 2767 OW SOL 845 22.670 16.640 3.070 1.00 0.00 +ATOM 2768 HW1 SOL 845 21.930 16.730 3.680 1.00 0.00 +ATOM 2769 HW2 SOL 845 22.910 17.550 2.860 1.00 0.00 +ATOM 2770 OW SOL 846 37.490 45.160 2.520 1.00 0.00 +ATOM 2771 HW1 SOL 846 38.300 45.610 2.760 1.00 0.00 +ATOM 2772 HW2 SOL 846 36.940 45.840 2.120 1.00 0.00 +ATOM 2773 OW SOL 847 32.900 21.350 9.260 1.00 0.00 +ATOM 2774 HW1 SOL 847 32.530 20.500 9.490 1.00 0.00 +ATOM 2775 HW2 SOL 847 32.140 21.890 9.030 1.00 0.00 +ATOM 2776 OW SOL 848 0.050 25.290 9.830 1.00 0.00 +ATOM 2777 HW1 SOL 848 -0.630 24.660 9.590 1.00 0.00 +ATOM 2778 HW2 SOL 848 -0.070 26.020 9.220 1.00 0.00 +ATOM 2779 OW SOL 849 2.630 18.580 8.370 1.00 0.00 +ATOM 2780 HW1 SOL 849 1.880 18.860 8.890 1.00 0.00 +ATOM 2781 HW2 SOL 849 3.110 19.380 8.170 1.00 0.00 +ATOM 2782 OW SOL 850 1.020 15.770 25.290 1.00 0.00 +ATOM 2783 HW1 SOL 850 0.470 15.900 26.060 1.00 0.00 +ATOM 2784 HW2 SOL 850 0.680 14.980 24.870 1.00 0.00 +ATOM 2785 OW SOL 851 7.730 21.840 20.540 1.00 0.00 +ATOM 2786 HW1 SOL 851 8.660 21.820 20.780 1.00 0.00 +ATOM 2787 HW2 SOL 851 7.290 22.150 21.330 1.00 0.00 +ATOM 2788 OW SOL 852 6.690 2.890 9.520 1.00 0.00 +ATOM 2789 HW1 SOL 852 6.160 3.530 10.000 1.00 0.00 +ATOM 2790 HW2 SOL 852 7.160 3.410 8.870 1.00 0.00 +ATOM 2791 OW SOL 853 27.520 5.730 23.780 1.00 0.00 +ATOM 2792 HW1 SOL 853 26.740 6.200 24.060 1.00 0.00 +ATOM 2793 HW2 SOL 853 27.200 4.890 23.470 1.00 0.00 +ATOM 2794 OW SOL 854 24.470 0.220 22.970 1.00 0.00 +ATOM 2795 HW1 SOL 854 24.310 -0.720 22.950 1.00 0.00 +ATOM 2796 HW2 SOL 854 23.890 0.550 23.650 1.00 0.00 +ATOM 2797 OW SOL 855 44.670 32.300 29.670 1.00 0.00 +ATOM 2798 HW1 SOL 855 44.990 32.360 30.570 1.00 0.00 +ATOM 2799 HW2 SOL 855 44.730 31.370 29.450 1.00 0.00 +ATOM 2800 OW SOL 856 43.770 10.380 4.360 1.00 0.00 +ATOM 2801 HW1 SOL 856 43.840 11.180 4.870 1.00 0.00 +ATOM 2802 HW2 SOL 856 44.070 10.620 3.490 1.00 0.00 +ATOM 2803 OW SOL 857 9.500 2.140 0.280 1.00 0.00 +ATOM 2804 HW1 SOL 857 10.330 1.680 0.170 1.00 0.00 +ATOM 2805 HW2 SOL 857 9.690 3.040 0.020 1.00 0.00 +ATOM 2806 OW SOL 858 -17.729 -6.179 -1.578 1.00 0.00 +ATOM 2807 HW1 SOL 858 -18.199 -6.459 -2.368 1.00 0.00 +ATOM 2808 HW2 SOL 858 -18.159 -5.359 -1.318 1.00 0.00 +ATOM 2809 OW SOL 859 2.820 28.680 9.710 1.00 0.00 +ATOM 2810 HW1 SOL 859 3.350 29.330 10.170 1.00 0.00 +ATOM 2811 HW2 SOL 859 2.200 28.360 10.370 1.00 0.00 +ATOM 2812 OW SOL 860 12.240 11.520 30.700 1.00 0.00 +ATOM 2813 HW1 SOL 860 12.990 11.650 30.120 1.00 0.00 +ATOM 2814 HW2 SOL 860 11.540 11.230 30.120 1.00 0.00 +ATOM 2815 OW SOL 861 32.310 45.210 16.560 1.00 0.00 +ATOM 2816 HW1 SOL 861 32.560 45.070 15.650 1.00 0.00 +ATOM 2817 HW2 SOL 861 31.850 44.410 16.810 1.00 0.00 +ATOM 2818 OW SOL 862 27.100 11.660 22.960 1.00 0.00 +ATOM 2819 HW1 SOL 862 27.790 11.000 22.860 1.00 0.00 +ATOM 2820 HW2 SOL 862 27.570 12.500 22.890 1.00 0.00 +ATOM 2821 OW SOL 863 27.760 5.040 2.190 1.00 0.00 +ATOM 2822 HW1 SOL 863 27.820 4.150 2.530 1.00 0.00 +ATOM 2823 HW2 SOL 863 27.030 5.430 2.670 1.00 0.00 +ATOM 2824 OW SOL 864 8.200 4.020 7.570 1.00 0.00 +ATOM 2825 HW1 SOL 864 8.550 4.350 6.740 1.00 0.00 +ATOM 2826 HW2 SOL 864 8.950 4.000 8.160 1.00 0.00 +ATOM 2827 OW SOL 865 31.470 29.030 11.320 1.00 0.00 +ATOM 2828 HW1 SOL 865 31.150 28.140 11.480 1.00 0.00 +ATOM 2829 HW2 SOL 865 32.410 28.930 11.170 1.00 0.00 +ATOM 2830 OW SOL 866 28.610 9.720 29.330 1.00 0.00 +ATOM 2831 HW1 SOL 866 27.910 10.060 28.770 1.00 0.00 +ATOM 2832 HW2 SOL 866 28.220 9.680 30.200 1.00 0.00 +ATOM 2833 OW SOL 867 29.340 28.050 22.070 1.00 0.00 +ATOM 2834 HW1 SOL 867 29.730 27.880 21.210 1.00 0.00 +ATOM 2835 HW2 SOL 867 29.050 27.180 22.370 1.00 0.00 +ATOM 2836 OW SOL 868 14.690 35.620 0.300 1.00 0.00 +ATOM 2837 HW1 SOL 868 14.500 36.430 -0.180 1.00 0.00 +ATOM 2838 HW2 SOL 868 14.960 35.920 1.170 1.00 0.00 +ATOM 2839 OW SOL 869 29.850 38.130 11.820 1.00 0.00 +ATOM 2840 HW1 SOL 869 29.010 37.670 11.770 1.00 0.00 +ATOM 2841 HW2 SOL 869 29.970 38.520 10.960 1.00 0.00 +ATOM 2842 OW SOL 870 41.490 3.680 11.150 1.00 0.00 +ATOM 2843 HW1 SOL 870 41.650 3.190 11.950 1.00 0.00 +ATOM 2844 HW2 SOL 870 41.730 3.080 10.450 1.00 0.00 +ATOM 2845 OW SOL 871 11.970 29.120 12.010 1.00 0.00 +ATOM 2846 HW1 SOL 871 11.510 29.040 11.170 1.00 0.00 +ATOM 2847 HW2 SOL 871 11.500 28.540 12.600 1.00 0.00 +ATOM 2848 OW SOL 872 1.640 18.410 12.890 1.00 0.00 +ATOM 2849 HW1 SOL 872 1.380 18.680 12.010 1.00 0.00 +ATOM 2850 HW2 SOL 872 0.960 18.760 13.470 1.00 0.00 +ATOM 2851 OW SOL 873 22.040 34.230 0.240 1.00 0.00 +ATOM 2852 HW1 SOL 873 22.290 35.150 0.270 1.00 0.00 +ATOM 2853 HW2 SOL 873 22.400 33.910 -0.590 1.00 0.00 +ATOM 2854 OW SOL 874 4.310 8.140 1.470 1.00 0.00 +ATOM 2855 HW1 SOL 874 3.540 7.580 1.530 1.00 0.00 +ATOM 2856 HW2 SOL 874 4.360 8.580 2.320 1.00 0.00 +ATOM 2857 OW SOL 875 44.930 7.010 22.530 1.00 0.00 +ATOM 2858 HW1 SOL 875 45.350 7.210 23.360 1.00 0.00 +ATOM 2859 HW2 SOL 875 45.520 6.400 22.100 1.00 0.00 +ATOM 2860 OW SOL 876 32.290 18.900 10.500 1.00 0.00 +ATOM 2861 HW1 SOL 876 33.140 18.700 10.100 1.00 0.00 +ATOM 2862 HW2 SOL 876 32.490 19.070 11.420 1.00 0.00 +ATOM 2863 OW SOL 877 38.100 8.540 10.420 1.00 0.00 +ATOM 2864 HW1 SOL 877 37.410 8.920 9.890 1.00 0.00 +ATOM 2865 HW2 SOL 877 38.450 7.820 9.890 1.00 0.00 +ATOM 2866 OW SOL 878 3.310 27.100 22.990 1.00 0.00 +ATOM 2867 HW1 SOL 878 3.770 27.890 22.690 1.00 0.00 +ATOM 2868 HW2 SOL 878 2.390 27.280 22.800 1.00 0.00 +ATOM 2869 OW SOL 879 8.510 7.840 20.360 1.00 0.00 +ATOM 2870 HW1 SOL 879 8.710 8.220 21.220 1.00 0.00 +ATOM 2871 HW2 SOL 879 8.310 6.920 20.540 1.00 0.00 +ATOM 2872 OW SOL 880 29.950 20.670 20.570 1.00 0.00 +ATOM 2873 HW1 SOL 880 29.340 21.300 20.950 1.00 0.00 +ATOM 2874 HW2 SOL 880 30.810 21.090 20.640 1.00 0.00 +ATOM 2875 OW SOL 881 27.980 27.120 12.920 1.00 0.00 +ATOM 2876 HW1 SOL 881 28.140 27.420 12.020 1.00 0.00 +ATOM 2877 HW2 SOL 881 28.450 27.760 13.460 1.00 0.00 +ATOM 2878 OW SOL 882 33.230 14.380 8.750 1.00 0.00 +ATOM 2879 HW1 SOL 882 34.060 14.830 8.910 1.00 0.00 +ATOM 2880 HW2 SOL 882 32.820 14.320 9.610 1.00 0.00 +ATOM 2881 OW SOL 883 2.350 8.590 5.260 1.00 0.00 +ATOM 2882 HW1 SOL 883 1.660 7.930 5.160 1.00 0.00 +ATOM 2883 HW2 SOL 883 1.890 9.420 5.330 1.00 0.00 +ATOM 2884 OW SOL 884 11.710 9.300 19.250 1.00 0.00 +ATOM 2885 HW1 SOL 884 11.560 8.400 19.550 1.00 0.00 +ATOM 2886 HW2 SOL 884 10.890 9.560 18.830 1.00 0.00 +ATOM 2887 OW SOL 885 42.890 26.950 11.520 1.00 0.00 +ATOM 2888 HW1 SOL 885 43.540 26.740 12.190 1.00 0.00 +ATOM 2889 HW2 SOL 885 42.760 27.890 11.590 1.00 0.00 +ATOM 2890 OW SOL 886 45.937 34.520 2.440 1.00 0.00 +ATOM 2891 HW1 SOL 886 46.557 34.820 3.110 1.00 0.00 +ATOM 2892 HW2 SOL 886 45.127 34.350 2.910 1.00 0.00 +ATOM 2893 OW SOL 887 7.110 37.680 4.780 1.00 0.00 +ATOM 2894 HW1 SOL 887 6.390 38.310 4.780 1.00 0.00 +ATOM 2895 HW2 SOL 887 7.850 38.150 4.410 1.00 0.00 +ATOM 2896 OW SOL 888 4.540 25.340 20.920 1.00 0.00 +ATOM 2897 HW1 SOL 888 4.720 25.830 20.120 1.00 0.00 +ATOM 2898 HW2 SOL 888 4.070 25.950 21.480 1.00 0.00 +ATOM 2899 OW SOL 889 23.240 31.420 12.640 1.00 0.00 +ATOM 2900 HW1 SOL 889 24.130 31.210 12.330 1.00 0.00 +ATOM 2901 HW2 SOL 889 22.690 31.280 11.870 1.00 0.00 +ATOM 2902 OW SOL 890 14.670 3.950 3.520 1.00 0.00 +ATOM 2903 HW1 SOL 890 14.690 4.220 4.440 1.00 0.00 +ATOM 2904 HW2 SOL 890 14.500 3.010 3.550 1.00 0.00 +ATOM 2905 OW SOL 891 43.220 9.900 22.210 1.00 0.00 +ATOM 2906 HW1 SOL 891 43.790 9.190 21.920 1.00 0.00 +ATOM 2907 HW2 SOL 891 43.490 10.650 21.670 1.00 0.00 +ATOM 2908 OW SOL 892 41.360 17.590 20.600 1.00 0.00 +ATOM 2909 HW1 SOL 892 40.980 18.470 20.700 1.00 0.00 +ATOM 2910 HW2 SOL 892 40.820 17.030 21.150 1.00 0.00 +ATOM 2911 OW SOL 893 11.790 34.950 17.730 1.00 0.00 +ATOM 2912 HW1 SOL 893 11.210 35.570 18.160 1.00 0.00 +ATOM 2913 HW2 SOL 893 12.670 35.200 18.030 1.00 0.00 +ATOM 2914 OW SOL 894 3.690 30.960 28.870 1.00 0.00 +ATOM 2915 HW1 SOL 894 4.390 31.170 29.490 1.00 0.00 +ATOM 2916 HW2 SOL 894 3.630 31.720 28.310 1.00 0.00 +ATOM 2917 OW SOL 895 33.290 45.320 11.730 1.00 0.00 +ATOM 2918 HW1 SOL 895 33.000 46.210 11.570 1.00 0.00 +ATOM 2919 HW2 SOL 895 32.900 44.810 11.010 1.00 0.00 +ATOM 2920 OW SOL 896 2.680 28.570 29.140 1.00 0.00 +ATOM 2921 HW1 SOL 896 3.120 29.380 28.890 1.00 0.00 +ATOM 2922 HW2 SOL 896 3.130 27.880 28.650 1.00 0.00 +ATOM 2923 OW SOL 897 3.730 41.700 31.020 1.00 0.00 +ATOM 2924 HW1 SOL 897 3.380 42.190 31.770 1.00 0.00 +ATOM 2925 HW2 SOL 897 4.670 41.850 31.050 1.00 0.00 +ATOM 2926 OW SOL 898 39.540 18.460 10.710 1.00 0.00 +ATOM 2927 HW1 SOL 898 39.490 18.110 11.600 1.00 0.00 +ATOM 2928 HW2 SOL 898 39.960 19.310 10.810 1.00 0.00 +ATOM 2929 OW SOL 899 21.130 33.140 19.190 1.00 0.00 +ATOM 2930 HW1 SOL 899 20.350 33.690 19.160 1.00 0.00 +ATOM 2931 HW2 SOL 899 21.740 33.560 18.580 1.00 0.00 +ATOM 2932 OW SOL 900 35.270 39.830 32.050 1.00 0.00 +ATOM 2933 HW1 SOL 900 34.980 40.230 31.240 1.00 0.00 +ATOM 2934 HW2 SOL 900 35.930 40.440 32.400 1.00 0.00 +ATOM 2935 OW SOL 901 41.570 24.680 12.390 1.00 0.00 +ATOM 2936 HW1 SOL 901 42.050 23.950 11.990 1.00 0.00 +ATOM 2937 HW2 SOL 901 42.090 25.450 12.170 1.00 0.00 +ATOM 2938 OW SOL 902 45.290 15.930 27.740 1.00 0.00 +ATOM 2939 HW1 SOL 902 44.890 15.130 28.090 1.00 0.00 +ATOM 2940 HW2 SOL 902 45.450 16.470 28.520 1.00 0.00 +ATOM 2941 OW SOL 903 47.237 2.900 30.810 1.00 0.00 +ATOM 2942 HW1 SOL 903 48.027 3.350 31.070 1.00 0.00 +ATOM 2943 HW2 SOL 903 46.567 3.190 31.430 1.00 0.00 +ATOM 2944 OW SOL 904 39.690 7.640 26.320 1.00 0.00 +ATOM 2945 HW1 SOL 904 39.130 6.980 25.900 1.00 0.00 +ATOM 2946 HW2 SOL 904 39.110 8.090 26.930 1.00 0.00 +ATOM 2947 OW SOL 905 30.650 0.520 5.510 1.00 0.00 +ATOM 2948 HW1 SOL 905 30.460 -0.260 4.990 1.00 0.00 +ATOM 2949 HW2 SOL 905 30.250 1.240 5.010 1.00 0.00 +ATOM 2950 OW SOL 906 18.730 8.350 0.950 1.00 0.00 +ATOM 2951 HW1 SOL 906 18.060 8.150 1.600 1.00 0.00 +ATOM 2952 HW2 SOL 906 19.330 7.610 0.990 1.00 0.00 +ATOM 2953 OW SOL 907 2.730 41.840 10.960 1.00 0.00 +ATOM 2954 HW1 SOL 907 3.230 42.650 10.860 1.00 0.00 +ATOM 2955 HW2 SOL 907 3.390 41.150 10.960 1.00 0.00 +ATOM 2956 OW SOL 908 15.980 22.680 4.310 1.00 0.00 +ATOM 2957 HW1 SOL 908 16.090 23.560 4.660 1.00 0.00 +ATOM 2958 HW2 SOL 908 15.980 22.790 3.360 1.00 0.00 +ATOM 2959 OW SOL 909 6.710 31.520 30.270 1.00 0.00 +ATOM 2960 HW1 SOL 909 6.670 32.340 30.770 1.00 0.00 +ATOM 2961 HW2 SOL 909 7.410 31.670 29.630 1.00 0.00 +ATOM 2962 OW SOL 910 28.470 19.650 1.400 1.00 0.00 +ATOM 2963 HW1 SOL 910 28.600 18.810 1.820 1.00 0.00 +ATOM 2964 HW2 SOL 910 28.550 19.470 0.460 1.00 0.00 +ATOM 2965 OW SOL 911 45.250 27.410 7.170 1.00 0.00 +ATOM 2966 HW1 SOL 911 45.210 28.040 6.450 1.00 0.00 +ATOM 2967 HW2 SOL 911 44.680 27.780 7.840 1.00 0.00 +ATOM 2968 OW SOL 912 4.110 22.450 12.880 1.00 0.00 +ATOM 2969 HW1 SOL 912 3.710 22.670 13.720 1.00 0.00 +ATOM 2970 HW2 SOL 912 3.540 21.780 12.510 1.00 0.00 +ATOM 2971 OW SOL 913 19.000 36.500 0.180 1.00 0.00 +ATOM 2972 HW1 SOL 913 18.370 35.830 0.460 1.00 0.00 +ATOM 2973 HW2 SOL 913 19.060 36.380 -0.770 1.00 0.00 +ATOM 2974 OW SOL 914 21.840 6.160 3.280 1.00 0.00 +ATOM 2975 HW1 SOL 914 22.560 5.900 2.690 1.00 0.00 +ATOM 2976 HW2 SOL 914 21.050 6.000 2.770 1.00 0.00 +ATOM 2977 OW SOL 915 7.370 41.400 15.510 1.00 0.00 +ATOM 2978 HW1 SOL 915 8.180 41.540 15.010 1.00 0.00 +ATOM 2979 HW2 SOL 915 6.770 41.000 14.880 1.00 0.00 +ATOM 2980 OW SOL 916 17.330 14.830 2.660 1.00 0.00 +ATOM 2981 HW1 SOL 916 16.460 15.190 2.500 1.00 0.00 +ATOM 2982 HW2 SOL 916 17.170 14.010 3.120 1.00 0.00 +ATOM 2983 OW SOL 917 0.890 21.920 23.350 1.00 0.00 +ATOM 2984 HW1 SOL 917 1.030 21.100 22.870 1.00 0.00 +ATOM 2985 HW2 SOL 917 1.570 22.510 23.030 1.00 0.00 +ATOM 2986 OW SOL 918 18.470 8.080 21.150 1.00 0.00 +ATOM 2987 HW1 SOL 918 18.590 8.650 21.910 1.00 0.00 +ATOM 2988 HW2 SOL 918 18.370 8.680 20.410 1.00 0.00 +ATOM 2989 OW SOL 919 31.300 28.460 6.530 1.00 0.00 +ATOM 2990 HW1 SOL 919 30.770 28.570 5.740 1.00 0.00 +ATOM 2991 HW2 SOL 919 30.920 27.700 6.970 1.00 0.00 +ATOM 2992 OW SOL 920 36.830 33.990 24.760 1.00 0.00 +ATOM 2993 HW1 SOL 920 37.110 33.400 25.460 1.00 0.00 +ATOM 2994 HW2 SOL 920 36.040 33.570 24.400 1.00 0.00 +ATOM 2995 OW SOL 921 31.100 41.030 1.260 1.00 0.00 +ATOM 2996 HW1 SOL 921 31.510 41.720 0.730 1.00 0.00 +ATOM 2997 HW2 SOL 921 31.830 40.510 1.590 1.00 0.00 +ATOM 2998 OW SOL 922 39.920 2.310 29.020 1.00 0.00 +ATOM 2999 HW1 SOL 922 40.320 1.490 28.730 1.00 0.00 +ATOM 3000 HW2 SOL 922 39.190 2.450 28.410 1.00 0.00 +ATOM 3001 OW SOL 923 38.160 21.580 17.560 1.00 0.00 +ATOM 3002 HW1 SOL 923 38.970 21.090 17.750 1.00 0.00 +ATOM 3003 HW2 SOL 923 37.790 21.130 16.800 1.00 0.00 +ATOM 3004 OW SOL 924 1.530 12.870 14.380 1.00 0.00 +ATOM 3005 HW1 SOL 924 2.280 12.280 14.270 1.00 0.00 +ATOM 3006 HW2 SOL 924 0.840 12.310 14.730 1.00 0.00 +ATOM 3007 OW SOL 925 32.100 23.560 12.660 1.00 0.00 +ATOM 3008 HW1 SOL 925 31.900 24.400 13.070 1.00 0.00 +ATOM 3009 HW2 SOL 925 33.040 23.580 12.490 1.00 0.00 +ATOM 3010 OW SOL 926 28.620 23.850 2.440 1.00 0.00 +ATOM 3011 HW1 SOL 926 29.330 24.320 1.990 1.00 0.00 +ATOM 3012 HW2 SOL 926 28.370 23.160 1.830 1.00 0.00 +ATOM 3013 OW SOL 927 27.280 41.880 21.790 1.00 0.00 +ATOM 3014 HW1 SOL 927 27.800 41.090 21.970 1.00 0.00 +ATOM 3015 HW2 SOL 927 27.110 41.840 20.850 1.00 0.00 +ATOM 3016 OW SOL 928 37.890 41.110 29.900 1.00 0.00 +ATOM 3017 HW1 SOL 928 36.990 40.820 29.750 1.00 0.00 +ATOM 3018 HW2 SOL 928 37.870 41.500 30.780 1.00 0.00 +ATOM 3019 OW SOL 929 35.540 43.410 22.070 1.00 0.00 +ATOM 3020 HW1 SOL 929 35.670 44.260 21.650 1.00 0.00 +ATOM 3021 HW2 SOL 929 35.690 42.770 21.370 1.00 0.00 +ATOM 3022 OW SOL 930 5.860 21.670 6.640 1.00 0.00 +ATOM 3023 HW1 SOL 930 5.680 22.600 6.500 1.00 0.00 +ATOM 3024 HW2 SOL 930 6.550 21.660 7.290 1.00 0.00 +ATOM 3025 OW SOL 931 31.730 13.560 6.730 1.00 0.00 +ATOM 3026 HW1 SOL 931 32.340 13.920 7.380 1.00 0.00 +ATOM 3027 HW2 SOL 931 31.470 12.720 7.100 1.00 0.00 +ATOM 3028 OW SOL 932 11.220 41.570 16.810 1.00 0.00 +ATOM 3029 HW1 SOL 932 11.080 41.590 17.760 1.00 0.00 +ATOM 3030 HW2 SOL 932 10.350 41.710 16.430 1.00 0.00 +ATOM 3031 OW SOL 933 16.710 26.690 14.880 1.00 0.00 +ATOM 3032 HW1 SOL 933 16.040 26.900 14.220 1.00 0.00 +ATOM 3033 HW2 SOL 933 16.270 26.110 15.490 1.00 0.00 +ATOM 3034 OW SOL 934 41.510 29.810 2.950 1.00 0.00 +ATOM 3035 HW1 SOL 934 41.440 29.180 3.670 1.00 0.00 +ATOM 3036 HW2 SOL 934 42.360 29.630 2.550 1.00 0.00 +ATOM 3037 OW SOL 935 21.890 27.800 22.110 1.00 0.00 +ATOM 3038 HW1 SOL 935 20.940 27.910 22.060 1.00 0.00 +ATOM 3039 HW2 SOL 935 22.020 26.880 22.300 1.00 0.00 +ATOM 3040 OW SOL 936 29.440 13.000 27.810 1.00 0.00 +ATOM 3041 HW1 SOL 936 28.490 12.910 27.790 1.00 0.00 +ATOM 3042 HW2 SOL 936 29.760 12.200 27.400 1.00 0.00 +ATOM 3043 OW SOL 937 0.680 44.540 0.420 1.00 0.00 +ATOM 3044 HW1 SOL 937 1.130 43.790 0.040 1.00 0.00 +ATOM 3045 HW2 SOL 937 1.050 45.300 -0.030 1.00 0.00 +ATOM 3046 OW SOL 938 -15.659 34.309 -2.568 1.00 0.00 +ATOM 3047 HW1 SOL 938 -15.699 34.769 -1.728 1.00 0.00 +ATOM 3048 HW2 SOL 938 -16.189 34.849 -3.168 1.00 0.00 +ATOM 3049 OW SOL 939 9.240 6.990 25.330 1.00 0.00 +ATOM 3050 HW1 SOL 939 8.880 6.460 26.040 1.00 0.00 +ATOM 3051 HW2 SOL 939 10.100 6.600 25.170 1.00 0.00 +ATOM 3052 OW SOL 940 6.470 24.910 8.900 1.00 0.00 +ATOM 3053 HW1 SOL 940 6.450 25.260 9.790 1.00 0.00 +ATOM 3054 HW2 SOL 940 5.960 25.540 8.390 1.00 0.00 +ATOM 3055 OW SOL 941 5.950 0.010 2.160 1.00 0.00 +ATOM 3056 HW1 SOL 941 5.980 0.900 1.810 1.00 0.00 +ATOM 3057 HW2 SOL 941 6.420 0.060 2.990 1.00 0.00 +ATOM 3058 OW SOL 942 43.480 27.910 28.540 1.00 0.00 +ATOM 3059 HW1 SOL 942 43.690 26.980 28.620 1.00 0.00 +ATOM 3060 HW2 SOL 942 44.280 28.360 28.810 1.00 0.00 +ATOM 3061 OW SOL 943 39.950 31.640 22.890 1.00 0.00 +ATOM 3062 HW1 SOL 943 39.130 31.340 22.500 1.00 0.00 +ATOM 3063 HW2 SOL 943 40.390 32.110 22.190 1.00 0.00 +ATOM 3064 OW SOL 944 17.470 12.140 15.120 1.00 0.00 +ATOM 3065 HW1 SOL 944 17.330 12.840 14.480 1.00 0.00 +ATOM 3066 HW2 SOL 944 18.390 12.230 15.370 1.00 0.00 +ATOM 3067 OW SOL 945 44.560 5.960 25.190 1.00 0.00 +ATOM 3068 HW1 SOL 945 45.180 6.350 25.810 1.00 0.00 +ATOM 3069 HW2 SOL 945 43.920 6.650 25.020 1.00 0.00 +ATOM 3070 OW SOL 946 3.510 10.130 7.760 1.00 0.00 +ATOM 3071 HW1 SOL 946 3.850 10.880 8.260 1.00 0.00 +ATOM 3072 HW2 SOL 946 2.630 10.410 7.510 1.00 0.00 +ATOM 3073 OW SOL 947 9.780 4.360 20.890 1.00 0.00 +ATOM 3074 HW1 SOL 947 9.580 3.470 21.180 1.00 0.00 +ATOM 3075 HW2 SOL 947 8.940 4.710 20.590 1.00 0.00 +ATOM 3076 OW SOL 948 21.710 37.670 28.960 1.00 0.00 +ATOM 3077 HW1 SOL 948 22.190 37.270 28.240 1.00 0.00 +ATOM 3078 HW2 SOL 948 21.440 36.930 29.500 1.00 0.00 +ATOM 3079 OW SOL 949 7.830 24.960 24.750 1.00 0.00 +ATOM 3080 HW1 SOL 949 7.100 24.480 24.360 1.00 0.00 +ATOM 3081 HW2 SOL 949 7.540 25.880 24.760 1.00 0.00 +ATOM 3082 OW SOL 950 41.390 40.010 26.330 1.00 0.00 +ATOM 3083 HW1 SOL 950 41.220 40.930 26.150 1.00 0.00 +ATOM 3084 HW2 SOL 950 42.110 39.780 25.740 1.00 0.00 +ATOM 3085 OW SOL 951 30.240 39.010 9.290 1.00 0.00 +ATOM 3086 HW1 SOL 951 30.140 39.950 9.160 1.00 0.00 +ATOM 3087 HW2 SOL 951 29.940 38.620 8.470 1.00 0.00 +ATOM 3088 OW SOL 952 9.010 33.470 11.040 1.00 0.00 +ATOM 3089 HW1 SOL 952 8.190 33.160 11.430 1.00 0.00 +ATOM 3090 HW2 SOL 952 9.300 34.170 11.610 1.00 0.00 +ATOM 3091 OW SOL 953 19.280 41.100 20.160 1.00 0.00 +ATOM 3092 HW1 SOL 953 19.620 41.680 20.840 1.00 0.00 +ATOM 3093 HW2 SOL 953 20.030 40.600 19.860 1.00 0.00 +ATOM 3094 OW SOL 954 41.330 7.680 3.430 1.00 0.00 +ATOM 3095 HW1 SOL 954 41.500 8.500 2.950 1.00 0.00 +ATOM 3096 HW2 SOL 954 41.130 7.960 4.320 1.00 0.00 +ATOM 3097 OW SOL 955 32.140 23.820 22.720 1.00 0.00 +ATOM 3098 HW1 SOL 955 31.830 24.560 23.230 1.00 0.00 +ATOM 3099 HW2 SOL 955 33.090 23.940 22.670 1.00 0.00 +ATOM 3100 OW SOL 956 44.150 18.530 21.660 1.00 0.00 +ATOM 3101 HW1 SOL 956 44.090 19.340 21.160 1.00 0.00 +ATOM 3102 HW2 SOL 956 43.300 18.120 21.550 1.00 0.00 +ATOM 3103 OW SOL 957 29.460 29.210 13.650 1.00 0.00 +ATOM 3104 HW1 SOL 957 29.380 30.140 13.450 1.00 0.00 +ATOM 3105 HW2 SOL 957 30.400 29.090 13.820 1.00 0.00 +ATOM 3106 OW SOL 958 32.080 11.200 24.470 1.00 0.00 +ATOM 3107 HW1 SOL 958 31.830 10.710 23.690 1.00 0.00 +ATOM 3108 HW2 SOL 958 31.470 10.900 25.140 1.00 0.00 +ATOM 3109 OW SOL 959 33.950 41.040 9.340 1.00 0.00 +ATOM 3110 HW1 SOL 959 34.780 41.520 9.310 1.00 0.00 +ATOM 3111 HW2 SOL 959 34.120 40.220 8.880 1.00 0.00 +ATOM 3112 OW SOL 960 4.680 7.650 10.760 1.00 0.00 +ATOM 3113 HW1 SOL 960 4.430 6.850 10.310 1.00 0.00 +ATOM 3114 HW2 SOL 960 4.340 7.550 11.650 1.00 0.00 +ATOM 3115 OW SOL 961 20.210 25.810 4.180 1.00 0.00 +ATOM 3116 HW1 SOL 961 20.640 26.250 3.440 1.00 0.00 +ATOM 3117 HW2 SOL 961 19.340 26.190 4.210 1.00 0.00 +ATOM 3118 OW SOL 962 31.730 33.330 5.890 1.00 0.00 +ATOM 3119 HW1 SOL 962 31.350 32.870 5.150 1.00 0.00 +ATOM 3120 HW2 SOL 962 31.610 32.740 6.630 1.00 0.00 +ATOM 3121 OW SOL 963 33.970 29.450 10.630 1.00 0.00 +ATOM 3122 HW1 SOL 963 34.140 30.070 9.930 1.00 0.00 +ATOM 3123 HW2 SOL 963 34.200 29.920 11.430 1.00 0.00 +ATOM 3124 OW SOL 964 15.880 10.220 17.600 1.00 0.00 +ATOM 3125 HW1 SOL 964 15.550 10.510 16.760 1.00 0.00 +ATOM 3126 HW2 SOL 964 15.690 10.940 18.200 1.00 0.00 +ATOM 3127 OW SOL 965 21.960 14.720 31.920 1.00 0.00 +ATOM 3128 HW1 SOL 965 21.170 14.390 32.350 1.00 0.00 +ATOM 3129 HW2 SOL 965 21.840 14.510 30.990 1.00 0.00 +ATOM 3130 OW SOL 966 14.440 4.730 10.130 1.00 0.00 +ATOM 3131 HW1 SOL 966 15.120 5.360 10.370 1.00 0.00 +ATOM 3132 HW2 SOL 966 14.090 5.060 9.310 1.00 0.00 +ATOM 3133 OW SOL 967 43.790 12.970 11.050 1.00 0.00 +ATOM 3134 HW1 SOL 967 43.030 13.080 10.480 1.00 0.00 +ATOM 3135 HW2 SOL 967 43.510 12.350 11.720 1.00 0.00 +ATOM 3136 OW SOL 968 21.210 21.700 2.930 1.00 0.00 +ATOM 3137 HW1 SOL 968 20.750 22.510 2.720 1.00 0.00 +ATOM 3138 HW2 SOL 968 22.080 21.970 3.200 1.00 0.00 +ATOM 3139 OW SOL 969 40.240 25.580 23.330 1.00 0.00 +ATOM 3140 HW1 SOL 969 39.680 25.850 22.600 1.00 0.00 +ATOM 3141 HW2 SOL 969 40.670 24.780 23.030 1.00 0.00 +ATOM 3142 OW SOL 970 9.790 10.560 29.660 1.00 0.00 +ATOM 3143 HW1 SOL 970 10.000 10.040 28.880 1.00 0.00 +ATOM 3144 HW2 SOL 970 8.900 10.880 29.510 1.00 0.00 +ATOM 3145 OW SOL 971 25.370 6.400 7.050 1.00 0.00 +ATOM 3146 HW1 SOL 971 25.730 6.740 6.230 1.00 0.00 +ATOM 3147 HW2 SOL 971 24.850 5.640 6.790 1.00 0.00 +ATOM 3148 OW SOL 972 33.860 29.680 2.660 1.00 0.00 +ATOM 3149 HW1 SOL 972 34.400 29.460 3.420 1.00 0.00 +ATOM 3150 HW2 SOL 972 33.820 28.870 2.140 1.00 0.00 +ATOM 3151 OW SOL 973 7.190 21.770 25.940 1.00 0.00 +ATOM 3152 HW1 SOL 973 6.600 21.030 26.030 1.00 0.00 +ATOM 3153 HW2 SOL 973 6.780 22.330 25.290 1.00 0.00 +ATOM 3154 OW SOL 974 20.120 13.450 5.030 1.00 0.00 +ATOM 3155 HW1 SOL 974 19.600 14.210 4.750 1.00 0.00 +ATOM 3156 HW2 SOL 974 20.770 13.810 5.640 1.00 0.00 +ATOM 3157 OW SOL 975 41.160 19.810 2.930 1.00 0.00 +ATOM 3158 HW1 SOL 975 40.620 19.550 3.680 1.00 0.00 +ATOM 3159 HW2 SOL 975 42.040 19.520 3.160 1.00 0.00 +ATOM 3160 OW SOL 976 35.630 12.850 18.220 1.00 0.00 +ATOM 3161 HW1 SOL 976 35.530 12.860 19.170 1.00 0.00 +ATOM 3162 HW2 SOL 976 36.400 12.300 18.060 1.00 0.00 +ATOM 3163 OW SOL 977 39.150 15.050 10.100 1.00 0.00 +ATOM 3164 HW1 SOL 977 38.560 14.910 9.370 1.00 0.00 +ATOM 3165 HW2 SOL 977 39.340 15.990 10.070 1.00 0.00 +ATOM 3166 OW SOL 978 36.250 19.550 28.260 1.00 0.00 +ATOM 3167 HW1 SOL 978 36.140 19.740 27.330 1.00 0.00 +ATOM 3168 HW2 SOL 978 37.160 19.270 28.350 1.00 0.00 +ATOM 3169 OW SOL 979 30.630 8.530 6.700 1.00 0.00 +ATOM 3170 HW1 SOL 979 30.410 7.620 6.890 1.00 0.00 +ATOM 3171 HW2 SOL 979 31.230 8.480 5.960 1.00 0.00 +ATOM 3172 OW SOL 980 2.020 8.460 9.490 1.00 0.00 +ATOM 3173 HW1 SOL 980 2.480 8.930 10.190 1.00 0.00 +ATOM 3174 HW2 SOL 980 2.640 8.440 8.760 1.00 0.00 +ATOM 3175 OW SOL 981 11.730 28.450 9.230 1.00 0.00 +ATOM 3176 HW1 SOL 981 10.950 27.990 8.930 1.00 0.00 +ATOM 3177 HW2 SOL 981 12.410 27.780 9.270 1.00 0.00 +ATOM 3178 OW SOL 982 0.790 27.700 22.280 1.00 0.00 +ATOM 3179 HW1 SOL 982 0.070 27.940 22.860 1.00 0.00 +ATOM 3180 HW2 SOL 982 0.760 28.370 21.590 1.00 0.00 +ATOM 3181 OW SOL 983 3.580 21.380 8.380 1.00 0.00 +ATOM 3182 HW1 SOL 983 4.120 21.900 7.780 1.00 0.00 +ATOM 3183 HW2 SOL 983 3.070 22.020 8.870 1.00 0.00 +ATOM 3184 OW SOL 984 -0.927 16.610 19.180 1.00 0.00 +ATOM 3185 HW1 SOL 984 -1.807 16.390 18.870 1.00 0.00 +ATOM 3186 HW2 SOL 984 -0.717 17.430 18.730 1.00 0.00 +ATOM 3187 OW SOL 985 25.990 25.080 28.680 1.00 0.00 +ATOM 3188 HW1 SOL 985 25.070 24.880 28.540 1.00 0.00 +ATOM 3189 HW2 SOL 985 26.420 24.850 27.850 1.00 0.00 +ATOM 3190 OW SOL 986 42.310 8.990 28.140 1.00 0.00 +ATOM 3191 HW1 SOL 986 41.610 9.640 28.020 1.00 0.00 +ATOM 3192 HW2 SOL 986 42.980 9.230 27.500 1.00 0.00 +ATOM 3193 OW SOL 987 24.610 34.800 3.630 1.00 0.00 +ATOM 3194 HW1 SOL 987 24.740 34.130 2.950 1.00 0.00 +ATOM 3195 HW2 SOL 987 25.470 35.210 3.730 1.00 0.00 +ATOM 3196 OW SOL 988 39.190 40.240 7.560 1.00 0.00 +ATOM 3197 HW1 SOL 988 39.890 39.590 7.610 1.00 0.00 +ATOM 3198 HW2 SOL 988 39.580 40.960 7.060 1.00 0.00 +ATOM 3199 OW SOL 989 13.200 38.020 22.630 1.00 0.00 +ATOM 3200 HW1 SOL 989 13.460 38.110 23.540 1.00 0.00 +ATOM 3201 HW2 SOL 989 13.980 38.270 22.130 1.00 0.00 +ATOM 3202 OW SOL 990 40.620 28.120 14.800 1.00 0.00 +ATOM 3203 HW1 SOL 990 39.680 28.040 14.650 1.00 0.00 +ATOM 3204 HW2 SOL 990 40.760 29.040 15.020 1.00 0.00 +ATOM 3205 OW SOL 991 0.840 24.250 0.400 1.00 0.00 +ATOM 3206 HW1 SOL 991 -0.030 24.270 0.810 1.00 0.00 +ATOM 3207 HW2 SOL 991 0.660 24.170 -0.540 1.00 0.00 +ATOM 3208 OW SOL 992 40.910 41.580 14.360 1.00 0.00 +ATOM 3209 HW1 SOL 992 41.430 42.150 13.800 1.00 0.00 +ATOM 3210 HW2 SOL 992 40.060 42.030 14.430 1.00 0.00 +ATOM 3211 OW SOL 993 31.940 43.240 24.510 1.00 0.00 +ATOM 3212 HW1 SOL 993 32.210 42.320 24.600 1.00 0.00 +ATOM 3213 HW2 SOL 993 32.150 43.640 25.350 1.00 0.00 +ATOM 3214 OW SOL 994 19.260 14.590 27.970 1.00 0.00 +ATOM 3215 HW1 SOL 994 19.930 14.430 28.640 1.00 0.00 +ATOM 3216 HW2 SOL 994 19.710 14.420 27.140 1.00 0.00 +ATOM 3217 OW SOL 995 10.030 21.540 9.350 1.00 0.00 +ATOM 3218 HW1 SOL 995 10.580 21.770 10.100 1.00 0.00 +ATOM 3219 HW2 SOL 995 10.610 21.010 8.790 1.00 0.00 +ATOM 3220 OW SOL 996 29.430 35.800 25.660 1.00 0.00 +ATOM 3221 HW1 SOL 996 30.330 36.110 25.530 1.00 0.00 +ATOM 3222 HW2 SOL 996 29.500 35.130 26.330 1.00 0.00 +ATOM 3223 OW SOL 997 39.660 5.020 18.450 1.00 0.00 +ATOM 3224 HW1 SOL 997 39.740 5.970 18.440 1.00 0.00 +ATOM 3225 HW2 SOL 997 38.720 4.860 18.600 1.00 0.00 +ATOM 3226 OW SOL 998 38.990 11.510 14.570 1.00 0.00 +ATOM 3227 HW1 SOL 998 39.770 12.070 14.540 1.00 0.00 +ATOM 3228 HW2 SOL 998 39.200 10.780 13.980 1.00 0.00 +ATOM 3229 OW SOL 999 42.760 27.750 21.820 1.00 0.00 +ATOM 3230 HW1 SOL 999 42.170 27.670 22.570 1.00 0.00 +ATOM 3231 HW2 SOL 999 42.290 28.300 21.200 1.00 0.00 +ATOM 3232 OW SOL 1000 39.580 35.070 9.880 1.00 0.00 +ATOM 3233 HW1 SOL 1000 40.190 34.810 9.190 1.00 0.00 +ATOM 3234 HW2 SOL 1000 39.470 36.010 9.770 1.00 0.00 +ATOM 3235 OW SOL 1001 5.480 38.770 18.880 1.00 0.00 +ATOM 3236 HW1 SOL 1001 5.710 39.610 18.470 1.00 0.00 +ATOM 3237 HW2 SOL 1001 5.190 39.010 19.760 1.00 0.00 +ATOM 3238 OW SOL 1002 0.320 17.520 30.310 1.00 0.00 +ATOM 3239 HW1 SOL 1002 0.850 16.820 30.710 1.00 0.00 +ATOM 3240 HW2 SOL 1002 -0.410 17.620 30.910 1.00 0.00 +ATOM 3241 OW SOL 1003 2.470 26.920 5.520 1.00 0.00 +ATOM 3242 HW1 SOL 1003 3.420 26.910 5.400 1.00 0.00 +ATOM 3243 HW2 SOL 1003 2.320 27.500 6.260 1.00 0.00 +ATOM 3244 OW SOL 1004 31.610 37.200 15.080 1.00 0.00 +ATOM 3245 HW1 SOL 1004 30.830 37.380 15.610 1.00 0.00 +ATOM 3246 HW2 SOL 1004 31.310 36.560 14.430 1.00 0.00 +ATOM 3247 OW SOL 1005 18.920 27.670 13.180 1.00 0.00 +ATOM 3248 HW1 SOL 1005 18.420 27.340 13.930 1.00 0.00 +ATOM 3249 HW2 SOL 1005 19.390 28.420 13.530 1.00 0.00 +ATOM 3250 OW SOL 1006 34.720 29.220 31.330 1.00 0.00 +ATOM 3251 HW1 SOL 1006 34.120 28.520 31.600 1.00 0.00 +ATOM 3252 HW2 SOL 1006 35.510 29.080 31.860 1.00 0.00 +ATOM 3253 OW SOL 1007 11.940 17.720 26.310 1.00 0.00 +ATOM 3254 HW1 SOL 1007 12.110 16.780 26.190 1.00 0.00 +ATOM 3255 HW2 SOL 1007 12.640 18.150 25.830 1.00 0.00 +ATOM 3256 OW SOL 1008 2.790 17.950 19.930 1.00 0.00 +ATOM 3257 HW1 SOL 1008 2.630 18.590 19.230 1.00 0.00 +ATOM 3258 HW2 SOL 1008 3.180 17.200 19.470 1.00 0.00 +ATOM 3259 OW SOL 1009 25.080 2.980 26.930 1.00 0.00 +ATOM 3260 HW1 SOL 1009 24.300 2.490 27.220 1.00 0.00 +ATOM 3261 HW2 SOL 1009 24.810 3.390 26.110 1.00 0.00 +ATOM 3262 OW SOL 1010 33.780 8.710 25.420 1.00 0.00 +ATOM 3263 HW1 SOL 1010 33.210 9.410 25.120 1.00 0.00 +ATOM 3264 HW2 SOL 1010 34.070 8.270 24.620 1.00 0.00 +ATOM 3265 OW SOL 1011 7.750 30.930 27.670 1.00 0.00 +ATOM 3266 HW1 SOL 1011 8.690 31.040 27.570 1.00 0.00 +ATOM 3267 HW2 SOL 1011 7.490 30.400 26.920 1.00 0.00 +ATOM 3268 OW SOL 1012 22.250 25.060 11.100 1.00 0.00 +ATOM 3269 HW1 SOL 1012 22.990 24.800 11.640 1.00 0.00 +ATOM 3270 HW2 SOL 1012 21.720 24.270 11.010 1.00 0.00 +ATOM 3271 OW SOL 1013 14.230 36.090 17.380 1.00 0.00 +ATOM 3272 HW1 SOL 1013 14.550 36.910 17.750 1.00 0.00 +ATOM 3273 HW2 SOL 1013 14.010 36.310 16.470 1.00 0.00 +ATOM 3274 OW SOL 1014 43.620 13.110 23.600 1.00 0.00 +ATOM 3275 HW1 SOL 1014 44.070 12.950 22.770 1.00 0.00 +ATOM 3276 HW2 SOL 1014 43.150 13.930 23.460 1.00 0.00 +ATOM 3277 OW SOL 1015 34.660 25.150 15.730 1.00 0.00 +ATOM 3278 HW1 SOL 1015 33.960 25.790 15.890 1.00 0.00 +ATOM 3279 HW2 SOL 1015 35.470 25.660 15.810 1.00 0.00 +ATOM 3280 OW SOL 1016 40.370 0.710 17.840 1.00 0.00 +ATOM 3281 HW1 SOL 1016 40.720 -0.030 18.330 1.00 0.00 +ATOM 3282 HW2 SOL 1016 40.540 1.470 18.380 1.00 0.00 +ATOM 3283 OW SOL 1017 30.870 22.580 26.320 1.00 0.00 +ATOM 3284 HW1 SOL 1017 30.330 22.310 27.060 1.00 0.00 +ATOM 3285 HW2 SOL 1017 31.760 22.610 26.660 1.00 0.00 +ATOM 3286 OW SOL 1018 15.590 28.260 28.850 1.00 0.00 +ATOM 3287 HW1 SOL 1018 16.230 28.510 29.520 1.00 0.00 +ATOM 3288 HW2 SOL 1018 15.450 27.330 28.990 1.00 0.00 +ATOM 3289 OW SOL 1019 33.960 30.060 25.920 1.00 0.00 +ATOM 3290 HW1 SOL 1019 33.150 30.550 26.020 1.00 0.00 +ATOM 3291 HW2 SOL 1019 34.430 30.490 25.210 1.00 0.00 +ATOM 3292 OW SOL 1020 33.380 1.470 5.360 1.00 0.00 +ATOM 3293 HW1 SOL 1020 33.240 0.750 5.970 1.00 0.00 +ATOM 3294 HW2 SOL 1020 32.540 1.580 4.920 1.00 0.00 +ATOM 3295 OW SOL 1021 21.370 21.900 6.740 1.00 0.00 +ATOM 3296 HW1 SOL 1021 20.560 22.030 6.240 1.00 0.00 +ATOM 3297 HW2 SOL 1021 21.430 20.950 6.860 1.00 0.00 +ATOM 3298 OW SOL 1022 20.590 32.320 24.010 1.00 0.00 +ATOM 3299 HW1 SOL 1022 20.170 31.620 23.510 1.00 0.00 +ATOM 3300 HW2 SOL 1022 21.350 32.570 23.480 1.00 0.00 +ATOM 3301 OW SOL 1023 44.680 27.800 17.770 1.00 0.00 +ATOM 3302 HW1 SOL 1023 44.160 28.560 18.050 1.00 0.00 +ATOM 3303 HW2 SOL 1023 45.310 28.160 17.150 1.00 0.00 +ATOM 3304 OW SOL 1024 38.110 15.200 14.950 1.00 0.00 +ATOM 3305 HW1 SOL 1024 38.300 15.940 15.540 1.00 0.00 +ATOM 3306 HW2 SOL 1024 38.940 14.720 14.900 1.00 0.00 +ATOM 3307 OW SOL 1025 33.770 18.020 29.020 1.00 0.00 +ATOM 3308 HW1 SOL 1025 34.620 18.420 28.870 1.00 0.00 +ATOM 3309 HW2 SOL 1025 33.420 17.860 28.150 1.00 0.00 +ATOM 3310 OW SOL 1026 13.430 26.530 1.940 1.00 0.00 +ATOM 3311 HW1 SOL 1026 13.540 26.480 2.890 1.00 0.00 +ATOM 3312 HW2 SOL 1026 12.570 26.140 1.780 1.00 0.00 +ATOM 3313 OW SOL 1027 38.040 42.310 15.230 1.00 0.00 +ATOM 3314 HW1 SOL 1027 37.710 41.430 15.410 1.00 0.00 +ATOM 3315 HW2 SOL 1027 38.010 42.760 16.070 1.00 0.00 +ATOM 3316 OW SOL 1028 28.370 9.350 15.700 1.00 0.00 +ATOM 3317 HW1 SOL 1028 28.040 8.540 15.310 1.00 0.00 +ATOM 3318 HW2 SOL 1028 28.830 9.790 14.980 1.00 0.00 +ATOM 3319 OW SOL 1029 14.320 6.610 24.490 1.00 0.00 +ATOM 3320 HW1 SOL 1029 13.790 5.830 24.610 1.00 0.00 +ATOM 3321 HW2 SOL 1029 13.840 7.130 23.840 1.00 0.00 +ATOM 3322 OW SOL 1030 33.360 14.300 4.310 1.00 0.00 +ATOM 3323 HW1 SOL 1030 32.990 14.120 5.180 1.00 0.00 +ATOM 3324 HW2 SOL 1030 33.330 15.250 4.230 1.00 0.00 +ATOM 3325 OW SOL 1031 43.890 43.320 26.180 1.00 0.00 +ATOM 3326 HW1 SOL 1031 44.570 42.680 26.410 1.00 0.00 +ATOM 3327 HW2 SOL 1031 44.350 44.160 26.170 1.00 0.00 +ATOM 3328 OW SOL 1032 18.910 37.670 31.930 1.00 0.00 +ATOM 3329 HW1 SOL 1032 18.250 37.290 32.500 1.00 0.00 +ATOM 3330 HW2 SOL 1032 18.580 38.550 31.720 1.00 0.00 +ATOM 3331 OW SOL 1033 5.760 0.480 30.100 1.00 0.00 +ATOM 3332 HW1 SOL 1033 5.190 0.090 29.440 1.00 0.00 +ATOM 3333 HW2 SOL 1033 6.370 -0.220 30.330 1.00 0.00 +ATOM 3334 OW SOL 1034 29.790 5.560 7.760 1.00 0.00 +ATOM 3335 HW1 SOL 1034 30.100 4.690 8.010 1.00 0.00 +ATOM 3336 HW2 SOL 1034 29.030 5.710 8.320 1.00 0.00 +ATOM 3337 OW SOL 1035 34.620 16.850 13.280 1.00 0.00 +ATOM 3338 HW1 SOL 1035 34.150 17.070 14.080 1.00 0.00 +ATOM 3339 HW2 SOL 1035 34.940 17.690 12.950 1.00 0.00 +ATOM 3340 OW SOL 1036 40.660 4.640 21.410 1.00 0.00 +ATOM 3341 HW1 SOL 1036 40.290 5.410 21.840 1.00 0.00 +ATOM 3342 HW2 SOL 1036 41.470 4.460 21.890 1.00 0.00 +ATOM 3343 OW SOL 1037 45.837 30.760 2.750 1.00 0.00 +ATOM 3344 HW1 SOL 1037 45.547 30.550 1.860 1.00 0.00 +ATOM 3345 HW2 SOL 1037 46.257 29.960 3.070 1.00 0.00 +ATOM 3346 OW SOL 1038 6.700 36.110 11.900 1.00 0.00 +ATOM 3347 HW1 SOL 1038 6.470 36.430 12.780 1.00 0.00 +ATOM 3348 HW2 SOL 1038 7.380 35.450 12.060 1.00 0.00 +ATOM 3349 OW SOL 1039 7.170 42.280 1.090 1.00 0.00 +ATOM 3350 HW1 SOL 1039 6.370 41.790 0.910 1.00 0.00 +ATOM 3351 HW2 SOL 1039 6.870 43.170 1.260 1.00 0.00 +ATOM 3352 OW SOL 1040 45.010 13.920 17.800 1.00 0.00 +ATOM 3353 HW1 SOL 1040 45.840 13.680 18.200 1.00 0.00 +ATOM 3354 HW2 SOL 1040 44.590 14.500 18.440 1.00 0.00 +ATOM 3355 OW SOL 1041 29.290 33.850 27.510 1.00 0.00 +ATOM 3356 HW1 SOL 1041 28.880 33.980 28.360 1.00 0.00 +ATOM 3357 HW2 SOL 1041 29.020 32.970 27.240 1.00 0.00 +ATOM 3358 OW SOL 1042 35.640 23.040 24.380 1.00 0.00 +ATOM 3359 HW1 SOL 1042 35.520 22.120 24.150 1.00 0.00 +ATOM 3360 HW2 SOL 1042 36.430 23.050 24.930 1.00 0.00 +ATOM 3361 OW SOL 1043 19.400 39.350 27.920 1.00 0.00 +ATOM 3362 HW1 SOL 1043 19.920 40.080 27.580 1.00 0.00 +ATOM 3363 HW2 SOL 1043 20.020 38.800 28.390 1.00 0.00 +ATOM 3364 OW SOL 1044 5.000 33.480 3.660 1.00 0.00 +ATOM 3365 HW1 SOL 1044 5.570 33.320 4.400 1.00 0.00 +ATOM 3366 HW2 SOL 1044 4.730 32.610 3.360 1.00 0.00 +ATOM 3367 OW SOL 1045 5.590 0.650 17.020 1.00 0.00 +ATOM 3368 HW1 SOL 1045 6.440 0.710 17.450 1.00 0.00 +ATOM 3369 HW2 SOL 1045 5.420 -0.290 16.940 1.00 0.00 +ATOM 3370 OW SOL 1046 16.070 15.040 17.030 1.00 0.00 +ATOM 3371 HW1 SOL 1046 15.730 14.230 17.400 1.00 0.00 +ATOM 3372 HW2 SOL 1046 16.150 14.860 16.090 1.00 0.00 +ATOM 3373 OW SOL 1047 14.130 8.410 5.690 1.00 0.00 +ATOM 3374 HW1 SOL 1047 13.450 7.920 5.230 1.00 0.00 +ATOM 3375 HW2 SOL 1047 14.210 9.230 5.200 1.00 0.00 +ATOM 3376 OW SOL 1048 8.120 19.160 23.860 1.00 0.00 +ATOM 3377 HW1 SOL 1048 7.750 19.890 23.370 1.00 0.00 +ATOM 3378 HW2 SOL 1048 8.220 19.500 24.750 1.00 0.00 +ATOM 3379 OW SOL 1049 31.230 41.220 30.890 1.00 0.00 +ATOM 3380 HW1 SOL 1049 30.590 41.140 30.190 1.00 0.00 +ATOM 3381 HW2 SOL 1049 30.710 41.280 31.690 1.00 0.00 +ATOM 3382 OW SOL 1050 19.990 9.780 22.820 1.00 0.00 +ATOM 3383 HW1 SOL 1050 19.700 10.390 23.500 1.00 0.00 +ATOM 3384 HW2 SOL 1050 20.670 10.250 22.340 1.00 0.00 +ATOM 3385 OW SOL 1051 41.160 42.390 23.410 1.00 0.00 +ATOM 3386 HW1 SOL 1051 41.910 42.930 23.150 1.00 0.00 +ATOM 3387 HW2 SOL 1051 41.270 42.260 24.350 1.00 0.00 +ATOM 3388 OW SOL 1052 43.330 28.130 14.550 1.00 0.00 +ATOM 3389 HW1 SOL 1052 43.680 28.990 14.810 1.00 0.00 +ATOM 3390 HW2 SOL 1052 42.380 28.230 14.640 1.00 0.00 +ATOM 3391 OW SOL 1053 42.620 6.920 20.890 1.00 0.00 +ATOM 3392 HW1 SOL 1053 43.380 6.940 21.470 1.00 0.00 +ATOM 3393 HW2 SOL 1053 42.160 6.110 21.140 1.00 0.00 +ATOM 3394 OW SOL 1054 34.230 28.730 17.330 1.00 0.00 +ATOM 3395 HW1 SOL 1054 33.520 28.260 16.890 1.00 0.00 +ATOM 3396 HW2 SOL 1054 34.640 28.060 17.880 1.00 0.00 +ATOM 3397 OW SOL 1055 10.550 4.820 0.630 1.00 0.00 +ATOM 3398 HW1 SOL 1055 11.040 4.660 1.440 1.00 0.00 +ATOM 3399 HW2 SOL 1055 10.020 5.590 0.820 1.00 0.00 +ATOM 3400 OW SOL 1056 21.620 3.910 16.660 1.00 0.00 +ATOM 3401 HW1 SOL 1056 20.870 3.650 17.190 1.00 0.00 +ATOM 3402 HW2 SOL 1056 21.660 3.260 15.960 1.00 0.00 +ATOM 3403 OW SOL 1057 32.640 21.130 14.560 1.00 0.00 +ATOM 3404 HW1 SOL 1057 32.390 21.080 15.480 1.00 0.00 +ATOM 3405 HW2 SOL 1057 32.320 21.990 14.270 1.00 0.00 +ATOM 3406 OW SOL 1058 35.940 2.470 12.550 1.00 0.00 +ATOM 3407 HW1 SOL 1058 35.440 2.860 11.830 1.00 0.00 +ATOM 3408 HW2 SOL 1058 35.270 2.250 13.210 1.00 0.00 +ATOM 3409 OW SOL 1059 13.580 -0.907 8.950 1.00 0.00 +ATOM 3410 HW1 SOL 1059 13.780 -0.937 9.880 1.00 0.00 +ATOM 3411 HW2 SOL 1059 13.090 -1.707 8.780 1.00 0.00 +ATOM 3412 OW SOL 1060 35.740 14.750 15.910 1.00 0.00 +ATOM 3413 HW1 SOL 1060 35.800 14.120 16.630 1.00 0.00 +ATOM 3414 HW2 SOL 1060 36.640 14.860 15.600 1.00 0.00 +ATOM 3415 OW SOL 1061 5.010 26.380 18.170 1.00 0.00 +ATOM 3416 HW1 SOL 1061 5.580 25.640 17.940 1.00 0.00 +ATOM 3417 HW2 SOL 1061 5.260 27.070 17.560 1.00 0.00 +ATOM 3418 OW SOL 1062 21.680 14.440 17.800 1.00 0.00 +ATOM 3419 HW1 SOL 1062 22.520 14.170 18.170 1.00 0.00 +ATOM 3420 HW2 SOL 1062 21.050 13.830 18.170 1.00 0.00 +ATOM 3421 OW SOL 1063 32.340 4.600 26.220 1.00 0.00 +ATOM 3422 HW1 SOL 1063 32.170 4.140 25.400 1.00 0.00 +ATOM 3423 HW2 SOL 1063 33.250 4.390 26.430 1.00 0.00 +ATOM 3424 OW SOL 1064 37.150 17.540 16.610 1.00 0.00 +ATOM 3425 HW1 SOL 1064 36.690 17.260 17.400 1.00 0.00 +ATOM 3426 HW2 SOL 1064 36.640 18.270 16.270 1.00 0.00 +ATOM 3427 OW SOL 1065 39.040 40.750 24.690 1.00 0.00 +ATOM 3428 HW1 SOL 1065 39.350 41.130 23.870 1.00 0.00 +ATOM 3429 HW2 SOL 1065 39.530 39.940 24.780 1.00 0.00 +ATOM 3430 OW SOL 1066 17.110 37.520 14.890 1.00 0.00 +ATOM 3431 HW1 SOL 1066 17.650 38.250 14.590 1.00 0.00 +ATOM 3432 HW2 SOL 1066 16.660 37.210 14.110 1.00 0.00 +ATOM 3433 OW SOL 1067 16.740 11.770 21.670 1.00 0.00 +ATOM 3434 HW1 SOL 1067 16.280 12.460 21.190 1.00 0.00 +ATOM 3435 HW2 SOL 1067 17.290 11.350 21.010 1.00 0.00 +ATOM 3436 OW SOL 1068 15.570 17.830 4.960 1.00 0.00 +ATOM 3437 HW1 SOL 1068 15.690 18.530 5.600 1.00 0.00 +ATOM 3438 HW2 SOL 1068 15.410 17.050 5.500 1.00 0.00 +ATOM 3439 OW SOL 1069 21.640 5.450 13.980 1.00 0.00 +ATOM 3440 HW1 SOL 1069 21.910 5.730 13.110 1.00 0.00 +ATOM 3441 HW2 SOL 1069 21.590 4.490 13.920 1.00 0.00 +ATOM 3442 OW SOL 1070 33.820 5.940 20.980 1.00 0.00 +ATOM 3443 HW1 SOL 1070 33.840 5.450 20.160 1.00 0.00 +ATOM 3444 HW2 SOL 1070 33.200 5.470 21.530 1.00 0.00 +ATOM 3445 OW SOL 1071 37.830 20.100 14.900 1.00 0.00 +ATOM 3446 HW1 SOL 1071 37.660 19.410 14.270 1.00 0.00 +ATOM 3447 HW2 SOL 1071 38.780 20.150 14.960 1.00 0.00 +ATOM 3448 OW SOL 1072 8.620 22.210 16.170 1.00 0.00 +ATOM 3449 HW1 SOL 1072 9.380 21.990 16.710 1.00 0.00 +ATOM 3450 HW2 SOL 1072 8.380 21.370 15.760 1.00 0.00 +ATOM 3451 OW SOL 1073 34.790 25.300 23.030 1.00 0.00 +ATOM 3452 HW1 SOL 1073 34.420 25.780 23.760 1.00 0.00 +ATOM 3453 HW2 SOL 1073 35.080 24.470 23.400 1.00 0.00 +ATOM 3454 OW SOL 1074 11.440 44.240 25.460 1.00 0.00 +ATOM 3455 HW1 SOL 1074 11.420 44.020 24.530 1.00 0.00 +ATOM 3456 HW2 SOL 1074 11.900 43.500 25.870 1.00 0.00 +ATOM 3457 OW SOL 1075 42.960 44.850 11.480 1.00 0.00 +ATOM 3458 HW1 SOL 1075 42.510 45.290 12.200 1.00 0.00 +ATOM 3459 HW2 SOL 1075 43.460 44.150 11.910 1.00 0.00 +ATOM 3460 OW SOL 1076 29.940 16.590 21.810 1.00 0.00 +ATOM 3461 HW1 SOL 1076 29.480 16.950 22.570 1.00 0.00 +ATOM 3462 HW2 SOL 1076 30.830 16.940 21.880 1.00 0.00 +ATOM 3463 OW SOL 1077 11.280 23.190 27.730 1.00 0.00 +ATOM 3464 HW1 SOL 1077 10.750 22.390 27.770 1.00 0.00 +ATOM 3465 HW2 SOL 1077 10.630 23.890 27.620 1.00 0.00 +ATOM 3466 OW SOL 1078 34.330 18.760 6.420 1.00 0.00 +ATOM 3467 HW1 SOL 1078 34.080 18.150 5.730 1.00 0.00 +ATOM 3468 HW2 SOL 1078 33.580 19.350 6.500 1.00 0.00 +ATOM 3469 OW SOL 1079 10.490 11.070 9.130 1.00 0.00 +ATOM 3470 HW1 SOL 1079 10.190 10.520 8.400 1.00 0.00 +ATOM 3471 HW2 SOL 1079 10.080 10.670 9.900 1.00 0.00 +ATOM 3472 OW SOL 1080 44.700 9.680 26.490 1.00 0.00 +ATOM 3473 HW1 SOL 1080 45.130 10.530 26.520 1.00 0.00 +ATOM 3474 HW2 SOL 1080 43.920 9.820 25.950 1.00 0.00 +ATOM 3475 OW SOL 1081 11.860 32.170 17.330 1.00 0.00 +ATOM 3476 HW1 SOL 1081 11.680 33.110 17.230 1.00 0.00 +ATOM 3477 HW2 SOL 1081 11.090 31.750 16.940 1.00 0.00 +ATOM 3478 OW SOL 1082 31.680 13.430 22.690 1.00 0.00 +ATOM 3479 HW1 SOL 1082 31.760 12.740 23.350 1.00 0.00 +ATOM 3480 HW2 SOL 1082 31.810 12.980 21.850 1.00 0.00 +ATOM 3481 OW SOL 1083 0.280 40.300 29.480 1.00 0.00 +ATOM 3482 HW1 SOL 1083 -0.110 39.560 29.020 1.00 0.00 +ATOM 3483 HW2 SOL 1083 -0.470 40.780 29.850 1.00 0.00 +ATOM 3484 OW SOL 1084 33.860 24.860 7.860 1.00 0.00 +ATOM 3485 HW1 SOL 1084 34.640 24.440 8.230 1.00 0.00 +ATOM 3486 HW2 SOL 1084 33.140 24.500 8.370 1.00 0.00 +ATOM 3487 OW SOL 1085 36.520 36.480 2.550 1.00 0.00 +ATOM 3488 HW1 SOL 1085 36.710 36.910 1.710 1.00 0.00 +ATOM 3489 HW2 SOL 1085 36.170 35.620 2.300 1.00 0.00 +ATOM 3490 OW SOL 1086 41.560 32.710 9.340 1.00 0.00 +ATOM 3491 HW1 SOL 1086 42.100 32.920 10.100 1.00 0.00 +ATOM 3492 HW2 SOL 1086 42.010 33.160 8.610 1.00 0.00 +ATOM 3493 OW SOL 1087 10.330 25.080 9.690 1.00 0.00 +ATOM 3494 HW1 SOL 1087 9.960 25.140 10.570 1.00 0.00 +ATOM 3495 HW2 SOL 1087 11.130 24.580 9.800 1.00 0.00 +ATOM 3496 OW SOL 1088 41.670 2.150 26.340 1.00 0.00 +ATOM 3497 HW1 SOL 1088 41.900 1.520 27.020 1.00 0.00 +ATOM 3498 HW2 SOL 1088 41.960 2.990 26.680 1.00 0.00 +ATOM 3499 OW SOL 1089 33.720 43.210 6.430 1.00 0.00 +ATOM 3500 HW1 SOL 1089 34.070 43.970 6.890 1.00 0.00 +ATOM 3501 HW2 SOL 1089 34.490 42.810 6.020 1.00 0.00 +ATOM 3502 OW SOL 1090 11.370 31.640 0.420 1.00 0.00 +ATOM 3503 HW1 SOL 1090 10.530 31.190 0.460 1.00 0.00 +ATOM 3504 HW2 SOL 1090 11.380 32.200 1.190 1.00 0.00 +ATOM 3505 OW SOL 1091 21.420 19.200 8.040 1.00 0.00 +ATOM 3506 HW1 SOL 1091 22.240 18.910 7.630 1.00 0.00 +ATOM 3507 HW2 SOL 1091 21.700 19.830 8.700 1.00 0.00 +ATOM 3508 OW SOL 1092 1.510 6.270 17.700 1.00 0.00 +ATOM 3509 HW1 SOL 1092 1.180 5.850 16.900 1.00 0.00 +ATOM 3510 HW2 SOL 1092 1.080 7.130 17.710 1.00 0.00 +ATOM 3511 OW SOL 1093 28.430 38.340 18.370 1.00 0.00 +ATOM 3512 HW1 SOL 1093 28.590 38.560 17.450 1.00 0.00 +ATOM 3513 HW2 SOL 1093 28.570 37.400 18.420 1.00 0.00 +ATOM 3514 OW SOL 1094 28.480 22.120 28.130 1.00 0.00 +ATOM 3515 HW1 SOL 1094 28.120 22.600 27.390 1.00 0.00 +ATOM 3516 HW2 SOL 1094 28.140 21.230 28.030 1.00 0.00 +ATOM 3517 OW SOL 1095 28.640 44.450 25.620 1.00 0.00 +ATOM 3518 HW1 SOL 1095 28.000 44.000 25.060 1.00 0.00 +ATOM 3519 HW2 SOL 1095 28.510 44.070 26.490 1.00 0.00 +ATOM 3520 OW SOL 1096 15.600 20.860 22.170 1.00 0.00 +ATOM 3521 HW1 SOL 1096 15.210 21.470 22.790 1.00 0.00 +ATOM 3522 HW2 SOL 1096 16.430 20.600 22.570 1.00 0.00 +ATOM 3523 OW SOL 1097 40.070 24.940 19.320 1.00 0.00 +ATOM 3524 HW1 SOL 1097 40.080 24.070 19.730 1.00 0.00 +ATOM 3525 HW2 SOL 1097 40.940 25.030 18.940 1.00 0.00 +ATOM 3526 OW SOL 1098 29.390 38.710 15.890 1.00 0.00 +ATOM 3527 HW1 SOL 1098 28.790 38.000 15.630 1.00 0.00 +ATOM 3528 HW2 SOL 1098 29.360 39.330 15.160 1.00 0.00 +ATOM 3529 OW SOL 1099 1.700 1.690 17.510 1.00 0.00 +ATOM 3530 HW1 SOL 1099 0.870 2.100 17.780 1.00 0.00 +ATOM 3531 HW2 SOL 1099 1.580 1.530 16.570 1.00 0.00 +ATOM 3532 OW SOL 1100 41.880 13.010 4.970 1.00 0.00 +ATOM 3533 HW1 SOL 1100 42.440 13.350 5.670 1.00 0.00 +ATOM 3534 HW2 SOL 1100 41.410 12.280 5.370 1.00 0.00 +ATOM 3535 OW SOL 1101 39.350 3.640 8.720 1.00 0.00 +ATOM 3536 HW1 SOL 1101 40.260 3.920 8.750 1.00 0.00 +ATOM 3537 HW2 SOL 1101 39.380 2.740 8.410 1.00 0.00 +ATOM 3538 OW SOL 1102 29.370 6.560 17.080 1.00 0.00 +ATOM 3539 HW1 SOL 1102 29.180 7.060 16.290 1.00 0.00 +ATOM 3540 HW2 SOL 1102 29.000 5.700 16.920 1.00 0.00 +ATOM 3541 OW SOL 1103 22.330 10.830 12.740 1.00 0.00 +ATOM 3542 HW1 SOL 1103 22.140 10.170 12.070 1.00 0.00 +ATOM 3543 HW2 SOL 1103 21.880 11.620 12.420 1.00 0.00 +ATOM 3544 OW SOL 1104 35.900 23.960 9.590 1.00 0.00 +ATOM 3545 HW1 SOL 1104 35.870 23.040 9.870 1.00 0.00 +ATOM 3546 HW2 SOL 1104 36.100 24.450 10.390 1.00 0.00 +ATOM 3547 OW SOL 1105 1.580 43.320 5.980 1.00 0.00 +ATOM 3548 HW1 SOL 1105 0.910 43.830 6.440 1.00 0.00 +ATOM 3549 HW2 SOL 1105 2.190 43.050 6.670 1.00 0.00 +ATOM 3550 OW SOL 1106 22.730 17.010 27.530 1.00 0.00 +ATOM 3551 HW1 SOL 1106 21.840 17.330 27.700 1.00 0.00 +ATOM 3552 HW2 SOL 1106 23.250 17.380 28.240 1.00 0.00 +ATOM 3553 OW SOL 1107 14.020 31.800 0.080 1.00 0.00 +ATOM 3554 HW1 SOL 1107 14.390 31.560 0.930 1.00 0.00 +ATOM 3555 HW2 SOL 1107 13.070 31.840 0.240 1.00 0.00 +ATOM 3556 OW SOL 1108 28.970 15.290 26.070 1.00 0.00 +ATOM 3557 HW1 SOL 1108 29.190 14.570 26.660 1.00 0.00 +ATOM 3558 HW2 SOL 1108 29.040 16.070 26.620 1.00 0.00 +ATOM 3559 OW SOL 1109 14.050 13.020 13.320 1.00 0.00 +ATOM 3560 HW1 SOL 1109 13.600 12.580 12.610 1.00 0.00 +ATOM 3561 HW2 SOL 1109 13.820 13.950 13.220 1.00 0.00 +ATOM 3562 OW SOL 1110 20.410 34.960 16.030 1.00 0.00 +ATOM 3563 HW1 SOL 1110 21.200 34.440 16.150 1.00 0.00 +ATOM 3564 HW2 SOL 1110 20.590 35.780 16.490 1.00 0.00 +ATOM 3565 OW SOL 1111 19.430 22.970 5.070 1.00 0.00 +ATOM 3566 HW1 SOL 1111 19.210 22.230 4.510 1.00 0.00 +ATOM 3567 HW2 SOL 1111 19.810 23.620 4.480 1.00 0.00 +ATOM 3568 OW SOL 1112 37.720 6.240 5.940 1.00 0.00 +ATOM 3569 HW1 SOL 1112 37.510 6.010 5.040 1.00 0.00 +ATOM 3570 HW2 SOL 1112 37.690 5.410 6.420 1.00 0.00 +ATOM 3571 OW SOL 1113 13.170 15.290 26.810 1.00 0.00 +ATOM 3572 HW1 SOL 1113 12.800 15.190 27.680 1.00 0.00 +ATOM 3573 HW2 SOL 1113 12.770 14.590 26.290 1.00 0.00 +ATOM 3574 OW SOL 1114 17.040 2.660 13.540 1.00 0.00 +ATOM 3575 HW1 SOL 1114 17.170 2.370 12.630 1.00 0.00 +ATOM 3576 HW2 SOL 1114 17.680 3.360 13.660 1.00 0.00 +ATOM 3577 OW SOL 1115 11.330 28.970 17.820 1.00 0.00 +ATOM 3578 HW1 SOL 1115 11.300 29.190 18.760 1.00 0.00 +ATOM 3579 HW2 SOL 1115 10.720 29.590 17.410 1.00 0.00 +ATOM 3580 OW SOL 1116 38.770 9.280 5.830 1.00 0.00 +ATOM 3581 HW1 SOL 1116 38.460 8.370 5.800 1.00 0.00 +ATOM 3582 HW2 SOL 1116 38.000 9.810 5.660 1.00 0.00 +ATOM 3583 OW SOL 1117 16.640 42.950 5.890 1.00 0.00 +ATOM 3584 HW1 SOL 1117 15.860 42.400 5.960 1.00 0.00 +ATOM 3585 HW2 SOL 1117 16.550 43.580 6.610 1.00 0.00 +ATOM 3586 OW SOL 1118 6.910 14.640 30.460 1.00 0.00 +ATOM 3587 HW1 SOL 1118 6.320 15.350 30.710 1.00 0.00 +ATOM 3588 HW2 SOL 1118 6.720 14.470 29.540 1.00 0.00 +ATOM 3589 OW SOL 1119 13.040 2.000 9.540 1.00 0.00 +ATOM 3590 HW1 SOL 1119 12.950 1.180 9.040 1.00 0.00 +ATOM 3591 HW2 SOL 1119 13.720 1.810 10.190 1.00 0.00 +ATOM 3592 OW SOL 1120 28.970 32.070 16.280 1.00 0.00 +ATOM 3593 HW1 SOL 1120 29.610 32.760 16.460 1.00 0.00 +ATOM 3594 HW2 SOL 1120 29.000 31.960 15.330 1.00 0.00 +ATOM 3595 OW SOL 1121 40.860 12.120 2.030 1.00 0.00 +ATOM 3596 HW1 SOL 1121 41.690 12.400 2.420 1.00 0.00 +ATOM 3597 HW2 SOL 1121 40.200 12.610 2.520 1.00 0.00 +ATOM 3598 OW SOL 1122 20.310 16.730 24.750 1.00 0.00 +ATOM 3599 HW1 SOL 1122 21.060 16.230 24.440 1.00 0.00 +ATOM 3600 HW2 SOL 1122 19.910 17.090 23.950 1.00 0.00 +ATOM 3601 OW SOL 1123 11.330 42.380 12.070 1.00 0.00 +ATOM 3602 HW1 SOL 1123 11.370 43.330 12.120 1.00 0.00 +ATOM 3603 HW2 SOL 1123 12.180 42.080 12.380 1.00 0.00 +ATOM 3604 OW SOL 1124 41.560 16.300 18.000 1.00 0.00 +ATOM 3605 HW1 SOL 1124 41.110 16.560 17.200 1.00 0.00 +ATOM 3606 HW2 SOL 1124 41.470 17.060 18.580 1.00 0.00 +ATOM 3607 OW SOL 1125 31.680 36.000 10.070 1.00 0.00 +ATOM 3608 HW1 SOL 1125 31.360 35.820 9.190 1.00 0.00 +ATOM 3609 HW2 SOL 1125 31.560 36.940 10.180 1.00 0.00 +ATOM 3610 OW SOL 1126 13.620 11.060 19.930 1.00 0.00 +ATOM 3611 HW1 SOL 1126 12.960 10.410 19.720 1.00 0.00 +ATOM 3612 HW2 SOL 1126 13.750 10.980 20.870 1.00 0.00 +ATOM 3613 OW SOL 1127 41.450 16.830 9.210 1.00 0.00 +ATOM 3614 HW1 SOL 1127 40.860 17.350 9.760 1.00 0.00 +ATOM 3615 HW2 SOL 1127 42.220 16.680 9.760 1.00 0.00 +ATOM 3616 OW SOL 1128 21.830 41.610 27.550 1.00 0.00 +ATOM 3617 HW1 SOL 1128 21.140 42.260 27.390 1.00 0.00 +ATOM 3618 HW2 SOL 1128 21.880 41.540 28.500 1.00 0.00 +ATOM 3619 OW SOL 1129 11.930 1.130 22.060 1.00 0.00 +ATOM 3620 HW1 SOL 1129 12.710 0.810 22.520 1.00 0.00 +ATOM 3621 HW2 SOL 1129 11.250 1.130 22.730 1.00 0.00 +ATOM 3622 OW SOL 1130 38.140 32.270 26.860 1.00 0.00 +ATOM 3623 HW1 SOL 1130 38.240 31.480 26.320 1.00 0.00 +ATOM 3624 HW2 SOL 1130 37.980 31.940 27.740 1.00 0.00 +ATOM 3625 OW SOL 1131 3.290 35.440 3.310 1.00 0.00 +ATOM 3626 HW1 SOL 1131 3.700 35.970 2.630 1.00 0.00 +ATOM 3627 HW2 SOL 1131 3.850 34.670 3.400 1.00 0.00 +ATOM 3628 OW SOL 1132 25.650 26.600 25.220 1.00 0.00 +ATOM 3629 HW1 SOL 1132 25.480 27.480 25.570 1.00 0.00 +ATOM 3630 HW2 SOL 1132 24.870 26.100 25.450 1.00 0.00 +ATOM 3631 OW SOL 1133 3.350 15.750 18.540 1.00 0.00 +ATOM 3632 HW1 SOL 1133 3.740 14.930 18.240 1.00 0.00 +ATOM 3633 HW2 SOL 1133 3.300 16.290 17.740 1.00 0.00 +ATOM 3634 OW SOL 1134 40.910 42.970 29.650 1.00 0.00 +ATOM 3635 HW1 SOL 1134 40.940 43.070 30.600 1.00 0.00 +ATOM 3636 HW2 SOL 1134 40.480 42.130 29.510 1.00 0.00 +ATOM 3637 OW SOL 1135 44.840 31.550 10.010 1.00 0.00 +ATOM 3638 HW1 SOL 1135 44.620 30.850 9.400 1.00 0.00 +ATOM 3639 HW2 SOL 1135 45.590 31.210 10.500 1.00 0.00 +ATOM 3640 OW SOL 1136 40.890 16.280 13.640 1.00 0.00 +ATOM 3641 HW1 SOL 1136 40.620 15.460 13.230 1.00 0.00 +ATOM 3642 HW2 SOL 1136 41.790 16.120 13.910 1.00 0.00 +ATOM 3643 OW SOL 1137 28.870 22.780 5.570 1.00 0.00 +ATOM 3644 HW1 SOL 1137 28.720 23.220 4.740 1.00 0.00 +ATOM 3645 HW2 SOL 1137 28.970 21.850 5.330 1.00 0.00 +ATOM 3646 OW SOL 1138 21.460 4.660 5.580 1.00 0.00 +ATOM 3647 HW1 SOL 1138 20.630 4.920 5.990 1.00 0.00 +ATOM 3648 HW2 SOL 1138 21.570 5.280 4.860 1.00 0.00 +ATOM 3649 OW SOL 1139 23.880 4.270 6.300 1.00 0.00 +ATOM 3650 HW1 SOL 1139 24.110 3.770 5.520 1.00 0.00 +ATOM 3651 HW2 SOL 1139 22.960 4.510 6.170 1.00 0.00 +ATOM 3652 OW SOL 1140 12.990 23.630 21.000 1.00 0.00 +ATOM 3653 HW1 SOL 1140 12.680 24.500 20.760 1.00 0.00 +ATOM 3654 HW2 SOL 1140 13.050 23.650 21.960 1.00 0.00 +ATOM 3655 OW SOL 1141 43.670 43.900 23.240 1.00 0.00 +ATOM 3656 HW1 SOL 1141 43.790 43.860 24.190 1.00 0.00 +ATOM 3657 HW2 SOL 1141 44.230 43.210 22.900 1.00 0.00 +ATOM 3658 OW SOL 1142 9.660 24.800 22.610 1.00 0.00 +ATOM 3659 HW1 SOL 1142 10.090 23.950 22.660 1.00 0.00 +ATOM 3660 HW2 SOL 1142 9.070 24.810 23.370 1.00 0.00 +ATOM 3661 OW SOL 1143 6.550 34.570 1.240 1.00 0.00 +ATOM 3662 HW1 SOL 1143 6.880 34.730 2.130 1.00 0.00 +ATOM 3663 HW2 SOL 1143 5.890 35.250 1.110 1.00 0.00 +ATOM 3664 OW SOL 1144 35.440 9.110 11.990 1.00 0.00 +ATOM 3665 HW1 SOL 1144 36.190 8.750 11.530 1.00 0.00 +ATOM 3666 HW2 SOL 1144 35.790 9.850 12.480 1.00 0.00 +ATOM 3667 OW SOL 1145 6.980 10.270 16.430 1.00 0.00 +ATOM 3668 HW1 SOL 1145 7.490 10.850 15.860 1.00 0.00 +ATOM 3669 HW2 SOL 1145 7.640 9.830 16.970 1.00 0.00 +ATOM 3670 OW SOL 1146 32.790 5.980 13.050 1.00 0.00 +ATOM 3671 HW1 SOL 1146 32.100 5.490 12.620 1.00 0.00 +ATOM 3672 HW2 SOL 1146 32.390 6.820 13.270 1.00 0.00 +ATOM 3673 OW SOL 1147 12.450 26.480 20.720 1.00 0.00 +ATOM 3674 HW1 SOL 1147 11.630 26.890 20.990 1.00 0.00 +ATOM 3675 HW2 SOL 1147 12.930 27.170 20.280 1.00 0.00 +ATOM 3676 OW SOL 1148 27.650 20.650 23.610 1.00 0.00 +ATOM 3677 HW1 SOL 1148 28.000 19.770 23.450 1.00 0.00 +ATOM 3678 HW2 SOL 1148 28.410 21.230 23.550 1.00 0.00 +ATOM 3679 OW SOL 1149 27.560 26.300 6.090 1.00 0.00 +ATOM 3680 HW1 SOL 1149 27.560 26.840 5.300 1.00 0.00 +ATOM 3681 HW2 SOL 1149 26.720 25.840 6.060 1.00 0.00 +ATOM 3682 OW SOL 1150 11.450 14.900 3.960 1.00 0.00 +ATOM 3683 HW1 SOL 1150 11.410 14.780 3.010 1.00 0.00 +ATOM 3684 HW2 SOL 1150 11.590 15.840 4.080 1.00 0.00 +ATOM 3685 OW SOL 1151 44.450 5.830 8.050 1.00 0.00 +ATOM 3686 HW1 SOL 1151 45.030 5.700 8.800 1.00 0.00 +ATOM 3687 HW2 SOL 1151 43.640 5.380 8.280 1.00 0.00 +ATOM 3688 OW SOL 1152 10.780 33.860 29.080 1.00 0.00 +ATOM 3689 HW1 SOL 1152 11.640 34.240 28.890 1.00 0.00 +ATOM 3690 HW2 SOL 1152 10.780 33.030 28.600 1.00 0.00 +ATOM 3691 OW SOL 1153 27.200 36.210 31.420 1.00 0.00 +ATOM 3692 HW1 SOL 1153 26.520 36.850 31.650 1.00 0.00 +ATOM 3693 HW2 SOL 1153 28.020 36.690 31.540 1.00 0.00 +ATOM 3694 OW SOL 1154 0.390 23.730 6.630 1.00 0.00 +ATOM 3695 HW1 SOL 1154 0.770 23.780 5.760 1.00 0.00 +ATOM 3696 HW2 SOL 1154 -0.210 24.470 6.680 1.00 0.00 +ATOM 3697 OW SOL 1155 16.500 5.680 21.310 1.00 0.00 +ATOM 3698 HW1 SOL 1155 16.510 5.200 22.140 1.00 0.00 +ATOM 3699 HW2 SOL 1155 17.050 6.450 21.470 1.00 0.00 +ATOM 3700 OW SOL 1156 23.770 35.860 27.720 1.00 0.00 +ATOM 3701 HW1 SOL 1156 24.390 36.110 27.040 1.00 0.00 +ATOM 3702 HW2 SOL 1156 23.280 35.130 27.340 1.00 0.00 +ATOM 3703 OW SOL 1157 13.770 28.960 20.000 1.00 0.00 +ATOM 3704 HW1 SOL 1157 14.110 29.010 19.100 1.00 0.00 +ATOM 3705 HW2 SOL 1157 13.230 29.750 20.090 1.00 0.00 +ATOM 3706 OW SOL 1158 14.260 30.290 27.400 1.00 0.00 +ATOM 3707 HW1 SOL 1158 13.960 29.610 26.800 1.00 0.00 +ATOM 3708 HW2 SOL 1158 14.720 29.810 28.100 1.00 0.00 +ATOM 3709 OW SOL 1159 37.090 29.100 19.640 1.00 0.00 +ATOM 3710 HW1 SOL 1159 36.680 28.450 19.080 1.00 0.00 +ATOM 3711 HW2 SOL 1159 37.920 29.300 19.200 1.00 0.00 +ATOM 3712 OW SOL 1160 7.950 28.550 4.560 1.00 0.00 +ATOM 3713 HW1 SOL 1160 7.710 29.040 5.340 1.00 0.00 +ATOM 3714 HW2 SOL 1160 8.090 27.660 4.860 1.00 0.00 +ATOM 3715 OW SOL 1161 25.880 32.480 26.460 1.00 0.00 +ATOM 3716 HW1 SOL 1161 26.360 33.120 25.930 1.00 0.00 +ATOM 3717 HW2 SOL 1161 26.530 31.810 26.680 1.00 0.00 +ATOM 3718 OW SOL 1162 24.040 22.040 2.900 1.00 0.00 +ATOM 3719 HW1 SOL 1162 24.730 21.630 2.380 1.00 0.00 +ATOM 3720 HW2 SOL 1162 24.070 21.570 3.740 1.00 0.00 +ATOM 3721 OW SOL 1163 39.430 31.400 3.900 1.00 0.00 +ATOM 3722 HW1 SOL 1163 38.570 31.170 3.550 1.00 0.00 +ATOM 3723 HW2 SOL 1163 40.050 30.960 3.310 1.00 0.00 +ATOM 3724 OW SOL 1164 14.380 31.230 2.740 1.00 0.00 +ATOM 3725 HW1 SOL 1164 13.670 30.660 3.040 1.00 0.00 +ATOM 3726 HW2 SOL 1164 14.270 32.030 3.240 1.00 0.00 +ATOM 3727 OW SOL 1165 20.100 42.020 24.580 1.00 0.00 +ATOM 3728 HW1 SOL 1165 20.190 41.960 23.630 1.00 0.00 +ATOM 3729 HW2 SOL 1165 20.530 41.230 24.920 1.00 0.00 +ATOM 3730 OW SOL 1166 6.330 9.080 14.120 1.00 0.00 +ATOM 3731 HW1 SOL 1166 6.150 9.200 15.050 1.00 0.00 +ATOM 3732 HW2 SOL 1166 6.630 8.180 14.040 1.00 0.00 +ATOM 3733 OW SOL 1167 34.730 37.450 19.560 1.00 0.00 +ATOM 3734 HW1 SOL 1167 33.830 37.700 19.350 1.00 0.00 +ATOM 3735 HW2 SOL 1167 34.740 36.490 19.480 1.00 0.00 +ATOM 3736 OW SOL 1168 10.330 19.800 25.890 1.00 0.00 +ATOM 3737 HW1 SOL 1168 10.200 20.170 26.770 1.00 0.00 +ATOM 3738 HW2 SOL 1168 10.820 19.000 26.030 1.00 0.00 +ATOM 3739 OW SOL 1169 19.690 32.100 11.660 1.00 0.00 +ATOM 3740 HW1 SOL 1169 19.240 31.790 12.440 1.00 0.00 +ATOM 3741 HW2 SOL 1169 20.200 31.340 11.370 1.00 0.00 +ATOM 3742 OW SOL 1170 36.470 42.770 27.590 1.00 0.00 +ATOM 3743 HW1 SOL 1170 35.850 43.100 26.940 1.00 0.00 +ATOM 3744 HW2 SOL 1170 35.930 42.320 28.240 1.00 0.00 +ATOM 3745 OW SOL 1171 28.130 18.710 20.930 1.00 0.00 +ATOM 3746 HW1 SOL 1171 28.240 18.490 20.000 1.00 0.00 +ATOM 3747 HW2 SOL 1171 28.850 19.320 21.110 1.00 0.00 +ATOM 3748 OW SOL 1172 11.440 34.080 2.950 1.00 0.00 +ATOM 3749 HW1 SOL 1172 11.190 33.270 3.380 1.00 0.00 +ATOM 3750 HW2 SOL 1172 10.640 34.610 2.950 1.00 0.00 +ATOM 3751 OW SOL 1173 27.700 22.420 21.200 1.00 0.00 +ATOM 3752 HW1 SOL 1173 26.910 22.260 21.710 1.00 0.00 +ATOM 3753 HW2 SOL 1173 27.520 22.050 20.340 1.00 0.00 +ATOM 3754 OW SOL 1174 15.840 36.530 24.910 1.00 0.00 +ATOM 3755 HW1 SOL 1174 14.950 36.730 25.200 1.00 0.00 +ATOM 3756 HW2 SOL 1174 16.190 35.950 25.580 1.00 0.00 +ATOM 3757 OW SOL 1175 40.060 4.280 24.860 1.00 0.00 +ATOM 3758 HW1 SOL 1175 40.900 4.430 24.420 1.00 0.00 +ATOM 3759 HW2 SOL 1175 40.150 3.420 25.270 1.00 0.00 +ATOM 3760 OW SOL 1176 41.200 16.350 2.390 1.00 0.00 +ATOM 3761 HW1 SOL 1176 41.350 16.570 3.310 1.00 0.00 +ATOM 3762 HW2 SOL 1176 40.270 16.500 2.260 1.00 0.00 +ATOM 3763 OW SOL 1177 37.210 23.270 28.730 1.00 0.00 +ATOM 3764 HW1 SOL 1177 37.930 23.150 29.360 1.00 0.00 +ATOM 3765 HW2 SOL 1177 36.480 23.590 29.260 1.00 0.00 +ATOM 3766 OW SOL 1178 8.600 5.470 27.330 1.00 0.00 +ATOM 3767 HW1 SOL 1178 8.460 4.570 27.040 1.00 0.00 +ATOM 3768 HW2 SOL 1178 8.540 5.430 28.280 1.00 0.00 +ATOM 3769 OW SOL 1179 14.350 34.820 22.770 1.00 0.00 +ATOM 3770 HW1 SOL 1179 14.950 34.580 23.480 1.00 0.00 +ATOM 3771 HW2 SOL 1179 14.520 35.750 22.630 1.00 0.00 +ATOM 3772 OW SOL 1180 24.960 37.750 14.910 1.00 0.00 +ATOM 3773 HW1 SOL 1180 24.320 37.050 15.040 1.00 0.00 +ATOM 3774 HW2 SOL 1180 24.760 38.100 14.040 1.00 0.00 +ATOM 3775 OW SOL 1181 44.160 21.240 20.050 1.00 0.00 +ATOM 3776 HW1 SOL 1181 43.250 21.270 19.770 1.00 0.00 +ATOM 3777 HW2 SOL 1181 44.590 21.940 19.560 1.00 0.00 +ATOM 3778 OW SOL 1182 30.940 10.820 26.790 1.00 0.00 +ATOM 3779 HW1 SOL 1182 31.490 10.650 27.560 1.00 0.00 +ATOM 3780 HW2 SOL 1182 30.410 10.030 26.690 1.00 0.00 +ATOM 3781 OW SOL 1183 41.470 21.590 18.710 1.00 0.00 +ATOM 3782 HW1 SOL 1183 40.820 20.890 18.620 1.00 0.00 +ATOM 3783 HW2 SOL 1183 41.140 22.130 19.430 1.00 0.00 +ATOM 3784 OW SOL 1184 19.530 20.640 20.110 1.00 0.00 +ATOM 3785 HW1 SOL 1184 20.450 20.900 20.140 1.00 0.00 +ATOM 3786 HW2 SOL 1184 19.210 20.770 21.000 1.00 0.00 +ATOM 3787 OW SOL 1185 1.730 35.940 0.250 1.00 0.00 +ATOM 3788 HW1 SOL 1185 0.990 36.460 -0.050 1.00 0.00 +ATOM 3789 HW2 SOL 1185 1.480 35.630 1.110 1.00 0.00 +ATOM 3790 OW SOL 1186 10.680 39.340 22.330 1.00 0.00 +ATOM 3791 HW1 SOL 1186 11.460 38.930 22.730 1.00 0.00 +ATOM 3792 HW2 SOL 1186 10.570 40.150 22.820 1.00 0.00 +ATOM 3793 OW SOL 1187 23.840 2.950 1.270 1.00 0.00 +ATOM 3794 HW1 SOL 1187 23.880 3.900 1.310 1.00 0.00 +ATOM 3795 HW2 SOL 1187 22.980 2.730 1.630 1.00 0.00 +ATOM 3796 OW SOL 1188 38.820 9.350 12.920 1.00 0.00 +ATOM 3797 HW1 SOL 1188 38.720 8.980 12.040 1.00 0.00 +ATOM 3798 HW2 SOL 1188 38.150 8.910 13.440 1.00 0.00 +ATOM 3799 OW SOL 1189 28.250 25.490 22.900 1.00 0.00 +ATOM 3800 HW1 SOL 1189 27.960 25.020 23.680 1.00 0.00 +ATOM 3801 HW2 SOL 1189 27.590 25.280 22.240 1.00 0.00 +ATOM 3802 OW SOL 1190 24.560 17.170 14.390 1.00 0.00 +ATOM 3803 HW1 SOL 1190 24.940 17.890 14.890 1.00 0.00 +ATOM 3804 HW2 SOL 1190 25.300 16.750 13.960 1.00 0.00 +ATOM 3805 OW SOL 1191 0.860 19.360 1.910 1.00 0.00 +ATOM 3806 HW1 SOL 1191 0.600 19.950 2.610 1.00 0.00 +ATOM 3807 HW2 SOL 1191 1.100 18.540 2.360 1.00 0.00 +ATOM 3808 OW SOL 1192 2.660 15.690 13.220 1.00 0.00 +ATOM 3809 HW1 SOL 1192 2.450 15.140 13.970 1.00 0.00 +ATOM 3810 HW2 SOL 1192 2.280 16.540 13.430 1.00 0.00 +ATOM 3811 OW SOL 1193 13.280 3.630 26.500 1.00 0.00 +ATOM 3812 HW1 SOL 1193 12.770 3.250 27.220 1.00 0.00 +ATOM 3813 HW2 SOL 1193 12.850 3.310 25.710 1.00 0.00 +ATOM 3814 OW SOL 1194 28.750 40.190 13.510 1.00 0.00 +ATOM 3815 HW1 SOL 1194 27.820 40.160 13.280 1.00 0.00 +ATOM 3816 HW2 SOL 1194 29.170 39.650 12.850 1.00 0.00 +ATOM 3817 OW SOL 1195 16.620 4.720 26.300 1.00 0.00 +ATOM 3818 HW1 SOL 1195 17.120 5.420 26.730 1.00 0.00 +ATOM 3819 HW2 SOL 1195 15.710 4.890 26.560 1.00 0.00 +ATOM 3820 OW SOL 1196 22.510 5.680 29.770 1.00 0.00 +ATOM 3821 HW1 SOL 1196 23.340 5.220 29.610 1.00 0.00 +ATOM 3822 HW2 SOL 1196 22.190 5.910 28.890 1.00 0.00 +ATOM 3823 OW SOL 1197 18.300 27.590 3.550 1.00 0.00 +ATOM 3824 HW1 SOL 1197 17.650 28.110 3.090 1.00 0.00 +ATOM 3825 HW2 SOL 1197 18.940 28.230 3.870 1.00 0.00 +ATOM 3826 OW SOL 1198 10.000 25.460 12.380 1.00 0.00 +ATOM 3827 HW1 SOL 1198 10.740 26.060 12.490 1.00 0.00 +ATOM 3828 HW2 SOL 1198 9.750 25.230 13.280 1.00 0.00 +ATOM 3829 OW SOL 1199 17.250 0.660 16.340 1.00 0.00 +ATOM 3830 HW1 SOL 1199 16.400 0.990 16.050 1.00 0.00 +ATOM 3831 HW2 SOL 1199 17.730 1.440 16.600 1.00 0.00 +ATOM 3832 OW SOL 1200 17.590 33.840 22.490 1.00 0.00 +ATOM 3833 HW1 SOL 1200 17.500 34.760 22.230 1.00 0.00 +ATOM 3834 HW2 SOL 1200 17.990 33.420 21.720 1.00 0.00 +ATOM 3835 OW SOL 1201 23.990 36.550 1.230 1.00 0.00 +ATOM 3836 HW1 SOL 1201 23.410 37.150 1.700 1.00 0.00 +ATOM 3837 HW2 SOL 1201 24.630 36.270 1.890 1.00 0.00 +ATOM 3838 OW SOL 1202 25.360 3.870 11.660 1.00 0.00 +ATOM 3839 HW1 SOL 1202 24.780 3.870 10.900 1.00 0.00 +ATOM 3840 HW2 SOL 1202 24.960 4.490 12.270 1.00 0.00 +ATOM 3841 OW SOL 1203 19.650 44.330 2.100 1.00 0.00 +ATOM 3842 HW1 SOL 1203 19.320 43.440 2.140 1.00 0.00 +ATOM 3843 HW2 SOL 1203 20.450 44.270 1.580 1.00 0.00 +ATOM 3844 OW SOL 1204 30.900 4.870 11.420 1.00 0.00 +ATOM 3845 HW1 SOL 1204 31.300 5.330 10.680 1.00 0.00 +ATOM 3846 HW2 SOL 1204 30.090 5.360 11.590 1.00 0.00 +ATOM 3847 OW SOL 1205 3.240 19.330 0.490 1.00 0.00 +ATOM 3848 HW1 SOL 1205 3.680 19.800 1.200 1.00 0.00 +ATOM 3849 HW2 SOL 1205 2.400 19.070 0.860 1.00 0.00 +ATOM 3850 OW SOL 1206 21.670 18.600 17.900 1.00 0.00 +ATOM 3851 HW1 SOL 1206 21.640 18.860 18.820 1.00 0.00 +ATOM 3852 HW2 SOL 1206 21.300 19.350 17.430 1.00 0.00 +ATOM 3853 OW SOL 1207 39.070 23.840 13.460 1.00 0.00 +ATOM 3854 HW1 SOL 1207 39.760 24.090 12.840 1.00 0.00 +ATOM 3855 HW2 SOL 1207 38.290 24.310 13.150 1.00 0.00 +ATOM 3856 OW SOL 1208 0.590 23.530 12.800 1.00 0.00 +ATOM 3857 HW1 SOL 1208 -0.040 24.230 12.960 1.00 0.00 +ATOM 3858 HW2 SOL 1208 1.210 23.590 13.530 1.00 0.00 +ATOM 3859 OW SOL 1209 24.710 17.530 8.550 1.00 0.00 +ATOM 3860 HW1 SOL 1209 25.570 17.340 8.950 1.00 0.00 +ATOM 3861 HW2 SOL 1209 24.110 17.580 9.290 1.00 0.00 +ATOM 3862 OW SOL 1210 43.920 32.140 20.760 1.00 0.00 +ATOM 3863 HW1 SOL 1210 44.570 32.170 20.060 1.00 0.00 +ATOM 3864 HW2 SOL 1210 43.190 32.670 20.430 1.00 0.00 +ATOM 3865 OW SOL 1211 3.140 27.410 13.000 1.00 0.00 +ATOM 3866 HW1 SOL 1211 3.440 26.850 12.280 1.00 0.00 +ATOM 3867 HW2 SOL 1211 3.950 27.700 13.420 1.00 0.00 +ATOM 3868 OW SOL 1212 27.750 41.730 6.840 1.00 0.00 +ATOM 3869 HW1 SOL 1212 27.040 42.280 6.500 1.00 0.00 +ATOM 3870 HW2 SOL 1212 28.550 42.140 6.530 1.00 0.00 +ATOM 3871 OW SOL 1213 30.710 9.120 3.660 1.00 0.00 +ATOM 3872 HW1 SOL 1213 31.460 9.630 3.970 1.00 0.00 +ATOM 3873 HW2 SOL 1213 30.960 8.210 3.800 1.00 0.00 +ATOM 3874 OW SOL 1214 16.070 40.790 12.400 1.00 0.00 +ATOM 3875 HW1 SOL 1214 15.910 40.100 11.760 1.00 0.00 +ATOM 3876 HW2 SOL 1214 16.980 41.030 12.270 1.00 0.00 +ATOM 3877 OW SOL 1215 12.710 23.910 9.850 1.00 0.00 +ATOM 3878 HW1 SOL 1215 13.230 24.460 10.430 1.00 0.00 +ATOM 3879 HW2 SOL 1215 13.180 23.080 9.830 1.00 0.00 +ATOM 3880 OW SOL 1216 5.060 40.470 9.910 1.00 0.00 +ATOM 3881 HW1 SOL 1216 5.980 40.270 10.100 1.00 0.00 +ATOM 3882 HW2 SOL 1216 4.940 41.370 10.190 1.00 0.00 +ATOM 3883 OW SOL 1217 43.650 18.440 3.810 1.00 0.00 +ATOM 3884 HW1 SOL 1217 43.540 17.820 4.530 1.00 0.00 +ATOM 3885 HW2 SOL 1217 44.120 19.180 4.190 1.00 0.00 +ATOM 3886 OW SOL 1218 13.240 15.740 19.130 1.00 0.00 +ATOM 3887 HW1 SOL 1218 12.390 16.140 18.930 1.00 0.00 +ATOM 3888 HW2 SOL 1218 13.140 15.380 20.000 1.00 0.00 +ATOM 3889 OW SOL 1219 36.200 13.590 3.520 1.00 0.00 +ATOM 3890 HW1 SOL 1219 36.290 13.560 2.570 1.00 0.00 +ATOM 3891 HW2 SOL 1219 35.250 13.580 3.680 1.00 0.00 +ATOM 3892 OW SOL 1220 42.410 26.250 3.230 1.00 0.00 +ATOM 3893 HW1 SOL 1220 41.620 25.870 3.610 1.00 0.00 +ATOM 3894 HW2 SOL 1220 42.880 26.630 3.980 1.00 0.00 +ATOM 3895 OW SOL 1221 32.180 38.400 19.330 1.00 0.00 +ATOM 3896 HW1 SOL 1221 32.610 38.710 20.120 1.00 0.00 +ATOM 3897 HW2 SOL 1221 31.710 39.170 18.990 1.00 0.00 +ATOM 3898 OW SOL 1222 44.370 2.960 9.750 1.00 0.00 +ATOM 3899 HW1 SOL 1222 45.200 3.110 9.300 1.00 0.00 +ATOM 3900 HW2 SOL 1222 43.700 3.140 9.090 1.00 0.00 +ATOM 3901 OW SOL 1223 16.390 25.780 4.640 1.00 0.00 +ATOM 3902 HW1 SOL 1223 15.520 26.160 4.490 1.00 0.00 +ATOM 3903 HW2 SOL 1223 16.970 26.290 4.070 1.00 0.00 +ATOM 3904 OW SOL 1224 26.330 37.500 6.440 1.00 0.00 +ATOM 3905 HW1 SOL 1224 25.510 37.300 6.890 1.00 0.00 +ATOM 3906 HW2 SOL 1224 26.120 38.240 5.870 1.00 0.00 +ATOM 3907 OW SOL 1225 21.670 20.080 25.180 1.00 0.00 +ATOM 3908 HW1 SOL 1225 22.440 19.960 24.630 1.00 0.00 +ATOM 3909 HW2 SOL 1225 21.330 19.190 25.310 1.00 0.00 +ATOM 3910 OW SOL 1226 25.220 0.960 8.910 1.00 0.00 +ATOM 3911 HW1 SOL 1226 25.830 0.740 8.210 1.00 0.00 +ATOM 3912 HW2 SOL 1226 25.670 0.680 9.710 1.00 0.00 +ATOM 3913 OW SOL 1227 25.170 8.440 21.550 1.00 0.00 +ATOM 3914 HW1 SOL 1227 24.700 7.870 22.170 1.00 0.00 +ATOM 3915 HW2 SOL 1227 24.820 8.190 20.700 1.00 0.00 +ATOM 3916 OW SOL 1228 19.800 3.920 23.910 1.00 0.00 +ATOM 3917 HW1 SOL 1228 20.330 3.570 24.630 1.00 0.00 +ATOM 3918 HW2 SOL 1228 20.400 3.980 23.170 1.00 0.00 +ATOM 3919 OW SOL 1229 17.050 41.540 26.090 1.00 0.00 +ATOM 3920 HW1 SOL 1229 17.930 41.210 26.280 1.00 0.00 +ATOM 3921 HW2 SOL 1229 17.180 42.470 25.910 1.00 0.00 +ATOM 3922 OW SOL 1230 27.550 6.770 14.990 1.00 0.00 +ATOM 3923 HW1 SOL 1230 27.680 6.260 14.190 1.00 0.00 +ATOM 3924 HW2 SOL 1230 26.900 6.270 15.490 1.00 0.00 +ATOM 3925 OW SOL 1231 16.450 18.730 24.710 1.00 0.00 +ATOM 3926 HW1 SOL 1231 16.030 17.960 25.090 1.00 0.00 +ATOM 3927 HW2 SOL 1231 16.270 19.430 25.330 1.00 0.00 +ATOM 3928 OW SOL 1232 17.420 40.110 22.080 1.00 0.00 +ATOM 3929 HW1 SOL 1232 18.130 40.050 22.720 1.00 0.00 +ATOM 3930 HW2 SOL 1232 17.840 40.450 21.290 1.00 0.00 +ATOM 3931 OW SOL 1233 15.540 24.690 16.370 1.00 0.00 +ATOM 3932 HW1 SOL 1233 15.210 24.850 17.250 1.00 0.00 +ATOM 3933 HW2 SOL 1233 15.570 23.730 16.300 1.00 0.00 +ATOM 3934 OW SOL 1234 14.010 21.560 9.420 1.00 0.00 +ATOM 3935 HW1 SOL 1234 13.980 21.180 10.290 1.00 0.00 +ATOM 3936 HW2 SOL 1234 14.890 21.360 9.100 1.00 0.00 +ATOM 3937 OW SOL 1235 34.940 7.200 18.110 1.00 0.00 +ATOM 3938 HW1 SOL 1235 34.230 7.120 17.460 1.00 0.00 +ATOM 3939 HW2 SOL 1235 34.980 6.340 18.520 1.00 0.00 +ATOM 3940 OW SOL 1236 21.520 9.830 2.890 1.00 0.00 +ATOM 3941 HW1 SOL 1236 21.600 10.720 2.550 1.00 0.00 +ATOM 3942 HW2 SOL 1236 21.840 9.270 2.190 1.00 0.00 +ATOM 3943 OW SOL 1237 44.950 25.080 23.960 1.00 0.00 +ATOM 3944 HW1 SOL 1237 45.330 24.200 23.880 1.00 0.00 +ATOM 3945 HW2 SOL 1237 44.570 25.260 23.100 1.00 0.00 +ATOM 3946 OW SOL 1238 35.280 5.100 15.730 1.00 0.00 +ATOM 3947 HW1 SOL 1238 36.180 5.240 16.030 1.00 0.00 +ATOM 3948 HW2 SOL 1238 35.380 4.660 14.880 1.00 0.00 +ATOM 3949 OW SOL 1239 19.210 13.140 18.910 1.00 0.00 +ATOM 3950 HW1 SOL 1239 18.840 13.910 19.330 1.00 0.00 +ATOM 3951 HW2 SOL 1239 18.810 12.400 19.360 1.00 0.00 +ATOM 3952 OW SOL 1240 42.110 30.450 26.860 1.00 0.00 +ATOM 3953 HW1 SOL 1240 41.570 31.090 27.320 1.00 0.00 +ATOM 3954 HW2 SOL 1240 42.200 29.720 27.490 1.00 0.00 +ATOM 3955 OW SOL 1241 25.020 14.380 24.340 1.00 0.00 +ATOM 3956 HW1 SOL 1241 25.350 13.600 23.900 1.00 0.00 +ATOM 3957 HW2 SOL 1241 25.400 15.110 23.850 1.00 0.00 +ATOM 3958 OW SOL 1242 43.350 37.100 25.610 1.00 0.00 +ATOM 3959 HW1 SOL 1242 43.900 37.550 24.970 1.00 0.00 +ATOM 3960 HW2 SOL 1242 42.460 37.200 25.270 1.00 0.00 +ATOM 3961 OW SOL 1243 41.670 6.580 14.050 1.00 0.00 +ATOM 3962 HW1 SOL 1243 41.130 5.950 14.520 1.00 0.00 +ATOM 3963 HW2 SOL 1243 42.570 6.380 14.340 1.00 0.00 +ATOM 3964 OW SOL 1244 12.790 41.470 8.640 1.00 0.00 +ATOM 3965 HW1 SOL 1244 11.860 41.280 8.570 1.00 0.00 +ATOM 3966 HW2 SOL 1244 13.170 40.700 9.060 1.00 0.00 +ATOM 3967 OW SOL 1245 17.240 11.690 2.280 1.00 0.00 +ATOM 3968 HW1 SOL 1245 17.070 11.910 3.200 1.00 0.00 +ATOM 3969 HW2 SOL 1245 16.390 11.430 1.930 1.00 0.00 +ATOM 3970 OW SOL 1246 3.250 2.570 3.150 1.00 0.00 +ATOM 3971 HW1 SOL 1246 2.730 1.950 3.670 1.00 0.00 +ATOM 3972 HW2 SOL 1246 3.340 2.150 2.290 1.00 0.00 +ATOM 3973 OW SOL 1247 43.110 35.880 10.130 1.00 0.00 +ATOM 3974 HW1 SOL 1247 43.070 35.000 10.480 1.00 0.00 +ATOM 3975 HW2 SOL 1247 42.840 36.440 10.860 1.00 0.00 +ATOM 3976 OW SOL 1248 35.240 43.260 11.310 1.00 0.00 +ATOM 3977 HW1 SOL 1248 35.650 43.070 12.150 1.00 0.00 +ATOM 3978 HW2 SOL 1248 34.760 44.080 11.450 1.00 0.00 +ATOM 3979 OW SOL 1249 24.970 34.470 12.100 1.00 0.00 +ATOM 3980 HW1 SOL 1249 24.960 33.630 11.640 1.00 0.00 +ATOM 3981 HW2 SOL 1249 24.060 34.600 12.390 1.00 0.00 +ATOM 3982 OW SOL 1250 27.730 34.180 29.720 1.00 0.00 +ATOM 3983 HW1 SOL 1250 27.570 34.850 30.380 1.00 0.00 +ATOM 3984 HW2 SOL 1250 26.920 33.680 29.690 1.00 0.00 +ATOM 3985 OW SOL 1251 13.760 26.960 8.090 1.00 0.00 +ATOM 3986 HW1 SOL 1251 14.350 27.590 7.680 1.00 0.00 +ATOM 3987 HW2 SOL 1251 14.330 26.230 8.330 1.00 0.00 +ATOM 3988 OW SOL 1252 18.300 32.700 31.980 1.00 0.00 +ATOM 3989 HW1 SOL 1252 17.750 33.070 32.670 1.00 0.00 +ATOM 3990 HW2 SOL 1252 19.190 32.740 32.330 1.00 0.00 +ATOM 3991 OW SOL 1253 12.710 4.220 18.050 1.00 0.00 +ATOM 3992 HW1 SOL 1253 12.640 3.270 18.110 1.00 0.00 +ATOM 3993 HW2 SOL 1253 13.240 4.480 18.800 1.00 0.00 +ATOM 3994 OW SOL 1254 8.400 16.890 2.000 1.00 0.00 +ATOM 3995 HW1 SOL 1254 8.740 16.470 2.800 1.00 0.00 +ATOM 3996 HW2 SOL 1254 8.120 17.760 2.290 1.00 0.00 +ATOM 3997 OW SOL 1255 13.860 40.390 19.350 1.00 0.00 +ATOM 3998 HW1 SOL 1255 13.880 39.980 18.480 1.00 0.00 +ATOM 3999 HW2 SOL 1255 14.530 39.920 19.850 1.00 0.00 +ATOM 4000 OW SOL 1256 26.970 18.320 30.220 1.00 0.00 +ATOM 4001 HW1 SOL 1256 27.740 18.870 30.370 1.00 0.00 +ATOM 4002 HW2 SOL 1256 26.650 18.120 31.090 1.00 0.00 +ATOM 4003 OW SOL 1257 35.450 37.010 11.180 1.00 0.00 +ATOM 4004 HW1 SOL 1257 36.170 37.580 11.460 1.00 0.00 +ATOM 4005 HW2 SOL 1257 34.800 37.620 10.830 1.00 0.00 +ATOM 4006 OW SOL 1258 0.020 10.950 2.290 1.00 0.00 +ATOM 4007 HW1 SOL 1258 0.010 11.870 2.030 1.00 0.00 +ATOM 4008 HW2 SOL 1258 0.930 10.680 2.180 1.00 0.00 +ATOM 4009 OW SOL 1259 31.080 38.340 27.890 1.00 0.00 +ATOM 4010 HW1 SOL 1259 31.890 38.330 28.410 1.00 0.00 +ATOM 4011 HW2 SOL 1259 30.910 37.420 27.700 1.00 0.00 +ATOM 4012 OW SOL 1260 42.390 45.330 21.070 1.00 0.00 +ATOM 4013 HW1 SOL 1260 41.640 44.810 20.790 1.00 0.00 +ATOM 4014 HW2 SOL 1260 42.890 44.750 21.650 1.00 0.00 +ATOM 4015 OW SOL 1261 4.550 36.430 1.060 1.00 0.00 +ATOM 4016 HW1 SOL 1261 5.090 36.500 0.280 1.00 0.00 +ATOM 4017 HW2 SOL 1261 3.660 36.340 0.730 1.00 0.00 +ATOM 4018 OW SOL 1262 6.560 32.670 15.700 1.00 0.00 +ATOM 4019 HW1 SOL 1262 6.900 32.630 16.600 1.00 0.00 +ATOM 4020 HW2 SOL 1262 5.940 31.950 15.650 1.00 0.00 +ATOM 4021 OW SOL 1263 2.240 17.230 3.710 1.00 0.00 +ATOM 4022 HW1 SOL 1263 1.570 16.570 3.920 1.00 0.00 +ATOM 4023 HW2 SOL 1263 2.310 17.760 4.500 1.00 0.00 +ATOM 4024 OW SOL 1264 34.910 40.000 25.580 1.00 0.00 +ATOM 4025 HW1 SOL 1264 35.200 40.770 25.100 1.00 0.00 +ATOM 4026 HW2 SOL 1264 35.660 39.750 26.120 1.00 0.00 +ATOM 4027 OW SOL 1265 7.090 26.080 11.620 1.00 0.00 +ATOM 4028 HW1 SOL 1265 7.960 25.940 12.000 1.00 0.00 +ATOM 4029 HW2 SOL 1265 6.560 25.370 11.980 1.00 0.00 +ATOM 4030 OW SOL 1266 4.490 27.490 31.380 1.00 0.00 +ATOM 4031 HW1 SOL 1266 4.360 27.710 32.310 1.00 0.00 +ATOM 4032 HW2 SOL 1266 3.960 28.120 30.910 1.00 0.00 +ATOM 4033 OW SOL 1267 35.680 26.730 29.310 1.00 0.00 +ATOM 4034 HW1 SOL 1267 35.940 26.450 28.430 1.00 0.00 +ATOM 4035 HW2 SOL 1267 35.410 27.640 29.200 1.00 0.00 +ATOM 4036 OW SOL 1268 32.990 20.100 27.280 1.00 0.00 +ATOM 4037 HW1 SOL 1268 33.370 20.970 27.400 1.00 0.00 +ATOM 4038 HW2 SOL 1268 33.030 19.940 26.330 1.00 0.00 +ATOM 4039 OW SOL 1269 41.860 21.600 6.910 1.00 0.00 +ATOM 4040 HW1 SOL 1269 41.850 20.760 7.360 1.00 0.00 +ATOM 4041 HW2 SOL 1269 40.950 21.750 6.650 1.00 0.00 +ATOM 4042 OW SOL 1270 3.580 40.810 14.870 1.00 0.00 +ATOM 4043 HW1 SOL 1270 2.710 40.730 14.500 1.00 0.00 +ATOM 4044 HW2 SOL 1270 3.450 41.230 15.720 1.00 0.00 +ATOM 4045 OW SOL 1271 4.670 15.560 23.920 1.00 0.00 +ATOM 4046 HW1 SOL 1271 4.580 16.510 23.810 1.00 0.00 +ATOM 4047 HW2 SOL 1271 5.010 15.250 23.080 1.00 0.00 +ATOM 4048 OW SOL 1272 1.450 9.170 16.090 1.00 0.00 +ATOM 4049 HW1 SOL 1272 0.660 8.970 16.600 1.00 0.00 +ATOM 4050 HW2 SOL 1272 2.170 9.060 16.700 1.00 0.00 +ATOM 4051 OW SOL 1273 23.110 21.530 21.120 1.00 0.00 +ATOM 4052 HW1 SOL 1273 23.780 21.860 21.730 1.00 0.00 +ATOM 4053 HW2 SOL 1273 23.580 20.890 20.580 1.00 0.00 +ATOM 4054 OW SOL 1274 41.430 1.190 9.570 1.00 0.00 +ATOM 4055 HW1 SOL 1274 41.530 1.040 8.630 1.00 0.00 +ATOM 4056 HW2 SOL 1274 41.890 0.450 9.980 1.00 0.00 +ATOM 4057 OW SOL 1275 30.380 23.770 30.680 1.00 0.00 +ATOM 4058 HW1 SOL 1275 30.900 23.030 30.360 1.00 0.00 +ATOM 4059 HW2 SOL 1275 30.840 24.060 31.470 1.00 0.00 +ATOM 4060 OW SOL 1276 36.820 42.990 4.400 1.00 0.00 +ATOM 4061 HW1 SOL 1276 37.100 43.710 3.840 1.00 0.00 +ATOM 4062 HW2 SOL 1276 36.140 42.540 3.890 1.00 0.00 +ATOM 4063 OW SOL 1277 43.780 15.530 30.640 1.00 0.00 +ATOM 4064 HW1 SOL 1277 44.250 14.830 30.180 1.00 0.00 +ATOM 4065 HW2 SOL 1277 43.550 15.140 31.490 1.00 0.00 +ATOM 4066 OW SOL 1278 27.840 28.680 27.690 1.00 0.00 +ATOM 4067 HW1 SOL 1278 27.850 28.360 28.590 1.00 0.00 +ATOM 4068 HW2 SOL 1278 26.930 28.590 27.420 1.00 0.00 +ATOM 4069 OW SOL 1279 11.000 7.780 9.480 1.00 0.00 +ATOM 4070 HW1 SOL 1279 10.250 7.820 10.070 1.00 0.00 +ATOM 4071 HW2 SOL 1279 11.670 8.310 9.920 1.00 0.00 +ATOM 4072 OW SOL 1280 17.800 35.570 16.770 1.00 0.00 +ATOM 4073 HW1 SOL 1280 18.440 35.220 16.150 1.00 0.00 +ATOM 4074 HW2 SOL 1280 17.490 36.380 16.370 1.00 0.00 +ATOM 4075 OW SOL 1281 1.310 41.460 16.480 1.00 0.00 +ATOM 4076 HW1 SOL 1281 0.620 40.870 16.180 1.00 0.00 +ATOM 4077 HW2 SOL 1281 1.140 42.280 16.010 1.00 0.00 +ATOM 4078 OW SOL 1282 5.850 7.650 18.590 1.00 0.00 +ATOM 4079 HW1 SOL 1282 5.710 7.140 17.790 1.00 0.00 +ATOM 4080 HW2 SOL 1282 6.520 7.160 19.070 1.00 0.00 +ATOM 4081 OW SOL 1283 12.750 15.660 12.570 1.00 0.00 +ATOM 4082 HW1 SOL 1283 12.070 15.250 12.030 1.00 0.00 +ATOM 4083 HW2 SOL 1283 12.260 16.160 13.230 1.00 0.00 +ATOM 4084 OW SOL 1284 40.430 0.140 24.970 1.00 0.00 +ATOM 4085 HW1 SOL 1284 40.770 1.000 25.210 1.00 0.00 +ATOM 4086 HW2 SOL 1284 41.210 -0.390 24.810 1.00 0.00 +ATOM 4087 OW SOL 1285 44.830 23.520 18.780 1.00 0.00 +ATOM 4088 HW1 SOL 1285 45.090 24.100 19.490 1.00 0.00 +ATOM 4089 HW2 SOL 1285 44.840 24.080 18.000 1.00 0.00 +ATOM 4090 OW SOL 1286 15.110 16.020 2.570 1.00 0.00 +ATOM 4091 HW1 SOL 1286 15.190 16.800 3.110 1.00 0.00 +ATOM 4092 HW2 SOL 1286 14.440 16.240 1.920 1.00 0.00 +ATOM 4093 OW SOL 1287 40.240 15.980 22.450 1.00 0.00 +ATOM 4094 HW1 SOL 1287 40.700 15.680 23.240 1.00 0.00 +ATOM 4095 HW2 SOL 1287 39.780 15.210 22.130 1.00 0.00 +ATOM 4096 OW SOL 1288 8.180 19.520 15.340 1.00 0.00 +ATOM 4097 HW1 SOL 1288 7.510 18.850 15.240 1.00 0.00 +ATOM 4098 HW2 SOL 1288 8.830 19.120 15.920 1.00 0.00 +ATOM 4099 OW SOL 1289 5.290 19.470 25.140 1.00 0.00 +ATOM 4100 HW1 SOL 1289 4.440 19.060 25.260 1.00 0.00 +ATOM 4101 HW2 SOL 1289 5.920 18.750 25.180 1.00 0.00 +ATOM 4102 OW SOL 1290 5.310 26.810 5.570 1.00 0.00 +ATOM 4103 HW1 SOL 1290 6.240 26.600 5.650 1.00 0.00 +ATOM 4104 HW2 SOL 1290 5.050 27.070 6.450 1.00 0.00 +ATOM 4105 OW SOL 1291 31.070 17.120 30.880 1.00 0.00 +ATOM 4106 HW1 SOL 1291 30.190 16.950 31.230 1.00 0.00 +ATOM 4107 HW2 SOL 1291 31.140 16.530 30.120 1.00 0.00 +ATOM 4108 OW SOL 1292 17.880 20.300 5.460 1.00 0.00 +ATOM 4109 HW1 SOL 1292 18.470 20.270 4.710 1.00 0.00 +ATOM 4110 HW2 SOL 1292 17.160 20.860 5.180 1.00 0.00 +ATOM 4111 OW SOL 1293 15.040 32.050 32.050 1.00 0.00 +ATOM 4112 HW1 SOL 1293 15.210 31.800 31.140 1.00 0.00 +ATOM 4113 HW2 SOL 1293 14.190 32.500 32.030 1.00 0.00 +ATOM 4114 OW SOL 1294 17.500 29.000 27.060 1.00 0.00 +ATOM 4115 HW1 SOL 1294 17.270 29.920 26.930 1.00 0.00 +ATOM 4116 HW2 SOL 1294 16.710 28.610 27.440 1.00 0.00 +ATOM 4117 OW SOL 1295 1.940 30.600 22.870 1.00 0.00 +ATOM 4118 HW1 SOL 1295 2.820 30.310 22.660 1.00 0.00 +ATOM 4119 HW2 SOL 1295 1.420 30.360 22.110 1.00 0.00 +ATOM 4120 OW SOL 1296 33.150 9.950 28.600 1.00 0.00 +ATOM 4121 HW1 SOL 1296 33.800 9.320 28.270 1.00 0.00 +ATOM 4122 HW2 SOL 1296 33.630 10.490 29.230 1.00 0.00 +ATOM 4123 OW SOL 1297 42.670 25.960 18.830 1.00 0.00 +ATOM 4124 HW1 SOL 1297 43.540 26.180 18.520 1.00 0.00 +ATOM 4125 HW2 SOL 1297 42.680 26.150 19.760 1.00 0.00 +ATOM 4126 OW SOL 1298 26.780 36.190 21.150 1.00 0.00 +ATOM 4127 HW1 SOL 1298 27.280 36.040 21.960 1.00 0.00 +ATOM 4128 HW2 SOL 1298 27.360 35.890 20.450 1.00 0.00 +ATOM 4129 OW SOL 1299 35.560 26.660 18.770 1.00 0.00 +ATOM 4130 HW1 SOL 1299 36.140 25.900 18.660 1.00 0.00 +ATOM 4131 HW2 SOL 1299 35.840 27.050 19.600 1.00 0.00 +ATOM 4132 OW SOL 1300 23.660 2.500 21.590 1.00 0.00 +ATOM 4133 HW1 SOL 1300 24.020 1.620 21.700 1.00 0.00 +ATOM 4134 HW2 SOL 1300 23.160 2.460 20.770 1.00 0.00 +ATOM 4135 OW SOL 1301 19.180 20.160 0.170 1.00 0.00 +ATOM 4136 HW1 SOL 1301 18.780 19.550 0.790 1.00 0.00 +ATOM 4137 HW2 SOL 1301 20.110 20.180 0.420 1.00 0.00 +ATOM 4138 OW SOL 1302 26.030 43.940 5.750 1.00 0.00 +ATOM 4139 HW1 SOL 1302 26.640 44.530 6.200 1.00 0.00 +ATOM 4140 HW2 SOL 1302 26.150 44.150 4.820 1.00 0.00 +ATOM 4141 OW SOL 1303 13.720 14.830 0.540 1.00 0.00 +ATOM 4142 HW1 SOL 1303 13.190 15.580 0.300 1.00 0.00 +ATOM 4143 HW2 SOL 1303 14.530 14.930 0.030 1.00 0.00 +ATOM 4144 OW SOL 1304 21.760 30.510 8.550 1.00 0.00 +ATOM 4145 HW1 SOL 1304 22.140 31.150 7.950 1.00 0.00 +ATOM 4146 HW2 SOL 1304 21.500 29.780 7.980 1.00 0.00 +ATOM 4147 OW SOL 1305 6.770 27.040 27.660 1.00 0.00 +ATOM 4148 HW1 SOL 1305 6.710 27.750 28.290 1.00 0.00 +ATOM 4149 HW2 SOL 1305 7.710 26.960 27.490 1.00 0.00 +ATOM 4150 OW SOL 1306 32.570 19.180 31.980 1.00 0.00 +ATOM 4151 HW1 SOL 1306 31.930 19.440 32.640 1.00 0.00 +ATOM 4152 HW2 SOL 1306 32.070 18.650 31.360 1.00 0.00 +ATOM 4153 OW SOL 1307 16.460 6.460 11.080 1.00 0.00 +ATOM 4154 HW1 SOL 1307 17.370 6.660 11.290 1.00 0.00 +ATOM 4155 HW2 SOL 1307 15.960 6.820 11.810 1.00 0.00 +ATOM 4156 OW SOL 1308 30.330 39.870 5.170 1.00 0.00 +ATOM 4157 HW1 SOL 1308 30.570 40.110 6.070 1.00 0.00 +ATOM 4158 HW2 SOL 1308 30.640 40.610 4.640 1.00 0.00 +ATOM 4159 OW SOL 1309 44.200 43.280 2.610 1.00 0.00 +ATOM 4160 HW1 SOL 1309 43.790 42.860 1.850 1.00 0.00 +ATOM 4161 HW2 SOL 1309 45.070 43.530 2.300 1.00 0.00 +ATOM 4162 OW SOL 1310 14.680 7.420 15.140 1.00 0.00 +ATOM 4163 HW1 SOL 1310 13.900 6.870 15.050 1.00 0.00 +ATOM 4164 HW2 SOL 1310 15.170 7.030 15.860 1.00 0.00 +ATOM 4165 OW SOL 1311 30.080 29.480 17.040 1.00 0.00 +ATOM 4166 HW1 SOL 1311 30.000 30.400 17.280 1.00 0.00 +ATOM 4167 HW2 SOL 1311 29.880 29.450 16.100 1.00 0.00 +ATOM 4168 OW SOL 1312 17.230 0.260 2.550 1.00 0.00 +ATOM 4169 HW1 SOL 1312 17.310 0.800 3.340 1.00 0.00 +ATOM 4170 HW2 SOL 1312 18.100 -0.120 2.430 1.00 0.00 +ATOM 4171 OW SOL 1313 42.580 5.180 2.460 1.00 0.00 +ATOM 4172 HW1 SOL 1313 42.130 5.980 2.720 1.00 0.00 +ATOM 4173 HW2 SOL 1313 43.440 5.470 2.150 1.00 0.00 +ATOM 4174 OW SOL 1314 32.150 5.540 3.020 1.00 0.00 +ATOM 4175 HW1 SOL 1314 32.960 5.170 2.670 1.00 0.00 +ATOM 4176 HW2 SOL 1314 32.430 6.300 3.540 1.00 0.00 +ATOM 4177 OW SOL 1315 23.860 28.720 20.060 1.00 0.00 +ATOM 4178 HW1 SOL 1315 23.360 28.690 20.870 1.00 0.00 +ATOM 4179 HW2 SOL 1315 23.280 29.170 19.440 1.00 0.00 +ATOM 4180 OW SOL 1316 13.190 12.080 10.730 1.00 0.00 +ATOM 4181 HW1 SOL 1316 14.040 11.970 10.300 1.00 0.00 +ATOM 4182 HW2 SOL 1316 12.730 11.250 10.570 1.00 0.00 +ATOM 4183 OW SOL 1317 27.400 44.260 30.650 1.00 0.00 +ATOM 4184 HW1 SOL 1317 27.650 43.370 30.880 1.00 0.00 +ATOM 4185 HW2 SOL 1317 27.840 44.430 29.820 1.00 0.00 +ATOM 4186 OW SOL 1318 34.220 34.840 26.900 1.00 0.00 +ATOM 4187 HW1 SOL 1318 34.630 35.620 26.510 1.00 0.00 +ATOM 4188 HW2 SOL 1318 33.350 35.150 27.170 1.00 0.00 +ATOM 4189 OW SOL 1319 26.210 2.640 17.040 1.00 0.00 +ATOM 4190 HW1 SOL 1319 25.380 2.170 16.960 1.00 0.00 +ATOM 4191 HW2 SOL 1319 26.370 2.700 17.980 1.00 0.00 +ATOM 4192 OW SOL 1320 2.820 22.120 1.170 1.00 0.00 +ATOM 4193 HW1 SOL 1320 2.430 22.830 0.670 1.00 0.00 +ATOM 4194 HW2 SOL 1320 2.980 21.430 0.520 1.00 0.00 +ATOM 4195 OW SOL 1321 30.280 17.860 5.760 1.00 0.00 +ATOM 4196 HW1 SOL 1321 30.520 17.630 4.870 1.00 0.00 +ATOM 4197 HW2 SOL 1321 30.300 18.820 5.780 1.00 0.00 +ATOM 4198 OW SOL 1322 1.330 2.950 20.990 1.00 0.00 +ATOM 4199 HW1 SOL 1322 0.420 2.720 21.200 1.00 0.00 +ATOM 4200 HW2 SOL 1322 1.280 3.360 20.130 1.00 0.00 +ATOM 4201 OW SOL 1323 14.440 10.560 4.000 1.00 0.00 +ATOM 4202 HW1 SOL 1323 14.650 10.660 3.070 1.00 0.00 +ATOM 4203 HW2 SOL 1323 14.290 11.450 4.310 1.00 0.00 +ATOM 4204 OW SOL 1324 29.220 19.950 7.650 1.00 0.00 +ATOM 4205 HW1 SOL 1324 28.310 19.750 7.430 1.00 0.00 +ATOM 4206 HW2 SOL 1324 29.650 19.090 7.680 1.00 0.00 +ATOM 4207 OW SOL 1325 5.360 19.070 20.840 1.00 0.00 +ATOM 4208 HW1 SOL 1325 4.470 18.770 20.630 1.00 0.00 +ATOM 4209 HW2 SOL 1325 5.640 19.550 20.060 1.00 0.00 +ATOM 4210 OW SOL 1326 34.120 8.080 22.640 1.00 0.00 +ATOM 4211 HW1 SOL 1326 34.300 7.310 22.100 1.00 0.00 +ATOM 4212 HW2 SOL 1326 33.200 8.270 22.480 1.00 0.00 +ATOM 4213 OW SOL 1327 18.510 32.520 8.030 1.00 0.00 +ATOM 4214 HW1 SOL 1327 19.020 31.950 7.450 1.00 0.00 +ATOM 4215 HW2 SOL 1327 19.050 33.300 8.130 1.00 0.00 +ATOM 4216 OW SOL 1328 14.090 1.280 3.190 1.00 0.00 +ATOM 4217 HW1 SOL 1328 13.480 0.670 3.590 1.00 0.00 +ATOM 4218 HW2 SOL 1328 14.260 0.930 2.320 1.00 0.00 +ATOM 4219 OW SOL 1329 0.950 3.120 7.910 1.00 0.00 +ATOM 4220 HW1 SOL 1329 0.590 3.360 7.050 1.00 0.00 +ATOM 4221 HW2 SOL 1329 1.890 3.010 7.750 1.00 0.00 +ATOM 4222 OW SOL 1330 -2.367 18.480 32.050 1.00 0.00 +ATOM 4223 HW1 SOL 1330 -1.687 19.000 32.480 1.00 0.00 +ATOM 4224 HW2 SOL 1330 -2.697 17.890 32.730 1.00 0.00 +ATOM 4225 OW SOL 1331 28.620 20.740 10.180 1.00 0.00 +ATOM 4226 HW1 SOL 1331 29.040 21.440 10.680 1.00 0.00 +ATOM 4227 HW2 SOL 1331 29.060 20.750 9.330 1.00 0.00 +ATOM 4228 OW SOL 1332 45.110 18.980 18.200 1.00 0.00 +ATOM 4229 HW1 SOL 1332 44.590 19.590 17.670 1.00 0.00 +ATOM 4230 HW2 SOL 1332 45.440 19.500 18.920 1.00 0.00 +ATOM 4231 OW SOL 1333 47.057 38.300 9.050 1.00 0.00 +ATOM 4232 HW1 SOL 1333 47.067 39.210 8.770 1.00 0.00 +ATOM 4233 HW2 SOL 1333 46.617 37.830 8.340 1.00 0.00 +ATOM 4234 OW SOL 1334 13.620 11.350 7.630 1.00 0.00 +ATOM 4235 HW1 SOL 1334 12.850 11.510 8.180 1.00 0.00 +ATOM 4236 HW2 SOL 1334 13.480 10.480 7.270 1.00 0.00 +ATOM 4237 OW SOL 1335 9.550 15.370 30.350 1.00 0.00 +ATOM 4238 HW1 SOL 1335 8.720 14.890 30.350 1.00 0.00 +ATOM 4239 HW2 SOL 1335 9.300 16.270 30.140 1.00 0.00 +ATOM 4240 OW SOL 1336 2.760 0.140 4.280 1.00 0.00 +ATOM 4241 HW1 SOL 1336 2.180 -0.460 4.750 1.00 0.00 +ATOM 4242 HW2 SOL 1336 3.570 0.140 4.790 1.00 0.00 +ATOM 4243 OW SOL 1337 2.610 13.470 6.030 1.00 0.00 +ATOM 4244 HW1 SOL 1337 1.980 13.770 6.690 1.00 0.00 +ATOM 4245 HW2 SOL 1337 3.370 14.040 6.140 1.00 0.00 +ATOM 4246 OW SOL 1338 12.770 29.440 31.130 1.00 0.00 +ATOM 4247 HW1 SOL 1338 12.980 30.050 30.420 1.00 0.00 +ATOM 4248 HW2 SOL 1338 11.810 29.420 31.150 1.00 0.00 +ATOM 4249 OW SOL 1339 44.549 42.349 33.218 1.00 0.00 +ATOM 4250 HW1 SOL 1339 45.479 42.119 33.238 1.00 0.00 +ATOM 4251 HW2 SOL 1339 44.469 43.069 33.838 1.00 0.00 +ATOM 4252 OW SOL 1340 24.810 29.150 26.910 1.00 0.00 +ATOM 4253 HW1 SOL 1340 24.130 29.390 26.280 1.00 0.00 +ATOM 4254 HW2 SOL 1340 24.340 28.690 27.610 1.00 0.00 +ATOM 4255 OW SOL 1341 23.060 11.950 9.820 1.00 0.00 +ATOM 4256 HW1 SOL 1341 22.790 11.080 9.550 1.00 0.00 +ATOM 4257 HW2 SOL 1341 23.840 11.810 10.350 1.00 0.00 +ATOM 4258 OW SOL 1342 10.200 9.350 23.620 1.00 0.00 +ATOM 4259 HW1 SOL 1342 9.530 9.780 23.080 1.00 0.00 +ATOM 4260 HW2 SOL 1342 10.000 8.420 23.560 1.00 0.00 +ATOM 4261 OW SOL 1343 6.840 5.650 29.950 1.00 0.00 +ATOM 4262 HW1 SOL 1343 6.630 6.490 29.540 1.00 0.00 +ATOM 4263 HW2 SOL 1343 7.370 5.880 30.720 1.00 0.00 +ATOM 4264 OW SOL 1344 8.650 12.650 2.120 1.00 0.00 +ATOM 4265 HW1 SOL 1344 8.430 13.410 2.650 1.00 0.00 +ATOM 4266 HW2 SOL 1344 7.840 12.420 1.660 1.00 0.00 +ATOM 4267 OW SOL 1345 45.230 3.940 18.190 1.00 0.00 +ATOM 4268 HW1 SOL 1345 44.360 4.290 18.010 1.00 0.00 +ATOM 4269 HW2 SOL 1345 45.810 4.690 18.080 1.00 0.00 +ATOM 4270 OW SOL 1346 44.040 15.060 3.120 1.00 0.00 +ATOM 4271 HW1 SOL 1346 43.100 15.060 2.960 1.00 0.00 +ATOM 4272 HW2 SOL 1346 44.130 15.430 4.000 1.00 0.00 +ATOM 4273 OW SOL 1347 28.250 26.480 3.440 1.00 0.00 +ATOM 4274 HW1 SOL 1347 27.680 26.890 2.790 1.00 0.00 +ATOM 4275 HW2 SOL 1347 28.340 25.570 3.140 1.00 0.00 +ATOM 4276 OW SOL 1348 41.940 36.920 0.640 1.00 0.00 +ATOM 4277 HW1 SOL 1348 41.290 37.380 0.100 1.00 0.00 +ATOM 4278 HW2 SOL 1348 41.660 36.010 0.630 1.00 0.00 +ATOM 4279 OW SOL 1349 41.009 8.171 -2.108 1.00 0.00 +ATOM 4280 HW1 SOL 1349 41.129 8.721 -1.338 1.00 0.00 +ATOM 4281 HW2 SOL 1349 41.699 8.441 -2.708 1.00 0.00 +ATOM 4282 OW SOL 1350 14.600 25.960 18.800 1.00 0.00 +ATOM 4283 HW1 SOL 1350 14.790 25.180 19.310 1.00 0.00 +ATOM 4284 HW2 SOL 1350 13.660 25.900 18.620 1.00 0.00 +ATOM 4285 OW SOL 1351 11.270 14.280 6.540 1.00 0.00 +ATOM 4286 HW1 SOL 1351 10.350 14.420 6.740 1.00 0.00 +ATOM 4287 HW2 SOL 1351 11.310 14.260 5.580 1.00 0.00 +ATOM 4288 OW SOL 1352 13.280 35.140 25.230 1.00 0.00 +ATOM 4289 HW1 SOL 1352 13.780 34.420 25.630 1.00 0.00 +ATOM 4290 HW2 SOL 1352 13.650 35.230 24.350 1.00 0.00 +ATOM 4291 OW SOL 1353 29.690 28.480 4.350 1.00 0.00 +ATOM 4292 HW1 SOL 1353 29.120 27.730 4.220 1.00 0.00 +ATOM 4293 HW2 SOL 1353 29.290 29.180 3.840 1.00 0.00 +ATOM 4294 OW SOL 1354 31.510 9.670 20.030 1.00 0.00 +ATOM 4295 HW1 SOL 1354 32.300 9.900 19.550 1.00 0.00 +ATOM 4296 HW2 SOL 1354 30.840 9.540 19.360 1.00 0.00 +ATOM 4297 OW SOL 1355 12.760 5.320 15.600 1.00 0.00 +ATOM 4298 HW1 SOL 1355 12.580 5.060 16.510 1.00 0.00 +ATOM 4299 HW2 SOL 1355 12.700 4.500 15.100 1.00 0.00 +ATOM 4300 OW SOL 1356 22.650 41.560 30.850 1.00 0.00 +ATOM 4301 HW1 SOL 1356 23.030 42.210 31.450 1.00 0.00 +ATOM 4302 HW2 SOL 1356 22.260 40.910 31.430 1.00 0.00 +ATOM 4303 OW SOL 1357 41.860 35.240 27.730 1.00 0.00 +ATOM 4304 HW1 SOL 1357 42.010 35.990 28.310 1.00 0.00 +ATOM 4305 HW2 SOL 1357 41.070 35.480 27.240 1.00 0.00 +ATOM 4306 OW SOL 1358 32.210 15.590 17.710 1.00 0.00 +ATOM 4307 HW1 SOL 1358 32.590 15.450 18.580 1.00 0.00 +ATOM 4308 HW2 SOL 1358 31.580 16.290 17.840 1.00 0.00 +ATOM 4309 OW SOL 1359 1.280 13.030 23.370 1.00 0.00 +ATOM 4310 HW1 SOL 1359 2.080 13.370 22.970 1.00 0.00 +ATOM 4311 HW2 SOL 1359 0.830 12.570 22.660 1.00 0.00 +ATOM 4312 OW SOL 1360 24.010 38.670 29.160 1.00 0.00 +ATOM 4313 HW1 SOL 1360 24.260 38.070 29.860 1.00 0.00 +ATOM 4314 HW2 SOL 1360 23.080 38.480 29.000 1.00 0.00 +ATOM 4315 OW SOL 1361 19.960 12.060 16.170 1.00 0.00 +ATOM 4316 HW1 SOL 1361 19.800 12.290 17.090 1.00 0.00 +ATOM 4317 HW2 SOL 1361 20.540 11.310 16.210 1.00 0.00 +ATOM 4318 OW SOL 1362 44.170 38.930 15.350 1.00 0.00 +ATOM 4319 HW1 SOL 1362 43.370 38.410 15.470 1.00 0.00 +ATOM 4320 HW2 SOL 1362 44.790 38.320 14.950 1.00 0.00 +ATOM 4321 OW SOL 1363 31.310 11.370 31.260 1.00 0.00 +ATOM 4322 HW1 SOL 1363 31.250 10.440 31.010 1.00 0.00 +ATOM 4323 HW2 SOL 1363 30.480 11.550 31.700 1.00 0.00 +ATOM 4324 OW SOL 1364 17.590 16.110 7.110 1.00 0.00 +ATOM 4325 HW1 SOL 1364 18.110 16.840 7.450 1.00 0.00 +ATOM 4326 HW2 SOL 1364 16.690 16.330 7.340 1.00 0.00 +ATOM 4327 OW SOL 1365 9.020 9.480 10.700 1.00 0.00 +ATOM 4328 HW1 SOL 1365 8.230 9.740 11.170 1.00 0.00 +ATOM 4329 HW2 SOL 1365 8.690 8.950 9.970 1.00 0.00 +ATOM 4330 OW SOL 1366 7.970 1.080 18.350 1.00 0.00 +ATOM 4331 HW1 SOL 1366 8.370 0.320 18.760 1.00 0.00 +ATOM 4332 HW2 SOL 1366 8.670 1.730 18.310 1.00 0.00 +ATOM 4333 OW SOL 1367 41.150 -0.257 1.240 1.00 0.00 +ATOM 4334 HW1 SOL 1367 40.670 -0.997 1.630 1.00 0.00 +ATOM 4335 HW2 SOL 1367 41.290 0.343 1.970 1.00 0.00 +ATOM 4336 OW SOL 1368 28.730 35.590 1.020 1.00 0.00 +ATOM 4337 HW1 SOL 1368 29.420 34.920 1.030 1.00 0.00 +ATOM 4338 HW2 SOL 1368 29.150 36.360 0.640 1.00 0.00 +ATOM 4339 OW SOL 1369 33.200 18.430 19.330 1.00 0.00 +ATOM 4340 HW1 SOL 1369 33.770 19.150 19.040 1.00 0.00 +ATOM 4341 HW2 SOL 1369 32.320 18.720 19.110 1.00 0.00 +ATOM 4342 OW SOL 1370 37.260 19.030 20.050 1.00 0.00 +ATOM 4343 HW1 SOL 1370 36.570 19.340 19.470 1.00 0.00 +ATOM 4344 HW2 SOL 1370 36.820 18.420 20.650 1.00 0.00 +ATOM 4345 OW SOL 1371 36.040 45.140 19.960 1.00 0.00 +ATOM 4346 HW1 SOL 1371 36.730 44.880 19.360 1.00 0.00 +ATOM 4347 HW2 SOL 1371 35.280 44.630 19.690 1.00 0.00 +ATOM 4348 OW SOL 1372 44.920 12.100 21.090 1.00 0.00 +ATOM 4349 HW1 SOL 1372 45.560 12.440 20.460 1.00 0.00 +ATOM 4350 HW2 SOL 1372 44.080 12.180 20.640 1.00 0.00 +ATOM 4351 OW SOL 1373 17.660 40.290 8.460 1.00 0.00 +ATOM 4352 HW1 SOL 1373 18.340 40.150 9.120 1.00 0.00 +ATOM 4353 HW2 SOL 1373 17.740 41.220 8.230 1.00 0.00 +ATOM 4354 OW SOL 1374 0.470 44.470 31.600 1.00 0.00 +ATOM 4355 HW1 SOL 1374 0.280 43.860 32.320 1.00 0.00 +ATOM 4356 HW2 SOL 1374 1.390 44.310 31.390 1.00 0.00 +ATOM 4357 OW SOL 1375 16.860 46.687 31.670 1.00 0.00 +ATOM 4358 HW1 SOL 1375 16.390 47.507 31.530 1.00 0.00 +ATOM 4359 HW2 SOL 1375 17.380 46.567 30.880 1.00 0.00 +ATOM 4360 OW SOL 1376 15.900 50.637 5.630 1.00 0.00 +ATOM 4361 HW1 SOL 1376 15.220 51.307 5.700 1.00 0.00 +ATOM 4362 HW2 SOL 1376 16.320 50.627 6.490 1.00 0.00 +ATOM 4363 OW SOL 1377 13.950 18.710 21.680 1.00 0.00 +ATOM 4364 HW1 SOL 1377 14.420 19.540 21.800 1.00 0.00 +ATOM 4365 HW2 SOL 1377 14.170 18.440 20.790 1.00 0.00 +ATOM 4366 OW SOL 1378 27.200 35.730 3.560 1.00 0.00 +ATOM 4367 HW1 SOL 1378 27.670 35.720 2.720 1.00 0.00 +ATOM 4368 HW2 SOL 1378 26.860 36.620 3.630 1.00 0.00 +ATOM 4369 OW SOL 1379 31.210 26.320 11.430 1.00 0.00 +ATOM 4370 HW1 SOL 1379 31.500 25.780 10.700 1.00 0.00 +ATOM 4371 HW2 SOL 1379 30.270 26.150 11.490 1.00 0.00 +ATOM 4372 OW SOL 1380 13.870 23.160 6.420 1.00 0.00 +ATOM 4373 HW1 SOL 1380 14.360 23.860 6.850 1.00 0.00 +ATOM 4374 HW2 SOL 1380 14.310 22.360 6.690 1.00 0.00 +ATOM 4375 OW SOL 1381 34.020 3.320 8.140 1.00 0.00 +ATOM 4376 HW1 SOL 1381 33.990 3.320 9.100 1.00 0.00 +ATOM 4377 HW2 SOL 1381 34.920 3.540 7.930 1.00 0.00 +ATOM 4378 OW SOL 1382 40.540 43.350 8.570 1.00 0.00 +ATOM 4379 HW1 SOL 1382 39.780 43.890 8.360 1.00 0.00 +ATOM 4380 HW2 SOL 1382 41.290 43.900 8.360 1.00 0.00 +ATOM 4381 OW SOL 1383 21.430 3.240 26.330 1.00 0.00 +ATOM 4382 HW1 SOL 1383 21.850 3.980 26.770 1.00 0.00 +ATOM 4383 HW2 SOL 1383 21.820 2.470 26.730 1.00 0.00 +ATOM 4384 OW SOL 1384 26.870 34.710 7.390 1.00 0.00 +ATOM 4385 HW1 SOL 1384 26.700 35.490 6.870 1.00 0.00 +ATOM 4386 HW2 SOL 1384 27.360 34.130 6.810 1.00 0.00 +ATOM 4387 OW SOL 1385 3.430 7.780 27.610 1.00 0.00 +ATOM 4388 HW1 SOL 1385 3.730 7.800 28.520 1.00 0.00 +ATOM 4389 HW2 SOL 1385 4.190 7.470 27.120 1.00 0.00 +ATOM 4390 OW SOL 1386 14.430 33.470 14.980 1.00 0.00 +ATOM 4391 HW1 SOL 1386 13.930 33.530 14.160 1.00 0.00 +ATOM 4392 HW2 SOL 1386 14.310 34.320 15.390 1.00 0.00 +ATOM 4393 OW SOL 1387 17.700 39.750 18.100 1.00 0.00 +ATOM 4394 HW1 SOL 1387 18.240 40.300 18.670 1.00 0.00 +ATOM 4395 HW2 SOL 1387 17.080 40.370 17.690 1.00 0.00 +ATOM 4396 OW SOL 1388 24.990 25.050 5.820 1.00 0.00 +ATOM 4397 HW1 SOL 1388 24.130 24.640 5.690 1.00 0.00 +ATOM 4398 HW2 SOL 1388 24.790 25.880 6.260 1.00 0.00 +ATOM 4399 OW SOL 1389 13.000 21.970 14.070 1.00 0.00 +ATOM 4400 HW1 SOL 1389 13.420 21.280 14.600 1.00 0.00 +ATOM 4401 HW2 SOL 1389 12.580 22.530 14.720 1.00 0.00 +ATOM 4402 OW SOL 1390 11.910 7.680 3.200 1.00 0.00 +ATOM 4403 HW1 SOL 1390 11.640 8.200 3.960 1.00 0.00 +ATOM 4404 HW2 SOL 1390 11.670 8.220 2.440 1.00 0.00 +ATOM 4405 OW SOL 1391 7.280 42.430 12.660 1.00 0.00 +ATOM 4406 HW1 SOL 1391 8.050 41.940 12.950 1.00 0.00 +ATOM 4407 HW2 SOL 1391 6.550 41.830 12.780 1.00 0.00 +ATOM 4408 OW SOL 1392 3.000 4.640 19.330 1.00 0.00 +ATOM 4409 HW1 SOL 1392 3.460 4.100 18.690 1.00 0.00 +ATOM 4410 HW2 SOL 1392 2.590 5.340 18.820 1.00 0.00 +ATOM 4411 OW SOL 1393 23.260 17.060 10.810 1.00 0.00 +ATOM 4412 HW1 SOL 1393 22.880 17.520 11.550 1.00 0.00 +ATOM 4413 HW2 SOL 1393 22.740 16.260 10.720 1.00 0.00 +ATOM 4414 OW SOL 1394 12.500 2.670 14.890 1.00 0.00 +ATOM 4415 HW1 SOL 1394 11.840 2.130 14.470 1.00 0.00 +ATOM 4416 HW2 SOL 1394 12.570 2.310 15.780 1.00 0.00 +ATOM 4417 OW SOL 1395 8.640 24.500 14.490 1.00 0.00 +ATOM 4418 HW1 SOL 1395 8.740 23.930 15.250 1.00 0.00 +ATOM 4419 HW2 SOL 1395 8.180 23.960 13.850 1.00 0.00 +ATOM 4420 OW SOL 1396 45.050 18.160 8.100 1.00 0.00 +ATOM 4421 HW1 SOL 1396 44.950 18.080 9.050 1.00 0.00 +ATOM 4422 HW2 SOL 1396 44.320 18.710 7.830 1.00 0.00 +ATOM 4423 OW SOL 1397 11.250 23.920 7.000 1.00 0.00 +ATOM 4424 HW1 SOL 1397 11.410 24.170 7.900 1.00 0.00 +ATOM 4425 HW2 SOL 1397 12.110 23.650 6.660 1.00 0.00 +ATOM 4426 OW SOL 1398 35.120 21.380 29.810 1.00 0.00 +ATOM 4427 HW1 SOL 1398 35.330 22.230 29.420 1.00 0.00 +ATOM 4428 HW2 SOL 1398 35.470 20.740 29.190 1.00 0.00 +ATOM 4429 OW SOL 1399 11.590 8.950 27.520 1.00 0.00 +ATOM 4430 HW1 SOL 1399 12.480 9.250 27.740 1.00 0.00 +ATOM 4431 HW2 SOL 1399 11.630 8.000 27.630 1.00 0.00 +ATOM 4432 OW SOL 1400 2.370 29.210 7.090 1.00 0.00 +ATOM 4433 HW1 SOL 1400 2.610 29.070 8.010 1.00 0.00 +ATOM 4434 HW2 SOL 1400 1.420 29.090 7.070 1.00 0.00 +ATOM 4435 OW SOL 1401 -2.887 4.090 29.130 1.00 0.00 +ATOM 4436 HW1 SOL 1401 -2.567 3.580 28.390 1.00 0.00 +ATOM 4437 HW2 SOL 1401 -3.177 4.920 28.740 1.00 0.00 +ATOM 4438 OW SOL 1402 35.750 1.630 4.120 1.00 0.00 +ATOM 4439 HW1 SOL 1402 34.860 1.710 4.460 1.00 0.00 +ATOM 4440 HW2 SOL 1402 35.660 1.800 3.180 1.00 0.00 +ATOM 4441 OW SOL 1403 7.440 11.780 7.370 1.00 0.00 +ATOM 4442 HW1 SOL 1403 8.290 11.330 7.330 1.00 0.00 +ATOM 4443 HW2 SOL 1403 7.120 11.600 8.250 1.00 0.00 +ATOM 4444 OW SOL 1404 4.390 18.830 13.110 1.00 0.00 +ATOM 4445 HW1 SOL 1404 4.320 19.630 12.600 1.00 0.00 +ATOM 4446 HW2 SOL 1404 3.510 18.460 13.120 1.00 0.00 +ATOM 4447 OW SOL 1405 23.010 10.260 0.120 1.00 0.00 +ATOM 4448 HW1 SOL 1405 23.010 11.150 0.480 1.00 0.00 +ATOM 4449 HW2 SOL 1405 23.790 9.850 0.510 1.00 0.00 +ATOM 4450 OW SOL 1406 44.450 18.280 26.600 1.00 0.00 +ATOM 4451 HW1 SOL 1406 44.840 17.430 26.810 1.00 0.00 +ATOM 4452 HW2 SOL 1406 43.660 18.070 26.100 1.00 0.00 +ATOM 4453 OW SOL 1407 29.350 33.330 10.860 1.00 0.00 +ATOM 4454 HW1 SOL 1407 30.120 33.880 10.760 1.00 0.00 +ATOM 4455 HW2 SOL 1407 29.100 33.100 9.960 1.00 0.00 +ATOM 4456 OW SOL 1408 42.080 10.610 16.480 1.00 0.00 +ATOM 4457 HW1 SOL 1408 42.010 10.260 15.590 1.00 0.00 +ATOM 4458 HW2 SOL 1408 41.180 10.680 16.780 1.00 0.00 +ATOM 4459 OW SOL 1409 44.300 34.460 8.110 1.00 0.00 +ATOM 4460 HW1 SOL 1409 43.990 35.150 8.700 1.00 0.00 +ATOM 4461 HW2 SOL 1409 45.150 34.210 8.460 1.00 0.00 +ATOM 4462 OW SOL 1410 48.717 10.850 25.980 1.00 0.00 +ATOM 4463 HW1 SOL 1410 48.837 10.810 26.930 1.00 0.00 +ATOM 4464 HW2 SOL 1410 49.587 11.060 25.640 1.00 0.00 +ATOM 4465 OW SOL 1411 38.990 13.070 0.150 1.00 0.00 +ATOM 4466 HW1 SOL 1411 38.140 12.810 0.490 1.00 0.00 +ATOM 4467 HW2 SOL 1411 39.620 12.600 0.690 1.00 0.00 +ATOM 4468 OW SOL 1412 28.400 35.610 19.040 1.00 0.00 +ATOM 4469 HW1 SOL 1412 29.280 35.610 18.660 1.00 0.00 +ATOM 4470 HW2 SOL 1412 27.830 35.270 18.350 1.00 0.00 +ATOM 4471 OW SOL 1413 12.880 23.300 23.930 1.00 0.00 +ATOM 4472 HW1 SOL 1413 13.460 23.400 24.680 1.00 0.00 +ATOM 4473 HW2 SOL 1413 12.110 22.860 24.270 1.00 0.00 +ATOM 4474 OW SOL 1414 12.370 19.600 18.430 1.00 0.00 +ATOM 4475 HW1 SOL 1414 12.870 20.280 18.890 1.00 0.00 +ATOM 4476 HW2 SOL 1414 12.750 18.780 18.740 1.00 0.00 +ATOM 4477 OW SOL 1415 30.500 5.490 30.580 1.00 0.00 +ATOM 4478 HW1 SOL 1415 30.560 4.680 30.060 1.00 0.00 +ATOM 4479 HW2 SOL 1415 30.240 6.160 29.950 1.00 0.00 +ATOM 4480 OW SOL 1416 32.140 29.000 22.620 1.00 0.00 +ATOM 4481 HW1 SOL 1416 32.790 28.430 23.030 1.00 0.00 +ATOM 4482 HW2 SOL 1416 31.500 28.390 22.240 1.00 0.00 +ATOM 4483 OW SOL 1417 2.480 31.920 14.100 1.00 0.00 +ATOM 4484 HW1 SOL 1417 2.380 31.520 14.960 1.00 0.00 +ATOM 4485 HW2 SOL 1417 2.140 32.810 14.210 1.00 0.00 +ATOM 4486 OW SOL 1418 0.590 13.710 2.000 1.00 0.00 +ATOM 4487 HW1 SOL 1418 1.300 14.340 2.010 1.00 0.00 +ATOM 4488 HW2 SOL 1418 -0.170 14.190 2.330 1.00 0.00 +ATOM 4489 OW SOL 1419 15.390 21.920 12.490 1.00 0.00 +ATOM 4490 HW1 SOL 1419 14.760 22.190 13.160 1.00 0.00 +ATOM 4491 HW2 SOL 1419 15.710 22.740 12.120 1.00 0.00 +ATOM 4492 OW SOL 1420 34.580 19.340 16.130 1.00 0.00 +ATOM 4493 HW1 SOL 1420 34.160 18.480 16.050 1.00 0.00 +ATOM 4494 HW2 SOL 1420 33.880 19.970 15.950 1.00 0.00 +ATOM 4495 OW SOL 1421 38.490 11.710 9.120 1.00 0.00 +ATOM 4496 HW1 SOL 1421 37.990 12.400 9.570 1.00 0.00 +ATOM 4497 HW2 SOL 1421 37.830 11.110 8.790 1.00 0.00 +ATOM 4498 OW SOL 1422 32.760 5.660 0.010 1.00 0.00 +ATOM 4499 HW1 SOL 1422 31.850 5.430 0.220 1.00 0.00 +ATOM 4500 HW2 SOL 1422 33.260 5.350 0.760 1.00 0.00 +ATOM 4501 OW SOL 1423 7.270 6.290 10.630 1.00 0.00 +ATOM 4502 HW1 SOL 1423 7.650 6.880 9.980 1.00 0.00 +ATOM 4503 HW2 SOL 1423 6.360 6.560 10.700 1.00 0.00 +ATOM 4504 OW SOL 1424 22.480 24.180 5.270 1.00 0.00 +ATOM 4505 HW1 SOL 1424 22.300 23.430 5.830 1.00 0.00 +ATOM 4506 HW2 SOL 1424 21.610 24.540 5.080 1.00 0.00 +ATOM 4507 OW SOL 1425 6.830 23.620 28.370 1.00 0.00 +ATOM 4508 HW1 SOL 1425 6.330 22.880 28.000 1.00 0.00 +ATOM 4509 HW2 SOL 1425 6.270 23.980 29.050 1.00 0.00 +ATOM 4510 OW SOL 1426 35.000 10.490 21.860 1.00 0.00 +ATOM 4511 HW1 SOL 1426 34.770 9.700 22.360 1.00 0.00 +ATOM 4512 HW2 SOL 1426 34.990 10.210 20.950 1.00 0.00 +ATOM 4513 OW SOL 1427 33.890 15.430 22.910 1.00 0.00 +ATOM 4514 HW1 SOL 1427 33.280 14.700 23.020 1.00 0.00 +ATOM 4515 HW2 SOL 1427 34.660 15.180 23.410 1.00 0.00 +ATOM 4516 OW SOL 1428 35.450 22.190 20.860 1.00 0.00 +ATOM 4517 HW1 SOL 1428 35.600 21.470 20.250 1.00 0.00 +ATOM 4518 HW2 SOL 1428 35.490 21.780 21.730 1.00 0.00 +ATOM 4519 OW SOL 1429 8.720 21.640 0.270 1.00 0.00 +ATOM 4520 HW1 SOL 1429 8.110 22.320 0.000 1.00 0.00 +ATOM 4521 HW2 SOL 1429 8.270 21.180 0.980 1.00 0.00 +ATOM 4522 OW SOL 1430 3.960 20.320 10.800 1.00 0.00 +ATOM 4523 HW1 SOL 1430 4.620 19.660 10.610 1.00 0.00 +ATOM 4524 HW2 SOL 1430 3.940 20.880 10.030 1.00 0.00 +ATOM 4525 OW SOL 1431 22.440 32.930 22.070 1.00 0.00 +ATOM 4526 HW1 SOL 1431 22.100 32.450 21.320 1.00 0.00 +ATOM 4527 HW2 SOL 1431 23.360 32.650 22.140 1.00 0.00 +ATOM 4528 OW SOL 1432 9.270 44.470 1.420 1.00 0.00 +ATOM 4529 HW1 SOL 1432 9.520 44.670 0.510 1.00 0.00 +ATOM 4530 HW2 SOL 1432 8.520 45.040 1.590 1.00 0.00 +ATOM 4531 OW SOL 1433 23.480 23.490 8.820 1.00 0.00 +ATOM 4532 HW1 SOL 1433 22.900 22.810 8.460 1.00 0.00 +ATOM 4533 HW2 SOL 1433 24.280 23.020 9.050 1.00 0.00 +ATOM 4534 OW SOL 1434 39.360 21.540 8.710 1.00 0.00 +ATOM 4535 HW1 SOL 1434 38.580 21.000 8.580 1.00 0.00 +ATOM 4536 HW2 SOL 1434 39.050 22.440 8.600 1.00 0.00 +ATOM 4537 OW SOL 1435 10.600 31.680 4.090 1.00 0.00 +ATOM 4538 HW1 SOL 1435 9.950 31.260 3.540 1.00 0.00 +ATOM 4539 HW2 SOL 1435 10.830 31.010 4.740 1.00 0.00 +ATOM 4540 OW SOL 1436 9.060 10.120 2.990 1.00 0.00 +ATOM 4541 HW1 SOL 1436 10.010 10.020 3.080 1.00 0.00 +ATOM 4542 HW2 SOL 1436 8.940 11.050 2.800 1.00 0.00 +ATOM 4543 OW SOL 1437 16.910 8.160 8.010 1.00 0.00 +ATOM 4544 HW1 SOL 1437 15.960 8.160 7.940 1.00 0.00 +ATOM 4545 HW2 SOL 1437 17.140 7.250 8.170 1.00 0.00 +ATOM 4546 OW SOL 1438 25.250 28.410 14.510 1.00 0.00 +ATOM 4547 HW1 SOL 1438 25.150 28.080 15.410 1.00 0.00 +ATOM 4548 HW2 SOL 1438 25.460 27.630 14.000 1.00 0.00 +ATOM 4549 OW SOL 1439 41.670 0.170 29.210 1.00 0.00 +ATOM 4550 HW1 SOL 1439 42.610 0.160 29.410 1.00 0.00 +ATOM 4551 HW2 SOL 1439 41.380 -0.720 29.370 1.00 0.00 +ATOM 4552 OW SOL 1440 26.260 7.880 5.010 1.00 0.00 +ATOM 4553 HW1 SOL 1440 25.370 8.220 4.930 1.00 0.00 +ATOM 4554 HW2 SOL 1440 26.810 8.650 5.150 1.00 0.00 +ATOM 4555 OW SOL 1441 27.480 10.420 5.130 1.00 0.00 +ATOM 4556 HW1 SOL 1441 26.790 11.070 5.270 1.00 0.00 +ATOM 4557 HW2 SOL 1441 27.960 10.740 4.370 1.00 0.00 +ATOM 4558 OW SOL 1442 40.590 20.570 16.170 1.00 0.00 +ATOM 4559 HW1 SOL 1442 41.060 21.290 16.590 1.00 0.00 +ATOM 4560 HW2 SOL 1442 40.840 20.630 15.250 1.00 0.00 +ATOM 4561 OW SOL 1443 42.490 1.250 5.200 1.00 0.00 +ATOM 4562 HW1 SOL 1443 42.300 2.140 5.500 1.00 0.00 +ATOM 4563 HW2 SOL 1443 42.810 1.370 4.300 1.00 0.00 +ATOM 4564 OW SOL 1444 38.260 27.000 17.040 1.00 0.00 +ATOM 4565 HW1 SOL 1444 39.130 27.300 17.320 1.00 0.00 +ATOM 4566 HW2 SOL 1444 38.230 26.080 17.290 1.00 0.00 +ATOM 4567 OW SOL 1445 37.550 11.340 25.100 1.00 0.00 +ATOM 4568 HW1 SOL 1445 36.610 11.380 24.940 1.00 0.00 +ATOM 4569 HW2 SOL 1445 37.700 11.980 25.800 1.00 0.00 +ATOM 4570 OW SOL 1446 3.760 42.000 3.760 1.00 0.00 +ATOM 4571 HW1 SOL 1446 3.720 42.960 3.710 1.00 0.00 +ATOM 4572 HW2 SOL 1446 2.920 41.700 3.430 1.00 0.00 +ATOM 4573 OW SOL 1447 4.980 16.270 11.800 1.00 0.00 +ATOM 4574 HW1 SOL 1447 5.050 17.160 12.150 1.00 0.00 +ATOM 4575 HW2 SOL 1447 4.070 16.020 11.950 1.00 0.00 +ATOM 4576 OW SOL 1448 20.400 20.440 13.830 1.00 0.00 +ATOM 4577 HW1 SOL 1448 20.500 20.410 14.780 1.00 0.00 +ATOM 4578 HW2 SOL 1448 19.450 20.400 13.690 1.00 0.00 +ATOM 4579 OW SOL 1449 19.570 38.960 5.340 1.00 0.00 +ATOM 4580 HW1 SOL 1449 19.360 39.890 5.430 1.00 0.00 +ATOM 4581 HW2 SOL 1449 18.910 38.620 4.730 1.00 0.00 +ATOM 4582 OW SOL 1450 22.130 29.430 17.470 1.00 0.00 +ATOM 4583 HW1 SOL 1450 22.310 30.010 16.730 1.00 0.00 +ATOM 4584 HW2 SOL 1450 21.730 28.650 17.070 1.00 0.00 +ATOM 4585 OW SOL 1451 43.500 33.430 11.410 1.00 0.00 +ATOM 4586 HW1 SOL 1451 43.410 33.050 12.280 1.00 0.00 +ATOM 4587 HW2 SOL 1451 44.190 32.930 10.990 1.00 0.00 +ATOM 4588 OW SOL 1452 23.550 8.440 4.340 1.00 0.00 +ATOM 4589 HW1 SOL 1452 23.300 7.540 4.550 1.00 0.00 +ATOM 4590 HW2 SOL 1452 22.720 8.880 4.170 1.00 0.00 +ATOM 4591 OW SOL 1453 34.710 23.730 13.430 1.00 0.00 +ATOM 4592 HW1 SOL 1453 34.630 24.260 14.230 1.00 0.00 +ATOM 4593 HW2 SOL 1453 35.080 22.900 13.730 1.00 0.00 +ATOM 4594 OW SOL 1454 16.790 12.830 4.610 1.00 0.00 +ATOM 4595 HW1 SOL 1454 16.190 13.570 4.640 1.00 0.00 +ATOM 4596 HW2 SOL 1454 17.310 12.910 5.410 1.00 0.00 +ATOM 4597 OW SOL 1455 29.790 7.170 23.610 1.00 0.00 +ATOM 4598 HW1 SOL 1455 30.090 7.060 24.510 1.00 0.00 +ATOM 4599 HW2 SOL 1455 29.070 6.550 23.510 1.00 0.00 +ATOM 4600 OW SOL 1456 36.440 2.220 25.070 1.00 0.00 +ATOM 4601 HW1 SOL 1456 36.040 2.220 24.200 1.00 0.00 +ATOM 4602 HW2 SOL 1456 36.220 1.360 25.430 1.00 0.00 +ATOM 4603 OW SOL 1457 37.670 36.260 14.560 1.00 0.00 +ATOM 4604 HW1 SOL 1457 37.150 35.860 15.250 1.00 0.00 +ATOM 4605 HW2 SOL 1457 38.110 36.990 14.990 1.00 0.00 +ATOM 4606 OW SOL 1458 21.920 31.420 28.860 1.00 0.00 +ATOM 4607 HW1 SOL 1458 22.350 31.660 28.040 1.00 0.00 +ATOM 4608 HW2 SOL 1458 21.110 31.930 28.850 1.00 0.00 +ATOM 4609 OW SOL 1459 9.220 24.970 27.350 1.00 0.00 +ATOM 4610 HW1 SOL 1459 8.590 24.610 27.980 1.00 0.00 +ATOM 4611 HW2 SOL 1459 8.800 24.840 26.500 1.00 0.00 +ATOM 4612 OW SOL 1460 22.740 0.080 25.050 1.00 0.00 +ATOM 4613 HW1 SOL 1460 22.750 -0.830 24.750 1.00 0.00 +ATOM 4614 HW2 SOL 1460 21.820 0.250 25.240 1.00 0.00 +ATOM 4615 OW SOL 1461 39.730 38.970 28.360 1.00 0.00 +ATOM 4616 HW1 SOL 1461 38.860 39.170 28.010 1.00 0.00 +ATOM 4617 HW2 SOL 1461 40.330 39.260 27.670 1.00 0.00 +ATOM 4618 OW SOL 1462 36.430 12.180 0.970 1.00 0.00 +ATOM 4619 HW1 SOL 1462 35.990 11.790 1.720 1.00 0.00 +ATOM 4620 HW2 SOL 1462 35.730 12.370 0.350 1.00 0.00 +ATOM 4621 OW SOL 1463 25.070 25.420 10.200 1.00 0.00 +ATOM 4622 HW1 SOL 1463 24.940 26.260 9.770 1.00 0.00 +ATOM 4623 HW2 SOL 1463 24.350 24.880 9.900 1.00 0.00 +ATOM 4624 OW SOL 1464 35.910 11.440 13.370 1.00 0.00 +ATOM 4625 HW1 SOL 1464 35.410 12.250 13.490 1.00 0.00 +ATOM 4626 HW2 SOL 1464 36.830 11.720 13.370 1.00 0.00 +ATOM 4627 OW SOL 1465 43.750 1.120 16.430 1.00 0.00 +ATOM 4628 HW1 SOL 1465 44.410 1.770 16.170 1.00 0.00 +ATOM 4629 HW2 SOL 1465 43.650 1.230 17.370 1.00 0.00 +ATOM 4630 OW SOL 1466 9.270 8.980 17.960 1.00 0.00 +ATOM 4631 HW1 SOL 1466 8.830 8.720 18.770 1.00 0.00 +ATOM 4632 HW2 SOL 1466 9.510 8.150 17.540 1.00 0.00 +ATOM 4633 OW SOL 1467 10.270 0.570 27.340 1.00 0.00 +ATOM 4634 HW1 SOL 1467 10.660 0.210 28.130 1.00 0.00 +ATOM 4635 HW2 SOL 1467 10.650 0.050 26.630 1.00 0.00 +ATOM 4636 OW SOL 1468 16.150 35.390 4.300 1.00 0.00 +ATOM 4637 HW1 SOL 1468 16.070 36.140 3.710 1.00 0.00 +ATOM 4638 HW2 SOL 1468 15.460 34.790 4.020 1.00 0.00 +ATOM 4639 OW SOL 1469 37.940 23.070 4.060 1.00 0.00 +ATOM 4640 HW1 SOL 1469 38.460 23.530 3.400 1.00 0.00 +ATOM 4641 HW2 SOL 1469 38.530 22.990 4.810 1.00 0.00 +ATOM 4642 OW SOL 1470 28.980 3.090 14.400 1.00 0.00 +ATOM 4643 HW1 SOL 1470 29.760 3.510 14.040 1.00 0.00 +ATOM 4644 HW2 SOL 1470 29.010 3.290 15.330 1.00 0.00 +ATOM 4645 OW SOL 1471 45.290 25.830 28.560 1.00 0.00 +ATOM 4646 HW1 SOL 1471 44.740 25.250 28.030 1.00 0.00 +ATOM 4647 HW2 SOL 1471 45.820 26.310 27.930 1.00 0.00 +ATOM 4648 OW SOL 1472 43.350 18.920 13.240 1.00 0.00 +ATOM 4649 HW1 SOL 1472 43.710 18.560 14.050 1.00 0.00 +ATOM 4650 HW2 SOL 1472 43.230 19.850 13.430 1.00 0.00 +ATOM 4651 OW SOL 1473 30.560 0.800 19.920 1.00 0.00 +ATOM 4652 HW1 SOL 1473 30.730 0.030 19.380 1.00 0.00 +ATOM 4653 HW2 SOL 1473 30.670 0.490 20.820 1.00 0.00 +ATOM 4654 OW SOL 1474 25.640 25.430 19.260 1.00 0.00 +ATOM 4655 HW1 SOL 1474 26.230 24.770 18.910 1.00 0.00 +ATOM 4656 HW2 SOL 1474 25.800 25.420 20.200 1.00 0.00 +ATOM 4657 OW SOL 1475 10.790 7.180 12.630 1.00 0.00 +ATOM 4658 HW1 SOL 1475 10.300 6.750 13.320 1.00 0.00 +ATOM 4659 HW2 SOL 1475 11.200 6.460 12.150 1.00 0.00 +ATOM 4660 OW SOL 1476 33.940 31.560 29.900 1.00 0.00 +ATOM 4661 HW1 SOL 1476 34.480 32.000 29.240 1.00 0.00 +ATOM 4662 HW2 SOL 1476 34.540 30.960 30.340 1.00 0.00 +ATOM 4663 OW SOL 1477 22.390 13.850 28.750 1.00 0.00 +ATOM 4664 HW1 SOL 1477 22.550 12.940 29.000 1.00 0.00 +ATOM 4665 HW2 SOL 1477 23.190 14.110 28.290 1.00 0.00 +ATOM 4666 OW SOL 1478 13.080 42.260 2.590 1.00 0.00 +ATOM 4667 HW1 SOL 1478 12.970 42.070 1.660 1.00 0.00 +ATOM 4668 HW2 SOL 1478 13.910 42.740 2.630 1.00 0.00 +ATOM 4669 OW SOL 1479 10.600 24.790 30.970 1.00 0.00 +ATOM 4670 HW1 SOL 1479 11.000 25.540 31.390 1.00 0.00 +ATOM 4671 HW2 SOL 1479 9.690 24.800 31.260 1.00 0.00 +ATOM 4672 OW SOL 1480 31.750 32.980 30.700 1.00 0.00 +ATOM 4673 HW1 SOL 1480 32.620 32.690 30.400 1.00 0.00 +ATOM 4674 HW2 SOL 1480 31.170 32.260 30.460 1.00 0.00 +ATOM 4675 OW SOL 1481 24.080 38.750 22.840 1.00 0.00 +ATOM 4676 HW1 SOL 1481 24.670 39.190 23.450 1.00 0.00 +ATOM 4677 HW2 SOL 1481 24.380 37.840 22.830 1.00 0.00 +ATOM 4678 OW SOL 1482 7.830 24.680 31.820 1.00 0.00 +ATOM 4679 HW1 SOL 1482 7.160 24.840 31.150 1.00 0.00 +ATOM 4680 HW2 SOL 1482 7.820 23.730 31.940 1.00 0.00 +ATOM 4681 OW SOL 1483 44.330 43.530 15.890 1.00 0.00 +ATOM 4682 HW1 SOL 1483 44.410 44.430 15.580 1.00 0.00 +ATOM 4683 HW2 SOL 1483 44.620 43.560 16.800 1.00 0.00 +ATOM 4684 OW SOL 1484 35.600 35.030 5.260 1.00 0.00 +ATOM 4685 HW1 SOL 1484 34.840 35.500 4.910 1.00 0.00 +ATOM 4686 HW2 SOL 1484 35.280 34.590 6.040 1.00 0.00 +ATOM 4687 OW SOL 1485 40.280 34.220 3.830 1.00 0.00 +ATOM 4688 HW1 SOL 1485 40.480 33.280 3.780 1.00 0.00 +ATOM 4689 HW2 SOL 1485 39.970 34.350 4.730 1.00 0.00 +ATOM 4690 OW SOL 1486 39.720 38.910 13.900 1.00 0.00 +ATOM 4691 HW1 SOL 1486 39.830 38.620 12.990 1.00 0.00 +ATOM 4692 HW2 SOL 1486 40.130 39.780 13.920 1.00 0.00 +ATOM 4693 OW SOL 1487 21.550 14.800 0.720 1.00 0.00 +ATOM 4694 HW1 SOL 1487 21.060 15.540 0.350 1.00 0.00 +ATOM 4695 HW2 SOL 1487 21.880 15.120 1.550 1.00 0.00 +ATOM 4696 OW SOL 1488 43.680 17.290 10.580 1.00 0.00 +ATOM 4697 HW1 SOL 1488 43.710 17.930 11.290 1.00 0.00 +ATOM 4698 HW2 SOL 1488 44.230 16.570 10.890 1.00 0.00 +ATOM 4699 OW SOL 1489 37.670 11.290 16.960 1.00 0.00 +ATOM 4700 HW1 SOL 1489 38.460 11.150 17.480 1.00 0.00 +ATOM 4701 HW2 SOL 1489 37.970 11.210 16.050 1.00 0.00 +ATOM 4702 OW SOL 1490 24.840 31.460 20.840 1.00 0.00 +ATOM 4703 HW1 SOL 1490 25.690 31.510 20.400 1.00 0.00 +ATOM 4704 HW2 SOL 1490 24.340 30.840 20.310 1.00 0.00 +ATOM 4705 OW SOL 1491 1.090 40.180 13.430 1.00 0.00 +ATOM 4706 HW1 SOL 1491 1.580 39.480 12.990 1.00 0.00 +ATOM 4707 HW2 SOL 1491 0.310 40.300 12.880 1.00 0.00 +ATOM 4708 OW SOL 1492 41.100 27.830 17.710 1.00 0.00 +ATOM 4709 HW1 SOL 1492 41.680 27.260 18.210 1.00 0.00 +ATOM 4710 HW2 SOL 1492 41.670 28.240 17.050 1.00 0.00 +ATOM 4711 OW SOL 1493 13.450 6.590 7.990 1.00 0.00 +ATOM 4712 HW1 SOL 1493 12.850 6.920 8.660 1.00 0.00 +ATOM 4713 HW2 SOL 1493 13.290 7.140 7.230 1.00 0.00 +ATOM 4714 OW SOL 1494 29.090 32.630 8.280 1.00 0.00 +ATOM 4715 HW1 SOL 1494 29.150 33.050 7.420 1.00 0.00 +ATOM 4716 HW2 SOL 1494 29.970 32.270 8.430 1.00 0.00 +ATOM 4717 OW SOL 1495 32.510 44.700 29.870 1.00 0.00 +ATOM 4718 HW1 SOL 1495 31.770 44.540 30.450 1.00 0.00 +ATOM 4719 HW2 SOL 1495 33.210 45.000 30.440 1.00 0.00 +ATOM 4720 OW SOL 1496 30.310 37.900 3.430 1.00 0.00 +ATOM 4721 HW1 SOL 1496 30.370 38.490 4.170 1.00 0.00 +ATOM 4722 HW2 SOL 1496 29.520 38.170 2.960 1.00 0.00 +ATOM 4723 OW SOL 1497 0.290 6.740 5.690 1.00 0.00 +ATOM 4724 HW1 SOL 1497 -0.150 6.590 6.520 1.00 0.00 +ATOM 4725 HW2 SOL 1497 0.470 5.870 5.340 1.00 0.00 +ATOM 4726 OW SOL 1498 26.570 44.580 3.200 1.00 0.00 +ATOM 4727 HW1 SOL 1498 25.700 44.850 2.890 1.00 0.00 +ATOM 4728 HW2 SOL 1498 27.080 44.460 2.390 1.00 0.00 +ATOM 4729 OW SOL 1499 42.640 33.330 6.390 1.00 0.00 +ATOM 4730 HW1 SOL 1499 43.250 33.810 6.960 1.00 0.00 +ATOM 4731 HW2 SOL 1499 43.190 33.000 5.680 1.00 0.00 +ATOM 4732 OW SOL 1500 43.540 25.390 6.730 1.00 0.00 +ATOM 4733 HW1 SOL 1500 43.220 25.460 7.630 1.00 0.00 +ATOM 4734 HW2 SOL 1500 43.690 26.300 6.460 1.00 0.00 +ATOM 4735 OW SOL 1501 24.840 15.310 16.920 1.00 0.00 +ATOM 4736 HW1 SOL 1501 24.960 14.450 16.500 1.00 0.00 +ATOM 4737 HW2 SOL 1501 25.660 15.770 16.760 1.00 0.00 +ATOM 4738 OW SOL 1502 28.400 10.120 7.780 1.00 0.00 +ATOM 4739 HW1 SOL 1502 28.040 10.420 6.940 1.00 0.00 +ATOM 4740 HW2 SOL 1502 29.120 9.540 7.540 1.00 0.00 +ATOM 4741 OW SOL 1503 15.520 38.450 20.950 1.00 0.00 +ATOM 4742 HW1 SOL 1503 15.940 37.610 20.730 1.00 0.00 +ATOM 4743 HW2 SOL 1503 16.180 38.920 21.450 1.00 0.00 +ATOM 4744 OW SOL 1504 39.670 19.470 18.970 1.00 0.00 +ATOM 4745 HW1 SOL 1504 39.840 18.750 18.360 1.00 0.00 +ATOM 4746 HW2 SOL 1504 38.770 19.330 19.270 1.00 0.00 +ATOM 4747 OW SOL 1505 30.610 10.060 14.110 1.00 0.00 +ATOM 4748 HW1 SOL 1505 30.730 10.790 14.730 1.00 0.00 +ATOM 4749 HW2 SOL 1505 31.500 9.850 13.810 1.00 0.00 +ATOM 4750 OW SOL 1506 20.810 14.540 21.750 1.00 0.00 +ATOM 4751 HW1 SOL 1506 21.260 15.360 21.540 1.00 0.00 +ATOM 4752 HW2 SOL 1506 19.970 14.620 21.300 1.00 0.00 +ATOM 4753 OW SOL 1507 29.280 39.950 29.320 1.00 0.00 +ATOM 4754 HW1 SOL 1507 29.910 39.280 29.070 1.00 0.00 +ATOM 4755 HW2 SOL 1507 28.430 39.580 29.060 1.00 0.00 +ATOM 4756 OW SOL 1508 24.030 6.090 1.570 1.00 0.00 +ATOM 4757 HW1 SOL 1508 23.370 6.390 0.950 1.00 0.00 +ATOM 4758 HW2 SOL 1508 24.860 6.420 1.210 1.00 0.00 +ATOM 4759 OW SOL 1509 9.480 3.460 17.210 1.00 0.00 +ATOM 4760 HW1 SOL 1509 10.000 2.940 16.600 1.00 0.00 +ATOM 4761 HW2 SOL 1509 9.920 4.310 17.220 1.00 0.00 +ATOM 4762 OW SOL 1510 8.380 22.730 11.660 1.00 0.00 +ATOM 4763 HW1 SOL 1510 8.320 21.880 11.240 1.00 0.00 +ATOM 4764 HW2 SOL 1510 9.290 22.790 11.960 1.00 0.00 +ATOM 4765 OW SOL 1511 24.940 36.990 25.610 1.00 0.00 +ATOM 4766 HW1 SOL 1511 24.920 37.950 25.650 1.00 0.00 +ATOM 4767 HW2 SOL 1511 24.660 36.780 24.710 1.00 0.00 +ATOM 4768 OW SOL 1512 12.050 1.630 0.140 1.00 0.00 +ATOM 4769 HW1 SOL 1512 12.560 2.430 0.020 1.00 0.00 +ATOM 4770 HW2 SOL 1512 12.620 1.060 0.670 1.00 0.00 +ATOM 4771 OW SOL 1513 19.630 39.050 23.900 1.00 0.00 +ATOM 4772 HW1 SOL 1513 20.220 38.940 23.160 1.00 0.00 +ATOM 4773 HW2 SOL 1513 20.200 39.080 24.660 1.00 0.00 +ATOM 4774 OW SOL 1514 34.480 24.240 1.410 1.00 0.00 +ATOM 4775 HW1 SOL 1514 34.700 25.100 1.750 1.00 0.00 +ATOM 4776 HW2 SOL 1514 34.980 23.630 1.960 1.00 0.00 +ATOM 4777 OW SOL 1515 44.030 31.510 25.340 1.00 0.00 +ATOM 4778 HW1 SOL 1515 43.260 31.190 25.810 1.00 0.00 +ATOM 4779 HW2 SOL 1515 44.270 30.810 24.740 1.00 0.00 +ATOM 4780 OW SOL 1516 23.230 18.480 23.300 1.00 0.00 +ATOM 4781 HW1 SOL 1516 23.200 17.760 23.930 1.00 0.00 +ATOM 4782 HW2 SOL 1516 23.870 18.200 22.640 1.00 0.00 +ATOM 4783 OW SOL 1517 32.700 32.210 16.630 1.00 0.00 +ATOM 4784 HW1 SOL 1517 32.890 32.610 15.780 1.00 0.00 +ATOM 4785 HW2 SOL 1517 33.560 32.140 17.050 1.00 0.00 +ATOM 4786 OW SOL 1518 41.410 19.270 0.210 1.00 0.00 +ATOM 4787 HW1 SOL 1518 41.110 19.400 1.120 1.00 0.00 +ATOM 4788 HW2 SOL 1518 42.210 18.750 0.300 1.00 0.00 +ATOM 4789 OW SOL 1519 35.140 20.580 23.140 1.00 0.00 +ATOM 4790 HW1 SOL 1519 35.800 19.990 23.500 1.00 0.00 +ATOM 4791 HW2 SOL 1519 34.330 20.330 23.590 1.00 0.00 +ATOM 4792 OW SOL 1520 8.390 38.110 21.680 1.00 0.00 +ATOM 4793 HW1 SOL 1520 9.240 38.420 22.000 1.00 0.00 +ATOM 4794 HW2 SOL 1520 8.540 37.910 20.760 1.00 0.00 +ATOM 4795 OW SOL 1521 17.210 7.970 18.230 1.00 0.00 +ATOM 4796 HW1 SOL 1521 16.600 7.250 18.110 1.00 0.00 +ATOM 4797 HW2 SOL 1521 16.740 8.740 17.930 1.00 0.00 +ATOM 4798 OW SOL 1522 29.350 10.320 11.470 1.00 0.00 +ATOM 4799 HW1 SOL 1522 28.830 9.550 11.210 1.00 0.00 +ATOM 4800 HW2 SOL 1522 29.750 10.070 12.300 1.00 0.00 +ATOM 4801 OW SOL 1523 32.280 30.670 19.170 1.00 0.00 +ATOM 4802 HW1 SOL 1523 31.950 31.530 18.900 1.00 0.00 +ATOM 4803 HW2 SOL 1523 33.160 30.630 18.810 1.00 0.00 +ATOM 4804 OW SOL 1524 31.440 35.750 30.980 1.00 0.00 +ATOM 4805 HW1 SOL 1524 31.390 34.800 30.920 1.00 0.00 +ATOM 4806 HW2 SOL 1524 32.270 35.920 31.430 1.00 0.00 +ATOM 4807 OW SOL 1525 31.350 35.940 18.890 1.00 0.00 +ATOM 4808 HW1 SOL 1525 31.310 36.900 18.920 1.00 0.00 +ATOM 4809 HW2 SOL 1525 31.770 35.700 19.720 1.00 0.00 +ATOM 4810 OW SOL 1526 37.010 15.810 12.480 1.00 0.00 +ATOM 4811 HW1 SOL 1526 36.120 16.070 12.720 1.00 0.00 +ATOM 4812 HW2 SOL 1526 37.420 15.580 13.310 1.00 0.00 +ATOM 4813 OW SOL 1527 42.180 21.380 28.150 1.00 0.00 +ATOM 4814 HW1 SOL 1527 41.630 20.840 28.730 1.00 0.00 +ATOM 4815 HW2 SOL 1527 43.000 20.890 28.100 1.00 0.00 +ATOM 4816 OW SOL 1528 26.550 7.700 26.720 1.00 0.00 +ATOM 4817 HW1 SOL 1528 27.070 8.230 26.120 1.00 0.00 +ATOM 4818 HW2 SOL 1528 25.640 7.860 26.460 1.00 0.00 +ATOM 4819 OW SOL 1529 39.340 31.750 31.310 1.00 0.00 +ATOM 4820 HW1 SOL 1529 39.700 32.010 30.460 1.00 0.00 +ATOM 4821 HW2 SOL 1529 40.090 31.710 31.900 1.00 0.00 +ATOM 4822 OW SOL 1530 24.250 18.060 17.540 1.00 0.00 +ATOM 4823 HW1 SOL 1530 24.360 17.170 17.200 1.00 0.00 +ATOM 4824 HW2 SOL 1530 23.310 18.150 17.680 1.00 0.00 +ATOM 4825 OW SOL 1531 9.550 30.840 16.770 1.00 0.00 +ATOM 4826 HW1 SOL 1531 8.760 30.700 17.290 1.00 0.00 +ATOM 4827 HW2 SOL 1531 9.360 30.400 15.940 1.00 0.00 +ATOM 4828 OW SOL 1532 38.770 0.090 10.340 1.00 0.00 +ATOM 4829 HW1 SOL 1532 38.520 0.240 11.260 1.00 0.00 +ATOM 4830 HW2 SOL 1532 39.570 0.600 10.220 1.00 0.00 +ATOM 4831 OW SOL 1533 9.080 25.340 19.780 1.00 0.00 +ATOM 4832 HW1 SOL 1533 9.110 25.060 20.700 1.00 0.00 +ATOM 4833 HW2 SOL 1533 8.440 26.040 19.760 1.00 0.00 +ATOM 4834 OW SOL 1534 41.610 14.900 24.630 1.00 0.00 +ATOM 4835 HW1 SOL 1534 41.330 15.500 25.330 1.00 0.00 +ATOM 4836 HW2 SOL 1534 42.220 14.300 25.070 1.00 0.00 +ATOM 4837 OW SOL 1535 40.370 3.740 4.550 1.00 0.00 +ATOM 4838 HW1 SOL 1535 40.990 4.390 4.880 1.00 0.00 +ATOM 4839 HW2 SOL 1535 39.610 4.250 4.260 1.00 0.00 +ATOM 4840 OW SOL 1536 5.050 43.330 10.210 1.00 0.00 +ATOM 4841 HW1 SOL 1536 5.250 43.420 9.270 1.00 0.00 +ATOM 4842 HW2 SOL 1536 5.460 44.090 10.620 1.00 0.00 +ATOM 4843 OW SOL 1537 43.170 31.610 13.450 1.00 0.00 +ATOM 4844 HW1 SOL 1537 43.640 31.200 14.180 1.00 0.00 +ATOM 4845 HW2 SOL 1537 42.470 32.110 13.870 1.00 0.00 +ATOM 4846 OW SOL 1538 13.700 38.500 25.580 1.00 0.00 +ATOM 4847 HW1 SOL 1538 14.060 39.300 25.210 1.00 0.00 +ATOM 4848 HW2 SOL 1538 14.220 38.340 26.360 1.00 0.00 +ATOM 4849 OW SOL 1539 19.890 22.720 30.930 1.00 0.00 +ATOM 4850 HW1 SOL 1539 19.310 22.430 31.630 1.00 0.00 +ATOM 4851 HW2 SOL 1539 20.770 22.580 31.280 1.00 0.00 +ATOM 4852 OW SOL 1540 5.220 9.590 20.000 1.00 0.00 +ATOM 4853 HW1 SOL 1540 5.490 9.310 20.870 1.00 0.00 +ATOM 4854 HW2 SOL 1540 5.630 8.970 19.400 1.00 0.00 +ATOM 4855 OW SOL 1541 25.960 38.190 2.720 1.00 0.00 +ATOM 4856 HW1 SOL 1541 26.790 38.490 2.350 1.00 0.00 +ATOM 4857 HW2 SOL 1541 25.970 38.520 3.620 1.00 0.00 +ATOM 4858 OW SOL 1542 33.740 11.480 8.240 1.00 0.00 +ATOM 4859 HW1 SOL 1542 32.800 11.340 8.270 1.00 0.00 +ATOM 4860 HW2 SOL 1542 33.850 12.430 8.320 1.00 0.00 +ATOM 4861 OW SOL 1543 5.110 40.610 5.610 1.00 0.00 +ATOM 4862 HW1 SOL 1543 4.370 40.000 5.690 1.00 0.00 +ATOM 4863 HW2 SOL 1543 4.830 41.230 4.930 1.00 0.00 +ATOM 4864 OW SOL 1544 31.120 2.880 29.350 1.00 0.00 +ATOM 4865 HW1 SOL 1544 31.980 2.650 28.990 1.00 0.00 +ATOM 4866 HW2 SOL 1544 30.520 2.260 28.940 1.00 0.00 +ATOM 4867 OW SOL 1545 30.830 42.900 16.730 1.00 0.00 +ATOM 4868 HW1 SOL 1545 31.380 42.180 16.400 1.00 0.00 +ATOM 4869 HW2 SOL 1545 30.180 43.030 16.030 1.00 0.00 +ATOM 4870 OW SOL 1546 19.000 9.460 14.430 1.00 0.00 +ATOM 4871 HW1 SOL 1546 18.720 9.490 13.520 1.00 0.00 +ATOM 4872 HW2 SOL 1546 18.500 10.160 14.860 1.00 0.00 +ATOM 4873 OW SOL 1547 10.200 22.630 24.740 1.00 0.00 +ATOM 4874 HW1 SOL 1547 10.470 21.880 25.260 1.00 0.00 +ATOM 4875 HW2 SOL 1547 9.260 22.700 24.900 1.00 0.00 +ATOM 4876 OW SOL 1548 41.830 8.130 18.400 1.00 0.00 +ATOM 4877 HW1 SOL 1548 42.300 8.000 19.220 1.00 0.00 +ATOM 4878 HW2 SOL 1548 41.450 9.010 18.470 1.00 0.00 +ATOM 4879 OW SOL 1549 13.670 38.810 5.400 1.00 0.00 +ATOM 4880 HW1 SOL 1549 12.940 38.990 5.990 1.00 0.00 +ATOM 4881 HW2 SOL 1549 13.300 38.220 4.740 1.00 0.00 +ATOM 4882 OW SOL 1550 0.530 2.070 28.720 1.00 0.00 +ATOM 4883 HW1 SOL 1550 -0.130 1.430 29.000 1.00 0.00 +ATOM 4884 HW2 SOL 1550 1.020 2.250 29.520 1.00 0.00 +ATOM 4885 OW SOL 1551 37.290 19.380 25.560 1.00 0.00 +ATOM 4886 HW1 SOL 1551 38.200 19.680 25.530 1.00 0.00 +ATOM 4887 HW2 SOL 1551 37.350 18.430 25.590 1.00 0.00 +ATOM 4888 OW SOL 1552 9.560 2.710 4.550 1.00 0.00 +ATOM 4889 HW1 SOL 1552 10.370 2.540 4.060 1.00 0.00 +ATOM 4890 HW2 SOL 1552 9.410 3.650 4.430 1.00 0.00 +ATOM 4891 OW SOL 1553 19.030 41.040 12.600 1.00 0.00 +ATOM 4892 HW1 SOL 1553 19.340 40.790 11.730 1.00 0.00 +ATOM 4893 HW2 SOL 1553 19.490 40.460 13.200 1.00 0.00 +ATOM 4894 OW SOL 1554 38.710 16.090 1.370 1.00 0.00 +ATOM 4895 HW1 SOL 1554 38.330 15.350 0.900 1.00 0.00 +ATOM 4896 HW2 SOL 1554 38.450 16.850 0.840 1.00 0.00 +ATOM 4897 OW SOL 1555 14.200 0.060 23.860 1.00 0.00 +ATOM 4898 HW1 SOL 1555 14.530 0.750 23.300 1.00 0.00 +ATOM 4899 HW2 SOL 1555 14.720 0.120 24.660 1.00 0.00 +ATOM 4900 OW SOL 1556 35.090 11.620 24.250 1.00 0.00 +ATOM 4901 HW1 SOL 1556 35.020 11.160 23.410 1.00 0.00 +ATOM 4902 HW2 SOL 1556 34.240 11.460 24.670 1.00 0.00 +ATOM 4903 OW SOL 1557 11.400 39.130 6.800 1.00 0.00 +ATOM 4904 HW1 SOL 1557 10.950 38.290 6.870 1.00 0.00 +ATOM 4905 HW2 SOL 1557 10.710 39.790 6.880 1.00 0.00 +ATOM 4906 OW SOL 1558 25.390 21.930 22.780 1.00 0.00 +ATOM 4907 HW1 SOL 1558 25.160 22.610 23.420 1.00 0.00 +ATOM 4908 HW2 SOL 1558 26.130 21.460 23.170 1.00 0.00 +ATOM 4909 OW SOL 1559 20.570 3.250 21.020 1.00 0.00 +ATOM 4910 HW1 SOL 1559 20.630 4.180 20.800 1.00 0.00 +ATOM 4911 HW2 SOL 1559 21.320 2.850 20.580 1.00 0.00 +ATOM 4912 OW SOL 1560 7.610 14.590 3.860 1.00 0.00 +ATOM 4913 HW1 SOL 1560 8.080 15.340 4.230 1.00 0.00 +ATOM 4914 HW2 SOL 1560 6.710 14.890 3.760 1.00 0.00 +ATOM 4915 OW SOL 1561 32.090 44.460 9.380 1.00 0.00 +ATOM 4916 HW1 SOL 1561 31.380 44.350 8.750 1.00 0.00 +ATOM 4917 HW2 SOL 1561 32.790 44.890 8.890 1.00 0.00 +ATOM 4918 OW SOL 1562 11.840 37.760 30.060 1.00 0.00 +ATOM 4919 HW1 SOL 1562 12.190 38.640 29.900 1.00 0.00 +ATOM 4920 HW2 SOL 1562 12.000 37.280 29.250 1.00 0.00 +ATOM 4921 OW SOL 1563 37.400 29.950 31.700 1.00 0.00 +ATOM 4922 HW1 SOL 1563 37.150 29.700 32.590 1.00 0.00 +ATOM 4923 HW2 SOL 1563 38.250 30.390 31.810 1.00 0.00 +ATOM 4924 OW SOL 1564 39.330 26.370 3.740 1.00 0.00 +ATOM 4925 HW1 SOL 1564 39.560 25.680 3.120 1.00 0.00 +ATOM 4926 HW2 SOL 1564 39.290 27.170 3.210 1.00 0.00 +ATOM 4927 OW SOL 1565 12.250 41.560 26.690 1.00 0.00 +ATOM 4928 HW1 SOL 1565 12.170 40.610 26.680 1.00 0.00 +ATOM 4929 HW2 SOL 1565 12.980 41.740 27.280 1.00 0.00 +ATOM 4930 OW SOL 1566 16.670 35.790 20.790 1.00 0.00 +ATOM 4931 HW1 SOL 1566 15.960 35.150 20.780 1.00 0.00 +ATOM 4932 HW2 SOL 1566 17.290 35.460 20.130 1.00 0.00 +ATOM 4933 OW SOL 1567 32.700 21.460 20.900 1.00 0.00 +ATOM 4934 HW1 SOL 1567 33.420 20.940 21.260 1.00 0.00 +ATOM 4935 HW2 SOL 1567 32.640 22.210 21.490 1.00 0.00 +ATOM 4936 OW SOL 1568 34.460 6.360 31.110 1.00 0.00 +ATOM 4937 HW1 SOL 1568 35.370 6.620 31.190 1.00 0.00 +ATOM 4938 HW2 SOL 1568 33.960 7.160 31.280 1.00 0.00 +ATOM 4939 OW SOL 1569 34.290 0.310 8.130 1.00 0.00 +ATOM 4940 HW1 SOL 1569 34.260 1.270 8.060 1.00 0.00 +ATOM 4941 HW2 SOL 1569 35.150 0.120 8.470 1.00 0.00 +ATOM 4942 OW SOL 1570 31.390 0.570 23.020 1.00 0.00 +ATOM 4943 HW1 SOL 1570 31.580 -0.290 23.400 1.00 0.00 +ATOM 4944 HW2 SOL 1570 32.230 1.020 23.040 1.00 0.00 +ATOM 4945 OW SOL 1571 34.710 24.070 29.540 1.00 0.00 +ATOM 4946 HW1 SOL 1571 34.610 23.860 30.470 1.00 0.00 +ATOM 4947 HW2 SOL 1571 34.760 25.030 29.520 1.00 0.00 +ATOM 4948 OW SOL 1572 34.680 31.530 18.130 1.00 0.00 +ATOM 4949 HW1 SOL 1572 35.100 31.800 18.940 1.00 0.00 +ATOM 4950 HW2 SOL 1572 35.060 30.680 17.920 1.00 0.00 +ATOM 4951 OW SOL 1573 36.190 8.270 6.680 1.00 0.00 +ATOM 4952 HW1 SOL 1573 35.890 7.990 5.820 1.00 0.00 +ATOM 4953 HW2 SOL 1573 36.740 7.550 6.990 1.00 0.00 +ATOM 4954 OW SOL 1574 0.890 15.270 15.500 1.00 0.00 +ATOM 4955 HW1 SOL 1574 1.020 14.450 15.030 1.00 0.00 +ATOM 4956 HW2 SOL 1574 0.480 15.000 16.330 1.00 0.00 +ATOM 4957 OW SOL 1575 27.410 24.090 9.750 1.00 0.00 +ATOM 4958 HW1 SOL 1575 27.920 24.050 10.560 1.00 0.00 +ATOM 4959 HW2 SOL 1575 26.550 24.410 10.020 1.00 0.00 +ATOM 4960 OW SOL 1576 21.410 3.250 11.050 1.00 0.00 +ATOM 4961 HW1 SOL 1576 21.470 4.170 11.290 1.00 0.00 +ATOM 4962 HW2 SOL 1576 22.090 3.120 10.400 1.00 0.00 +ATOM 4963 OW SOL 1577 36.770 7.010 1.370 1.00 0.00 +ATOM 4964 HW1 SOL 1577 36.390 6.830 0.510 1.00 0.00 +ATOM 4965 HW2 SOL 1577 36.590 7.940 1.530 1.00 0.00 +ATOM 4966 OW SOL 1578 11.450 10.780 25.570 1.00 0.00 +ATOM 4967 HW1 SOL 1578 11.400 10.230 26.350 1.00 0.00 +ATOM 4968 HW2 SOL 1578 10.970 10.290 24.900 1.00 0.00 +ATOM 4969 OW SOL 1579 10.410 21.910 21.270 1.00 0.00 +ATOM 4970 HW1 SOL 1579 10.700 21.410 22.020 1.00 0.00 +ATOM 4971 HW2 SOL 1579 11.210 22.320 20.920 1.00 0.00 +ATOM 4972 OW SOL 1580 45.130 43.800 18.410 1.00 0.00 +ATOM 4973 HW1 SOL 1580 46.010 44.130 18.600 1.00 0.00 +ATOM 4974 HW2 SOL 1580 44.860 43.370 19.230 1.00 0.00 +ATOM 4975 OW SOL 1581 42.030 30.520 6.830 1.00 0.00 +ATOM 4976 HW1 SOL 1581 42.530 31.320 6.680 1.00 0.00 +ATOM 4977 HW2 SOL 1581 41.120 30.800 6.840 1.00 0.00 +ATOM 4978 OW SOL 1582 19.170 41.960 5.510 1.00 0.00 +ATOM 4979 HW1 SOL 1582 19.790 42.670 5.670 1.00 0.00 +ATOM 4980 HW2 SOL 1582 18.340 42.270 5.860 1.00 0.00 +ATOM 4981 OW SOL 1583 24.330 14.240 2.660 1.00 0.00 +ATOM 4982 HW1 SOL 1583 25.250 14.390 2.890 1.00 0.00 +ATOM 4983 HW2 SOL 1583 23.880 15.040 2.920 1.00 0.00 +ATOM 4984 OW SOL 1584 22.580 40.980 10.240 1.00 0.00 +ATOM 4985 HW1 SOL 1584 23.140 41.600 10.690 1.00 0.00 +ATOM 4986 HW2 SOL 1584 22.160 41.480 9.540 1.00 0.00 +ATOM 4987 OW SOL 1585 14.350 41.380 6.330 1.00 0.00 +ATOM 4988 HW1 SOL 1585 14.400 40.460 6.090 1.00 0.00 +ATOM 4989 HW2 SOL 1585 13.760 41.400 7.090 1.00 0.00 +ATOM 4990 OW SOL 1586 2.410 24.630 18.230 1.00 0.00 +ATOM 4991 HW1 SOL 1586 1.950 25.140 18.890 1.00 0.00 +ATOM 4992 HW2 SOL 1586 3.200 25.150 18.040 1.00 0.00 +ATOM 4993 OW SOL 1587 22.410 42.470 1.480 1.00 0.00 +ATOM 4994 HW1 SOL 1587 23.060 41.870 1.100 1.00 0.00 +ATOM 4995 HW2 SOL 1587 22.460 42.310 2.420 1.00 0.00 +ATOM 4996 OW SOL 1588 10.730 21.960 18.120 1.00 0.00 +ATOM 4997 HW1 SOL 1588 10.940 21.240 18.710 1.00 0.00 +ATOM 4998 HW2 SOL 1588 10.080 22.480 18.610 1.00 0.00 +ATOM 4999 OW SOL 1589 17.540 26.610 19.390 1.00 0.00 +ATOM 5000 HW1 SOL 1589 17.960 25.750 19.390 1.00 0.00 +ATOM 5001 HW2 SOL 1589 16.600 26.410 19.320 1.00 0.00 +ATOM 5002 OW SOL 1590 5.210 13.220 17.640 1.00 0.00 +ATOM 5003 HW1 SOL 1590 5.010 13.590 16.780 1.00 0.00 +ATOM 5004 HW2 SOL 1590 4.950 12.300 17.570 1.00 0.00 +ATOM 5005 OW SOL 1591 14.830 18.010 19.080 1.00 0.00 +ATOM 5006 HW1 SOL 1591 15.600 18.300 18.590 1.00 0.00 +ATOM 5007 HW2 SOL 1591 14.640 17.140 18.740 1.00 0.00 +ATOM 5008 OW SOL 1592 23.030 35.660 21.230 1.00 0.00 +ATOM 5009 HW1 SOL 1592 22.240 36.110 21.530 1.00 0.00 +ATOM 5010 HW2 SOL 1592 22.760 34.740 21.130 1.00 0.00 +ATOM 5011 OW SOL 1593 40.910 30.740 15.620 1.00 0.00 +ATOM 5012 HW1 SOL 1593 40.750 31.270 16.400 1.00 0.00 +ATOM 5013 HW2 SOL 1593 41.030 31.380 14.920 1.00 0.00 +ATOM 5014 OW SOL 1594 11.860 23.610 16.270 1.00 0.00 +ATOM 5015 HW1 SOL 1594 11.090 24.180 16.320 1.00 0.00 +ATOM 5016 HW2 SOL 1594 11.690 22.920 16.910 1.00 0.00 +ATOM 5017 OW SOL 1595 14.290 40.230 30.150 1.00 0.00 +ATOM 5018 HW1 SOL 1595 14.150 40.380 31.090 1.00 0.00 +ATOM 5019 HW2 SOL 1595 13.730 40.880 29.720 1.00 0.00 +ATOM 5020 OW SOL 1596 3.950 2.880 17.220 1.00 0.00 +ATOM 5021 HW1 SOL 1596 4.600 2.220 17.000 1.00 0.00 +ATOM 5022 HW2 SOL 1596 3.180 2.380 17.480 1.00 0.00 +ATOM 5023 OW SOL 1597 15.210 20.240 26.610 1.00 0.00 +ATOM 5024 HW1 SOL 1597 14.810 20.060 27.470 1.00 0.00 +ATOM 5025 HW2 SOL 1597 14.590 19.890 25.980 1.00 0.00 +ATOM 5026 OW SOL 1598 16.640 24.610 31.410 1.00 0.00 +ATOM 5027 HW1 SOL 1598 17.420 24.400 31.930 1.00 0.00 +ATOM 5028 HW2 SOL 1598 16.120 25.190 31.970 1.00 0.00 +ATOM 5029 OW SOL 1599 21.210 24.910 26.580 1.00 0.00 +ATOM 5030 HW1 SOL 1599 20.670 25.390 25.950 1.00 0.00 +ATOM 5031 HW2 SOL 1599 20.600 24.640 27.270 1.00 0.00 +ATOM 5032 OW SOL 1600 10.260 1.210 14.080 1.00 0.00 +ATOM 5033 HW1 SOL 1600 10.670 0.730 13.360 1.00 0.00 +ATOM 5034 HW2 SOL 1600 9.320 1.170 13.890 1.00 0.00 +ATOM 5035 OW SOL 1601 28.740 -0.627 9.330 1.00 0.00 +ATOM 5036 HW1 SOL 1601 28.940 -0.157 10.150 1.00 0.00 +ATOM 5037 HW2 SOL 1601 28.640 -1.537 9.590 1.00 0.00 +ATOM 5038 OW SOL 1602 2.700 18.000 24.630 1.00 0.00 +ATOM 5039 HW1 SOL 1602 2.200 18.410 23.920 1.00 0.00 +ATOM 5040 HW2 SOL 1602 2.210 17.200 24.830 1.00 0.00 +ATOM 5041 OW SOL 1603 36.360 34.450 16.620 1.00 0.00 +ATOM 5042 HW1 SOL 1603 35.990 35.260 16.980 1.00 0.00 +ATOM 5043 HW2 SOL 1603 35.710 34.140 16.000 1.00 0.00 +ATOM 5044 OW SOL 1604 31.540 8.390 31.240 1.00 0.00 +ATOM 5045 HW1 SOL 1604 30.840 7.740 31.340 1.00 0.00 +ATOM 5046 HW2 SOL 1604 31.700 8.430 30.300 1.00 0.00 +ATOM 5047 OW SOL 1605 32.170 36.010 2.050 1.00 0.00 +ATOM 5048 HW1 SOL 1605 32.370 35.510 2.840 1.00 0.00 +ATOM 5049 HW2 SOL 1605 31.490 36.630 2.320 1.00 0.00 +ATOM 5050 OW SOL 1606 27.580 27.270 29.950 1.00 0.00 +ATOM 5051 HW1 SOL 1606 27.640 27.210 30.900 1.00 0.00 +ATOM 5052 HW2 SOL 1606 27.220 26.420 29.670 1.00 0.00 +ATOM 5053 OW SOL 1607 37.600 0.370 5.730 1.00 0.00 +ATOM 5054 HW1 SOL 1607 37.260 -0.510 5.530 1.00 0.00 +ATOM 5055 HW2 SOL 1607 37.190 0.930 5.080 1.00 0.00 +ATOM 5056 OW SOL 1608 26.730 12.700 28.300 1.00 0.00 +ATOM 5057 HW1 SOL 1608 26.330 12.050 28.880 1.00 0.00 +ATOM 5058 HW2 SOL 1608 26.000 13.200 27.950 1.00 0.00 +ATOM 5059 OW SOL 1609 43.220 14.060 7.400 1.00 0.00 +ATOM 5060 HW1 SOL 1609 43.540 13.160 7.500 1.00 0.00 +ATOM 5061 HW2 SOL 1609 42.680 14.200 8.180 1.00 0.00 +ATOM 5062 OW SOL 1610 38.860 28.670 22.930 1.00 0.00 +ATOM 5063 HW1 SOL 1610 39.790 28.890 22.980 1.00 0.00 +ATOM 5064 HW2 SOL 1610 38.790 28.080 22.180 1.00 0.00 +ATOM 5065 OW SOL 1611 12.100 4.000 22.050 1.00 0.00 +ATOM 5066 HW1 SOL 1611 12.150 3.040 22.100 1.00 0.00 +ATOM 5067 HW2 SOL 1611 11.300 4.170 21.560 1.00 0.00 +ATOM 5068 OW SOL 1612 23.020 20.700 10.040 1.00 0.00 +ATOM 5069 HW1 SOL 1612 23.880 20.930 9.690 1.00 0.00 +ATOM 5070 HW2 SOL 1612 23.200 20.290 10.880 1.00 0.00 +ATOM 5071 OW SOL 1613 24.820 19.980 19.290 1.00 0.00 +ATOM 5072 HW1 SOL 1613 24.540 19.530 18.500 1.00 0.00 +ATOM 5073 HW2 SOL 1613 25.640 20.420 19.040 1.00 0.00 +ATOM 5074 OW SOL 1614 27.400 8.790 9.910 1.00 0.00 +ATOM 5075 HW1 SOL 1614 26.450 8.880 9.850 1.00 0.00 +ATOM 5076 HW2 SOL 1614 27.720 9.110 9.070 1.00 0.00 +ATOM 5077 OW SOL 1615 40.060 19.610 25.760 1.00 0.00 +ATOM 5078 HW1 SOL 1615 40.310 20.520 25.590 1.00 0.00 +ATOM 5079 HW2 SOL 1615 40.640 19.090 25.200 1.00 0.00 +ATOM 5080 OW SOL 1616 11.030 12.680 0.660 1.00 0.00 +ATOM 5081 HW1 SOL 1616 10.830 13.600 0.830 1.00 0.00 +ATOM 5082 HW2 SOL 1616 10.410 12.190 1.200 1.00 0.00 +ATOM 5083 OW SOL 1617 29.470 39.130 23.880 1.00 0.00 +ATOM 5084 HW1 SOL 1617 30.410 39.030 23.720 1.00 0.00 +ATOM 5085 HW2 SOL 1617 29.410 39.720 24.630 1.00 0.00 +ATOM 5086 OW SOL 1618 36.110 10.290 8.640 1.00 0.00 +ATOM 5087 HW1 SOL 1618 35.230 10.650 8.510 1.00 0.00 +ATOM 5088 HW2 SOL 1618 36.180 9.570 8.010 1.00 0.00 +ATOM 5089 OW SOL 1619 34.830 30.180 14.830 1.00 0.00 +ATOM 5090 HW1 SOL 1619 34.550 29.820 15.670 1.00 0.00 +ATOM 5091 HW2 SOL 1619 35.700 30.560 15.000 1.00 0.00 +ATOM 5092 OW SOL 1620 21.370 33.880 31.420 1.00 0.00 +ATOM 5093 HW1 SOL 1620 22.190 34.320 31.210 1.00 0.00 +ATOM 5094 HW2 SOL 1620 21.370 33.100 30.870 1.00 0.00 +ATOM 5095 OW SOL 1621 6.480 22.090 3.960 1.00 0.00 +ATOM 5096 HW1 SOL 1621 7.120 22.610 4.450 1.00 0.00 +ATOM 5097 HW2 SOL 1621 5.890 21.750 4.630 1.00 0.00 +ATOM 5098 OW SOL 1622 12.240 33.700 9.700 1.00 0.00 +ATOM 5099 HW1 SOL 1622 12.260 33.050 10.410 1.00 0.00 +ATOM 5100 HW2 SOL 1622 12.100 33.180 8.910 1.00 0.00 +ATOM 5101 OW SOL 1623 32.890 41.480 20.390 1.00 0.00 +ATOM 5102 HW1 SOL 1623 32.170 41.210 19.820 1.00 0.00 +ATOM 5103 HW2 SOL 1623 32.480 42.000 21.080 1.00 0.00 +ATOM 5104 OW SOL 1624 12.380 33.230 22.020 1.00 0.00 +ATOM 5105 HW1 SOL 1624 11.820 33.490 22.760 1.00 0.00 +ATOM 5106 HW2 SOL 1624 13.060 33.900 21.990 1.00 0.00 +ATOM 5107 OW SOL 1625 28.910 13.960 30.800 1.00 0.00 +ATOM 5108 HW1 SOL 1625 29.740 14.280 30.460 1.00 0.00 +ATOM 5109 HW2 SOL 1625 28.570 13.380 30.110 1.00 0.00 +ATOM 5110 OW SOL 1626 19.500 10.860 6.060 1.00 0.00 +ATOM 5111 HW1 SOL 1626 19.860 11.580 5.550 1.00 0.00 +ATOM 5112 HW2 SOL 1626 19.320 10.170 5.420 1.00 0.00 +ATOM 5113 OW SOL 1627 34.650 4.500 2.320 1.00 0.00 +ATOM 5114 HW1 SOL 1627 35.560 4.510 2.030 1.00 0.00 +ATOM 5115 HW2 SOL 1627 34.710 4.380 3.270 1.00 0.00 +ATOM 5116 OW SOL 1628 39.150 29.780 18.010 1.00 0.00 +ATOM 5117 HW1 SOL 1628 39.880 29.160 18.090 1.00 0.00 +ATOM 5118 HW2 SOL 1628 39.570 30.600 17.740 1.00 0.00 +ATOM 5119 OW SOL 1629 33.240 14.930 20.270 1.00 0.00 +ATOM 5120 HW1 SOL 1629 32.970 14.060 20.580 1.00 0.00 +ATOM 5121 HW2 SOL 1629 33.390 15.430 21.070 1.00 0.00 +ATOM 5122 OW SOL 1630 24.370 5.810 13.330 1.00 0.00 +ATOM 5123 HW1 SOL 1630 24.170 6.720 13.540 1.00 0.00 +ATOM 5124 HW2 SOL 1630 24.540 5.400 14.180 1.00 0.00 +ATOM 5125 OW SOL 1631 15.790 43.940 31.460 1.00 0.00 +ATOM 5126 HW1 SOL 1631 16.010 44.860 31.500 1.00 0.00 +ATOM 5127 HW2 SOL 1631 14.880 43.900 31.760 1.00 0.00 +ATOM 5128 OW SOL 1632 0.660 21.610 8.200 1.00 0.00 +ATOM 5129 HW1 SOL 1632 1.390 21.150 7.780 1.00 0.00 +ATOM 5130 HW2 SOL 1632 0.480 22.350 7.610 1.00 0.00 +ATOM 5131 OW SOL 1633 16.330 0.760 25.590 1.00 0.00 +ATOM 5132 HW1 SOL 1633 16.870 0.000 25.360 1.00 0.00 +ATOM 5133 HW2 SOL 1633 16.970 1.430 25.850 1.00 0.00 +ATOM 5134 OW SOL 1634 44.520 12.090 15.980 1.00 0.00 +ATOM 5135 HW1 SOL 1634 43.720 11.640 16.260 1.00 0.00 +ATOM 5136 HW2 SOL 1634 44.760 12.650 16.720 1.00 0.00 +ATOM 5137 OW SOL 1635 19.800 26.070 30.680 1.00 0.00 +ATOM 5138 HW1 SOL 1635 19.800 25.560 29.870 1.00 0.00 +ATOM 5139 HW2 SOL 1635 19.080 26.690 30.570 1.00 0.00 +ATOM 5140 OW SOL 1636 44.200 30.470 15.850 1.00 0.00 +ATOM 5141 HW1 SOL 1636 44.960 30.980 16.120 1.00 0.00 +ATOM 5142 HW2 SOL 1636 43.610 30.510 16.600 1.00 0.00 +ATOM 5143 OW SOL 1637 23.930 3.400 9.010 1.00 0.00 +ATOM 5144 HW1 SOL 1637 23.860 3.730 8.110 1.00 0.00 +ATOM 5145 HW2 SOL 1637 24.480 2.620 8.940 1.00 0.00 +ATOM 5146 OW SOL 1638 21.850 9.280 10.410 1.00 0.00 +ATOM 5147 HW1 SOL 1638 22.380 8.820 9.750 1.00 0.00 +ATOM 5148 HW2 SOL 1638 21.070 9.560 9.930 1.00 0.00 +ATOM 5149 OW SOL 1639 17.970 43.370 17.640 1.00 0.00 +ATOM 5150 HW1 SOL 1639 17.960 44.150 17.090 1.00 0.00 +ATOM 5151 HW2 SOL 1639 18.250 43.690 18.500 1.00 0.00 +ATOM 5152 OW SOL 1640 27.020 18.020 18.010 1.00 0.00 +ATOM 5153 HW1 SOL 1640 26.080 18.150 18.040 1.00 0.00 +ATOM 5154 HW2 SOL 1640 27.180 17.550 17.190 1.00 0.00 +ATOM 5155 OW SOL 1641 20.130 27.440 10.860 1.00 0.00 +ATOM 5156 HW1 SOL 1641 19.860 27.460 11.780 1.00 0.00 +ATOM 5157 HW2 SOL 1641 20.500 26.570 10.730 1.00 0.00 +ATOM 5158 OW SOL 1642 0.050 8.880 20.520 1.00 0.00 +ATOM 5159 HW1 SOL 1642 0.960 9.170 20.440 1.00 0.00 +ATOM 5160 HW2 SOL 1642 0.090 8.130 21.110 1.00 0.00 +ATOM 5161 OW SOL 1643 0.940 4.260 4.710 1.00 0.00 +ATOM 5162 HW1 SOL 1643 0.690 3.750 3.940 1.00 0.00 +ATOM 5163 HW2 SOL 1643 1.880 4.110 4.800 1.00 0.00 +ATOM 5164 OW SOL 1644 15.600 9.340 30.830 1.00 0.00 +ATOM 5165 HW1 SOL 1644 15.780 10.170 31.270 1.00 0.00 +ATOM 5166 HW2 SOL 1644 14.880 8.960 31.340 1.00 0.00 +ATOM 5167 OW SOL 1645 26.670 41.540 19.180 1.00 0.00 +ATOM 5168 HW1 SOL 1645 26.770 41.540 18.230 1.00 0.00 +ATOM 5169 HW2 SOL 1645 26.500 40.630 19.410 1.00 0.00 +ATOM 5170 OW SOL 1646 30.640 44.230 0.920 1.00 0.00 +ATOM 5171 HW1 SOL 1646 30.950 44.540 1.770 1.00 0.00 +ATOM 5172 HW2 SOL 1646 29.700 44.400 0.920 1.00 0.00 +ATOM 5173 OW SOL 1647 34.080 44.450 0.610 1.00 0.00 +ATOM 5174 HW1 SOL 1647 34.760 44.200 -0.020 1.00 0.00 +ATOM 5175 HW2 SOL 1647 33.250 44.260 0.160 1.00 0.00 +ATOM 5176 OW SOL 1648 27.850 44.650 0.390 1.00 0.00 +ATOM 5177 HW1 SOL 1648 27.320 44.090 -0.170 1.00 0.00 +ATOM 5178 HW2 SOL 1648 27.460 45.520 0.310 1.00 0.00 +ATOM 5179 OW SOL 1649 -6.639 35.829 -0.868 1.00 0.00 +ATOM 5180 HW1 SOL 1649 -7.279 36.439 -0.498 1.00 0.00 +ATOM 5181 HW2 SOL 1649 -6.379 35.269 -0.138 1.00 0.00 +ATOM 5182 OW SOL 1650 25.120 32.330 23.340 1.00 0.00 +ATOM 5183 HW1 SOL 1650 25.130 32.100 22.410 1.00 0.00 +ATOM 5184 HW2 SOL 1650 25.130 31.490 23.800 1.00 0.00 +ATOM 5185 OW SOL 1651 22.820 43.300 17.800 1.00 0.00 +ATOM 5186 HW1 SOL 1651 23.710 43.620 17.970 1.00 0.00 +ATOM 5187 HW2 SOL 1651 22.940 42.450 17.400 1.00 0.00 +ATOM 5188 OW SOL 1652 44.630 5.260 30.630 1.00 0.00 +ATOM 5189 HW1 SOL 1652 44.480 4.710 31.400 1.00 0.00 +ATOM 5190 HW2 SOL 1652 44.440 4.690 29.890 1.00 0.00 +ATOM 5191 OW SOL 1653 44.200 38.080 28.100 1.00 0.00 +ATOM 5192 HW1 SOL 1653 43.890 38.020 27.200 1.00 0.00 +ATOM 5193 HW2 SOL 1653 43.400 38.050 28.630 1.00 0.00 +ATOM 5194 OW SOL 1654 38.870 6.380 8.880 1.00 0.00 +ATOM 5195 HW1 SOL 1654 39.170 5.840 8.150 1.00 0.00 +ATOM 5196 HW2 SOL 1654 39.540 6.260 9.550 1.00 0.00 +ATOM 5197 OW SOL 1655 28.400 31.240 26.720 1.00 0.00 +ATOM 5198 HW1 SOL 1655 28.150 30.570 27.360 1.00 0.00 +ATOM 5199 HW2 SOL 1655 28.670 30.740 25.950 1.00 0.00 +ATOM 5200 OW SOL 1656 26.230 44.550 21.040 1.00 0.00 +ATOM 5201 HW1 SOL 1656 26.570 43.740 21.420 1.00 0.00 +ATOM 5202 HW2 SOL 1656 25.780 44.990 21.770 1.00 0.00 +ATOM 5203 OW SOL 1657 25.850 45.377 11.400 1.00 0.00 +ATOM 5204 HW1 SOL 1657 26.580 45.967 11.600 1.00 0.00 +ATOM 5205 HW2 SOL 1657 26.100 44.547 11.820 1.00 0.00 +ATOM 5206 OW SOL 1658 25.720 31.900 6.290 1.00 0.00 +ATOM 5207 HW1 SOL 1658 24.820 31.930 5.960 1.00 0.00 +ATOM 5208 HW2 SOL 1658 26.260 32.090 5.520 1.00 0.00 +ATOM 5209 OW SOL 1659 12.500 10.960 22.620 1.00 0.00 +ATOM 5210 HW1 SOL 1659 12.160 10.260 23.180 1.00 0.00 +ATOM 5211 HW2 SOL 1659 11.710 11.390 22.280 1.00 0.00 +ATOM 5212 OW SOL 1660 26.880 21.440 18.360 1.00 0.00 +ATOM 5213 HW1 SOL 1660 27.490 20.950 17.820 1.00 0.00 +ATOM 5214 HW2 SOL 1660 26.790 22.280 17.920 1.00 0.00 +ATOM 5215 OW SOL 1661 35.340 32.300 20.500 1.00 0.00 +ATOM 5216 HW1 SOL 1661 36.170 31.960 20.850 1.00 0.00 +ATOM 5217 HW2 SOL 1661 34.670 31.770 20.930 1.00 0.00 +ATOM 5218 OW SOL 1662 19.720 5.820 1.580 1.00 0.00 +ATOM 5219 HW1 SOL 1662 19.630 5.350 0.750 1.00 0.00 +ATOM 5220 HW2 SOL 1662 18.820 5.860 1.930 1.00 0.00 +ATOM 5221 OW SOL 1663 19.610 21.400 27.020 1.00 0.00 +ATOM 5222 HW1 SOL 1663 20.160 21.170 26.270 1.00 0.00 +ATOM 5223 HW2 SOL 1663 20.130 21.160 27.780 1.00 0.00 +ATOM 5224 OW SOL 1664 26.820 43.140 12.460 1.00 0.00 +ATOM 5225 HW1 SOL 1664 27.470 42.730 11.890 1.00 0.00 +ATOM 5226 HW2 SOL 1664 26.490 42.420 13.000 1.00 0.00 +ATOM 5227 OW SOL 1665 30.140 22.110 23.770 1.00 0.00 +ATOM 5228 HW1 SOL 1665 30.390 22.210 24.700 1.00 0.00 +ATOM 5229 HW2 SOL 1665 30.410 22.940 23.370 1.00 0.00 +ATOM 5230 OW SOL 1666 27.240 33.840 24.390 1.00 0.00 +ATOM 5231 HW1 SOL 1666 27.040 34.670 23.960 1.00 0.00 +ATOM 5232 HW2 SOL 1666 26.510 33.260 24.140 1.00 0.00 +ATOM 5233 OW SOL 1667 34.700 0.740 30.900 1.00 0.00 +ATOM 5234 HW1 SOL 1667 34.590 1.680 31.000 1.00 0.00 +ATOM 5235 HW2 SOL 1667 35.490 0.640 30.370 1.00 0.00 +ATOM 5236 OW SOL 1668 37.100 11.140 30.210 1.00 0.00 +ATOM 5237 HW1 SOL 1668 36.900 10.440 30.840 1.00 0.00 +ATOM 5238 HW2 SOL 1668 37.710 11.710 30.680 1.00 0.00 +ATOM 5239 OW SOL 1669 15.530 22.000 16.820 1.00 0.00 +ATOM 5240 HW1 SOL 1669 16.150 21.570 17.410 1.00 0.00 +ATOM 5241 HW2 SOL 1669 15.060 21.270 16.410 1.00 0.00 +ATOM 5242 OW SOL 1670 18.070 45.240 19.970 1.00 0.00 +ATOM 5243 HW1 SOL 1670 17.130 45.070 19.920 1.00 0.00 +ATOM 5244 HW2 SOL 1670 18.160 45.910 20.640 1.00 0.00 +ATOM 5245 OW SOL 1671 9.160 37.170 18.100 1.00 0.00 +ATOM 5246 HW1 SOL 1671 8.350 37.200 17.580 1.00 0.00 +ATOM 5247 HW2 SOL 1671 9.000 36.480 18.750 1.00 0.00 +ATOM 5248 OW SOL 1672 16.880 38.450 6.160 1.00 0.00 +ATOM 5249 HW1 SOL 1672 16.920 39.020 6.930 1.00 0.00 +ATOM 5250 HW2 SOL 1672 16.040 37.990 6.240 1.00 0.00 +ATOM 5251 OW SOL 1673 33.350 9.050 9.820 1.00 0.00 +ATOM 5252 HW1 SOL 1673 34.020 8.840 10.480 1.00 0.00 +ATOM 5253 HW2 SOL 1673 33.710 9.810 9.360 1.00 0.00 +ATOM 5254 OW SOL 1674 38.610 32.900 13.090 1.00 0.00 +ATOM 5255 HW1 SOL 1674 39.370 33.490 13.170 1.00 0.00 +ATOM 5256 HW2 SOL 1674 38.320 32.760 13.990 1.00 0.00 +ATOM 5257 OW SOL 1675 22.480 0.240 0.210 1.00 0.00 +ATOM 5258 HW1 SOL 1675 22.100 -0.390 -0.400 1.00 0.00 +ATOM 5259 HW2 SOL 1675 23.110 0.730 -0.320 1.00 0.00 +ATOM 5260 OW SOL 1676 2.100 41.050 19.130 1.00 0.00 +ATOM 5261 HW1 SOL 1676 1.920 41.100 18.190 1.00 0.00 +ATOM 5262 HW2 SOL 1676 1.450 41.620 19.530 1.00 0.00 +ATOM 5263 OW SOL 1677 37.240 6.270 25.760 1.00 0.00 +ATOM 5264 HW1 SOL 1677 36.630 5.980 26.440 1.00 0.00 +ATOM 5265 HW2 SOL 1677 37.100 5.670 25.030 1.00 0.00 +ATOM 5266 OW SOL 1678 0.250 0.310 26.310 1.00 0.00 +ATOM 5267 HW1 SOL 1678 0.220 0.990 26.970 1.00 0.00 +ATOM 5268 HW2 SOL 1678 1.150 0.340 25.980 1.00 0.00 +ATOM 5269 OW SOL 1679 34.820 17.970 24.750 1.00 0.00 +ATOM 5270 HW1 SOL 1679 33.950 17.940 25.150 1.00 0.00 +ATOM 5271 HW2 SOL 1679 35.400 18.250 25.460 1.00 0.00 +ATOM 5272 OW SOL 1680 4.510 9.100 3.810 1.00 0.00 +ATOM 5273 HW1 SOL 1680 3.680 9.030 4.290 1.00 0.00 +ATOM 5274 HW2 SOL 1680 5.110 9.520 4.430 1.00 0.00 +ATOM 5275 OW SOL 1681 44.930 13.440 29.260 1.00 0.00 +ATOM 5276 HW1 SOL 1681 45.860 13.550 29.110 1.00 0.00 +ATOM 5277 HW2 SOL 1681 44.800 12.490 29.290 1.00 0.00 +ATOM 5278 OW SOL 1682 38.250 40.480 21.660 1.00 0.00 +ATOM 5279 HW1 SOL 1682 37.570 41.110 21.410 1.00 0.00 +ATOM 5280 HW2 SOL 1682 37.830 39.920 22.310 1.00 0.00 +ATOM 5281 OW SOL 1683 33.060 33.980 11.040 1.00 0.00 +ATOM 5282 HW1 SOL 1683 32.860 34.720 10.460 1.00 0.00 +ATOM 5283 HW2 SOL 1683 33.990 34.080 11.250 1.00 0.00 +ATOM 5284 OW SOL 1684 18.990 35.170 13.560 1.00 0.00 +ATOM 5285 HW1 SOL 1684 19.480 35.210 14.380 1.00 0.00 +ATOM 5286 HW2 SOL 1684 18.770 36.080 13.370 1.00 0.00 +ATOM 5287 OW SOL 1685 32.600 11.340 4.000 1.00 0.00 +ATOM 5288 HW1 SOL 1685 32.690 11.750 4.870 1.00 0.00 +ATOM 5289 HW2 SOL 1685 32.340 12.060 3.430 1.00 0.00 +ATOM 5290 OW SOL 1686 34.700 15.790 30.430 1.00 0.00 +ATOM 5291 HW1 SOL 1686 34.310 16.570 30.030 1.00 0.00 +ATOM 5292 HW2 SOL 1686 33.990 15.150 30.460 1.00 0.00 +ATOM 5293 OW SOL 1687 8.140 37.830 10.230 1.00 0.00 +ATOM 5294 HW1 SOL 1687 8.010 37.290 9.450 1.00 0.00 +ATOM 5295 HW2 SOL 1687 7.640 37.380 10.910 1.00 0.00 +ATOM 5296 OW SOL 1688 6.200 23.890 12.840 1.00 0.00 +ATOM 5297 HW1 SOL 1688 5.390 23.380 12.920 1.00 0.00 +ATOM 5298 HW2 SOL 1688 6.780 23.330 12.310 1.00 0.00 +ATOM 5299 OW SOL 1689 39.270 2.590 31.630 1.00 0.00 +ATOM 5300 HW1 SOL 1689 39.040 3.500 31.830 1.00 0.00 +ATOM 5301 HW2 SOL 1689 39.320 2.560 30.680 1.00 0.00 +ATOM 5302 OW SOL 1690 28.629 34.419 33.278 1.00 0.00 +ATOM 5303 HW1 SOL 1690 28.309 34.989 32.568 1.00 0.00 +ATOM 5304 HW2 SOL 1690 28.119 34.679 34.038 1.00 0.00 +ATOM 5305 OW SOL 1691 30.560 40.610 19.370 1.00 0.00 +ATOM 5306 HW1 SOL 1691 29.950 40.660 18.630 1.00 0.00 +ATOM 5307 HW2 SOL 1691 30.030 40.300 20.100 1.00 0.00 +ATOM 5308 OW SOL 1692 39.210 26.540 11.030 1.00 0.00 +ATOM 5309 HW1 SOL 1692 38.440 26.190 11.480 1.00 0.00 +ATOM 5310 HW2 SOL 1692 39.710 26.970 11.720 1.00 0.00 +ATOM 5311 OW SOL 1693 38.620 38.670 16.350 1.00 0.00 +ATOM 5312 HW1 SOL 1693 39.350 38.460 16.930 1.00 0.00 +ATOM 5313 HW2 SOL 1693 39.030 38.800 15.500 1.00 0.00 +ATOM 5314 OW SOL 1694 3.290 14.640 26.590 1.00 0.00 +ATOM 5315 HW1 SOL 1694 2.820 14.930 25.800 1.00 0.00 +ATOM 5316 HW2 SOL 1694 4.120 14.290 26.260 1.00 0.00 +ATOM 5317 OW SOL 1695 27.780 8.940 24.740 1.00 0.00 +ATOM 5318 HW1 SOL 1695 27.350 9.300 23.960 1.00 0.00 +ATOM 5319 HW2 SOL 1695 28.400 8.290 24.400 1.00 0.00 +ATOM 5320 OW SOL 1696 34.760 17.500 1.860 1.00 0.00 +ATOM 5321 HW1 SOL 1696 35.660 17.210 2.010 1.00 0.00 +ATOM 5322 HW2 SOL 1696 34.840 18.250 1.260 1.00 0.00 +ATOM 5323 OW SOL 1697 21.600 22.560 19.050 1.00 0.00 +ATOM 5324 HW1 SOL 1697 22.150 22.320 19.800 1.00 0.00 +ATOM 5325 HW2 SOL 1697 21.860 23.450 18.840 1.00 0.00 +ATOM 5326 OW SOL 1698 17.140 4.080 23.600 1.00 0.00 +ATOM 5327 HW1 SOL 1698 16.740 4.090 24.470 1.00 0.00 +ATOM 5328 HW2 SOL 1698 18.070 4.260 23.760 1.00 0.00 +ATOM 5329 OW SOL 1699 22.230 14.440 15.140 1.00 0.00 +ATOM 5330 HW1 SOL 1699 21.760 14.470 15.970 1.00 0.00 +ATOM 5331 HW2 SOL 1699 22.990 15.000 15.270 1.00 0.00 +ATOM 5332 OW SOL 1700 7.330 35.280 3.790 1.00 0.00 +ATOM 5333 HW1 SOL 1700 7.250 34.630 4.480 1.00 0.00 +ATOM 5334 HW2 SOL 1700 7.090 36.110 4.200 1.00 0.00 +ATOM 5335 OW SOL 1701 43.730 24.490 26.750 1.00 0.00 +ATOM 5336 HW1 SOL 1701 43.500 24.970 25.950 1.00 0.00 +ATOM 5337 HW2 SOL 1701 44.280 23.770 26.450 1.00 0.00 +ATOM 5338 OW SOL 1702 10.500 37.490 11.790 1.00 0.00 +ATOM 5339 HW1 SOL 1702 10.060 36.760 12.210 1.00 0.00 +ATOM 5340 HW2 SOL 1702 9.810 37.940 11.300 1.00 0.00 +ATOM 5341 OW SOL 1703 43.580 15.280 13.780 1.00 0.00 +ATOM 5342 HW1 SOL 1703 43.760 15.370 12.850 1.00 0.00 +ATOM 5343 HW2 SOL 1703 44.440 15.210 14.190 1.00 0.00 +ATOM 5344 OW SOL 1704 44.120 0.740 2.060 1.00 0.00 +ATOM 5345 HW1 SOL 1704 43.530 0.070 2.380 1.00 0.00 +ATOM 5346 HW2 SOL 1704 44.730 0.280 1.480 1.00 0.00 +ATOM 5347 OW SOL 1705 30.140 5.770 0.990 1.00 0.00 +ATOM 5348 HW1 SOL 1705 30.850 5.780 1.620 1.00 0.00 +ATOM 5349 HW2 SOL 1705 29.380 5.470 1.480 1.00 0.00 +ATOM 5350 OW SOL 1706 13.470 21.660 0.960 1.00 0.00 +ATOM 5351 HW1 SOL 1706 13.510 22.260 1.700 1.00 0.00 +ATOM 5352 HW2 SOL 1706 12.980 22.140 0.290 1.00 0.00 +ATOM 5353 OW SOL 1707 9.450 41.130 13.790 1.00 0.00 +ATOM 5354 HW1 SOL 1707 9.970 40.320 13.870 1.00 0.00 +ATOM 5355 HW2 SOL 1707 9.950 41.670 13.180 1.00 0.00 +ATOM 5356 OW SOL 1708 37.980 18.260 31.750 1.00 0.00 +ATOM 5357 HW1 SOL 1708 38.330 18.750 31.010 1.00 0.00 +ATOM 5358 HW2 SOL 1708 37.120 18.640 31.920 1.00 0.00 +ATOM 5359 OW SOL 1709 40.570 10.160 25.100 1.00 0.00 +ATOM 5360 HW1 SOL 1709 40.290 9.470 25.710 1.00 0.00 +ATOM 5361 HW2 SOL 1709 41.520 10.050 25.050 1.00 0.00 +ATOM 5362 OW SOL 1710 35.730 6.430 13.090 1.00 0.00 +ATOM 5363 HW1 SOL 1710 34.790 6.260 13.120 1.00 0.00 +ATOM 5364 HW2 SOL 1710 35.860 6.880 12.260 1.00 0.00 +ATOM 5365 OW SOL 1711 23.950 40.480 16.600 1.00 0.00 +ATOM 5366 HW1 SOL 1711 24.580 39.950 17.090 1.00 0.00 +ATOM 5367 HW2 SOL 1711 24.450 40.780 15.840 1.00 0.00 +ATOM 5368 OW SOL 1712 36.290 28.940 8.460 1.00 0.00 +ATOM 5369 HW1 SOL 1712 36.080 29.740 8.950 1.00 0.00 +ATOM 5370 HW2 SOL 1712 35.600 28.870 7.800 1.00 0.00 +ATOM 5371 OW SOL 1713 17.050 9.740 12.220 1.00 0.00 +ATOM 5372 HW1 SOL 1713 17.220 10.660 12.050 1.00 0.00 +ATOM 5373 HW2 SOL 1713 16.100 9.690 12.310 1.00 0.00 +ATOM 5374 OW SOL 1714 0.310 29.670 28.570 1.00 0.00 +ATOM 5375 HW1 SOL 1714 1.170 29.440 28.910 1.00 0.00 +ATOM 5376 HW2 SOL 1714 0.410 29.630 27.610 1.00 0.00 +ATOM 5377 OW SOL 1715 14.740 28.240 11.730 1.00 0.00 +ATOM 5378 HW1 SOL 1715 15.050 28.860 12.380 1.00 0.00 +ATOM 5379 HW2 SOL 1715 13.950 28.640 11.370 1.00 0.00 +ATOM 5380 OW SOL 1716 16.790 7.950 2.460 1.00 0.00 +ATOM 5381 HW1 SOL 1716 16.210 7.210 2.640 1.00 0.00 +ATOM 5382 HW2 SOL 1716 16.220 8.720 2.520 1.00 0.00 +ATOM 5383 OW SOL 1717 16.280 44.490 8.020 1.00 0.00 +ATOM 5384 HW1 SOL 1717 16.030 45.390 7.800 1.00 0.00 +ATOM 5385 HW2 SOL 1717 15.510 44.130 8.460 1.00 0.00 +ATOM 5386 OW SOL 1718 11.820 17.370 14.470 1.00 0.00 +ATOM 5387 HW1 SOL 1718 11.160 17.700 15.080 1.00 0.00 +ATOM 5388 HW2 SOL 1718 12.630 17.370 14.970 1.00 0.00 +ATOM 5389 OW SOL 1719 43.510 41.040 17.200 1.00 0.00 +ATOM 5390 HW1 SOL 1719 43.870 40.420 16.560 1.00 0.00 +ATOM 5391 HW2 SOL 1719 43.520 41.880 16.740 1.00 0.00 +ATOM 5392 OW SOL 1720 6.150 34.530 9.150 1.00 0.00 +ATOM 5393 HW1 SOL 1720 5.730 35.390 9.120 1.00 0.00 +ATOM 5394 HW2 SOL 1720 5.910 34.180 10.010 1.00 0.00 +ATOM 5395 OW SOL 1721 23.730 40.440 6.380 1.00 0.00 +ATOM 5396 HW1 SOL 1721 23.320 39.750 5.860 1.00 0.00 +ATOM 5397 HW2 SOL 1721 23.960 40.020 7.210 1.00 0.00 +ATOM 5398 OW SOL 1722 14.680 43.440 11.240 1.00 0.00 +ATOM 5399 HW1 SOL 1722 15.580 43.760 11.160 1.00 0.00 +ATOM 5400 HW2 SOL 1722 14.710 42.540 10.920 1.00 0.00 +ATOM 5401 OW SOL 1723 3.560 6.730 6.990 1.00 0.00 +ATOM 5402 HW1 SOL 1723 3.240 7.230 6.240 1.00 0.00 +ATOM 5403 HW2 SOL 1723 3.630 5.840 6.670 1.00 0.00 +ATOM 5404 OW SOL 1724 16.600 10.720 27.210 1.00 0.00 +ATOM 5405 HW1 SOL 1724 17.080 10.080 26.690 1.00 0.00 +ATOM 5406 HW2 SOL 1724 17.260 11.130 27.770 1.00 0.00 +ATOM 5407 OW SOL 1725 17.660 42.800 29.840 1.00 0.00 +ATOM 5408 HW1 SOL 1725 16.840 43.000 30.290 1.00 0.00 +ATOM 5409 HW2 SOL 1725 18.210 42.400 30.510 1.00 0.00 +ATOM 5410 OW SOL 1726 0.040 8.050 11.450 1.00 0.00 +ATOM 5411 HW1 SOL 1726 0.520 8.320 10.670 1.00 0.00 +ATOM 5412 HW2 SOL 1726 -0.780 8.550 11.400 1.00 0.00 +ATOM 5413 OW SOL 1727 35.190 2.950 28.570 1.00 0.00 +ATOM 5414 HW1 SOL 1727 34.700 2.410 27.950 1.00 0.00 +ATOM 5415 HW2 SOL 1727 35.900 2.380 28.880 1.00 0.00 +ATOM 5416 OW SOL 1728 21.670 2.700 2.800 1.00 0.00 +ATOM 5417 HW1 SOL 1728 21.370 1.890 3.210 1.00 0.00 +ATOM 5418 HW2 SOL 1728 21.370 3.400 3.380 1.00 0.00 +ATOM 5419 OW SOL 1729 39.660 6.890 0.330 1.00 0.00 +ATOM 5420 HW1 SOL 1729 39.170 7.710 0.420 1.00 0.00 +ATOM 5421 HW2 SOL 1729 40.490 7.060 0.780 1.00 0.00 +ATOM 5422 OW SOL 1730 43.580 41.000 11.360 1.00 0.00 +ATOM 5423 HW1 SOL 1730 42.700 41.000 11.000 1.00 0.00 +ATOM 5424 HW2 SOL 1730 43.680 41.860 11.760 1.00 0.00 +ATOM 5425 OW SOL 1731 41.260 3.110 1.330 1.00 0.00 +ATOM 5426 HW1 SOL 1731 41.800 3.610 1.950 1.00 0.00 +ATOM 5427 HW2 SOL 1731 41.620 3.340 0.470 1.00 0.00 +ATOM 5428 OW SOL 1732 43.770 15.870 22.660 1.00 0.00 +ATOM 5429 HW1 SOL 1732 43.950 15.670 21.750 1.00 0.00 +ATOM 5430 HW2 SOL 1732 44.380 16.580 22.880 1.00 0.00 +ATOM 5431 OW SOL 1733 37.140 0.840 29.620 1.00 0.00 +ATOM 5432 HW1 SOL 1733 37.740 1.350 30.160 1.00 0.00 +ATOM 5433 HW2 SOL 1733 37.700 0.260 29.100 1.00 0.00 +ATOM 5434 OW SOL 1734 37.970 13.120 27.180 1.00 0.00 +ATOM 5435 HW1 SOL 1734 37.640 12.800 28.020 1.00 0.00 +ATOM 5436 HW2 SOL 1734 38.910 13.250 27.330 1.00 0.00 +ATOM 5437 OW SOL 1735 44.290 2.460 24.510 1.00 0.00 +ATOM 5438 HW1 SOL 1735 43.960 2.740 25.360 1.00 0.00 +ATOM 5439 HW2 SOL 1735 44.960 1.810 24.710 1.00 0.00 +ATOM 5440 OW SOL 1736 42.110 29.760 30.210 1.00 0.00 +ATOM 5441 HW1 SOL 1736 42.380 29.220 29.480 1.00 0.00 +ATOM 5442 HW2 SOL 1736 41.320 29.340 30.550 1.00 0.00 +ATOM 5443 OW SOL 1737 25.010 11.700 4.310 1.00 0.00 +ATOM 5444 HW1 SOL 1737 24.700 12.050 3.470 1.00 0.00 +ATOM 5445 HW2 SOL 1737 24.740 12.350 4.950 1.00 0.00 +ATOM 5446 OW SOL 1738 0.140 3.240 12.170 1.00 0.00 +ATOM 5447 HW1 SOL 1738 -0.290 3.160 11.320 1.00 0.00 +ATOM 5448 HW2 SOL 1738 -0.570 3.160 12.810 1.00 0.00 +ATOM 5449 OW SOL 1739 13.650 12.050 0.190 1.00 0.00 +ATOM 5450 HW1 SOL 1739 12.690 12.020 0.120 1.00 0.00 +ATOM 5451 HW2 SOL 1739 13.860 12.980 0.230 1.00 0.00 +ATOM 5452 OW SOL 1740 19.190 21.850 9.000 1.00 0.00 +ATOM 5453 HW1 SOL 1740 19.000 21.090 9.540 1.00 0.00 +ATOM 5454 HW2 SOL 1740 19.980 22.220 9.390 1.00 0.00 +ATOM 5455 OW SOL 1741 17.850 12.320 29.130 1.00 0.00 +ATOM 5456 HW1 SOL 1741 18.180 13.020 28.560 1.00 0.00 +ATOM 5457 HW2 SOL 1741 17.280 12.770 29.750 1.00 0.00 +ATOM 5458 OW SOL 1742 11.830 38.010 18.650 1.00 0.00 +ATOM 5459 HW1 SOL 1742 10.880 38.090 18.590 1.00 0.00 +ATOM 5460 HW2 SOL 1742 12.060 38.370 19.500 1.00 0.00 +ATOM 5461 OW SOL 1743 41.250 18.160 23.660 1.00 0.00 +ATOM 5462 HW1 SOL 1743 42.150 17.840 23.640 1.00 0.00 +ATOM 5463 HW2 SOL 1743 40.720 17.400 23.400 1.00 0.00 +ATOM 5464 OW SOL 1744 1.150 29.670 25.630 1.00 0.00 +ATOM 5465 HW1 SOL 1744 1.590 29.960 24.830 1.00 0.00 +ATOM 5466 HW2 SOL 1744 1.040 28.730 25.510 1.00 0.00 +ATOM 5467 OW SOL 1745 19.590 19.640 3.380 1.00 0.00 +ATOM 5468 HW1 SOL 1745 20.170 20.360 3.140 1.00 0.00 +ATOM 5469 HW2 SOL 1745 20.150 19.050 3.900 1.00 0.00 +ATOM 5470 OW SOL 1746 11.310 4.940 24.520 1.00 0.00 +ATOM 5471 HW1 SOL 1746 11.440 4.940 23.570 1.00 0.00 +ATOM 5472 HW2 SOL 1746 11.030 4.040 24.710 1.00 0.00 +ATOM 5473 OW SOL 1747 25.190 41.460 14.170 1.00 0.00 +ATOM 5474 HW1 SOL 1747 25.150 40.710 13.580 1.00 0.00 +ATOM 5475 HW2 SOL 1747 24.450 42.000 13.910 1.00 0.00 +ATOM 5476 OW SOL 1748 43.850 3.920 26.810 1.00 0.00 +ATOM 5477 HW1 SOL 1748 44.650 4.060 27.330 1.00 0.00 +ATOM 5478 HW2 SOL 1748 43.780 4.710 26.280 1.00 0.00 +ATOM 5479 OW SOL 1749 42.770 12.600 19.350 1.00 0.00 +ATOM 5480 HW1 SOL 1749 42.080 13.260 19.360 1.00 0.00 +ATOM 5481 HW2 SOL 1749 42.690 12.180 18.490 1.00 0.00 +ATOM 5482 OW SOL 1750 29.710 32.190 13.670 1.00 0.00 +ATOM 5483 HW1 SOL 1750 29.440 32.610 12.850 1.00 0.00 +ATOM 5484 HW2 SOL 1750 30.660 32.190 13.650 1.00 0.00 +ATOM 5485 OW SOL 1751 34.590 34.810 19.630 1.00 0.00 +ATOM 5486 HW1 SOL 1751 34.800 33.970 20.060 1.00 0.00 +ATOM 5487 HW2 SOL 1751 34.870 34.680 18.720 1.00 0.00 +ATOM 5488 OW SOL 1752 14.710 17.530 31.720 1.00 0.00 +ATOM 5489 HW1 SOL 1752 14.660 18.060 30.920 1.00 0.00 +ATOM 5490 HW2 SOL 1752 14.790 18.160 32.430 1.00 0.00 +ATOM 5491 OW SOL 1753 19.450 9.200 8.330 1.00 0.00 +ATOM 5492 HW1 SOL 1753 18.540 8.900 8.310 1.00 0.00 +ATOM 5493 HW2 SOL 1753 19.550 9.700 7.520 1.00 0.00 +ATOM 5494 OW SOL 1754 6.560 28.750 29.700 1.00 0.00 +ATOM 5495 HW1 SOL 1754 6.240 28.280 30.470 1.00 0.00 +ATOM 5496 HW2 SOL 1754 6.440 29.670 29.920 1.00 0.00 +ATOM 5497 OW SOL 1755 18.670 18.320 23.230 1.00 0.00 +ATOM 5498 HW1 SOL 1755 17.790 18.560 23.540 1.00 0.00 +ATOM 5499 HW2 SOL 1755 18.550 18.130 22.300 1.00 0.00 +ATOM 5500 OW SOL 1756 28.140 14.010 14.840 1.00 0.00 +ATOM 5501 HW1 SOL 1756 28.610 13.440 15.450 1.00 0.00 +ATOM 5502 HW2 SOL 1756 28.820 14.380 14.280 1.00 0.00 +ATOM 5503 OW SOL 1757 23.950 6.480 23.770 1.00 0.00 +ATOM 5504 HW1 SOL 1757 24.230 7.210 24.320 1.00 0.00 +ATOM 5505 HW2 SOL 1757 23.030 6.660 23.570 1.00 0.00 +ATOM 5506 OW SOL 1758 21.110 7.290 23.290 1.00 0.00 +ATOM 5507 HW1 SOL 1758 20.950 6.660 22.580 1.00 0.00 +ATOM 5508 HW2 SOL 1758 21.050 8.150 22.870 1.00 0.00 +ATOM 5509 OW SOL 1759 42.310 19.480 8.430 1.00 0.00 +ATOM 5510 HW1 SOL 1759 41.510 19.100 8.800 1.00 0.00 +ATOM 5511 HW2 SOL 1759 42.920 19.530 9.160 1.00 0.00 +ATOM 5512 OW SOL 1760 30.950 34.400 0.280 1.00 0.00 +ATOM 5513 HW1 SOL 1760 31.570 35.070 0.570 1.00 0.00 +ATOM 5514 HW2 SOL 1760 31.490 33.760 -0.180 1.00 0.00 +ATOM 5515 OW SOL 1761 9.600 44.720 20.530 1.00 0.00 +ATOM 5516 HW1 SOL 1761 9.860 44.610 21.440 1.00 0.00 +ATOM 5517 HW2 SOL 1761 9.140 43.910 20.320 1.00 0.00 +ATOM 5518 OW SOL 1762 0.250 7.550 14.020 1.00 0.00 +ATOM 5519 HW1 SOL 1762 0.120 7.740 13.090 1.00 0.00 +ATOM 5520 HW2 SOL 1762 0.480 8.400 14.400 1.00 0.00 +ATOM 5521 OW SOL 1763 19.640 12.180 1.060 1.00 0.00 +ATOM 5522 HW1 SOL 1763 19.620 11.430 0.480 1.00 0.00 +ATOM 5523 HW2 SOL 1763 18.920 12.040 1.680 1.00 0.00 +ATOM 5524 OW SOL 1764 -20.469 16.071 -0.178 1.00 0.00 +ATOM 5525 HW1 SOL 1764 -20.759 15.261 -0.608 1.00 0.00 +ATOM 5526 HW2 SOL 1764 -20.729 16.771 -0.778 1.00 0.00 +ATOM 5527 OW SOL 1765 8.050 8.040 8.580 1.00 0.00 +ATOM 5528 HW1 SOL 1765 7.200 8.050 8.140 1.00 0.00 +ATOM 5529 HW2 SOL 1765 8.690 8.210 7.890 1.00 0.00 +ATOM 5530 OW SOL 1766 5.140 16.750 1.880 1.00 0.00 +ATOM 5531 HW1 SOL 1766 5.580 16.350 1.130 1.00 0.00 +ATOM 5532 HW2 SOL 1766 4.560 17.410 1.490 1.00 0.00 +ATOM 5533 OW SOL 1767 38.020 32.660 8.820 1.00 0.00 +ATOM 5534 HW1 SOL 1767 38.750 33.210 9.110 1.00 0.00 +ATOM 5535 HW2 SOL 1767 38.350 32.220 8.030 1.00 0.00 +ATOM 5536 OW SOL 1768 43.030 22.950 15.670 1.00 0.00 +ATOM 5537 HW1 SOL 1768 42.300 23.560 15.790 1.00 0.00 +ATOM 5538 HW2 SOL 1768 43.810 23.490 15.810 1.00 0.00 +ATOM 5539 OW SOL 1769 17.970 8.470 31.410 1.00 0.00 +ATOM 5540 HW1 SOL 1769 17.050 8.640 31.190 1.00 0.00 +ATOM 5541 HW2 SOL 1769 18.050 7.520 31.390 1.00 0.00 +ATOM 5542 OW SOL 1770 12.660 13.150 25.120 1.00 0.00 +ATOM 5543 HW1 SOL 1770 13.550 13.070 25.480 1.00 0.00 +ATOM 5544 HW2 SOL 1770 12.310 12.260 25.130 1.00 0.00 +ATOM 5545 OW SOL 1771 11.300 26.530 26.660 1.00 0.00 +ATOM 5546 HW1 SOL 1771 11.200 26.580 25.710 1.00 0.00 +ATOM 5547 HW2 SOL 1771 10.650 25.890 26.940 1.00 0.00 +ATOM 5548 OW SOL 1772 38.280 23.870 8.180 1.00 0.00 +ATOM 5549 HW1 SOL 1772 38.270 24.750 7.810 1.00 0.00 +ATOM 5550 HW2 SOL 1772 37.440 23.790 8.640 1.00 0.00 +ATOM 5551 OW SOL 1773 10.260 36.560 6.890 1.00 0.00 +ATOM 5552 HW1 SOL 1773 9.580 36.240 7.480 1.00 0.00 +ATOM 5553 HW2 SOL 1773 9.810 36.660 6.050 1.00 0.00 +ATOM 5554 OW SOL 1774 4.600 29.310 22.250 1.00 0.00 +ATOM 5555 HW1 SOL 1774 4.650 29.750 21.410 1.00 0.00 +ATOM 5556 HW2 SOL 1774 5.490 29.350 22.600 1.00 0.00 +ATOM 5557 OW SOL 1775 32.210 21.520 30.650 1.00 0.00 +ATOM 5558 HW1 SOL 1775 32.200 20.710 31.150 1.00 0.00 +ATOM 5559 HW2 SOL 1775 32.930 21.400 30.030 1.00 0.00 +ATOM 5560 OW SOL 1776 10.190 16.620 18.590 1.00 0.00 +ATOM 5561 HW1 SOL 1776 9.990 17.260 19.270 1.00 0.00 +ATOM 5562 HW2 SOL 1776 9.480 15.980 18.640 1.00 0.00 +ATOM 5563 OW SOL 1777 38.880 15.020 30.230 1.00 0.00 +ATOM 5564 HW1 SOL 1777 39.380 15.810 30.440 1.00 0.00 +ATOM 5565 HW2 SOL 1777 39.550 14.360 30.050 1.00 0.00 +ATOM 5566 OW SOL 1778 14.170 19.890 29.180 1.00 0.00 +ATOM 5567 HW1 SOL 1778 13.720 20.660 29.530 1.00 0.00 +ATOM 5568 HW2 SOL 1778 13.510 19.200 29.160 1.00 0.00 +ATOM 5569 OW SOL 1779 13.550 19.400 24.460 1.00 0.00 +ATOM 5570 HW1 SOL 1779 14.000 19.050 23.690 1.00 0.00 +ATOM 5571 HW2 SOL 1779 12.710 19.720 24.120 1.00 0.00 +ATOM 5572 OW SOL 1780 40.550 9.930 21.220 1.00 0.00 +ATOM 5573 HW1 SOL 1780 39.930 10.330 21.830 1.00 0.00 +ATOM 5574 HW2 SOL 1780 41.400 10.060 21.620 1.00 0.00 +ATOM 5575 OW SOL 1781 17.260 12.720 12.130 1.00 0.00 +ATOM 5576 HW1 SOL 1781 17.700 13.390 11.600 1.00 0.00 +ATOM 5577 HW2 SOL 1781 16.560 13.190 12.580 1.00 0.00 +ATOM 5578 OW SOL 1782 31.310 27.520 1.570 1.00 0.00 +ATOM 5579 HW1 SOL 1782 31.670 26.650 1.740 1.00 0.00 +ATOM 5580 HW2 SOL 1782 31.530 28.030 2.360 1.00 0.00 +ATOM 5581 OW SOL 1783 18.920 26.960 22.230 1.00 0.00 +ATOM 5582 HW1 SOL 1783 18.450 26.660 21.460 1.00 0.00 +ATOM 5583 HW2 SOL 1783 18.240 27.310 22.810 1.00 0.00 +ATOM 5584 OW SOL 1784 26.290 15.870 19.690 1.00 0.00 +ATOM 5585 HW1 SOL 1784 26.790 16.510 19.180 1.00 0.00 +ATOM 5586 HW2 SOL 1784 25.900 15.290 19.040 1.00 0.00 +ATOM 5587 OW SOL 1785 21.780 39.610 25.450 1.00 0.00 +ATOM 5588 HW1 SOL 1785 21.980 38.700 25.220 1.00 0.00 +ATOM 5589 HW2 SOL 1785 22.600 39.950 25.810 1.00 0.00 +ATOM 5590 OW SOL 1786 14.040 20.030 15.760 1.00 0.00 +ATOM 5591 HW1 SOL 1786 14.240 19.150 15.420 1.00 0.00 +ATOM 5592 HW2 SOL 1786 13.630 19.860 16.610 1.00 0.00 +ATOM 5593 OW SOL 1787 5.200 3.980 21.610 1.00 0.00 +ATOM 5594 HW1 SOL 1787 5.580 3.130 21.380 1.00 0.00 +ATOM 5595 HW2 SOL 1787 4.570 4.170 20.920 1.00 0.00 +ATOM 5596 OW SOL 1788 44.400 0.000 29.500 1.00 0.00 +ATOM 5597 HW1 SOL 1788 44.680 -0.380 30.330 1.00 0.00 +ATOM 5598 HW2 SOL 1788 44.920 -0.450 28.840 1.00 0.00 +ATOM 5599 OW SOL 1789 4.130 26.580 27.670 1.00 0.00 +ATOM 5600 HW1 SOL 1789 4.220 25.890 27.010 1.00 0.00 +ATOM 5601 HW2 SOL 1789 5.020 26.840 27.880 1.00 0.00 +ATOM 5602 OW SOL 1790 29.050 22.010 14.260 1.00 0.00 +ATOM 5603 HW1 SOL 1790 29.190 21.640 15.130 1.00 0.00 +ATOM 5604 HW2 SOL 1790 29.600 21.480 13.680 1.00 0.00 +ATOM 5605 OW SOL 1791 33.920 38.640 16.410 1.00 0.00 +ATOM 5606 HW1 SOL 1791 33.640 37.970 15.790 1.00 0.00 +ATOM 5607 HW2 SOL 1791 33.570 38.350 17.260 1.00 0.00 +ATOM 5608 OW SOL 1792 0.800 27.580 30.720 1.00 0.00 +ATOM 5609 HW1 SOL 1792 1.600 27.860 30.270 1.00 0.00 +ATOM 5610 HW2 SOL 1792 0.450 26.880 30.170 1.00 0.00 +ATOM 5611 OW SOL 1793 -3.957 22.990 22.930 1.00 0.00 +ATOM 5612 HW1 SOL 1793 -3.067 22.740 23.180 1.00 0.00 +ATOM 5613 HW2 SOL 1793 -4.507 22.680 23.660 1.00 0.00 +ATOM 5614 OW SOL 1794 25.590 5.460 16.320 1.00 0.00 +ATOM 5615 HW1 SOL 1794 24.670 5.580 16.560 1.00 0.00 +ATOM 5616 HW2 SOL 1794 25.920 4.830 16.960 1.00 0.00 +ATOM 5617 OW SOL 1795 8.460 29.120 25.350 1.00 0.00 +ATOM 5618 HW1 SOL 1795 8.520 29.480 24.460 1.00 0.00 +ATOM 5619 HW2 SOL 1795 9.360 28.900 25.590 1.00 0.00 +ATOM 5620 OW SOL 1796 7.750 42.410 20.400 1.00 0.00 +ATOM 5621 HW1 SOL 1796 7.350 42.140 21.230 1.00 0.00 +ATOM 5622 HW2 SOL 1796 7.430 41.780 19.760 1.00 0.00 +ATOM 5623 OW SOL 1797 41.430 7.240 30.720 1.00 0.00 +ATOM 5624 HW1 SOL 1797 41.360 6.530 30.090 1.00 0.00 +ATOM 5625 HW2 SOL 1797 41.860 7.950 30.230 1.00 0.00 +ATOM 5626 OW SOL 1798 22.810 44.410 29.390 1.00 0.00 +ATOM 5627 HW1 SOL 1798 23.390 43.940 28.790 1.00 0.00 +ATOM 5628 HW2 SOL 1798 22.620 43.780 30.080 1.00 0.00 +ATOM 5629 OW SOL 1799 43.270 29.970 18.780 1.00 0.00 +ATOM 5630 HW1 SOL 1799 44.070 30.490 18.930 1.00 0.00 +ATOM 5631 HW2 SOL 1799 42.670 30.270 19.460 1.00 0.00 +ATOM 5632 OW SOL 1800 3.840 7.200 13.360 1.00 0.00 +ATOM 5633 HW1 SOL 1800 4.210 7.120 14.240 1.00 0.00 +ATOM 5634 HW2 SOL 1800 3.450 6.350 13.180 1.00 0.00 +ATOM 5635 OW SOL 1801 10.620 7.180 6.660 1.00 0.00 +ATOM 5636 HW1 SOL 1801 10.380 7.250 7.580 1.00 0.00 +ATOM 5637 HW2 SOL 1801 11.040 6.320 6.590 1.00 0.00 +ATOM 5638 OW SOL 1802 21.350 29.190 1.470 1.00 0.00 +ATOM 5639 HW1 SOL 1802 21.690 29.360 0.590 1.00 0.00 +ATOM 5640 HW2 SOL 1802 21.960 28.550 1.840 1.00 0.00 +ATOM 5641 OW SOL 1803 29.100 26.460 26.440 1.00 0.00 +ATOM 5642 HW1 SOL 1803 28.850 27.370 26.600 1.00 0.00 +ATOM 5643 HW2 SOL 1803 29.540 26.190 27.250 1.00 0.00 +ATOM 5644 OW SOL 1804 41.500 9.040 10.290 1.00 0.00 +ATOM 5645 HW1 SOL 1804 40.980 8.300 10.600 1.00 0.00 +ATOM 5646 HW2 SOL 1804 41.550 8.920 9.340 1.00 0.00 +ATOM 5647 OW SOL 1805 10.380 19.790 2.780 1.00 0.00 +ATOM 5648 HW1 SOL 1805 9.420 19.860 2.820 1.00 0.00 +ATOM 5649 HW2 SOL 1805 10.600 20.150 1.920 1.00 0.00 +ATOM 5650 OW SOL 1806 14.700 28.280 22.510 1.00 0.00 +ATOM 5651 HW1 SOL 1806 14.290 28.520 21.680 1.00 0.00 +ATOM 5652 HW2 SOL 1806 14.570 27.330 22.580 1.00 0.00 +ATOM 5653 OW SOL 1807 12.870 25.550 28.700 1.00 0.00 +ATOM 5654 HW1 SOL 1807 12.140 25.130 29.150 1.00 0.00 +ATOM 5655 HW2 SOL 1807 12.450 26.070 28.010 1.00 0.00 +ATOM 5656 OW SOL 1808 30.560 2.790 8.100 1.00 0.00 +ATOM 5657 HW1 SOL 1808 30.920 1.940 7.840 1.00 0.00 +ATOM 5658 HW2 SOL 1808 29.700 2.580 8.480 1.00 0.00 +ATOM 5659 OW SOL 1809 1.750 38.830 3.130 1.00 0.00 +ATOM 5660 HW1 SOL 1809 1.430 39.720 3.310 1.00 0.00 +ATOM 5661 HW2 SOL 1809 2.260 38.600 3.910 1.00 0.00 +ATOM 5662 OW SOL 1810 33.180 1.490 27.940 1.00 0.00 +ATOM 5663 HW1 SOL 1810 32.420 1.200 27.440 1.00 0.00 +ATOM 5664 HW2 SOL 1810 33.400 0.750 28.500 1.00 0.00 +ATOM 5665 OW SOL 1811 28.490 6.240 5.030 1.00 0.00 +ATOM 5666 HW1 SOL 1811 28.900 6.400 5.880 1.00 0.00 +ATOM 5667 HW2 SOL 1811 27.830 6.930 4.950 1.00 0.00 +ATOM 5668 OW SOL 1812 32.800 26.440 3.990 1.00 0.00 +ATOM 5669 HW1 SOL 1812 33.450 25.750 4.140 1.00 0.00 +ATOM 5670 HW2 SOL 1812 31.980 26.060 4.290 1.00 0.00 +ATOM 5671 OW SOL 1813 4.910 18.350 16.530 1.00 0.00 +ATOM 5672 HW1 SOL 1813 5.170 17.930 15.710 1.00 0.00 +ATOM 5673 HW2 SOL 1813 3.970 18.160 16.600 1.00 0.00 +ATOM 5674 OW SOL 1814 14.040 43.930 18.130 1.00 0.00 +ATOM 5675 HW1 SOL 1814 14.000 43.570 17.240 1.00 0.00 +ATOM 5676 HW2 SOL 1814 13.960 43.170 18.710 1.00 0.00 +ATOM 5677 OW SOL 1815 6.110 19.630 28.790 1.00 0.00 +ATOM 5678 HW1 SOL 1815 5.690 18.910 29.260 1.00 0.00 +ATOM 5679 HW2 SOL 1815 5.410 20.260 28.640 1.00 0.00 +ATOM 5680 OW SOL 1816 2.480 43.910 29.500 1.00 0.00 +ATOM 5681 HW1 SOL 1816 2.950 43.160 29.850 1.00 0.00 +ATOM 5682 HW2 SOL 1816 3.100 44.300 28.870 1.00 0.00 +ATOM 5683 OW SOL 1817 -0.037 15.400 11.590 1.00 0.00 +ATOM 5684 HW1 SOL 1817 -0.387 14.520 11.470 1.00 0.00 +ATOM 5685 HW2 SOL 1817 0.763 15.420 11.070 1.00 0.00 +ATOM 5686 OW SOL 1818 16.290 32.280 19.110 1.00 0.00 +ATOM 5687 HW1 SOL 1818 16.950 31.610 19.260 1.00 0.00 +ATOM 5688 HW2 SOL 1818 15.900 32.050 18.260 1.00 0.00 +ATOM 5689 OW SOL 1819 33.920 42.380 31.100 1.00 0.00 +ATOM 5690 HW1 SOL 1819 33.490 43.030 30.550 1.00 0.00 +ATOM 5691 HW2 SOL 1819 33.290 41.660 31.170 1.00 0.00 +ATOM 5692 OW SOL 1820 20.980 40.950 16.090 1.00 0.00 +ATOM 5693 HW1 SOL 1820 21.520 40.160 16.170 1.00 0.00 +ATOM 5694 HW2 SOL 1820 20.240 40.800 16.680 1.00 0.00 +ATOM 5695 OW SOL 1821 17.570 34.380 29.730 1.00 0.00 +ATOM 5696 HW1 SOL 1821 18.270 34.980 30.010 1.00 0.00 +ATOM 5697 HW2 SOL 1821 17.550 33.710 30.410 1.00 0.00 +ATOM 5698 OW SOL 1822 30.740 1.470 2.340 1.00 0.00 +ATOM 5699 HW1 SOL 1822 30.930 1.960 1.530 1.00 0.00 +ATOM 5700 HW2 SOL 1822 30.420 2.130 2.950 1.00 0.00 +ATOM 5701 OW SOL 1823 21.970 24.760 16.160 1.00 0.00 +ATOM 5702 HW1 SOL 1823 21.620 24.270 15.410 1.00 0.00 +ATOM 5703 HW2 SOL 1823 21.420 25.540 16.210 1.00 0.00 +ATOM 5704 OW SOL 1824 11.750 17.550 4.220 1.00 0.00 +ATOM 5705 HW1 SOL 1824 11.630 18.460 3.970 1.00 0.00 +ATOM 5706 HW2 SOL 1824 12.280 17.580 5.020 1.00 0.00 +ATOM 5707 OW SOL 1825 27.680 23.740 17.100 1.00 0.00 +ATOM 5708 HW1 SOL 1825 27.470 24.670 16.940 1.00 0.00 +ATOM 5709 HW2 SOL 1825 28.610 23.670 16.910 1.00 0.00 +ATOM 5710 OW SOL 1826 26.310 7.280 1.070 1.00 0.00 +ATOM 5711 HW1 SOL 1826 27.220 7.270 1.370 1.00 0.00 +ATOM 5712 HW2 SOL 1826 26.010 8.170 1.230 1.00 0.00 +ATOM 5713 OW SOL 1827 21.000 17.300 5.790 1.00 0.00 +ATOM 5714 HW1 SOL 1827 20.360 16.670 5.440 1.00 0.00 +ATOM 5715 HW2 SOL 1827 20.530 17.740 6.490 1.00 0.00 +ATOM 5716 OW SOL 1828 38.620 17.820 13.200 1.00 0.00 +ATOM 5717 HW1 SOL 1828 39.440 17.440 13.530 1.00 0.00 +ATOM 5718 HW2 SOL 1828 38.130 17.070 12.860 1.00 0.00 +ATOM 5719 OW SOL 1829 12.220 36.010 27.970 1.00 0.00 +ATOM 5720 HW1 SOL 1829 12.700 35.500 27.310 1.00 0.00 +ATOM 5721 HW2 SOL 1829 11.570 36.500 27.470 1.00 0.00 +ATOM 5722 OW SOL 1830 12.010 36.110 21.250 1.00 0.00 +ATOM 5723 HW1 SOL 1830 12.800 35.690 20.920 1.00 0.00 +ATOM 5724 HW2 SOL 1830 12.320 36.880 21.730 1.00 0.00 +ATOM 5725 OW SOL 1831 34.700 27.210 1.100 1.00 0.00 +ATOM 5726 HW1 SOL 1831 34.130 27.210 0.330 1.00 0.00 +ATOM 5727 HW2 SOL 1831 35.530 27.560 0.770 1.00 0.00 +ATOM 5728 OW SOL 1832 1.780 13.300 19.630 1.00 0.00 +ATOM 5729 HW1 SOL 1832 1.760 14.170 20.040 1.00 0.00 +ATOM 5730 HW2 SOL 1832 2.590 12.910 19.950 1.00 0.00 +ATOM 5731 OW SOL 1833 11.340 17.390 22.040 1.00 0.00 +ATOM 5732 HW1 SOL 1833 11.540 16.860 22.810 1.00 0.00 +ATOM 5733 HW2 SOL 1833 12.060 18.020 21.990 1.00 0.00 +ATOM 5734 OW SOL 1834 41.300 37.980 3.040 1.00 0.00 +ATOM 5735 HW1 SOL 1834 41.720 37.460 2.360 1.00 0.00 +ATOM 5736 HW2 SOL 1834 40.750 38.600 2.560 1.00 0.00 +ATOM 5737 OW SOL 1835 7.350 29.220 9.120 1.00 0.00 +ATOM 5738 HW1 SOL 1835 7.860 28.420 8.990 1.00 0.00 +ATOM 5739 HW2 SOL 1835 7.990 29.890 9.320 1.00 0.00 +ATOM 5740 OW SOL 1836 15.670 33.020 24.290 1.00 0.00 +ATOM 5741 HW1 SOL 1836 16.240 33.150 23.540 1.00 0.00 +ATOM 5742 HW2 SOL 1836 15.180 32.220 24.080 1.00 0.00 +ATOM 5743 OW SOL 1837 33.510 39.320 21.720 1.00 0.00 +ATOM 5744 HW1 SOL 1837 33.040 39.420 22.550 1.00 0.00 +ATOM 5745 HW2 SOL 1837 33.430 40.170 21.290 1.00 0.00 +ATOM 5746 OW SOL 1838 2.780 10.050 23.210 1.00 0.00 +ATOM 5747 HW1 SOL 1838 2.970 10.430 24.070 1.00 0.00 +ATOM 5748 HW2 SOL 1838 2.270 9.270 23.390 1.00 0.00 +ATOM 5749 OW SOL 1839 29.530 25.930 0.310 1.00 0.00 +ATOM 5750 HW1 SOL 1839 29.970 26.490 0.950 1.00 0.00 +ATOM 5751 HW2 SOL 1839 30.150 25.840 -0.400 1.00 0.00 +ATOM 5752 OW SOL 1840 31.710 18.430 13.830 1.00 0.00 +ATOM 5753 HW1 SOL 1840 32.480 17.880 13.670 1.00 0.00 +ATOM 5754 HW2 SOL 1840 32.060 19.290 14.060 1.00 0.00 +ATOM 5755 OW SOL 1841 12.750 17.490 29.150 1.00 0.00 +ATOM 5756 HW1 SOL 1841 12.790 16.530 29.210 1.00 0.00 +ATOM 5757 HW2 SOL 1841 12.720 17.660 28.210 1.00 0.00 +ATOM 5758 OW SOL 1842 25.870 15.930 11.590 1.00 0.00 +ATOM 5759 HW1 SOL 1842 24.990 16.290 11.550 1.00 0.00 +ATOM 5760 HW2 SOL 1842 26.440 16.650 11.340 1.00 0.00 +ATOM 5761 OW SOL 1843 35.590 16.540 18.650 1.00 0.00 +ATOM 5762 HW1 SOL 1843 34.760 16.980 18.870 1.00 0.00 +ATOM 5763 HW2 SOL 1843 35.400 15.610 18.760 1.00 0.00 +ATOM 5764 OW SOL 1844 32.180 27.920 26.400 1.00 0.00 +ATOM 5765 HW1 SOL 1844 31.610 28.260 27.090 1.00 0.00 +ATOM 5766 HW2 SOL 1844 32.910 28.550 26.360 1.00 0.00 +ATOM 5767 OW SOL 1845 23.300 24.560 25.150 1.00 0.00 +ATOM 5768 HW1 SOL 1845 22.470 24.620 25.620 1.00 0.00 +ATOM 5769 HW2 SOL 1845 23.660 23.710 25.410 1.00 0.00 +ATOM 5770 OW SOL 1846 0.520 14.060 7.670 1.00 0.00 +ATOM 5771 HW1 SOL 1846 0.480 13.110 7.760 1.00 0.00 +ATOM 5772 HW2 SOL 1846 -0.380 14.350 7.780 1.00 0.00 +ATOM 5773 OW SOL 1847 -1.977 20.550 16.800 1.00 0.00 +ATOM 5774 HW1 SOL 1847 -1.977 21.440 16.470 1.00 0.00 +ATOM 5775 HW2 SOL 1847 -2.717 20.520 17.420 1.00 0.00 +ATOM 5776 OW SOL 1848 24.080 45.040 2.540 1.00 0.00 +ATOM 5777 HW1 SOL 1848 23.320 45.220 2.000 1.00 0.00 +ATOM 5778 HW2 SOL 1848 23.720 44.650 3.340 1.00 0.00 +ATOM 5779 OW SOL 1849 26.690 39.820 4.860 1.00 0.00 +ATOM 5780 HW1 SOL 1849 26.220 40.500 4.380 1.00 0.00 +ATOM 5781 HW2 SOL 1849 27.170 40.290 5.540 1.00 0.00 +ATOM 5782 OW SOL 1850 2.720 19.260 27.800 1.00 0.00 +ATOM 5783 HW1 SOL 1850 2.800 18.430 27.340 1.00 0.00 +ATOM 5784 HW2 SOL 1850 2.810 19.020 28.730 1.00 0.00 +ATOM 5785 OW SOL 1851 41.620 22.020 25.590 1.00 0.00 +ATOM 5786 HW1 SOL 1851 41.880 21.770 26.480 1.00 0.00 +ATOM 5787 HW2 SOL 1851 41.440 22.960 25.640 1.00 0.00 +ATOM 5788 OW SOL 1852 2.850 31.400 0.420 1.00 0.00 +ATOM 5789 HW1 SOL 1852 2.540 30.500 0.460 1.00 0.00 +ATOM 5790 HW2 SOL 1852 2.150 31.880 -0.020 1.00 0.00 +ATOM 5791 OW SOL 1853 11.800 27.190 13.930 1.00 0.00 +ATOM 5792 HW1 SOL 1853 12.420 26.450 13.940 1.00 0.00 +ATOM 5793 HW2 SOL 1853 11.720 27.440 14.850 1.00 0.00 +ATOM 5794 OW SOL 1854 0.750 5.150 15.320 1.00 0.00 +ATOM 5795 HW1 SOL 1854 -0.110 4.750 15.450 1.00 0.00 +ATOM 5796 HW2 SOL 1854 0.580 5.920 14.770 1.00 0.00 +ATOM 5797 OW SOL 1855 13.200 44.460 30.950 1.00 0.00 +ATOM 5798 HW1 SOL 1855 12.340 44.820 31.150 1.00 0.00 +ATOM 5799 HW2 SOL 1855 13.190 44.350 29.990 1.00 0.00 +ATOM 5800 OW SOL 1856 8.730 16.700 22.140 1.00 0.00 +ATOM 5801 HW1 SOL 1856 9.660 16.900 22.000 1.00 0.00 +ATOM 5802 HW2 SOL 1856 8.330 17.550 22.320 1.00 0.00 +ATOM 5803 OW SOL 1857 31.110 41.550 10.220 1.00 0.00 +ATOM 5804 HW1 SOL 1857 31.690 41.530 9.470 1.00 0.00 +ATOM 5805 HW2 SOL 1857 31.680 41.700 10.970 1.00 0.00 +ATOM 5806 OW SOL 1858 15.070 35.920 9.870 1.00 0.00 +ATOM 5807 HW1 SOL 1858 15.520 35.640 9.070 1.00 0.00 +ATOM 5808 HW2 SOL 1858 14.180 36.110 9.580 1.00 0.00 +ATOM 5809 OW SOL 1859 43.520 29.130 8.610 1.00 0.00 +ATOM 5810 HW1 SOL 1859 42.900 29.220 9.340 1.00 0.00 +ATOM 5811 HW2 SOL 1859 43.070 29.520 7.870 1.00 0.00 +ATOM 5812 OW SOL 1860 10.910 44.730 29.640 1.00 0.00 +ATOM 5813 HW1 SOL 1860 10.080 44.290 29.820 1.00 0.00 +ATOM 5814 HW2 SOL 1860 10.770 45.630 29.940 1.00 0.00 +ATOM 5815 OW SOL 1861 6.500 19.620 18.320 1.00 0.00 +ATOM 5816 HW1 SOL 1861 6.080 19.000 17.720 1.00 0.00 +ATOM 5817 HW2 SOL 1861 6.120 20.470 18.090 1.00 0.00 +ATOM 5818 OW SOL 1862 31.120 43.510 19.420 1.00 0.00 +ATOM 5819 HW1 SOL 1862 30.800 42.860 20.050 1.00 0.00 +ATOM 5820 HW2 SOL 1862 31.010 43.090 18.570 1.00 0.00 +ATOM 5821 OW SOL 1863 14.850 43.830 21.720 1.00 0.00 +ATOM 5822 HW1 SOL 1863 14.550 44.340 22.470 1.00 0.00 +ATOM 5823 HW2 SOL 1863 14.960 44.480 21.020 1.00 0.00 +ATOM 5824 OW SOL 1864 39.330 22.340 6.070 1.00 0.00 +ATOM 5825 HW1 SOL 1864 38.830 21.530 6.170 1.00 0.00 +ATOM 5826 HW2 SOL 1864 39.030 22.900 6.790 1.00 0.00 +ATOM 5827 OW SOL 1865 43.880 24.080 1.960 1.00 0.00 +ATOM 5828 HW1 SOL 1865 43.230 23.380 1.970 1.00 0.00 +ATOM 5829 HW2 SOL 1865 43.630 24.650 2.680 1.00 0.00 +ATOM 5830 OW SOL 1866 19.801 3.251 -0.298 1.00 0.00 +ATOM 5831 HW1 SOL 1866 20.531 3.011 0.272 1.00 0.00 +ATOM 5832 HW2 SOL 1866 19.781 2.561 -0.958 1.00 0.00 +ATOM 5833 OW SOL 1867 -13.319 -1.459 -4.058 1.00 0.00 +ATOM 5834 HW1 SOL 1867 -14.169 -1.089 -4.298 1.00 0.00 +ATOM 5835 HW2 SOL 1867 -13.319 -1.469 -3.098 1.00 0.00 +ATOM 5836 OW SOL 1868 -16.487 -5.557 21.220 1.00 0.00 +ATOM 5837 HW1 SOL 1868 -16.287 -6.057 22.010 1.00 0.00 +ATOM 5838 HW2 SOL 1868 -16.787 -6.217 20.590 1.00 0.00 +ATOM 5839 OW SOL 1869 10.840 29.780 5.910 1.00 0.00 +ATOM 5840 HW1 SOL 1869 11.760 29.820 6.180 1.00 0.00 +ATOM 5841 HW2 SOL 1869 10.540 28.930 6.230 1.00 0.00 +ATOM 5842 OW SOL 1870 3.550 31.450 6.230 1.00 0.00 +ATOM 5843 HW1 SOL 1870 3.530 31.430 5.270 1.00 0.00 +ATOM 5844 HW2 SOL 1870 3.040 30.680 6.490 1.00 0.00 +ATOM 5845 OW SOL 1871 24.100 22.510 16.880 1.00 0.00 +ATOM 5846 HW1 SOL 1871 23.720 22.000 17.600 1.00 0.00 +ATOM 5847 HW2 SOL 1871 23.480 23.220 16.740 1.00 0.00 +ATOM 5848 OW SOL 1872 10.330 18.570 16.600 1.00 0.00 +ATOM 5849 HW1 SOL 1872 11.000 19.080 17.060 1.00 0.00 +ATOM 5850 HW2 SOL 1872 10.110 17.870 17.220 1.00 0.00 +ATOM 5851 OW SOL 1873 0.430 37.110 11.260 1.00 0.00 +ATOM 5852 HW1 SOL 1873 -0.210 36.870 10.590 1.00 0.00 +ATOM 5853 HW2 SOL 1873 1.070 37.650 10.800 1.00 0.00 +ATOM 5854 OW SOL 1874 18.160 36.780 23.280 1.00 0.00 +ATOM 5855 HW1 SOL 1874 18.580 37.580 23.600 1.00 0.00 +ATOM 5856 HW2 SOL 1874 17.480 36.590 23.930 1.00 0.00 +ATOM 5857 OW SOL 1875 24.150 10.280 7.000 1.00 0.00 +ATOM 5858 HW1 SOL 1875 24.270 10.290 6.050 1.00 0.00 +ATOM 5859 HW2 SOL 1875 24.750 10.960 7.320 1.00 0.00 +ATOM 5860 OW SOL 1876 27.330 6.350 28.940 1.00 0.00 +ATOM 5861 HW1 SOL 1876 28.230 6.540 29.210 1.00 0.00 +ATOM 5862 HW2 SOL 1876 27.170 6.940 28.200 1.00 0.00 +ATOM 5863 OW SOL 1877 10.660 38.670 25.740 1.00 0.00 +ATOM 5864 HW1 SOL 1877 11.600 38.480 25.730 1.00 0.00 +ATOM 5865 HW2 SOL 1877 10.250 37.820 25.900 1.00 0.00 +ATOM 5866 OW SOL 1878 31.790 3.120 13.870 1.00 0.00 +ATOM 5867 HW1 SOL 1878 32.390 3.850 13.690 1.00 0.00 +ATOM 5868 HW2 SOL 1878 31.580 2.760 13.010 1.00 0.00 +ATOM 5869 OW SOL 1879 29.060 18.080 14.270 1.00 0.00 +ATOM 5870 HW1 SOL 1879 28.880 18.160 13.330 1.00 0.00 +ATOM 5871 HW2 SOL 1879 30.020 18.140 14.330 1.00 0.00 +ATOM 5872 OW SOL 1880 40.800 11.060 7.070 1.00 0.00 +ATOM 5873 HW1 SOL 1880 40.100 11.300 7.680 1.00 0.00 +ATOM 5874 HW2 SOL 1880 40.480 10.260 6.650 1.00 0.00 +ATOM 5875 OW SOL 1881 15.300 35.670 7.040 1.00 0.00 +ATOM 5876 HW1 SOL 1881 15.750 35.610 6.200 1.00 0.00 +ATOM 5877 HW2 SOL 1881 15.320 34.780 7.390 1.00 0.00 +ATOM 5878 OW SOL 1882 18.470 15.130 20.900 1.00 0.00 +ATOM 5879 HW1 SOL 1882 18.510 16.070 20.730 1.00 0.00 +ATOM 5880 HW2 SOL 1882 17.620 14.990 21.300 1.00 0.00 +ATOM 5881 OW SOL 1883 33.450 35.790 16.860 1.00 0.00 +ATOM 5882 HW1 SOL 1883 32.760 35.750 17.530 1.00 0.00 +ATOM 5883 HW2 SOL 1883 32.980 36.010 16.050 1.00 0.00 +ATOM 5884 OW SOL 1884 15.880 2.600 18.340 1.00 0.00 +ATOM 5885 HW1 SOL 1884 15.690 2.540 17.400 1.00 0.00 +ATOM 5886 HW2 SOL 1884 16.480 3.330 18.420 1.00 0.00 +ATOM 5887 OW SOL 1885 12.360 39.110 13.960 1.00 0.00 +ATOM 5888 HW1 SOL 1885 11.650 38.750 13.430 1.00 0.00 +ATOM 5889 HW2 SOL 1885 12.090 38.960 14.860 1.00 0.00 +ATOM 5890 OW SOL 1886 32.430 39.820 24.420 1.00 0.00 +ATOM 5891 HW1 SOL 1886 33.220 40.290 24.710 1.00 0.00 +ATOM 5892 HW2 SOL 1886 32.620 38.900 24.590 1.00 0.00 +ATOM 5893 OW SOL 1887 35.510 36.690 24.850 1.00 0.00 +ATOM 5894 HW1 SOL 1887 36.120 35.950 24.810 1.00 0.00 +ATOM 5895 HW2 SOL 1887 35.770 37.260 24.130 1.00 0.00 +ATOM 5896 OW SOL 1888 20.430 0.490 4.180 1.00 0.00 +ATOM 5897 HW1 SOL 1888 20.080 -0.050 3.470 1.00 0.00 +ATOM 5898 HW2 SOL 1888 20.430 -0.090 4.940 1.00 0.00 +ATOM 5899 OW SOL 1889 21.510 34.200 26.780 1.00 0.00 +ATOM 5900 HW1 SOL 1889 20.650 34.360 26.390 1.00 0.00 +ATOM 5901 HW2 SOL 1889 21.930 33.570 26.200 1.00 0.00 +ATOM 5902 OW SOL 1890 29.980 7.280 13.810 1.00 0.00 +ATOM 5903 HW1 SOL 1890 30.250 8.140 14.140 1.00 0.00 +ATOM 5904 HW2 SOL 1890 29.190 7.070 14.310 1.00 0.00 +ATOM 5905 OW SOL 1891 14.070 6.350 2.070 1.00 0.00 +ATOM 5906 HW1 SOL 1891 13.240 6.590 2.470 1.00 0.00 +ATOM 5907 HW2 SOL 1891 14.330 5.550 2.520 1.00 0.00 +ATOM 5908 OW SOL 1892 26.700 2.870 3.600 1.00 0.00 +ATOM 5909 HW1 SOL 1892 26.680 1.930 3.770 1.00 0.00 +ATOM 5910 HW2 SOL 1892 25.780 3.100 3.470 1.00 0.00 +ATOM 5911 OW SOL 1893 26.690 34.000 14.450 1.00 0.00 +ATOM 5912 HW1 SOL 1893 26.990 33.090 14.340 1.00 0.00 +ATOM 5913 HW2 SOL 1893 26.080 34.140 13.730 1.00 0.00 +ATOM 5914 OW SOL 1894 20.430 23.180 14.780 1.00 0.00 +ATOM 5915 HW1 SOL 1894 19.650 23.690 14.550 1.00 0.00 +ATOM 5916 HW2 SOL 1894 20.340 22.370 14.280 1.00 0.00 +ATOM 5917 OW SOL 1895 2.850 3.900 12.900 1.00 0.00 +ATOM 5918 HW1 SOL 1895 2.670 3.970 13.840 1.00 0.00 +ATOM 5919 HW2 SOL 1895 2.050 3.550 12.520 1.00 0.00 +ATOM 5920 OW SOL 1896 6.890 5.350 2.490 1.00 0.00 +ATOM 5921 HW1 SOL 1896 6.460 6.190 2.340 1.00 0.00 +ATOM 5922 HW2 SOL 1896 6.270 4.850 3.030 1.00 0.00 +ATOM 5923 OW SOL 1897 11.000 32.740 13.590 1.00 0.00 +ATOM 5924 HW1 SOL 1897 11.100 33.290 14.370 1.00 0.00 +ATOM 5925 HW2 SOL 1897 10.460 32.010 13.880 1.00 0.00 +ATOM 5926 OW SOL 1898 23.590 36.220 7.670 1.00 0.00 +ATOM 5927 HW1 SOL 1898 23.670 35.470 8.250 1.00 0.00 +ATOM 5928 HW2 SOL 1898 23.350 35.840 6.820 1.00 0.00 +ATOM 5929 OW SOL 1899 8.380 15.220 26.980 1.00 0.00 +ATOM 5930 HW1 SOL 1899 8.690 14.750 26.210 1.00 0.00 +ATOM 5931 HW2 SOL 1899 8.910 14.890 27.710 1.00 0.00 +ATOM 5932 OW SOL 1900 2.430 23.330 14.890 1.00 0.00 +ATOM 5933 HW1 SOL 1900 2.260 24.160 15.330 1.00 0.00 +ATOM 5934 HW2 SOL 1900 2.630 22.720 15.590 1.00 0.00 +ATOM 5935 OW SOL 1901 22.230 13.580 7.550 1.00 0.00 +ATOM 5936 HW1 SOL 1901 21.960 14.300 8.120 1.00 0.00 +ATOM 5937 HW2 SOL 1901 22.250 12.820 8.120 1.00 0.00 +ATOM 5938 OW SOL 1902 42.790 5.090 17.650 1.00 0.00 +ATOM 5939 HW1 SOL 1902 42.780 5.960 18.060 1.00 0.00 +ATOM 5940 HW2 SOL 1902 42.000 4.660 17.980 1.00 0.00 +ATOM 5941 OW SOL 1903 26.250 37.010 11.470 1.00 0.00 +ATOM 5942 HW1 SOL 1903 26.710 37.000 10.630 1.00 0.00 +ATOM 5943 HW2 SOL 1903 26.090 36.080 11.660 1.00 0.00 +ATOM 5944 OW SOL 1904 25.120 21.710 28.800 1.00 0.00 +ATOM 5945 HW1 SOL 1904 25.030 22.510 29.320 1.00 0.00 +ATOM 5946 HW2 SOL 1904 24.820 21.010 29.380 1.00 0.00 +ATOM 5947 OW SOL 1905 25.650 12.220 10.630 1.00 0.00 +ATOM 5948 HW1 SOL 1905 25.290 12.500 11.470 1.00 0.00 +ATOM 5949 HW2 SOL 1905 26.460 12.730 10.530 1.00 0.00 +ATOM 5950 OW SOL 1906 9.780 36.090 26.110 1.00 0.00 +ATOM 5951 HW1 SOL 1906 10.120 35.260 25.780 1.00 0.00 +ATOM 5952 HW2 SOL 1906 8.840 35.960 26.190 1.00 0.00 +ATOM 5953 OW SOL 1907 27.030 2.770 24.270 1.00 0.00 +ATOM 5954 HW1 SOL 1907 26.120 3.070 24.320 1.00 0.00 +ATOM 5955 HW2 SOL 1907 27.130 2.420 23.390 1.00 0.00 +ATOM 5956 OW SOL 1908 30.830 37.070 21.820 1.00 0.00 +ATOM 5957 HW1 SOL 1908 30.890 36.120 21.750 1.00 0.00 +ATOM 5958 HW2 SOL 1908 31.270 37.280 22.640 1.00 0.00 +ATOM 5959 OW SOL 1909 39.060 28.670 27.330 1.00 0.00 +ATOM 5960 HW1 SOL 1909 38.600 28.910 26.530 1.00 0.00 +ATOM 5961 HW2 SOL 1909 38.630 29.200 28.010 1.00 0.00 +ATOM 5962 OW SOL 1910 17.110 19.370 29.980 1.00 0.00 +ATOM 5963 HW1 SOL 1910 16.450 19.160 29.320 1.00 0.00 +ATOM 5964 HW2 SOL 1910 16.890 20.250 30.260 1.00 0.00 +ATOM 5965 OW SOL 1911 44.120 2.110 21.760 1.00 0.00 +ATOM 5966 HW1 SOL 1911 44.080 2.150 22.720 1.00 0.00 +ATOM 5967 HW2 SOL 1911 43.590 1.360 21.530 1.00 0.00 +ATOM 5968 OW SOL 1912 32.490 39.120 13.300 1.00 0.00 +ATOM 5969 HW1 SOL 1912 32.430 38.450 13.980 1.00 0.00 +ATOM 5970 HW2 SOL 1912 32.470 38.630 12.480 1.00 0.00 +ATOM 5971 OW SOL 1913 31.470 20.790 17.190 1.00 0.00 +ATOM 5972 HW1 SOL 1913 31.200 20.030 17.710 1.00 0.00 +ATOM 5973 HW2 SOL 1913 31.170 21.540 17.700 1.00 0.00 +ATOM 5974 OW SOL 1914 25.670 16.470 28.200 1.00 0.00 +ATOM 5975 HW1 SOL 1914 25.070 17.150 27.900 1.00 0.00 +ATOM 5976 HW2 SOL 1914 26.050 16.820 29.010 1.00 0.00 +ATOM 5977 OW SOL 1915 27.170 24.480 25.970 1.00 0.00 +ATOM 5978 HW1 SOL 1915 26.560 25.100 25.560 1.00 0.00 +ATOM 5979 HW2 SOL 1915 28.000 24.940 25.970 1.00 0.00 +ATOM 5980 OW SOL 1916 10.320 28.390 21.780 1.00 0.00 +ATOM 5981 HW1 SOL 1916 10.490 29.320 21.880 1.00 0.00 +ATOM 5982 HW2 SOL 1916 9.430 28.260 22.110 1.00 0.00 +ATOM 5983 OW SOL 1917 34.210 21.360 2.320 1.00 0.00 +ATOM 5984 HW1 SOL 1917 33.310 21.570 2.560 1.00 0.00 +ATOM 5985 HW2 SOL 1917 34.130 20.650 1.690 1.00 0.00 +ATOM 5986 OW SOL 1918 4.470 16.940 27.690 1.00 0.00 +ATOM 5987 HW1 SOL 1918 4.090 16.130 27.360 1.00 0.00 +ATOM 5988 HW2 SOL 1918 5.200 17.130 27.090 1.00 0.00 +ATOM 5989 OW SOL 1919 40.030 30.340 12.130 1.00 0.00 +ATOM 5990 HW1 SOL 1919 39.710 31.190 12.430 1.00 0.00 +ATOM 5991 HW2 SOL 1919 39.430 29.710 12.520 1.00 0.00 +ATOM 5992 OW SOL 1920 24.100 40.390 20.760 1.00 0.00 +ATOM 5993 HW1 SOL 1920 24.490 39.840 20.080 1.00 0.00 +ATOM 5994 HW2 SOL 1920 23.950 39.790 21.490 1.00 0.00 +ATOM 5995 OW SOL 1921 4.080 2.410 7.990 1.00 0.00 +ATOM 5996 HW1 SOL 1921 4.960 2.270 8.340 1.00 0.00 +ATOM 5997 HW2 SOL 1921 3.740 1.530 7.860 1.00 0.00 +ATOM 5998 OW SOL 1922 12.240 36.340 9.900 1.00 0.00 +ATOM 5999 HW1 SOL 1922 12.070 35.440 9.650 1.00 0.00 +ATOM 6000 HW2 SOL 1922 11.470 36.620 10.390 1.00 0.00 +ATOM 6001 OW SOL 1923 37.990 17.440 8.410 1.00 0.00 +ATOM 6002 HW1 SOL 1923 37.640 18.130 7.850 1.00 0.00 +ATOM 6003 HW2 SOL 1923 38.440 17.900 9.120 1.00 0.00 +ATOM 6004 OW SOL 1924 35.280 8.380 27.780 1.00 0.00 +ATOM 6005 HW1 SOL 1924 35.140 7.470 28.040 1.00 0.00 +ATOM 6006 HW2 SOL 1924 34.730 8.500 27.010 1.00 0.00 +ATOM 6007 OW SOL 1925 39.310 13.780 3.400 1.00 0.00 +ATOM 6008 HW1 SOL 1925 38.980 13.670 4.290 1.00 0.00 +ATOM 6009 HW2 SOL 1925 38.970 14.640 3.130 1.00 0.00 +ATOM 6010 OW SOL 1926 40.730 6.290 6.460 1.00 0.00 +ATOM 6011 HW1 SOL 1926 39.960 6.480 5.930 1.00 0.00 +ATOM 6012 HW2 SOL 1926 41.200 7.120 6.530 1.00 0.00 +ATOM 6013 OW SOL 1927 45.280 43.670 8.690 1.00 0.00 +ATOM 6014 HW1 SOL 1927 45.480 42.850 9.140 1.00 0.00 +ATOM 6015 HW2 SOL 1927 45.340 44.340 9.370 1.00 0.00 +ATOM 6016 OW SOL 1928 38.950 18.970 28.360 1.00 0.00 +ATOM 6017 HW1 SOL 1928 39.680 18.890 28.980 1.00 0.00 +ATOM 6018 HW2 SOL 1928 39.370 19.270 27.550 1.00 0.00 +ATOM 6019 OW SOL 1929 38.770 26.400 21.230 1.00 0.00 +ATOM 6020 HW1 SOL 1929 37.850 26.220 21.020 1.00 0.00 +ATOM 6021 HW2 SOL 1929 39.270 25.930 20.570 1.00 0.00 +ATOM 6022 OW SOL 1930 0.920 19.800 10.600 1.00 0.00 +ATOM 6023 HW1 SOL 1930 1.500 20.570 10.550 1.00 0.00 +ATOM 6024 HW2 SOL 1930 0.070 20.130 10.310 1.00 0.00 +ATOM 6025 OW SOL 1931 28.580 42.310 10.710 1.00 0.00 +ATOM 6026 HW1 SOL 1931 28.010 41.700 10.250 1.00 0.00 +ATOM 6027 HW2 SOL 1931 29.470 41.970 10.570 1.00 0.00 +ATOM 6028 OW SOL 1932 18.970 23.690 21.950 1.00 0.00 +ATOM 6029 HW1 SOL 1932 18.170 24.180 22.140 1.00 0.00 +ATOM 6030 HW2 SOL 1932 19.030 23.030 22.640 1.00 0.00 +ATOM 6031 OW SOL 1933 8.880 5.240 4.410 1.00 0.00 +ATOM 6032 HW1 SOL 1933 8.180 5.210 3.760 1.00 0.00 +ATOM 6033 HW2 SOL 1933 8.720 6.040 4.900 1.00 0.00 +ATOM 6034 OW SOL 1934 37.040 5.110 10.610 1.00 0.00 +ATOM 6035 HW1 SOL 1934 37.610 5.410 9.900 1.00 0.00 +ATOM 6036 HW2 SOL 1934 37.610 4.600 11.180 1.00 0.00 +ATOM 6037 OW SOL 1935 34.450 1.530 14.610 1.00 0.00 +ATOM 6038 HW1 SOL 1935 33.980 0.700 14.550 1.00 0.00 +ATOM 6039 HW2 SOL 1935 34.630 1.650 15.540 1.00 0.00 +ATOM 6040 OW SOL 1936 9.320 35.400 13.190 1.00 0.00 +ATOM 6041 HW1 SOL 1936 8.640 35.240 13.840 1.00 0.00 +ATOM 6042 HW2 SOL 1936 10.120 35.070 13.590 1.00 0.00 +ATOM 6043 OW SOL 1937 4.200 11.960 31.320 1.00 0.00 +ATOM 6044 HW1 SOL 1937 4.600 12.540 31.970 1.00 0.00 +ATOM 6045 HW2 SOL 1937 3.960 11.170 31.810 1.00 0.00 +ATOM 6046 OW SOL 1938 29.850 7.360 28.860 1.00 0.00 +ATOM 6047 HW1 SOL 1938 29.710 8.270 29.110 1.00 0.00 +ATOM 6048 HW2 SOL 1938 29.790 7.360 27.900 1.00 0.00 +ATOM 6049 OW SOL 1939 8.130 11.010 22.370 1.00 0.00 +ATOM 6050 HW1 SOL 1939 7.600 11.410 21.690 1.00 0.00 +ATOM 6051 HW2 SOL 1939 7.530 10.930 23.120 1.00 0.00 +ATOM 6052 OW SOL 1940 7.930 4.000 24.350 1.00 0.00 +ATOM 6053 HW1 SOL 1940 8.040 3.650 25.230 1.00 0.00 +ATOM 6054 HW2 SOL 1940 7.830 3.230 23.790 1.00 0.00 +ATOM 6055 OW SOL 1941 16.400 35.220 27.510 1.00 0.00 +ATOM 6056 HW1 SOL 1941 16.640 34.720 28.290 1.00 0.00 +ATOM 6057 HW2 SOL 1941 16.570 36.130 27.750 1.00 0.00 +ATOM 6058 OW SOL 1942 21.880 11.120 21.670 1.00 0.00 +ATOM 6059 HW1 SOL 1942 22.800 11.280 21.450 1.00 0.00 +ATOM 6060 HW2 SOL 1942 21.500 11.990 21.790 1.00 0.00 +ATOM 6061 OW SOL 1943 32.430 26.960 16.080 1.00 0.00 +ATOM 6062 HW1 SOL 1943 32.320 27.730 15.530 1.00 0.00 +ATOM 6063 HW2 SOL 1943 31.540 26.720 16.340 1.00 0.00 +ATOM 6064 OW SOL 1944 29.460 2.890 4.410 1.00 0.00 +ATOM 6065 HW1 SOL 1944 28.520 2.930 4.280 1.00 0.00 +ATOM 6066 HW2 SOL 1944 29.670 3.690 4.890 1.00 0.00 +ATOM 6067 OW SOL 1945 39.540 18.560 4.790 1.00 0.00 +ATOM 6068 HW1 SOL 1945 38.630 18.530 4.480 1.00 0.00 +ATOM 6069 HW2 SOL 1945 39.630 17.770 5.330 1.00 0.00 +ATOM 6070 OW SOL 1946 44.650 7.920 3.560 1.00 0.00 +ATOM 6071 HW1 SOL 1946 45.020 7.500 4.340 1.00 0.00 +ATOM 6072 HW2 SOL 1946 44.410 8.800 3.840 1.00 0.00 +ATOM 6073 OW SOL 1947 37.360 31.090 15.330 1.00 0.00 +ATOM 6074 HW1 SOL 1947 37.730 31.100 16.210 1.00 0.00 +ATOM 6075 HW2 SOL 1947 37.890 30.460 14.850 1.00 0.00 +ATOM 6076 OW SOL 1948 16.690 29.870 2.400 1.00 0.00 +ATOM 6077 HW1 SOL 1948 17.400 30.460 2.640 1.00 0.00 +ATOM 6078 HW2 SOL 1948 15.930 30.440 2.290 1.00 0.00 +ATOM 6079 OW SOL 1949 1.950 24.490 4.610 1.00 0.00 +ATOM 6080 HW1 SOL 1949 1.700 24.890 3.780 1.00 0.00 +ATOM 6081 HW2 SOL 1949 2.330 25.200 5.120 1.00 0.00 +ATOM 6082 OW SOL 1950 24.020 2.440 4.350 1.00 0.00 +ATOM 6083 HW1 SOL 1950 24.120 1.510 4.570 1.00 0.00 +ATOM 6084 HW2 SOL 1950 23.160 2.480 3.920 1.00 0.00 +ATOM 6085 OW SOL 1951 24.720 33.180 8.450 1.00 0.00 +ATOM 6086 HW1 SOL 1951 25.210 33.950 8.150 1.00 0.00 +ATOM 6087 HW2 SOL 1951 25.070 32.460 7.940 1.00 0.00 +ATOM 6088 OW SOL 1952 21.350 38.990 21.590 1.00 0.00 +ATOM 6089 HW1 SOL 1952 22.170 38.770 22.020 1.00 0.00 +ATOM 6090 HW2 SOL 1952 21.600 39.280 20.710 1.00 0.00 +ATOM 6091 OW SOL 1953 31.000 28.160 19.640 1.00 0.00 +ATOM 6092 HW1 SOL 1953 31.610 27.450 19.870 1.00 0.00 +ATOM 6093 HW2 SOL 1953 31.520 28.750 19.100 1.00 0.00 +ATOM 6094 OW SOL 1954 24.030 28.950 4.630 1.00 0.00 +ATOM 6095 HW1 SOL 1954 24.090 28.460 5.450 1.00 0.00 +ATOM 6096 HW2 SOL 1954 23.740 29.820 4.890 1.00 0.00 +ATOM 6097 OW SOL 1955 41.300 16.520 29.690 1.00 0.00 +ATOM 6098 HW1 SOL 1955 41.420 17.440 29.930 1.00 0.00 +ATOM 6099 HW2 SOL 1955 42.170 16.140 29.740 1.00 0.00 +ATOM 6100 OW SOL 1956 60.049 20.002 32.688 1.00 0.00 +ATOM 6101 HW1 SOL 1956 60.839 20.241 32.198 1.00 0.00 +ATOM 6102 HW2 SOL 1956 59.889 20.752 33.268 1.00 0.00 +ATOM 6103 OW SOL 1957 54.827 20.930 30.720 1.00 0.00 +ATOM 6104 HW1 SOL 1957 55.257 20.150 31.070 1.00 0.00 +ATOM 6105 HW2 SOL 1957 54.237 21.200 31.420 1.00 0.00 +ATOM 6106 OW SOL 1958 24.110 42.100 25.780 1.00 0.00 +ATOM 6107 HW1 SOL 1958 23.300 41.890 26.250 1.00 0.00 +ATOM 6108 HW2 SOL 1958 24.580 42.700 26.360 1.00 0.00 +ATOM 6109 OW SOL 1959 29.380 31.840 21.050 1.00 0.00 +ATOM 6110 HW1 SOL 1959 29.990 31.250 20.600 1.00 0.00 +ATOM 6111 HW2 SOL 1959 29.350 31.510 21.950 1.00 0.00 +ATOM 6112 OW SOL 1960 25.360 27.900 17.390 1.00 0.00 +ATOM 6113 HW1 SOL 1960 25.360 27.250 18.090 1.00 0.00 +ATOM 6114 HW2 SOL 1960 24.800 28.600 17.710 1.00 0.00 +ATOM 6115 OW SOL 1961 18.610 6.140 28.030 1.00 0.00 +ATOM 6116 HW1 SOL 1961 19.180 5.610 28.600 1.00 0.00 +ATOM 6117 HW2 SOL 1961 19.220 6.670 27.510 1.00 0.00 +ATOM 6118 OW SOL 1962 35.250 24.350 4.330 1.00 0.00 +ATOM 6119 HW1 SOL 1962 35.610 25.220 4.450 1.00 0.00 +ATOM 6120 HW2 SOL 1962 35.970 23.840 3.960 1.00 0.00 +ATOM 6121 OW SOL 1963 29.610 30.200 24.040 1.00 0.00 +ATOM 6122 HW1 SOL 1963 29.120 29.460 23.700 1.00 0.00 +ATOM 6123 HW2 SOL 1963 30.510 30.040 23.760 1.00 0.00 +ATOM 6124 OW SOL 1964 19.150 1.590 11.640 1.00 0.00 +ATOM 6125 HW1 SOL 1964 19.410 1.280 12.510 1.00 0.00 +ATOM 6126 HW2 SOL 1964 19.840 2.210 11.390 1.00 0.00 +ATOM 6127 OW SOL 1965 28.970 14.030 22.570 1.00 0.00 +ATOM 6128 HW1 SOL 1965 28.860 14.920 22.230 1.00 0.00 +ATOM 6129 HW2 SOL 1965 29.880 14.000 22.860 1.00 0.00 +ATOM 6130 OW SOL 1966 31.980 31.680 12.390 1.00 0.00 +ATOM 6131 HW1 SOL 1966 31.850 30.810 12.010 1.00 0.00 +ATOM 6132 HW2 SOL 1966 32.760 32.020 11.940 1.00 0.00 +ATOM 6133 OW SOL 1967 19.460 24.130 28.560 1.00 0.00 +ATOM 6134 HW1 SOL 1967 19.730 23.640 29.330 1.00 0.00 +ATOM 6135 HW2 SOL 1967 19.070 23.480 27.980 1.00 0.00 +ATOM 6136 OW SOL 1968 20.690 19.340 31.490 1.00 0.00 +ATOM 6137 HW1 SOL 1968 19.940 19.920 31.630 1.00 0.00 +ATOM 6138 HW2 SOL 1968 20.350 18.460 31.670 1.00 0.00 +ATOM 6139 OW SOL 1969 44.870 37.350 4.320 1.00 0.00 +ATOM 6140 HW1 SOL 1969 44.460 36.890 3.590 1.00 0.00 +ATOM 6141 HW2 SOL 1969 45.580 37.860 3.920 1.00 0.00 +ATOM 6142 OW SOL 1970 46.807 30.340 12.270 1.00 0.00 +ATOM 6143 HW1 SOL 1970 47.027 29.470 12.620 1.00 0.00 +ATOM 6144 HW2 SOL 1970 46.867 30.920 13.020 1.00 0.00 +ATOM 6145 OW SOL 1971 19.300 24.470 19.200 1.00 0.00 +ATOM 6146 HW1 SOL 1971 19.180 24.190 20.110 1.00 0.00 +ATOM 6147 HW2 SOL 1971 20.190 24.210 18.980 1.00 0.00 +ATOM 6148 OW SOL 1972 38.010 4.970 13.730 1.00 0.00 +ATOM 6149 HW1 SOL 1972 37.340 5.520 13.330 1.00 0.00 +ATOM 6150 HW2 SOL 1972 37.570 4.130 13.870 1.00 0.00 +ATOM 6151 OW SOL 1973 27.480 0.760 7.500 1.00 0.00 +ATOM 6152 HW1 SOL 1973 27.470 1.720 7.610 1.00 0.00 +ATOM 6153 HW2 SOL 1973 27.870 0.440 8.310 1.00 0.00 +ATOM 6154 OW SOL 1974 12.470 21.940 30.110 1.00 0.00 +ATOM 6155 HW1 SOL 1974 11.730 22.250 29.590 1.00 0.00 +ATOM 6156 HW2 SOL 1974 12.940 22.740 30.370 1.00 0.00 +ATOM 6157 OW SOL 1975 8.430 14.580 6.780 1.00 0.00 +ATOM 6158 HW1 SOL 1975 8.100 14.570 5.890 1.00 0.00 +ATOM 6159 HW2 SOL 1975 7.980 13.850 7.210 1.00 0.00 +ATOM 6160 OW SOL 1976 40.030 41.310 0.390 1.00 0.00 +ATOM 6161 HW1 SOL 1976 39.980 41.490 -0.550 1.00 0.00 +ATOM 6162 HW2 SOL 1976 39.500 40.520 0.520 1.00 0.00 +ATOM 6163 OW SOL 1977 29.300 17.460 27.620 1.00 0.00 +ATOM 6164 HW1 SOL 1977 29.880 17.870 28.260 1.00 0.00 +ATOM 6165 HW2 SOL 1977 28.480 17.960 27.680 1.00 0.00 +ATOM 6166 OW SOL 1978 15.370 3.680 30.660 1.00 0.00 +ATOM 6167 HW1 SOL 1978 14.490 3.960 30.880 1.00 0.00 +ATOM 6168 HW2 SOL 1978 15.600 4.180 29.880 1.00 0.00 +ATOM 6169 OW SOL 1979 35.270 29.280 23.470 1.00 0.00 +ATOM 6170 HW1 SOL 1979 35.190 28.760 22.670 1.00 0.00 +ATOM 6171 HW2 SOL 1979 35.850 30.000 23.230 1.00 0.00 +ATOM 6172 OW SOL 1980 42.780 4.570 23.050 1.00 0.00 +ATOM 6173 HW1 SOL 1980 43.270 5.130 23.660 1.00 0.00 +ATOM 6174 HW2 SOL 1980 43.130 3.690 23.210 1.00 0.00 +ATOM 6175 OW SOL 1981 25.310 32.720 29.400 1.00 0.00 +ATOM 6176 HW1 SOL 1981 25.270 32.900 28.460 1.00 0.00 +ATOM 6177 HW2 SOL 1981 24.950 31.840 29.490 1.00 0.00 +ATOM 6178 OW SOL 1982 22.180 31.190 15.280 1.00 0.00 +ATOM 6179 HW1 SOL 1982 22.520 31.360 14.400 1.00 0.00 +ATOM 6180 HW2 SOL 1982 21.340 30.760 15.130 1.00 0.00 +ATOM 6181 OW SOL 1983 29.960 26.400 17.400 1.00 0.00 +ATOM 6182 HW1 SOL 1983 29.080 26.480 17.020 1.00 0.00 +ATOM 6183 HW2 SOL 1983 30.080 27.220 17.880 1.00 0.00 +ATOM 6184 OW SOL 1984 40.520 27.560 30.920 1.00 0.00 +ATOM 6185 HW1 SOL 1984 39.850 27.550 31.610 1.00 0.00 +ATOM 6186 HW2 SOL 1984 41.190 26.960 31.240 1.00 0.00 +ATOM 6187 OW SOL 1985 27.619 63.429 33.378 1.00 0.00 +ATOM 6188 HW1 SOL 1985 27.569 64.069 34.078 1.00 0.00 +ATOM 6189 HW2 SOL 1985 27.569 62.579 33.818 1.00 0.00 +ATOM 6190 OW SOL 1986 24.880 56.447 25.850 1.00 0.00 +ATOM 6191 HW1 SOL 1986 25.070 56.187 26.750 1.00 0.00 +ATOM 6192 HW2 SOL 1986 25.420 57.227 25.710 1.00 0.00 +ATOM 6193 OW SOL 1987 22.640 24.970 22.500 1.00 0.00 +ATOM 6194 HW1 SOL 1987 21.910 24.400 22.260 1.00 0.00 +ATOM 6195 HW2 SOL 1987 22.650 24.960 23.450 1.00 0.00 +ATOM 6196 OW SOL 1988 28.420 20.070 16.720 1.00 0.00 +ATOM 6197 HW1 SOL 1988 29.360 20.120 16.880 1.00 0.00 +ATOM 6198 HW2 SOL 1988 28.130 19.290 17.180 1.00 0.00 +ATOM 6199 OW SOL 1989 44.780 24.890 16.580 1.00 0.00 +ATOM 6200 HW1 SOL 1989 45.570 25.440 16.580 1.00 0.00 +ATOM 6201 HW2 SOL 1989 44.100 25.440 16.210 1.00 0.00 +ATOM 6202 OW SOL 1990 19.040 41.800 2.910 1.00 0.00 +ATOM 6203 HW1 SOL 1990 19.140 41.830 3.860 1.00 0.00 +ATOM 6204 HW2 SOL 1990 18.420 41.090 2.750 1.00 0.00 +ATOM 6205 OW SOL 1991 13.060 44.630 12.980 1.00 0.00 +ATOM 6206 HW1 SOL 1991 13.560 45.100 13.640 1.00 0.00 +ATOM 6207 HW2 SOL 1991 13.720 44.230 12.410 1.00 0.00 +ATOM 6208 OW SOL 1992 21.050 10.350 18.640 1.00 0.00 +ATOM 6209 HW1 SOL 1992 21.880 10.380 18.170 1.00 0.00 +ATOM 6210 HW2 SOL 1992 21.110 9.590 19.210 1.00 0.00 +ATOM 6211 OW SOL 1993 16.730 8.120 23.970 1.00 0.00 +ATOM 6212 HW1 SOL 1993 16.250 7.360 24.290 1.00 0.00 +ATOM 6213 HW2 SOL 1993 16.060 8.700 23.600 1.00 0.00 +ATOM 6214 OW SOL 1994 7.090 8.800 26.260 1.00 0.00 +ATOM 6215 HW1 SOL 1994 7.900 8.380 25.960 1.00 0.00 +ATOM 6216 HW2 SOL 1994 6.430 8.110 26.190 1.00 0.00 +ATOM 6217 OW SOL 1995 38.740 38.160 30.890 1.00 0.00 +ATOM 6218 HW1 SOL 1995 39.460 37.740 31.370 1.00 0.00 +ATOM 6219 HW2 SOL 1995 39.180 38.640 30.190 1.00 0.00 +ATOM 6220 OW SOL 1996 0.450 26.140 19.710 1.00 0.00 +ATOM 6221 HW1 SOL 1996 0.190 26.890 19.180 1.00 0.00 +ATOM 6222 HW2 SOL 1996 0.310 26.410 20.620 1.00 0.00 +ATOM 6223 OW SOL 1997 4.430 4.630 1.090 1.00 0.00 +ATOM 6224 HW1 SOL 1997 3.520 4.650 1.410 1.00 0.00 +ATOM 6225 HW2 SOL 1997 4.720 5.540 1.180 1.00 0.00 +ATOM 6226 OW SOL 1998 -0.229 3.661 -0.428 1.00 0.00 +ATOM 6227 HW1 SOL 1998 -1.179 3.761 -0.488 1.00 0.00 +ATOM 6228 HW2 SOL 1998 0.071 4.431 0.052 1.00 0.00 +ATOM 6229 OW SOL 1999 28.450 4.120 16.910 1.00 0.00 +ATOM 6230 HW1 SOL 1999 29.100 3.720 17.490 1.00 0.00 +ATOM 6231 HW2 SOL 1999 27.690 3.550 16.980 1.00 0.00 +ATOM 6232 OW SOL 2000 3.800 32.400 11.350 1.00 0.00 +ATOM 6233 HW1 SOL 2000 4.010 31.850 10.600 1.00 0.00 +ATOM 6234 HW2 SOL 2000 3.150 31.900 11.840 1.00 0.00 +ATOM 6235 OW SOL 2001 14.540 6.390 27.300 1.00 0.00 +ATOM 6236 HW1 SOL 2001 14.520 6.800 26.440 1.00 0.00 +ATOM 6237 HW2 SOL 2001 13.620 6.300 27.550 1.00 0.00 +ATOM 6238 OW SOL 2002 33.930 1.430 23.300 1.00 0.00 +ATOM 6239 HW1 SOL 2002 34.600 1.720 22.680 1.00 0.00 +ATOM 6240 HW2 SOL 2002 33.650 2.230 23.740 1.00 0.00 +ATOM 6241 OW SOL 2003 22.790 34.070 17.370 1.00 0.00 +ATOM 6242 HW1 SOL 2003 23.420 34.710 17.690 1.00 0.00 +ATOM 6243 HW2 SOL 2003 23.330 33.370 17.000 1.00 0.00 +ATOM 6244 OW SOL 2004 6.550 16.890 25.980 1.00 0.00 +ATOM 6245 HW1 SOL 2004 6.340 16.160 25.400 1.00 0.00 +ATOM 6246 HW2 SOL 2004 7.380 16.650 26.390 1.00 0.00 +ATOM 6247 OW SOL 2005 17.120 15.250 14.370 1.00 0.00 +ATOM 6248 HW1 SOL 2005 16.720 15.950 13.850 1.00 0.00 +ATOM 6249 HW2 SOL 2005 17.940 15.620 14.680 1.00 0.00 +ATOM 6250 OW SOL 2006 5.980 8.150 28.970 1.00 0.00 +ATOM 6251 HW1 SOL 2006 6.200 8.790 29.640 1.00 0.00 +ATOM 6252 HW2 SOL 2006 6.500 8.400 28.210 1.00 0.00 +ATOM 6253 OW SOL 2007 24.270 19.050 2.160 1.00 0.00 +ATOM 6254 HW1 SOL 2007 24.740 18.230 2.310 1.00 0.00 +ATOM 6255 HW2 SOL 2007 24.960 19.700 2.030 1.00 0.00 +ATOM 6256 OW SOL 2008 32.780 20.040 24.450 1.00 0.00 +ATOM 6257 HW1 SOL 2008 32.660 19.290 23.870 1.00 0.00 +ATOM 6258 HW2 SOL 2008 31.980 20.550 24.360 1.00 0.00 +ATOM 6259 OW SOL 2009 22.550 29.820 31.060 1.00 0.00 +ATOM 6260 HW1 SOL 2009 22.970 30.440 31.660 1.00 0.00 +ATOM 6261 HW2 SOL 2009 22.260 30.360 30.320 1.00 0.00 +ATOM 6262 OW SOL 2010 2.070 13.780 28.850 1.00 0.00 +ATOM 6263 HW1 SOL 2010 2.630 13.010 28.930 1.00 0.00 +ATOM 6264 HW2 SOL 2010 2.500 14.320 28.190 1.00 0.00 +ATOM 6265 OW SOL 2011 37.030 35.030 29.590 1.00 0.00 +ATOM 6266 HW1 SOL 2011 36.670 34.310 29.080 1.00 0.00 +ATOM 6267 HW2 SOL 2011 36.860 34.780 30.500 1.00 0.00 +ATOM 6268 OW SOL 2012 28.320 41.250 31.700 1.00 0.00 +ATOM 6269 HW1 SOL 2012 28.280 40.750 30.880 1.00 0.00 +ATOM 6270 HW2 SOL 2012 27.410 41.380 31.950 1.00 0.00 +ATOM 6271 OW SOL 2013 40.600 14.010 19.210 1.00 0.00 +ATOM 6272 HW1 SOL 2013 39.770 14.310 19.570 1.00 0.00 +ATOM 6273 HW2 SOL 2013 40.930 14.760 18.720 1.00 0.00 +ATOM 6274 OW SOL 2014 23.910 24.840 2.770 1.00 0.00 +ATOM 6275 HW1 SOL 2014 24.270 24.020 2.430 1.00 0.00 +ATOM 6276 HW2 SOL 2014 23.480 24.590 3.580 1.00 0.00 +ATOM 6277 OW SOL 2015 6.090 13.560 27.900 1.00 0.00 +ATOM 6278 HW1 SOL 2015 5.570 13.270 27.150 1.00 0.00 +ATOM 6279 HW2 SOL 2015 6.720 14.180 27.530 1.00 0.00 +ATOM 6280 OW SOL 2016 19.840 37.830 17.690 1.00 0.00 +ATOM 6281 HW1 SOL 2016 19.450 37.410 18.460 1.00 0.00 +ATOM 6282 HW2 SOL 2016 19.200 38.480 17.420 1.00 0.00 +ATOM 6283 OW SOL 2017 7.200 27.820 19.810 1.00 0.00 +ATOM 6284 HW1 SOL 2017 7.600 28.610 19.440 1.00 0.00 +ATOM 6285 HW2 SOL 2017 6.290 27.850 19.510 1.00 0.00 +ATOM 6286 OW SOL 2018 19.390 0.910 14.200 1.00 0.00 +ATOM 6287 HW1 SOL 2018 19.760 0.410 14.930 1.00 0.00 +ATOM 6288 HW2 SOL 2018 18.450 0.740 14.250 1.00 0.00 +ATOM 6289 OW SOL 2019 20.640 0.300 19.230 1.00 0.00 +ATOM 6290 HW1 SOL 2019 19.740 0.030 19.430 1.00 0.00 +ATOM 6291 HW2 SOL 2019 20.990 -0.410 18.700 1.00 0.00 +ATOM 6292 OW SOL 2020 4.740 23.630 2.300 1.00 0.00 +ATOM 6293 HW1 SOL 2020 5.430 23.150 2.750 1.00 0.00 +ATOM 6294 HW2 SOL 2020 4.150 22.960 1.980 1.00 0.00 +ATOM 6295 OW SOL 2021 21.750 32.750 2.590 1.00 0.00 +ATOM 6296 HW1 SOL 2021 20.850 32.430 2.520 1.00 0.00 +ATOM 6297 HW2 SOL 2021 21.840 33.390 1.890 1.00 0.00 +ATOM 6298 OW SOL 2022 40.130 22.730 20.670 1.00 0.00 +ATOM 6299 HW1 SOL 2022 40.620 22.930 21.470 1.00 0.00 +ATOM 6300 HW2 SOL 2022 39.830 21.830 20.800 1.00 0.00 +ATOM 6301 OW SOL 2023 17.540 5.810 31.440 1.00 0.00 +ATOM 6302 HW1 SOL 2023 18.410 5.500 31.180 1.00 0.00 +ATOM 6303 HW2 SOL 2023 16.940 5.430 30.800 1.00 0.00 +ATOM 6304 OW SOL 2024 29.300 42.640 14.340 1.00 0.00 +ATOM 6305 HW1 SOL 2024 28.970 41.780 14.110 1.00 0.00 +ATOM 6306 HW2 SOL 2024 28.880 43.240 13.720 1.00 0.00 +ATOM 6307 OW SOL 2025 39.940 19.950 21.790 1.00 0.00 +ATOM 6308 HW1 SOL 2025 39.220 19.430 21.440 1.00 0.00 +ATOM 6309 HW2 SOL 2025 40.040 19.640 22.690 1.00 0.00 +ATOM 6310 OW SOL 2026 2.460 9.370 18.520 1.00 0.00 +ATOM 6311 HW1 SOL 2026 2.600 10.160 18.010 1.00 0.00 +ATOM 6312 HW2 SOL 2026 3.220 9.310 19.100 1.00 0.00 +ATOM 6313 OW SOL 2027 26.880 30.940 8.660 1.00 0.00 +ATOM 6314 HW1 SOL 2027 26.380 31.000 7.850 1.00 0.00 +ATOM 6315 HW2 SOL 2027 27.680 31.430 8.490 1.00 0.00 +ATOM 6316 OW SOL 2028 12.780 1.760 5.870 1.00 0.00 +ATOM 6317 HW1 SOL 2028 12.850 0.880 5.490 1.00 0.00 +ATOM 6318 HW2 SOL 2028 11.930 1.760 6.300 1.00 0.00 +ATOM 6319 OW SOL 2029 39.070 33.720 16.120 1.00 0.00 +ATOM 6320 HW1 SOL 2029 39.310 33.350 16.970 1.00 0.00 +ATOM 6321 HW2 SOL 2029 38.170 34.020 16.240 1.00 0.00 +ATOM 6322 OW SOL 2030 23.830 8.520 14.100 1.00 0.00 +ATOM 6323 HW1 SOL 2030 23.950 9.170 13.400 1.00 0.00 +ATOM 6324 HW2 SOL 2030 23.030 8.810 14.550 1.00 0.00 +ATOM 6325 OW SOL 2031 16.570 3.990 1.210 1.00 0.00 +ATOM 6326 HW1 SOL 2031 15.880 4.050 1.870 1.00 0.00 +ATOM 6327 HW2 SOL 2031 17.310 3.590 1.670 1.00 0.00 +ATOM 6328 OW SOL 2032 40.870 12.860 29.770 1.00 0.00 +ATOM 6329 HW1 SOL 2032 40.950 12.530 28.880 1.00 0.00 +ATOM 6330 HW2 SOL 2032 40.660 12.080 30.300 1.00 0.00 +ATOM 6331 OW SOL 2033 35.450 23.180 17.580 1.00 0.00 +ATOM 6332 HW1 SOL 2033 35.260 23.820 16.900 1.00 0.00 +ATOM 6333 HW2 SOL 2033 36.400 23.040 17.530 1.00 0.00 +ATOM 6334 OW SOL 2034 14.900 38.850 16.790 1.00 0.00 +ATOM 6335 HW1 SOL 2034 15.360 38.580 15.990 1.00 0.00 +ATOM 6336 HW2 SOL 2034 15.350 39.640 17.080 1.00 0.00 +ATOM 6337 OW SOL 2035 39.550 37.990 5.000 1.00 0.00 +ATOM 6338 HW1 SOL 2035 39.590 38.950 4.930 1.00 0.00 +ATOM 6339 HW2 SOL 2035 40.160 37.670 4.340 1.00 0.00 +ATOM 6340 OW SOL 2036 35.920 26.960 10.620 1.00 0.00 +ATOM 6341 HW1 SOL 2036 36.390 26.920 9.790 1.00 0.00 +ATOM 6342 HW2 SOL 2036 35.190 27.570 10.460 1.00 0.00 +ATOM 6343 OW SOL 2037 36.950 26.450 14.720 1.00 0.00 +ATOM 6344 HW1 SOL 2037 37.570 25.840 14.320 1.00 0.00 +ATOM 6345 HW2 SOL 2037 37.410 26.800 15.480 1.00 0.00 +ATOM 6346 OW SOL 2038 10.680 15.440 0.700 1.00 0.00 +ATOM 6347 HW1 SOL 2038 9.910 15.820 1.120 1.00 0.00 +ATOM 6348 HW2 SOL 2038 11.200 16.200 0.430 1.00 0.00 +ATOM 6349 OW SOL 2039 36.520 44.210 9.120 1.00 0.00 +ATOM 6350 HW1 SOL 2039 37.410 44.500 9.320 1.00 0.00 +ATOM 6351 HW2 SOL 2039 36.200 43.840 9.950 1.00 0.00 +ATOM 6352 OW SOL 2040 9.670 36.030 2.370 1.00 0.00 +ATOM 6353 HW1 SOL 2040 8.750 36.050 2.620 1.00 0.00 +ATOM 6354 HW2 SOL 2040 9.670 36.170 1.420 1.00 0.00 +ATOM 6355 OW SOL 2041 28.660 4.080 27.280 1.00 0.00 +ATOM 6356 HW1 SOL 2041 28.940 3.720 28.120 1.00 0.00 +ATOM 6357 HW2 SOL 2041 27.790 3.710 27.140 1.00 0.00 +ATOM 6358 OW SOL 2042 12.210 34.730 0.460 1.00 0.00 +ATOM 6359 HW1 SOL 2042 12.010 34.390 1.330 1.00 0.00 +ATOM 6360 HW2 SOL 2042 13.150 34.880 0.470 1.00 0.00 +ATOM 6361 OW SOL 2043 29.030 17.740 24.100 1.00 0.00 +ATOM 6362 HW1 SOL 2043 28.810 16.830 24.320 1.00 0.00 +ATOM 6363 HW2 SOL 2043 29.300 18.130 24.930 1.00 0.00 +ATOM 6364 OW SOL 2044 31.950 31.210 1.710 1.00 0.00 +ATOM 6365 HW1 SOL 2044 32.490 31.990 1.520 1.00 0.00 +ATOM 6366 HW2 SOL 2044 32.580 30.560 2.010 1.00 0.00 +ATOM 6367 OW SOL 2045 10.470 12.260 21.460 1.00 0.00 +ATOM 6368 HW1 SOL 2045 9.580 11.920 21.350 1.00 0.00 +ATOM 6369 HW2 SOL 2045 10.620 12.790 20.680 1.00 0.00 +ATOM 6370 OW SOL 2046 31.770 24.110 9.780 1.00 0.00 +ATOM 6371 HW1 SOL 2046 31.650 23.490 10.500 1.00 0.00 +ATOM 6372 HW2 SOL 2046 31.020 23.960 9.210 1.00 0.00 +ATOM 6373 OW SOL 2047 0.400 12.170 25.840 1.00 0.00 +ATOM 6374 HW1 SOL 2047 1.290 12.130 26.180 1.00 0.00 +ATOM 6375 HW2 SOL 2047 0.510 12.440 24.930 1.00 0.00 +ATOM 6376 OW SOL 2048 8.900 16.750 4.940 1.00 0.00 +ATOM 6377 HW1 SOL 2048 9.820 16.980 5.090 1.00 0.00 +ATOM 6378 HW2 SOL 2048 8.450 17.050 5.720 1.00 0.00 +ATOM 6379 OW SOL 2049 17.950 24.500 13.870 1.00 0.00 +ATOM 6380 HW1 SOL 2049 17.630 24.370 12.980 1.00 0.00 +ATOM 6381 HW2 SOL 2049 17.510 25.290 14.170 1.00 0.00 +ATOM 6382 OW SOL 2050 22.130 38.880 4.690 1.00 0.00 +ATOM 6383 HW1 SOL 2050 21.710 38.700 3.850 1.00 0.00 +ATOM 6384 HW2 SOL 2050 21.430 38.820 5.330 1.00 0.00 +ATOM 6385 OW SOL 2051 41.030 20.850 11.110 1.00 0.00 +ATOM 6386 HW1 SOL 2051 40.740 21.450 10.420 1.00 0.00 +ATOM 6387 HW2 SOL 2051 41.980 20.810 11.010 1.00 0.00 +ATOM 6388 OW SOL 2052 16.910 19.640 13.050 1.00 0.00 +ATOM 6389 HW1 SOL 2052 16.350 20.290 12.630 1.00 0.00 +ATOM 6390 HW2 SOL 2052 16.960 19.920 13.960 1.00 0.00 +ATOM 6391 OW SOL 2053 31.780 41.360 7.180 1.00 0.00 +ATOM 6392 HW1 SOL 2053 31.550 42.060 6.560 1.00 0.00 +ATOM 6393 HW2 SOL 2053 32.550 41.690 7.640 1.00 0.00 +ATOM 6394 OW SOL 2054 14.830 11.470 15.300 1.00 0.00 +ATOM 6395 HW1 SOL 2054 14.530 12.110 14.660 1.00 0.00 +ATOM 6396 HW2 SOL 2054 15.770 11.630 15.380 1.00 0.00 +ATOM 6397 OW SOL 2055 13.230 27.420 16.490 1.00 0.00 +ATOM 6398 HW1 SOL 2055 14.130 27.740 16.600 1.00 0.00 +ATOM 6399 HW2 SOL 2055 12.690 28.080 16.940 1.00 0.00 +ATOM 6400 OW SOL 2056 23.170 42.720 4.380 1.00 0.00 +ATOM 6401 HW1 SOL 2056 23.500 42.180 5.090 1.00 0.00 +ATOM 6402 HW2 SOL 2056 22.500 43.270 4.780 1.00 0.00 +ATOM 6403 OW SOL 2057 13.730 41.530 13.200 1.00 0.00 +ATOM 6404 HW1 SOL 2057 14.630 41.410 12.870 1.00 0.00 +ATOM 6405 HW2 SOL 2057 13.410 40.640 13.330 1.00 0.00 +ATOM 6406 OW SOL 2058 38.890 31.250 6.500 1.00 0.00 +ATOM 6407 HW1 SOL 2058 39.150 31.410 5.590 1.00 0.00 +ATOM 6408 HW2 SOL 2058 38.480 30.380 6.480 1.00 0.00 +ATOM 6409 OW SOL 2059 0.500 42.270 27.870 1.00 0.00 +ATOM 6410 HW1 SOL 2059 0.460 41.480 28.400 1.00 0.00 +ATOM 6411 HW2 SOL 2059 1.220 42.780 28.250 1.00 0.00 +ATOM 6412 OW SOL 2060 14.030 14.020 6.710 1.00 0.00 +ATOM 6413 HW1 SOL 2060 13.950 13.110 6.990 1.00 0.00 +ATOM 6414 HW2 SOL 2060 13.120 14.330 6.670 1.00 0.00 +ATOM 6415 OW SOL 2061 31.060 5.530 22.010 1.00 0.00 +ATOM 6416 HW1 SOL 2061 30.650 5.650 21.150 1.00 0.00 +ATOM 6417 HW2 SOL 2061 30.680 6.230 22.550 1.00 0.00 +ATOM 6418 OW SOL 2062 34.100 3.550 31.010 1.00 0.00 +ATOM 6419 HW1 SOL 2062 34.190 4.510 31.030 1.00 0.00 +ATOM 6420 HW2 SOL 2062 34.570 3.300 30.210 1.00 0.00 +ATOM 6421 OW SOL 2063 36.110 42.270 24.360 1.00 0.00 +ATOM 6422 HW1 SOL 2063 36.990 42.570 24.590 1.00 0.00 +ATOM 6423 HW2 SOL 2063 35.940 42.640 23.500 1.00 0.00 +ATOM 6424 OW SOL 2064 9.370 35.530 20.390 1.00 0.00 +ATOM 6425 HW1 SOL 2064 9.030 35.580 21.290 1.00 0.00 +ATOM 6426 HW2 SOL 2064 10.310 35.620 20.490 1.00 0.00 +ATOM 6427 OW SOL 2065 19.890 35.890 30.210 1.00 0.00 +ATOM 6428 HW1 SOL 2065 20.330 35.360 30.880 1.00 0.00 +ATOM 6429 HW2 SOL 2065 19.590 36.670 30.680 1.00 0.00 +ATOM 6430 OW SOL 2066 32.489 62.029 33.468 1.00 0.00 +ATOM 6431 HW1 SOL 2066 32.209 62.059 32.548 1.00 0.00 +ATOM 6432 HW2 SOL 2066 32.789 62.919 33.648 1.00 0.00 +ATOM 6433 OW SOL 2067 32.690 58.097 16.790 1.00 0.00 +ATOM 6434 HW1 SOL 2067 32.640 58.837 17.400 1.00 0.00 +ATOM 6435 HW2 SOL 2067 33.200 57.437 17.260 1.00 0.00 +ATOM 6436 OW SOL 2068 17.860 30.440 23.060 1.00 0.00 +ATOM 6437 HW1 SOL 2068 17.590 29.600 23.430 1.00 0.00 +ATOM 6438 HW2 SOL 2068 17.950 31.020 23.810 1.00 0.00 +ATOM 6439 OW SOL 2069 41.040 41.630 5.840 1.00 0.00 +ATOM 6440 HW1 SOL 2069 41.340 42.520 5.630 1.00 0.00 +ATOM 6441 HW2 SOL 2069 41.830 41.180 6.120 1.00 0.00 +ATOM 6442 OW SOL 2070 2.670 10.570 1.950 1.00 0.00 +ATOM 6443 HW1 SOL 2070 3.230 9.810 2.090 1.00 0.00 +ATOM 6444 HW2 SOL 2070 3.240 11.320 2.130 1.00 0.00 +ATOM 6445 OW SOL 2071 1.400 19.020 22.230 1.00 0.00 +ATOM 6446 HW1 SOL 2071 0.520 18.820 21.920 1.00 0.00 +ATOM 6447 HW2 SOL 2071 1.980 18.650 21.560 1.00 0.00 +ATOM 6448 OW SOL 2072 32.650 17.760 22.230 1.00 0.00 +ATOM 6449 HW1 SOL 2072 33.210 17.890 21.460 1.00 0.00 +ATOM 6450 HW2 SOL 2072 33.110 17.110 22.750 1.00 0.00 +ATOM 6451 OW SOL 2073 40.180 30.420 9.600 1.00 0.00 +ATOM 6452 HW1 SOL 2073 40.680 31.220 9.420 1.00 0.00 +ATOM 6453 HW2 SOL 2073 40.080 30.410 10.550 1.00 0.00 +ATOM 6454 OW SOL 2074 30.090 22.470 11.400 1.00 0.00 +ATOM 6455 HW1 SOL 2074 30.930 22.560 11.840 1.00 0.00 +ATOM 6456 HW2 SOL 2074 29.560 23.190 11.740 1.00 0.00 +ATOM 6457 OW SOL 2075 22.590 2.410 19.150 1.00 0.00 +ATOM 6458 HW1 SOL 2075 22.940 2.610 18.280 1.00 0.00 +ATOM 6459 HW2 SOL 2075 22.190 1.540 19.050 1.00 0.00 +ATOM 6460 OW SOL 2076 0.990 15.750 21.130 1.00 0.00 +ATOM 6461 HW1 SOL 2076 0.660 16.040 20.280 1.00 0.00 +ATOM 6462 HW2 SOL 2076 1.730 16.330 21.310 1.00 0.00 +ATOM 6463 OW SOL 2077 25.660 29.120 22.810 1.00 0.00 +ATOM 6464 HW1 SOL 2077 25.640 29.490 21.930 1.00 0.00 +ATOM 6465 HW2 SOL 2077 25.720 28.170 22.660 1.00 0.00 +ATOM 6466 OW SOL 2078 15.840 17.060 12.830 1.00 0.00 +ATOM 6467 HW1 SOL 2078 16.220 17.940 12.860 1.00 0.00 +ATOM 6468 HW2 SOL 2078 15.390 17.030 11.980 1.00 0.00 +ATOM 6469 OW SOL 2079 6.260 21.000 22.930 1.00 0.00 +ATOM 6470 HW1 SOL 2079 5.830 20.620 22.170 1.00 0.00 +ATOM 6471 HW2 SOL 2079 5.870 20.560 23.690 1.00 0.00 +ATOM 6472 OW SOL 2080 35.350 40.130 12.970 1.00 0.00 +ATOM 6473 HW1 SOL 2080 35.480 40.250 13.910 1.00 0.00 +ATOM 6474 HW2 SOL 2080 34.420 39.940 12.870 1.00 0.00 +ATOM 6475 OW SOL 2081 21.790 9.440 25.870 1.00 0.00 +ATOM 6476 HW1 SOL 2081 21.380 9.290 26.720 1.00 0.00 +ATOM 6477 HW2 SOL 2081 21.740 10.380 25.730 1.00 0.00 +ATOM 6478 OW SOL 2082 35.680 34.660 12.580 1.00 0.00 +ATOM 6479 HW1 SOL 2082 36.420 34.760 13.170 1.00 0.00 +ATOM 6480 HW2 SOL 2082 35.440 35.550 12.330 1.00 0.00 +ATOM 6481 OW SOL 2083 19.790 35.200 4.390 1.00 0.00 +ATOM 6482 HW1 SOL 2083 19.810 34.530 3.720 1.00 0.00 +ATOM 6483 HW2 SOL 2083 19.000 35.710 4.200 1.00 0.00 +ATOM 6484 OW SOL 2084 35.900 12.970 20.910 1.00 0.00 +ATOM 6485 HW1 SOL 2084 35.680 12.100 21.260 1.00 0.00 +ATOM 6486 HW2 SOL 2084 36.000 13.520 21.690 1.00 0.00 +ATOM 6487 OW SOL 2085 14.560 34.640 19.840 1.00 0.00 +ATOM 6488 HW1 SOL 2085 14.710 35.050 18.980 1.00 0.00 +ATOM 6489 HW2 SOL 2085 14.820 33.720 19.710 1.00 0.00 +ATOM 6490 OW SOL 2086 9.350 17.150 7.770 1.00 0.00 +ATOM 6491 HW1 SOL 2086 8.620 17.730 8.020 1.00 0.00 +ATOM 6492 HW2 SOL 2086 8.940 16.300 7.640 1.00 0.00 +ATOM 6493 OW SOL 2087 35.930 17.910 22.240 1.00 0.00 +ATOM 6494 HW1 SOL 2087 35.440 17.160 21.910 1.00 0.00 +ATOM 6495 HW2 SOL 2087 35.650 17.990 23.150 1.00 0.00 +ATOM 6496 OW SOL 2088 8.300 2.730 26.840 1.00 0.00 +ATOM 6497 HW1 SOL 2088 8.960 2.060 27.020 1.00 0.00 +ATOM 6498 HW2 SOL 2088 7.560 2.240 26.480 1.00 0.00 +ATOM 6499 OW SOL 2089 30.910 33.080 18.440 1.00 0.00 +ATOM 6500 HW1 SOL 2089 31.550 33.020 17.730 1.00 0.00 +ATOM 6501 HW2 SOL 2089 30.750 34.020 18.540 1.00 0.00 +ATOM 6502 OW SOL 2090 24.980 4.860 29.030 1.00 0.00 +ATOM 6503 HW1 SOL 2090 25.820 5.280 29.190 1.00 0.00 +ATOM 6504 HW2 SOL 2090 25.080 4.430 28.180 1.00 0.00 +ATOM 6505 OW SOL 2091 43.020 8.840 1.470 1.00 0.00 +ATOM 6506 HW1 SOL 2091 43.310 8.330 2.230 1.00 0.00 +ATOM 6507 HW2 SOL 2091 43.780 9.370 1.240 1.00 0.00 +ATOM 6508 OW SOL 2092 10.530 16.910 10.480 1.00 0.00 +ATOM 6509 HW1 SOL 2092 10.710 16.020 10.800 1.00 0.00 +ATOM 6510 HW2 SOL 2092 10.200 16.780 9.600 1.00 0.00 +ATOM 6511 OW SOL 2093 22.530 42.580 20.490 1.00 0.00 +ATOM 6512 HW1 SOL 2093 22.500 43.030 19.650 1.00 0.00 +ATOM 6513 HW2 SOL 2093 23.180 41.890 20.360 1.00 0.00 +ATOM 6514 OW SOL 2094 24.080 28.000 7.150 1.00 0.00 +ATOM 6515 HW1 SOL 2094 24.840 28.090 7.710 1.00 0.00 +ATOM 6516 HW2 SOL 2094 23.370 27.750 7.740 1.00 0.00 +ATOM 6517 OW SOL 2095 7.200 37.370 7.660 1.00 0.00 +ATOM 6518 HW1 SOL 2095 7.140 37.080 6.760 1.00 0.00 +ATOM 6519 HW2 SOL 2095 6.300 37.550 7.930 1.00 0.00 +ATOM 6520 OW SOL 2096 8.720 35.160 8.920 1.00 0.00 +ATOM 6521 HW1 SOL 2096 7.790 35.120 8.700 1.00 0.00 +ATOM 6522 HW2 SOL 2096 8.880 34.370 9.430 1.00 0.00 +ATOM 6523 OW SOL 2097 28.030 36.310 23.470 1.00 0.00 +ATOM 6524 HW1 SOL 2097 28.190 37.260 23.520 1.00 0.00 +ATOM 6525 HW2 SOL 2097 28.500 35.950 24.220 1.00 0.00 +ATOM 6526 OW SOL 2098 19.010 15.880 4.500 1.00 0.00 +ATOM 6527 HW1 SOL 2098 18.480 15.750 3.720 1.00 0.00 +ATOM 6528 HW2 SOL 2098 18.400 15.760 5.230 1.00 0.00 +ATOM 6529 OW SOL 2099 4.450 38.440 2.810 1.00 0.00 +ATOM 6530 HW1 SOL 2099 3.600 38.630 2.430 1.00 0.00 +ATOM 6531 HW2 SOL 2099 4.730 37.620 2.410 1.00 0.00 +ATOM 6532 OW SOL 2100 23.550 15.510 20.700 1.00 0.00 +ATOM 6533 HW1 SOL 2100 23.230 14.620 20.530 1.00 0.00 +ATOM 6534 HW2 SOL 2100 24.490 15.460 20.540 1.00 0.00 +ATOM 6535 OW SOL 2101 29.970 40.530 26.080 1.00 0.00 +ATOM 6536 HW1 SOL 2101 30.380 39.850 26.610 1.00 0.00 +ATOM 6537 HW2 SOL 2101 30.050 41.320 26.600 1.00 0.00 +ATOM 6538 OW SOL 2102 25.000 11.320 21.130 1.00 0.00 +ATOM 6539 HW1 SOL 2102 25.270 10.410 21.240 1.00 0.00 +ATOM 6540 HW2 SOL 2102 25.530 11.810 21.750 1.00 0.00 +ATOM 6541 OW SOL 2103 40.080 44.410 13.180 1.00 0.00 +ATOM 6542 HW1 SOL 2103 40.490 44.680 14.000 1.00 0.00 +ATOM 6543 HW2 SOL 2103 39.230 44.860 13.170 1.00 0.00 +ATOM 6544 OW SOL 2104 42.240 7.670 24.460 1.00 0.00 +ATOM 6545 HW1 SOL 2104 41.470 7.560 25.010 1.00 0.00 +ATOM 6546 HW2 SOL 2104 41.900 7.670 23.570 1.00 0.00 +ATOM 6547 OW SOL 2105 23.130 31.980 26.240 1.00 0.00 +ATOM 6548 HW1 SOL 2105 24.070 32.170 26.230 1.00 0.00 +ATOM 6549 HW2 SOL 2105 22.960 31.570 25.390 1.00 0.00 +ATOM 6550 OW SOL 2106 7.930 40.390 9.570 1.00 0.00 +ATOM 6551 HW1 SOL 2106 8.490 40.320 8.790 1.00 0.00 +ATOM 6552 HW2 SOL 2106 7.990 39.520 9.980 1.00 0.00 +ATOM 6553 OW SOL 2107 23.870 18.450 6.200 1.00 0.00 +ATOM 6554 HW1 SOL 2107 23.220 17.780 6.020 1.00 0.00 +ATOM 6555 HW2 SOL 2107 24.370 18.100 6.940 1.00 0.00 +ATOM 6556 OW SOL 2108 37.790 9.120 28.180 1.00 0.00 +ATOM 6557 HW1 SOL 2108 37.840 9.420 29.080 1.00 0.00 +ATOM 6558 HW2 SOL 2108 36.860 9.100 27.980 1.00 0.00 +ATOM 6559 OW SOL 2109 42.390 4.100 7.330 1.00 0.00 +ATOM 6560 HW1 SOL 2109 41.710 4.770 7.370 1.00 0.00 +ATOM 6561 HW2 SOL 2109 42.650 4.080 6.410 1.00 0.00 +ATOM 6562 OW SOL 2110 16.420 24.040 23.330 1.00 0.00 +ATOM 6563 HW1 SOL 2110 15.940 24.840 23.530 1.00 0.00 +ATOM 6564 HW2 SOL 2110 16.520 23.610 24.180 1.00 0.00 +ATOM 6565 OW SOL 2111 20.520 44.140 6.290 1.00 0.00 +ATOM 6566 HW1 SOL 2111 19.920 44.450 6.970 1.00 0.00 +ATOM 6567 HW2 SOL 2111 21.370 44.460 6.560 1.00 0.00 +ATOM 6568 OW SOL 2112 12.710 44.620 4.540 1.00 0.00 +ATOM 6569 HW1 SOL 2112 11.840 44.250 4.440 1.00 0.00 +ATOM 6570 HW2 SOL 2112 13.280 43.870 4.700 1.00 0.00 +ATOM 6571 OW SOL 2113 37.270 8.070 23.700 1.00 0.00 +ATOM 6572 HW1 SOL 2113 37.260 9.010 23.860 1.00 0.00 +ATOM 6573 HW2 SOL 2113 37.240 7.680 24.570 1.00 0.00 +ATOM 6574 OW SOL 2114 43.420 35.420 14.020 1.00 0.00 +ATOM 6575 HW1 SOL 2114 43.020 36.100 13.470 1.00 0.00 +ATOM 6576 HW2 SOL 2114 44.210 35.830 14.370 1.00 0.00 +ATOM 6577 OW SOL 2115 46.467 39.720 0.150 1.00 0.00 +ATOM 6578 HW1 SOL 2115 45.857 39.080 -0.230 1.00 0.00 +ATOM 6579 HW2 SOL 2115 46.537 39.470 1.070 1.00 0.00 +ATOM 6580 MG MG 2116 44.850 33.320 25.610 1.00 0.00 +TER +ENDMDL diff --git a/user-doc/tutorials/trieste-1/traj-broken.xtc b/user-doc/tutorials/trieste-1/traj-broken.xtc new file mode 100644 index 0000000000000000000000000000000000000000..79cd51ae665d526767a467dd4b816a907c2875a9 GIT binary patch literal 117620 zcmV)CK*GNO00+we02#CZ000000000$krXEY00000000000000$krXEY0000$5fnT? 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 z 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 z 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 literal 0 HcmV?d00001 diff --git a/user-doc/tutorials/trieste-1/traj-whole.xtc b/user-doc/tutorials/trieste-1/traj-whole.xtc new file mode 100644 index 0000000000000000000000000000000000000000..2e5f5db59243209406a82c6a56260763c6a07ca5 GIT binary patch literal 116036 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 literal 0 HcmV?d00001 From bc8c5aaa4a930e113beb52311bfbdcf00f102464 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Tue, 2 May 2017 12:23:25 +0200 Subject: [PATCH 43/62] Reformatted examples [makedoc] I used the same convention as in tutorial 1: - plumedfile for plumed input - verbatim with ">" for shell commands - verbatim with "gnuplot>" for gnuplot commands In addition, I used code{.py} to color python syntax @gtribello just revert if you think there is some problem --- user-doc/tutorials/a-trieste-2.txt | 94 +++++++++++++++--------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/user-doc/tutorials/a-trieste-2.txt b/user-doc/tutorials/a-trieste-2.txt index 7173b95d05..1e95624453 100644 --- a/user-doc/tutorials/a-trieste-2.txt +++ b/user-doc/tutorials/a-trieste-2.txt @@ -87,18 +87,18 @@ As discussed in the introduction we are going to be using model data in this exe using PLUMED. The following short python script will generate 10000 (pseudo) random variables between 0 and 1 from a uniform disribution in a format that PLUMED can understand: -\verbatim +\code{.py} import random print("#! FIELDS time rand") for i in range(0,10001): print(i, random.uniform(0,1) ) -\endverbatim +\endcode Copy the contents of the box above to a plain text file called generate_data.py, save the file and then execute the script within it by running: \verbatim -python generate_data.py > mydata +> python generate_data.py > mydata \endverbatim This will generate a file called mydata that contains 10001 uniform random variables. PLUMED will ignore the first number in the colvar file as it assumes @@ -106,7 +106,7 @@ this is the initial configuration you provided for the trajectory. The sample m using gnuplot and the command: \verbatim -p 'mydata' u 1:2 w p +gnuplot> p 'mydata' u 1:2 w p \endverbatim The probability distribution that we generated these random variables is considerably simpler than the probability distribution that we would typically @@ -124,18 +124,18 @@ These are: Lets now try estimating these quantieis by calculating \f$\frac{S_n}{n}\f$ from the points we generated and exploting the central limit theorem. We can do this calculation by writing a PLUMED input file that reads: -\verbatim +\plumedfile data: READ FILE=mydata VALUES=rand d2: MATHEVAL ARG=data VAR=a FUNC=a*a PERIODIC=NO av: AVERAGE ARG=data STRIDE=1 av2: AVERAGE ARG=d2 STRIDE=1 PRINT ARG=av,av2 STRIDE=10000 FILE=colvar -\endverbatim +\endplumedfile If you copy this input to a file called plumed.dat you can then run the calculation by executing: \verbatim -plumed driver --noatoms +> plumed driver --noatoms \endverbatim When the calculation is finished you should have a file called colvar that contains the estimate of the ensemble averages \f$\langle X \rangle\f$ and \f$\langle X^2 \rangle\f$. @@ -162,22 +162,22 @@ for our random variable. The theory behind what we do here is explained in this To do such a calculation with PLUMED on the random variables we generated from the uniform distribution in the previous section we would use an input like the one below: -\verbatim +\plumedfile data: READ FILE=mydata VALUES=rand hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE DUMPGRID GRID=hh FILE=myhist.dat -\endverbatim +\endplumedfile Once again you can run this calculation by using the command: \verbatim -plumed driver --noatoms +> plumed driver --noatoms \endverbatim Once this calculation is completed you can then plot the output using gnuplot and the command: \verbatim -p 'myhist.dat' u 1:2 w l +gnuplot> p 'myhist.dat' u 1:2 w l \endverbatim In the previous section we compared the estimates we got for the ensemble average with the exact analytical values, which we could determine @@ -213,16 +213,16 @@ various parts of the trajectory are all consistent. We can perform a block averaging on the data we generated at the start of the first exercise above by using PLUMED and the input file below: -\verbatim +\plumedfile data: READ FILE=mydata VALUES=rand av: AVERAGE ARG=data STRIDE=1 CLEAR=1000 PRINT ARG=av STRIDE=1000 FILE=colvar -\endverbatim +\endplumedfile Once again this calculation can be executed by running the command: \verbatim -plumed driver --noatoms +> plumed driver --noatoms \endverbatim The key differences between this input and the ones that we have seen previously is the CLEAR keyword on the line AVERAGE. The intruction CLEAR=1000 tells PLUMED @@ -232,7 +232,7 @@ on step 1000 and the accumulated data is immediately cleared after printing so t that were output from the calculation above by using gnuplot and the following command: \verbatim -p 'colvar' u 1:2:3 w e +gnuplot> p 'colvar' u 1:2:3 w e \endverbatim If you try this now you should see that all the average values that were calculated are relatively consistent but that there are differences between them. Try to @@ -242,11 +242,11 @@ you exptracted using PLUMED lie within this range? Is this behavior inline with We can also perform block averaging when we estimate histograms using PLUMED. The following input will calculate these block averaged histograms for the data we generated at the start of this exercise using PLUMED. -\verbatim +\plumedfile data: READ FILE=mydata VALUES=rand hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE CLEAR=1000 DUMPGRID GRID=hh FILE=myhist.dat STRIDE=1000 -\endverbatim +\endplumedfile Notice that the input here has the same structure as the input for the \ref AVERAGE. Once again we have a CLEAR=1000 keyword that tells PLUMED that the data that has been accumulated for calculating the histogram should be deleted every 1000 steps. In addition, we can set a STRIDE for \ref DUMPGRID and thus output the histogram from each of @@ -267,7 +267,7 @@ output files. In particular, the input above should give you 10 output files wh We can plot all of these histograms using gnuplot and the command: \verbatim -p 'analysis.0.myhist.dat' u 1:2:3 w e, 'analysis.1.myhist.dat' u 1:2:3 w e, 'analysis.2.myhist.dat' u 1:2:3 w e, 'analysis.3.myhist.dat' u 1:2:3 w e, 'analysis.4.myhist.dat' u 1:2:3 w e, 'analysis.5.myhist.dat' u 1:2:3 w e, 'analysis.6.myhist.dat' u 1:2:3 w e, 'analysis.7.myhist.dat' u 1:2:3 w e, 'analysis.8.myhist.dat' u 1:2:3 w e, 'myhist.dat' u 1:2:3 w e +gnuplot> p 'analysis.0.myhist.dat' u 1:2:3 w e, 'analysis.1.myhist.dat' u 1:2:3 w e, 'analysis.2.myhist.dat' u 1:2:3 w e, 'analysis.3.myhist.dat' u 1:2:3 w e, 'analysis.4.myhist.dat' u 1:2:3 w e, 'analysis.5.myhist.dat' u 1:2:3 w e, 'analysis.6.myhist.dat' u 1:2:3 w e, 'analysis.7.myhist.dat' u 1:2:3 w e, 'analysis.8.myhist.dat' u 1:2:3 w e, 'myhist.dat' u 1:2:3 w e \endverbatim Performing a comparison between the results from each of these blocks of data is more involved than the analysis we performed when comparing the ensemble averages as we have @@ -299,7 +299,7 @@ they don't fall in a range between 0 and 1 they are discarded: P(x) = \frac{1}{\sqrt{2\pi}\sigma} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) \f] -\verbatim +\code{.py} import random n = 0 @@ -310,12 +310,12 @@ while True : print(n, x ) n = n + 1 if n==10001 : break -\endverbatim +\endcode Copy the script above to a file called gen-normal.py and then execute the python script within it using the command: \verbatim -python gen-normal.py > mynormal +> python gen-normal.py > mynormal \endverbatim @@ -361,37 +361,37 @@ uniform distribution. The trick here is calculate the following weighted mean r where here the sums run over all the random variables, the \f$Y_i\f$s, that we sampled from the Gaussian distribution. If you used the script above the \f$V(Y_i)\f$ values were output for you so you can calculate this estimate of the ensemble average for the unbiased distribution in this case using the following PLUMED input. -\verbatim +\plumedfile UNITS NATURAL # This ensures that Boltzmann's constant is one data: READ FILE=mynormal VALUES=rand mm: RESTRAINT ARG=data AT=0.6 KAPPA=33.333 rw: REWEIGHT_BIAS TEMP=1 av: AVERAGE ARG=data STRIDE=1 LOGWEIGHTS=rw PRINT ARG=av STRIDE=10000 FILE=colvar -\endverbatim +\endplumedfile Try to run this calculation now using: \verbatim -plumed driver --noatoms +> plumed driver --noatoms \endverbatim and see how close you get to the ensemble average for the uniform distribution. Once you have done this try the following input, which allows you to compute the reweighted histogram. -\verbatim +\plumedfile UNITS NATURAL # This ensures that Boltzmann's constant is one data: READ FILE=mynormal VALUES=rand mm: RESTRAINT ARG=data AT=0.6 KAPPA=33.333 rw: REWEIGHT_BIAS TEMP=1 hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE LOGWEIGHTS=rw DUMPGRID GRID=hh FILE=myhist.dat -\endverbatim +\endplumedfile Plot the histogram that you obtain from this calculation using the command: \verbatim -p 'myhist.dat' w l +gnuplot> p 'myhist.dat' w l \endverbatim @@ -410,7 +410,7 @@ from one edge of CV space to the other during a single timestep. In other words will be similar to the value obtained from the \f$i\f$th trajectory frame. This problem can be resolved, however, and to show how we will thus use the following python script to generate some correlated model data: -\verbatim +\code{.py} import random prev = 0.; @@ -419,12 +419,12 @@ for i in range(0,10001): new = 0.95*prev + 2*random.uniform(0,1) - 1 print( i, new/2. + 0.5 ) prev = new -\endverbatim +\endcode Copy the python script above to a filled called correlated-data.py and then execute the script using the command: \verbatim -python correlated-data.py > mycorr +> python correlated-data.py > mycorr \endverbatim The autocorrelation function, \f$R(\tau)\f$ provides a simple method for determining whether or not there are correlations between the random variables, \f$X\f$, @@ -451,7 +451,7 @@ We account for the correlations in the data when we do our analysis by performin the analysis with PLUMED and explain the results that we get at each stage of the process. We wil begin by analysing the data we generated by sampling from the uniform distribution using the following PLUMED input: -\verbatim +\plumedfile data: READ FILE=mydata VALUES=rand av5: AVERAGE ARG=data STRIDE=1 CLEAR=5 PRINT ARG=av5 FILE=colvar5 STRIDE=5 @@ -481,17 +481,17 @@ av65: AVERAGE ARG=data STRIDE=1 CLEAR=65 PRINT ARG=av65 FILE=colvar65 STRIDE=65 av70: AVERAGE ARG=data STRIDE=1 CLEAR=70 PRINT ARG=av70 FILE=colvar70 STRIDE=70 -\endverbatim +\endplumedfile Copy the input above to a file called plumed.dat and run the calculation using the command: \verbatim -plumed driver --noatoms +> plumed driver --noatoms \endverbatim This calculation should output 14 colvar files, which should then be further analysed using the following python script: -\verbatim +\code{.py} import numpy as np import math @@ -513,18 +513,18 @@ for i in range(1,15): # root of the sample variance divided by the number of data points that this estimate was # calcualted from. This last term is a measure of the eror bar print( fmult, mean, math.sqrt( sample_variance / len(sq) ) ) -\endverbatim +\endcode Copy this script to a file called block-average-script.py and then execute the contents using the command: \verbatim -python block-average-script.py > myaverages.dat +> python block-average-script.py > myaverages.dat \endverbatim This will output a single file called myaverages.dat that can be plotted using gnuplot and the command: \verbatim -p 'myaverages.dat' u 1:2:3 w e, 'myaverages.dat' w l +gnuplot> p 'myaverages.dat' u 1:2:3 w e, 'myaverages.dat' w l \endverbatim The final result should be a graph like that shown in the left panel of the figure below. The figure on the right shows what you should obtain when you repeat the same @@ -550,7 +550,7 @@ Instead we are going to reweight using the ideas from \ref trieste-2-biases and The first step in doing all this is, as always, to generate some data. The python script below will generate this data: -\verbatim +\code{.py} import math import random @@ -576,12 +576,12 @@ for i in range(0,100010): elif( random.uniform(0,1) mcdata +> python do-monte-carlo.py > mcdata \endverbatim This will run a short Monte Carlo simulation that generates (time-correlated) random data from a (roughly) Gaussian distribution by attempting @@ -594,27 +594,27 @@ the adjacent data points in the time series and that we have to do block averagi We can use the following PLUMED input to calculate block averages for the unbiased histogram from the data we generated: -\verbatim +\plumedfile UNITS NATURAL # This ensures that Boltzmann's constant is one data: READ FILE=mcdata VALUES=rand mm: READ FILE=mcdata VALUES=cv.* rw: REWEIGHT_BIAS TEMP=1 hh: HISTOGRAM ARG=data STRIDE=1 GRID_MIN=0 GRID_MAX=1.0 GRID_BIN=20 KERNEL=DISCRETE LOGWEIGHTS=rw CLEAR=500 DUMPGRID GRID=hh FILE=myhist.dat STRIDE=500 -\endverbatim +\endplumedfile Notice that this input instructs PLUMED to calculate block averages for the histogram from each set of 500 consecutive frames in the trajectory. I have worked out that this is an appropriate length of time to average over by performing the analysis described in \ref triete-2-correlation. We will come back to how precisely I did this momentarily, however. For the time being though you can execute this input using: \verbatim -plumed driver --noatoms +> plumed driver --noatoms \endverbatim Executing this command will generate a number of files containing histograms. The following python script will merge all this data and calculate the final histogram together with the appropriate error bars. -\verbatim +\code{.py} import math import glob import numpy as np @@ -683,18 +683,18 @@ for i in range(0,len(griddata[:,0])) : for j in range(0,grid_dimension) : print( griddata[i,j], end=" " ) for j in range(0,nquantities) : print( average[j,i], errors[j,i], end=" " ) print() -\endverbatim +\endcode Copy this script to a file called merge-histograms.py and then run its contents by executing the command: \verbatim -python merge-histograms.py > final-histogram.dat +> python merge-histograms.py > final-histogram.dat \endverbatim This will output the final average histogram together with some error bars. You can plot this function using gnuplot by executing the command: \verbatim -p 'final-histogram.dat' u 1:2:3 w e, '' u 1:2 w l +gnuplot> p 'final-histogram.dat' u 1:2:3 w e, '' u 1:2 w l \endverbatim From 774fc9892d8ae2513434d8b713de9111a50b7709 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Tue, 2 May 2017 23:16:56 +0100 Subject: [PATCH 44/62] Added some links to appropriate material in trieste-2 tutorial --- user-doc/tutorials/a-trieste-2.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/user-doc/tutorials/a-trieste-2.txt b/user-doc/tutorials/a-trieste-2.txt index 1e95624453..9b5aa758d9 100644 --- a/user-doc/tutorials/a-trieste-2.txt +++ b/user-doc/tutorials/a-trieste-2.txt @@ -77,7 +77,11 @@ This observation is important as it ensures that the probability that \f$\frac{S distribution, \f$\langle Y\rangle\f$, increases as we increase the value of \f$n\f$. The central limit theorem therefore allows us to get an estimate for the ensemble average for a particular quantity \f$Y\f$ by taking repeated samples of \f$Y\f$ from our distribution. These samples can be taken by, for example, performing a molecular dynamics simulation. Furthermore, and as we will see in the exercises that follow, we can also get an estimate of how much we might expect the -system to fluctuate about this average. +system to fluctuate about this average. Incidentally, if you are confused at this stage you might want to work through these two videos and exercises in order to get a +better understanding of the central limit theorem, confidence limits and error bars: + +- Error bars exercise: http://gtribello.github.io/mathNET/error_bar_video.html +- Confidence limits exercise: http://gtribello.github.io/mathNET/central-limit-theorem-video.html \section trieste-2-instructions Instructions @@ -534,7 +538,7 @@ analysis on the correlated data that we generated using the python script in thi \image html trieste-2-block-averages.png "The ensemble average and an estimate of the associated error bars calculated for different lengths of block average. The left panel shows the output obtained when the uncorrelated samples taken from uniform distribution are analysed in this way. The right panel shows the output obtained when the correlated samples that are generated using the python script in this section are analysed." -The output that you obtain from these two calculations is explained in the video at: +The output that you obtain from these two calculations is explained in the video at: http://gtribello.github.io/mathNET/block_averaging_video.html Before wathcing this explanation though take some time to note down the differences between the two graphs above. Try to look through the scripts above and to understand what is being done in the PLUMED inputs and the python scripts above so as to work out what the data in these two figures are telling you. From 85f16db464754dc03b878b1e4a2bc56e9f0aff2e Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Wed, 3 May 2017 14:52:31 +0200 Subject: [PATCH 45/62] Small improvements in doc --- src/generic/FitToTemplate.cpp | 55 +++++++++++++++++++++++++++++++++-- src/generic/Group.cpp | 11 +++---- src/generic/Print.cpp | 21 +++++++++++-- 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/generic/FitToTemplate.cpp b/src/generic/FitToTemplate.cpp index d4bec95019..8ff513715d 100644 --- a/src/generic/FitToTemplate.cpp +++ b/src/generic/FitToTemplate.cpp @@ -63,6 +63,7 @@ change the result. Examples are: - \ref DISTANCE CV with COMPONENTS. Since the alignment could involve a rotation (with TYPE=OPTIMAL) the actual components could be different from the original ones. - \ref CELL components for a similar reason. +- \ref DISTANCE from a \ref FIXEDATOM, provided the fixed atom is introduced _after_ the \ref FIT_TO_TEMPLATE action. \attention The implementation of TYPE=OPTIMAL is available but should be considered in testing phase. Please report any @@ -78,15 +79,65 @@ this action is performed at every MD step. \par Examples -Align the atomic position to a template then print them +Align the atomic position to a template then print them. +The following example is only translating the system so as +to align the center of mass of a molecule to the one in the reference +structure `ref.pdb`: \plumedfile -# to see the effect, one could dump the atoms before alignment +# dump coordinates before fitting, to see the difference: DUMPATOMS FILE=dump-before.xyz ATOMS=1-20 + +# fit coordinates to ref.pdb template +# this is a "TYPE=SIMPLE" fit, so that only translations are used. FIT_TO_TEMPLATE STRIDE=1 REFERENCE=ref.pdb TYPE=SIMPLE + +# dump coordinates after fitting, to see the difference: DUMPATOMS FILE=dump-after.xyz ATOMS=1-20 \endplumedfile +The following example instead performs a rototranslational fit. +\plumedfile +# dump coordinates before fitting, to see the difference: +DUMPATOMS FILE=dump-before.xyz ATOMS=1-20 + +# fit coordinates to ref.pdb template +# this is a "TYPE=OPTIMAL" fit, so that rototranslations are used. +FIT_TO_TEMPLATE STRIDE=1 REFERENCE=ref.pdb TYPE=OPTIMAL + +# dump coordinates after fitting, to see the difference: +DUMPATOMS FILE=dump-after.xyz ATOMS=1-20 +\endplumedfile + +In the following example you see two completely equivalent way +to restrain an atom close to a position that is defined in the reference +frame of an aligned molecule. It could be for instance the center of mass +of a ligand with respect to a protein +\plumedfile +# center of the ligand: +ce: CENTER ATOMS=100-110 + +FIT_TO_TEMPLATE REFERENCE=protein.pdb TYPE=OPTIMAL + +# place a fixed atom in the protein reference coordinates: +fix: FIXEDATOM AT=1.0,1.1,1.0 + +# take the distance between the fixed atom and the center of the ligand +d: DISTANCE ATOMS=ce,fix + +# apply a restraint +RESTRAINT ARG=d AT=0.0 KAPPA=100.0 +\endplumedfile +Notice that you could have obtained an (almost) identical result adding a fictitious +atom to `ref.pdb` with the serial number corresponding to the `ce` atom (there is no automatic way +to get it, but in this example it should be the number of atoms of the system plus one), +and properly setting the weights for alignment and displacement in \ref RMSD. +There are two differences to be expected: +(ab) \ref FIT_TO_TEMPLATE might be slower since it has to rototranslate all the available atoms and +(b) variables employing PBCs (such as \ref DISTANCE without `NOPBC`, as in the example above) + are allowed after \ref FIT_TO_TEMPLATE, whereas \ref RMSD expects PBCs to be already solved. +The latter means that before the \ref RMSD statement one should use \ref WRAPAROUND or \ref WHOLEMOLECULES to properly place +the ligand. */ diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index 234a01c282..e8c953cbe0 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -48,12 +48,13 @@ the index file and `NDX_GROUP` to set the name of the group to be imported (defa It is also possible to remove atoms from a list and or sort them using keywords `REMOVE`, `SORT`, and `UNIQUE`. The flow is the following: -- If `ATOMS` is present take the ordered list of atoms from the `ATOMS` keyword. -- If `NDX_FILE` is present append the list from the the gromacs group. -- If `REMOVE` is present remove the first occurence of each of these atoms from the list. +- If `ATOMS` is present, then take the ordered list of atoms from the `ATOMS` keyword as a starting list. +- If `NDX_FILE` is present, then append to it the list obtained from the gromacs group. +- If `REMOVE` is present, then remove the first occurence of each of these atoms from the list. If one tries to remove an atom that was not listed plumed adds a notice in the output. -- If `SORT` is present resulting list is sorted. -- If `UNIQUE` is present the resuling list is sorted and duplicate elements are removed. + An atom that is present twice in the original list might be removed twice. +- If `SORT` is present, then the resulting list is sorted by increasing serial number. +- If `UNIQUE` is present, then the resuling list is sorted by increasing serial number _and_ duplicate elements are removed. Notice that this command just creates a shortcut, and does not imply any real calculation. So, having a huge group defined does not slow down your calculation in any way. diff --git a/src/generic/Print.cpp b/src/generic/Print.cpp index 74245cf99a..0fb11e02e3 100644 --- a/src/generic/Print.cpp +++ b/src/generic/Print.cpp @@ -35,18 +35,35 @@ Print quantities to a file. This directive can be used multiple times in the input so you can print files with different strides or print different quantities to different files. You can control the buffering of output using the \subpage FLUSH keyword. +Output file is either appended or backed up depending on the presence of the \ref RESTART action. +A per-action `RESTART` keyword can be used as well. + +Notice that printing happens in the so-called "update" phase. This implies that printing +is affected by the presence of \ref UPDATE_IF actions. In addition, one might decide to start +and stop printing at preassigned values of time using the `UPDATE_FROM` and `UPDATE_UNTIL` keywords. +Keep into account that even on steps when the action is not updated (and thus the file is not printed) +the argument will be activated. In other words, if you use `UPDATE_FROM` to start printing at a given time, +the collective variables this PRINT statement depends on will be computed also before that time. \par Examples + The following input instructs plumed to print the distance between atoms 3 and 5 on a file called COLVAR every 10 steps, and the distance and total energy on a file called COLVAR_ALL every 1000 steps. \plumedfile -DISTANCE ATOMS=2,5 LABEL=distance -ENERGY LABEL=energy +# compute distance: +distance: DISTANCE ATOMS=2,5 +# compute total energy (potential) +energy: ENERGY +# print distance on a file PRINT ARG=distance STRIDE=10 FILE=COLVAR +# print both variables on another file PRINT ARG=distance,energy STRIDE=1000 FILE=COLVAR_ALL \endplumedfile +Notice that \ref DISTANCE and \ref ENERGY are computed respectively every 10 and 1000 steps, that is +only when required. + */ //+ENDPLUMEDOC From 987c7838f792eebff59340838633d5bb63932c44 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Tue, 2 May 2017 22:04:07 +0200 Subject: [PATCH 46/62] Improved trieste-1 [makedoc] --- user-doc/tutorials/a-trieste-1.txt | 38 +++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/user-doc/tutorials/a-trieste-1.txt b/user-doc/tutorials/a-trieste-1.txt index db7454ac05..5622cad76a 100644 --- a/user-doc/tutorials/a-trieste-1.txt +++ b/user-doc/tutorials/a-trieste-1.txt @@ -27,6 +27,9 @@ The \tarball{trieste-1} for this project contains the following files: - traj-whole.xtc: A trajectory for the same system in GROMACS xtc format. To make the exercise easier, RNA duplex has been made whole already. - traj-broken.xtc: The same trajectory as it was originally produced by GROMACS. Here the RNA duplex is broken and should be fixed. +This tutorial has been tested on a pre-release version of version 2.4. However, it should not take advantage +of 2.4-only features, thus should also work with version 2.3. + \section trieste-1-intro Introduction This tutorial asks you to compute a variety of different collective variables using PLUMED for a particular trajectory and to compare the files and graphs that you obtain with the correct ones that are shown online. Compared to some of the other tutorials that are available here this tutorial contains considerably less guidance so in doing this tutorial you will have to @@ -134,7 +137,7 @@ To analyze the trajectory provided here, you should: - Run the command `plumed driver --mf_xtc traj.xtc --plumed plumed.dat`. Here `traj.xtc` is the trajectory that you want to analyze. Notice that \ref driver -can read multpliple file formats using embedded molfile plugins from VMD (that's where the `mf` letters come from). +can read multiple file formats using embedded molfile plugins from VMD (that's where the `mf` letters come from). Notice that you can also visualize trajectories with VMD directly. Trajectory `traj.xtc` can be visualized with the command `vmd ref.pdb traj-whole.xtc`. @@ -166,6 +169,8 @@ Whenever you see an highlighted \highlight{FILL} string, this is a string that y \plumedfile # First load information about the molecule. MOLINFO __FILL__ +# Notice that this is special kind of "action" ("setup action") +# that is only used during setup. It will not be re-executed at each step. # Define some group that will make the rest of the input more readable # Here are the atoms belonging to RNA. @@ -220,7 +225,7 @@ The command above will create a file `COLVAR` like this one: \endverbatim Notice that the first line informs you about the content of each column and the second and third lines tell you that variable `c` (the \f$\chi\f$ torsion) is -defined between \f$-pi\f$ and \f$+pi\f$. +defined between \f$-\pi\f$ and \f$+\pi\f$. __In case you obtain different numbers, check your input, you might have made some mistake!__ @@ -273,10 +278,12 @@ Notice for many functions you should say to PLUMED if the function is periodic. See \ref Function for a detailed explanation of how to choose this keyword. You might think that it is easier to combine the variables after you have written them -already, using e.g. and awk or python script. That's fine if you are analyzing a trajectory. +already, using, e.g., an awk or python script. That's fine if you are analyzing a trajectory. However, as we will learn later, computing variables within PLUMED you will be able to add bias potentials on those combinations, influencing their dynamics. Actually, you could implement any arbitrarily complex collective variable using just \ref DISTANCE and \ref MATHEVAL! +Anyway, if the CV combinations that you are willing to use can be computed easily with some +external program, do it and compare the results with the output of the PLUMED driver. \subsection trieste-1-ex-1b Exercize 1b: Combining collective variables @@ -286,7 +293,7 @@ As an optional exercize, create a file with the following quantities: Notice that the serial numbers of the phosphorous atoms can be easily extracted using the following command \verbatim -grep ATOM ref.pdb | grep " P " | awk '{print $2}' +> grep ATOM ref.pdb | grep " P " | awk '{print $2}' \endverbatim Here's a template input file to be completed by you. @@ -311,10 +318,10 @@ s: SORT __FILL__ # Print the required variables PRINT FILE=COLVAR __FILL__ - \endplumedfile Notice that using the collective variable \ref DISTANCES you might be able to do the same with a significantly simpler input file! +If you have time, also try that and compare the result. The resulting `COLVAR` file should look like this one: @@ -356,7 +363,8 @@ could require the molecules to be whole (an example of such variables is \ref RM You might think that there are alternative programs that can be used to reconstruct PBCs correctly in your trajectory *before* analyzing it. However, you should keep in mind that if you need to compute CVs on the fly to add a bias potential on those (as we will to in the next tutorials) you will -have to learn how to reconstruct PBCs within PLUMED. +have to learn how to reconstruct PBCs within PLUMED. If you know alternative tools that can reconstruct PBCs, +it is a good idea to also use them and compare the result with PLUMED. \subsection trieste-1-ex-2 Exercise 2: Solving PBC issues and dump atomic coordinates @@ -546,6 +554,24 @@ force your molecule to a specific orientation. \endhidden +\subsection trieste-1-conclusions Conclusions + +In summary, in this tutorial you should have learned how to use PLUMED to: +- Manipulate atomic coordinates. +- Compute collective variables. + +All of this was done by just reading an already available trajectory. +Notice that there are many alternative tools that could have been used to do the same exercize. +Indeed, if you are familiar with other tools, it might be a good idea to also try them and compare the results. +The special things of working with PLUMED are the following: +- PLUMED implements a vast library of useful collective variables. + Browse the manual and search for ideas that are suitable for your system. +- PLUMED has a simple and intuitive syntax to combine collective variables ending up in descriptors capable to + characterize complex conformational changes. +- And finally, the most special thing: any collective variable that can be computed within PLUMED can also + be biased while you are running your MD simulation! You will learn more later about this topic. + +The last point is probably the main reason why PLUMED exists and what distinguishes it from other available software. */ From 8578bcc25f3cd735a8c533a13538802f982f76e6 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Wed, 3 May 2017 14:04:12 -0400 Subject: [PATCH 47/62] Coordination Number R_POWER flag (#230) * Added R_POWER option to multicolvar/CoordinationNumber This is to allow the coordination number moments from White and Voth 2014 JCTC and subsequent papers. They are used as a scalar proxy for biasing radial distribution. Regtest and CHANGES line have been added as well as the function/documentation. --- CHANGES/v2.4.txt | 1 + .../rt-coordination-powers-multi/Makefile | 1 + .../cn_out.reference | 6 + .../rt-coordination-powers-multi/config | 4 + .../rt-coordination-powers-multi/plumed.dat | 5 + .../rt-coordination-powers/Makefile | 1 + .../multicolvar/rt-coordination-powers/config | 4 + .../derivatives.reference | 196 ++++++++++++++++++ .../rt-coordination-powers/plumed.dat | 3 + src/multicolvar/CoordinationNumbers.cpp | 64 +++++- 10 files changed, 274 insertions(+), 11 deletions(-) create mode 100644 regtest/multicolvar/rt-coordination-powers-multi/Makefile create mode 100644 regtest/multicolvar/rt-coordination-powers-multi/cn_out.reference create mode 100644 regtest/multicolvar/rt-coordination-powers-multi/config create mode 100644 regtest/multicolvar/rt-coordination-powers-multi/plumed.dat create mode 100644 regtest/multicolvar/rt-coordination-powers/Makefile create mode 100644 regtest/multicolvar/rt-coordination-powers/config create mode 100644 regtest/multicolvar/rt-coordination-powers/derivatives.reference create mode 100644 regtest/multicolvar/rt-coordination-powers/plumed.dat diff --git a/CHANGES/v2.4.txt b/CHANGES/v2.4.txt index 3a2f658fac..43b058aaa4 100644 --- a/CHANGES/v2.4.txt +++ b/CHANGES/v2.4.txt @@ -34,6 +34,7 @@ Changes from version 2.3 which are relevant for users: trajectory with replica suffix is not found the driver will look for a trajectory without the replica suffix. - Internal molfile implementation has been updated to VMD 1.9.3. - Examples in the documentation now have syntax highlighting and links to the documentation of used actions. + - \ref COORDINATIONNUMBER : Added option to have pairwise distance moments of coordination number in the multicolvar module Changes from version 2.3 which are relevant for developers: - A few fixes has been made to improve exception safety. Although we still cannot declare diff --git a/regtest/multicolvar/rt-coordination-powers-multi/Makefile b/regtest/multicolvar/rt-coordination-powers-multi/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers-multi/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/multicolvar/rt-coordination-powers-multi/cn_out.reference b/regtest/multicolvar/rt-coordination-powers-multi/cn_out.reference new file mode 100644 index 0000000000..fbebd72b92 --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers-multi/cn_out.reference @@ -0,0 +1,6 @@ +#! FIELDS time cn0.mean cn1.mean cn2.mean + 0.000000 1.171228 1.453038 1.843475 + 0.005000 1.166065 1.441594 1.826868 + 0.010000 1.172897 1.440122 1.816671 + 0.015000 1.158162 1.412160 1.776137 + 0.020000 1.105913 1.356438 1.719031 diff --git a/regtest/multicolvar/rt-coordination-powers-multi/config b/regtest/multicolvar/rt-coordination-powers-multi/config new file mode 100644 index 0000000000..ba8b778571 --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers-multi/config @@ -0,0 +1,4 @@ +type=driver +# this is to test a different name +arg="--plumed plumed.dat --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +extra_files="../../trajectories/trajectory.xyz" diff --git a/regtest/multicolvar/rt-coordination-powers-multi/plumed.dat b/regtest/multicolvar/rt-coordination-powers-multi/plumed.dat new file mode 100644 index 0000000000..e7c2dcce2f --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers-multi/plumed.dat @@ -0,0 +1,5 @@ +cn0: COORDINATIONNUMBER SPECIES=1-10 SWITCH={RATIONAL R_0=1.0 D_MAX=8} MEAN +cn1: COORDINATIONNUMBER SPECIES=1-10 SWITCH={RATIONAL R_0=1.0 D_MAX=8} R_POWER=1 MEAN +cn2: COORDINATIONNUMBER SPECIES=1-10 SWITCH={RATIONAL R_0=1.0 D_MAX=8} R_POWER=2 MEAN +PRINT ARG=cn0.mean,cn1.mean,cn2.mean STRIDE=1 FILE=cn_out + diff --git a/regtest/multicolvar/rt-coordination-powers/Makefile b/regtest/multicolvar/rt-coordination-powers/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/multicolvar/rt-coordination-powers/config b/regtest/multicolvar/rt-coordination-powers/config new file mode 100644 index 0000000000..ba8b778571 --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers/config @@ -0,0 +1,4 @@ +type=driver +# this is to test a different name +arg="--plumed plumed.dat --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +extra_files="../../trajectories/trajectory.xyz" diff --git a/regtest/multicolvar/rt-coordination-powers/derivatives.reference b/regtest/multicolvar/rt-coordination-powers/derivatives.reference new file mode 100644 index 0000000000..d6fa5fe2f4 --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers/derivatives.reference @@ -0,0 +1,196 @@ +#! FIELDS time parameter c1.mean c1num.mean + 0.000000 0 0.3371 0.3371 + 0.000000 1 0.2309 0.2309 + 0.000000 2 0.1160 0.1160 + 0.000000 3 -0.3510 -0.3510 + 0.000000 4 0.3400 0.3399 + 0.000000 5 0.0247 0.0247 + 0.000000 6 -0.2278 -0.2278 + 0.000000 7 -0.3331 -0.3331 + 0.000000 8 0.1717 0.1717 + 0.000000 9 0.3075 0.3075 + 0.000000 10 -0.3590 -0.3590 + 0.000000 11 0.0586 0.0586 + 0.000000 12 0.3427 0.3427 + 0.000000 13 0.3101 0.3101 + 0.000000 14 -0.0220 -0.0220 + 0.000000 15 -0.3299 -0.3299 + 0.000000 16 0.2127 0.2127 + 0.000000 17 -0.1563 -0.1563 + 0.000000 18 -0.3289 -0.3289 + 0.000000 19 -0.3329 -0.3329 + 0.000000 20 -0.0762 -0.0762 + 0.000000 21 0.2298 0.2298 + 0.000000 22 -0.3171 -0.3171 + 0.000000 23 -0.1589 -0.1589 + 0.000000 24 0.2379 0.2379 + 0.000000 25 0.1246 0.1246 + 0.000000 26 -0.0916 -0.0916 + 0.000000 27 -0.2175 -0.2175 + 0.000000 28 0.1238 0.1238 + 0.000000 29 0.1338 0.1338 + 0.000000 30 1.2685 1.2685 + 0.000000 31 0.0008 0.0008 + 0.000000 32 -0.0777 -0.0777 + 0.000000 33 0.0008 0.0008 + 0.000000 34 1.1232 1.1232 + 0.000000 35 0.0031 0.0031 + 0.000000 36 -0.0777 -0.0777 + 0.000000 37 0.0031 0.0031 + 0.000000 38 2.5442 2.5442 + 0.005000 0 0.3287 0.3287 + 0.005000 1 0.2323 0.2323 + 0.005000 2 0.1100 0.1100 + 0.005000 3 -0.3587 -0.3587 + 0.005000 4 0.3366 0.3366 + 0.005000 5 0.0181 0.0181 + 0.005000 6 -0.2232 -0.2232 + 0.005000 7 -0.3296 -0.3296 + 0.005000 8 0.1699 0.1699 + 0.005000 9 0.2907 0.2907 + 0.005000 10 -0.3585 -0.3585 + 0.005000 11 0.0690 0.0690 + 0.005000 12 0.3444 0.3444 + 0.005000 13 0.2895 0.2895 + 0.005000 14 -0.0237 -0.0237 + 0.005000 15 -0.3163 -0.3163 + 0.005000 16 0.1948 0.1948 + 0.005000 17 -0.1721 -0.1721 + 0.005000 18 -0.3260 -0.3260 + 0.005000 19 -0.3198 -0.3198 + 0.005000 20 -0.0941 -0.0941 + 0.005000 21 0.2273 0.2273 + 0.005000 22 -0.2878 -0.2878 + 0.005000 23 -0.1523 -0.1523 + 0.005000 24 0.2355 0.2355 + 0.005000 25 0.1149 0.1149 + 0.005000 26 -0.0652 -0.0652 + 0.005000 27 -0.2023 -0.2023 + 0.005000 28 0.1276 0.1276 + 0.005000 29 0.1406 0.1406 + 0.005000 30 1.2982 1.2982 + 0.005000 31 0.0073 0.0073 + 0.005000 32 -0.0442 -0.0442 + 0.005000 33 0.0073 0.0073 + 0.005000 34 1.0615 1.0615 + 0.005000 35 0.0049 0.0049 + 0.005000 36 -0.0442 -0.0442 + 0.005000 37 0.0049 0.0049 + 0.005000 38 2.4945 2.4945 + 0.010000 0 0.3057 0.3057 + 0.010000 1 0.2219 0.2219 + 0.010000 2 0.1122 0.1122 + 0.010000 3 -0.3610 -0.3610 + 0.010000 4 0.3207 0.3207 + 0.010000 5 0.0249 0.0249 + 0.010000 6 -0.2431 -0.2431 + 0.010000 7 -0.3226 -0.3226 + 0.010000 8 0.1861 0.1861 + 0.010000 9 0.3110 0.3110 + 0.010000 10 -0.3230 -0.3230 + 0.010000 11 0.0536 0.0536 + 0.010000 12 0.3321 0.3321 + 0.010000 13 0.2459 0.2459 + 0.010000 14 -0.0204 -0.0204 + 0.010000 15 -0.3035 -0.3035 + 0.010000 16 0.1750 0.1750 + 0.010000 17 -0.1894 -0.1894 + 0.010000 18 -0.3215 -0.3215 + 0.010000 19 -0.3011 -0.3011 + 0.010000 20 -0.0991 -0.0991 + 0.010000 21 0.2342 0.2342 + 0.010000 22 -0.2677 -0.2677 + 0.010000 23 -0.1511 -0.1511 + 0.010000 24 0.2325 0.2325 + 0.010000 25 0.1200 0.1200 + 0.010000 26 -0.0458 -0.0458 + 0.010000 27 -0.1864 -0.1864 + 0.010000 28 0.1309 0.1309 + 0.010000 29 0.1290 0.1290 + 0.010000 30 1.3545 1.3545 + 0.010000 31 -0.0010 -0.0010 + 0.010000 32 -0.0324 -0.0324 + 0.010000 33 -0.0010 -0.0010 + 0.010000 34 0.9468 0.9468 + 0.010000 35 0.0117 0.0117 + 0.010000 36 -0.0324 -0.0324 + 0.010000 37 0.0117 0.0117 + 0.010000 38 2.4481 2.4481 + 0.015000 0 0.2784 0.2784 + 0.015000 1 0.2040 0.2040 + 0.015000 2 0.0908 0.0908 + 0.015000 3 -0.3455 -0.3455 + 0.015000 4 0.2867 0.2867 + 0.015000 5 0.0230 0.0230 + 0.015000 6 -0.2596 -0.2596 + 0.015000 7 -0.3044 -0.3044 + 0.015000 8 0.2036 0.2036 + 0.015000 9 0.3216 0.3216 + 0.015000 10 -0.2752 -0.2752 + 0.015000 11 0.0411 0.0411 + 0.015000 12 0.3142 0.3142 + 0.015000 13 0.1924 0.1924 + 0.015000 14 -0.0163 -0.0163 + 0.015000 15 -0.2939 -0.2939 + 0.015000 16 0.1585 0.1585 + 0.015000 17 -0.2067 -0.2067 + 0.015000 18 -0.3090 -0.3090 + 0.015000 19 -0.2674 -0.2674 + 0.015000 20 -0.0777 -0.0777 + 0.015000 21 0.2317 0.2317 + 0.015000 22 -0.2560 -0.2560 + 0.015000 23 -0.1327 -0.1327 + 0.015000 24 0.2310 0.2310 + 0.015000 25 0.1251 0.1251 + 0.015000 26 -0.0350 -0.0350 + 0.015000 27 -0.1689 -0.1689 + 0.015000 28 0.1362 0.1362 + 0.015000 29 0.1099 0.1099 + 0.015000 30 1.3936 1.3936 + 0.015000 31 -0.0040 -0.0040 + 0.015000 32 -0.0365 -0.0365 + 0.015000 33 -0.0040 -0.0040 + 0.015000 34 0.8269 0.8269 + 0.015000 35 -0.0103 -0.0103 + 0.015000 36 -0.0365 -0.0365 + 0.015000 37 -0.0103 -0.0103 + 0.015000 38 2.3506 2.3506 + 0.020000 0 0.2666 0.2666 + 0.020000 1 0.1868 0.1868 + 0.020000 2 0.0703 0.0703 + 0.020000 3 -0.3254 -0.3254 + 0.020000 4 0.2691 0.2691 + 0.020000 5 0.0102 0.0102 + 0.020000 6 -0.2645 -0.2645 + 0.020000 7 -0.2835 -0.2835 + 0.020000 8 0.2141 0.2141 + 0.020000 9 0.3166 0.3166 + 0.020000 10 -0.2635 -0.2635 + 0.020000 11 0.0653 0.0653 + 0.020000 12 0.3024 0.3024 + 0.020000 13 0.1976 0.1976 + 0.020000 14 -0.0355 -0.0355 + 0.020000 15 -0.2931 -0.2931 + 0.020000 16 0.1405 0.1405 + 0.020000 17 -0.2154 -0.2154 + 0.020000 18 -0.2976 -0.2976 + 0.020000 19 -0.2589 -0.2589 + 0.020000 20 -0.0579 -0.0579 + 0.020000 21 0.2223 0.2223 + 0.020000 22 -0.2594 -0.2594 + 0.020000 23 -0.1251 -0.1251 + 0.020000 24 0.2263 0.2263 + 0.020000 25 0.1348 0.1348 + 0.020000 26 -0.0242 -0.0242 + 0.020000 27 -0.1535 -0.1535 + 0.020000 28 0.1365 0.1365 + 0.020000 29 0.0982 0.0982 + 0.020000 30 1.3941 1.3941 + 0.020000 31 0.0116 0.0116 + 0.020000 32 -0.0319 -0.0319 + 0.020000 33 0.0116 0.0116 + 0.020000 34 0.8065 0.8065 + 0.020000 35 -0.0388 -0.0388 + 0.020000 36 -0.0319 -0.0319 + 0.020000 37 -0.0388 -0.0388 + 0.020000 38 2.2835 2.2835 diff --git a/regtest/multicolvar/rt-coordination-powers/plumed.dat b/regtest/multicolvar/rt-coordination-powers/plumed.dat new file mode 100644 index 0000000000..ec3e4821ca --- /dev/null +++ b/regtest/multicolvar/rt-coordination-powers/plumed.dat @@ -0,0 +1,3 @@ +COORDINATIONNUMBER SPECIES=1-10 R_0=1 R_POWER=2 LABEL=c1 MEAN +COORDINATIONNUMBER SPECIES=1-10 R_0=1 NUMERICAL_DERIVATIVES R_POWER=2 LABEL=c1num MEAN +DUMPDERIVATIVES ARG=c1.*,c1num.* STRIDE=1 FILE=derivatives FMT=%8.4f diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp index 38c26d348b..e280931ed3 100644 --- a/src/multicolvar/CoordinationNumbers.cpp +++ b/src/multicolvar/CoordinationNumbers.cpp @@ -44,6 +44,14 @@ To make the calculation of coordination numbers differentiable the following fun s = \frac{ 1 - \left(\frac{r-d_0}{r_0}\right)^n } { 1 - \left(\frac{r-d_0}{r_0}\right)^m } \f] +If R_POWER is set, this will use the product of pairwise distance +raised to the R_POWER with the coordination number function defined +above. This was used in White and Voth \cite white2014efficient as a +way of indirectly biasing radial distribution functions. Note that in +that reference this function is referred to as moments of coordination +number, but here we call them powers to distinguish from the existing +MOMENTS keyword of Multicolvars. + \par Examples The following input tells plumed to calculate the coordination numbers of atoms 1-100 with themselves. @@ -59,14 +67,23 @@ number of coordination numbers more than 6 is then computed. COORDINATIONNUMBER SPECIESA=101-110 SPECIESB=1-100 R_0=3.0 MORE_THAN={RATIONAL R_0=6.0 NN=6 MM=12 D_0=0} \endplumedfile +The following input tells plumed to calculate the mean coordination number of all atoms with themselves +and its powers. An explicit cutoff is set for each of 8. +\plumedfile +cn0: COORDINATIONNUMBER SPECIES=1-10 SWITCH={RATIONAL R_0=1.0 D_MAX=8} MEAN +cn1: COORDINATIONNUMBER SPECIES=1-10 SWITCH={RATIONAL R_0=1.0 D_MAX=8} R_POWER=1 MEAN +cn2: COORDINATIONNUMBER SPECIES=1-10 SWITCH={RATIONAL R_0=1.0 D_MAX=8} R_POWER=2 MEAN +PRINT ARG=cn0.mean,cn1.mean,cn2.mean STRIDE=1 FILE=cn_out +\endplumedfile + */ //+ENDPLUMEDOC class CoordinationNumbers : public MultiColvarBase { private: -// double nl_cut; double rcut2; + int r_power; SwitchingFunction switchingFunction; public: static void registerKeywords( Keywords& keys ); @@ -86,9 +103,11 @@ void CoordinationNumbers::registerKeywords( Keywords& keys ) { keys.add("compulsory","MM","0","The m parameter of the switching function; 0 implies 2*NN"); keys.add("compulsory","D_0","0.0","The d_0 parameter of the switching function"); keys.add("compulsory","R_0","The r_0 parameter of the switching function"); + keys.add("optional","R_POWER","Multiply the coordination number function by a power of r, " + "as done in White and Voth (see note above, default: no)"); keys.add("optional","SWITCH","This keyword is used if you want to employ an alternative to the continuous swiching function defined above. " - "The following provides information on the \\ref switchingfunction that are available. " - "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); + "The following provides information on the \\ref switchingfunction that are available. " + "When this keyword is present you no longer need the NN, MM, D_0 and R_0 keywords."); // Use actionWithDistributionKeywords keys.use("MEAN"); keys.use("MORE_THAN"); keys.use("LESS_THAN"); keys.use("MAX"); keys.use("MIN"); keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MOMENTS"); @@ -97,8 +116,10 @@ void CoordinationNumbers::registerKeywords( Keywords& keys ) { CoordinationNumbers::CoordinationNumbers(const ActionOptions&ao): Action(ao), - MultiColvarBase(ao) + MultiColvarBase(ao), + r_power(0) { + // Read in the switching function std::string sw, errors; parse("SWITCH",sw); if(sw.length()>0) { @@ -110,11 +131,25 @@ CoordinationNumbers::CoordinationNumbers(const ActionOptions&ao): parse("R_0",r_0); parse("D_0",d_0); if( r_0<0.0 ) error("you must set a value for R_0"); switchingFunction.set(nn,mm,r_0,d_0); + } log.printf(" coordination of central atom and those within %s\n",( switchingFunction.description() ).c_str() ); + + //get cutoff of switching function + double rcut = switchingFunction.get_dmax(); + + //parse power + parse("R_POWER", r_power); + if(r_power > 0) { + log.printf(" Multiplying switching function by r^%d\n", r_power); + double offset = switchingFunction.calculate(rcut*0.9999, rcut2) * pow(rcut*0.9999, r_power); + log.printf(" You will have a discontinuous jump of %f to 0 near the cutoff of your switching function. " + "Consider setting D_MAX or reducing R_POWER if this is large\n", offset); + } + // Set the link cell cutoff - setLinkCellCutoff( switchingFunction.get_dmax() ); - rcut2 = switchingFunction.get_dmax()*switchingFunction.get_dmax(); + setLinkCellCutoff( rcut ); + rcut2 = rcut * rcut; // And setup the ActionWithVessel std::vector all_atoms; setupMultiColvarBase( all_atoms ); checkRead(); @@ -122,15 +157,23 @@ CoordinationNumbers::CoordinationNumbers(const ActionOptions&ao): double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myatoms ) const { // Calculate the coordination number - double dfunc, d2, sw; + double dfunc, d2, sw, d, raised; for(unsigned i=1; i 0) { + d = sqrt(d2); raised = pow( d, r_power - 1 ); + accumulateSymmetryFunction( 1, i, sw * raised * d, + (dfunc * d * raised + sw * r_power) * distance, + (-dfunc * d * raised - sw * r_power) * Tensor(distance, distance), + myatoms ); + } else { + accumulateSymmetryFunction( 1, i, sw, (dfunc)*distance, (-dfunc)*Tensor(distance,distance), myatoms ); + } } } @@ -139,4 +182,3 @@ double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myat } } - From 8858ff1b6fa98916603ce8e2ac270674dd9cf3d8 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Thu, 4 May 2017 08:38:35 +0100 Subject: [PATCH 48/62] Fixed bug that occurs when using Q6 and LOWEST/HIGHEST --- CHANGES/v2.3.txt | 1 + regtest/crystallization/rt-q6/colv.reference | 4 ++-- regtest/crystallization/rt-q6/plumed.dat | 4 ++-- src/vesselbase/StoreDataVessel.cpp | 9 +++------ 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/CHANGES/v2.3.txt b/CHANGES/v2.3.txt index d5aa9352d2..b2586b9e30 100644 --- a/CHANGES/v2.3.txt +++ b/CHANGES/v2.3.txt @@ -160,6 +160,7 @@ See branch \branch{v2.3} on git repository. - Prevented users from causing segfaults by storing derivatives without LOWMEM flag. In these caess PLUMED crashes with meaningful errors. - Fixed bug in \ref HISTOGRAM that causes nans when using KERNEL=DISCRETE option - Fixed a bug in the parser related to braces, see \issue{229} +- Fixed a bug that appeared when using \ref Q3, \ref Q4 and \ref Q6 with LOWEST or HIGHEST flag For developers: - plumedcheck validation has been made stricter. All the checks are now described in the developer manual. diff --git a/regtest/crystallization/rt-q6/colv.reference b/regtest/crystallization/rt-q6/colv.reference index 8d69c80ee2..320d616223 100644 --- a/regtest/crystallization/rt-q6/colv.reference +++ b/regtest/crystallization/rt-q6/colv.reference @@ -1,2 +1,2 @@ -#! FIELDS time q6.mean - 0.000000 0.245096 +#! FIELDS time q6.mean q6.lowest + 0.000000 0.245096 0.150123 diff --git a/regtest/crystallization/rt-q6/plumed.dat b/regtest/crystallization/rt-q6/plumed.dat index f09db50863..d107217876 100644 --- a/regtest/crystallization/rt-q6/plumed.dat +++ b/regtest/crystallization/rt-q6/plumed.dat @@ -3,10 +3,10 @@ COORDINATIONNUMBER SPECIES=1-64 SWITCH={RATIONAL D_0=3.0 R_0=1.5} MEAN LABEL=c PRINT ARG=c.* FILE=colv2 DUMPDERIVATIVES ARG=c.* FILE=deriv2 FMT=%8.4f -Q6 SPECIES=1-64 D_0=3.0 R_0=1.5 MEAN LABEL=q6 +Q6 SPECIES=1-64 D_0=3.0 R_0=1.5 MEAN LOWEST LABEL=q6 # Q6 SPECIES=1-64 D_0=3.0 R_0=1.5 MEAN NUMERICAL_DERIVATIVES LABEL=q6n PRINT ARG=q6.* FILE=colv -DUMPDERIVATIVES ARG=q6.* FILE=deriv FMT=%8.4f +DUMPDERIVATIVES ARG=q6.mean FILE=deriv FMT=%8.4f Q4 SPECIES=1-64 D_0=3.0 R_0=1.5 MEAN LABEL=q4 # Q4 SPECIES=1-64 D_0=3.0 R_0=1.5 MEAN NUMERICAL_DERIVATIVES LABEL=q4n diff --git a/src/vesselbase/StoreDataVessel.cpp b/src/vesselbase/StoreDataVessel.cpp index d08ec32dd1..e75cf9f370 100644 --- a/src/vesselbase/StoreDataVessel.cpp +++ b/src/vesselbase/StoreDataVessel.cpp @@ -37,8 +37,6 @@ StoreDataVessel::StoreDataVessel( const VesselOptions& da ): ActionWithValue* myval=dynamic_cast( getAction() ); if( !myval ) hasderiv=false; else hasderiv=!myval->doNotCalculateDerivatives(); - - vecsize=getAction()->getNumberOfQuantities(); } void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) { @@ -46,8 +44,6 @@ void StoreDataVessel::addActionThatUses( ActionWithVessel* actionThatUses ) { } void StoreDataVessel::resize() { - plumed_dbg_assert( vecsize>0 ); - if( getAction()->lowmem || !getAction()->derivativesAreRequired() ) { nspace = 1; active_der.resize( max_lowmem_stash * ( 1 + getAction()->getNumberOfDerivatives() ) ); @@ -58,6 +54,7 @@ void StoreDataVessel::resize() { nspace = 1 + getAction()->maxderivatives; active_der.resize( getNumberOfStoredValues() * ( 1 + getAction()->maxderivatives ) ); } + vecsize=getAction()->getNumberOfQuantities(); resizeBuffer( getNumberOfStoredValues()*vecsize*nspace ); local_buffer.resize( getNumberOfStoredValues()*vecsize*nspace ); } @@ -102,14 +99,14 @@ void StoreDataVessel::storeDerivatives( const unsigned& myelem, MultiValue& myva } void StoreDataVessel::retrieveSequentialValue( const unsigned& jelem, const bool& normed, std::vector& values ) const { - plumed_assert( values.size()==vecsize ); + plumed_dbg_assert( values.size()==vecsize ); unsigned ibuf = jelem * vecsize * nspace; for(unsigned i=0; i2 ) getAction()->normalizeVector( values ); } void StoreDataVessel::retrieveValueWithIndex( const unsigned& myelem, const bool& normed, std::vector& values ) const { - plumed_assert( values.size()==vecsize ); + plumed_dbg_assert( values.size()==vecsize ); unsigned jelem = getStoreIndex( myelem ); retrieveSequentialValue( jelem, normed, values ); } From eeb1da233a09dfb80d72ccf55e9848793ebad110 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Thu, 4 May 2017 12:01:27 +0100 Subject: [PATCH 49/62] Some optimization improvements in histograms --- src/analysis/Histogram.cpp | 17 ++++++++++++++--- src/gridtools/GridVessel.cpp | 8 ++++++-- src/gridtools/GridVessel.h | 1 + src/gridtools/HistogramOnGrid.cpp | 4 ++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp index 16abb4a6dc..58e9815981 100644 --- a/src/analysis/Histogram.cpp +++ b/src/analysis/Histogram.cpp @@ -311,6 +311,8 @@ void Histogram::turnOnDerivatives() { if( !mbase ) error("do not know how to get histogram derivatives for actions of type " + myvessels[i]->getName() ); tmp_atoms = mbase->getAbsoluteIndexes(); for(unsigned j=0; jresizeTemporyMultiValues( 1 ); } ActionAtomistic::requestAtoms( all_atoms ); finalForces.resize( 3*all_atoms.size() + 9 ); @@ -386,7 +388,10 @@ void Histogram::compute( const unsigned& current, MultiValue& myvals ) const { for(unsigned i=2; igetNumberOfQuantities(); ++i) myvals.setValue( i-1, cvals[i] ); myvals.setValue( 0, cvals[0] ); myvals.setValue( myvessels[0]->getNumberOfQuantities() - 1, ww ); if( in_apply ) { - MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); + MultiValue& tmpval = stashes[0]->getTemporyMultiValue(0); + if( tmpval.getNumberOfValues()!=myvessels[0]->getNumberOfQuantities() || + tmpval.getNumberOfDerivatives()!=myvessels[0]->getNumberOfDerivatives() ) + tmpval.resize( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), true, tmpval ); for(unsigned j=0; jretrieveSequentialValue( current, false, cvals ); totweight *= cvals[0]; } // And this bit the derivatives - MultiValue tmpval( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); + MultiValue& tmpval = stashes[0]->getTemporyMultiValue(0); + if( tmpval.getNumberOfValues()!=myvessels[0]->getNumberOfQuantities() || + tmpval.getNumberOfDerivatives()!=myvessels[0]->getNumberOfDerivatives() ) + tmpval.resize( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); stashes[0]->retrieveDerivatives( stashes[0]->getTrueIndex(current), false, tmpval ); for(unsigned j=0; jgetNumberOfQuantities(), myvessels[i]->getNumberOfDerivatives() ); + MultiValue& tmpval = stashes[0]->getTemporyMultiValue(0); + if( tmpval.getNumberOfValues()!=myvessels[0]->getNumberOfQuantities() || + tmpval.getNumberOfDerivatives()!=myvessels[0]->getNumberOfDerivatives() ) + tmpval.resize( myvessels[0]->getNumberOfQuantities(), myvessels[0]->getNumberOfDerivatives() ); stashes[i]->retrieveDerivatives( stashes[i]->getTrueIndex(current), false, tmpval ); for(unsigned j=0; j& indic } void GridVessel::getGridPointCoordinates( const unsigned& ipoint, std::vector& x ) const { - plumed_dbg_assert( bounds_set && x.size()==dimension && ipoint tindices( dimension ); getGridPointCoordinates( ipoint, tindices, x ); +} + +void GridVessel::getGridPointCoordinates( const unsigned& ipoint, std::vector& tindices, std::vector& x ) const { + plumed_dbg_assert( bounds_set && x.size()==dimension && tindices.size()==dimension && ipoint tindices( dimension ); getIndices( ipoint, tindices ); + getIndices( ipoint, tindices ); for(unsigned i=0; i& ) const ; + void getGridPointCoordinates( const unsigned&, std::vector&, std::vector& ) const ; /// Get the dimensionality of the function unsigned getDimension() const ; /// Get the number of components in the vector stored on each grid point diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index 43fe891c27..1ddae05a4c 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -121,11 +121,11 @@ void HistogramOnGrid::calculate( const unsigned& current, MultiValue& myvals, st std::vector intforce( 2*dimension, 0.0 ); std::vector vv( getVectorOfValues() ); - double newval; std::vector xx( dimension ); + double newval; std::vector tindices( dimension ); std::vector xx( dimension ); for(unsigned i=0; iset(xx[j]); newval = kernel->evaluate( vv, der, true ); From 4bc18f5790dab5f67b1214be0e978ddc7c951f55 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 4 May 2017 15:46:23 +0200 Subject: [PATCH 50/62] doc regex --- user-doc/Regex.txt | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/user-doc/Regex.txt b/user-doc/Regex.txt index 93561f6322..11999b5821 100644 --- a/user-doc/Regex.txt +++ b/user-doc/Regex.txt @@ -2,8 +2,9 @@ \page Regex Regular Expressions -When you use a collective variable that has many calculated components and you want to -refer to them as arguments you can use regular expressions. +When you use need to pass many arguments to a PLUMED action, being them +components of a few collective variables or also multiple collective variables, +you might find it convenient to use [regular expressions](https://en.wikipedia.org/wiki/Regular_expression). Since version 2.1, plumed takes advantage of a configuration scripts that detects libraries installed on your system. If regex library is found, @@ -13,13 +14,17 @@ or function names. Regular expressions are enclosed in round braces and must not contain spaces (the components names have no spaces indeed, so why use them?). -As an example then command +As an example the command: \plumedfile d1: DISTANCE ATOMS=1,2 COMPONENTS PRINT ARG=(d1\.[xy]) STRIDE=100 FILE=colvar FMT=%8.4f \endplumedfile -will cause both the d1.x and d1.y components of the DISTANCE action to be printed out in the order that they are created by plumed. -The "." character must be escaped in order to interpret it as a literal ".". An unescaped dot is a wildcard which is matched by any character, +will cause both the d1.x and d1.y components of the DISTANCE action to be printed. + +Notice that selection does not happen in alphabetic order, nor in the order in which `[xy]` are listed, but rather in the order in which +the two variables have been created by PLUMED. +Also notice that the +`.` character must be escaped as `\.` in order to interpret it as a literal `.`. An unescaped dot is a wildcard which is matched by any character, So as an example \plumedfile d1: DISTANCE ATOMS=1,2 COMPONENTS @@ -32,27 +37,47 @@ PRINT ARG=(d1.[xy]) STRIDE=100 FILE=colvar FMT=%8.4f PRINT ARG=(d1\.[xy]) STRIDE=100 FILE=colvar FMT=%8.4f \endplumedfile -You can include more than one regular expression by using comma separated regular expressions - +You can concatenate more than one regular expression by using comma separated regular expressions. +The resulting matches will be concatenated: \plumedfile t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 d1: DISTANCE ATOMS=7,17 COMPONENTS + +# The first expression matches d1.x and d1.y +# The second expression matches t1 and t2 PRINT ARG=(d1\.[xy]),(t[0-9]) STRIDE=100 FILE=colvar FMT=%8.4f +# Thus this is the same as ARG=d1.x,d1.y,t1,t2 \endplumedfile -(this selects t1,t2,d1.x and d2.x) Be aware that if you have overlapping selection they will be duplicated so it -a better alternative is to use the "or" operator "|". - +Be aware that if you have overlapping selections they will be duplicated. +As an alternative you could use the "or" operator `|`: \plumedfile t1: TORSION ATOMS=5,7,9,15 t2: TORSION ATOMS=7,9,15,17 d1: DISTANCE ATOMS=7,17 COMPONENTS + +# Here is a single regular expression PRINT ARG=(d1\.[xy]|t[0-9]) STRIDE=100 FILE=colvar FMT=%8.4f +# Thus this is the same as ARG=t1,t2,d1.x,d1.y \endplumedfile this selects the same set of arguments as the previous example. +\note +Be careful you do not confuse regular expressions, which are triggered by the parethesis `()` and only available when +PLUMED has been compiled with the regex library, with the capability of PLUMED to use `*` as a wildcard in arguments: +\plumedfile +d1: DISTANCE ATOMS=1,2 COMPONENTS +# this is a regular expression that selects all components of d1 +# i.e. d1.x d1.y and d1.z +PRINT ARG=(d1\..*) STRIDE=100 FILE=colvar_reg FMT=%8.4f + +# this is a wildcard that selects all the components of d1 as well +PRINT ARG=d1.* STRIDE=100 FILE=colvar_wild FMT=%8.4f +\endplumedfile +Regular expressions are way more flexible than wildcards! + You can check the log to see whether or not your regular expression is picking the set of components you desire. For more information on regular expressions visit http://www.regular-expressions.info/reference.html. From 0e7f526d5c71ed05b0e24093f39fbbc6865a8c35 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 4 May 2017 16:12:06 +0200 Subject: [PATCH 51/62] Improved driver doc --- src/cltools/Driver.cpp | 68 +++++++++++++++++++++++---------------- user-doc/Installation.txt | 21 ++++++++++-- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/cltools/Driver.cpp b/src/cltools/Driver.cpp index 08168b8fb2..3448d229f9 100644 --- a/src/cltools/Driver.cpp +++ b/src/cltools/Driver.cpp @@ -101,47 +101,58 @@ will read a file produced by \ref DUMPMASSCHARGE . \par Examples -The following command tells plumed to postprocess the trajectory contained in trajectory.xyz - by performing the actions described in the input file plumed.dat. If an action that takes the +The following command tells plumed to postprocess the trajectory contained in `trajectory.xyz` + by performing the actions described in the input file `plumed.dat`. If an action that takes the stride keyword is given a stride equal to \f$n\f$ then it will be performed only on every \f$n\f$th -frame in the trajectory file. +frames in the trajectory file. \verbatim plumed driver --plumed plumed.dat --ixyz trajectory.xyz \endverbatim -The following command tells plumed to postprocess the trajectory contained in trajectory.xyz. - by performing the actions described in the input file plumed.dat. Here though ---trajectory-stride is set equal to the frequency with which frames were output during the trajectory -and the --timestep is equal to the simulation timestep. As such the STRIDE parameters in the plumed.dat -files are no longer ignored and any files output resemble those that would have been generated -had we run the calculation we are running with driver when the MD simulation was running. +Notice that `xyz` files are expected to be in internal PLUMED units, that is by default nm. +You can change this behavior by using the `--length-units` option: \verbatim -plumed driver --plumed plumed.dat --ixyz trajectory.xyz --trajectory-stride 100 --timestep 0.001 +plumed driver --plumed plumed.dat --ixyz trajectory.xyz --length-units A \endverbatim - -By default you have access to a subset of the trajectory file formats -supported by VMD, e.g. xtc and dcd: - +The strings accepted by the `--length-units` options are the same ones accepted by the \ref UNITS action. +Other file formats typically have their default coordinates (e.g., `gro` files are always in nm) +and it thus should not be necessary to use the `--length-units` option. Additionally, +consider that the units used by the `driver` might be different by the units used in the PLUMED input +file `plumed.dat`. For instance consider the command: \verbatim -plumed driver --plumed plumed.dat --pdb diala.pdb --mf_xtc traj.xtc --trajectory-stride 100 --timestep 0.001 +plumed driver --plumed plumed.dat --ixyz trajectory.xyz --length-units A +\endverbatim +where `plumed.dat` is +\verbatim +# no explicit UNITS action here +d: DISTANCE ATOMS=1,2 +PRINT ARG=d FILE=colvar \endverbatim +In this case, the driver reads the `xyz` file assuming it to contain coordinates in Angstrom units. +However, the resulting `colvar` file contains a distance expressed in nm. -where --mf_ prefixes the extension of one of the accepted molfile -plugin format. +The following command tells plumed to postprocess the trajectory contained in trajectory.xyz. + by performing the actions described in the input file plumed.dat. +\verbatim +plumed driver --plumed plumed.dat --ixyz trajectory.xyz --trajectory-stride 100 --timestep 0.001 +\endverbatim +Here though +`--trajectory-stride` is set equal to the frequency with which frames were output during the trajectory +and the `--timestep` is equal to the simulation timestep. As such the `STRIDE` parameters in the `plumed.dat` +files are referred to the original timestep and any files output resemble those that would have been generated +had we run the calculation we are running with driver when the MD simulation was running. -To have support of all of VMD's plugins you need to recompile -PLUMED. You need to download the SOURCE of VMD, which contains -a plugins directory. Adapt build.sh and compile it. At -the end, you should get the molfile plugins compiled as a static -library libmolfile_plugin.a. Locate said file and libmolfile_plugin.h, -and customize the configure command with something along -the lines of: +PLUMED can read natively xyz files (in PLUMED units) and gro files (in nm). In addition, +PLUMED includes by default support for a +subset of the trajectory file formats supported by VMD, e.g. xtc and dcd: \verbatim -configure [...] LDFLAGS="-ltcl8.5 -L/mypathtomolfilelibrary/ -L/mypathtotcl" CPPFLAGS="-I/mypathtolibmolfile_plugin.h/" +plumed driver --plumed plumed.dat --pdb diala.pdb --mf_xtc traj.xtc --trajectory-stride 100 --timestep 0.001 \endverbatim -and rebuild. +where `--mf_` prefixes the extension of one of the accepted molfile plugin format. +If PLUMED has been \ref Installation "installed" with full molfile support, other formats will be available. +Just type `plumed driver --help` to see which plugins are available. Molfile plugin require periodic cell to be triangular (i.e. first vector oriented along x and second vector in xy plane). This is true for many MD codes. However, it could be false @@ -152,14 +163,15 @@ the `--natoms` option: plumed driver --plumed plumed.dat --imf_crd trajectory.crd --natoms 128 \endverbatim -Check the available molfile plugins and limitations at http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/. +Check the available molfile plugins and limitations at [this link](http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/). Additionally, you can use the xdrfile implementation of xtc and trr. To this aim, just -download and install properly the xdrfile library (see here: http://www.gromacs.org/Developer_Zone/Programming_Guide/XTC_Library). +download and install properly the xdrfile library (see [this link](http://www.gromacs.org/Developer_Zone/Programming_Guide/XTC_Library)). If the xdrfile library is installed properly the PLUMED configure script should be able to detect it and enable it. Notice that the xdrfile implementation of xtc and trr is more robust than the molfile one, since it provides support for generic cell shapes. +In addition, it allows \ref DUMPATOMS to write compressed xtc files. */ diff --git a/user-doc/Installation.txt b/user-doc/Installation.txt index 6b2a7c5dce..aea4abc192 100644 --- a/user-doc/Installation.txt +++ b/user-doc/Installation.txt @@ -254,6 +254,23 @@ in the configuration file. -DF77_NO_UNDERSCORE to CPPFLAGS Notice that "./configure" should automatically try this solution. +\subsection installation-vmdplugins VMD trajectory plugins + +If you configure PLUMED with VMD's plugins you will be able to read +many more trajectory formats. To this aim, +you need to download the SOURCE of VMD, which contains +a plugins directory. Adapt build.sh and compile it. At +the end, you should get the molfile plugins compiled as a static +library `libmolfile_plugin.a`. Locate said file and `libmolfile_plugin.h`, +and customize the configure command with something along +the lines of: + +\verbatim +./configure LDFLAGS="-ltcl8.5 -L/mypathtomolfilelibrary/ -L/mypathtotcl" CPPFLAGS="-I/mypathtolibmolfile_plugin.h/" +\endverbatim + +and rebuild. + \section CompilingPlumed Compiling PLUMED Once configured, PLUMED can be compiled using the following command: @@ -438,12 +455,12 @@ There are different options available when patching. You can check all of them u > plumed patch --help \endverbatim Particularly interesting options include: -- --static (default) just link PLUMED as a collection of object files. This is only suggested if for external reasons you +- --static just link PLUMED as a collection of object files. This is only suggested if for external reasons you absolutely need a static executable. Notice that with this setting it is often more complicated to configure properly the MD code, since all the libraries that PLUMED depends on should be properly specified. The `./configure` script does its best in this sense, but sometime it cannot solve the problem. Additionally, this patching mode has been reported not to work properly on OSX. -- --shared allows you to link PLUMED as a shared library. As a result when PLUMED is updated, there will be no need to recompile the MD code. +- --shared (default) allows you to link PLUMED as a shared library. As a result when PLUMED is updated, there will be no need to recompile the MD code. This is way better than --static since the libraries that PLUMED depends on should be automatically linked. Notice that if you later remove the directory where PLUMED is installed also the MD code will not run anymore. - --runtime allows you to choose the location of the PLUMED library at runtime by setting the variable PLUMED_KERNEL. From 52f8590bf8646dcac8a74d7cbec7f0da47261dce Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 4 May 2017 16:13:42 +0200 Subject: [PATCH 52/62] doc --- src/cltools/Driver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cltools/Driver.cpp b/src/cltools/Driver.cpp index b15515cb68..e9337040c3 100644 --- a/src/cltools/Driver.cpp +++ b/src/cltools/Driver.cpp @@ -123,11 +123,11 @@ file `plumed.dat`. For instance consider the command: plumed driver --plumed plumed.dat --ixyz trajectory.xyz --length-units A \endverbatim where `plumed.dat` is -\verbatim +\plumedfile # no explicit UNITS action here d: DISTANCE ATOMS=1,2 PRINT ARG=d FILE=colvar -\endverbatim +\endplumedfile In this case, the driver reads the `xyz` file assuming it to contain coordinates in Angstrom units. However, the resulting `colvar` file contains a distance expressed in nm. From 8ff8874138292069c4e0f85865dc9e668862418a Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 4 May 2017 18:39:28 +0200 Subject: [PATCH 53/62] renamed file File was inconsistent with action and class name --- src/analysis/{Commit.cpp => Committor.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/analysis/{Commit.cpp => Committor.cpp} (100%) diff --git a/src/analysis/Commit.cpp b/src/analysis/Committor.cpp similarity index 100% rename from src/analysis/Commit.cpp rename to src/analysis/Committor.cpp From 9d462172620cf376238681533f8440af95cbe76a Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 4 May 2017 18:43:41 +0200 Subject: [PATCH 54/62] headers Notice that almost all files were updated with the astyle commit 2813d759200182dd1a8962ed0048d765fc789b14 Year in header is here updated to 2017 --- src/adjmat/ActionWithInputMatrix.cpp | 2 +- src/adjmat/ActionWithInputMatrix.h | 2 +- src/adjmat/AdjacencyMatrixBase.cpp | 2 +- src/adjmat/AdjacencyMatrixBase.h | 2 +- src/adjmat/AdjacencyMatrixVessel.cpp | 2 +- src/adjmat/AdjacencyMatrixVessel.h | 2 +- src/adjmat/AlignedMatrixBase.cpp | 2 +- src/adjmat/ClusterAnalysisBase.cpp | 2 +- src/adjmat/ClusterAnalysisBase.h | 2 +- src/adjmat/ClusterDiameter.cpp | 2 +- src/adjmat/ClusterDistribution.cpp | 2 +- src/adjmat/ClusterProperties.cpp | 2 +- src/adjmat/ClusterSize.cpp | 2 +- src/adjmat/ClusterWithSurface.cpp | 2 +- src/adjmat/ClusteringBase.cpp | 2 +- src/adjmat/ClusteringBase.h | 2 +- src/adjmat/ContactAlignedMatrix.cpp | 2 +- src/adjmat/ContactMatrix.cpp | 2 +- src/adjmat/DFSClustering.cpp | 2 +- src/adjmat/HbondMatrix.cpp | 2 +- src/adjmat/MatrixColumnSums.cpp | 2 +- src/adjmat/MatrixRowSums.cpp | 2 +- src/adjmat/OutputCluster.cpp | 2 +- src/adjmat/Sprint.cpp | 2 +- src/analysis/Analysis.cpp | 2 +- src/analysis/Analysis.h | 2 +- src/analysis/AnalysisWithLandmarks.cpp | 2 +- src/analysis/AnalysisWithLandmarks.h | 2 +- src/analysis/Average.cpp | 2 +- src/analysis/AverageVessel.cpp | 2 +- src/analysis/AverageVessel.h | 2 +- src/analysis/ClassicalMultiDimensionalScaling.cpp | 2 +- src/analysis/ClassicalScaling.cpp | 2 +- src/analysis/Commit.cpp | 2 +- src/analysis/Histogram.cpp | 2 +- src/analysis/LandmarkRegister.cpp | 2 +- src/analysis/LandmarkRegister.h | 2 +- src/analysis/LandmarkSelectionBase.cpp | 2 +- src/analysis/LandmarkSelectionBase.h | 2 +- src/analysis/SelectAllFrames.cpp | 2 +- src/bias/ABMD.cpp | 2 +- src/bias/Bias.cpp | 2 +- src/bias/Bias.h | 2 +- src/bias/BiasValue.cpp | 2 +- src/bias/ExtendedLagrangian.cpp | 2 +- src/bias/External.cpp | 2 +- src/bias/LWalls.cpp | 2 +- src/bias/Metainference.cpp | 2 +- src/bias/MovingRestraint.cpp | 2 +- src/bias/PBMetaD.cpp | 2 +- src/bias/Restraint.cpp | 2 +- src/bias/ReweightBase.cpp | 2 +- src/bias/ReweightBase.h | 2 +- src/bias/ReweightBias.cpp | 2 +- src/bias/ReweightMetad.cpp | 2 +- src/bias/ReweightTemperature.cpp | 2 +- src/bias/UWalls.cpp | 2 +- src/cltools/CLTool.h | 2 +- src/cltools/DriverDouble.cpp | 2 +- src/cltools/DriverFloat.cpp | 2 +- src/cltools/GenTemplate.cpp | 2 +- src/cltools/Info.cpp | 2 +- src/cltools/Manual.cpp | 2 +- src/cltools/SimpleMD.cpp | 2 +- src/cltools/SumHills.cpp | 2 +- src/cltools/kT.cpp | 2 +- src/colvar/Angle.cpp | 2 +- src/colvar/Cell.cpp | 2 +- src/colvar/Colvar.h | 2 +- src/colvar/Constant.cpp | 2 +- src/colvar/ContactMap.cpp | 2 +- src/colvar/Coordination.cpp | 2 +- src/colvar/CoordinationBase.cpp | 2 +- src/colvar/CoordinationBase.h | 2 +- src/colvar/DHEnergy.cpp | 2 +- src/colvar/DRMSD.cpp | 2 +- src/colvar/Dipole.cpp | 2 +- src/colvar/Distance.cpp | 2 +- src/colvar/Energy.cpp | 2 +- src/colvar/Fake.cpp | 2 +- src/colvar/FretEfficiency.cpp | 2 +- src/colvar/Gyration.cpp | 2 +- src/colvar/Jcoupling.cpp | 2 +- src/colvar/MultiRMSD.cpp | 2 +- src/colvar/NOE.cpp | 2 +- src/colvar/PCARMSD.cpp | 2 +- src/colvar/PRE.cpp | 2 +- src/colvar/PathMSD.cpp | 2 +- src/colvar/PathMSDBase.cpp | 2 +- src/colvar/PathMSDBase.h | 2 +- src/colvar/Position.cpp | 2 +- src/colvar/PropertyMap.cpp | 2 +- src/colvar/Puckering.cpp | 2 +- src/colvar/RDC.cpp | 2 +- src/colvar/RMSD.cpp | 2 +- src/colvar/Template.cpp | 2 +- src/colvar/Volume.cpp | 2 +- src/config/Config.h | 2 +- src/config/Config.inc.in | 2 +- src/core/Action.cpp | 2 +- src/core/Action.h | 2 +- src/core/ActionAtomistic.cpp | 2 +- src/core/ActionPilot.cpp | 2 +- src/core/ActionPilot.h | 2 +- src/core/ActionRegister.cpp | 2 +- src/core/ActionRegister.h | 2 +- src/core/ActionSet.cpp | 2 +- src/core/ActionSet.h | 2 +- src/core/ActionSetup.cpp | 2 +- src/core/ActionSetup.h | 2 +- src/core/ActionWithArguments.cpp | 2 +- src/core/ActionWithArguments.h | 2 +- src/core/ActionWithValue.cpp | 2 +- src/core/ActionWithValue.h | 2 +- src/core/ActionWithVirtualAtom.cpp | 2 +- src/core/ActionWithVirtualAtom.h | 2 +- src/core/CLTool.cpp | 2 +- src/core/CLTool.h | 2 +- src/core/CLToolMain.cpp | 2 +- src/core/CLToolMain.h | 2 +- src/core/CLToolRegister.cpp | 2 +- src/core/CLToolRegister.h | 2 +- src/core/Colvar.cpp | 2 +- src/core/Colvar.h | 2 +- src/core/ExchangePatterns.cpp | 2 +- src/core/ExchangePatterns.h | 2 +- src/core/FlexibleBin.cpp | 2 +- src/core/FlexibleBin.h | 2 +- src/core/GREX.cpp | 2 +- src/core/GREX.h | 2 +- src/core/MDAtoms.cpp | 2 +- src/core/PlumedMainInitializer.cpp | 2 +- src/core/SetupMolInfo.cpp | 2 +- src/core/SetupMolInfo.h | 2 +- src/core/TargetDist.cpp | 2 +- src/core/TargetDist.h | 2 +- src/core/Value.cpp | 2 +- src/core/Value.h | 2 +- src/core/WithCmd.h | 2 +- src/crystallization/CubicHarmonicBase.cpp | 2 +- src/crystallization/CubicHarmonicBase.h | 2 +- src/crystallization/Fccubic.cpp | 2 +- src/crystallization/Gradient.cpp | 2 +- src/crystallization/Gradient.h | 2 +- src/crystallization/GradientVessel.cpp | 2 +- src/crystallization/InterMolecularTorsions.cpp | 2 +- src/crystallization/LocalSteinhardt.h | 2 +- src/crystallization/MoleculeOrientation.cpp | 2 +- src/crystallization/MoleculePlane.cpp | 2 +- src/crystallization/OrientationSphere.cpp | 2 +- src/crystallization/OrientationSphere.h | 2 +- src/crystallization/Q3.cpp | 2 +- src/crystallization/Q4.cpp | 2 +- src/crystallization/Q6.cpp | 2 +- src/crystallization/SMAC.cpp | 2 +- src/crystallization/SimpleCubic.cpp | 2 +- src/crystallization/Steinhardt.cpp | 2 +- src/crystallization/Tetrahedral.cpp | 2 +- src/crystallization/VectorMean.cpp | 2 +- src/crystallization/VectorMultiColvar.cpp | 2 +- src/crystallization/VectorMultiColvar.h | 2 +- src/crystallization/VectorSum.cpp | 2 +- src/function/Combine.cpp | 2 +- src/function/Ensemble.cpp | 2 +- src/function/FuncPathMSD.cpp | 2 +- src/function/FuncSumHills.cpp | 2 +- src/function/Function.cpp | 2 +- src/function/Function.h | 2 +- src/function/LocalEnsemble.cpp | 2 +- src/function/Matheval.cpp | 2 +- src/function/Piecewise.cpp | 2 +- src/function/Sort.cpp | 2 +- src/function/Stats.cpp | 2 +- src/function/Target.cpp | 2 +- src/generic/Debug.cpp | 2 +- src/generic/DumpAtoms.cpp | 2 +- src/generic/DumpDerivatives.cpp | 2 +- src/generic/DumpForces.cpp | 2 +- src/generic/DumpMassCharge.cpp | 2 +- src/generic/DumpProjections.cpp | 2 +- src/generic/EffectiveEnergyDrift.cpp | 2 +- src/generic/Flush.cpp | 2 +- src/generic/Group.cpp | 2 +- src/generic/Include.cpp | 2 +- src/generic/Print.cpp | 2 +- src/generic/RandomExchanges.cpp | 2 +- src/generic/Read.cpp | 2 +- src/generic/ResetCell.cpp | 2 +- src/generic/Time.cpp | 2 +- src/generic/UpdateIf.cpp | 2 +- src/generic/WholeMolecules.cpp | 2 +- src/generic/WrapAround.cpp | 2 +- src/gridtools/ActionWithGrid.cpp | 2 +- src/gridtools/ActionWithGrid.h | 2 +- src/gridtools/ActionWithInputGrid.cpp | 2 +- src/gridtools/ActionWithInputGrid.h | 2 +- src/gridtools/AverageOnGrid.cpp | 2 +- src/gridtools/ContourFindingBase.cpp | 2 +- src/gridtools/ContourFindingBase.h | 2 +- src/gridtools/ConvertToFES.cpp | 2 +- src/gridtools/DumpCube.cpp | 2 +- src/gridtools/DumpGrid.cpp | 2 +- src/gridtools/FindContour.cpp | 2 +- src/gridtools/FindContourSurface.cpp | 2 +- src/gridtools/FindSphericalContour.cpp | 2 +- src/gridtools/FourierTransform.cpp | 2 +- src/gridtools/GridPrintingBase.cpp | 2 +- src/gridtools/GridPrintingBase.h | 2 +- src/gridtools/GridVessel.h | 2 +- src/gridtools/HistogramOnGrid.cpp | 2 +- src/gridtools/HistogramOnGrid.h | 2 +- src/gridtools/InterpolateGrid.cpp | 2 +- src/main/main.cpp | 2 +- src/manyrestraints/ManyRestraintsBase.cpp | 2 +- src/manyrestraints/ManyRestraintsBase.h | 2 +- src/manyrestraints/UWalls.cpp | 2 +- src/mapping/Mapping.cpp | 2 +- src/mapping/Mapping.h | 2 +- src/mapping/PCAVars.cpp | 2 +- src/mapping/Path.cpp | 2 +- src/mapping/PathBase.cpp | 2 +- src/mapping/PathBase.h | 2 +- src/mapping/PropertyMap.cpp | 2 +- src/mapping/SpathVessel.cpp | 2 +- src/mapping/ZpathVessel.cpp | 2 +- src/multicolvar/ActionVolume.cpp | 2 +- src/multicolvar/ActionVolume.h | 2 +- src/multicolvar/AlphaBeta.cpp | 2 +- src/multicolvar/Angles.cpp | 2 +- src/multicolvar/AtomValuePack.cpp | 2 +- src/multicolvar/AtomValuePack.h | 2 +- src/multicolvar/Bridge.cpp | 2 +- src/multicolvar/BridgedMultiColvarFunction.cpp | 2 +- src/multicolvar/BridgedMultiColvarFunction.h | 2 +- src/multicolvar/CatomPack.cpp | 2 +- src/multicolvar/CatomPack.h | 2 +- src/multicolvar/CenterOfMultiColvar.cpp | 2 +- src/multicolvar/CoordinationNumbers.cpp | 2 +- src/multicolvar/Density.cpp | 2 +- src/multicolvar/DihedralCorrelation.cpp | 2 +- src/multicolvar/DistanceFromContour.cpp | 2 +- src/multicolvar/Distances.cpp | 2 +- src/multicolvar/DumpMultiColvar.cpp | 2 +- src/multicolvar/InPlaneDistances.cpp | 2 +- src/multicolvar/LocalAverage.cpp | 2 +- src/multicolvar/MultiColvar.cpp | 2 +- src/multicolvar/MultiColvar.h | 2 +- src/multicolvar/MultiColvarBase.cpp | 2 +- src/multicolvar/MultiColvarBase.h | 2 +- src/multicolvar/MultiColvarDensity.cpp | 2 +- src/multicolvar/MultiColvarFilter.cpp | 2 +- src/multicolvar/MultiColvarFilter.h | 2 +- src/multicolvar/MultiColvarFunction.cpp | 2 +- src/multicolvar/MultiColvarFunction.h | 2 +- src/multicolvar/NumberOfLinks.cpp | 2 +- src/multicolvar/Torsions.cpp | 2 +- src/multicolvar/VolumeAround.cpp | 2 +- src/multicolvar/VolumeCavity.cpp | 2 +- src/multicolvar/VolumeGradientBase.cpp | 2 +- src/multicolvar/VolumeGradientBase.h | 2 +- src/multicolvar/VolumeInCylinder.cpp | 2 +- src/multicolvar/VolumeInSphere.cpp | 2 +- src/multicolvar/VolumeTetrapore.cpp | 2 +- src/multicolvar/XDistances.cpp | 2 +- src/multicolvar/XYDistances.cpp | 2 +- src/reference/ArgumentOnlyDistance.cpp | 2 +- src/reference/DRMSD.cpp | 2 +- src/reference/DRMSD.h | 2 +- src/reference/Direction.cpp | 2 +- src/reference/Direction.h | 2 +- src/reference/DotProductDistance.cpp | 2 +- src/reference/EuclideanDistance.cpp | 2 +- src/reference/FakeFrame.h | 2 +- src/reference/IntermolecularDRMSD.cpp | 2 +- src/reference/IntramolecularDRMSD.cpp | 2 +- src/reference/MahalanobisDistance.cpp | 2 +- src/reference/MetricRegister.cpp | 2 +- src/reference/MetricRegister.h | 2 +- src/reference/MultiDomainRMSD.cpp | 2 +- src/reference/MultiDomainRMSD.h | 2 +- src/reference/MultiReferenceBase.cpp | 2 +- src/reference/MultiReferenceBase.h | 2 +- src/reference/NormalizedEuclideanDistance.cpp | 2 +- src/reference/OptimalRMSD.cpp | 2 +- src/reference/PointWiseMapping.cpp | 2 +- src/reference/PointWiseMapping.h | 2 +- src/reference/RMSDBase.cpp | 2 +- src/reference/RMSDBase.h | 2 +- src/reference/ReferenceArguments.cpp | 2 +- src/reference/ReferenceArguments.h | 2 +- src/reference/ReferenceAtoms.cpp | 2 +- src/reference/ReferenceAtoms.h | 2 +- src/reference/ReferenceConfiguration.cpp | 2 +- src/reference/ReferenceConfiguration.h | 2 +- src/reference/ReferenceValuePack.cpp | 2 +- src/reference/ReferenceValuePack.h | 2 +- src/reference/SimpleRMSD.cpp | 2 +- src/reference/SingleDomainRMSD.cpp | 2 +- src/reference/SingleDomainRMSD.h | 2 +- src/secondarystructure/AlphaRMSD.cpp | 2 +- src/secondarystructure/AntibetaRMSD.cpp | 2 +- src/secondarystructure/ParabetaRMSD.cpp | 2 +- src/secondarystructure/SecondaryStructureRMSD.cpp | 2 +- src/secondarystructure/SecondaryStructureRMSD.h | 2 +- src/setup/Load.cpp | 2 +- src/setup/Restart.cpp | 2 +- src/setup/Units.cpp | 2 +- src/tools/Angle.cpp | 2 +- src/tools/Angle.h | 2 +- src/tools/AtomNumber.h | 2 +- src/tools/BiasRepresentation.cpp | 2 +- src/tools/BiasRepresentation.h | 2 +- src/tools/Brent1DRootSearch.h | 2 +- src/tools/Citations.cpp | 2 +- src/tools/Citations.h | 2 +- src/tools/Communicator.cpp | 2 +- src/tools/Communicator.h | 2 +- src/tools/CubicInterpolation.cpp | 2 +- src/tools/CubicInterpolation.h | 2 +- src/tools/DLLoader.cpp | 2 +- src/tools/DLLoader.h | 2 +- src/tools/DynamicList.h | 2 +- src/tools/ERMSD.cpp | 2 +- src/tools/ERMSD.h | 2 +- src/tools/Exception.cpp | 2 +- src/tools/Exception.h | 2 +- src/tools/FileBase.cpp | 2 +- src/tools/FileBase.h | 2 +- src/tools/Grid.cpp | 2 +- src/tools/Grid.h | 2 +- src/tools/HistogramBead.cpp | 2 +- src/tools/HistogramBead.h | 2 +- src/tools/IFile.cpp | 2 +- src/tools/IFile.h | 2 +- src/tools/Kearsley.cpp | 2 +- src/tools/Kearsley.h | 2 +- src/tools/KernelFunctions.cpp | 2 +- src/tools/KernelFunctions.h | 2 +- src/tools/Keywords.cpp | 2 +- src/tools/Keywords.h | 2 +- src/tools/LatticeReduction.cpp | 2 +- src/tools/LatticeReduction.h | 2 +- src/tools/LinkCells.cpp | 2 +- src/tools/LinkCells.h | 2 +- src/tools/Log.h | 2 +- src/tools/LoopUnroller.h | 2 +- src/tools/Matrix.h | 2 +- src/tools/MatrixSquareBracketsAccess.h | 2 +- src/tools/Minimise1DBrent.h | 2 +- src/tools/MinimiseBase.h | 2 +- src/tools/MolDataClass.cpp | 2 +- src/tools/MolDataClass.h | 2 +- src/tools/MultiValue.cpp | 2 +- src/tools/MultiValue.h | 2 +- src/tools/NeighborList.cpp | 2 +- src/tools/NeighborList.h | 2 +- src/tools/OFile.cpp | 2 +- src/tools/OFile.h | 2 +- src/tools/OpenMP.cpp | 2 +- src/tools/OpenMP.h | 2 +- src/tools/OptimalAlignment.cpp | 2 +- src/tools/OptimalAlignment.h | 2 +- src/tools/PDB.cpp | 2 +- src/tools/PDB.h | 2 +- src/tools/Pbc.cpp | 2 +- src/tools/Pbc.h | 2 +- src/tools/RMSD.cpp | 2 +- src/tools/RMSD.h | 2 +- src/tools/Random.cpp | 2 +- src/tools/Random.h | 2 +- src/tools/RootFindingBase.h | 2 +- src/tools/Stopwatch.cpp | 2 +- src/tools/Stopwatch.h | 2 +- src/tools/SwitchingFunction.cpp | 2 +- src/tools/SwitchingFunction.h | 2 +- src/tools/Tensor.cpp | 2 +- src/tools/Tensor.h | 2 +- src/tools/Tools.cpp | 2 +- src/tools/Tools.h | 2 +- src/tools/Torsion.cpp | 2 +- src/tools/Torsion.h | 2 +- src/tools/Units.cpp | 2 +- src/tools/Units.h | 2 +- src/tools/Vector.cpp | 2 +- src/tools/Vector.h | 2 +- src/vatom/ActionWithVirtualAtom.h | 2 +- src/vatom/COM.cpp | 2 +- src/vatom/Center.cpp | 2 +- src/vatom/FixedAtom.cpp | 2 +- src/vatom/Ghost.cpp | 2 +- src/vesselbase/ActionWithAveraging.cpp | 2 +- src/vesselbase/ActionWithAveraging.h | 2 +- src/vesselbase/ActionWithInputVessel.cpp | 2 +- src/vesselbase/ActionWithInputVessel.h | 2 +- src/vesselbase/ActionWithVessel.cpp | 2 +- src/vesselbase/ActionWithVessel.h | 2 +- src/vesselbase/AltMin.cpp | 2 +- src/vesselbase/AveragingVessel.cpp | 2 +- src/vesselbase/AveragingVessel.h | 2 +- src/vesselbase/Between.cpp | 2 +- src/vesselbase/BridgeVessel.cpp | 2 +- src/vesselbase/BridgeVessel.h | 2 +- src/vesselbase/FunctionVessel.cpp | 2 +- src/vesselbase/FunctionVessel.h | 2 +- src/vesselbase/Highest.cpp | 2 +- src/vesselbase/Histogram.cpp | 2 +- src/vesselbase/LessThan.cpp | 2 +- src/vesselbase/LessThan.h | 2 +- src/vesselbase/Lowest.cpp | 2 +- src/vesselbase/Max.cpp | 2 +- src/vesselbase/Mean.cpp | 2 +- src/vesselbase/Min.cpp | 2 +- src/vesselbase/Moments.cpp | 2 +- src/vesselbase/MoreThan.cpp | 2 +- src/vesselbase/OrderingVessel.cpp | 2 +- src/vesselbase/OrderingVessel.h | 2 +- src/vesselbase/ShortcutVessel.cpp | 2 +- src/vesselbase/ShortcutVessel.h | 2 +- src/vesselbase/StoreDataVessel.cpp | 2 +- src/vesselbase/StoreDataVessel.h | 2 +- src/vesselbase/Sum.cpp | 2 +- src/vesselbase/ValueVessel.cpp | 2 +- src/vesselbase/ValueVessel.h | 2 +- src/vesselbase/Vessel.cpp | 2 +- src/vesselbase/Vessel.h | 2 +- src/vesselbase/VesselRegister.cpp | 2 +- src/vesselbase/VesselRegister.h | 2 +- src/wrapper/Plumed.c | 2 +- src/wrapper/Plumed.h | 2 +- 429 files changed, 429 insertions(+), 429 deletions(-) diff --git a/src/adjmat/ActionWithInputMatrix.cpp b/src/adjmat/ActionWithInputMatrix.cpp index 44b4073426..afbba96251 100644 --- a/src/adjmat/ActionWithInputMatrix.cpp +++ b/src/adjmat/ActionWithInputMatrix.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ActionWithInputMatrix.h b/src/adjmat/ActionWithInputMatrix.h index 7ad2118140..91f43fb7eb 100644 --- a/src/adjmat/ActionWithInputMatrix.h +++ b/src/adjmat/ActionWithInputMatrix.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/AdjacencyMatrixBase.cpp b/src/adjmat/AdjacencyMatrixBase.cpp index 9f6cc8de7d..41fbef64db 100644 --- a/src/adjmat/AdjacencyMatrixBase.cpp +++ b/src/adjmat/AdjacencyMatrixBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/AdjacencyMatrixBase.h b/src/adjmat/AdjacencyMatrixBase.h index f1db57037e..c53ee83500 100644 --- a/src/adjmat/AdjacencyMatrixBase.h +++ b/src/adjmat/AdjacencyMatrixBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/AdjacencyMatrixVessel.cpp b/src/adjmat/AdjacencyMatrixVessel.cpp index e2198184a5..c869255633 100644 --- a/src/adjmat/AdjacencyMatrixVessel.cpp +++ b/src/adjmat/AdjacencyMatrixVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/AdjacencyMatrixVessel.h b/src/adjmat/AdjacencyMatrixVessel.h index eeee7e72e8..aee9e774e8 100644 --- a/src/adjmat/AdjacencyMatrixVessel.h +++ b/src/adjmat/AdjacencyMatrixVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/AlignedMatrixBase.cpp b/src/adjmat/AlignedMatrixBase.cpp index 408cf8c736..93d923d686 100644 --- a/src/adjmat/AlignedMatrixBase.cpp +++ b/src/adjmat/AlignedMatrixBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterAnalysisBase.cpp b/src/adjmat/ClusterAnalysisBase.cpp index ee6c743064..0ed5451fba 100644 --- a/src/adjmat/ClusterAnalysisBase.cpp +++ b/src/adjmat/ClusterAnalysisBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterAnalysisBase.h b/src/adjmat/ClusterAnalysisBase.h index 24a1b80aee..287e11816d 100644 --- a/src/adjmat/ClusterAnalysisBase.h +++ b/src/adjmat/ClusterAnalysisBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterDiameter.cpp b/src/adjmat/ClusterDiameter.cpp index ec26f2eeb9..fbecd9705f 100644 --- a/src/adjmat/ClusterDiameter.cpp +++ b/src/adjmat/ClusterDiameter.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterDistribution.cpp b/src/adjmat/ClusterDistribution.cpp index 93f12fb04c..3666028302 100644 --- a/src/adjmat/ClusterDistribution.cpp +++ b/src/adjmat/ClusterDistribution.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterProperties.cpp b/src/adjmat/ClusterProperties.cpp index 9a0d38e5be..a1ba49c2a1 100644 --- a/src/adjmat/ClusterProperties.cpp +++ b/src/adjmat/ClusterProperties.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterSize.cpp b/src/adjmat/ClusterSize.cpp index b0b22621d6..1d3888521b 100644 --- a/src/adjmat/ClusterSize.cpp +++ b/src/adjmat/ClusterSize.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusterWithSurface.cpp b/src/adjmat/ClusterWithSurface.cpp index ab472eee50..cd624d4d3c 100644 --- a/src/adjmat/ClusterWithSurface.cpp +++ b/src/adjmat/ClusterWithSurface.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusteringBase.cpp b/src/adjmat/ClusteringBase.cpp index 6db59c9ac2..b7003ee459 100644 --- a/src/adjmat/ClusteringBase.cpp +++ b/src/adjmat/ClusteringBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ClusteringBase.h b/src/adjmat/ClusteringBase.h index 741ac9046e..9d9aa88fcd 100644 --- a/src/adjmat/ClusteringBase.h +++ b/src/adjmat/ClusteringBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ContactAlignedMatrix.cpp b/src/adjmat/ContactAlignedMatrix.cpp index e1bdfcdba0..93b04c6029 100644 --- a/src/adjmat/ContactAlignedMatrix.cpp +++ b/src/adjmat/ContactAlignedMatrix.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/ContactMatrix.cpp b/src/adjmat/ContactMatrix.cpp index 1105a1aa23..f559315b7c 100644 --- a/src/adjmat/ContactMatrix.cpp +++ b/src/adjmat/ContactMatrix.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/DFSClustering.cpp b/src/adjmat/DFSClustering.cpp index af0dc327e8..1f8870fee7 100644 --- a/src/adjmat/DFSClustering.cpp +++ b/src/adjmat/DFSClustering.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/HbondMatrix.cpp b/src/adjmat/HbondMatrix.cpp index f75e95754b..f5a2d0ba02 100644 --- a/src/adjmat/HbondMatrix.cpp +++ b/src/adjmat/HbondMatrix.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/MatrixColumnSums.cpp b/src/adjmat/MatrixColumnSums.cpp index 56aa981dff..8433270071 100644 --- a/src/adjmat/MatrixColumnSums.cpp +++ b/src/adjmat/MatrixColumnSums.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/MatrixRowSums.cpp b/src/adjmat/MatrixRowSums.cpp index 038aa89a71..569eafa5e7 100644 --- a/src/adjmat/MatrixRowSums.cpp +++ b/src/adjmat/MatrixRowSums.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/OutputCluster.cpp b/src/adjmat/OutputCluster.cpp index c2b752f0d0..a288d5fcc2 100644 --- a/src/adjmat/OutputCluster.cpp +++ b/src/adjmat/OutputCluster.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/adjmat/Sprint.cpp b/src/adjmat/Sprint.cpp index f7e0a0da8f..396f6cd0ea 100644 --- a/src/adjmat/Sprint.cpp +++ b/src/adjmat/Sprint.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/Analysis.cpp b/src/analysis/Analysis.cpp index 989981ab6b..5901ca7624 100644 --- a/src/analysis/Analysis.cpp +++ b/src/analysis/Analysis.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/Analysis.h b/src/analysis/Analysis.h index b17b34e8f7..b71150fe75 100644 --- a/src/analysis/Analysis.h +++ b/src/analysis/Analysis.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/AnalysisWithLandmarks.cpp b/src/analysis/AnalysisWithLandmarks.cpp index 9cd67c52f4..7302d5152d 100644 --- a/src/analysis/AnalysisWithLandmarks.cpp +++ b/src/analysis/AnalysisWithLandmarks.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/AnalysisWithLandmarks.h b/src/analysis/AnalysisWithLandmarks.h index b129a4d01e..ebc99b9cd1 100644 --- a/src/analysis/AnalysisWithLandmarks.h +++ b/src/analysis/AnalysisWithLandmarks.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/Average.cpp b/src/analysis/Average.cpp index 92c3e35a2c..c8d74df679 100644 --- a/src/analysis/Average.cpp +++ b/src/analysis/Average.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/AverageVessel.cpp b/src/analysis/AverageVessel.cpp index 96e4a72fe0..5c7646769b 100644 --- a/src/analysis/AverageVessel.cpp +++ b/src/analysis/AverageVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/AverageVessel.h b/src/analysis/AverageVessel.h index 3b056b8c48..05eea9d544 100644 --- a/src/analysis/AverageVessel.h +++ b/src/analysis/AverageVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/ClassicalMultiDimensionalScaling.cpp b/src/analysis/ClassicalMultiDimensionalScaling.cpp index 93bb25f1d4..ac342a0cef 100644 --- a/src/analysis/ClassicalMultiDimensionalScaling.cpp +++ b/src/analysis/ClassicalMultiDimensionalScaling.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/ClassicalScaling.cpp b/src/analysis/ClassicalScaling.cpp index e7c911eeef..a80883a9f3 100644 --- a/src/analysis/ClassicalScaling.cpp +++ b/src/analysis/ClassicalScaling.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/Commit.cpp b/src/analysis/Commit.cpp index 5cbacf4db1..1b7a3ccf68 100644 --- a/src/analysis/Commit.cpp +++ b/src/analysis/Commit.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/Histogram.cpp b/src/analysis/Histogram.cpp index 9c8fc13757..ba21ec691c 100644 --- a/src/analysis/Histogram.cpp +++ b/src/analysis/Histogram.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/LandmarkRegister.cpp b/src/analysis/LandmarkRegister.cpp index b612d38fed..06fac779f8 100644 --- a/src/analysis/LandmarkRegister.cpp +++ b/src/analysis/LandmarkRegister.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/LandmarkRegister.h b/src/analysis/LandmarkRegister.h index dd4c5d38d9..fa54680f20 100644 --- a/src/analysis/LandmarkRegister.h +++ b/src/analysis/LandmarkRegister.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/LandmarkSelectionBase.cpp b/src/analysis/LandmarkSelectionBase.cpp index 5bd8f7e60f..7602b9bc77 100644 --- a/src/analysis/LandmarkSelectionBase.cpp +++ b/src/analysis/LandmarkSelectionBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/LandmarkSelectionBase.h b/src/analysis/LandmarkSelectionBase.h index a8300ff107..2eea0c3565 100644 --- a/src/analysis/LandmarkSelectionBase.h +++ b/src/analysis/LandmarkSelectionBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/analysis/SelectAllFrames.cpp b/src/analysis/SelectAllFrames.cpp index 8f61b7305d..2190a5603f 100644 --- a/src/analysis/SelectAllFrames.cpp +++ b/src/analysis/SelectAllFrames.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ABMD.cpp b/src/bias/ABMD.cpp index 5e8bef344e..1fdedf3240 100644 --- a/src/bias/ABMD.cpp +++ b/src/bias/ABMD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/Bias.cpp b/src/bias/Bias.cpp index 4075e3433e..4d5c9ba5ef 100644 --- a/src/bias/Bias.cpp +++ b/src/bias/Bias.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/Bias.h b/src/bias/Bias.h index 25776466f4..776138e900 100644 --- a/src/bias/Bias.h +++ b/src/bias/Bias.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/BiasValue.cpp b/src/bias/BiasValue.cpp index 3e77621a55..f6a0b80a6c 100644 --- a/src/bias/BiasValue.cpp +++ b/src/bias/BiasValue.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ExtendedLagrangian.cpp b/src/bias/ExtendedLagrangian.cpp index 85de570dd5..ff768b6409 100644 --- a/src/bias/ExtendedLagrangian.cpp +++ b/src/bias/ExtendedLagrangian.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/External.cpp b/src/bias/External.cpp index 62bc54cf92..4a1a6befa6 100644 --- a/src/bias/External.cpp +++ b/src/bias/External.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/LWalls.cpp b/src/bias/LWalls.cpp index 33d7f7c046..5f05d124bd 100644 --- a/src/bias/LWalls.cpp +++ b/src/bias/LWalls.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/Metainference.cpp b/src/bias/Metainference.cpp index e4d3e8b94f..11e0abc019 100644 --- a/src/bias/Metainference.cpp +++ b/src/bias/Metainference.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/MovingRestraint.cpp b/src/bias/MovingRestraint.cpp index 13cafce97e..ae9f1c5fe2 100644 --- a/src/bias/MovingRestraint.cpp +++ b/src/bias/MovingRestraint.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/PBMetaD.cpp b/src/bias/PBMetaD.cpp index 7d00eebd93..5840eee82b 100644 --- a/src/bias/PBMetaD.cpp +++ b/src/bias/PBMetaD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/Restraint.cpp b/src/bias/Restraint.cpp index 8bb3df2027..76a963fefe 100644 --- a/src/bias/Restraint.cpp +++ b/src/bias/Restraint.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ReweightBase.cpp b/src/bias/ReweightBase.cpp index bfb5ddede4..b3567cec3c 100644 --- a/src/bias/ReweightBase.cpp +++ b/src/bias/ReweightBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ReweightBase.h b/src/bias/ReweightBase.h index f39e94d705..32d15892cd 100644 --- a/src/bias/ReweightBase.h +++ b/src/bias/ReweightBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ReweightBias.cpp b/src/bias/ReweightBias.cpp index d0b2d90a3e..26a43610bd 100644 --- a/src/bias/ReweightBias.cpp +++ b/src/bias/ReweightBias.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ReweightMetad.cpp b/src/bias/ReweightMetad.cpp index 766ed40dfc..7c646db48f 100644 --- a/src/bias/ReweightMetad.cpp +++ b/src/bias/ReweightMetad.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/ReweightTemperature.cpp b/src/bias/ReweightTemperature.cpp index 203d4930ef..6c219bbf1a 100644 --- a/src/bias/ReweightTemperature.cpp +++ b/src/bias/ReweightTemperature.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/bias/UWalls.cpp b/src/bias/UWalls.cpp index 0f096f11b1..172f6bdd99 100644 --- a/src/bias/UWalls.cpp +++ b/src/bias/UWalls.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/CLTool.h b/src/cltools/CLTool.h index 3d5adbbc53..b4ad6e31bb 100644 --- a/src/cltools/CLTool.h +++ b/src/cltools/CLTool.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/DriverDouble.cpp b/src/cltools/DriverDouble.cpp index 4ef9a46d2b..7cac3b4a3d 100644 --- a/src/cltools/DriverDouble.cpp +++ b/src/cltools/DriverDouble.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/DriverFloat.cpp b/src/cltools/DriverFloat.cpp index d410866dab..b7705e000c 100644 --- a/src/cltools/DriverFloat.cpp +++ b/src/cltools/DriverFloat.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/GenTemplate.cpp b/src/cltools/GenTemplate.cpp index bce33af848..8df42b9f63 100644 --- a/src/cltools/GenTemplate.cpp +++ b/src/cltools/GenTemplate.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/Info.cpp b/src/cltools/Info.cpp index fe9c1e1923..1a78a2e50b 100644 --- a/src/cltools/Info.cpp +++ b/src/cltools/Info.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/Manual.cpp b/src/cltools/Manual.cpp index 4df53a6962..00ed022d3c 100644 --- a/src/cltools/Manual.cpp +++ b/src/cltools/Manual.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/SimpleMD.cpp b/src/cltools/SimpleMD.cpp index d94f89b8f7..78a938fa55 100644 --- a/src/cltools/SimpleMD.cpp +++ b/src/cltools/SimpleMD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/SumHills.cpp b/src/cltools/SumHills.cpp index ffdc518743..0dd09dee8b 100644 --- a/src/cltools/SumHills.cpp +++ b/src/cltools/SumHills.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/cltools/kT.cpp b/src/cltools/kT.cpp index b1e25b4b8a..57760a93b9 100644 --- a/src/cltools/kT.cpp +++ b/src/cltools/kT.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Angle.cpp b/src/colvar/Angle.cpp index ed57d03ea5..543c9b731c 100644 --- a/src/colvar/Angle.cpp +++ b/src/colvar/Angle.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Cell.cpp b/src/colvar/Cell.cpp index 5c59e9f49d..266bb0393f 100644 --- a/src/colvar/Cell.cpp +++ b/src/colvar/Cell.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Colvar.h b/src/colvar/Colvar.h index 2d8904d64d..50360ef87f 100644 --- a/src/colvar/Colvar.h +++ b/src/colvar/Colvar.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Constant.cpp b/src/colvar/Constant.cpp index 49423413df..c74f7f6a1f 100644 --- a/src/colvar/Constant.cpp +++ b/src/colvar/Constant.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/ContactMap.cpp b/src/colvar/ContactMap.cpp index 9405f172f4..f39a80bc05 100644 --- a/src/colvar/ContactMap.cpp +++ b/src/colvar/ContactMap.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Coordination.cpp b/src/colvar/Coordination.cpp index c1aa2da4f2..c430bb082b 100644 --- a/src/colvar/Coordination.cpp +++ b/src/colvar/Coordination.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/CoordinationBase.cpp b/src/colvar/CoordinationBase.cpp index 2d1c6707a1..89c6ec2cf6 100644 --- a/src/colvar/CoordinationBase.cpp +++ b/src/colvar/CoordinationBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/CoordinationBase.h b/src/colvar/CoordinationBase.h index 6b0f174cd3..4fb118639f 100644 --- a/src/colvar/CoordinationBase.h +++ b/src/colvar/CoordinationBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/DHEnergy.cpp b/src/colvar/DHEnergy.cpp index 23ed21d58d..29d03589b2 100644 --- a/src/colvar/DHEnergy.cpp +++ b/src/colvar/DHEnergy.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/DRMSD.cpp b/src/colvar/DRMSD.cpp index 5a3152ad45..ee5f898745 100644 --- a/src/colvar/DRMSD.cpp +++ b/src/colvar/DRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Dipole.cpp b/src/colvar/Dipole.cpp index 09a4a65800..166dbf68fc 100644 --- a/src/colvar/Dipole.cpp +++ b/src/colvar/Dipole.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Distance.cpp b/src/colvar/Distance.cpp index c3a9817715..33ec593cc3 100644 --- a/src/colvar/Distance.cpp +++ b/src/colvar/Distance.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Energy.cpp b/src/colvar/Energy.cpp index 11e2532e0e..891285e146 100644 --- a/src/colvar/Energy.cpp +++ b/src/colvar/Energy.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Fake.cpp b/src/colvar/Fake.cpp index 70bd7f2789..5cc2fd79cc 100644 --- a/src/colvar/Fake.cpp +++ b/src/colvar/Fake.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/FretEfficiency.cpp b/src/colvar/FretEfficiency.cpp index 02600e1057..ca48e5e58a 100644 --- a/src/colvar/FretEfficiency.cpp +++ b/src/colvar/FretEfficiency.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Gyration.cpp b/src/colvar/Gyration.cpp index 5cf35aea06..da8671af05 100644 --- a/src/colvar/Gyration.cpp +++ b/src/colvar/Gyration.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Jcoupling.cpp b/src/colvar/Jcoupling.cpp index d192b8bbd6..94e5b82a0b 100644 --- a/src/colvar/Jcoupling.cpp +++ b/src/colvar/Jcoupling.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/MultiRMSD.cpp b/src/colvar/MultiRMSD.cpp index 7656c232be..2f27f6341f 100644 --- a/src/colvar/MultiRMSD.cpp +++ b/src/colvar/MultiRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/NOE.cpp b/src/colvar/NOE.cpp index 82d2b4372a..69d9a3797c 100644 --- a/src/colvar/NOE.cpp +++ b/src/colvar/NOE.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/PCARMSD.cpp b/src/colvar/PCARMSD.cpp index f5d1cf6f2c..69e5f3bdce 100644 --- a/src/colvar/PCARMSD.cpp +++ b/src/colvar/PCARMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/PRE.cpp b/src/colvar/PRE.cpp index 906826b1f5..2a48386272 100644 --- a/src/colvar/PRE.cpp +++ b/src/colvar/PRE.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/PathMSD.cpp b/src/colvar/PathMSD.cpp index cdfd96ee1d..86fb1deda3 100644 --- a/src/colvar/PathMSD.cpp +++ b/src/colvar/PathMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/PathMSDBase.cpp b/src/colvar/PathMSDBase.cpp index 9f33b1fe6d..a0d107453e 100644 --- a/src/colvar/PathMSDBase.cpp +++ b/src/colvar/PathMSDBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/PathMSDBase.h b/src/colvar/PathMSDBase.h index dae1603cb5..ff5f138467 100644 --- a/src/colvar/PathMSDBase.h +++ b/src/colvar/PathMSDBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Position.cpp b/src/colvar/Position.cpp index a381e039e0..fba9df1dbc 100644 --- a/src/colvar/Position.cpp +++ b/src/colvar/Position.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/PropertyMap.cpp b/src/colvar/PropertyMap.cpp index a8a21fef20..7ecb08b0cd 100644 --- a/src/colvar/PropertyMap.cpp +++ b/src/colvar/PropertyMap.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Puckering.cpp b/src/colvar/Puckering.cpp index 1ac5f6a101..b9a0642149 100644 --- a/src/colvar/Puckering.cpp +++ b/src/colvar/Puckering.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/RDC.cpp b/src/colvar/RDC.cpp index 18db380141..067ea3f2cd 100644 --- a/src/colvar/RDC.cpp +++ b/src/colvar/RDC.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/RMSD.cpp b/src/colvar/RMSD.cpp index bca340c78f..bdc9b4ac56 100644 --- a/src/colvar/RMSD.cpp +++ b/src/colvar/RMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Template.cpp b/src/colvar/Template.cpp index 85cb95d27e..d22383b2b0 100644 --- a/src/colvar/Template.cpp +++ b/src/colvar/Template.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/colvar/Volume.cpp b/src/colvar/Volume.cpp index 7b4fb9aacf..2a388d778b 100644 --- a/src/colvar/Volume.cpp +++ b/src/colvar/Volume.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/config/Config.h b/src/config/Config.h index 39c441e98d..4b8d2cd074 100644 --- a/src/config/Config.h +++ b/src/config/Config.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/config/Config.inc.in b/src/config/Config.inc.in index 6596895588..e5a9e9bd31 100644 --- a/src/config/Config.inc.in +++ b/src/config/Config.inc.in @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/Action.cpp b/src/core/Action.cpp index 4db8c1f296..f54c3a7526 100644 --- a/src/core/Action.cpp +++ b/src/core/Action.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/Action.h b/src/core/Action.h index 6641498ae9..89cea1f6e4 100644 --- a/src/core/Action.h +++ b/src/core/Action.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionAtomistic.cpp b/src/core/ActionAtomistic.cpp index 28e093f99a..d6d51d47de 100644 --- a/src/core/ActionAtomistic.cpp +++ b/src/core/ActionAtomistic.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionPilot.cpp b/src/core/ActionPilot.cpp index 96d312115c..c1a42f83f6 100644 --- a/src/core/ActionPilot.cpp +++ b/src/core/ActionPilot.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionPilot.h b/src/core/ActionPilot.h index 069c18c968..87cc21bcae 100644 --- a/src/core/ActionPilot.h +++ b/src/core/ActionPilot.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionRegister.cpp b/src/core/ActionRegister.cpp index c5f9e16b99..70ccf01de3 100644 --- a/src/core/ActionRegister.cpp +++ b/src/core/ActionRegister.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionRegister.h b/src/core/ActionRegister.h index bcce7ccfa4..b5be9b17ee 100644 --- a/src/core/ActionRegister.h +++ b/src/core/ActionRegister.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionSet.cpp b/src/core/ActionSet.cpp index 6bec94646d..cab0b7144f 100644 --- a/src/core/ActionSet.cpp +++ b/src/core/ActionSet.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionSet.h b/src/core/ActionSet.h index 0273d53829..5fa4ac9f4a 100644 --- a/src/core/ActionSet.h +++ b/src/core/ActionSet.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionSetup.cpp b/src/core/ActionSetup.cpp index 0c6903efba..2dc1d9a085 100644 --- a/src/core/ActionSetup.cpp +++ b/src/core/ActionSetup.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionSetup.h b/src/core/ActionSetup.h index d76a0bea1a..b02937f92f 100644 --- a/src/core/ActionSetup.h +++ b/src/core/ActionSetup.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionWithArguments.cpp b/src/core/ActionWithArguments.cpp index a90b64ecb9..e4dc90f79b 100644 --- a/src/core/ActionWithArguments.cpp +++ b/src/core/ActionWithArguments.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionWithArguments.h b/src/core/ActionWithArguments.h index 47a14b7607..406dcff8b4 100644 --- a/src/core/ActionWithArguments.h +++ b/src/core/ActionWithArguments.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionWithValue.cpp b/src/core/ActionWithValue.cpp index bc92a9410d..7c4f7bf6a8 100644 --- a/src/core/ActionWithValue.cpp +++ b/src/core/ActionWithValue.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionWithValue.h b/src/core/ActionWithValue.h index 9d13f30d17..cfc666c2a6 100644 --- a/src/core/ActionWithValue.h +++ b/src/core/ActionWithValue.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionWithVirtualAtom.cpp b/src/core/ActionWithVirtualAtom.cpp index 681b4b3ffb..01a566d768 100644 --- a/src/core/ActionWithVirtualAtom.cpp +++ b/src/core/ActionWithVirtualAtom.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ActionWithVirtualAtom.h b/src/core/ActionWithVirtualAtom.h index 74bf868ae1..d2ddd24e9e 100644 --- a/src/core/ActionWithVirtualAtom.h +++ b/src/core/ActionWithVirtualAtom.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/CLTool.cpp b/src/core/CLTool.cpp index c7441d41ed..65b1b1b2fa 100644 --- a/src/core/CLTool.cpp +++ b/src/core/CLTool.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/CLTool.h b/src/core/CLTool.h index c9ab30778e..bf2ab2c58a 100644 --- a/src/core/CLTool.h +++ b/src/core/CLTool.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/CLToolMain.cpp b/src/core/CLToolMain.cpp index 174f1f611d..64fcd48f78 100644 --- a/src/core/CLToolMain.cpp +++ b/src/core/CLToolMain.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/CLToolMain.h b/src/core/CLToolMain.h index a8cdb42e29..a624acc977 100644 --- a/src/core/CLToolMain.h +++ b/src/core/CLToolMain.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/CLToolRegister.cpp b/src/core/CLToolRegister.cpp index 3143e02e7d..8a608aef9c 100644 --- a/src/core/CLToolRegister.cpp +++ b/src/core/CLToolRegister.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/CLToolRegister.h b/src/core/CLToolRegister.h index 4de2cb64e7..34a719bd52 100644 --- a/src/core/CLToolRegister.h +++ b/src/core/CLToolRegister.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/Colvar.cpp b/src/core/Colvar.cpp index 239afdc8d3..963d236338 100644 --- a/src/core/Colvar.cpp +++ b/src/core/Colvar.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/Colvar.h b/src/core/Colvar.h index 4a7ef6a08b..31bd861f22 100644 --- a/src/core/Colvar.h +++ b/src/core/Colvar.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ExchangePatterns.cpp b/src/core/ExchangePatterns.cpp index fdd22e74ec..65af708174 100644 --- a/src/core/ExchangePatterns.cpp +++ b/src/core/ExchangePatterns.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/ExchangePatterns.h b/src/core/ExchangePatterns.h index 14099be4da..97481208d8 100644 --- a/src/core/ExchangePatterns.h +++ b/src/core/ExchangePatterns.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/FlexibleBin.cpp b/src/core/FlexibleBin.cpp index 6160d77999..a07a0cb29e 100644 --- a/src/core/FlexibleBin.cpp +++ b/src/core/FlexibleBin.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/FlexibleBin.h b/src/core/FlexibleBin.h index 658a6fe3e3..b495cbcd6b 100644 --- a/src/core/FlexibleBin.h +++ b/src/core/FlexibleBin.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/GREX.cpp b/src/core/GREX.cpp index c5e4993dad..d7ddaa8d33 100644 --- a/src/core/GREX.cpp +++ b/src/core/GREX.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/GREX.h b/src/core/GREX.h index 2266d1581f..58f181cbef 100644 --- a/src/core/GREX.h +++ b/src/core/GREX.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/MDAtoms.cpp b/src/core/MDAtoms.cpp index 1f11ad9cd4..370527d2fb 100644 --- a/src/core/MDAtoms.cpp +++ b/src/core/MDAtoms.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/PlumedMainInitializer.cpp b/src/core/PlumedMainInitializer.cpp index b7fc8e3e45..7205dea3f6 100644 --- a/src/core/PlumedMainInitializer.cpp +++ b/src/core/PlumedMainInitializer.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/SetupMolInfo.cpp b/src/core/SetupMolInfo.cpp index ece94a7f09..eff9c98d3c 100644 --- a/src/core/SetupMolInfo.cpp +++ b/src/core/SetupMolInfo.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/SetupMolInfo.h b/src/core/SetupMolInfo.h index 362073b8bd..2f4341d6a5 100644 --- a/src/core/SetupMolInfo.h +++ b/src/core/SetupMolInfo.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/TargetDist.cpp b/src/core/TargetDist.cpp index 1bed184498..62a451eacd 100644 --- a/src/core/TargetDist.cpp +++ b/src/core/TargetDist.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/TargetDist.h b/src/core/TargetDist.h index f90b8a4be2..bd91bfaa03 100644 --- a/src/core/TargetDist.h +++ b/src/core/TargetDist.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/Value.cpp b/src/core/Value.cpp index 62fb26c51a..debd7984e7 100644 --- a/src/core/Value.cpp +++ b/src/core/Value.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/Value.h b/src/core/Value.h index 6bbd9b6cee..1564a6231f 100644 --- a/src/core/Value.h +++ b/src/core/Value.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/core/WithCmd.h b/src/core/WithCmd.h index 0397c2e5c7..1edac40d58 100644 --- a/src/core/WithCmd.h +++ b/src/core/WithCmd.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/CubicHarmonicBase.cpp b/src/crystallization/CubicHarmonicBase.cpp index a51b066d6b..895a27f181 100644 --- a/src/crystallization/CubicHarmonicBase.cpp +++ b/src/crystallization/CubicHarmonicBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/CubicHarmonicBase.h b/src/crystallization/CubicHarmonicBase.h index 8faf993df6..fd3b3bad48 100644 --- a/src/crystallization/CubicHarmonicBase.h +++ b/src/crystallization/CubicHarmonicBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Fccubic.cpp b/src/crystallization/Fccubic.cpp index fc1793ab39..8296cd66d2 100644 --- a/src/crystallization/Fccubic.cpp +++ b/src/crystallization/Fccubic.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Gradient.cpp b/src/crystallization/Gradient.cpp index 173d9e5adb..6348a7b0b9 100644 --- a/src/crystallization/Gradient.cpp +++ b/src/crystallization/Gradient.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Gradient.h b/src/crystallization/Gradient.h index e639a84587..3132c2752a 100644 --- a/src/crystallization/Gradient.h +++ b/src/crystallization/Gradient.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/GradientVessel.cpp b/src/crystallization/GradientVessel.cpp index a266bbf019..d0a6296238 100644 --- a/src/crystallization/GradientVessel.cpp +++ b/src/crystallization/GradientVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/InterMolecularTorsions.cpp b/src/crystallization/InterMolecularTorsions.cpp index d350038d8e..afbf689701 100644 --- a/src/crystallization/InterMolecularTorsions.cpp +++ b/src/crystallization/InterMolecularTorsions.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/LocalSteinhardt.h b/src/crystallization/LocalSteinhardt.h index c7ced6ab35..3fca53a9b7 100644 --- a/src/crystallization/LocalSteinhardt.h +++ b/src/crystallization/LocalSteinhardt.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/MoleculeOrientation.cpp b/src/crystallization/MoleculeOrientation.cpp index 0923a8d0ad..ab8c757e0d 100644 --- a/src/crystallization/MoleculeOrientation.cpp +++ b/src/crystallization/MoleculeOrientation.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/MoleculePlane.cpp b/src/crystallization/MoleculePlane.cpp index 62e3f13d9b..8ad967c85f 100644 --- a/src/crystallization/MoleculePlane.cpp +++ b/src/crystallization/MoleculePlane.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp index 1f0dc49697..50bb6e25fa 100644 --- a/src/crystallization/OrientationSphere.cpp +++ b/src/crystallization/OrientationSphere.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/OrientationSphere.h b/src/crystallization/OrientationSphere.h index 616f2b49b6..f25a14f7a7 100644 --- a/src/crystallization/OrientationSphere.h +++ b/src/crystallization/OrientationSphere.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Q3.cpp b/src/crystallization/Q3.cpp index 6c3aeedc2f..33d4ed991f 100644 --- a/src/crystallization/Q3.cpp +++ b/src/crystallization/Q3.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Q4.cpp b/src/crystallization/Q4.cpp index fa76b0d10e..2dd578a2a9 100644 --- a/src/crystallization/Q4.cpp +++ b/src/crystallization/Q4.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Q6.cpp b/src/crystallization/Q6.cpp index 447b0e1cb4..daea730c7d 100644 --- a/src/crystallization/Q6.cpp +++ b/src/crystallization/Q6.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/SMAC.cpp b/src/crystallization/SMAC.cpp index ce83df7380..6d1d8bf799 100644 --- a/src/crystallization/SMAC.cpp +++ b/src/crystallization/SMAC.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/SimpleCubic.cpp b/src/crystallization/SimpleCubic.cpp index c7acc9f195..9fc63d9096 100644 --- a/src/crystallization/SimpleCubic.cpp +++ b/src/crystallization/SimpleCubic.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp index 0cfeb44757..f36c436eda 100644 --- a/src/crystallization/Steinhardt.cpp +++ b/src/crystallization/Steinhardt.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/Tetrahedral.cpp b/src/crystallization/Tetrahedral.cpp index 616cf766bf..f5c6f873cd 100644 --- a/src/crystallization/Tetrahedral.cpp +++ b/src/crystallization/Tetrahedral.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/VectorMean.cpp b/src/crystallization/VectorMean.cpp index 26f7080906..a4e6a3c77d 100644 --- a/src/crystallization/VectorMean.cpp +++ b/src/crystallization/VectorMean.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/VectorMultiColvar.cpp b/src/crystallization/VectorMultiColvar.cpp index 943e1edf0b..012087f7e3 100644 --- a/src/crystallization/VectorMultiColvar.cpp +++ b/src/crystallization/VectorMultiColvar.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/VectorMultiColvar.h b/src/crystallization/VectorMultiColvar.h index 8646f2d60b..679d4e77cc 100644 --- a/src/crystallization/VectorMultiColvar.h +++ b/src/crystallization/VectorMultiColvar.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/crystallization/VectorSum.cpp b/src/crystallization/VectorSum.cpp index 0eb8744f0c..d6ff9574dd 100644 --- a/src/crystallization/VectorSum.cpp +++ b/src/crystallization/VectorSum.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Combine.cpp b/src/function/Combine.cpp index e76ed7b8bb..b74e160142 100644 --- a/src/function/Combine.cpp +++ b/src/function/Combine.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Ensemble.cpp b/src/function/Ensemble.cpp index 9976c25015..b6b26b1c3b 100644 --- a/src/function/Ensemble.cpp +++ b/src/function/Ensemble.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/FuncPathMSD.cpp b/src/function/FuncPathMSD.cpp index aa38d1db10..2020c0158b 100644 --- a/src/function/FuncPathMSD.cpp +++ b/src/function/FuncPathMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/FuncSumHills.cpp b/src/function/FuncSumHills.cpp index b22e9c18ff..4ffcc29e42 100644 --- a/src/function/FuncSumHills.cpp +++ b/src/function/FuncSumHills.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Function.cpp b/src/function/Function.cpp index 0852d31810..0f920c66f5 100644 --- a/src/function/Function.cpp +++ b/src/function/Function.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Function.h b/src/function/Function.h index 02215e1cce..44cbe9a2a4 100644 --- a/src/function/Function.h +++ b/src/function/Function.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/LocalEnsemble.cpp b/src/function/LocalEnsemble.cpp index 6e3bd96f68..e623be76a0 100644 --- a/src/function/LocalEnsemble.cpp +++ b/src/function/LocalEnsemble.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Matheval.cpp b/src/function/Matheval.cpp index 59e6e9bf05..c03983c12f 100644 --- a/src/function/Matheval.cpp +++ b/src/function/Matheval.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Piecewise.cpp b/src/function/Piecewise.cpp index e0f4bbd52a..e3e147b69c 100644 --- a/src/function/Piecewise.cpp +++ b/src/function/Piecewise.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Sort.cpp b/src/function/Sort.cpp index f1e9b2a717..4636f3ad26 100644 --- a/src/function/Sort.cpp +++ b/src/function/Sort.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Stats.cpp b/src/function/Stats.cpp index 429442e6d8..3513c9dcb8 100644 --- a/src/function/Stats.cpp +++ b/src/function/Stats.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/function/Target.cpp b/src/function/Target.cpp index 5ce9124956..7f5fbf0bb8 100644 --- a/src/function/Target.cpp +++ b/src/function/Target.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Debug.cpp b/src/generic/Debug.cpp index 790b5a3794..0496e4f0cf 100644 --- a/src/generic/Debug.cpp +++ b/src/generic/Debug.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/DumpAtoms.cpp b/src/generic/DumpAtoms.cpp index 2123ee0157..e1cd7b927b 100644 --- a/src/generic/DumpAtoms.cpp +++ b/src/generic/DumpAtoms.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/DumpDerivatives.cpp b/src/generic/DumpDerivatives.cpp index c74343aca0..7c1075cf11 100644 --- a/src/generic/DumpDerivatives.cpp +++ b/src/generic/DumpDerivatives.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/DumpForces.cpp b/src/generic/DumpForces.cpp index f5e204d65b..4a6aa3efb2 100644 --- a/src/generic/DumpForces.cpp +++ b/src/generic/DumpForces.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/DumpMassCharge.cpp b/src/generic/DumpMassCharge.cpp index 4153bc8384..c685bc9156 100644 --- a/src/generic/DumpMassCharge.cpp +++ b/src/generic/DumpMassCharge.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/DumpProjections.cpp b/src/generic/DumpProjections.cpp index 3f0d404297..8c17707f0a 100644 --- a/src/generic/DumpProjections.cpp +++ b/src/generic/DumpProjections.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/EffectiveEnergyDrift.cpp b/src/generic/EffectiveEnergyDrift.cpp index 1c3961390a..68f315c0a9 100644 --- a/src/generic/EffectiveEnergyDrift.cpp +++ b/src/generic/EffectiveEnergyDrift.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Flush.cpp b/src/generic/Flush.cpp index c8d008c87d..e05159a036 100644 --- a/src/generic/Flush.cpp +++ b/src/generic/Flush.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Group.cpp b/src/generic/Group.cpp index ecd562e8ff..1625e15e8e 100644 --- a/src/generic/Group.cpp +++ b/src/generic/Group.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Include.cpp b/src/generic/Include.cpp index 664c84ba67..f9984e5899 100644 --- a/src/generic/Include.cpp +++ b/src/generic/Include.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Print.cpp b/src/generic/Print.cpp index 2a87d1f7ba..8542a978c9 100644 --- a/src/generic/Print.cpp +++ b/src/generic/Print.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/RandomExchanges.cpp b/src/generic/RandomExchanges.cpp index be36873bcc..adc8557ca0 100644 --- a/src/generic/RandomExchanges.cpp +++ b/src/generic/RandomExchanges.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Read.cpp b/src/generic/Read.cpp index 88c2796300..20ea7845b4 100644 --- a/src/generic/Read.cpp +++ b/src/generic/Read.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/ResetCell.cpp b/src/generic/ResetCell.cpp index fd14c1fe10..a33a3cffe4 100644 --- a/src/generic/ResetCell.cpp +++ b/src/generic/ResetCell.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/Time.cpp b/src/generic/Time.cpp index 3512cb53da..9826b045fa 100644 --- a/src/generic/Time.cpp +++ b/src/generic/Time.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/UpdateIf.cpp b/src/generic/UpdateIf.cpp index 2d067fcf3d..086007f0ce 100644 --- a/src/generic/UpdateIf.cpp +++ b/src/generic/UpdateIf.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/WholeMolecules.cpp b/src/generic/WholeMolecules.cpp index 12e9c82813..768d07d623 100644 --- a/src/generic/WholeMolecules.cpp +++ b/src/generic/WholeMolecules.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/generic/WrapAround.cpp b/src/generic/WrapAround.cpp index 946a060fde..8d65a1c6ff 100644 --- a/src/generic/WrapAround.cpp +++ b/src/generic/WrapAround.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ActionWithGrid.cpp b/src/gridtools/ActionWithGrid.cpp index d959d18743..10243e55ac 100644 --- a/src/gridtools/ActionWithGrid.cpp +++ b/src/gridtools/ActionWithGrid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ActionWithGrid.h b/src/gridtools/ActionWithGrid.h index 342bfd067d..a9d3f7e977 100644 --- a/src/gridtools/ActionWithGrid.h +++ b/src/gridtools/ActionWithGrid.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ActionWithInputGrid.cpp b/src/gridtools/ActionWithInputGrid.cpp index 4179370723..bb5207ab3f 100644 --- a/src/gridtools/ActionWithInputGrid.cpp +++ b/src/gridtools/ActionWithInputGrid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ActionWithInputGrid.h b/src/gridtools/ActionWithInputGrid.h index db87e1f0e5..38ccf9f7b7 100644 --- a/src/gridtools/ActionWithInputGrid.h +++ b/src/gridtools/ActionWithInputGrid.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/AverageOnGrid.cpp b/src/gridtools/AverageOnGrid.cpp index 0f9c5cc737..c14843d703 100644 --- a/src/gridtools/AverageOnGrid.cpp +++ b/src/gridtools/AverageOnGrid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ContourFindingBase.cpp b/src/gridtools/ContourFindingBase.cpp index 3188da8f66..566ec5bdb1 100644 --- a/src/gridtools/ContourFindingBase.cpp +++ b/src/gridtools/ContourFindingBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ContourFindingBase.h b/src/gridtools/ContourFindingBase.h index 38a5a4fc43..7b3063012c 100644 --- a/src/gridtools/ContourFindingBase.h +++ b/src/gridtools/ContourFindingBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/ConvertToFES.cpp b/src/gridtools/ConvertToFES.cpp index 4e3bbdf170..b419a66c1d 100644 --- a/src/gridtools/ConvertToFES.cpp +++ b/src/gridtools/ConvertToFES.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/DumpCube.cpp b/src/gridtools/DumpCube.cpp index 59745a17af..4747073750 100644 --- a/src/gridtools/DumpCube.cpp +++ b/src/gridtools/DumpCube.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/DumpGrid.cpp b/src/gridtools/DumpGrid.cpp index bc8f4ce3a5..fca2512d4a 100644 --- a/src/gridtools/DumpGrid.cpp +++ b/src/gridtools/DumpGrid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/FindContour.cpp b/src/gridtools/FindContour.cpp index bee14ed555..677c4b2789 100644 --- a/src/gridtools/FindContour.cpp +++ b/src/gridtools/FindContour.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/FindContourSurface.cpp b/src/gridtools/FindContourSurface.cpp index 5aeddd073d..8ffcaa7168 100644 --- a/src/gridtools/FindContourSurface.cpp +++ b/src/gridtools/FindContourSurface.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/FindSphericalContour.cpp b/src/gridtools/FindSphericalContour.cpp index b65761523b..e714dcadfa 100644 --- a/src/gridtools/FindSphericalContour.cpp +++ b/src/gridtools/FindSphericalContour.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/FourierTransform.cpp b/src/gridtools/FourierTransform.cpp index 5a53b390de..d8509b27d2 100644 --- a/src/gridtools/FourierTransform.cpp +++ b/src/gridtools/FourierTransform.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/GridPrintingBase.cpp b/src/gridtools/GridPrintingBase.cpp index 7a0c6743fc..f09edd59ac 100644 --- a/src/gridtools/GridPrintingBase.cpp +++ b/src/gridtools/GridPrintingBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/GridPrintingBase.h b/src/gridtools/GridPrintingBase.h index d33865d73b..6a93b78b15 100644 --- a/src/gridtools/GridPrintingBase.h +++ b/src/gridtools/GridPrintingBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/GridVessel.h b/src/gridtools/GridVessel.h index 7458c6605e..844a73022e 100644 --- a/src/gridtools/GridVessel.h +++ b/src/gridtools/GridVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index ea6fb7c797..0c1c19c407 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/HistogramOnGrid.h b/src/gridtools/HistogramOnGrid.h index 351c6a182e..65c23737ce 100644 --- a/src/gridtools/HistogramOnGrid.h +++ b/src/gridtools/HistogramOnGrid.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/InterpolateGrid.cpp b/src/gridtools/InterpolateGrid.cpp index e8f97c0d4a..8166678673 100644 --- a/src/gridtools/InterpolateGrid.cpp +++ b/src/gridtools/InterpolateGrid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/main/main.cpp b/src/main/main.cpp index 4e3d6376cd..03825a867a 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/manyrestraints/ManyRestraintsBase.cpp b/src/manyrestraints/ManyRestraintsBase.cpp index d13d51cfac..39e0b553f1 100644 --- a/src/manyrestraints/ManyRestraintsBase.cpp +++ b/src/manyrestraints/ManyRestraintsBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/manyrestraints/ManyRestraintsBase.h b/src/manyrestraints/ManyRestraintsBase.h index 565ea340df..fc60c965e3 100644 --- a/src/manyrestraints/ManyRestraintsBase.h +++ b/src/manyrestraints/ManyRestraintsBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/manyrestraints/UWalls.cpp b/src/manyrestraints/UWalls.cpp index f4c75f0d89..293ac09527 100644 --- a/src/manyrestraints/UWalls.cpp +++ b/src/manyrestraints/UWalls.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/Mapping.cpp b/src/mapping/Mapping.cpp index 1a5ac96eca..718eba8381 100644 --- a/src/mapping/Mapping.cpp +++ b/src/mapping/Mapping.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/Mapping.h b/src/mapping/Mapping.h index 35dd617618..df83a1ef67 100644 --- a/src/mapping/Mapping.h +++ b/src/mapping/Mapping.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/PCAVars.cpp b/src/mapping/PCAVars.cpp index b8d51d7c80..31e1257589 100644 --- a/src/mapping/PCAVars.cpp +++ b/src/mapping/PCAVars.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/Path.cpp b/src/mapping/Path.cpp index 0372e0ebd2..bd0d1cbe68 100644 --- a/src/mapping/Path.cpp +++ b/src/mapping/Path.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/PathBase.cpp b/src/mapping/PathBase.cpp index 87bd7fc52d..62c6dc1563 100644 --- a/src/mapping/PathBase.cpp +++ b/src/mapping/PathBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/PathBase.h b/src/mapping/PathBase.h index ab98922f66..dbddfad916 100644 --- a/src/mapping/PathBase.h +++ b/src/mapping/PathBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/PropertyMap.cpp b/src/mapping/PropertyMap.cpp index 9da32b47bb..ca5d8827bc 100644 --- a/src/mapping/PropertyMap.cpp +++ b/src/mapping/PropertyMap.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/SpathVessel.cpp b/src/mapping/SpathVessel.cpp index 23271e14f6..51b01fa6e4 100644 --- a/src/mapping/SpathVessel.cpp +++ b/src/mapping/SpathVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/mapping/ZpathVessel.cpp b/src/mapping/ZpathVessel.cpp index 9c8606a8f2..bcc12d06ba 100644 --- a/src/mapping/ZpathVessel.cpp +++ b/src/mapping/ZpathVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/ActionVolume.cpp b/src/multicolvar/ActionVolume.cpp index 5f12881e13..d57f55b682 100644 --- a/src/multicolvar/ActionVolume.cpp +++ b/src/multicolvar/ActionVolume.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/ActionVolume.h b/src/multicolvar/ActionVolume.h index f71cbca394..362c2183f0 100644 --- a/src/multicolvar/ActionVolume.h +++ b/src/multicolvar/ActionVolume.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/AlphaBeta.cpp b/src/multicolvar/AlphaBeta.cpp index 8bedbc355e..5cb86b84b5 100644 --- a/src/multicolvar/AlphaBeta.cpp +++ b/src/multicolvar/AlphaBeta.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/Angles.cpp b/src/multicolvar/Angles.cpp index 2f190d484c..dbefe56818 100644 --- a/src/multicolvar/Angles.cpp +++ b/src/multicolvar/Angles.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/AtomValuePack.cpp b/src/multicolvar/AtomValuePack.cpp index 99a52a8fb5..7dfaa0e41e 100644 --- a/src/multicolvar/AtomValuePack.cpp +++ b/src/multicolvar/AtomValuePack.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/AtomValuePack.h b/src/multicolvar/AtomValuePack.h index c98aa3265f..d9bd42d166 100644 --- a/src/multicolvar/AtomValuePack.h +++ b/src/multicolvar/AtomValuePack.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/Bridge.cpp b/src/multicolvar/Bridge.cpp index 88e562b3a1..1b8b27f936 100644 --- a/src/multicolvar/Bridge.cpp +++ b/src/multicolvar/Bridge.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/BridgedMultiColvarFunction.cpp b/src/multicolvar/BridgedMultiColvarFunction.cpp index ce351d7072..210095d906 100644 --- a/src/multicolvar/BridgedMultiColvarFunction.cpp +++ b/src/multicolvar/BridgedMultiColvarFunction.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/BridgedMultiColvarFunction.h b/src/multicolvar/BridgedMultiColvarFunction.h index 5e285922cc..6df50d3e70 100644 --- a/src/multicolvar/BridgedMultiColvarFunction.h +++ b/src/multicolvar/BridgedMultiColvarFunction.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/CatomPack.cpp b/src/multicolvar/CatomPack.cpp index 900fa5e706..583a48ff48 100644 --- a/src/multicolvar/CatomPack.cpp +++ b/src/multicolvar/CatomPack.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/CatomPack.h b/src/multicolvar/CatomPack.h index 130e971cdb..d5ad04497a 100644 --- a/src/multicolvar/CatomPack.h +++ b/src/multicolvar/CatomPack.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/CenterOfMultiColvar.cpp b/src/multicolvar/CenterOfMultiColvar.cpp index e12021803d..f9668a76a5 100644 --- a/src/multicolvar/CenterOfMultiColvar.cpp +++ b/src/multicolvar/CenterOfMultiColvar.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp index a3823b4887..b830d7f9d5 100644 --- a/src/multicolvar/CoordinationNumbers.cpp +++ b/src/multicolvar/CoordinationNumbers.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/Density.cpp b/src/multicolvar/Density.cpp index 11fcc1f710..bde5853aab 100644 --- a/src/multicolvar/Density.cpp +++ b/src/multicolvar/Density.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/DihedralCorrelation.cpp b/src/multicolvar/DihedralCorrelation.cpp index 5167d7a8b2..f8dde06b91 100644 --- a/src/multicolvar/DihedralCorrelation.cpp +++ b/src/multicolvar/DihedralCorrelation.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/DistanceFromContour.cpp b/src/multicolvar/DistanceFromContour.cpp index 52d8ab1d43..5da6ec4b8c 100644 --- a/src/multicolvar/DistanceFromContour.cpp +++ b/src/multicolvar/DistanceFromContour.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/Distances.cpp b/src/multicolvar/Distances.cpp index 0d5910f75a..97bc0b5d33 100644 --- a/src/multicolvar/Distances.cpp +++ b/src/multicolvar/Distances.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/DumpMultiColvar.cpp b/src/multicolvar/DumpMultiColvar.cpp index 27029a4369..9a12d79d02 100644 --- a/src/multicolvar/DumpMultiColvar.cpp +++ b/src/multicolvar/DumpMultiColvar.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/InPlaneDistances.cpp b/src/multicolvar/InPlaneDistances.cpp index 861337523f..6ed1fb7276 100644 --- a/src/multicolvar/InPlaneDistances.cpp +++ b/src/multicolvar/InPlaneDistances.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index 7f5edf6940..f3cd29dd37 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvar.cpp b/src/multicolvar/MultiColvar.cpp index 0e86d4821f..faee6f0628 100644 --- a/src/multicolvar/MultiColvar.cpp +++ b/src/multicolvar/MultiColvar.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvar.h b/src/multicolvar/MultiColvar.h index 58effe2d34..434468d4e7 100644 --- a/src/multicolvar/MultiColvar.h +++ b/src/multicolvar/MultiColvar.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarBase.cpp b/src/multicolvar/MultiColvarBase.cpp index 6babc9254c..de1598cdfc 100644 --- a/src/multicolvar/MultiColvarBase.cpp +++ b/src/multicolvar/MultiColvarBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarBase.h b/src/multicolvar/MultiColvarBase.h index 98c6b70409..239c3e9e69 100644 --- a/src/multicolvar/MultiColvarBase.h +++ b/src/multicolvar/MultiColvarBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarDensity.cpp b/src/multicolvar/MultiColvarDensity.cpp index 0161a8c006..0612eb7e05 100644 --- a/src/multicolvar/MultiColvarDensity.cpp +++ b/src/multicolvar/MultiColvarDensity.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarFilter.cpp b/src/multicolvar/MultiColvarFilter.cpp index 8d8b0c2be1..1aed479081 100644 --- a/src/multicolvar/MultiColvarFilter.cpp +++ b/src/multicolvar/MultiColvarFilter.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarFilter.h b/src/multicolvar/MultiColvarFilter.h index e6310bf109..5662cbffb3 100644 --- a/src/multicolvar/MultiColvarFilter.h +++ b/src/multicolvar/MultiColvarFilter.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarFunction.cpp b/src/multicolvar/MultiColvarFunction.cpp index 2d32a25cc2..b214e55009 100644 --- a/src/multicolvar/MultiColvarFunction.cpp +++ b/src/multicolvar/MultiColvarFunction.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/MultiColvarFunction.h b/src/multicolvar/MultiColvarFunction.h index c063a03043..32be2a75ea 100644 --- a/src/multicolvar/MultiColvarFunction.h +++ b/src/multicolvar/MultiColvarFunction.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/NumberOfLinks.cpp b/src/multicolvar/NumberOfLinks.cpp index 5d8e89733a..8059ba8357 100644 --- a/src/multicolvar/NumberOfLinks.cpp +++ b/src/multicolvar/NumberOfLinks.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/Torsions.cpp b/src/multicolvar/Torsions.cpp index d97577fbeb..6e72c2e990 100644 --- a/src/multicolvar/Torsions.cpp +++ b/src/multicolvar/Torsions.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeAround.cpp b/src/multicolvar/VolumeAround.cpp index bab79d8e0a..66e7af505e 100644 --- a/src/multicolvar/VolumeAround.cpp +++ b/src/multicolvar/VolumeAround.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeCavity.cpp b/src/multicolvar/VolumeCavity.cpp index af14a2be05..11afa4e927 100644 --- a/src/multicolvar/VolumeCavity.cpp +++ b/src/multicolvar/VolumeCavity.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeGradientBase.cpp b/src/multicolvar/VolumeGradientBase.cpp index a7e351123d..e5de7c105b 100644 --- a/src/multicolvar/VolumeGradientBase.cpp +++ b/src/multicolvar/VolumeGradientBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeGradientBase.h b/src/multicolvar/VolumeGradientBase.h index 31cb5332fc..d561e58cea 100644 --- a/src/multicolvar/VolumeGradientBase.h +++ b/src/multicolvar/VolumeGradientBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeInCylinder.cpp b/src/multicolvar/VolumeInCylinder.cpp index 6e9f636bfe..8d3a06c422 100644 --- a/src/multicolvar/VolumeInCylinder.cpp +++ b/src/multicolvar/VolumeInCylinder.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeInSphere.cpp b/src/multicolvar/VolumeInSphere.cpp index c5f47fc4ae..dc6d633b53 100644 --- a/src/multicolvar/VolumeInSphere.cpp +++ b/src/multicolvar/VolumeInSphere.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/VolumeTetrapore.cpp b/src/multicolvar/VolumeTetrapore.cpp index 98fe915c33..df23afaeee 100644 --- a/src/multicolvar/VolumeTetrapore.cpp +++ b/src/multicolvar/VolumeTetrapore.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/XDistances.cpp b/src/multicolvar/XDistances.cpp index f2a870de19..ed322480aa 100644 --- a/src/multicolvar/XDistances.cpp +++ b/src/multicolvar/XDistances.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/multicolvar/XYDistances.cpp b/src/multicolvar/XYDistances.cpp index ebbb421807..43a3e681ed 100644 --- a/src/multicolvar/XYDistances.cpp +++ b/src/multicolvar/XYDistances.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ArgumentOnlyDistance.cpp b/src/reference/ArgumentOnlyDistance.cpp index 0e4a3e2aee..f0e20fee73 100644 --- a/src/reference/ArgumentOnlyDistance.cpp +++ b/src/reference/ArgumentOnlyDistance.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/DRMSD.cpp b/src/reference/DRMSD.cpp index 626259ae8f..c996965174 100644 --- a/src/reference/DRMSD.cpp +++ b/src/reference/DRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/DRMSD.h b/src/reference/DRMSD.h index e99f382f4e..517abb82cb 100644 --- a/src/reference/DRMSD.h +++ b/src/reference/DRMSD.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/Direction.cpp b/src/reference/Direction.cpp index 6398fadaee..50091c143f 100644 --- a/src/reference/Direction.cpp +++ b/src/reference/Direction.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/Direction.h b/src/reference/Direction.h index 7fbcf9cd7b..c0c35e47cf 100644 --- a/src/reference/Direction.h +++ b/src/reference/Direction.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/DotProductDistance.cpp b/src/reference/DotProductDistance.cpp index 0b0f4eb73d..9582f65a35 100644 --- a/src/reference/DotProductDistance.cpp +++ b/src/reference/DotProductDistance.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/EuclideanDistance.cpp b/src/reference/EuclideanDistance.cpp index d49ae78bd2..23583330a0 100644 --- a/src/reference/EuclideanDistance.cpp +++ b/src/reference/EuclideanDistance.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/FakeFrame.h b/src/reference/FakeFrame.h index 2929d725b5..7a4b368304 100644 --- a/src/reference/FakeFrame.h +++ b/src/reference/FakeFrame.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/IntermolecularDRMSD.cpp b/src/reference/IntermolecularDRMSD.cpp index 6903c83522..a50ab13f0b 100644 --- a/src/reference/IntermolecularDRMSD.cpp +++ b/src/reference/IntermolecularDRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/IntramolecularDRMSD.cpp b/src/reference/IntramolecularDRMSD.cpp index 2a7b4b64ff..00d3ab0694 100644 --- a/src/reference/IntramolecularDRMSD.cpp +++ b/src/reference/IntramolecularDRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MahalanobisDistance.cpp b/src/reference/MahalanobisDistance.cpp index 19a3e96697..0306bca066 100644 --- a/src/reference/MahalanobisDistance.cpp +++ b/src/reference/MahalanobisDistance.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MetricRegister.cpp b/src/reference/MetricRegister.cpp index b22c33379f..ef1cb2ae61 100644 --- a/src/reference/MetricRegister.cpp +++ b/src/reference/MetricRegister.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MetricRegister.h b/src/reference/MetricRegister.h index 64cb3424ef..fa70830e6d 100644 --- a/src/reference/MetricRegister.h +++ b/src/reference/MetricRegister.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MultiDomainRMSD.cpp b/src/reference/MultiDomainRMSD.cpp index 2e4050d542..d89014be33 100644 --- a/src/reference/MultiDomainRMSD.cpp +++ b/src/reference/MultiDomainRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MultiDomainRMSD.h b/src/reference/MultiDomainRMSD.h index 0fa98eb88e..770bd0ec92 100644 --- a/src/reference/MultiDomainRMSD.h +++ b/src/reference/MultiDomainRMSD.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MultiReferenceBase.cpp b/src/reference/MultiReferenceBase.cpp index 3468d1c137..5b3ab06e90 100644 --- a/src/reference/MultiReferenceBase.cpp +++ b/src/reference/MultiReferenceBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/MultiReferenceBase.h b/src/reference/MultiReferenceBase.h index 213ca6866a..91643378b8 100644 --- a/src/reference/MultiReferenceBase.h +++ b/src/reference/MultiReferenceBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/NormalizedEuclideanDistance.cpp b/src/reference/NormalizedEuclideanDistance.cpp index 9b4d14a321..e375b26c1e 100644 --- a/src/reference/NormalizedEuclideanDistance.cpp +++ b/src/reference/NormalizedEuclideanDistance.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/OptimalRMSD.cpp b/src/reference/OptimalRMSD.cpp index 7487f20d9d..6dc1241292 100644 --- a/src/reference/OptimalRMSD.cpp +++ b/src/reference/OptimalRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/PointWiseMapping.cpp b/src/reference/PointWiseMapping.cpp index 96743aac9e..353f09a85b 100644 --- a/src/reference/PointWiseMapping.cpp +++ b/src/reference/PointWiseMapping.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/PointWiseMapping.h b/src/reference/PointWiseMapping.h index a530d3492b..b06abe9e73 100644 --- a/src/reference/PointWiseMapping.h +++ b/src/reference/PointWiseMapping.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/RMSDBase.cpp b/src/reference/RMSDBase.cpp index 68b30e099f..d5a95f2231 100644 --- a/src/reference/RMSDBase.cpp +++ b/src/reference/RMSDBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/RMSDBase.h b/src/reference/RMSDBase.h index e1fb621e26..6f14cca35f 100644 --- a/src/reference/RMSDBase.h +++ b/src/reference/RMSDBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceArguments.cpp b/src/reference/ReferenceArguments.cpp index 685a59e1e7..e84b59cf67 100644 --- a/src/reference/ReferenceArguments.cpp +++ b/src/reference/ReferenceArguments.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceArguments.h b/src/reference/ReferenceArguments.h index 0d96b7e506..f9055110b7 100644 --- a/src/reference/ReferenceArguments.h +++ b/src/reference/ReferenceArguments.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceAtoms.cpp b/src/reference/ReferenceAtoms.cpp index f4a623a0a3..d8145008b2 100644 --- a/src/reference/ReferenceAtoms.cpp +++ b/src/reference/ReferenceAtoms.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceAtoms.h b/src/reference/ReferenceAtoms.h index 0323c1b90e..45b1e2ba84 100644 --- a/src/reference/ReferenceAtoms.h +++ b/src/reference/ReferenceAtoms.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceConfiguration.cpp b/src/reference/ReferenceConfiguration.cpp index f5bcbd823b..73916715e8 100644 --- a/src/reference/ReferenceConfiguration.cpp +++ b/src/reference/ReferenceConfiguration.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceConfiguration.h b/src/reference/ReferenceConfiguration.h index c76fd0e94e..cf9237f2b7 100644 --- a/src/reference/ReferenceConfiguration.h +++ b/src/reference/ReferenceConfiguration.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceValuePack.cpp b/src/reference/ReferenceValuePack.cpp index 106e1f1487..a5386d94b1 100644 --- a/src/reference/ReferenceValuePack.cpp +++ b/src/reference/ReferenceValuePack.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ReferenceValuePack.h b/src/reference/ReferenceValuePack.h index d5bc2078bf..086f90fb51 100644 --- a/src/reference/ReferenceValuePack.h +++ b/src/reference/ReferenceValuePack.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/SimpleRMSD.cpp b/src/reference/SimpleRMSD.cpp index 299203ae29..1ad5d8b592 100644 --- a/src/reference/SimpleRMSD.cpp +++ b/src/reference/SimpleRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/SingleDomainRMSD.cpp b/src/reference/SingleDomainRMSD.cpp index a499e66709..be924ff31f 100644 --- a/src/reference/SingleDomainRMSD.cpp +++ b/src/reference/SingleDomainRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/SingleDomainRMSD.h b/src/reference/SingleDomainRMSD.h index 9ecf96123d..de7fc24c99 100644 --- a/src/reference/SingleDomainRMSD.h +++ b/src/reference/SingleDomainRMSD.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/secondarystructure/AlphaRMSD.cpp b/src/secondarystructure/AlphaRMSD.cpp index 6c9b49083e..d73abed364 100644 --- a/src/secondarystructure/AlphaRMSD.cpp +++ b/src/secondarystructure/AlphaRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/secondarystructure/AntibetaRMSD.cpp b/src/secondarystructure/AntibetaRMSD.cpp index 6e60d54454..84f3978a5c 100644 --- a/src/secondarystructure/AntibetaRMSD.cpp +++ b/src/secondarystructure/AntibetaRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/secondarystructure/ParabetaRMSD.cpp b/src/secondarystructure/ParabetaRMSD.cpp index fe87408643..f3dde29edb 100644 --- a/src/secondarystructure/ParabetaRMSD.cpp +++ b/src/secondarystructure/ParabetaRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/secondarystructure/SecondaryStructureRMSD.cpp b/src/secondarystructure/SecondaryStructureRMSD.cpp index 8c51dc8edb..629ea1fc96 100644 --- a/src/secondarystructure/SecondaryStructureRMSD.cpp +++ b/src/secondarystructure/SecondaryStructureRMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/secondarystructure/SecondaryStructureRMSD.h b/src/secondarystructure/SecondaryStructureRMSD.h index 336d3bec8e..a5291bb02a 100644 --- a/src/secondarystructure/SecondaryStructureRMSD.h +++ b/src/secondarystructure/SecondaryStructureRMSD.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/setup/Load.cpp b/src/setup/Load.cpp index 93f9d39b88..e06a13c82a 100644 --- a/src/setup/Load.cpp +++ b/src/setup/Load.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/setup/Restart.cpp b/src/setup/Restart.cpp index ffa4f46b1b..d9436bd183 100644 --- a/src/setup/Restart.cpp +++ b/src/setup/Restart.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/setup/Units.cpp b/src/setup/Units.cpp index 1b4225d244..0be6e97379 100644 --- a/src/setup/Units.cpp +++ b/src/setup/Units.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Angle.cpp b/src/tools/Angle.cpp index c3841e1282..6b23a25f9b 100644 --- a/src/tools/Angle.cpp +++ b/src/tools/Angle.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Angle.h b/src/tools/Angle.h index 1d6a58e520..2e326f1047 100644 --- a/src/tools/Angle.h +++ b/src/tools/Angle.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/AtomNumber.h b/src/tools/AtomNumber.h index 60eb9ca775..98f24222b3 100644 --- a/src/tools/AtomNumber.h +++ b/src/tools/AtomNumber.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/BiasRepresentation.cpp b/src/tools/BiasRepresentation.cpp index 20a03aa69c..6a8a21e351 100644 --- a/src/tools/BiasRepresentation.cpp +++ b/src/tools/BiasRepresentation.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/BiasRepresentation.h b/src/tools/BiasRepresentation.h index 9533e53c49..fac52aaddc 100644 --- a/src/tools/BiasRepresentation.h +++ b/src/tools/BiasRepresentation.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Brent1DRootSearch.h b/src/tools/Brent1DRootSearch.h index 138760737c..cced1aee9f 100644 --- a/src/tools/Brent1DRootSearch.h +++ b/src/tools/Brent1DRootSearch.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Citations.cpp b/src/tools/Citations.cpp index 508255c2c5..d9b11bd9c0 100644 --- a/src/tools/Citations.cpp +++ b/src/tools/Citations.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Citations.h b/src/tools/Citations.h index 7d7ba10bee..e65ed03439 100644 --- a/src/tools/Citations.h +++ b/src/tools/Citations.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Communicator.cpp b/src/tools/Communicator.cpp index ac10f3931a..91aff7374c 100644 --- a/src/tools/Communicator.cpp +++ b/src/tools/Communicator.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Communicator.h b/src/tools/Communicator.h index 86ef8314d6..a1675b90af 100644 --- a/src/tools/Communicator.h +++ b/src/tools/Communicator.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/CubicInterpolation.cpp b/src/tools/CubicInterpolation.cpp index fd35339bd5..d18c7ab0e9 100644 --- a/src/tools/CubicInterpolation.cpp +++ b/src/tools/CubicInterpolation.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/CubicInterpolation.h b/src/tools/CubicInterpolation.h index fdbdcc3615..bac3bea4db 100644 --- a/src/tools/CubicInterpolation.h +++ b/src/tools/CubicInterpolation.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/DLLoader.cpp b/src/tools/DLLoader.cpp index b56e4c2367..c778c4c3d6 100644 --- a/src/tools/DLLoader.cpp +++ b/src/tools/DLLoader.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/DLLoader.h b/src/tools/DLLoader.h index fdad73f2a1..31bf329162 100644 --- a/src/tools/DLLoader.h +++ b/src/tools/DLLoader.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/DynamicList.h b/src/tools/DynamicList.h index c5252de5b0..d38585cf7c 100644 --- a/src/tools/DynamicList.h +++ b/src/tools/DynamicList.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/ERMSD.cpp b/src/tools/ERMSD.cpp index 65c9da9f27..1a4771cad7 100644 --- a/src/tools/ERMSD.cpp +++ b/src/tools/ERMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/ERMSD.h b/src/tools/ERMSD.h index f07d83711a..daa6264a0e 100644 --- a/src/tools/ERMSD.h +++ b/src/tools/ERMSD.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Exception.cpp b/src/tools/Exception.cpp index 223b4b1417..bff700d7c8 100644 --- a/src/tools/Exception.cpp +++ b/src/tools/Exception.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Exception.h b/src/tools/Exception.h index 9e3c6dcf2f..6dfbb7703a 100644 --- a/src/tools/Exception.h +++ b/src/tools/Exception.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/FileBase.cpp b/src/tools/FileBase.cpp index b3e3bd75a1..743a512f3c 100644 --- a/src/tools/FileBase.cpp +++ b/src/tools/FileBase.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/FileBase.h b/src/tools/FileBase.h index 4cba79bc47..daa7d00203 100644 --- a/src/tools/FileBase.h +++ b/src/tools/FileBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Grid.cpp b/src/tools/Grid.cpp index 7188780e4a..9b0ac8f20a 100644 --- a/src/tools/Grid.cpp +++ b/src/tools/Grid.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Grid.h b/src/tools/Grid.h index 0e46fff1a3..fd2a815ed0 100644 --- a/src/tools/Grid.h +++ b/src/tools/Grid.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/HistogramBead.cpp b/src/tools/HistogramBead.cpp index bdef4556f6..9c97a6033b 100644 --- a/src/tools/HistogramBead.cpp +++ b/src/tools/HistogramBead.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/HistogramBead.h b/src/tools/HistogramBead.h index aae33470c5..77956d3f9d 100644 --- a/src/tools/HistogramBead.h +++ b/src/tools/HistogramBead.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/IFile.cpp b/src/tools/IFile.cpp index 5cd3261350..7259eec5ad 100644 --- a/src/tools/IFile.cpp +++ b/src/tools/IFile.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/IFile.h b/src/tools/IFile.h index 2d54338df6..5c1f3406ab 100644 --- a/src/tools/IFile.h +++ b/src/tools/IFile.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Kearsley.cpp b/src/tools/Kearsley.cpp index bf1f82dd1e..38442418b5 100644 --- a/src/tools/Kearsley.cpp +++ b/src/tools/Kearsley.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Kearsley.h b/src/tools/Kearsley.h index b003562938..352c72027f 100644 --- a/src/tools/Kearsley.h +++ b/src/tools/Kearsley.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/KernelFunctions.cpp b/src/tools/KernelFunctions.cpp index d5da1a3872..38a0c60acd 100644 --- a/src/tools/KernelFunctions.cpp +++ b/src/tools/KernelFunctions.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/KernelFunctions.h b/src/tools/KernelFunctions.h index a7535e0b28..81f656efc2 100644 --- a/src/tools/KernelFunctions.h +++ b/src/tools/KernelFunctions.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Keywords.cpp b/src/tools/Keywords.cpp index 7b7e36419c..bfaadb82d3 100644 --- a/src/tools/Keywords.cpp +++ b/src/tools/Keywords.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Keywords.h b/src/tools/Keywords.h index 7da2155f5e..abcf450c5d 100644 --- a/src/tools/Keywords.h +++ b/src/tools/Keywords.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/LatticeReduction.cpp b/src/tools/LatticeReduction.cpp index c0bc6b1d03..faf36b45f2 100644 --- a/src/tools/LatticeReduction.cpp +++ b/src/tools/LatticeReduction.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/LatticeReduction.h b/src/tools/LatticeReduction.h index 16d999a9c4..7f5c0e1497 100644 --- a/src/tools/LatticeReduction.h +++ b/src/tools/LatticeReduction.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/LinkCells.cpp b/src/tools/LinkCells.cpp index 324e0f8034..8e3c3b7ae5 100644 --- a/src/tools/LinkCells.cpp +++ b/src/tools/LinkCells.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/LinkCells.h b/src/tools/LinkCells.h index b493dbf87a..3dd54f1748 100644 --- a/src/tools/LinkCells.h +++ b/src/tools/LinkCells.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Log.h b/src/tools/Log.h index c25ca3f383..4ac26c1b50 100644 --- a/src/tools/Log.h +++ b/src/tools/Log.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/LoopUnroller.h b/src/tools/LoopUnroller.h index 83f33ed700..c1b4bb58d4 100644 --- a/src/tools/LoopUnroller.h +++ b/src/tools/LoopUnroller.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Matrix.h b/src/tools/Matrix.h index fd1e35d6d9..61cc2a7834 100644 --- a/src/tools/Matrix.h +++ b/src/tools/Matrix.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/MatrixSquareBracketsAccess.h b/src/tools/MatrixSquareBracketsAccess.h index 1e8188bb32..113497bcea 100644 --- a/src/tools/MatrixSquareBracketsAccess.h +++ b/src/tools/MatrixSquareBracketsAccess.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Minimise1DBrent.h b/src/tools/Minimise1DBrent.h index 097a05b444..ef8862c5e6 100644 --- a/src/tools/Minimise1DBrent.h +++ b/src/tools/Minimise1DBrent.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/MinimiseBase.h b/src/tools/MinimiseBase.h index 27714da7ca..86cfcb4d0a 100644 --- a/src/tools/MinimiseBase.h +++ b/src/tools/MinimiseBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/MolDataClass.cpp b/src/tools/MolDataClass.cpp index 310267d5ac..66f5f07a10 100644 --- a/src/tools/MolDataClass.cpp +++ b/src/tools/MolDataClass.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/MolDataClass.h b/src/tools/MolDataClass.h index e3ee323356..655eb9357a 100644 --- a/src/tools/MolDataClass.h +++ b/src/tools/MolDataClass.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/MultiValue.cpp b/src/tools/MultiValue.cpp index 90aead54ab..cdf2421659 100644 --- a/src/tools/MultiValue.cpp +++ b/src/tools/MultiValue.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/MultiValue.h b/src/tools/MultiValue.h index d287e060d2..5f5f6ec643 100644 --- a/src/tools/MultiValue.h +++ b/src/tools/MultiValue.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/NeighborList.cpp b/src/tools/NeighborList.cpp index 1d78265738..6cde3e7c81 100644 --- a/src/tools/NeighborList.cpp +++ b/src/tools/NeighborList.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/NeighborList.h b/src/tools/NeighborList.h index 5afa872180..12f86d9216 100644 --- a/src/tools/NeighborList.h +++ b/src/tools/NeighborList.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/OFile.cpp b/src/tools/OFile.cpp index 92108a1321..0681444d10 100644 --- a/src/tools/OFile.cpp +++ b/src/tools/OFile.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/OFile.h b/src/tools/OFile.h index 84f044a94d..710ed976c0 100644 --- a/src/tools/OFile.h +++ b/src/tools/OFile.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/OpenMP.cpp b/src/tools/OpenMP.cpp index 928c3da156..e0a42d6a52 100644 --- a/src/tools/OpenMP.cpp +++ b/src/tools/OpenMP.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/OpenMP.h b/src/tools/OpenMP.h index c79258ff76..5b321752e8 100644 --- a/src/tools/OpenMP.h +++ b/src/tools/OpenMP.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/OptimalAlignment.cpp b/src/tools/OptimalAlignment.cpp index ac28cbb1f7..99b883b4e0 100644 --- a/src/tools/OptimalAlignment.cpp +++ b/src/tools/OptimalAlignment.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/OptimalAlignment.h b/src/tools/OptimalAlignment.h index bb7c2f4387..0411c071d0 100644 --- a/src/tools/OptimalAlignment.h +++ b/src/tools/OptimalAlignment.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/PDB.cpp b/src/tools/PDB.cpp index 5aa30f4360..d6810304e3 100644 --- a/src/tools/PDB.cpp +++ b/src/tools/PDB.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/PDB.h b/src/tools/PDB.h index 0fbb0cc1ac..cf2219cec6 100644 --- a/src/tools/PDB.h +++ b/src/tools/PDB.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Pbc.cpp b/src/tools/Pbc.cpp index 99448c76e6..722afc19ef 100644 --- a/src/tools/Pbc.cpp +++ b/src/tools/Pbc.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Pbc.h b/src/tools/Pbc.h index ceee55c7b3..981ccd08c1 100644 --- a/src/tools/Pbc.h +++ b/src/tools/Pbc.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/RMSD.cpp b/src/tools/RMSD.cpp index 0bc2eff548..62ea6d745b 100644 --- a/src/tools/RMSD.cpp +++ b/src/tools/RMSD.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/RMSD.h b/src/tools/RMSD.h index b7c80bfa4a..a7ec1928e3 100644 --- a/src/tools/RMSD.h +++ b/src/tools/RMSD.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Random.cpp b/src/tools/Random.cpp index 7d03b9da3d..e180ed1527 100644 --- a/src/tools/Random.cpp +++ b/src/tools/Random.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Random.h b/src/tools/Random.h index 49e7a3b442..6a9836dd5d 100644 --- a/src/tools/Random.h +++ b/src/tools/Random.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/RootFindingBase.h b/src/tools/RootFindingBase.h index b737455605..d1e786c42a 100644 --- a/src/tools/RootFindingBase.h +++ b/src/tools/RootFindingBase.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Stopwatch.cpp b/src/tools/Stopwatch.cpp index 56f611db92..c7798e1f92 100644 --- a/src/tools/Stopwatch.cpp +++ b/src/tools/Stopwatch.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Stopwatch.h b/src/tools/Stopwatch.h index 1d55cf4c05..ebc74df444 100644 --- a/src/tools/Stopwatch.h +++ b/src/tools/Stopwatch.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/SwitchingFunction.cpp b/src/tools/SwitchingFunction.cpp index fcbe3bb37f..6eec6c985e 100644 --- a/src/tools/SwitchingFunction.cpp +++ b/src/tools/SwitchingFunction.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/SwitchingFunction.h b/src/tools/SwitchingFunction.h index 379280da4a..8add9db500 100644 --- a/src/tools/SwitchingFunction.h +++ b/src/tools/SwitchingFunction.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Tensor.cpp b/src/tools/Tensor.cpp index d063e28cf9..5b132af72e 100644 --- a/src/tools/Tensor.cpp +++ b/src/tools/Tensor.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Tensor.h b/src/tools/Tensor.h index 7cd6515c86..7987a6155e 100644 --- a/src/tools/Tensor.h +++ b/src/tools/Tensor.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Tools.cpp b/src/tools/Tools.cpp index bdb2bc0399..ebfdaf564b 100644 --- a/src/tools/Tools.cpp +++ b/src/tools/Tools.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Tools.h b/src/tools/Tools.h index 3c1d362f29..e3c5160a48 100644 --- a/src/tools/Tools.h +++ b/src/tools/Tools.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Torsion.cpp b/src/tools/Torsion.cpp index 4464e1bd17..76a88affe8 100644 --- a/src/tools/Torsion.cpp +++ b/src/tools/Torsion.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Torsion.h b/src/tools/Torsion.h index b898a99ccd..770bb7b478 100644 --- a/src/tools/Torsion.h +++ b/src/tools/Torsion.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Units.cpp b/src/tools/Units.cpp index 48737c9d08..a0da2c1544 100644 --- a/src/tools/Units.cpp +++ b/src/tools/Units.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Units.h b/src/tools/Units.h index 12074cc211..9aaca6c978 100644 --- a/src/tools/Units.h +++ b/src/tools/Units.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Vector.cpp b/src/tools/Vector.cpp index 8f2883acb8..218d85457e 100644 --- a/src/tools/Vector.cpp +++ b/src/tools/Vector.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/tools/Vector.h b/src/tools/Vector.h index 133ff4a194..0163d1851a 100644 --- a/src/tools/Vector.h +++ b/src/tools/Vector.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vatom/ActionWithVirtualAtom.h b/src/vatom/ActionWithVirtualAtom.h index d461218ab4..d18e280bb6 100644 --- a/src/vatom/ActionWithVirtualAtom.h +++ b/src/vatom/ActionWithVirtualAtom.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vatom/COM.cpp b/src/vatom/COM.cpp index 65f69a403e..16258558e2 100644 --- a/src/vatom/COM.cpp +++ b/src/vatom/COM.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vatom/Center.cpp b/src/vatom/Center.cpp index d29fca69fc..ca3f664517 100644 --- a/src/vatom/Center.cpp +++ b/src/vatom/Center.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vatom/FixedAtom.cpp b/src/vatom/FixedAtom.cpp index ccf7eb52ca..bb95bd898e 100644 --- a/src/vatom/FixedAtom.cpp +++ b/src/vatom/FixedAtom.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vatom/Ghost.cpp b/src/vatom/Ghost.cpp index fcd7893775..3fa8c674e5 100644 --- a/src/vatom/Ghost.cpp +++ b/src/vatom/Ghost.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ActionWithAveraging.cpp b/src/vesselbase/ActionWithAveraging.cpp index 57eae5302c..0d61026995 100644 --- a/src/vesselbase/ActionWithAveraging.cpp +++ b/src/vesselbase/ActionWithAveraging.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ActionWithAveraging.h b/src/vesselbase/ActionWithAveraging.h index f234ed0c06..71736f767a 100644 --- a/src/vesselbase/ActionWithAveraging.h +++ b/src/vesselbase/ActionWithAveraging.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ActionWithInputVessel.cpp b/src/vesselbase/ActionWithInputVessel.cpp index b75c1f4a0b..711c8143a8 100644 --- a/src/vesselbase/ActionWithInputVessel.cpp +++ b/src/vesselbase/ActionWithInputVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ActionWithInputVessel.h b/src/vesselbase/ActionWithInputVessel.h index 09d888f45f..dc20e9af16 100644 --- a/src/vesselbase/ActionWithInputVessel.h +++ b/src/vesselbase/ActionWithInputVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2014-2016 The plumed team + Copyright (c) 2014-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ActionWithVessel.cpp b/src/vesselbase/ActionWithVessel.cpp index ebbe511a4f..58cbf84dac 100644 --- a/src/vesselbase/ActionWithVessel.cpp +++ b/src/vesselbase/ActionWithVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ActionWithVessel.h b/src/vesselbase/ActionWithVessel.h index 8134037649..5d49bebecf 100644 --- a/src/vesselbase/ActionWithVessel.h +++ b/src/vesselbase/ActionWithVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/AltMin.cpp b/src/vesselbase/AltMin.cpp index 7dfa034d6a..202bb849e4 100644 --- a/src/vesselbase/AltMin.cpp +++ b/src/vesselbase/AltMin.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/AveragingVessel.cpp b/src/vesselbase/AveragingVessel.cpp index a3bbb4fd79..f44d22b242 100644 --- a/src/vesselbase/AveragingVessel.cpp +++ b/src/vesselbase/AveragingVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/AveragingVessel.h b/src/vesselbase/AveragingVessel.h index 78ada5a5e6..6cf480798a 100644 --- a/src/vesselbase/AveragingVessel.h +++ b/src/vesselbase/AveragingVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Between.cpp b/src/vesselbase/Between.cpp index ac02823d0f..68be61205e 100644 --- a/src/vesselbase/Between.cpp +++ b/src/vesselbase/Between.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/BridgeVessel.cpp b/src/vesselbase/BridgeVessel.cpp index 089dbfe2c8..bca7bc200e 100644 --- a/src/vesselbase/BridgeVessel.cpp +++ b/src/vesselbase/BridgeVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/BridgeVessel.h b/src/vesselbase/BridgeVessel.h index 42dcaa59cf..c881e45084 100644 --- a/src/vesselbase/BridgeVessel.h +++ b/src/vesselbase/BridgeVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/FunctionVessel.cpp b/src/vesselbase/FunctionVessel.cpp index 13b84e6156..ca241a4e18 100644 --- a/src/vesselbase/FunctionVessel.cpp +++ b/src/vesselbase/FunctionVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/FunctionVessel.h b/src/vesselbase/FunctionVessel.h index b6fd05d559..729b86ffb1 100644 --- a/src/vesselbase/FunctionVessel.h +++ b/src/vesselbase/FunctionVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Highest.cpp b/src/vesselbase/Highest.cpp index 437f681ec7..6cb28e8e06 100644 --- a/src/vesselbase/Highest.cpp +++ b/src/vesselbase/Highest.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Histogram.cpp b/src/vesselbase/Histogram.cpp index eb91f0ce2a..1ba33cdcda 100644 --- a/src/vesselbase/Histogram.cpp +++ b/src/vesselbase/Histogram.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/LessThan.cpp b/src/vesselbase/LessThan.cpp index 7d1c69c71c..fa51e4f084 100644 --- a/src/vesselbase/LessThan.cpp +++ b/src/vesselbase/LessThan.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/LessThan.h b/src/vesselbase/LessThan.h index f276f6e4a7..28ac4b147c 100644 --- a/src/vesselbase/LessThan.h +++ b/src/vesselbase/LessThan.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Lowest.cpp b/src/vesselbase/Lowest.cpp index 9121543b78..62bf667ed7 100644 --- a/src/vesselbase/Lowest.cpp +++ b/src/vesselbase/Lowest.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Max.cpp b/src/vesselbase/Max.cpp index d9b7b2c5a6..d114c28677 100644 --- a/src/vesselbase/Max.cpp +++ b/src/vesselbase/Max.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Mean.cpp b/src/vesselbase/Mean.cpp index d2979761b9..d84852732d 100644 --- a/src/vesselbase/Mean.cpp +++ b/src/vesselbase/Mean.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Min.cpp b/src/vesselbase/Min.cpp index 989ee34c61..5eb6750556 100644 --- a/src/vesselbase/Min.cpp +++ b/src/vesselbase/Min.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Moments.cpp b/src/vesselbase/Moments.cpp index 84d7e39190..3d400ebfb2 100644 --- a/src/vesselbase/Moments.cpp +++ b/src/vesselbase/Moments.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/MoreThan.cpp b/src/vesselbase/MoreThan.cpp index 6a98e3baec..59cfe5b2c9 100644 --- a/src/vesselbase/MoreThan.cpp +++ b/src/vesselbase/MoreThan.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/OrderingVessel.cpp b/src/vesselbase/OrderingVessel.cpp index 4eab917887..1af3ead4d6 100644 --- a/src/vesselbase/OrderingVessel.cpp +++ b/src/vesselbase/OrderingVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/OrderingVessel.h b/src/vesselbase/OrderingVessel.h index 6e8fb93cc5..45396ef48d 100644 --- a/src/vesselbase/OrderingVessel.h +++ b/src/vesselbase/OrderingVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ShortcutVessel.cpp b/src/vesselbase/ShortcutVessel.cpp index fc3be38c6f..cda075fcf4 100644 --- a/src/vesselbase/ShortcutVessel.cpp +++ b/src/vesselbase/ShortcutVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ShortcutVessel.h b/src/vesselbase/ShortcutVessel.h index c6e66d76cf..7cea470b13 100644 --- a/src/vesselbase/ShortcutVessel.h +++ b/src/vesselbase/ShortcutVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/StoreDataVessel.cpp b/src/vesselbase/StoreDataVessel.cpp index d08ec32dd1..447299dc6d 100644 --- a/src/vesselbase/StoreDataVessel.cpp +++ b/src/vesselbase/StoreDataVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/StoreDataVessel.h b/src/vesselbase/StoreDataVessel.h index 23f73160b9..46eeb3c6a0 100644 --- a/src/vesselbase/StoreDataVessel.h +++ b/src/vesselbase/StoreDataVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Sum.cpp b/src/vesselbase/Sum.cpp index 4a1aedd5a4..bd3fdba11c 100644 --- a/src/vesselbase/Sum.cpp +++ b/src/vesselbase/Sum.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ValueVessel.cpp b/src/vesselbase/ValueVessel.cpp index a234ffe174..8c916e9b0a 100644 --- a/src/vesselbase/ValueVessel.cpp +++ b/src/vesselbase/ValueVessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/ValueVessel.h b/src/vesselbase/ValueVessel.h index b805204199..b5fe67ef51 100644 --- a/src/vesselbase/ValueVessel.h +++ b/src/vesselbase/ValueVessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Vessel.cpp b/src/vesselbase/Vessel.cpp index 4ce9e10a05..31fab043b5 100644 --- a/src/vesselbase/Vessel.cpp +++ b/src/vesselbase/Vessel.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/Vessel.h b/src/vesselbase/Vessel.h index 2751780e2e..2763a2d971 100644 --- a/src/vesselbase/Vessel.h +++ b/src/vesselbase/Vessel.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/VesselRegister.cpp b/src/vesselbase/VesselRegister.cpp index 859d1bcbd0..6011f86f6f 100644 --- a/src/vesselbase/VesselRegister.cpp +++ b/src/vesselbase/VesselRegister.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/vesselbase/VesselRegister.h b/src/vesselbase/VesselRegister.h index a2bd24a20c..b7bbd37b64 100644 --- a/src/vesselbase/VesselRegister.h +++ b/src/vesselbase/VesselRegister.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/wrapper/Plumed.c b/src/wrapper/Plumed.c index 75d9a9280b..2976d3de51 100644 --- a/src/wrapper/Plumed.c +++ b/src/wrapper/Plumed.c @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/wrapper/Plumed.h b/src/wrapper/Plumed.h index 9ac3cc2e5c..4669517d73 100644 --- a/src/wrapper/Plumed.h +++ b/src/wrapper/Plumed.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2011-2016 The plumed team + Copyright (c) 2011-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. From 5040cf8e1f07ae26e6c0065e98afd23ab4d129b2 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Thu, 4 May 2017 18:54:16 +0200 Subject: [PATCH 55/62] Further headers --- src/gridtools/ActionWithIntegral.cpp | 2 +- src/gridtools/AverageOnGrid.h | 2 +- src/gridtools/GridToXYZ.cpp | 2 +- src/manyrestraints/LWalls.cpp | 2 +- src/reference/ArgumentOnlyDistance.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gridtools/ActionWithIntegral.cpp b/src/gridtools/ActionWithIntegral.cpp index 7deb7fbd39..f117103d43 100644 --- a/src/gridtools/ActionWithIntegral.cpp +++ b/src/gridtools/ActionWithIntegral.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2016 The plumed team + Copyright (c) 2016,2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/AverageOnGrid.h b/src/gridtools/AverageOnGrid.h index ad38b50e71..c1f8196038 100644 --- a/src/gridtools/AverageOnGrid.h +++ b/src/gridtools/AverageOnGrid.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/gridtools/GridToXYZ.cpp b/src/gridtools/GridToXYZ.cpp index 75e508a3f2..c384c6cbb6 100644 --- a/src/gridtools/GridToXYZ.cpp +++ b/src/gridtools/GridToXYZ.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2015,2016 The plumed team + Copyright (c) 2015-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/manyrestraints/LWalls.cpp b/src/manyrestraints/LWalls.cpp index c98405d04e..3bbddeb16c 100644 --- a/src/manyrestraints/LWalls.cpp +++ b/src/manyrestraints/LWalls.cpp @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2013-2016 The plumed team + Copyright (c) 2013-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. diff --git a/src/reference/ArgumentOnlyDistance.h b/src/reference/ArgumentOnlyDistance.h index 3636f0764e..3e292b3f34 100644 --- a/src/reference/ArgumentOnlyDistance.h +++ b/src/reference/ArgumentOnlyDistance.h @@ -1,5 +1,5 @@ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - Copyright (c) 2012-2016 The plumed team + Copyright (c) 2012-2017 The plumed team (see the PEOPLE file at the root of the distribution for a list of names) See http://www.plumed.org for more information. From 106f6a3b361e1be5e8ee46c89a0bd658819b3cb8 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Fri, 5 May 2017 08:34:57 +0200 Subject: [PATCH 56/62] astyle [makedoc] --- src/cltools/Driver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cltools/Driver.cpp b/src/cltools/Driver.cpp index 3448d229f9..a7b9e1b68e 100644 --- a/src/cltools/Driver.cpp +++ b/src/cltools/Driver.cpp @@ -143,7 +143,7 @@ files are referred to the original timestep and any files output resemble those had we run the calculation we are running with driver when the MD simulation was running. PLUMED can read natively xyz files (in PLUMED units) and gro files (in nm). In addition, -PLUMED includes by default support for a +PLUMED includes by default support for a subset of the trajectory file formats supported by VMD, e.g. xtc and dcd: \verbatim From fd27f122df2fa5375680d8e13e375b544fea3bbe Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Fri, 5 May 2017 15:47:17 +0100 Subject: [PATCH 57/62] Added routines for truncating kernel evaluation on spherical fibonacci grids --- .../rt-dfg-wcsurf/mysurface.xyz.reference | 200 +++++++++--------- .../rt-spherical-integral/colvar.reference | 10 +- .../rt-spherical-integral/forces.reference | 58 ++--- src/gridtools/GridVessel.cpp | 128 +++++++++-- src/gridtools/GridVessel.h | 19 +- src/gridtools/HistogramOnGrid.cpp | 11 +- src/gridtools/HistogramOnGrid.h | 1 + 7 files changed, 266 insertions(+), 161 deletions(-) diff --git a/regtest/adjmat/rt-dfg-wcsurf/mysurface.xyz.reference b/regtest/adjmat/rt-dfg-wcsurf/mysurface.xyz.reference index d68d0b82f8..44746f7615 100644 --- a/regtest/adjmat/rt-dfg-wcsurf/mysurface.xyz.reference +++ b/regtest/adjmat/rt-dfg-wcsurf/mysurface.xyz.reference @@ -1,102 +1,102 @@ 100 Grid converted to xyz file -X -20.8562 -274.8130 -33.1425 -X 66.4253 -274.8131 18.2044 -X -80.0064 -273.5955 41.0579 -X 37.7558 -274.8134 -101.8397 -X 47.2090 -274.8134 115.9678 -X -126.4082 -273.0455 -59.9072 -X 142.9675 -263.9868 -44.0784 -X -82.9297 -264.6495 141.5048 -X -34.1637 -242.1433 -159.0945 -X 142.4703 -241.3816 101.2043 -X -206.6447 -268.3255 25.7537 -X 141.5894 -263.6224 -166.3450 -X 6.7746 -210.7854 185.7717 -X -136.7488 -208.0931 -138.7649 -X 213.1740 -215.2100 10.8997 -X -171.2314 -211.7436 141.4800 -X 33.6909 -220.0528 -241.4799 -X 118.0120 -177.9869 171.3899 -X -239.7151 -199.5465 -55.1579 -X 212.5498 -188.0594 -120.4222 -X -80.8322 -191.4166 249.1663 -X -104.0823 -173.9927 -228.1912 -X 239.6331 -171.4259 101.6646 -X -241.6610 -160.2321 85.5914 -X 128.6707 -162.4754 -241.9468 -X 64.6759 -145.3199 250.3071 -X -224.2947 -142.4388 -145.7711 -X 241.4801 -123.3645 -40.2888 -X -175.4468 -135.6189 224.2733 -X -14.5224 -84.0142 -186.3329 -X 185.8863 -107.7394 173.6529 -X -274.8126 -109.4532 -2.6813 -X 209.6625 -105.3020 -188.3390 -X -26.8224 -96.5266 274.8133 -X -181.4369 -98.4902 -241.4959 -X 241.4801 -74.4417 45.1484 -X -243.1214 -80.3046 151.3425 -X 44.7517 -42.9526 -160.2221 -X 110.9327 -57.9740 218.7866 -X -274.8101 -63.0670 -103.4100 -X 241.4801 -50.3570 -96.9330 -X -131.8832 -52.5844 274.8101 -X -82.5840 -43.2106 -272.5754 -X 241.4801 -36.8033 143.1079 -X -274.8134 -31.0752 57.6120 -X 173.3147 -26.8605 -241.4801 -X 32.8887 -19.4218 274.8126 -X -241.4801 -15.9419 -207.5827 -X 241.4801 -7.2513 -7.6268 -X -241.0937 -3.3689 235.2836 -X 10.7868 1.9285 -192.5430 -X 170.2794 8.0714 208.1467 -X -274.8110 13.9006 -39.7089 -X 241.4509 20.5025 -164.5226 -X -64.6454 25.5112 274.8061 -X -153.9322 34.8602 -274.8134 -X 241.4800 33.3386 79.6427 -X -274.7596 45.7159 123.7074 -X 118.1954 51.6147 -274.8606 -X 241.4767 46.7318 0.0000 -X -242.7131 70.7003 222.3451 -X 24.0852 65.1089 -274.4382 -X 159.5822 67.7208 208.1467 -X -274.8134 78.2580 -48.6106 -X 241.4197 86.7022 -153.5714 -X -73.8736 92.7852 274.8060 -X -139.0544 105.4684 -267.7409 -X 241.4776 96.0521 88.1872 -X -269.7450 116.2225 111.3468 -X 114.1679 114.0849 -243.9701 -X 75.2354 113.0023 239.8624 -X -241.4818 132.9307 -139.9437 -X 241.4197 124.5574 -53.0754 -X -153.5999 142.2089 218.4801 -X -32.2901 141.2368 -249.1804 -X 205.1457 159.0684 172.8970 -X -244.0258 152.6469 10.0912 -X 188.5883 175.2119 -187.6705 -X -9.8697 148.2284 213.4405 -X -149.1039 170.0551 -178.6764 -X 225.8814 175.4530 30.3920 -X -182.3928 180.2542 126.9042 -X 47.4924 185.0818 -211.1084 -X 114.6629 208.1460 200.1021 -X -205.6525 205.7813 -65.6088 -X 179.1695 198.9938 -82.7809 -X -75.6512 209.3042 180.7648 -X -64.4692 215.9868 -179.2409 -X 173.8660 237.0384 91.3791 -X -178.4690 237.8158 47.0439 -X 83.1987 212.4801 -129.3930 -X 27.4856 241.4801 159.9310 -X -118.3214 241.4801 -91.6348 -X 136.3858 241.4801 -11.2993 -X -84.1522 241.8844 90.9661 -X 0.5523 248.4932 -113.2155 -X 72.9756 274.8134 80.4450 -X -80.9491 247.3379 -7.5023 -X 54.8628 274.8134 -41.6389 -X -7.0088 274.8134 38.5265 +X 39.1587 -274.8129 0.0000 +X -50.7787 -274.7733 -46.5174 +X 7.8969 -274.8134 89.9809 +X 66.0845 -274.8134 -86.1955 +X -122.5208 -273.0884 21.6722 +X 109.9911 -254.4508 69.9673 +X -37.9272 -257.7900 -141.0874 +X -73.8311 -258.4720 142.1573 +X 171.4871 -271.6723 -62.6268 +X -172.1950 -257.3091 -71.0796 +X 79.2668 -240.9763 169.3886 +X 65.3260 -263.4165 -208.2696 +X -192.6446 -252.4683 111.6415 +X 200.4365 -219.2019 44.0654 +X -118.6361 -207.9757 -168.7477 +X -28.0598 -208.1467 216.5352 +X 177.6362 -209.6665 -149.7120 +X -239.9099 -205.3792 -9.9210 +X 147.6486 -168.9793 146.9301 +X -11.1467 -185.7668 -241.0569 +X -154.7927 -176.5432 185.4933 +X 241.4801 -169.0316 -32.4908 +X -208.1398 -166.9850 -144.8182 +X 55.0272 -156.6972 244.6015 +X 138.3903 -165.0346 -241.5095 +X -245.6773 -144.9540 78.3778 +X 234.0044 -137.2586 108.1160 +X -107.0039 -139.6660 -255.6804 +X -98.8447 -139.0974 274.8134 +X 241.4801 -122.6291 -126.9152 +X -274.8101 -120.3683 -72.4391 +X 133.8367 -98.5551 208.1467 +X 27.7848 -61.2915 -161.6720 +X -226.4329 -100.1200 175.3624 +X 241.4801 -79.0075 20.0061 +X -208.8177 -93.1796 -225.7258 +X 1.3406 -77.0624 274.8127 +X 200.0394 -76.8732 -220.5143 +X -274.8133 -65.2266 25.4696 +X 230.3384 -62.1100 174.8186 +X -36.7649 -39.7519 -202.0922 +X -155.7205 -50.4379 247.4554 +X 241.4801 -37.9875 -66.1797 +X -274.8105 -40.4987 -141.0282 +X 89.9687 -28.6436 242.6752 +X 71.6911 -17.1824 -176.1075 +X -274.8016 -21.3393 130.2336 +X 241.4801 -12.6507 74.4509 +X -161.0559 -9.5602 -274.8134 +X -59.0121 -2.8109 274.8089 +X 241.4791 2.9622 -171.5354 +X -274.8108 8.3118 -34.2491 +X 177.1701 13.6841 208.1467 +X 7.4913 14.4246 -205.4239 +X -236.9471 30.5054 240.4404 +X 241.4810 26.7600 -12.3471 +X -241.4828 41.0707 -199.5251 +X 38.3043 42.0567 274.5465 +X 166.2744 50.5786 -241.4819 +X -274.8134 54.5731 63.2339 +X 241.4801 59.6134 136.8130 +X -89.0838 68.2280 -274.6021 +X -125.3442 77.9870 274.8060 +X 241.4197 73.5381 -102.4226 +X -274.8134 88.3433 -97.3333 +X 113.9749 79.1471 214.3135 +X 70.9584 99.1560 -274.6213 +X -250.5401 111.6426 162.8282 +X 241.4775 97.5011 40.2884 +X -167.0284 114.8139 -213.5121 +X -19.4419 112.4741 249.4533 +X 218.6379 142.5028 -204.2490 +X -273.4190 137.7833 2.6677 +X 194.9349 139.5283 175.1093 +X -24.4079 141.2368 -250.0756 +X -148.5398 146.6198 197.7093 +X 241.4197 153.5023 -45.1372 +X -223.1565 173.1080 -138.9144 +X 58.9344 151.9795 210.9997 +X 109.8473 177.4985 -216.6460 +X -217.0556 178.5305 81.6772 +X 204.8306 179.0529 82.2214 +X -90.1106 178.1411 -187.7671 +X -63.0636 196.2906 208.1466 +X 175.2033 194.1460 -103.8304 +X -206.1657 212.3819 -43.2207 +X 125.5594 230.0046 174.9424 +X 21.8886 208.8659 -182.8973 +X -133.9740 213.2089 115.1677 +X 175.4127 226.1354 5.5401 +X -116.4589 224.7626 -113.6524 +X 9.0769 241.4801 162.0215 +X 89.7391 228.6845 -109.6956 +X -135.4464 241.4801 19.5713 +X 109.0941 257.6786 74.3358 +X -25.2617 242.1312 -107.3869 +X -48.4661 250.9330 86.5259 +X 85.7817 274.8134 -28.2917 +X -62.8027 274.8134 -28.2762 +X 15.4694 274.8134 35.9737 diff --git a/regtest/crystallization/rt-spherical-integral/colvar.reference b/regtest/crystallization/rt-spherical-integral/colvar.reference index f8684e6a39..176f19c6ff 100644 --- a/regtest/crystallization/rt-spherical-integral/colvar.reference +++ b/regtest/crystallization/rt-spherical-integral/colvar.reference @@ -1,6 +1,6 @@ #! FIELDS time iv b.bias b.force2 - 0.000000 1.0485 0.4455 8.9106 - 1.000000 0.9842 0.2741 5.4827 - 2.000000 1.0049 0.3249 6.4986 - 3.000000 0.9474 0.1949 3.8973 - 4.000000 0.9911 0.2907 5.8143 + 0.000000 1.0002 0.3131 6.2624 + 1.000000 0.9990 0.3100 6.2005 + 2.000000 0.9896 0.2870 5.7398 + 3.000000 1.0004 0.3135 6.2707 + 4.000000 0.9985 0.3089 6.1773 diff --git a/regtest/crystallization/rt-spherical-integral/forces.reference b/regtest/crystallization/rt-spherical-integral/forces.reference index 1d0ff64ec7..c39663bf34 100644 --- a/regtest/crystallization/rt-spherical-integral/forces.reference +++ b/regtest/crystallization/rt-spherical-integral/forces.reference @@ -1,10 +1,10 @@ 201 - -0.1864 0.0267 0.3014 -X 0.0003 -0.0003 -0.0003 -X -0.1329 0.1134 -0.1861 -X 0.1329 -0.1134 0.1861 -X 0.0714 0.0810 0.0905 -X -0.0717 -0.0808 -0.0902 + -0.0027 0.0026 0.0014 +X -0.0000 0.0000 0.0000 +X -0.0018 -0.0021 0.0002 +X 0.0018 0.0021 -0.0002 +X 0.0008 0.0006 0.0009 +X -0.0008 -0.0006 -0.0009 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 @@ -202,12 +202,12 @@ X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 201 - 0.0172 0.1320 -0.1770 -X -0.0001 -0.0000 0.0000 -X 0.0075 -0.0076 -0.0156 -X -0.0310 -0.0846 0.0847 -X -0.0074 0.0077 0.0156 -X 0.0310 0.0846 -0.0847 + 0.0000 -0.0036 0.0028 +X -0.0000 -0.0000 0.0000 +X 0.0002 -0.0001 -0.0005 +X -0.0003 0.0021 -0.0025 +X -0.0002 0.0001 0.0005 +X 0.0003 -0.0021 0.0025 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 @@ -405,12 +405,12 @@ X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 201 - 0.0128 -0.0660 0.0610 -X 0.0030 0.0044 0.0010 -X -0.0172 0.0225 0.0312 -X 0.0002 -0.0006 -0.0012 -X -0.0015 -0.0029 0.0038 -X 0.0156 -0.0235 -0.0348 + 0.0125 -0.0616 0.0512 +X 0.0070 0.0067 -0.0013 +X -0.0114 0.0116 0.0292 +X -0.0000 0.0001 0.0002 +X -0.0024 -0.0077 0.0035 +X 0.0069 -0.0107 -0.0316 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 @@ -608,12 +608,12 @@ X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 201 - -0.0155 0.0614 -0.0330 -X 0.0011 -0.0024 -0.0009 -X -0.0060 -0.0023 -0.0019 -X -0.0015 0.0069 0.0035 -X -0.0097 0.1341 0.0065 -X 0.0161 -0.1364 -0.0072 + -0.0001 -0.0073 0.0092 +X 0.0003 -0.0004 -0.0002 +X 0.0005 -0.0018 -0.0011 +X -0.0006 0.0018 0.0011 +X -0.0013 0.0014 -0.0038 +X 0.0011 -0.0009 0.0040 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 @@ -811,12 +811,12 @@ X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 201 - 0.0124 -0.0030 -0.0094 -X -0.0208 0.0213 0.0286 -X 0.0208 -0.0213 -0.0286 -X -0.0261 0.0137 0.0262 + 0.0057 -0.0117 0.0061 +X 0.0005 0.0019 0.0006 +X -0.0005 -0.0019 -0.0006 +X 0.0148 0.0097 0.0061 X -0.0000 -0.0000 0.0000 -X 0.0261 -0.0137 -0.0262 +X -0.0148 -0.0097 -0.0061 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 X 0.0000 0.0000 0.0000 diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp index 3b89af0f2d..4b15dee2a3 100644 --- a/src/gridtools/GridVessel.cpp +++ b/src/gridtools/GridVessel.cpp @@ -111,11 +111,47 @@ void GridVessel::setBounds( const std::vector& smin, const std::vec } void GridVessel::setupFibonacciGrid( const unsigned& np ) { - bounds_set=true; - npoints = np; fib_increment = pi*( 3 - sqrt(5) ); + bounds_set=true; root5 = sqrt(5); + npoints = np; golden = ( 1 + sqrt(5) ) / 2.0; igolden = golden - 1; + fib_increment = 2*pi*igolden; log_golden2 = std::log( golden*golden ); fib_offset = 2 / static_cast( npoints ); - Random random; fib_rnd = std::floor( npoints*random.RandU01() ); + fib_shift = fib_offset/2 - 1; resize(); + + std::vector icoord( dimension ), jcoord( dimension ); + // Find minimum distance between each pair of points + std::vector tindices( dimension ); std::vector mindists( npoints ); + for(unsigned i=0; imindists[i] ) mindists[i]=dot; + } + } + // And now take minimum of dot products + double min=mindists[0]; + for(unsigned i=1; ifinal_cutoff ) { fib_nlist[i].push_back(j); } + } + } } std::string GridVessel::description() { @@ -170,8 +206,43 @@ void GridVessel::getIndices( const std::vector& point, std::vector& point ) const { plumed_dbg_assert( gtype==flat && bounds_set && point.size()==dimension ); - std::vector indices(dimension); getIndices( point, indices ); - return getIndex( indices ); + if( gtype==flat ) { + std::vector indices(dimension); getIndices( point, indices ); + return getIndex( indices ); + } else if( gtype==fibonacci ) { + return getFibonacciIndex( point ); + } else { + plumed_error(); + } +} + +unsigned GridVessel::getFibonacciIndex( const std::vector& p ) const { + plumed_dbg_assert( gtype==fibonacci ); + // Convert input point to coordinates on cylinder + unsigned k=2; double phi = atan2( p[2], p[0] ), sinthet2 = 1 - p[1]*p[1]; + // Calculate power to raise golden ratio + if( sinthet2 B(2,2), invB(2,2); std::vector thisp(3); + B(0,0) = 2*pi*((F0+1)*igolden - std::floor((F0+1)*igolden)) - fib_increment; + B(0,1) = 2*pi*((F1+1)*igolden - std::floor((F1+1)*igolden)) - fib_increment; + B(1,0) = -2*F0/npoints; B(1,1) = -2*F1/npoints; Invert( B, invB ); + std::vector vv(2), rc(2); vv[0]=-phi; vv[1] = p[1] - fib_shift; + mult( invB, vv, rc ); std::vector c(2); c[0]=std::floor(rc[0]); c[1]=std::floor(rc[1]); + unsigned outind; double mindist = 10000000.; + for(int s=0; s<4; ++s) { + double ttt, costheta = B(1,0)*( c[0] + s%2 ) + B(1,1)*( c[1] + s/2 ) + fib_shift; + if( costheta>1 ) ttt=1; else if( costheta<-1 ) ttt=-1; else ttt=costheta; + costheta = 2*ttt - costheta; + unsigned i = std::floor( 0.5*npoints*(1+costheta) ); getFibonacciCoordinates( i, thisp ); + double dist=0; for(unsigned j=0; j<3; ++j) { double tmp=thisp[j]-p[j]; dist += tmp*tmp; } + if( dist& nnbin, std::vector& indices ) const { @@ -183,7 +254,6 @@ void GridVessel::convertIndexToIndices( const unsigned& index, const std::vector if(dimension>=2) { // I think this is wrong indices[dimension-1]=(kk-indices[dimension-2])/nnbin[dimension-2]; } - } void GridVessel::getIndices( const unsigned& index, std::vector& indices ) const { @@ -197,22 +267,27 @@ void GridVessel::getGridPointCoordinates( const unsigned& ipoint, std::vector& tindices, std::vector& x ) const { plumed_dbg_assert( bounds_set && x.size()==dimension && tindices.size()==dimension && ipoint& tindices, std::vector& x ) const { + plumed_dbg_assert( gtype==flat ); getIndices( ipoint, tindices ); + for(unsigned i=0; i& x ) const { + plumed_dbg_assert( gtype==fibonacci ); + x[1] = (ipoint*fib_offset) + fib_shift; double r = sqrt( 1 - x[1]*x[1] ); + double phi = ipoint*fib_increment; x[0] = r*cos(phi); x[2] = r*sin(phi); + double norm=0; for(unsigned j=0; j<3; ++j) norm+=x[j]*x[j]; + norm = sqrt(norm); for(unsigned j=0; j<3; ++j) x[j] = x[j] / norm; +} + void GridVessel::getSplineNeighbors( const unsigned& mybox, std::vector& mysneigh ) const { plumed_dbg_assert( gtype==flat ); mysneigh.resize( static_cast(pow(2.,dimension)) ); @@ -285,11 +360,20 @@ std::vector GridVessel::getNbin() const { void GridVessel::getNeighbors( const std::vector& pp, const std::vector& nneigh, unsigned& num_neighbors, std::vector& neighbors ) const { - plumed_dbg_assert( gtype==flat && bounds_set && nneigh.size()==dimension ); - - std::vector indices( dimension ); - for(unsigned i=0; i indices( dimension ); + for(unsigned i=0; i& indices, const std::vector& nneigh, @@ -360,7 +444,7 @@ double GridVessel::getValueAndDerivatives( const std::vector& x, const u std::vector nindices(dimension); std::vector indices(dimension); getIndices( x, indices ); std::vector neigh; getSplineNeighbors( getIndex(indices), neigh ); - std::vector xfloor(dimension); getGridPointCoordinates( getIndex(x), xfloor ); + std::vector xfloor(dimension); getFlatGridCoordinates( getIndex(x), nindices, xfloor ); // loop over neighbors for(unsigned int ipoint=0; ipoint > fib_nlist; /// Units for Gaussian Cube file double cube_units; /// This flag is used to check if the user has created a valid input @@ -81,6 +83,12 @@ class GridVessel : public vesselbase::AveragingVessel { std::vector active; /// Convert a point in space the the correspoinding grid point unsigned getIndex( const std::vector& p ) const ; +/// Get the index of the closest point on the fibonacci sphere + unsigned getFibonacciIndex( const std::vector& p ) const ; +/// Get the flat grid coordinates + void getFlatGridCoordinates( const unsigned& ipoint, std::vector& tindices, std::vector& x ) const ; +/// Get the coordinates on the Fibonacci grid + void getFibonacciCoordinates( const unsigned& ipoint, std::vector& x ) const ; public: /// keywords static void registerKeywords( Keywords& keys ); @@ -92,6 +100,8 @@ class GridVessel : public vesselbase::AveragingVessel { std::string getType() const ; /// Set the minimum and maximum of the grid virtual void setBounds( const std::vector& smin, const std::vector& smax, const std::vector& nbins, const std::vector& spacing ); +/// Get the cutoff to use for the Fibonacci spheres + virtual double getFibonacciCutoff() const ; /// Setup the grid if it is a fibonacci grid on the surface of a sphere void setupFibonacciGrid( const unsigned& np ); /// Get a description of the grid to output to the log @@ -266,6 +276,11 @@ std::string GridVessel::getType() const { plumed_error(); } +inline +double GridVessel::getFibonacciCutoff() const { + return 0.0; +} + } } #endif diff --git a/src/gridtools/HistogramOnGrid.cpp b/src/gridtools/HistogramOnGrid.cpp index 1ddae05a4c..73ec78ab6b 100644 --- a/src/gridtools/HistogramOnGrid.cpp +++ b/src/gridtools/HistogramOnGrid.cpp @@ -52,6 +52,10 @@ HistogramOnGrid::HistogramOnGrid( const vesselbase::VesselOptions& da ): } } +double HistogramOnGrid::getFibonacciCutoff() const { + return std::log( epsilon / von_misses_norm ) / von_misses_concentration; +} + bool HistogramOnGrid::noDiscreteKernels() const { return !discrete; } @@ -79,10 +83,11 @@ KernelFunctions* HistogramOnGrid::getKernelAndNeighbors( std::vector& po KernelFunctions* kernel = new KernelFunctions( point, bandwidths, kerneltype, false, 1.0, true ); getNeighbors( kernel->getCenter(), nneigh, num_neigh, neighbors ); return kernel; + } else if( getType()=="fibonacci" ) { + getNeighbors( point, nneigh, num_neigh, neighbors ); + return NULL; } else { - num_neigh = getNumberOfPoints(); - if( neighbors.size()!=getNumberOfPoints() ) neighbors.resize( getNumberOfPoints() ); - for(unsigned i=0; i& buffer, std::vector& finalForces ); bool noDiscreteKernels() const ; + double getFibonacciCutoff() const ; }; inline From c010cbfa272ec45160d8671e978bb9e1643f7ce3 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Sun, 7 May 2017 17:20:36 +0100 Subject: [PATCH 58/62] Small fix to plumed_dbg_assert - nngrid not needed for fibonacci grids --- src/gridtools/GridVessel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gridtools/GridVessel.cpp b/src/gridtools/GridVessel.cpp index 4b15dee2a3..126b052082 100644 --- a/src/gridtools/GridVessel.cpp +++ b/src/gridtools/GridVessel.cpp @@ -360,9 +360,10 @@ std::vector GridVessel::getNbin() const { void GridVessel::getNeighbors( const std::vector& pp, const std::vector& nneigh, unsigned& num_neighbors, std::vector& neighbors ) const { - plumed_dbg_assert( bounds_set && nneigh.size()==dimension ); + plumed_dbg_assert( bounds_set ); if( gtype == flat ) { + plumed_dbg_assert( nneigh.size()==dimension ); std::vector indices( dimension ); for(unsigned i=0; i Date: Mon, 8 May 2017 19:19:39 +0100 Subject: [PATCH 59/62] Fix to bug in multicolvars + filters This fixes a problem in the way atoms are setup for calculations where you take an input from a multicolvar filter as input to a new multicolvar if SPECIESA and SPECIESB are used. For instance you might be calculating Q6 for those atoms that have a coordination number greater than 4 --- .../rt-q6-subset/deriv3.reference | 584 +++++++++--------- src/crystallization/CubicHarmonicBase.cpp | 3 +- src/crystallization/OrientationSphere.cpp | 3 +- src/crystallization/Steinhardt.cpp | 4 +- src/multicolvar/CoordinationNumbers.cpp | 3 +- src/multicolvar/LocalAverage.cpp | 3 +- src/multicolvar/MultiColvarBase.cpp | 9 +- 7 files changed, 311 insertions(+), 298 deletions(-) diff --git a/regtest/crystallization/rt-q6-subset/deriv3.reference b/regtest/crystallization/rt-q6-subset/deriv3.reference index ddb88fd1cc..5b6599395d 100644 --- a/regtest/crystallization/rt-q6-subset/deriv3.reference +++ b/regtest/crystallization/rt-q6-subset/deriv3.reference @@ -1,19 +1,19 @@ #! FIELDS time parameter w6.mean - 0.000000 0 -0.0263 - 0.000000 1 -0.0045 - 0.000000 2 0.0090 - 0.000000 3 -0.0214 - 0.000000 4 0.0054 - 0.000000 5 -0.0470 - 0.000000 6 0.0387 - 0.000000 7 -0.0254 - 0.000000 8 -0.0831 - 0.000000 9 -0.0156 - 0.000000 10 0.0026 - 0.000000 11 0.0182 - 0.000000 12 0.0013 - 0.000000 13 0.0369 - 0.000000 14 0.0071 + 0.000000 0 -0.0199 + 0.000000 1 -0.0007 + 0.000000 2 0.0263 + 0.000000 3 -0.0219 + 0.000000 4 0.0074 + 0.000000 5 -0.0449 + 0.000000 6 0.0372 + 0.000000 7 -0.0158 + 0.000000 8 -0.0789 + 0.000000 9 -0.0129 + 0.000000 10 0.0002 + 0.000000 11 0.0222 + 0.000000 12 0.0052 + 0.000000 13 0.0257 + 0.000000 14 0.0018 0.000000 15 0.0000 0.000000 16 0.0000 0.000000 17 0.0000 @@ -29,198 +29,198 @@ 0.000000 27 0.0000 0.000000 28 0.0000 0.000000 29 0.0000 - 0.000000 30 -0.0134 - 0.000000 31 -0.0220 + 0.000000 30 -0.0144 + 0.000000 31 -0.0214 0.000000 32 0.0061 0.000000 33 0.0000 0.000000 34 0.0000 0.000000 35 -0.0000 - 0.000000 36 0.0091 - 0.000000 37 0.0053 - 0.000000 38 -0.0099 + 0.000000 36 0.0101 + 0.000000 37 0.0059 + 0.000000 38 -0.0108 0.000000 39 -0.0000 0.000000 40 0.0000 0.000000 41 0.0000 0.000000 42 0.0000 - 0.000000 43 -0.0001 + 0.000000 43 -0.0000 0.000000 44 -0.0001 - 0.000000 45 -0.0133 - 0.000000 46 0.0004 - 0.000000 47 0.0048 - 0.000000 48 0.0117 + 0.000000 45 -0.0131 + 0.000000 46 -0.0018 + 0.000000 47 0.0025 + 0.000000 48 0.0105 0.000000 49 -0.0055 - 0.000000 50 0.0012 - 0.000000 51 -0.0006 - 0.000000 52 -0.0006 + 0.000000 50 0.0005 + 0.000000 51 -0.0005 + 0.000000 52 -0.0005 0.000000 53 0.0005 - 0.000000 54 0.0070 - 0.000000 55 0.0014 + 0.000000 54 0.0032 + 0.000000 55 -0.0014 0.000000 56 0.0147 - 0.000000 57 -0.0000 - 0.000000 58 0.0002 - 0.000000 59 0.0002 + 0.000000 57 0.0000 + 0.000000 58 0.0001 + 0.000000 59 0.0001 0.000000 60 0.0000 0.000000 61 0.0000 0.000000 62 0.0000 - 0.000000 63 0.0096 - 0.000000 64 -0.0058 - 0.000000 65 0.0032 + 0.000000 63 0.0088 + 0.000000 64 -0.0063 + 0.000000 65 0.0021 0.000000 66 0.0000 0.000000 67 0.0000 0.000000 68 0.0000 - 0.000000 69 -0.0040 - 0.000000 70 -0.0035 - 0.000000 71 0.0148 - 0.000000 72 -0.0008 - 0.000000 73 0.0051 - 0.000000 74 0.0074 - 0.000000 75 0.0005 - 0.000000 76 -0.0009 - 0.000000 77 -0.0009 - 0.000000 78 0.0003 - 0.000000 79 -0.0005 - 0.000000 80 -0.0002 - 0.000000 81 0.0035 - 0.000000 82 0.0005 - 0.000000 83 -0.0010 - 0.000000 84 0.0037 - 0.000000 85 0.0027 - 0.000000 86 -0.0008 - 0.000000 87 0.0077 - 0.000000 88 0.0014 - 0.000000 89 -0.0000 + 0.000000 69 -0.0026 + 0.000000 70 -0.0040 + 0.000000 71 0.0156 + 0.000000 72 0.0034 + 0.000000 73 0.0079 + 0.000000 74 0.0049 + 0.000000 75 -0.0004 + 0.000000 76 -0.0011 + 0.000000 77 -0.0015 + 0.000000 78 0.0002 + 0.000000 79 -0.0004 + 0.000000 80 -0.0001 + 0.000000 81 0.0031 + 0.000000 82 0.0012 + 0.000000 83 -0.0017 + 0.000000 84 0.0022 + 0.000000 85 0.0000 + 0.000000 86 -0.0023 + 0.000000 87 0.0072 + 0.000000 88 0.0022 + 0.000000 89 0.0017 0.000000 90 -0.0000 0.000000 91 0.0000 0.000000 92 0.0000 - 0.000000 93 0.0074 - 0.000000 94 -0.0047 - 0.000000 95 0.0023 + 0.000000 93 0.0067 + 0.000000 94 -0.0038 + 0.000000 95 0.0024 0.000000 96 -0.0000 0.000000 97 -0.0000 0.000000 98 0.0000 - 0.000000 99 -0.0101 - 0.000000 100 0.0184 - 0.000000 101 -0.0038 - 0.000000 102 -0.0063 - 0.000000 103 -0.0019 - 0.000000 104 0.0027 - 0.000000 105 0.0025 - 0.000000 106 0.0028 - 0.000000 107 0.0029 + 0.000000 99 -0.0104 + 0.000000 100 0.0198 + 0.000000 101 -0.0040 + 0.000000 102 -0.0051 + 0.000000 103 -0.0016 + 0.000000 104 0.0020 + 0.000000 105 0.0018 + 0.000000 106 0.0030 + 0.000000 107 0.0032 0.000000 108 0.0000 0.000000 109 0.0000 0.000000 110 0.0000 0.000000 111 -0.0000 0.000000 112 0.0001 - 0.000000 113 -0.0001 + 0.000000 113 -0.0000 0.000000 114 0.0000 0.000000 115 0.0000 0.000000 116 -0.0000 - 0.000000 117 -0.0030 - 0.000000 118 -0.0143 - 0.000000 119 -0.0110 + 0.000000 117 -0.0041 + 0.000000 118 -0.0116 + 0.000000 119 -0.0089 0.000000 120 0.0055 - 0.000000 121 0.0043 - 0.000000 122 0.0234 + 0.000000 121 0.0037 + 0.000000 122 0.0190 0.000000 123 -0.0000 0.000000 124 0.0000 0.000000 125 0.0000 - 0.000000 126 -0.0040 - 0.000000 127 0.0007 - 0.000000 128 -0.0057 - 0.000000 129 0.0024 - 0.000000 130 -0.0056 - 0.000000 131 -0.0244 - 0.000000 132 0.0020 - 0.000000 133 -0.0059 - 0.000000 134 0.0076 - 0.000000 135 -0.0070 - 0.000000 136 0.0009 - 0.000000 137 0.0080 + 0.000000 126 -0.0028 + 0.000000 127 -0.0012 + 0.000000 128 -0.0041 + 0.000000 129 0.0044 + 0.000000 130 -0.0054 + 0.000000 131 -0.0224 + 0.000000 132 0.0011 + 0.000000 133 -0.0034 + 0.000000 134 0.0059 + 0.000000 135 -0.0090 + 0.000000 136 0.0019 + 0.000000 137 0.0088 0.000000 138 -0.0000 0.000000 139 0.0000 0.000000 140 0.0000 0.000000 141 0.0000 0.000000 142 -0.0002 0.000000 143 -0.0001 - 0.000000 144 -0.0003 - 0.000000 145 -0.0181 - 0.000000 146 0.0127 - 0.000000 147 0.0003 - 0.000000 148 -0.0033 - 0.000000 149 0.0012 - 0.000000 150 -0.0001 + 0.000000 144 -0.0033 + 0.000000 145 -0.0162 + 0.000000 146 0.0084 + 0.000000 147 -0.0001 + 0.000000 148 -0.0038 + 0.000000 149 0.0011 + 0.000000 150 -0.0000 0.000000 151 -0.0000 0.000000 152 0.0000 - 0.000000 153 0.0085 - 0.000000 154 -0.0073 - 0.000000 155 0.0006 + 0.000000 153 0.0095 + 0.000000 154 -0.0087 + 0.000000 155 -0.0001 0.000000 156 -0.0000 - 0.000000 157 0.0000 + 0.000000 157 -0.0000 0.000000 158 0.0000 - 0.000000 159 -0.0000 - 0.000000 160 -0.0001 - 0.000000 161 -0.0004 - 0.000000 162 -0.0097 - 0.000000 163 0.0027 - 0.000000 164 -0.0004 - 0.000000 165 0.0014 - 0.000000 166 -0.0010 - 0.000000 167 0.0075 - 0.000000 168 0.0057 - 0.000000 169 -0.0039 - 0.000000 170 0.0127 - 0.000000 171 0.0075 - 0.000000 172 -0.0013 - 0.000000 173 0.0002 + 0.000000 159 -0.0004 + 0.000000 160 0.0008 + 0.000000 161 -0.0007 + 0.000000 162 -0.0095 + 0.000000 163 0.0021 + 0.000000 164 -0.0005 + 0.000000 165 0.0018 + 0.000000 166 -0.0015 + 0.000000 167 0.0072 + 0.000000 168 0.0062 + 0.000000 169 -0.0028 + 0.000000 170 0.0102 + 0.000000 171 0.0066 + 0.000000 172 0.0011 + 0.000000 173 -0.0011 0.000000 174 -0.0000 0.000000 175 -0.0000 0.000000 176 -0.0000 - 0.000000 177 0.0019 - 0.000000 178 0.0004 - 0.000000 179 0.0028 - 0.000000 180 -0.0020 - 0.000000 181 -0.0043 - 0.000000 182 0.0106 + 0.000000 177 0.0016 + 0.000000 178 0.0001 + 0.000000 179 0.0017 + 0.000000 180 -0.0007 + 0.000000 181 -0.0048 + 0.000000 182 0.0101 0.000000 183 -0.0000 0.000000 184 -0.0001 0.000000 185 0.0000 - 0.000000 186 0.0051 - 0.000000 187 0.0206 - 0.000000 188 -0.0031 + 0.000000 186 0.0031 + 0.000000 187 0.0176 + 0.000000 188 -0.0028 0.000000 189 0.0000 0.000000 190 0.0000 0.000000 191 0.0000 - 0.000000 192 0.0019 - 0.000000 193 0.0029 - 0.000000 194 -0.0073 - 0.000000 195 0.0023 - 0.000000 196 0.0096 - 0.000000 197 -0.0043 - 0.000000 198 0.0013 - 0.000000 199 0.0055 - 0.000000 200 0.0042 - 0.000000 201 0.0019 - 0.000000 202 -0.0002 - 0.000000 203 -0.0001 + 0.000000 192 0.0003 + 0.000000 193 0.0035 + 0.000000 194 -0.0084 + 0.000000 195 0.0015 + 0.000000 196 0.0079 + 0.000000 197 -0.0050 + 0.000000 198 0.0035 + 0.000000 199 0.0047 + 0.000000 200 0.0030 + 0.000000 201 0.0015 + 0.000000 202 -0.0003 + 0.000000 203 -0.0002 0.000000 204 -0.0000 0.000000 205 0.0000 0.000000 206 -0.0000 - 0.000000 207 0.0000 - 0.000000 208 0.0000 - 0.000000 209 0.0000 - 0.000000 210 0.0000 - 0.000000 211 0.0000 - 0.000000 212 0.0000 - 0.000000 213 0.0000 - 0.000000 214 0.0000 - 0.000000 215 0.0000 - 0.000000 216 0.0000 - 0.000000 217 0.0000 - 0.000000 218 0.0000 - 0.000000 219 0.0000 - 0.000000 220 0.0000 - 0.000000 221 0.0000 + 0.000000 207 -0.0064 + 0.000000 208 -0.0037 + 0.000000 209 -0.0173 + 0.000000 210 0.0005 + 0.000000 211 -0.0020 + 0.000000 212 -0.0021 + 0.000000 213 0.0015 + 0.000000 214 -0.0096 + 0.000000 215 -0.0042 + 0.000000 216 -0.0027 + 0.000000 217 0.0024 + 0.000000 218 -0.0040 + 0.000000 219 -0.0039 + 0.000000 220 0.0113 + 0.000000 221 0.0053 0.000000 222 0.0000 0.000000 223 0.0000 0.000000 224 0.0000 @@ -236,182 +236,182 @@ 0.000000 234 0.0000 0.000000 235 0.0000 0.000000 236 0.0000 - 0.000000 237 0.0000 - 0.000000 238 0.0000 - 0.000000 239 0.0000 + 0.000000 237 0.0010 + 0.000000 238 -0.0005 + 0.000000 239 0.0001 0.000000 240 0.0000 0.000000 241 0.0000 - 0.000000 242 0.0000 - 0.000000 243 0.0000 - 0.000000 244 0.0000 - 0.000000 245 0.0000 + 0.000000 242 -0.0000 + 0.000000 243 -0.0010 + 0.000000 244 -0.0006 + 0.000000 245 0.0009 0.000000 246 0.0000 - 0.000000 247 0.0000 + 0.000000 247 -0.0000 0.000000 248 0.0000 - 0.000000 249 0.0000 - 0.000000 250 0.0000 - 0.000000 251 0.0000 - 0.000000 252 0.0000 - 0.000000 253 0.0000 - 0.000000 254 0.0000 - 0.000000 255 0.0000 - 0.000000 256 0.0000 - 0.000000 257 0.0000 - 0.000000 258 0.0000 - 0.000000 259 0.0000 + 0.000000 249 -0.0000 + 0.000000 250 -0.0000 + 0.000000 251 -0.0000 + 0.000000 252 -0.0002 + 0.000000 253 0.0022 + 0.000000 254 0.0023 + 0.000000 255 0.0012 + 0.000000 256 -0.0000 + 0.000000 257 0.0006 + 0.000000 258 -0.0001 + 0.000000 259 -0.0000 0.000000 260 0.0000 - 0.000000 261 0.0000 - 0.000000 262 0.0000 - 0.000000 263 0.0000 - 0.000000 264 0.0000 - 0.000000 265 0.0000 + 0.000000 261 0.0038 + 0.000000 262 0.0028 + 0.000000 263 -0.0000 + 0.000000 264 -0.0000 + 0.000000 265 0.0001 0.000000 266 0.0000 0.000000 267 0.0000 0.000000 268 0.0000 0.000000 269 0.0000 - 0.000000 270 0.0000 - 0.000000 271 0.0000 - 0.000000 272 0.0000 - 0.000000 273 0.0000 - 0.000000 274 0.0000 + 0.000000 270 0.0008 + 0.000000 271 0.0005 + 0.000000 272 0.0012 + 0.000000 273 -0.0000 + 0.000000 274 -0.0000 0.000000 275 0.0000 - 0.000000 276 0.0000 - 0.000000 277 0.0000 - 0.000000 278 0.0000 - 0.000000 279 0.0000 - 0.000000 280 0.0000 - 0.000000 281 0.0000 - 0.000000 282 0.0000 - 0.000000 283 0.0000 - 0.000000 284 0.0000 - 0.000000 285 0.0000 - 0.000000 286 0.0000 - 0.000000 287 0.0000 - 0.000000 288 0.0000 - 0.000000 289 0.0000 - 0.000000 290 0.0000 - 0.000000 291 0.0000 - 0.000000 292 0.0000 - 0.000000 293 0.0000 - 0.000000 294 0.0000 - 0.000000 295 0.0000 - 0.000000 296 0.0000 + 0.000000 276 -0.0014 + 0.000000 277 0.0005 + 0.000000 278 -0.0009 + 0.000000 279 -0.0042 + 0.000000 280 -0.0028 + 0.000000 281 0.0025 + 0.000000 282 0.0009 + 0.000000 283 0.0002 + 0.000000 284 0.0006 + 0.000000 285 0.0001 + 0.000000 286 -0.0001 + 0.000000 287 -0.0000 + 0.000000 288 0.0004 + 0.000000 289 -0.0007 + 0.000000 290 0.0007 + 0.000000 291 0.0015 + 0.000000 292 0.0027 + 0.000000 293 0.0015 + 0.000000 294 0.0005 + 0.000000 295 -0.0008 + 0.000000 296 -0.0017 0.000000 297 0.0000 - 0.000000 298 0.0000 - 0.000000 299 0.0000 - 0.000000 300 0.0000 - 0.000000 301 0.0000 - 0.000000 302 0.0000 + 0.000000 298 -0.0000 + 0.000000 299 -0.0000 + 0.000000 300 0.0007 + 0.000000 301 -0.0009 + 0.000000 302 -0.0001 0.000000 303 0.0000 - 0.000000 304 0.0000 + 0.000000 304 -0.0000 0.000000 305 0.0000 - 0.000000 306 0.0000 - 0.000000 307 0.0000 - 0.000000 308 0.0000 - 0.000000 309 0.0000 - 0.000000 310 0.0000 - 0.000000 311 0.0000 - 0.000000 312 0.0000 - 0.000000 313 0.0000 - 0.000000 314 0.0000 + 0.000000 306 0.0002 + 0.000000 307 -0.0014 + 0.000000 308 0.0002 + 0.000000 309 -0.0012 + 0.000000 310 -0.0003 + 0.000000 311 0.0007 + 0.000000 312 0.0007 + 0.000000 313 -0.0002 + 0.000000 314 -0.0003 0.000000 315 0.0000 0.000000 316 0.0000 0.000000 317 0.0000 - 0.000000 318 0.0000 + 0.000000 318 -0.0000 0.000000 319 0.0000 - 0.000000 320 0.0000 + 0.000000 320 -0.0000 0.000000 321 0.0000 0.000000 322 0.0000 - 0.000000 323 0.0000 - 0.000000 324 0.0000 - 0.000000 325 0.0000 - 0.000000 326 0.0000 - 0.000000 327 0.0000 - 0.000000 328 0.0000 - 0.000000 329 0.0000 - 0.000000 330 0.0000 - 0.000000 331 0.0000 + 0.000000 323 -0.0000 + 0.000000 324 0.0011 + 0.000000 325 -0.0026 + 0.000000 326 -0.0021 + 0.000000 327 -0.0001 + 0.000000 328 0.0006 + 0.000000 329 0.0044 + 0.000000 330 -0.0000 + 0.000000 331 -0.0000 0.000000 332 0.0000 - 0.000000 333 0.0000 - 0.000000 334 0.0000 - 0.000000 335 0.0000 - 0.000000 336 0.0000 - 0.000000 337 0.0000 - 0.000000 338 0.0000 - 0.000000 339 0.0000 - 0.000000 340 0.0000 - 0.000000 341 0.0000 - 0.000000 342 0.0000 - 0.000000 343 0.0000 - 0.000000 344 0.0000 - 0.000000 345 0.0000 + 0.000000 333 -0.0013 + 0.000000 334 0.0019 + 0.000000 335 -0.0016 + 0.000000 336 -0.0020 + 0.000000 337 -0.0002 + 0.000000 338 -0.0019 + 0.000000 339 0.0010 + 0.000000 340 -0.0025 + 0.000000 341 0.0017 + 0.000000 342 0.0020 + 0.000000 343 -0.0010 + 0.000000 344 -0.0008 + 0.000000 345 -0.0000 0.000000 346 0.0000 - 0.000000 347 0.0000 + 0.000000 347 -0.0000 0.000000 348 0.0000 - 0.000000 349 0.0000 + 0.000000 349 -0.0000 0.000000 350 0.0000 - 0.000000 351 0.0000 - 0.000000 352 0.0000 - 0.000000 353 0.0000 - 0.000000 354 0.0000 - 0.000000 355 0.0000 - 0.000000 356 0.0000 - 0.000000 357 0.0000 - 0.000000 358 0.0000 + 0.000000 351 0.0030 + 0.000000 352 -0.0019 + 0.000000 353 0.0043 + 0.000000 354 0.0004 + 0.000000 355 0.0004 + 0.000000 356 0.0001 + 0.000000 357 -0.0000 + 0.000000 358 -0.0000 0.000000 359 0.0000 - 0.000000 360 0.0000 - 0.000000 361 0.0000 - 0.000000 362 0.0000 - 0.000000 363 0.0000 + 0.000000 360 -0.0010 + 0.000000 361 0.0015 + 0.000000 362 0.0006 + 0.000000 363 -0.0000 0.000000 364 0.0000 0.000000 365 0.0000 - 0.000000 366 0.0000 - 0.000000 367 0.0000 - 0.000000 368 0.0000 - 0.000000 369 0.0000 - 0.000000 370 0.0000 - 0.000000 371 0.0000 - 0.000000 372 0.0000 - 0.000000 373 0.0000 - 0.000000 374 0.0000 - 0.000000 375 0.0000 - 0.000000 376 0.0000 - 0.000000 377 0.0000 - 0.000000 378 0.0000 - 0.000000 379 0.0000 - 0.000000 380 0.0000 - 0.000000 381 0.0000 - 0.000000 382 0.0000 - 0.000000 383 0.0000 - 0.000000 384 0.0000 - 0.000000 385 0.0000 - 0.000000 386 0.0000 - 0.000000 387 0.0000 - 0.000000 388 0.0000 - 0.000000 389 0.0000 + 0.000000 366 0.0004 + 0.000000 367 -0.0009 + 0.000000 368 0.0003 + 0.000000 369 -0.0002 + 0.000000 370 0.0006 + 0.000000 371 0.0001 + 0.000000 372 -0.0003 + 0.000000 373 0.0004 + 0.000000 374 0.0003 + 0.000000 375 -0.0005 + 0.000000 376 -0.0011 + 0.000000 377 0.0025 + 0.000000 378 0.0010 + 0.000000 379 -0.0024 + 0.000000 380 0.0013 + 0.000000 381 -0.0000 + 0.000000 382 -0.0000 + 0.000000 383 -0.0000 + 0.000000 384 0.0003 + 0.000000 385 0.0003 + 0.000000 386 0.0011 + 0.000000 387 -0.0013 + 0.000000 388 0.0006 + 0.000000 389 0.0005 0.000000 390 0.0000 0.000000 391 0.0000 - 0.000000 392 0.0000 - 0.000000 393 0.0000 - 0.000000 394 0.0000 - 0.000000 395 0.0000 + 0.000000 392 -0.0000 + 0.000000 393 0.0019 + 0.000000 394 0.0029 + 0.000000 395 -0.0003 0.000000 396 0.0000 0.000000 397 0.0000 0.000000 398 0.0000 - 0.000000 399 0.0000 - 0.000000 400 0.0000 - 0.000000 401 0.0000 - 0.000000 402 0.0000 - 0.000000 403 0.0000 - 0.000000 404 0.0000 - 0.000000 405 0.0000 - 0.000000 406 0.0000 - 0.000000 407 0.0000 - 0.000000 408 0.0000 + 0.000000 399 0.0016 + 0.000000 400 -0.0005 + 0.000000 401 0.0010 + 0.000000 402 0.0007 + 0.000000 403 0.0017 + 0.000000 404 0.0007 + 0.000000 405 -0.0022 + 0.000000 406 0.0008 + 0.000000 407 0.0012 + 0.000000 408 0.0003 0.000000 409 0.0000 0.000000 410 0.0000 - 0.000000 411 0.0000 - 0.000000 412 0.0000 + 0.000000 411 -0.0000 + 0.000000 412 -0.0000 0.000000 413 0.0000 0.000000 414 -0.0010 0.000000 415 -0.0030 diff --git a/src/crystallization/CubicHarmonicBase.cpp b/src/crystallization/CubicHarmonicBase.cpp index a51b066d6b..c7629e726b 100644 --- a/src/crystallization/CubicHarmonicBase.cpp +++ b/src/crystallization/CubicHarmonicBase.cpp @@ -102,7 +102,8 @@ double CubicHarmonicBase::compute( const unsigned& tindex, multicolvar::AtomValu if ( (d2=distance[0]*distance[0])epsilon ){ double sw = switchingFunction.calculateSqr( d2, dfunc ); diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp index 1f0dc49697..9d544d8fd3 100644 --- a/src/crystallization/OrientationSphere.cpp +++ b/src/crystallization/OrientationSphere.cpp @@ -83,7 +83,8 @@ double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValu Vector& distance=myatoms.getPosition(i); if ( (d2=distance[0]*distance[0])epsilon ){ sw = switchingFunction.calculateSqr( d2, dfunc ); diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp index 0cfeb44757..398625a650 100644 --- a/src/crystallization/Steinhardt.cpp +++ b/src/crystallization/Steinhardt.cpp @@ -81,7 +81,9 @@ void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { Vector& distance=myatoms.getPosition(i); // getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); if ( (d2=distance[0]*distance[0])epsilon ){ + dlen = sqrt(d2); sw = switchingFunction.calculate( dlen, dfunc ); accumulateSymmetryFunction( -1, i, sw, (+dfunc)*distance, (-dfunc)*Tensor( distance,distance ), myatoms ); diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp index a3823b4887..c7ea37a036 100644 --- a/src/multicolvar/CoordinationNumbers.cpp +++ b/src/multicolvar/CoordinationNumbers.cpp @@ -127,7 +127,8 @@ double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myat Vector& distance=myatoms.getPosition(i); if ( (d2=distance[0]*distance[0])epsilon ){ sw = switchingFunction.calculateSqr( d2, dfunc ); accumulateSymmetryFunction( 1, i, sw, (dfunc)*distance, (-dfunc)*Tensor(distance,distance), myatoms ); diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index 7f5edf6940..171aa61baf 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -183,7 +183,8 @@ double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ) c Vector& distance=myatoms.getPosition(i); // getSeparation( myatoms.getPosition(0), myatoms.getPosition(i) ); if ( (d2=distance[0]*distance[0])epsilon) { sw = switchingFunction.calculateSqr( d2, dfunc ); diff --git a/src/multicolvar/MultiColvarBase.cpp b/src/multicolvar/MultiColvarBase.cpp index 6babc9254c..7cd1186771 100644 --- a/src/multicolvar/MultiColvarBase.cpp +++ b/src/multicolvar/MultiColvarBase.cpp @@ -376,8 +376,15 @@ void MultiColvarBase::setupMultiColvarBase( const std::vector& atoms bool found=false; unsigned inum; for(unsigned j=0; j0 && atom_lab[j].first>0 ) { - if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== + if( atom_lab[nat1+i].first==atom_lab[j].first && + mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ) { found=true; inum=j; break; } + } else if( atom_lab[nat1+i].first>0 ){ + if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== + all_atoms[atom_lab[j].second] ){ found=true; inum=nat1 + i; break; } + } else if( atom_lab[j].first>0 ){ + if( all_atoms[atom_lab[nat1+i].second]== + mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ) { found=true; inum=nat1+i; break; } } else if( all_atoms[atom_lab[nat1+i].second]==all_atoms[atom_lab[j].second] ) { found=true; inum=j; break; } } // This prevents mistakes being made in colvar setup From a1a6393cb0616efedc7ab84ddf6585b480c2ae71 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Mon, 8 May 2017 19:26:45 +0100 Subject: [PATCH 60/62] Added details of last commit to change log --- CHANGES/v2.3.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES/v2.3.txt b/CHANGES/v2.3.txt index b2586b9e30..184246aa64 100644 --- a/CHANGES/v2.3.txt +++ b/CHANGES/v2.3.txt @@ -161,6 +161,7 @@ See branch \branch{v2.3} on git repository. - Fixed bug in \ref HISTOGRAM that causes nans when using KERNEL=DISCRETE option - Fixed a bug in the parser related to braces, see \issue{229} - Fixed a bug that appeared when using \ref Q3, \ref Q4 and \ref Q6 with LOWEST or HIGHEST flag +- Fixed a bug that appears when you use \ref MFILTER_LESS as input to \ref COORDINATIONNUMBER with SPECIESA and SPECIESB flags For developers: - plumedcheck validation has been made stricter. All the checks are now described in the developer manual. From 1f6afac2756a8f9d93ac3595b2a829b4cd2ddab4 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Mon, 8 May 2017 19:27:57 +0100 Subject: [PATCH 61/62] Ran astyle --- src/crystallization/CubicHarmonicBase.cpp | 2 +- src/crystallization/OrientationSphere.cpp | 2 +- src/crystallization/Steinhardt.cpp | 2 +- src/multicolvar/CoordinationNumbers.cpp | 4 ++-- src/multicolvar/LocalAverage.cpp | 2 +- src/multicolvar/MultiColvarBase.cpp | 8 ++++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/crystallization/CubicHarmonicBase.cpp b/src/crystallization/CubicHarmonicBase.cpp index abec90a182..1f45c537bf 100644 --- a/src/crystallization/CubicHarmonicBase.cpp +++ b/src/crystallization/CubicHarmonicBase.cpp @@ -103,7 +103,7 @@ double CubicHarmonicBase::compute( const unsigned& tindex, multicolvar::AtomValu if ( (d2=distance[0]*distance[0])epsilon ){ + d2>epsilon ) { double sw = switchingFunction.calculateSqr( d2, dfunc ); diff --git a/src/crystallization/OrientationSphere.cpp b/src/crystallization/OrientationSphere.cpp index 9d7f6711bf..ad9761db8e 100644 --- a/src/crystallization/OrientationSphere.cpp +++ b/src/crystallization/OrientationSphere.cpp @@ -84,7 +84,7 @@ double OrientationSphere::compute( const unsigned& tindex, multicolvar::AtomValu if ( (d2=distance[0]*distance[0])epsilon ){ + d2>epsilon ) { sw = switchingFunction.calculateSqr( d2, dfunc ); diff --git a/src/crystallization/Steinhardt.cpp b/src/crystallization/Steinhardt.cpp index 41a3d827d1..072adff7fd 100644 --- a/src/crystallization/Steinhardt.cpp +++ b/src/crystallization/Steinhardt.cpp @@ -82,7 +82,7 @@ void Steinhardt::calculateVector( multicolvar::AtomValuePack& myatoms ) const { if ( (d2=distance[0]*distance[0])epsilon ){ + d2>epsilon ) { dlen = sqrt(d2); sw = switchingFunction.calculate( dlen, dfunc ); diff --git a/src/multicolvar/CoordinationNumbers.cpp b/src/multicolvar/CoordinationNumbers.cpp index f22cf80892..6e7165b4de 100644 --- a/src/multicolvar/CoordinationNumbers.cpp +++ b/src/multicolvar/CoordinationNumbers.cpp @@ -127,8 +127,8 @@ double CoordinationNumbers::compute( const unsigned& tindex, AtomValuePack& myat Vector& distance=myatoms.getPosition(i); if ( (d2=distance[0]*distance[0])epsilon ){ + (d2+=distance[2]*distance[2])epsilon ) { sw = switchingFunction.calculateSqr( d2, dfunc ); accumulateSymmetryFunction( 1, i, sw, (dfunc)*distance, (-dfunc)*Tensor(distance,distance), myatoms ); diff --git a/src/multicolvar/LocalAverage.cpp b/src/multicolvar/LocalAverage.cpp index 4aed64e664..1671f06b5a 100644 --- a/src/multicolvar/LocalAverage.cpp +++ b/src/multicolvar/LocalAverage.cpp @@ -184,7 +184,7 @@ double LocalAverage::compute( const unsigned& tindex, AtomValuePack& myatoms ) c if ( (d2=distance[0]*distance[0])epsilon) { + d2>epsilon) { sw = switchingFunction.calculateSqr( d2, dfunc ); diff --git a/src/multicolvar/MultiColvarBase.cpp b/src/multicolvar/MultiColvarBase.cpp index 8bbffdaf05..987eb1532a 100644 --- a/src/multicolvar/MultiColvarBase.cpp +++ b/src/multicolvar/MultiColvarBase.cpp @@ -376,13 +376,13 @@ void MultiColvarBase::setupMultiColvarBase( const std::vector& atoms bool found=false; unsigned inum; for(unsigned j=0; j0 && atom_lab[j].first>0 ) { - if( atom_lab[nat1+i].first==atom_lab[j].first && + if( atom_lab[nat1+i].first==atom_lab[j].first && mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ) { found=true; inum=j; break; } - } else if( atom_lab[nat1+i].first>0 ){ + } else if( atom_lab[nat1+i].first>0 ) { if( mybasemulticolvars[atom_lab[nat1+i].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[nat1+i].second)== - all_atoms[atom_lab[j].second] ){ found=true; inum=nat1 + i; break; } - } else if( atom_lab[j].first>0 ){ + all_atoms[atom_lab[j].second] ) { found=true; inum=nat1 + i; break; } + } else if( atom_lab[j].first>0 ) { if( all_atoms[atom_lab[nat1+i].second]== mybasemulticolvars[atom_lab[j].first-1]->getAbsoluteIndexOfCentralAtom(atom_lab[j].second) ) { found=true; inum=nat1+i; break; } } else if( all_atoms[atom_lab[nat1+i].second]==all_atoms[atom_lab[j].second] ) { found=true; inum=j; break; } From f5ab7a1bc6b2bd41cae4956e51640384f5697145 Mon Sep 17 00:00:00 2001 From: Gareth Tribello Date: Mon, 8 May 2017 19:29:01 +0100 Subject: [PATCH 62/62] Added a regtest on fibonacci sphere stuff with neighbor list --- .../rt-fibonacci-neighbors/Makefile | 1 + .../rt-fibonacci-neighbors/config | 4 + .../mykde.xyz.reference | 146 +++ .../rt-fibonacci-neighbors/plumed.dat | 5 + .../rt-fibonacci-neighbors/trajectory.xyz | 1015 +++++++++++++++++ 5 files changed, 1171 insertions(+) create mode 100644 regtest/crystallization/rt-fibonacci-neighbors/Makefile create mode 100644 regtest/crystallization/rt-fibonacci-neighbors/config create mode 100644 regtest/crystallization/rt-fibonacci-neighbors/mykde.xyz.reference create mode 100644 regtest/crystallization/rt-fibonacci-neighbors/plumed.dat create mode 100644 regtest/crystallization/rt-fibonacci-neighbors/trajectory.xyz diff --git a/regtest/crystallization/rt-fibonacci-neighbors/Makefile b/regtest/crystallization/rt-fibonacci-neighbors/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/crystallization/rt-fibonacci-neighbors/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/crystallization/rt-fibonacci-neighbors/config b/regtest/crystallization/rt-fibonacci-neighbors/config new file mode 100644 index 0000000000..86881dd730 --- /dev/null +++ b/regtest/crystallization/rt-fibonacci-neighbors/config @@ -0,0 +1,4 @@ +type=driver +plumed_modules=crystallization +# this is to test a different name +arg="--plumed plumed.dat --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt %8.4f" # --debug-forces forces.num" diff --git a/regtest/crystallization/rt-fibonacci-neighbors/mykde.xyz.reference b/regtest/crystallization/rt-fibonacci-neighbors/mykde.xyz.reference new file mode 100644 index 0000000000..fca6042116 --- /dev/null +++ b/regtest/crystallization/rt-fibonacci-neighbors/mykde.xyz.reference @@ -0,0 +1,146 @@ +144 +Grid converted to xyz file +X 0.0000 -0.0001 0.0000 +X -0.0000 -0.0001 -0.0000 +X 0.0000 -0.0000 0.0000 +X 0.0328 -0.1666 -0.0428 +X -0.2303 -0.6301 0.0407 +X 0.0000 -0.0000 0.0000 +X -0.0008 -0.0068 -0.0030 +X -0.0001 -0.0006 0.0003 +X 0.0212 -0.0423 -0.0078 +X -0.0214 -0.0406 -0.0089 +X 0.0000 -0.0000 0.0000 +X 0.0578 -0.2994 -0.1843 +X -0.6092 -1.0333 0.3530 +X 0.0000 -0.0000 0.0000 +X -0.0000 -0.0000 -0.0000 +X -0.0000 -0.0000 0.0000 +X 0.0244 -0.0387 -0.0206 +X -0.3800 -0.4406 -0.0157 +X 0.0004 -0.0006 0.0004 +X -0.0000 -0.0003 -0.0003 +X -0.0001 -0.0002 0.0001 +X 0.0000 -0.0000 -0.0000 +X -0.0000 -0.0000 -0.0000 +X 0.0000 -0.0002 0.0002 +X 0.0003 -0.0005 -0.0005 +X -0.0318 -0.0282 0.0101 +X 0.0002 -0.0002 0.0001 +X -0.0000 -0.0000 -0.0000 +X -0.0000 -0.0000 0.0000 +X 0.0002 -0.0002 -0.0001 +X -0.0000 -0.0000 -0.0000 +X 0.6438 -0.8099 1.0013 +X 0.0002 -0.0007 -0.0011 +X -0.0001 -0.0000 0.0000 +X 0.0000 -0.0000 0.0000 +X -0.0000 -0.0000 -0.0000 +X 0.0002 -0.0191 0.0337 +X 0.0001 -0.0001 -0.0001 +X -0.0018 -0.0009 0.0002 +X 1.1777 -0.7479 0.8938 +X -0.0000 -0.0000 -0.0000 +X -0.0000 -0.0000 0.0000 +X 0.0001 -0.0001 -0.0000 +X -0.0000 -0.0000 -0.0000 +X 3.1931 -3.7962 8.6127 +X 0.1915 -0.2011 -0.4704 +X -0.0038 -0.0016 0.0018 +X 0.0000 -0.0000 0.0000 +X -0.0000 -0.0000 -0.0000 +X -0.0001 -0.0002 0.0005 +X 0.0160 -0.0061 -0.0114 +X -0.0000 -0.0000 -0.0000 +X 6.1119 -2.6530 7.1805 +X 0.0002 -0.0017 -0.0065 +X -0.0000 -0.0000 0.0000 +X 0.0000 -0.0000 -0.0000 +X -0.0000 -0.0000 -0.0000 +X 1.8448 -2.7449 13.2225 +X 0.0376 -0.0126 -0.0545 +X -0.0002 -0.0000 0.0001 +X 0.0029 -0.0005 0.0016 +X -0.0000 -0.0000 -0.0000 +X -0.0000 -0.0000 0.0000 +X 0.0190 -0.0025 -0.0081 +X -0.0000 -0.0000 -0.0000 +X 0.7140 -0.1378 1.3425 +X 0.0288 -0.0088 -0.1113 +X -0.0000 -0.0000 0.0000 +X 0.0000 -0.0000 0.0000 +X -0.0000 -0.0000 -0.0000 +X -0.0005 -0.0001 0.0070 +X 0.0008 -0.0000 -0.0008 +X -0.0000 0.0000 0.0000 +X 0.0012 0.0000 0.0011 +X -0.0000 0.0000 -0.0000 +X -0.0000 0.0000 0.0000 +X 0.0000 0.0000 -0.0000 +X -0.0000 0.0000 -0.0000 +X 0.0424 0.0143 0.1517 +X 0.0005 0.0001 -0.0010 +X -0.0015 0.0002 0.0006 +X 0.0000 0.0000 0.0000 +X -0.0000 0.0000 -0.0000 +X -0.0000 0.0000 0.0001 +X 0.0001 0.0000 -0.0001 +X -0.0000 0.0000 -0.0000 +X 0.0000 0.0000 0.0000 +X 0.0000 0.0000 -0.0000 +X -0.0001 0.0000 0.0001 +X 0.0000 0.0000 0.0000 +X -0.0000 0.0000 -0.0000 +X 0.0001 0.0005 0.0018 +X 0.0000 0.0000 -0.0000 +X -0.0284 0.0090 0.0041 +X 0.0000 0.0000 0.0000 +X -0.0000 0.0000 -0.0000 +X -0.0000 0.0000 0.0000 +X 0.0000 0.0000 -0.0000 +X -0.0000 0.0000 -0.0000 +X 0.0329 0.0344 0.0765 +X 0.0000 0.0000 -0.0001 +X -0.1620 0.0826 0.0872 +X 0.0000 0.0000 0.0000 +X -0.0011 0.0010 -0.0017 +X -0.0015 0.0048 0.0093 +X 0.0000 0.0000 -0.0000 +X -0.0007 0.0004 -0.0000 +X 0.1343 0.1109 0.1423 +X -0.0001 0.0030 -0.0050 +X -0.0000 0.0000 0.0000 +X 0.0000 0.0000 -0.0000 +X -0.0001 0.0000 -0.0000 +X 0.2179 0.7861 1.1347 +X 0.0475 0.0639 -0.0771 +X -0.0947 0.0720 0.0269 +X 0.0002 0.0001 0.0001 +X -1.1281 2.4860 -2.9541 +X -0.0000 0.0000 0.0000 +X 0.0000 0.0000 -0.0000 +X -0.0001 0.0001 -0.0000 +X 12.6815 22.4857 21.1626 +X 0.7136 3.3712 -3.4886 +X -0.0003 0.0003 0.0002 +X 0.0023 0.0024 0.0003 +X -0.4946 0.8039 -0.5697 +X -0.0011 0.0478 0.0431 +X 0.4105 0.6843 -0.4248 +X -0.0100 0.0121 0.0006 +X 0.0849 0.1383 0.0688 +X -0.5650 5.0714 -3.7799 +X -0.0000 0.0000 0.0000 +X 0.2993 0.4518 -0.0720 +X -0.0005 0.0010 -0.0003 +X 0.0746 0.3857 0.2226 +X 2.5084 10.8001 -5.6446 +X -0.0001 0.0001 0.0000 +X 0.2341 0.4989 0.0803 +X -0.0375 0.1721 -0.0690 +X -0.0000 0.0000 0.0000 +X 0.1546 0.5001 -0.1027 +X -0.0000 0.0000 -0.0000 +X 0.0012 0.0070 0.0015 +X 0.0000 0.0014 -0.0003 +X -0.0000 0.0000 0.0000 diff --git a/regtest/crystallization/rt-fibonacci-neighbors/plumed.dat b/regtest/crystallization/rt-fibonacci-neighbors/plumed.dat new file mode 100644 index 0000000000..9b7e2cabfe --- /dev/null +++ b/regtest/crystallization/rt-fibonacci-neighbors/plumed.dat @@ -0,0 +1,5 @@ +b1: BOND_DIRECTIONS GROUP=1-5 SWITCH={RATIONAL D_0=2.0 R_0=0.5 D_MAX=5.0} + +h: HISTOGRAM VECTORS=b1 CONCENTRATION=100 GRID_BIN=144 + +GRID_TO_XYZ GRID=h FILE=mykde.xyz UNITS=A PRECISION=4 diff --git a/regtest/crystallization/rt-fibonacci-neighbors/trajectory.xyz b/regtest/crystallization/rt-fibonacci-neighbors/trajectory.xyz new file mode 100644 index 0000000000..13fdd1145b --- /dev/null +++ b/regtest/crystallization/rt-fibonacci-neighbors/trajectory.xyz @@ -0,0 +1,1015 @@ +201 +10 10 10 +Ar 5 5 5 +Ar 7.82637e-05 1.31538 7.55605 +Ar 2.18959 0.470446 6.78865 +Ar 3.83502 5.19416 8.30965 +Ar 5.297 6.71149 0.0769819 +Ar 4.17486 6.86773 5.88977 +Ar 5.26929 0.919649 6.53919 +Ar 9.10321 7.62198 2.62453 +Ar 3.28234 6.32639 7.5641 +Ar 2.47039 9.8255 7.2266 +Ar 0.726859 6.31635 8.84707 +Ar 7.66495 4.77732 2.37774 +Ar 1.66507 4.86517 8.97656 +Ar 9.04653 5.04523 5.16292 +Ar 4.93977 2.66145 0.907329 +Ar 5.00707 3.84142 2.77082 +Ar 4.64446 9.4098 0.50084 +Ar 8.27817 1.25365 0.158677 +Ar 6.29543 7.36225 7.25412 +Ar 2.33195 3.06322 3.51015 +Ar 8.45982 4.12081 8.41511 +Ar 5.37304 4.67917 2.87212 +Ar 5.71655 8.02406 0.330538 +Ar 9.55361 7.48293 5.54584 +Ar 8.4204 1.59768 2.12752 +Ar 0.909903 2.74588 0.029996 +Ar 7.0982 9.37897 2.39911 +Ar 8.86991 6.52059 1.50335 +Ar 3.87725 4.99741 1.47533 +Ar 5.90109 9.55409 5.56146 +Ar 4.08767 1.4182 5.64899 +Ar 4.64031 9.61095 1.26031 +Ar 6.29269 1.26712 6.51254 +Ar 2.47842 4.76432 3.89314 +Ar 9.01673 4.26497 1.42021 +Ar 1.31189 8.85648 0.921736 +Ar 3.65339 2.53057 1.35109 +Ar 3.49524 4.523 8.08945 +Ar 2.15248 6.79592 9.08922 +Ar 4.71262 5.05956 6.00394 +Ar 4.62245 9.51367 6.32739 +Ar 6.88981 7.02207 9.87145 +Ar 2.89316 5.37426 5.14435 +Ar 5.76717 8.76566 4.40039 +Ar 7.15642 8.0072 7.06535 +Ar 8.86031 5.24987 4.63323 +Ar 4.88943 6.67679 6.82049 +Ar 8.65883 8.90019 5.43948 +Ar 9.89362 2.15532 4.46023 +Ar 8.81504 4.39726 4.67532 +Ar 2.11519 9.99117 1.53604 +Ar 0.00595042 0.00879 7.73352 +Ar 4.17724 6.82494 6.80562 +Ar 7.08921 8.28708 0.945488 +Ar 6.29572 2.13852 2.13547 +Ar 9.5216 9.47545 3.89854 +Ar 2.84035 7.76866 7.83865 +Ar 1.93967 0.113162 1.91824 +Ar 8.19726 1.36455 3.98144 +Ar 8.28355 1.57731 9.87937 +Ar 1.01637 2.19411 6.34717 +Ar 6.96243 7.5294 6.69521 +Ar 5.98217 2.27008 3.18778 +Ar 7.62571 5.26123 5.53911 +Ar 7.02989 1.43045 1.61688 +Ar 8.13266 5.56836 7.38997 +Ar 5.28548 3.10739 5.88119 +Ar 2.58843 3.70226 3.93018 +Ar 3.87831 2.79293 0.782632 +Ar 6.71784 6.76237 5.13936 +Ar 9.44753 4.60697 9.40163 +Ar 5.17145 6.61355 4.01833 +Ar 1.50394 6.70098 3.43818 +Ar 8.29239 0.149506 2.7421 +Ar 9.17848 2.66613 9.70087 +Ar 6.94024 4.55752 8.17101 +Ar 7.0695 7.07826 4.36638 +Ar 9.91533 6.95679 2.79512 +Ar 0.0425392 4.95691 0.799169 +Ar 7.82992 7.46679 4.36426 +Ar 5.18478 0.668498 5.44023 +Ar 3.85769 6.26861 6.59053 +Ar 2.80289 8.15932 3.7191 +Ar 0.0934752 1.03797 5.2096 +Ar 0.552788 0.706349 1.60274 +Ar 0.506026 4.77804 4.57162 +Ar 1.50312 2.85942 8.33682 +Ar 6.81164 3.31175 0.574753 +Ar 0.0165742 8.56193 0.293555 +Ar 5.76173 7.38959 6.79332 +Ar 1.22507 9.73356 1.88276 +Ar 6.07611 1.25933 5.52862 +Ar 8.38102 9.74252 2.59014 +Ar 8.13048 8.97914 2.44586 +Ar 4.51851 2.6362 6.65503 +Ar 1.13676 5.46975 0.0607937 +Ar 4.31908 0.825065 6.87414 +Ar 1.23637 9.73346 0.296353 +Ar 7.69437 9.3403 2.50155 +Ar 4.99955 7.49252 6.71903 +Ar 0.363676 2.30572 2.21667 +Ar 6.1661 3.71466 2.24801 +Ar 1.65928 7.44104 1.59758 +Ar 1.24945 9.49157 4.8418 +Ar 0.179445 5.93546 7.21872 +Ar 4.41633 5.19175 7.71944 +Ar 9.7718 4.67741 3.29056 +Ar 2.05341 1.71379 3.7252 +Ar 2.54957 0.703352 1.23849 +Ar 5.17707 1.05185 8.41576 +Ar 3.27228 7.13547 5.76776 +Ar 8.36598 6.99791 3.8906 +Ar 3.62084 5.39505 4.55072 +Ar 0.830857 4.21579 4.7238 +Ar 2.16386 8.02019 5.27439 +Ar 2.4375 7.11564 2.63663 +Ar 4.59763 2.32867 7.95353 +Ar 2.66119 6.64689 4.25191 +Ar 1.34039 7.95856 9.46045 +Ar 0.638036 3.47492 2.92468 +Ar 8.34338 7.26443 3.29434 +Ar 0.453407 0.414204 1.53315 +Ar 5.19303 9.2915 2.20516 +Ar 6.99691 7.06461 4.94631 +Ar 3.78366 2.00645 2.32608 +Ar 8.61187 9.77238 4.44519 +Ar 0.316388 7.53174 5.91588 +Ar 2.32078 5.36528 4.30618 +Ar 9.6691 8.50531 8.67514 +Ar 9.97599 6.39523 4.68075 +Ar 8.15407 5.41535 5.72807 +Ar 8.21334 1.55414 0.410748 +Ar 0.965383 5.18773 0.22405 +Ar 5.16908 6.74525 7.37175 +Ar 1.91984 6.70991 3.45872 +Ar 9.21117 2.21656 3.80115 +Ar 0.263397 6.91126 7.62344 +Ar 5.89809 9.25503 9.29698 +Ar 8.31256 9.19236 6.01638 +Ar 4.90817 1.61419 9.76116 +Ar 5.31427 6.98558 6.67049 +Ar 6.10738 6.67965 4.95125 +Ar 4.41313 1.51217 5.02275 +Ar 0.516167 5.22063 3.20642 +Ar 1.07181 3.82969 5.51829 +Ar 9.35252 7.7203 5.13148 +Ar 6.96996 4.07538 4.8685 +Ar 5.34199 2.76647 6.05538 +Ar 5.3049 9.38254 2.35403 +Ar 7.83002 9.20252 6.81491 +Ar 2.3027 1.43684 8.99521 +Ar 0.0481561 9.35936 2.75353 +Ar 9.52431 5.0682 1.2295 +Ar 4.36491 1.07739 7.66175 +Ar 3.44576 2.97064 7.57621 +Ar 0.556062 5.73183 4.85286 +Ar 9.74348 8.64609 4.91841 +Ar 1.62204 1.5958 0.577229 +Ar 3.80608 8.83705 4.24134 +Ar 3.08327 0.601425 8.14416 +Ar 9.01218 7.70046 1.70796 +Ar 8.03268 5.22215 8.61622 +Ar 5.86862 3.89172 8.11895 +Ar 4.20038 5.79863 7.49145 +Ar 1.89549 7.43126 7.18919 +Ar 7.10114 8.7906 3.59379 +Ar 4.16796 0.964286 6.74693 +Ar 8.78192 7.6936 6.35205 +Ar 4.86471 1.13071 3.77485 +Ar 1.2174 0.768218 1.43302 +Ar 2.38019 3.90967 9.75881 +Ar 9.08691 3.624 8.59213 +Ar 0.73511 4.98631 4.83873 +Ar 7.40759 9.32843 3.00122 +Ar 0.80322 9.72476 4.08177 +Ar 8.33474 1.9808 1.29482 +Ar 5.75679 4.40268 5.85675 +Ar 3.82317 6.00133 4.29473 +Ar 9.95401 6.98066 4.0274 +Ar 7.93382 3.74249 0.0960789 +Ar 6.46495 6.44898 7.99035 +Ar 3.895 3.34307 6.93589 +Ar 6.66856 8.54365 3.14699 +Ar 0.055882 9.2083 3.81955 +Ar 2.64133 2.91 8.33648 +Ar 0.486975 4.58046 3.76817 +Ar 6.65973 0.115306 7.94881 +Ar 4.1556 3.20611 5.1459 +Ar 2.31895 4.65007 3.73359 +Ar 2.02449 5.66183 8.31524 +Ar 2.93043 1.81196 3.57526 +Ar 3.6904 4.63059 6.2783 +Ar 0.504816 4.4485 5.95927 +Ar 1.31023 1.04579 6.65308 +Ar 6.58594 9.82032 0.18916 +Ar 9.67723 5.23072 2.78796 +Ar 8.37082 8.34691 6.59888 +Ar 3.49529 5.34876 6.64147 +Ar 4.4237 9.17967 2.76668 +Ar 4.16007 8.36375 9.62535 +Ar 5.35956 8.18107 9.2989 +201 +10 10 10 +Ar 5 5 5 +Ar 9.41429 5.96723 1.26034 +Ar 1.96178 1.62958 8.35997 +Ar 8.38679 6.71648 3.91555 +Ar 1.15607 0.000402252 6.76065 +Ar 5.74346 0.322694 3.51393 +Ar 6.61425 5.7643 0.599598 +Ar 4.42624 1.7642 0.918009 +Ar 5.94159 0.330036 6.90932 +Ar 8.95724 4.34503 6.88594 +Ar 2.72443 9.4712 2.443 +Ar 1.27088 9.61436 8.57156 +Ar 7.82475 0.503933 9.60055 +Ar 1.37093 1.29043 8.24627 +Ar 5.05059 5.26454 1.18397 +Ar 2.77586 3.86707 3.91493 +Ar 1.23444 7.28307 6.48075 +Ar 0.225564 1.05562 1.87979 +Ar 7.19204 6.66364 5.80969 +Ar 2.92091 1.6911 2.23697 +Ar 8.8651 5.79362 3.41848 +Ar 8.34283 7.91982 8.49068 +Ar 1.69961 5.33532 0.731837 +Ar 1.22221 1.646 4.25107 +Ar 4.33928 0.330772 9.29321 +Ar 4.82049 7.9278 2.57524 +Ar 3.80628 2.08123 9.28528 +Ar 5.75853 3.56334 9.07848 +Ar 7.9114 6.98163 0.182512 +Ar 8.94964 6.54629 3.45891 +Ar 3.31292 0.177851 9.14368 +Ar 7.29983 8.31551 8.77797 +Ar 9.4207 3.62191 3.5206 +Ar 7.76393 8.44201 4.93295 +Ar 4.35375 3.52314 3.49157 +Ar 6.26152 7.4458 1.5754 +Ar 6.12058 8.54603 3.14608 +Ar 3.73662 1.33293 2.61863 +Ar 7.50525 0.709501 4.58914 +Ar 1.97518 6.83946 0.813265 +Ar 1.20177 8.09124 9.44193 +Ar 8.29722 1.41179 8.01168 +Ar 5.99194 6.55206 0.537268 +Ar 4.1358 0.318384 1.08049 +Ar 6.7108 8.34369 2.38217 +Ar 2.2254 2.27762 0.0157362 +Ar 9.33005 0.224617 5.13499 +Ar 7.93872 6.09468 3.31804 +Ar 6.4439 2.5912 0.260003 +Ar 6.42325 5.60325 3.76933 +Ar 1.37716 5.858 5.426 +Ar 0.815947 3.62593 1.00809 +Ar 9.13002 8.27927 9.70299 +Ar 8.39796 4.4872 6.42095 +Ar 4.68209 1.93634 4.01555 +Ar 3.78445 5.17596 2.27756 +Ar 1.36994 4.58481 6.89134 +Ar 7.39932 0.312551 3.03932 +Ar 2.74869 7.17761 4.08626 +Ar 5.77059 6.32939 7.98596 +Ar 3.46431 4.71857 4.92207 +Ar 8.57925 1.38002 3.99142 +Ar 0.561348 4.56879 7.65532 +Ar 10 9.99092 7.41617 +Ar 1.99 6.00734 5.42825 +Ar 5.75624 5.13759 7.47701 +Ar 7.9845 5.54778 1.46671 +Ar 2.463 5.71627 3.34365 +Ar 8.44641 8.76262 3.32073 +Ar 6.61891 4.02784 5.85027 +Ar 6.14501 9.2483 6.13926 +Ar 6.20714 3.43489 0.241668 +Ar 4.23845 5.68438 7.30373 +Ar 3.76277 0.866058 5.83115 +Ar 3.25262 6.85165 5.63984 +Ar 9.74538 0.602413 4.75344 +Ar 5.49515 6.98705 1.27237 +Ar 4.45107 9.17977 4.39511 +Ar 5.49302 1.24284 8.46325 +Ar 6.56273 9.73193 4.57616 +Ar 2.83333 9.72964 5.97956 +Ar 9.25623 9.49394 4.66668 +Ar 4.30824 8.66139 1.98631 +Ar 8.14225 6.72739 7.21585 +Ar 1.68483 6.88042 9.20936 +Ar 1.76306 1.78152 1.98052 +Ar 5.17482 3.23405 4.66967 +Ar 8.70438 4.45121 1.47775 +Ar 8.8235 6.60927 2.03913 +Ar 1.65414 1.09083 3.61192 +Ar 2.45494 0.238609 0.300402 +Ar 9.13224 5.47401 1.72576 +Ar 9.36609 5.83064 5.48907 +Ar 3.32312 1.72459 5.12964 +Ar 9.67038 0.0477785 3.0139 +Ar 8.43532 2.50356 7.33911 +Ar 7.08479 4.05874 5.263 +Ar 4.03688 7.8213 2.64789 +Ar 7.56626 6.20673 6.45346 +Ar 1.84355 4.55199 5.3318 +Ar 4.09058 0.311874 1.67285 +Ar 1.40259 3.3357 3.09118 +Ar 3.2215 3.79582 6.41376 +Ar 3.35103 0.782141 5.44029 +Ar 2.52718 4.3932 6.58614 +Ar 9.72696 1.0087 3.18377 +Ar 1.65406 9.85489 1.16442 +Ar 7.85281 2.2039 1.01461 +Ar 2.43011 2.82594 5.49228 +Ar 6.70468 5.5761 7.57833 +Ar 7.59697 2.3395 9.9829 +Ar 2.99503 7.45522 9.91835 +Ar 6.41665 4.63801 1.02468 +Ar 5.03358 9.30975 8.98036 +Ar 9.754 5.44049 8.30669 +Ar 9.75294 7.65209 8.69878 +Ar 3.75437 9.69667 1.93147 +Ar 8.96504 5.49478 0.847728 +Ar 7.08398 0.519357 8.83565 +Ar 2.69917 4.99773 6.87318 +Ar 6.89707 9.11773 1.71227 +Ar 4.81877 9.10853 7.03183 +Ar 9.02494 2.10064 5.48365 +Ar 8.06702 2.35834 6.58912 +Ar 4.52883 6.0687 6.67104 +Ar 3.77316 5.41796 9.697 +Ar 7.58699 4.53228 4.0675 +Ar 2.13819 6.61177 4.07049 +Ar 3.01463 6.88401 9.54292 +Ar 0.216561 9.7424 0.53752 +Ar 7.96038 0.115786 6.02006 +Ar 5.45015 0.730384 5.56517 +Ar 3.90933 4.08673 5.59109 +Ar 5.89636 0.111431 2.82762 +Ar 5.6569 5.54309 2.68586 +Ar 3.54305 8.0831 2.65734 +Ar 6.48154 5.29665 0.728548 +Ar 0.988572 4.93255 1.32815 +Ar 3.53126 9.93806 8.92149 +Ar 8.01629 9.82168 3.01218 +Ar 1.43244 5.06545 4.99835 +Ar 2.17063 1.72927 3.85219 +Ar 1.64685 8.56503 2.45427 +Ar 9.64197 2.50746 2.84081 +Ar 5.1529 4.86485 3.51869 +Ar 0.204031 9.15687 9.59515 +Ar 4.00523 5.8766 8.06355 +Ar 5.45435 1.30099 5.74699 +Ar 2.07209 5.63862 8.30683 +Ar 9.77984 9.84922 5.83705 +Ar 0.823947 8.0774 6.81656 +Ar 2.00402 1.63937 2.80788 +Ar 8.71827 7.892 0.907455 +Ar 7.6144 5.1707 3.91793 +Ar 5.96703 7.8021 9.86729 +Ar 7.77039 6.86431 8.41948 +Ar 3.96655 5.85257 4.20051 +Ar 6.90773 8.13622 5.50919 +Ar 4.7432 8.98639 4.29241 +Ar 0.000391542 6.58065 0.918404 +Ar 6.67623 7.45264 6.52465 +Ar 7.82769 0.0518158 0.868126 +Ar 2.14659 7.81356 2.53661 +Ar 2.95857 4.7319 9.09973 +Ar 2.50655 7.52406 6.8391 +Ar 2.08753 5.0639 8.97771 +Ar 9.73102 9.18436 1.48704 +Ar 7.71451 7.70618 7.75716 +Ar 6.36321 6.47096 7.42002 +Ar 7.80221 1.80408 1.19997 +Ar 0.77255 4.24933 8.41116 +Ar 4.30353 9.45963 7.98559 +Ar 8.28705 0.416034 2.28601 +Ar 0.434911 9.54651 8.24232 +Ar 7.50104 9.98299 4.17458 +Ar 1.08905 3.62057 0.968765 +Ar 8.23579 8.99207 9.65837 +Ar 8.17441 7.24963 4.58524 +Ar 6.0336 6.67519 9.8743 +Ar 6.25461 1.30178 8.96096 +Ar 2.36833 4.5146 6.80744 +Ar 7.0385 5.9878 6.90966 +Ar 2.02964 2.16739 7.32599 +Ar 7.1546 7.40477 1.95229 +Ar 8.3916 7.60827 2.18624 +Ar 6.76851 8.35845 0.504922 +Ar 4.57732 1.09521 7.25235 +Ar 5.38175 1.02257 6.40354 +Ar 2.42478 3.299 6.31842 +Ar 7.68851 0.789411 7.62721 +Ar 4.7033 8.3848 3.38452 +Ar 7.86713 2.78563 8.15297 +Ar 8.70376 4.12815 1.81981 +Ar 3.50968 7.25291 9.7199 +Ar 2.37746 8.0156 8.223 +Ar 6.0237 0.386598 7.55131 +Ar 3.55253 7.29884 1.65043 +Ar 6.77584 1.50371 2.87851 +Ar 5.91714 9.44596 8.29331 +Ar 0.303791 5.82117 6.41647 +Ar 3.07525 5.74306 3.68609 +201 +10 10 10 +Ar 5 5 5 +Ar 7.5695 0.652273 2.75348 +Ar 3.02871 3.54434 9.67253 +Ar 3.46591 1.54431 5.16009 +Ar 6.88987 8.07667 4.58841 +Ar 3.2784 0.124615 4.40638 +Ar 5.63489 5.6706 5.75652 +Ar 1.11175 5.10826 4.44486 +Ar 5.85182 1.48493 7.25622 +Ar 5.87793 0.32957 9.08952 +Ar 4.09143 4.6321 1.62533 +Ar 6.92757 1.71729 2.50726 +Ar 8.20092 2.88709 3.32639 +Ar 4.24314 4.41389 4.31431 +Ar 6.44286 5.18011 2.08885 +Ar 5.1332 3.6702 5.02298 +Ar 8.13234 0.291272 5.40555 +Ar 6.32031 5.49682 5.10782 +Ar 7.20948 9.75647 7.05298 +Ar 6.30165 1.84357 4.88743 +Ar 7.00235 8.49437 4.9026 +Ar 4.49827 2.34011 0.23474 +Ar 3.38934 4.58718 6.74611 +Ar 3.57162 8.20933 4.23101 +Ar 1.38688 9.24011 8.56061 +Ar 9.74908 2.75584 7.35949 +Ar 7.82175 0.123637 7.97382 +Ar 5.4719 6.26824 0.290541 +Ar 3.20619 6.51622 8.14288 +Ar 6.86567 1.29753 7.54228 +Ar 1.04098 5.69399 8.83811 +Ar 2.40964 8.78211 0.88676 +Ar 8.03795 3.89757 6.47873 +Ar 9.80936 5.91894 9.61583 +Ar 2.50697 4.72729 1.58855 +Ar 0.397496 0.719813 7.90158 +Ar 2.37858 6.82644 1.92756 +Ar 2.73417 3.17012 0.227274 +Ar 6.62178 2.21213 9.28902 +Ar 2.8849 6.5124 3.84612 +Ar 2.57187 5.33529 0.242924 +Ar 9.34847 9.67667 5.8707 +Ar 8.69281 0.0655631 1.91843 +Ar 5.10074 8.17946 2.20417 +Ar 1.83057 6.44666 8.93645 +Ar 1.3907 3.51769 1.83774 +Ar 0.431582 3.60519 2.44023 +Ar 3.84147 3.51096 8.6668 +Ar 3.20744 7.47109 6.6245 +Ar 5.16082 7.95015 8.09086 +Ar 3.22907 1.0014 0.591831 +Ar 4.33362 5.15876 3.22814 +Ar 6.12364 0.0696027 9.81289 +Ar 6.27369 1.91306 2.85189 +Ar 9.28788 1.4413 3.97386 +Ar 7.56102 8.01325 8.68794 +Ar 5.70929 6.03147 0.842391 +Ar 4.17251 7.44114 3.23595 +Ar 5.06807 8.98505 1.75787 +Ar 4.08904 4.54629 9.54362 +Ar 1.74194 6.85043 5.15791 +Ar 4.00413 7.43142 9.80445 +Ar 9.62922 8.29065 0.995498 +Ar 7.85494 7.94239 7.80114 +Ar 1.39837 2.43357 0.968659 +Ar 7.03856 7.1328 0.88807 +Ar 5.87647 5.89635 9.95334 +Ar 2.72528 3.75871 2.56752 +Ar 9.82881 2.74655 1.34113 +Ar 5.78786 6.55652 5.35274 +Ar 8.79341 0.775374 1.71586 +Ar 9.56571 0.960075 5.97675 +Ar 1.2045 3.96628 1.34091 +Ar 6.73604 2.57837 4.73408 +Ar 1.87079 2.32948 1.54378 +Ar 4.85577 0.971637 0.310194 +Ar 9.17023 4.13157 9.31294 +Ar 4.0708 8.00032 1.4194 +Ar 8.11845 6.80462 5.16441 +Ar 5.51341 3.83457 7.54757 +Ar 5.59622 5.72303 7.01768 +Ar 7.70103 1.17474 3.83296 +Ar 0.47252 1.648 7.93975 +Ar 8.41865 2.23189 1.30036 +Ar 2.99237 2.84531 1.10282 +Ar 9.80176 8.2239 9.06449 +Ar 2.26136 6.64316 1.63039 +Ar 1.10733 0.823489 0.374919 +Ar 2.3412 8.47198 8.57696 +Ar 4.78682 2.01087 6.6524 +Ar 7.63624 2.27704 0.131423 +Ar 7.14594 1.84213 0.630616 +Ar 0.54297 5.70175 9.36927 +Ar 3.59691 3.21922 5.40083 +Ar 1.62713 7.19937 9.85789 +Ar 6.60614 9.38363 0.726351 +Ar 4.42821 4.96468 1.31522 +Ar 3.82243 3.66313 6.2871 +Ar 7.7319 0.0130101 8.66038 +Ar 3.9303 6.55235 5.37968 +Ar 4.73192 9.39119 7.69784 +Ar 7.77598 0.879195 6.62258 +Ar 3.02735 0.595074 1.41636 +Ar 0.095646 7.52224 6.23197 +Ar 6.9111 4.93485 9.96059 +Ar 7.72596 0.247698 3.06745 +Ar 4.14182 1.5477 2.13207 +Ar 5.93871 1.85374 5.79569 +Ar 4.67173 7.71369 3.94445 +Ar 2.96776 9.10829 3.0169 +Ar 1.50726 2.50785 9.42107 +Ar 9.01082 4.90272 0.0233687 +Ar 9.03613 0.249924 0.471862 +Ar 1.54432 5.35012 9.3921 +Ar 3.66519 0.917451 9.6046 +Ar 4.46813 5.83682 9.48445 +Ar 3.7191 6.87722 5.38491 +Ar 8.03778 1.00432 9.58921 +Ar 6.41703 1.08694 8.16211 +Ar 5.2372 1.67929 3.74412 +Ar 6.70025 1.15234 7.39727 +Ar 2.14022 0.611399 5.79126 +Ar 1.75809 8.13962 2.64646 +Ar 0.482823 4.80752 9.91771 +Ar 8.13381 4.88368 0.0203477 +Ar 4.17207 6.26594e-05 1.05312 +Ar 5.96175 9.15947 3.14811 +Ar 6.12437 2.27608 4.03955 +Ar 2.02319 3.79761 6.45802 +Ar 2.40997 4.29148 6.91272 +Ar 9.53473 0.216787 3.53631 +Ar 6.87346 2.20639 2.77095 +Ar 6.82496 7.17839 7.19747 +Ar 3.9906 9.97153 1.55245 +Ar 1.56116 8.33942 0.61241 +Ar 5.85313 3.51874 9.53731 +Ar 1.46443 2.69562 5.20889 +Ar 3.04216 9.53591 0.120105 +Ar 9.07256 2.56259 9.50273 +Ar 1.15747 3.67556 5.14668 +Ar 3.27499 2.8093 5.83021 +Ar 9.35912 8.72381 1.09592 +Ar 8.54533 1.33405 1.36231 +Ar 7.0522 6.27707 8.70284 +Ar 6.10937 0.243665 5.27873 +Ar 9.33215 5.49947 9.62295 +Ar 5.77584 4.56012 1.87135 +Ar 5.57062 5.48482 3.34386 +Ar 7.63549 9.72064 4.85026 +Ar 1.37325 0.292358 3.6597 +Ar 7.30151 6.47369 3.32442 +Ar 1.35349 8.12004 3.4635 +Ar 1.94652 5.22653 2.32136 +Ar 1.83201 0.660737 5.01457 +Ar 5.2742 3.53386 3.64629 +Ar 6.12926 4.51776 9.94794 +Ar 9.32875 8.23612 4.45769 +Ar 7.07452 1.50233 9.587 +Ar 9.36504 8.16441 9.18602 +Ar 3.82113 1.72206 2.72879 +Ar 5.43716 2.31332 0.0197179 +Ar 1.09039 6.14815 1.96891 +Ar 6.10731 5.49318 3.82257 +Ar 6.89994 7.29952 3.05893 +Ar 1.07314 6.30569 9.68442 +Ar 6.28793 1.28038 9.27167 +Ar 6.06931 6.84658 0.388291 +Ar 8.06936 1.6727 2.99106 +Ar 4.84787 8.12857 6.83257 +Ar 5.29119 9.07386 4.34714 +Ar 2.48754 8.10747 2.19152 +Ar 2.08676 2.25699 3.17195 +Ar 0.0790594 8.75103 8.61796 +Ar 4.95345 2.57662 5.19423 +Ar 2.81286 5.66859 1.9909 +Ar 8.50158 6.1052 0.0689164 +Ar 0.19626 8.53626 8.90322 +Ar 0.0385946 8.65903 2.35741 +Ar 8.61275 4.49308 5.18629 +Ar 7.54091 0.0548941 2.60497 +Ar 5.53569 8.25785 9.75457 +Ar 6.19307 6.89595 0.263147 +Ar 4.20896 9.93945 2.34315 +Ar 1.92009 1.0224 3.41074 +Ar 4.61433 3.10742 6.32557 +Ar 4.74292 4.226 6.43278 +Ar 4.32824 4.65556 6.03059 +Ar 9.72228 2.31401 1.51634 +Ar 9.78818 9.90922 4.25526 +Ar 5.35562 1.9696 3.03432 +Ar 1.94742 0.302937 1.45493 +Ar 3.32748 4.87891 9.88146 +Ar 0.281228 6.59586 6.56879 +Ar 2.48455 7.78219 5.27545 +Ar 1.54141 6.51788 5.93987 +Ar 9.12572 6.02232 7.07396 +Ar 4.87855 3.79943 7.00175 +Ar 2.52032 9.00591 2.36043 +Ar 9.2389 8.14099 5.58907 +Ar 0.41205 5.32563 7.82447 +Ar 1.5827 0.373486 7.18541 +201 +10 10 10 +Ar 5 5 5 +Ar 0.585477 0.110114 0.684869 +Ar 9.77116 3.83664 2.40794 +Ar 4.18684 8.20726 9.4046 +Ar 3.33783 8.9657 6.45655 +Ar 2.25867 1.53205 9.13491 +Ar 6.07855 2.26309 5.67751 +Ar 1.83592 6.33235 7.80252 +Ar 2.45704 5.39349 8.31407 +Ar 9.6476 7.29512 9.0851 +Ar 9.65072 9.63741 5.91994 +Ar 4.9685 5.53802 7.4905 +Ar 4.97498 4.42215 3.02191 +Ar 3.18246 7.53316 9.83366 +Ar 0.0564456 8.68118 4.52756 +Ar 3.45015 6.72995 0.199055 +Ar 4.07436 7.82501 4.95659 +Ar 5.55356 8.63532 3.74031 +Ar 8.66305 9.87988 1.10149 +Ar 5.79989 8.70389 6.19807 +Ar 9.0962 9.78863 7.57851 +Ar 1.7219 9.95458 6.64506 +Ar 2.31068 5.55694 5.49373 +Ar 5.55733 1.9875 3.98937 +Ar 4.9474 0.995039 3.62681 +Ar 3.73159 6.80556 1.09921 +Ar 5.52801 9.24063 7.2093 +Ar 0.250363 7.84688 2.58753 +Ar 7.90095 1.20215 4.6146 +Ar 0.0740833 5.11728 6.08319 +Ar 4.33937 1.86764 9.36867 +Ar 4.3229 4.94322 0.726531 +Ar 9.45025 0.38419 7.07826 +Ar 4.0198 0.790307 2.68303 +Ar 3.72159 8.70243 1.74004 +Ar 0.741926 9.55034 2.6045 +Ar 6.10995 9.87933 1.97273 +Ar 1.69951 3.6705 0.0135434 +Ar 0.975465 4.64788 6.92031 +Ar 6.46646 1.76885 9.04255 +Ar 2.46148 0.102676 5.67826 +Ar 5.12551 4.46475 8.9939 +Ar 9.13758 5.27377 6.30692 +Ar 0.648155 3.53456 5.41551 +Ar 9.61115 4.56171 8.58274 +Ar 8.47088 0.0661062 1.0468 +Ar 6.26861 6.57449 7.44073 +Ar 5.98648 4.85276 0.419553 +Ar 4.91754 9.03034 2.95524 +Ar 1.11 5.71734 1.3814 +Ar 7.75146 8.72537 7.31582 +Ar 8.2173 8.13283 8.42835 +Ar 5.87103 4.41705 7.36285 +Ar 9.59406 7.41339 6.86644 +Ar 8.44531 0.363607 1.13458 +Ar 4.12048 2.8767 8.66202 +Ar 6.61595 4.21433 0.190167 +Ar 3.24932 1.25038 5.15464 +Ar 4.82227 7.90702 3.33424 +Ar 0.0198728 4.00283 5.56947 +Ar 4.28414 3.61125 4.26834 +Ar 4.84291 4.7602 4.7442 +Ar 0.814141 3.27089 3.80451 +Ar 9.43368 1.93755 4.33632 +Ar 5.91948 8.66953 8.8569 +Ar 0.522875 7.95447 0.860441 +Ar 2.1557 0.774862 3.10631 +Ar 2.31509 9.70521 5.54465 +Ar 7.60733 6.35225 2.21052 +Ar 4.99441 1.03751 7.4424 +Ar 7.81586 1.18925 7.74786 +Ar 9.58102 8.1604 1.76983 +Ar 0.757743 5.39434 2.67695 +Ar 9.78321 6.40155 0.794262 +Ar 7.62175 8.69311 5.09753 +Ar 1.36002 7.79604 7.98831 +Ar 5.54308 2.62802 9.10738 +Ar 0.933215 4.54895 4.257 +Ar 7.91614 6.64819 6.21247 +Ar 9.85106 6.84372 2.36851 +Ar 5.97392 3.70014 8.24905 +Ar 6.64836 9.00852 6.14584 +Ar 3.26696 7.72741 4.6529 +Ar 2.08414 8.20126 8.5472 +Ar 8.71225 6.83691 7.88704 +Ar 7.78519 5.69214 7.71757 +Ar 9.78456 9.12228 8.14702 +Ar 4.18868 9.10694 0.322859 +Ar 8.30622 2.6772 5.65806 +Ar 0.0157827 5.25929 2.88429 +Ar 0.632955 8.0814 4.11825 +Ar 5.01598 3.58241 9.48683 +Ar 6.2658 9.24671 9.49752 +Ar 5.29306 0.482018 1.27549 +Ar 1.34334 7.5973 7.88174 +Ar 6.84132 2.1142 3.40302 +Ar 8.03589 9.19091 1.63418 +Ar 0.873677 3.89043 6.50166 +Ar 2.08449 4.0845 8.1333 +Ar 0.499961 2.83645 2.26594 +Ar 5.12893 1.87383 3.39278 +Ar 7.96486 5.35161 4.56202 +Ar 0.835465 1.66366 1.1062 +Ar 8.88116 5.57788 7.50574 +Ar 9.00944 1.63399 2.39468 +Ar 8.10724 8.31387 1.1825 +Ar 7.40154 7.65349 2.18798 +Ar 5.80881 8.67864 1.94781 +Ar 4.47492 9.93644 1.79788 +Ar 8.01359 4.39 2.7289 +Ar 4.25763 7.93677 3.35346 +Ar 6.64434 1.34455 7.78315 +Ar 9.5285 5.42773 3.83717 +Ar 3.79528 7.30003 1.58419 +Ar 8.66185 9.6574 1.92608 +Ar 3.86281 2.25192 8.08468 +Ar 5.4693 2.60563 2.80889 +Ar 2.73772 2.92202 0.463033 +Ar 9.32158 7.7224 0.34999 +Ar 3.39061 5.98839 6.82779 +Ar 5.58232 2.10435 7.73404 +Ar 9.11083 5.67101 2.63003 +Ar 0.590107 7.93451 5.35025 +Ar 7.92024 5.52079 7.95577 +Ar 8.834 3.01055 8.28432 +Ar 8.8867 8.8272 8.6824 +Ar 2.77907 7.78888 7.70617 +Ar 9.63608 3.52666 2.59576 +Ar 9.9523 8.32903 6.02341 +Ar 5.02671 3.86767 3.99013 +Ar 9.89527 9.85848 1.39968 +Ar 5.66065 8.60828 9.44422 +Ar 3.25281 9.9649 0.0565812 +Ar 9.22475 0.377142 8.63133 +Ar 6.98223 0.27845 9.91102 +Ar 0.954877 8.61968 0.9086 +Ar 4.66669 2.98862 9.7805 +Ar 3.2901 6.73037 7.29006 +Ar 9.43989 6.2528 0.73777 +Ar 5.2691 7.78675 1.9626 +Ar 2.37807 8.25969 0.664659 +Ar 5.7161 0.444766 5.19037 +Ar 1.77788 0.838111 6.12816 +Ar 3.77918 6.68077 3.73031 +Ar 7.05868 5.18765 8.83197 +Ar 5.07012 3.43673 1.10128 +Ar 5.46813 2.88451 9.94419 +Ar 9.86988 2.99554 6.02776 +Ar 2.1216 7.68248 9.39316 +Ar 9.15878 1.55022 4.47531 +Ar 4.50696 8.42133 7.25026 +Ar 2.39512 4.72938 6.73935 +Ar 9.49451 4.19622 5.86391 +Ar 6.70501 1.07076 6.31325 +Ar 7.49134 7.01545 8.59661 +Ar 2.83648 2.75877 6.57069 +Ar 0.226766 1.25274 4.87276 +Ar 2.96327 3.68784 1.49853 +Ar 8.14282 6.32737 4.09754 +Ar 4.63358 6.59755 5.0765 +Ar 4.76308 3.09981 8.49083 +Ar 2.2856 4.0852 9.92717 +Ar 8.72976 1.0972 0.622184 +Ar 4.05474 7.98644 8.01343 +Ar 6.0611 8.82793 0.971363 +Ar 5.21621 8.90506 7.42054 +Ar 0.85252 8.31187 7.55784 +Ar 5.08025 3.78838 1.26698 +Ar 4.28152 9.54903 0.467227 +Ar 1.27929 1.10995 4.96625 +Ar 7.85078 8.07968 5.21226 +Ar 2.03223 5.74007 3.43845 +Ar 6.12752 5.15792 9.0895 +Ar 6.31432 4.74453 1.28442 +Ar 0.14469 1.80883 1.00882 +Ar 3.38733 0.859129 9.3866 +Ar 1.8513 4.83748 3.57565 +Ar 4.9641 1.69709 2.92853 +Ar 4.69439 8.58465 2.24284 +Ar 8.52547 7.61727 3.499 +Ar 5.41058 5.62408 3.91523 +Ar 4.29181 2.48439 5.20293 +Ar 2.54077 2.77065 6.32843 +Ar 9.42594 1.73494 9.07766 +Ar 7.05099 6.06211 5.80371 +Ar 5.62884 3.99252 2.32817 +Ar 3.01044 6.47846 3.49305 +Ar 8.11484 6.03974 9.99273 +Ar 6.75007 8.43681 7.50192 +Ar 7.78899 9.57315 5.97498 +Ar 5.15115 5.30966 9.47706 +Ar 9.31936 0.443993 2.18826 +Ar 7.14071 3.97125 4.85273 +Ar 5.07424 2.67889 4.05894 +Ar 1.72002 8.30412 7.30678 +Ar 8.9812 7.09069 3.30219 +Ar 2.71071 8.90597 2.62741 +Ar 1.81835 1.03718 1.82565 +Ar 8.37568 0.125978 7.30861 +Ar 8.92944 7.10977 3.83388 +Ar 9.39118 7.58272 2.7392 +201 +10 10 10 +Ar 5 5 5 +Ar 3.87313 5.73295 3.63497 +Ar 1.26258 0.100799 4.12172 +Ar 1.10159 4.34212 8.03789 +Ar 1.68553 8.74191 5.25031 +Ar 3.13274 1.94513 1.85997 +Ar 7.03405 1.31265 1.73485 +Ar 4.08922 7.47022 2.06127 +Ar 3.58184 0.00244104 1.02653 +Ar 5.27005 3.80757 3.76106 +Ar 2.89607 4.28288 2.40539 +Ar 0.114875 0.702451 6.08648 +Ar 9.34867 3.02487 9.05185 +Ar 1.84465 2.99507 8.0757 +Ar 6.06855 4.20323 3.7223 +Ar 3.25266 7.48637 3.35445 +Ar 7.16833 8.19242 0.0718171 +Ar 9.08901 9.00553 5.94015 +Ar 0.189675 7.86545 4.61016 +Ar 6.39849 9.35537 5.73023 +Ar 0.697546 3.65579 2.9288 +Ar 9.39054 6.74899 0.240582 +Ar 5.49707 9.28968 1.65453 +Ar 3.27444 3.51501 6.81452 +Ar 6.29866 1.5525 2.79149 +Ar 4.64982 9.60691 3.2555 +Ar 8.15288 5.51547 8.54029 +Ar 6.94179 0.599838 1.47644 +Ar 5.37966 5.96036 5.79728 +Ar 9.8735 3.95466 5.96734 +Ar 4.16777 7.64724 7.08618 +Ar 6.04369 6.22166 7.43236 +Ar 3.97462 1.4452 9.53387 +Ar 2.57261 7.93528 8.18957 +Ar 2.63467 0.829112 4.88013 +Ar 8.1737 5.4002 1.11248 +Ar 5.12547 3.70872 2.44357 +Ar 3.82244 3.81637 1.79699 +Ar 9.31441 7.23388 9.79397 +Ar 5.2172 5.52303 5.55224 +Ar 1.51073 0.920974 8.80278 +Ar 6.54699 5.25457 3.63229 +Ar 0.975062 7.86054 2.08892 +Ar 9.40749 1.6041 0.0695826 +Ar 9.3944 1.76099 7.02375 +Ar 1.05714 7.26908 1.40206 +Ar 0.875512 4.73728 9.53985 +Ar 0.87403 9.82149 9.78365 +Ar 9.08002 7.92467 9.95481 +Ar 8.81729 2.21584 1.57518 +Ar 9.95981 4.57134 0.530516 +Ar 3.01772 8.74764 1.52663 +Ar 1.4901 4.09918 4.85936 +Ar 2.14934 4.01285 4.04616 +Ar 3.94403 7.37757 4.88059 +Ar 2.71207 1.79254 7.2659 +Ar 7.72304 1.19616 3.9264 +Ar 1.46436 1.41616 1.41128 +Ar 6.25419 4.08813 9.26625 +Ar 5.47793 7.64297 5.31423 +Ar 1.24938 8.28795 5.64537 +Ar 5.906 2.20219 2.22719 +Ar 7.99586 6.40725 6.67558 +Ar 7.90695 2.08468 7.22678 +Ar 2.38571 6.54578 4.94976 +Ar 0.543483 4.32665 7.95794 +Ar 9.07555 2.81133 9.97924 +Ar 1.23925 7.99383 2.2824 +Ar 2.93181 4.88769 7.48209 +Ar 6.57922 7.03311 5.44743 +Ar 5.12078 4.9839 4.35566 +Ar 0.802694 0.877835 3.76606 +Ar 8.24957 0.516574 2.06065 +Ar 8.90722 3.65429 7.58976 +Ar 0.790915 2.90278 7.03097 +Ar 1.48872 0.835137 6.15335 +Ar 0.880791 3.45231 2.98357 +Ar 0.616992 9.78219 9.32629 +Ar 6.93267 7.37385 2.29875 +Ar 7.83518 5.78737 8.30345 +Ar 3.45898 5.08621 3.93421 +Ar 3.18839 7.21309 0.34932 +Ar 7.35437 4.84111 4.51841 +Ar 4.74387 0.259729 5.26859 +Ar 3.91218 1.96141 5.39494 +Ar 6.36433 5.35012 9.44947 +Ar 5.57066 6.1013 4.57543 +Ar 3.71078 7.13575 0.554679 +Ar 7.13267 8.751 8.08733 +Ar 8.4745 0.95792 9.7614 +Ar 6.51654 3.49025 0.550051 +Ar 4.51249 1.40634 6.39581 +Ar 4.61514 6.63256 3.35415 +Ar 6.44425 8.54386 6.58629 +Ar 3.85636 3.77078 5.43398 +Ar 9.44688 3.70312 8.32443 +Ar 3.20095 8.29598 0.518127 +Ar 8.66746 3.93658 2.16028 +Ar 4.47321 1.24615 3.99721 +Ar 3.23632 2.8568 4.22255 +Ar 0.305042 6.84601 0.845912 +Ar 4.30951 9.89081 4.81353 +Ar 5.91209 4.46826 8.08957 +Ar 2.89971 5.44071 2.08941 +Ar 9.1212 0.0409497 8.2423 +Ar 8.0862 4.81407 9.99059 +Ar 8.70323 5.10685 0.842173 +Ar 3.37046 7.37802 2.33168 +Ar 0.57017 2.84092 7.35925 +Ar 1.86622 5.56774 7.07927 +Ar 5.84218 9.5658 2.48035 +Ar 7.12449 1.24036 6.78823 +Ar 7.54274 0.831074 7.85693 +Ar 3.43707 6.7934 6.59203 +Ar 4.49628 8.96041 7.62218 +Ar 5.13876 7.08872 0.0466171 +Ar 0.329645 0.343775 7.82165 +Ar 5.90956 2.02453 6.30304 +Ar 5.60079 2.5502 1.13809 +Ar 0.648723 3.07937 4.9558 +Ar 6.55088 0.616576 2.78534 +Ar 1.88598 7.69475 5.67168 +Ar 6.47486 3.03928 1.09507 +Ar 4.7741 8.22263 7.81637 +Ar 4.67219 5.55962 0.577062 +Ar 2.12326 5.69258 5.24466 +Ar 1.13544 3.34053 4.33406 +Ar 4.29996 9.34654 7.28091 +Ar 8.37924 9.93932 0.116003 +Ar 3.85205 1.44965 4.19509 +Ar 7.23612 7.55002 3.13938 +Ar 6.55743 0.648518 9.64876 +Ar 5.7365 3.36003 2.04684 +Ar 5.40897 8.60198 3.3941 +Ar 8.8512 2.10176 4.25653 +Ar 8.37896 5.1477 7.42059 +Ar 2.43862 5.87741 1.59926 +Ar 0.857514 2.23809 5.65975 +Ar 5.20599 7.00215 5.14985 +Ar 2.245 1.74703 2.32142 +Ar 8.19193 1.72719 8.80939 +Ar 1.92166 7.2765 6.12871 +Ar 9.60594 7.0251 0.783787 +Ar 7.49085 8.79009 5.01202 +Ar 5.12531 1.03312 3.61994 +Ar 6.68699 8.23934 8.65404 +Ar 5.85407 9.37865 6.91885 +Ar 8.28803 6.91793 9.71231 +Ar 0.154994 4.99089 1.81561 +Ar 7.47213 4.11338 3.59508 +Ar 4.94654 6.47822 9.44509 +Ar 5.0936 8.16921 9.92238 +Ar 1.06304 6.57717 2.5574 +Ar 6.40198 8.14627 4.44098 +Ar 4.90826 3.16757 7.38135 +Ar 8.95555 6.00488 4.08592 +Ar 3.95336 4.17199 8.71278 +Ar 5.47846 6.40654 4.7525 +Ar 7.36347 7.83685 3.85437 +Ar 8.27623 8.65346 8.70981 +Ar 1.6617 8.19874 6.1984 +Ar 4.50241 2.00458 0.971449 +Ar 7.76135 5.04448 2.63619 +Ar 8.71161 6.07659 9.21288 +Ar 6.76582 3.08604 7.01563 +Ar 9.21579 9.78598 2.96539 +Ar 0.855888 4.90513 0.457679 +Ar 8.2507 9.56063 5.59129 +Ar 2.08136 1.42156 2.19529 +Ar 7.70847 6.17798 3.27745 +Ar 0.754502 0.909584 7.37261 +Ar 9.43419 0.423678 0.760008 +Ar 5.435 6.11527 9.33427 +Ar 8.02994 9.2571 4.03267 +Ar 0.606574 4.6945 0.383465 +Ar 9.35323 9.74732 3.19666 +Ar 6.36671 5.22578 9.74157 +Ar 5.95597 1.91401 8.77683 +Ar 1.40332 5.56064 7.74702 +Ar 6.30169 2.42405 1.04518 +Ar 2.34835 8.69722 4.20179 +Ar 0.670357 6.6892 5.34706 +Ar 8.63881 2.45052 5.89593 +Ar 1.26038 3.14406 2.16308 +Ar 1.58515 1.54755 9.59656 +Ar 7.05547 1.25183 9.5881 +Ar 3.01513 5.25619 0.776404 +Ar 2.64111 9.14238 6.04527 +Ar 6.33888 7.62816 6.48992 +Ar 5.49963 2.2152 0.907294 +Ar 7.72449 5.53304 3.83241 +Ar 4.46581 6.90197 1.34986 +Ar 7.2834 2.1483 6.41683 +Ar 9.77827 3.36416 1.43895 +Ar 3.87117 2.67413 4.07172 +Ar 6.46873 9.92897 6.25149 +Ar 0.268344 0.0617421 7.69979 +Ar 8.13526 9.23425 0.117487 +Ar 9.51619 8.66444 3.31978 +Ar 2.70354 8.34826 9.27735 +Ar 3.98257 4.97261 4.6757