All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Ghost.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 "ActionWithVirtualAtom.h"
23 #include "ActionRegister.h"
24 #include "tools/Vector.h"
25 #include "tools/Exception.h"
26 
27 using namespace std;
28 
29 namespace PLMD{
30 namespace vatom{
31 
32 //+PLUMEDOC VATOM GHOST
33 /*
34 Calculate the absolute position of a ghost atom with fixed coordinates
35 in the local reference frame formed by three atoms.
36 The computed ghost atom is stored as a virtual atom that can be accessed in
37 an atom list through the the label for the GHOST action that creates it.
38 
39 \par Examples
40 The following input instructs plumed to print the distance between the
41 ghost atom and the center of mass for atoms 15,20:
42 \verbatim
43 GHOST ATOMS=1,5,10 COORDINATES=10.0,10.0,10.0 LABEL=c1
44 COM ATOMS=15,20 LABEL=c2
45 DISTANCE ATOMS=c1,c2 LABEL=d1
46 PRINT ARG=d1
47 \endverbatim
48 (See also \ref DISTANCE and \ref PRINT).
49 
50 \warning If a force is added to a ghost atom, the contribution
51 to the virial could contain small artifacts. It is therefore discouraged to
52 use GHOST in a constant pressure simulation.
53 
54 */
55 //+ENDPLUMEDOC
56 
57 
58 class Ghost:
60 {
61  vector<double> coord;
62 public:
63  Ghost(const ActionOptions&ao);
64  void calculate();
65  static void registerKeywords( Keywords& keys );
66 };
67 
68 PLUMED_REGISTER_ACTION(Ghost,"GHOST")
69 
70 void Ghost::registerKeywords(Keywords& keys){
71  ActionWithVirtualAtom::registerKeywords(keys);
72  keys.add("atoms","COORDINATES","coordinates of the ghost atom in the local reference frame");
73 }
74 
75 Ghost::Ghost(const ActionOptions&ao):
76  Action(ao),
78 {
79  vector<AtomNumber> atoms;
80  parseAtomList("ATOMS",atoms);
81  if(atoms.size()!=3) error("ATOMS should contain a list of three atoms");
82 
83  parseVector("COORDINATES",coord);
84  if(coord.size()!=3) error("COORDINATES should be a list of three real numbers");
85 
86  checkRead();
87  log.printf(" of atoms");
88  for(unsigned i=0;i<atoms.size();++i) log.printf(" %d",atoms[i].serial());
89  log.printf("\n");
90  log<<" WARNING: GHOST does not include virial contributions, please avoid using it with constant pressure molecular dynamics\n";
91  requestAtoms(atoms);
92 }
93 
95  Vector pos;
96  vector<Tensor> deriv(getNumberOfAtoms());
97  vector<Vector> n;
98 
99 // first versor
100  Vector n01 = delta(getPosition(0), getPosition(1));
101  n.push_back(n01/n01.modulo());
102 
103 // auxiliary vector
104  Vector n02 = delta(getPosition(0), getPosition(2));
105 
106 // second versor
107  Vector n03 = crossProduct(n[0],n02);
108  double n03_norm = n03.modulo();
109  n.push_back(n03/n03_norm);
110 
111 // third versor
112  n.push_back(crossProduct(n[0],n[1]));
113 
114 // origin of the reference system
115  pos = getPosition(0);
116 
117  for(unsigned i=0;i<3;++i){
118  pos += coord[i] * n[i];
119  }
120 
121  setPosition(pos);
122  setMass(1.0);
123  setCharge(0.0);
124 
125 // some useful tensors for derivatives
126  Tensor dn0d0 = (-Tensor::identity()+Tensor(n[0],n[0]))/n01.modulo();
127  Tensor dn0d1 = (+Tensor::identity()-Tensor(n[0],n[0]))/n01.modulo();
128  Tensor dn02d0 = -Tensor::identity();
129  Tensor dn02d2 = Tensor::identity();
130 
131 // derivative of n1 = n0 x n02
132  Tensor dn1d0, dn1d1, dn1d2;
133  Vector aux0, aux1, aux2;
134 
135  for(unsigned j=0;j<3;++j){
136 // derivative of n0 x n02 with respect to point 0, coordinate j
137  Vector tmp00 = Vector( dn0d0(j,0), dn0d0(j,1), dn0d0(j,2));
138  Vector tmp020 = Vector(dn02d0(j,0), dn02d0(j,1), dn02d0(j,2));
139  Vector tmp0 = crossProduct(tmp00,n02) + crossProduct(n[0],tmp020);
140  aux0[j] = dotProduct(tmp0,n[1]);
141 // derivative of n0 x n02 with respect to point 1, coordinate j
142  Vector tmp01 = Vector( dn0d1(j,0), dn0d1(j,1), dn0d1(j,2));
143  Vector tmp1 = crossProduct(tmp01,n02);
144  aux1[j] = dotProduct(tmp1,n[1]);
145 // derivative of n0 x n02 with respect to point 2, coordinate j
146  Vector tmp022 = Vector(dn02d2(j,0), dn02d2(j,1), dn02d2(j,2));
147  Vector tmp2 = crossProduct(n[0],tmp022);
148  aux2[j] = dotProduct(tmp2,n[1]);
149 // derivative of n1 = (n0 x n02) / || (n0 x n02) ||
150  for(unsigned i=0;i<3;++i) {
151  dn1d0(j,i) = ( tmp0[i] - aux0[j] * n[1][i] ) / n03_norm;
152  dn1d1(j,i) = ( tmp1[i] - aux1[j] * n[1][i] ) / n03_norm;
153  dn1d2(j,i) = ( tmp2[i] - aux2[j] * n[1][i] ) / n03_norm;
154  }
155  }
156 
157 // Derivative of the last versor n2 = n0 x n1 = ( n0( n0 n02 ) - n02 ) / || n0 x n02 ||
158 // Scalar product and derivatives
159  double n0_n02 = dotProduct(n[0],n02);
160  Vector dn0_n02d0, dn0_n02d1, dn0_n02d2;
161 
162  for(unsigned j=0;j<3;++j){
163  for(unsigned i=0;i<3;++i){
164  dn0_n02d0[j] += dn0d0(j,i)*n02[i] + n[0][i]*dn02d0(j,i);
165  dn0_n02d1[j] += dn0d1(j,i)*n02[i];
166  dn0_n02d2[j] += n[0][i]*dn02d2(j,i);
167  }
168  }
169 
170  Tensor dn2d0, dn2d1, dn2d2;
171  for(unsigned j=0;j<3;++j){
172  for(unsigned i=0;i<3;++i){
173  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;
174  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;
175  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;
176  }
177  }
178 
179 // Finally, the derivative tensor
180  deriv[0] = Tensor::identity() + coord[0]*dn0d0 + coord[1]*dn1d0 + coord[2]*dn2d0;
181  deriv[1] = coord[0]*dn0d1 + coord[1]*dn1d1 + coord[2]*dn2d1;
182  deriv[2] = coord[1]*dn1d2 + coord[2]*dn2d2;
183 
184  setAtomsDerivatives(deriv);
185 }
186 
187 }
188 }
const Vector & getPosition(int) const
Get position of i-th atom.
Log & log
Reference to the log stream.
Definition: Action.h:93
double modulo() const
Compute the modulo.
Definition: Vector.h:325
VectorGeneric< 3 > crossProduct(const VectorGeneric< 3 > &v1, const VectorGeneric< 3 > &v2)
Definition: Vector.h:317
Class implementing fixed size matrices of doubles.
Definition: Tensor.h:70
void setPosition(const Vector &)
Set position of the virtual atom.
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
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.
void parseAtomList(const std::string &key, std::vector< AtomNumber > &t)
Parse a list of atoms without a numbered keyword.
void setMass(double)
Set its mass.
vector< double > coord
Definition: Ghost.cpp:61
void const char const char int * n
Definition: Matrix.h:42
void requestAtoms(const std::vector< AtomNumber > &a)
Request atoms on which the calculation depends.
static TensorGeneric< n, n > identity()
return an identity tensor
Definition: Tensor.h:318
This class holds the keywords and their documentation.
Definition: Keywords.h:36
void setAtomsDerivatives(const std::vector< Tensor > &d)
Set the derivatives of virtual atom coordinate wrt atoms on which it dependes.
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
Base class for all the input Actions.
Definition: Action.h:60
void parseVector(const std::string &key, std::vector< T > &t)
Parse one keyword as std::vector.
Definition: Action.h:311
Inherit from here if you are calculating the position of a virtual atom (eg a center of mass) ...
VectorGeneric< n > delta(const VectorGeneric< n > &v1, const VectorGeneric< n > &v2)
Definition: Vector.h:262
T dotProduct(const std::vector< T > &A, const std::vector< T > &B)
Calculate the dot product between two vectors.
Definition: Matrix.h:54
void calculate()
Calculate an Action.
Definition: Ghost.cpp:94
void setCharge(double)
Set its charge.
Tensor3d Tensor
Definition: Tensor.h:425
unsigned getNumberOfAtoms() const
Get number of available atoms.
Vector3d Vector
Alias for three dimensional vectors.
Definition: Vector.h:351
Provides the keyword GHOST
Definition: Ghost.cpp:58