All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Angles.cpp
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 The plumed team
3  (see the PEOPLE file at the root of the distribution for a list of names)
4 
5  See http://www.plumed-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
8 
9  plumed is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  plumed is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #include "MultiColvar.h"
23 #include "tools/Angle.h"
24 #include "tools/SwitchingFunction.h"
25 #include "core/ActionRegister.h"
26 
27 #include <string>
28 #include <cmath>
29 
30 using namespace std;
31 
32 namespace PLMD{
33 namespace multicolvar{
34 
35 //+PLUMEDOC MCOLVAR ANGLES
36 /*
37 Calculate functions of the distribution of angles .
38 
39 You can use this command to calculate functions such as:
40 
41 \f[
42  f(x) = \sum_{ijk} g( \theta_{ijk} )
43 \f]
44 
45 Alternatively you can use this command to calculate functions such as:
46 
47 \f[
48 f(x) = \sum_{ijk} s(r_{ij})s(r_{jk}) g(\theta_{ijk})
49 \f]
50 
51 where \f$s(r)\f$ is a \ref switchingfunction. This second form means that you can
52 use this to calculate functions of the angles in the first coordination sphere of
53 an atom / molecule \cite lj-recon.
54 
55 \par Examples
56 
57 The following example instructs plumed to find the average of two angles and to
58 print it to a file
59 
60 \verbatim
61 ANGLES ATOMS1=1,2,3 ATOMS2=4,5,6 MEAN LABEL=a1
62 PRINT ARG=a1.mean FILE=colvar
63 \endverbatim
64 
65 The following example tells plumed to calculate all angles involving
66 at least one atom from GROUPA and two atoms from GROUPB in which the distances
67 are less than 1.0. The number of angles between \f$\frac{\pi}{4}\f$ and
68 \f$\frac{3\pi}{4}\f$ is then output
69 
70 \verbatim
71 ANGLES GROUPA=1-10 GROUPB=11-100 BETWEEN={GAUSSIAN LOWER=0.25pi UPPER=0.75pi} SWITCH={GAUSSIAN R_0=1.0} LABEL=a1
72 PRINT ARG=a1.between FILE=colvar
73 \endverbatim
74 
75 This final example instructs plumed to calculate all the angles in the first coordination
76 spheres of the atoms. A discretized-normalized histogram of the distribution is then output
77 
78 \verbatim
79 ANGLES GROUP=1-38 HISTOGRAM={GAUSSIAN LOWER=0.0 UPPER=pi NBINS=20} SWITCH={GAUSSIAN R_0=1.0} LABEL=a1
80 PRINT ARG=a1.* FILE=colvar
81 \endverbatim
82 
83 */
84 //+ENDPLUMEDOC
85 
86 class Angles : public MultiColvar {
87 private:
88  bool use_sf;
89  Vector dij, dik;
92 public:
93  static void registerKeywords( Keywords& keys );
94  Angles(const ActionOptions&);
95 // active methods:
96  virtual double compute( const unsigned& j );
97 /// Returns the number of coordinates of the field
98  void calculateWeight();
99  bool isPeriodic(){ return false; }
100  Vector getCentralAtom();
101 };
102 
103 PLUMED_REGISTER_ACTION(Angles,"ANGLES")
104 
105 void Angles::registerKeywords( Keywords& keys ){
106  MultiColvar::registerKeywords( keys );
107  keys.use("ATOMS"); keys.use("MEAN"); keys.use("LESS_THAN");
108  keys.use("BETWEEN"); keys.use("HISTOGRAM"); keys.use("MORE_THAN");
109  // Could also add Region here in theory
110  keys.add("atoms-1","GROUP","Calculate angles for each distinct set of three atoms in the group");
111  keys.add("atoms-2","GROUPA","A group of central atoms about which angles should be calculated");
112  keys.add("atoms-2","GROUPB","When used in conjuction with GROUPA this keyword instructs plumed "
113  "to calculate all distinct angles involving one atom from GROUPA "
114  "and two atoms from GROUPB. The atom from GROUPA is the central atom.");
115  keys.add("atoms-3","GROUPC","This must be used in conjuction with GROUPA and GROUPB. All angles "
116  "involving one atom from GROUPA, one atom from GROUPB and one atom from "
117  "GROUPC are calculated. The GROUPA atoms are assumed to be the central "
118  "atoms");
119  keys.add("optional","SWITCH","A switching function that ensures that only angles between atoms that "
120  "are within a certain fixed cutoff are calculated. The following provides "
121  "information on the \\ref switchingfunction that are available.");
122  keys.add("optional","SWITCHA","A switching function on the distance between the atoms in group A and the atoms in "
123  "group B");
124  keys.add("optional","SWITCHB","A switching function on the distance between the atoms in group A and the atoms in "
125  "group B");
126 }
127 
128 Angles::Angles(const ActionOptions&ao):
130 use_sf(false)
131 {
132  // Read in the atoms
133  int natoms=3; readAtoms( natoms );
134  std::string sfinput,errors; parse("SWITCH",sfinput);
135  if( sfinput.length()>0 ){
136  use_sf=true;
138  sf1.set(sfinput,errors);
139  if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors );
140  sf2.set(sfinput,errors);
141  if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors );
142  log.printf(" only calculating angles for atoms separated by less than %s\n", sf1.description().c_str() );
143  } else {
144  parse("SWITCHA",sfinput);
145  if(sfinput.length()>0){
146  use_sf=true;
148  sf1.set(sfinput,errors);
149  if( errors.length()!=0 ) error("problem reading SWITCHA keyword : " + errors );
150  sfinput.clear(); parse("SWITCHB",sfinput);
151  if(sfinput.length()==0) error("found SWITCHA keyword without SWITCHB");
152  sf2.set(sfinput,errors);
153  if( errors.length()!=0 ) error("problem reading SWITCHB keyword : " + errors );
154  log.printf(" only calculating angles when the distance between GROUPA and GROUPB atoms is less than %s\n", sf1.description().c_str() );
155  log.printf(" only calculating angles when the distance between GROUPA and GROUPC atoms is less than %s\n", sf2.description().c_str() );
156  }
157  }
158 
159  // And setup the ActionWithVessel
161  // And check everything has been read in correctly
162  checkRead();
163 }
164 
168  if(!use_sf){ setWeight(1.0); return; }
169 
170  double w1, w2, dw1, dw2, wtot;
171  w1=sf1.calculate( dij.modulo(), dw1 );
172  w2=sf2.calculate( dik.modulo(), dw2 );
173  wtot=w1*w2; dw1*=w2; dw2*=w1;
174 
175  setWeight( wtot );
176  if( wtot<getTolerance() ) return;
178  addAtomsDerivativeOfWeight( 1, -dw1*dij - dw2*dik );
180  addBoxDerivativesOfWeight( (-dw1)*Tensor(dij,dij) + (-dw2)*Tensor(dik,dik) );
181 }
182 
183 double Angles::compute( const unsigned& j ){
184  Vector ddij,ddik; PLMD::Angle a;
185  double angle=a.compute(dij,dik,ddij,ddik);
186 
187  // And finish the calculation
188  addAtomsDerivatives( 0, ddik );
189  addAtomsDerivatives( 1, - ddik - ddij );
190  addAtomsDerivatives( 2, ddij );
191  addBoxDerivatives( -(Tensor(dij,ddij)+Tensor(dik,ddik)) );
192 
193  return angle;
194 }
195 
198  return getPosition(1);
199 }
200 
201 }
202 }
void addAtomsDerivativeOfWeight(const unsigned &i, const Vector &wder)
Set the derivative of the weight (used in MEAN and HISTOGRAM)
Definition: MultiColvar.h:118
double calculate(double x, double &df) const
Log & log
Reference to the log stream.
Definition: Action.h:93
void readAtoms(int &natoms)
Read in all the keywords that can be used to define atoms.
Definition: MultiColvar.cpp:71
Vector getSeparation(const Vector &vec1, const Vector &vec2) const
Get the separation between a pair of vectors.
double modulo() const
Compute the modulo.
Definition: Vector.h:325
SwitchingFunction sf1
Definition: Angles.cpp:90
double compute(const Vector &v1, const Vector &v2) const
Compute the angle between vectors v1 and v2.
Definition: Angle.cpp:28
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
Vector getCentralAtom()
Get the position of the central atom.
Definition: Angles.cpp:196
void set(int nn, int mm, double r_0, double d_0)
void error(const std::string &msg) const
Crash calculation and print documentation.
Definition: Action.cpp:195
void checkRead()
Check if Action was properly read.
Definition: Action.cpp:161
STL namespace.
Small class to compure switching functions in the form In the future we might extend it so as to be s...
Class to compute angles.
Definition: Angle.h:39
void readVesselKeywords()
Complete the setup of this object (this routine must be called after construction of ActionWithValue)...
virtual double compute(const unsigned &j)
Actually compute the colvar.
Definition: Angles.cpp:183
void addCentralAtomDerivatives(const unsigned &iatom, const Tensor &der)
Add derivatives to the central atom position.
Definition: MultiColvar.h:123
bool weightHasDerivatives
Does the weight have derivatives.
static TensorGeneric< n, n > identity()
return an identity tensor
Definition: Tensor.h:318
void parse(const std::string &key, T &t)
Parse one keyword as generic type.
Definition: Action.h:273
This class holds the keywords and their documentation.
Definition: Keywords.h:36
#define PLUMED_MULTICOLVAR_INIT(ao)
Definition: MultiColvar.h:28
void addBoxDerivatives(const Tensor &)
Add some derivatives to the virial.
This class is used to bring the relevant information to the Action constructor.
Definition: Action.h:41
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
void setWeight(const double &weight)
Set a weight for this colvar (used in MEAN and HISTOGRAM)
void addAtomsDerivatives(const int &, const Vector &)
Add some derivatives for an atom.
Definition: MultiColvar.h:113
const Vector & getPosition(unsigned) const
Get the position of atom iatom.
Definition: MultiColvar.h:93
Provides the keyword ANGLES
Definition: Angles.cpp:86
double getTolerance() const
Return the value of the tolerance.
This is the abstract base class to use for creating distributions of colvars and functions thereof...
Definition: MultiColvar.h:39
std::string description() const
Tensor3d Tensor
Definition: Tensor.h:425
void addBoxDerivativesOfWeight(const Tensor &vir)
void const char const char int double * a
Definition: Matrix.h:42
SwitchingFunction sf2
Definition: Angles.cpp:91
void calculateWeight()
Returns the number of coordinates of the field.
Definition: Angles.cpp:165
bool isPeriodic()
Are the base quantities periodic.
Definition: Angles.cpp:99