All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
PathMSDBase.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 <cmath>
23 #include "Colvar.h"
24 #include "PathMSDBase.h"
25 #include "ActionRegister.h"
26 #include "core/PlumedMain.h"
27 #include "core/Atoms.h"
28 #include "tools/PDB.h"
29 #include "tools/RMSD.h"
30 #include "tools/Tools.h"
31 
32 using namespace std;
33 
34 namespace PLMD{
35 namespace colvar{
36 
37 void PathMSDBase::registerKeywords(Keywords& keys){
38  Colvar::registerKeywords(keys);
39  keys.add("compulsory","LAMBDA","the lambda parameter is needed for smoothing, is in the units of plumed");
40  keys.add("compulsory","REFERENCE","the pdb is needed to provide the various milestones");
41  keys.add("optional","NEIGH_SIZE","size of the neighbor list");
42  keys.add("optional","NEIGH_STRIDE","how often the neighbor list needs to be calculated in time units");
43 }
44 
45 PathMSDBase::PathMSDBase(const ActionOptions&ao):
47 neigh_size(-1),
48 neigh_stride(-1),
49 nframes(0)
50 {
51  parse("LAMBDA",lambda);
52  parse("NEIGH_SIZE",neigh_size);
53  parse("NEIGH_STRIDE",neigh_stride);
54  parse("REFERENCE",reference);
55 
56  // open the file
57  FILE* fp=fopen(reference.c_str(),"r");
58  std::vector<AtomNumber> aaa;
59  if (fp!=NULL)
60  {
61  log<<"Opening reference file "<<reference.c_str()<<"\n";
62  bool do_read=true;
63  while (do_read){
64  PDB mypdb;
65  RMSD mymsd(log);
66  do_read=mypdb.readFromFilepointer(fp,plumed.getAtoms().usingNaturalUnits(),0.1/atoms.getUnits().getLength());
67  if(do_read){
68  unsigned nat=0;
69  nframes++;
70  if(mypdb.getAtomNumbers().size()==0) error("number of atoms in a frame should be more than zero");
71  if(nat==0) nat=mypdb.getAtomNumbers().size();
72  if(nat!=mypdb.getAtomNumbers().size()) error("frames should have the same number of atoms");
73  if(aaa.empty()) aaa=mypdb.getAtomNumbers();
74  if(aaa!=mypdb.getAtomNumbers()) error("frames should contain same atoms in same order");
75  log<<"Found PDB: "<<nframes<<" containing "<<mypdb.getAtomNumbers().size()<<" atoms\n";
76  pdbv.push_back(mypdb);
77 // requestAtoms(mypdb.getAtomNumbers()); // is done in non base classes
78  derivs_s.resize(mypdb.getAtomNumbers().size());
79  derivs_z.resize(mypdb.getAtomNumbers().size());
80  mymsd.set(mypdb,"OPTIMAL");
81  msdv.push_back(mymsd); // the vector that stores the frames
82  //log<<mypdb;
83  }else{break ;}
84  }
85  fclose (fp);
86  log<<"Found TOTAL "<<nframes<< " PDB in the file "<<reference.c_str()<<" \n";
87  if(nframes==0) error("at least one frame expected");
88  }
89  if(neigh_stride>0 || neigh_size>0){
90  if(neigh_size>int(nframes)){
91  log.printf(" List size required ( %d ) is too large: resizing to the maximum number of frames required: %u \n",neigh_size,nframes);
93  }
94  log.printf(" Neighbor list enabled: \n");
95  log.printf(" size : %d elements\n",neigh_size);
96  log.printf(" stride : %d timesteps \n",neigh_stride);
97  }else{
98  log.printf(" Neighbor list NOT enabled \n");
99  }
100 
101 }
102 
104 
105  if(neigh_size>0 && getExchangeStep()) error("Neighbor lists for this collective variable are not compatible with replica exchange, sorry for that!");
106 
107  //log.printf("NOW CALCULATE! \n");
108 
109 
110  // resize the list to full
111  if(imgVec.empty()){ // this is the signal that means: recalculate all
112  imgVec.resize(nframes);
113  for(unsigned i=0;i<nframes;i++){
114  imgVec[i].property=indexvec[i];
115  imgVec[i].index=i;
116  }
117  }
118 
119 // THIS IS THE HEAVY PART (RMSD STUFF)
120  unsigned stride=comm.Get_size();
121  unsigned rank=comm.Get_rank();
122  unsigned nat=pdbv[0].size();
123  plumed_assert(nat>0);
124  plumed_assert(nframes>0);
125  plumed_assert(imgVec.size()>0);
126 
127  std::vector<double> tmp_distances(imgVec.size(),0.0);
128  std::vector<Vector> tmp_derivs;
129 // this array is a merge of all tmp_derivs, so as to allow a single comm.Sum below
130  std::vector<Vector> tmp_derivs2(imgVec.size()*nat);
131 
132 // if imgVec.size() is less than nframes, it means that only some msd will be calculated
133  for(unsigned i=rank;i<imgVec.size();i+=stride){
134 // store temporary local results
135  tmp_distances[i]=msdv[imgVec[i].index].calculate(getPositions(),tmp_derivs,true);
136  plumed_assert(tmp_derivs.size()==nat);
137  for(unsigned j=0;j<nat;j++) tmp_derivs2[i*nat+j]=tmp_derivs[j];
138  }
139 // reduce over all processors
140  comm.Sum(&tmp_distances[0],imgVec.size());
141  comm.Sum(&tmp_derivs2[0][0],3*imgVec.size()*nat);
142 // assign imgVec[i].distance and imgVec[i].distder
143  for(unsigned i=0;i<imgVec.size();i++){
144  imgVec[i].distance=tmp_distances[i];
145  imgVec[i].distder.assign(&tmp_derivs2[i*nat],nat+&tmp_derivs2[i*nat]);
146  }
147 
148 // END OF THE HEAVY PART
149 
150  vector<Value*> val_s_path;
151  if(labels.size()>0){
152  for(unsigned i=0;i<labels.size();i++){ val_s_path.push_back(getPntrToComponent(labels[i].c_str()));}
153  }else{
154  val_s_path.push_back(getPntrToComponent("sss"));
155  }
156  Value* val_z_path=getPntrToComponent("zzz");
157 
158  vector<double> s_path(val_s_path.size());for(unsigned i=0;i<s_path.size();i++)s_path[i]=0.;
159  double partition=0.;
160  double tmp;
161 
162  // clean vector
163  for(unsigned i=0;i< derivs_z.size();i++){derivs_z[i].zero();}
164 
165  typedef vector< class ImagePath >::iterator imgiter;
166  for(imgiter it=imgVec.begin();it!=imgVec.end();++it){
167  (*it).similarity=exp(-lambda*((*it).distance));
168  //log<<"DISTANCE "<<(*it).distance<<"\n";
169  for(unsigned i=0;i<s_path.size();i++){
170  s_path[i]+=((*it).property[i])*(*it).similarity;
171  }
172  partition+=(*it).similarity;
173  }
174  for(unsigned i=0;i<s_path.size();i++){ s_path[i]/=partition; val_s_path[i]->set(s_path[i]) ;}
175  val_z_path->set(-(1./lambda)*std::log(partition));
176  for(unsigned j=0;j<s_path.size();j++){
177  // clean up
178  for(unsigned i=0;i< derivs_s.size();i++){derivs_s[i].zero();}
179  // do the derivative
180  for(imgiter it=imgVec.begin();it!=imgVec.end();++it){
181  double expval=(*it).similarity;
182  tmp=lambda*expval*(s_path[j]-(*it).property[j])/partition;
183  for(unsigned i=0;i< derivs_s.size();i++){ derivs_s[i]+=tmp*(*it).distder[i] ;}
184  if(j==0){for(unsigned i=0;i< derivs_z.size();i++){ derivs_z[i]+=(*it).distder[i]*expval/partition;}}
185  }
186  for(unsigned i=0;i< derivs_s.size();i++){
187  setAtomsDerivatives (val_s_path[j],i,derivs_s[i]);
188  if(j==0){setAtomsDerivatives (val_z_path,i,derivs_z[i]);}
189  }
190  }
191  for(unsigned i=0;i<val_s_path.size();++i) setBoxDerivativesNoPbc(val_s_path[i]);
192  setBoxDerivativesNoPbc(val_z_path);
193  //
194  // here set next round neighbors
195  //
196  if (neigh_size>0){
197  //if( int(getStep())%int(neigh_stride/getTimeStep())==0 ){
198  // enforce consistency: the stride is in time steps
199  if( int(getStep())%int(neigh_stride)==0 ){
200 
201  // next round do it all:empty the vector
202  imgVec.clear();
203  }
204  // time to analyze the results:
205  if(imgVec.size()==nframes){
206  //sort by msd
207  sort(imgVec.begin(), imgVec.end(), imgOrderByDist());
208  //resize
209  imgVec.resize(neigh_size);
210  }
211  }
212  //log.printf("CALCULATION DONE! \n");
213 }
214 
215 }
216 
217 }
Log & log
Reference to the log stream.
Definition: Action.h:93
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
std::vector< Vector > derivs_s
Definition: PathMSDBase.h:69
std::vector< Vector > derivs_z
Definition: PathMSDBase.h:70
void error(const std::string &msg) const
Crash calculation and print documentation.
Definition: Action.cpp:195
std::vector< ImagePath > imgVec
Definition: PathMSDBase.h:71
const std::vector< Vector > & getPositions() const
Get the array of all positions.
STL namespace.
void add(const std::string &t, const std::string &k, const std::string &d)
Add a new keyword of type t with name k and description d.
Definition: Keywords.cpp:167
Communicator & comm
Definition: Action.h:158
#define PLUMED_COLVAR_INIT(ao)
Definition: Colvar.h:29
void set(double)
Set the value of the function.
Definition: Value.h:174
std::vector< RMSD > msdv
Definition: PathMSDBase.h:67
void parse(const std::string &key, T &t)
Parse one keyword as generic type.
Definition: Action.h:273
FILE * fopen(const char *path, const char *mode)
Opens a file.
Definition: Action.cpp:83
This class holds the keywords and their documentation.
Definition: Keywords.h:36
int Get_rank() const
Obtain the rank of the present process.
This class is used to bring the relevant information to the Action constructor.
Definition: Action.h:41
virtual void calculate()
Calculate an Action.
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
bool getExchangeStep() const
Check if we are on an exchange step.
Definition: Action.cpp:217
Minimalistic pdb parser.
Definition: PDB.h:38
int fclose(FILE *fp)
Closes a file opened with Action::fclose().
Definition: Action.cpp:93
long int getStep() const
Return the present timestep.
Definition: Action.cpp:169
void setBoxDerivativesNoPbc()
Set box derivatives automatically.
Definition: Colvar.h:107
const Units & getUnits()
Definition: Atoms.h:181
const double & getLength() const
Get length units as double.
Definition: Units.h:95
Provides the keyword RMSD
Definition: RMSD.cpp:35
Main plumed object.
Definition: Plumed.h:201
bool readFromFilepointer(FILE *fp, bool naturalUnits, double scale)
Read from a file pointer.
Definition: PDB.cpp:76
Value * getPntrToComponent(int i)
Return a pointer to the component by index.
std::vector< std::string > labels
Definition: PathMSDBase.h:74
const std::vector< AtomNumber > & getAtomNumbers() const
Access to the indexes.
Definition: PDB.cpp:47
int Get_size() const
Obtain the number of processes.
std::vector< PDB > pdbv
Definition: PathMSDBase.h:73
std::vector< std::vector< double > > indexvec
Definition: PathMSDBase.h:75
void Sum(T *, int)
Wrapper for MPI_Allreduce with MPI_SUM.
Definition: Communicator.h:124