All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ContactMap.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 "Colvar.h"
23 #include "tools/NeighborList.h"
24 #include "ActionRegister.h"
25 #include "tools/SwitchingFunction.h"
26 
27 #include <string>
28 #include <cmath>
29 
30 using namespace std;
31 
32 namespace PLMD {
33 namespace colvar {
34 
35 //+PLUMEDOC COLVAR CONTACTMAP
36 /*
37 Calculate the distances between a number of pairs of atoms and transform each distance by a switching function.
38 The transformed distance can be compared with a set of reference values in order to calculate the squared distance
39 between two contact maps.
40 
41 \par Examples
42 
43 The following example calculates switching functions based on the distances between atoms
44 1 and 2, 3 and 4 and 4 and 5. The values of these three switching functions are then output
45 to a file named colvar.
46 
47 \verbatim
48 CONTACTMAP ATOMS1=1,2 ATOMS2=3,4 ATOMS3=4,5 ATOMS4=5,6 SWITCH=(RATIONAL R_0=1.5) LABEL=f1
49 PRINT ARG=f1.* FILE=colvar
50 \endverbatim
51 
52 The following example calculates the difference of the current contact map with respect
53 to a reference provided.
54 
55 \verbatim
56 CONTACTMAP ...
57 ATOMS1=1,2 REFERENCE1=0.1
58 ATOMS2=3,4 REFERENCE2=0.5
59 ATOMS3=4,5 REFERENCE3=0.25
60 ATOMS4=5,6 REFERENCE4=0.0
61 SWITCH=(RATIONAL R_0=1.5)
62 LABEL=cmap
63 CMDIST
64 ... CONTACTMAP
65 
66 PRINT ARG=cmap FILE=colvar
67 \endverbatim
68 (See also \ref PRINT)
69 
70 */
71 //+ENDPLUMEDOC
72 
73 class ContactMap : public Colvar {
74 private:
75  bool pbc, dosum, docmdist;
77  std::vector<SwitchingFunction> sfs;
78  vector<double> reference;
79 public:
80  static void registerKeywords( Keywords& keys );
81  ContactMap(const ActionOptions&);
82  ~ContactMap();
83 // active methods:
84  virtual void calculate();
86 };
87 
88 PLUMED_REGISTER_ACTION(ContactMap,"CONTACTMAP")
89 
90 void ContactMap::registerKeywords( Keywords& keys ){
91  Colvar::registerKeywords( keys );
92  keys.add("numbered","ATOMS","the atoms involved in each of the contacts you wish to calculate. "
93  "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one contact will be "
94  "calculated for each ATOM keyword you specify.");
95  keys.reset_style("ATOMS","atoms");
96  keys.add("numbered","SWITCH","The switching functions to use for each of the contacts in your map. "
97  "You can either specify a global switching function using SWITCH or one "
98  "switching function for each contact. Details of the various switching "
99  "functions you can use are provided on \\ref switchingfunction.");
100  keys.add("numbered","REFERENCE","A reference value for a given contact, by default is 0.0 "
101  "You can either specify a global reference value using REFERENCE or one "
102  "reference value for each contact.");
103  keys.reset_style("SWITCH","compulsory");
104  keys.addFlag("SUM",false,"calculate the sum of all the contacts in the input");
105  keys.addFlag("CMDIST",false,"calculate the distance with respect to the provided reference contant map");
106  keys.addOutputComponent("contact","COMPONENTS","By not using SUM or CMDIST each contact will be stored in a component");
107 }
108 
109 ContactMap::ContactMap(const ActionOptions&ao):
111 pbc(true),
112 dosum(false),
113 docmdist(false)
114 {
115  parseFlag("SUM",dosum);
116  parseFlag("CMDIST",docmdist);
117  if(docmdist==true&&dosum==true) error("You cannot use SUM and CMDIST together");
118  bool nopbc=!pbc;
119  parseFlag("NOPBC",nopbc);
120  pbc=!nopbc;
121 
122  // Read in the atoms
123  std::vector<AtomNumber> t, ga_lista, gb_lista;
124  for(int i=1;;++i ){
125  parseAtomList("ATOMS", i, t );
126  if( t.empty() ) break;
127 
128  if( t.size()!=2 ){
129  std::string ss; Tools::convert(i,ss);
130  error("ATOMS" + ss + " keyword has the wrong number of atoms");
131  }
132  ga_lista.push_back(t[0]); gb_lista.push_back(t[1]);
133  t.resize(0);
134 
135  // Add a value for this contact
136  std::string num; Tools::convert(i,num);
137  if(!dosum&&!docmdist) {addComponentWithDerivatives("contact"+num); componentIsNotPeriodic("contact"+num);}
138  }
139  // Create neighbour lists
140  nl= new NeighborList(ga_lista,gb_lista,true,pbc,getPbc());
141 
142  // Read in switching functions
143  std::string errors; sfs.resize( ga_lista.size() ); unsigned nswitch=0;
144  for(unsigned i=0;i<ga_lista.size();++i){
145  std::string num, sw1; Tools::convert(i+1, num);
146  if( !parseNumbered( "SWITCH", i+1, sw1 ) ) break;
147  nswitch++; sfs[i].set(sw1,errors);
148  if( errors.length()!=0 ) error("problem reading SWITCH" + num + " keyword : " + errors );
149  }
150  if( nswitch==0 ){
151  std::string sw; parse("SWITCH",sw);
152  if(sw.length()==0) error("no switching function specified use SWITCH keyword");
153  for(unsigned i=0;i<ga_lista.size();++i){
154  sfs[i].set(sw,errors);
155  if( errors.length()!=0 ) error("problem reading SWITCH keyword : " + errors );
156  }
157  } else if( nswitch!=sfs.size() ){
158  std::string num; Tools::convert(nswitch+1, num);
159  error("missing SWITCH" + num + " keyword");
160  }
161  // Read in reference values
162  nswitch=0;
163  reference.resize( ga_lista.size() );
164  for(unsigned i=0;i<ga_lista.size();++i) reference[i]=0.;
165  for(unsigned i=0;i<ga_lista.size();++i){
166  if( !parseNumbered( "REFERENCE", i+1, reference[i] ) ) break;
167  nswitch++;
168  }
169  if( nswitch==0 ){
170  parse("REFERENCE",reference[0]);
171  for(unsigned i=1;i<ga_lista.size();++i){
172  reference[i]=reference[0];
173  }
174  nswitch = ga_lista.size();
175  }
176  if ( nswitch != ga_lista.size() ) error("missing REFERENCE keyword");
177 
178  // Ouput details of all contacts
179  for(unsigned i=0;i<sfs.size();++i){
180  log.printf(" The %dth contact is calculated from atoms : %d %d. Inflection point of switching function is at %s. Reference contact value is %lf\n", i+1, ga_lista[i].serial(), gb_lista[i].serial() , ( sfs[i].description() ).c_str(), reference[i] );
181  }
182 
183  // Set up if it is just a list of contacts
184  if(dosum){
186  log.printf(" colvar is sum of all contacts in contact map\n");
187  }
188  if(docmdist){
190  log.printf(" colvar is distance between the contact map matrix and the provided reference matrix\n");
191  }
193  checkRead();
194 }
195 
197  delete nl;
198 }
199 
201 
202  double ncoord=0., coord;
203  Tensor virial;
204  std::vector<Vector> deriv(getNumberOfAtoms());
205 
206  for(unsigned int i=0;i<nl->size();i++) { // sum over close pairs
207  Vector distance;
208  unsigned i0=nl->getClosePair(i).first;
209  unsigned i1=nl->getClosePair(i).second;
210  if(pbc){
211  distance=pbcDistance(getPosition(i0),getPosition(i1));
212  } else {
213  distance=delta(getPosition(i0),getPosition(i1));
214  }
215 
216  double dfunc=0.;
217  coord = sfs[i].calculate(distance.modulo(), dfunc) - reference[i];
218  if( dosum ) {
219  deriv[i0] = deriv[i0] + (-dfunc)*distance ;
220  deriv[i1] = deriv[i1] + dfunc*distance ;
221  virial=virial+(-dfunc)*Tensor(distance,distance);
222  ncoord += coord;
223  } else if ( docmdist ) {
224  deriv[i0] = deriv[i0] + 2.*coord*(-dfunc)*distance ;
225  deriv[i1] = deriv[i1] + 2.*coord*dfunc*distance ;
226  virial=virial+2.*coord*(-dfunc)*Tensor(distance,distance);
227  ncoord += coord*coord;
228  } else {
229  Value* val=getPntrToComponent( i );
230  setAtomsDerivatives( val, i0, (-dfunc)*distance );
231  setAtomsDerivatives( val, i1, dfunc*distance );
232  setBoxDerivatives( val, (-dfunc)*Tensor(distance,distance) );
233  val->set(coord);
234  }
235  }
236 
237  if( dosum || docmdist){
238  for(unsigned i=0;i<deriv.size();++i) setAtomsDerivatives(i,deriv[i]);
239  setValue (ncoord);
240  setBoxDerivatives (virial);
241  }
242 }
243 
244 }
245 }
bool parseNumbered(const std::string &key, const int no, T &t)
Parse one numbered keyword as generic type.
Definition: Action.h:300
const Vector & getPosition(int) const
Get position of i-th atom.
void parseFlag(const std::string &key, bool &t)
Parse one keyword as boolean flag.
Definition: Action.cpp:104
void setNotPeriodic()
Set your default value to have no periodicity.
std::vector< PLMD::AtomNumber > & getFullAtomList()
Return the list of all atoms. These are needed to rebuild the neighbor list.
Log & log
Reference to the log stream.
Definition: Action.h:93
double modulo() const
Compute the modulo.
Definition: Vector.h:325
void componentIsNotPeriodic(const std::string &name)
Set your value component to have no periodicity.
Class implementing fixed size matrices of doubles.
Definition: Tensor.h:70
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
A class for holding the value of a function together with its derivatives.
Definition: Value.h:46
void setAtomsDerivatives(int, const Vector &)
Definition: Colvar.h:97
static bool convert(const std::string &str, double &t)
Convert a string to a double, reading it.
Definition: Tools.cpp:74
void error(const std::string &msg) const
Crash calculation and print documentation.
Definition: Action.cpp:195
Provides the keyword CONTACTMAP
Definition: ContactMap.cpp:73
vector< double > reference
Definition: ContactMap.cpp:78
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 addValueWithDerivatives()
Add a value with the name label that has derivatives.
void requestAtoms(const std::vector< AtomNumber > &a)
Definition: Colvar.cpp:44
#define PLUMED_COLVAR_INIT(ao)
Definition: Colvar.h:29
const Pbc & getPbc() const
Get reference to Pbc.
void setBoxDerivatives(const Tensor &)
Definition: Colvar.h:102
virtual void calculate()
Calculate an Action.
Definition: ContactMap.cpp:200
void set(double)
Set the value of the function.
Definition: Value.h:174
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
A class that implements neighbor lists from two lists or a single list of atoms.
Definition: NeighborList.h:36
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
This is the abstract base class to use for implementing new collective variables, within it there is ...
Definition: Colvar.h:39
std::pair< unsigned, unsigned > getClosePair(unsigned i) const
Get the i-th pair of the neighbor list.
std::vector< SwitchingFunction > sfs
Definition: ContactMap.cpp:77
VectorGeneric< n > delta(const VectorGeneric< n > &v1, const VectorGeneric< n > &v2)
Definition: Vector.h:262
void setValue(const double &d)
Set the default value (the one without name)
Vector pbcDistance(const Vector &, const Vector &) const
Compute the pbc distance between two positions.
void addComponentWithDerivatives(const std::string &name)
Add a value with a name like label.name that has derivatives.
Value * getPntrToComponent(int i)
Return a pointer to the component by index.
Tensor3d Tensor
Definition: Tensor.h:425
unsigned getNumberOfAtoms() const
Get number of available atoms.
unsigned size() const
Get the size of the neighbor list.