All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
SimpleMD.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 "CLTool.h"
23 #include "CLToolRegister.h"
24 #include "wrapper/Plumed.h"
25 #include "tools/Vector.h"
26 #include "tools/Random.h"
27 #include <string>
28 #include <cstdio>
29 #include <cmath>
30 #include <vector>
31 
32 using namespace std;
33 
34 namespace PLMD{
35 namespace cltools{
36 
37 //+PLUMEDOC TOOLS simplemd
38 /*
39 simplemd allows one to do molecular dynamics on systems of Lennard-Jones atoms.
40 
41 The input to simplemd is spcified in an input file. Configurations are input and
42 output in xyz format. The input file should contain one directive per line.
43 The directives available are as follows:
44 
45 \par Examples
46 
47 You run an MD simulation using simplemd with the following command:
48 \verbatim
49 plumed simplemd < in
50 \endverbatim
51 
52 The following is an example of an input file for a simplemd calculation. This file
53 instructs simplemd to do 50 steps of MD at a temperature of 0.722
54 \verbatim
55 nputfile input.xyz
56 outputfile output.xyz
57 temperature 0.722
58 tstep 0.005
59 friction 1
60 forcecutoff 2.5
61 listcutoff 3.0
62 nstep 50
63 nconfig 10 trajectory.xyz
64 nstat 10 energies.dat
65 \endverbatim
66 
67 If you run the following a description of all the directives that can be used in the
68 input file will be output.
69 \verbatim
70 plumed simplemd --help
71 \endverbatim
72 
73 */
74 //+ENDPLUMEDOC
75 
76 class SimpleMD:
77 public PLMD::CLTool
78 {
79  string description()const{
80  return "run lj code";
81  }
82 
87 
88 
89 public:
90 static void registerKeywords( Keywords& keys ){
91  keys.add("compulsory","nstep","The number of steps of dynamics you want to run");
92  keys.add("compulsory","temperature","NVE","the temperature at which you wish to run the simulation in LJ units");
93  keys.add("compulsory","friction","off","The friction (in LJ units) for the langevin thermostat that is used to keep the temperature constant");
94  keys.add("compulsory","tstep","0.005","the integration timestep in LJ units");
95  keys.add("compulsory","inputfile","An xyz file containing the initial configuration of the system");
96  keys.add("compulsory","forcecutoff","2.5","");
97  keys.add("compulsory","listcutoff","3.0","");
98  keys.add("compulsory","outputfile","An output xyz file containing the final configuration of the system");
99  keys.add("compulsory","nconfig","10","The frequency with which to write configurations to the trajectory file followed by the name of the trajectory file");
100  keys.add("compulsory","nstat","1","The frequency with which to write the statistics to the statistics file followed by the name of the statistics file");
101  keys.add("compulsory","maxneighbours","10000","The maximum number of neighbours an atom can have");
102  keys.add("compulsory","idum","0","The random number seed");
103  keys.add("compulsory","ndim","3","The dimensionality of the system (some interesting LJ clusters are two dimensional)");
104  keys.add("compulsory","wrapatoms","false","If true, atomic coordinates are written wrapped in minimal cell");
105 }
106 
107 SimpleMD( const CLToolOptions& co ) :
108  CLTool(co),
109  write_positions_first(true),
110  write_statistics_first(true),
111  write_statistics_last_time_reopened(0),
112  write_statistics_fp(NULL)
113 {
114  inputdata=ifile;
115 }
116 
117 private:
118 
119 void
120 read_input(double& temperature,
121  double& tstep,
122  double& friction,
123  double& forcecutoff,
124  double& listcutoff,
125  int& nstep,
126  int& nconfig,
127  int& nstat,
128  bool& wrapatoms,
129  string& inputfile,
130  string& outputfile,
131  string& trajfile,
132  string& statfile,
133  int& maxneighbours,
134  int& ndim,
135  int& idum)
136 {
137 
138  // Read everything from input file
139  char buffer1[256];
140  std::string tempstr; parse("temperature",tempstr);
141  if( tempstr!="NVE" ) Tools::convert(tempstr,temperature);
142  parse("tstep",tstep);
143  std::string frictionstr; parse("friction",frictionstr);
144  if( tempstr!="NVE" ){
145  if(frictionstr=="off"){ fprintf(stderr,"Specify friction for thermostat\n"); exit(1); }
146  Tools::convert(frictionstr,friction);
147  }
148  parse("forcecutoff",forcecutoff);
149  parse("listcutoff",listcutoff);
150  parse("nstep",nstep);
151  parse("maxneighbours",maxneighbours);
152  parse("idum",idum);
153 
154  // Read in stuff with sanity checks
155  parse("inputfile",inputfile);
156  if(inputfile.length()==0){
157  fprintf(stderr,"Specify input file\n");
158  exit(1);
159  }
160  parse("outputfile",outputfile);
161  if(outputfile.length()==0){
162  fprintf(stderr,"Specify output file\n");
163  exit(1);
164  }
165  std::string nconfstr; parse("nconfig",nconfstr);
166  sscanf(nconfstr.c_str(),"%100d %255s",&nconfig,buffer1);
167  trajfile=buffer1;
168  if(trajfile.length()==0){
169  fprintf(stderr,"Specify traj file\n");
170  exit(1);
171  }
172  std::string nstatstr; parse("nstat",nstatstr);
173  sscanf(nstatstr.c_str(),"%100d %255s",&nstat,buffer1);
174  statfile=buffer1;
175  if(statfile.length()==0){
176  fprintf(stderr,"Specify stat file\n");
177  exit(1);
178  }
179  parse("ndim",ndim);
180  if(ndim<1 || ndim>3){
181  fprintf(stderr,"ndim should be 1,2 or 3\n");
182  exit(1);
183  }
184  std::string w;
185  parse("wrapatoms",w);
186  wrapatoms=false;
187  if(w.length()>0 && (w[0]=='T' || w[0]=='t')) wrapatoms=true;
188 }
189 
190 void read_natoms(const string & inputfile,int & natoms){
191 // read the number of atoms in file "input.xyz"
192  FILE* fp=fopen(inputfile.c_str(),"r");
193  if(!fp){
194  fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str());
195  exit(1);
196  }
197  fscanf(fp,"%1000d",&natoms);
198  fclose(fp);
199 }
200 
201 void read_positions(const string& inputfile,int natoms,vector<Vector>& positions,double cell[3]){
202 // read positions and cell from a file called inputfile
203 // natoms (input variable) and number of atoms in the file should be consistent
204  FILE* fp=fopen(inputfile.c_str(),"r");
205  if(!fp){
206  fprintf(stderr,"ERROR: file %s not found\n",inputfile.c_str());
207  exit(1);
208  }
209  char buffer[256];
210  char atomname[256];
211  fgets(buffer,256,fp);
212  fscanf(fp,"%1000lf %1000lf %1000lf",&cell[0],&cell[1],&cell[2]);
213  for(int i=0;i<natoms;i++){
214  fscanf(fp,"%255s %1000lf %1000lf %1000lf",atomname,&positions[i][0],&positions[i][1],&positions[i][2]);
215 // note: atomname is read but not used
216  }
217  fclose(fp);
218 }
219 
220 void randomize_velocities(const int natoms,const int ndim,const double temperature,const vector<double>&masses,vector<Vector>& velocities,Random&random){
221 // randomize the velocities according to the temperature
222  for(int iatom=0;iatom<natoms;iatom++) for(int i=0;i<ndim;i++)
223  velocities[iatom][i]=sqrt(temperature/masses[iatom])*random.Gaussian();
224 }
225 
226 void pbc(const double cell[3],const Vector & vin,Vector & vout){
227 // apply periodic boundary condition to a vector
228  for(int i=0;i<3;i++){
229  vout[i]=vin[i]-floor(vin[i]/cell[i]+0.5)*cell[i];
230  }
231 }
232 
233 void check_list(const int natoms,const vector<Vector>& positions,const vector<Vector>&positions0,const double listcutoff,
234  const double forcecutoff,bool & recompute)
235 {
236 // check if the neighbour list have to be recomputed
237  Vector displacement; // displacement from positions0 to positions
238  double delta2; // square of the 'skin' thickness
239  recompute=false;
240  delta2=(0.5*(listcutoff-forcecutoff))*(0.5*(listcutoff-forcecutoff));
241 // if ANY atom moved more than half of the skin thickness, recompute is set to .true.
242  for(int iatom=0;iatom<natoms;iatom++){
243  for(int k=0;k<3;k++) displacement[k]=positions[iatom][k]-positions0[iatom][k];
244  double s=0.0;
245  for(int k=0;k<3;k++) s+=displacement[k]*displacement[k];
246  if(s>delta2) recompute=true;
247  }
248 }
249 
250 
251 void compute_list(const int natoms,const int listsize,const vector<Vector>& positions,const double cell[3],const double listcutoff,
252  vector<int>& point,vector<int>& list){
253 // see Allen-Tildesey for a definition of point and list
254  Vector distance; // distance of the two atoms
255  Vector distance_pbc; // minimum-image distance of the two atoms
256  double listcutoff2; // squared list cutoff
257  listcutoff2=listcutoff*listcutoff;
258  point[0]=0;
259  for(int iatom=0;iatom<natoms-1;iatom++){
260  point[iatom+1]=point[iatom];
261  for(int jatom=iatom+1;jatom<natoms;jatom++){
262  for(int k=0;k<3;k++) distance[k]=positions[iatom][k]-positions[jatom][k];
263  pbc(cell,distance,distance_pbc);
264 // if the interparticle distance is larger than the cutoff, skip
265  double d2=0; for(int k=0;k<3;k++) d2+=distance_pbc[k]*distance_pbc[k];
266  if(d2>listcutoff2)continue;
267  if(point[iatom+1]>listsize){
268 // too many neighbours
269  fprintf(stderr,"%s","Verlet list size exceeded\n");
270  fprintf(stderr,"%s","Increase maxneighbours\n");
271  exit(1);
272  }
273  list[point[iatom+1]]=jatom;
274  point[iatom+1]++;
275  }
276  }
277 }
278 
279 void compute_forces(const int natoms,const int listsize,const vector<Vector>& positions,const double cell[3],
280  double forcecutoff,const vector<int>& point,const vector<int>& list,vector<Vector>& forces,double & engconf)
281 {
282  Vector distance; // distance of the two atoms
283  Vector distance_pbc; // minimum-image distance of the two atoms
284  double distance_pbc2; // squared minimum-image distance
285  double forcecutoff2; // squared force cutoff
286  Vector f; // force
287  double engcorrection; // energy necessary shift the potential avoiding discontinuities
288 
289  forcecutoff2=forcecutoff*forcecutoff;
290  engconf=0.0;
291  for(int i=0;i<natoms;i++)for(int k=0;k<3;k++) forces[i][k]=0.0;
292  engcorrection=4.0*(1.0/pow(forcecutoff2,6.0)-1.0/pow(forcecutoff2,3));
293  for(int iatom=0;iatom<natoms-1;iatom++){
294  for(int jlist=point[iatom];jlist<point[iatom+1];jlist++){
295  int jatom=list[jlist];
296  for(int k=0;k<3;k++) distance[k]=positions[iatom][k]-positions[jatom][k];
297  pbc(cell,distance,distance_pbc);
298  distance_pbc2=0.0; for(int k=0;k<3;k++) distance_pbc2+=distance_pbc[k]*distance_pbc[k];
299 // if the interparticle distance is larger than the cutoff, skip
300  if(distance_pbc2>forcecutoff2) continue;
301  double distance_pbc6=distance_pbc2*distance_pbc2*distance_pbc2;
302  double distance_pbc8=distance_pbc6*distance_pbc2;
303  double distance_pbc12=distance_pbc6*distance_pbc6;
304  double distance_pbc14=distance_pbc12*distance_pbc2;
305  engconf+=4.0*(1.0/distance_pbc12 - 1.0/distance_pbc6) - engcorrection;
306  for(int k=0;k<3;k++) f[k]=2.0*distance_pbc[k]*4.0*(6.0/distance_pbc14-3.0/distance_pbc8);
307 // same force on the two atoms, with opposite sign:
308  for(int k=0;k<3;k++) forces[iatom][k]+=f[k];
309  for(int k=0;k<3;k++) forces[jatom][k]-=f[k];
310  }
311  }
312 }
313 
314 void compute_engkin(const int natoms,const vector<double>& masses,const vector<Vector>& velocities,double & engkin)
315 {
316 // calculate the kinetic energy from the velocities
317  engkin=0.0;
318  for(int iatom=0;iatom<natoms;iatom++)for(int k=0;k<3;k++){
319  engkin+=0.5*masses[iatom]*velocities[iatom][k]*velocities[iatom][k];
320  }
321 }
322 
323 
324 void thermostat(const int natoms,const int ndim,const vector<double>& masses,const double dt,const double friction,
325  const double temperature,vector<Vector>& velocities,double & engint,Random & random){
326 // Langevin thermostat, implemented as decribed in Bussi and Parrinello, Phys. Rev. E (2007)
327 // it is a linear combination of old velocities and new, randomly chosen, velocity,
328 // with proper coefficients
329  double c1,c2;
330  c1=exp(-friction*dt);
331  for(int iatom=0;iatom<natoms;iatom++){
332  c2=sqrt((1.0-c1*c1)*temperature/masses[iatom]);
333  for(int i=0;i<ndim;i++){
334  engint+=0.5*masses[iatom]*velocities[iatom][i]*velocities[iatom][i];
335  velocities[iatom][i]=c1*velocities[iatom][i]+c2*random.Gaussian();
336  engint-=0.5*masses[iatom]*velocities[iatom][i]*velocities[iatom][i];
337  }
338  }
339 }
340 
341 void write_positions(const string& trajfile,int natoms,const vector<Vector>& positions,const double cell[3],const bool wrapatoms)
342 {
343 // write positions on file trajfile
344 // positions are appended at the end of the file
345  Vector pos;
346  FILE*fp;
347  if(write_positions_first){
348  fp=fopen(trajfile.c_str(),"w");
349  write_positions_first=false;
350  } else {
351  fp=fopen(trajfile.c_str(),"a");
352  }
353  fprintf(fp,"%d\n",natoms);
354  fprintf(fp,"%f %f %f\n",cell[0],cell[1],cell[2]);
355  for(int iatom=0;iatom<natoms;iatom++){
356 // usually, it is better not to apply pbc here, so that diffusion
357 // is more easily calculated from a trajectory file:
358  if(wrapatoms) pbc(cell,positions[iatom],pos);
359  else for(int k=0;k<3;k++) pos[k]=positions[iatom][k];
360  fprintf(fp,"Ar %10.7f %10.7f %10.7f\n",pos[0],pos[1],pos[2]);
361  }
362  fclose(fp);
363 }
364 
365 void write_final_positions(const string& outputfile,int natoms,const vector<Vector>& positions,const double cell[3],const bool wrapatoms)
366 {
367 // write positions on file outputfile
368  Vector pos;
369  FILE*fp;
370  fp=fopen(outputfile.c_str(),"w");
371  fprintf(fp,"%d\n",natoms);
372  fprintf(fp,"%f %f %f\n",cell[0],cell[1],cell[2]);
373  for(int iatom=0;iatom<natoms;iatom++){
374 // usually, it is better not to apply pbc here, so that diffusion
375 // is more easily calculated from a trajectory file:
376  if(wrapatoms) pbc(cell,positions[iatom],pos);
377  else for(int k=0;k<3;k++) pos[k]=positions[iatom][k];
378  fprintf(fp,"Ar %10.7f %10.7f %10.7f\n",pos[0],pos[1],pos[2]);
379  }
380  fclose(fp);
381 }
382 
383 
384 void write_statistics(const string & statfile,const int istep,const double tstep,
385  const int natoms,const int ndim,const double engkin,const double engconf,const double engint){
386 // write statistics on file statfile
387  if(write_statistics_first){
388 // first time this routine is called, open the file
389  write_statistics_fp=fopen(statfile.c_str(),"w");
390  write_statistics_first=false;
391  }
392  if(istep-write_statistics_last_time_reopened>100){
393 // every 100 steps, reopen the file to flush the buffer
394  fclose(write_statistics_fp);
395  write_statistics_fp=fopen(statfile.c_str(),"a");
396  write_statistics_last_time_reopened=istep;
397  }
398  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);
399 }
400 
401 
402 
403 int main(FILE* in,FILE*out,PLMD::Communicator& pc){
404  int natoms; // number of atoms
405  vector<Vector> positions; // atomic positions
406  vector<Vector> velocities; // velocities
407  vector<double> masses; // masses
408  vector<Vector> forces; // forces
409  double cell[3]; // cell size
410  double cell9[3][3]; // cell size
411 
412 // neighbour list variables
413 // see Allen and Tildesey book for details
414  int listsize; // size of the list array
415  vector<int> list; // neighbour list
416  vector<int> point; // pointer to neighbour list
417  vector<Vector> positions0; // reference atomic positions, i.e. positions when the neighbour list
418 
419 // input parameters
420 // all of them have a reasonable default value, set in read_input()
421  double tstep; // simulation timestep
422  double temperature; // temperature
423  double friction; // friction for Langevin dynamics (for NVE, use 0)
424  double listcutoff; // cutoff for neighbour list
425  double forcecutoff; // cutoff for forces
426  int nstep; // number of steps
427  int nconfig; // stride for output of configurations
428  int nstat; // stride for output of statistics
429  int maxneighbour; // maximum average number of neighbours per atom
430  int ndim; // dimensionality of the system (1, 2, or 3)
431  int idum; // seed
432  bool wrapatoms; // if true, atomic coordinates are written wrapped in minimal cell
433  string inputfile; // name of file with starting configuration (xyz)
434  string outputfile; // name of file with final configuration (xyz)
435  string trajfile; // name of the trajectory file (xyz)
436  string statfile; // name of the file with statistics
437  string string; // a string for parsing
438 
439  double engkin; // kinetic energy
440  double engconf; // configurational energy
441  double engint; // integral for conserved energy in Langevin dynamics
442 
443  bool recompute_list; // control if the neighbour list have to be recomputed
444 
445  Random random; // random numbers stream
446 
447  PLMD::Plumed* plumed=NULL;
448 
449 // Commenting the next line it is possible to switch-off plumed
450  plumed=new PLMD::Plumed;
451 
452  if(plumed){
453  int s=sizeof(double);
454  plumed->cmd("setRealPrecision",&s);
455  }
456 
457  read_input(temperature,tstep,friction,forcecutoff,
458  listcutoff,nstep,nconfig,nstat,
459  wrapatoms,inputfile,outputfile,trajfile,statfile,
460  maxneighbour,ndim,idum);
461 
462 // number of atoms is read from file inputfile
463  read_natoms(inputfile,natoms);
464 
465 // write the parameters in output so they can be checked
466  fprintf(out,"%s %s\n","Starting configuration :",inputfile.c_str());
467  fprintf(out,"%s %s\n","Final configuration :",outputfile.c_str());
468  fprintf(out,"%s %d\n","Number of atoms :",natoms);
469  fprintf(out,"%s %f\n","Temperature :",temperature);
470  fprintf(out,"%s %f\n","Time step :",tstep);
471  fprintf(out,"%s %f\n","Friction :",friction);
472  fprintf(out,"%s %f\n","Cutoff for forces :",forcecutoff);
473  fprintf(out,"%s %f\n","Cutoff for neighbour list :",listcutoff);
474  fprintf(out,"%s %d\n","Number of steps :",nstep);
475  fprintf(out,"%s %d\n","Stride for trajectory :",nconfig);
476  fprintf(out,"%s %s\n","Trajectory file :",trajfile.c_str());
477  fprintf(out,"%s %d\n","Stride for statistics :",nstat);
478  fprintf(out,"%s %s\n","Statistics file :",statfile.c_str());
479  fprintf(out,"%s %d\n","Max average number of neighbours :",maxneighbour);
480  fprintf(out,"%s %d\n","Dimensionality :",ndim);
481  fprintf(out,"%s %d\n","Seed :",idum);
482  fprintf(out,"%s %s\n","Are atoms wrapped on output? :",(wrapatoms?"T":"F"));
483 
484 // Setting the seed
485  random.setSeed(idum);
486 
487 // Since each atom pair is counted once, the total number of pairs
488 // will be half of the number of neighbours times the number of atoms
489  listsize=maxneighbour*natoms/2;
490 
491 // allocation of dynamical arrays
492  positions.resize(natoms);
493  positions0.resize(natoms);
494  velocities.resize(natoms);
495  forces.resize(natoms);
496  masses.resize(natoms);
497  point.resize(natoms);
498  list.resize(listsize);
499 
500 // masses are hard-coded to 1
501  for(unsigned i=0;i<natoms;++i) masses[i]=1.0;
502 
503 // energy integral initialized to 0
504  engint=0.0;
505 
506 // positions are read from file inputfile
507  read_positions(inputfile,natoms,positions,cell);
508 
509 // velocities are randomized according to temperature
510  randomize_velocities(natoms,ndim,temperature,masses,velocities,random);
511 
512  if(plumed){
513  plumed->cmd("setNoVirial");
514  plumed->cmd("setNatoms",&natoms);
515  plumed->cmd("setMDEngine","simpleMD");
516  plumed->cmd("setTimestep",&tstep);
517  plumed->cmd("setPlumedDat","plumed.dat");
518  plumed->cmd("init");
519  }
520 
521 // neighbour list are computed, and reference positions are saved
522  compute_list(natoms,listsize,positions,cell,listcutoff,point,list);
523 
524  fprintf(out,"List size: %d\n",point[natoms-1]);
525  for(int iatom=0;iatom<natoms;++iatom) for(int k=0;k<3;++k) positions0[iatom][k]=positions[iatom][k];
526 
527 // forces are computed before starting md
528  compute_forces(natoms,listsize,positions,cell,forcecutoff,point,list,forces,engconf);
529 
530 // remove forces if ndim<3
531  if(ndim<3)
532  for(int iatom=0;iatom<natoms;++iatom) for(int k=ndim;k<3;++k) forces[iatom][k]=0.0;
533 
534 // here is the main md loop
535 // Langevin thermostat is applied before and after a velocity-Verlet integrator
536 // the overall structure is:
537 // thermostat
538 // update velocities
539 // update positions
540 // (eventually recompute neighbour list)
541 // compute forces
542 // update velocities
543 // thermostat
544 // (eventually dump output informations)
545  for(int istep=0;istep<nstep;istep++){
546  thermostat(natoms,ndim,masses,0.5*tstep,friction,temperature,velocities,engint,random);
547 
548  for(int iatom=0;iatom<natoms;iatom++) for(int k=0;k<3;k++)
549  velocities[iatom][k]+=forces[iatom][k]*0.5*tstep/masses[iatom];
550 
551  for(int iatom=0;iatom<natoms;iatom++) for(int k=0;k<3;k++)
552  positions[iatom][k]+=velocities[iatom][k]*tstep;
553 
554 // a check is performed to decide whether to recalculate the neighbour list
555  check_list(natoms,positions,positions0,listcutoff,forcecutoff,recompute_list);
556  if(recompute_list){
557  compute_list(natoms,listsize,positions,cell,listcutoff,point,list);
558  for(int iatom=0;iatom<natoms;++iatom) for(int k=0;k<3;++k) positions0[iatom][k]=positions[iatom][k];
559  fprintf(out,"Neighbour list recomputed at step %d\n",istep);
560  fprintf(out,"List size: %d\n",point[natoms-1]);
561  }
562 
563  compute_forces(natoms,listsize,positions,cell,forcecutoff,point,list,forces,engconf);
564 
565  if(plumed){
566  int istepplusone=istep+1;
567  for(int i=0;i<3;i++)for(int k=0;k<3;k++) cell9[i][k]=0.0;
568  for(int i=0;i<3;i++) cell9[i][i]=cell[i];
569  plumed->cmd("setStep",&istepplusone);
570  plumed->cmd("setMasses",&masses[0]);
571  plumed->cmd("setForces",&forces[0]);
572  plumed->cmd("setEnergy",&engconf);
573  plumed->cmd("setPositions",&positions[0]);
574  plumed->cmd("setBox",cell9);
575  plumed->cmd("calc");
576  }
577 // remove forces if ndim<3
578  if(ndim<3)
579  for(int iatom=0;iatom<natoms;++iatom) for(int k=ndim;k<3;++k) forces[iatom][k]=0.0;
580 
581  for(int iatom=0;iatom<natoms;iatom++) for(int k=0;k<3;k++)
582  velocities[iatom][k]+=forces[iatom][k]*0.5*tstep/masses[iatom];
583 
584  thermostat(natoms,ndim,masses,0.5*tstep,friction,temperature,velocities,engint,random);
585 
586 // kinetic energy is calculated
587  compute_engkin(natoms,masses,velocities,engkin);
588 
589 // eventually, write positions and statistics
590  if((istep+1)%nconfig==0) write_positions(trajfile,natoms,positions,cell,wrapatoms);
591  if((istep+1)%nstat==0) write_statistics(statfile,istep+1,tstep,natoms,ndim,engkin,engconf,engint);
592 
593  }
594 
595 // write final positions
596  write_final_positions(outputfile,natoms,positions,cell,wrapatoms);
597 
598 // close the statistic file if it was open:
599  if(write_statistics_fp) fclose(write_statistics_fp);
600 
601  if(plumed) delete plumed;
602 
603  return 0;
604 }
605 
606 
607 };
608 
609 PLUMED_REGISTER_CLTOOL(SimpleMD,"simplemd")
610 
611 }
612 }
613 
614 
615 
616 
void cmd(const char *key, const void *val=NULL)
Send a command to this plumed object.
Definition: Plumed.h:455
void write_final_positions(const string &outputfile, int natoms, const vector< Vector > &positions, const double cell[3], const bool wrapatoms)
Definition: SimpleMD.cpp:365
void write_positions(const string &trajfile, int natoms, const vector< Vector > &positions, const double cell[3], const bool wrapatoms)
Definition: SimpleMD.cpp:341
void randomize_velocities(const int natoms, const int ndim, const double temperature, const vector< double > &masses, vector< Vector > &velocities, Random &random)
Definition: SimpleMD.cpp:220
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
void thermostat(const int natoms, const int ndim, const vector< double > &masses, const double dt, const double friction, const double temperature, vector< Vector > &velocities, double &engint, Random &random)
Definition: SimpleMD.cpp:324
int main(FILE *in, FILE *out, PLMD::Communicator &pc)
virtual function mapping to the specific main for each tool
Definition: SimpleMD.cpp:403
Class containing wrappers to MPI.
Definition: Communicator.h:44
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
void compute_list(const int natoms, const int listsize, const vector< Vector > &positions, const double cell[3], const double listcutoff, vector< int > &point, vector< int > &list)
Definition: SimpleMD.cpp:251
int write_statistics_last_time_reopened
Definition: SimpleMD.cpp:85
void read_input(double &temperature, double &tstep, double &friction, double &forcecutoff, double &listcutoff, int &nstep, int &nconfig, int &nstat, bool &wrapatoms, string &inputfile, string &outputfile, string &trajfile, string &statfile, int &maxneighbours, int &ndim, int &idum)
Definition: SimpleMD.cpp:120
This is the abstract base class to use for implementing new command line tool, within it there is inf...
Definition: CLTool.h:55
void setSeed(int idum)
Definition: Random.cpp:51
This class holds the keywords and their documentation.
Definition: Keywords.h:36
void read_positions(const string &inputfile, int natoms, vector< Vector > &positions, double cell[3])
Definition: SimpleMD.cpp:201
static void registerKeywords(Keywords &keys)
Definition: SimpleMD.cpp:90
SimpleMD(const CLToolOptions &co)
Definition: SimpleMD.cpp:107
C++ wrapper for plumed.
Definition: Plumed.h:314
void const char const char int double int double double int int double int double * w
Definition: Matrix.h:42
void pbc(const double cell[3], const Vector &vin, Vector &vout)
Definition: SimpleMD.cpp:226
void write_statistics(const string &statfile, const int istep, const double tstep, const int natoms, const int ndim, const double engkin, const double engconf, const double engint)
Definition: SimpleMD.cpp:384
void check_list(const int natoms, const vector< Vector > &positions, const vector< Vector > &positions0, const double listcutoff, const double forcecutoff, bool &recompute)
Definition: SimpleMD.cpp:233
Main plumed object.
Definition: Plumed.h:201
double Gaussian()
Definition: Random.cpp:140
string description() const
virtual function returning a one-line descriptor for the tool
Definition: SimpleMD.cpp:79
void compute_forces(const int natoms, const int listsize, const vector< Vector > &positions, const double cell[3], double forcecutoff, const vector< int > &point, const vector< int > &list, vector< Vector > &forces, double &engconf)
Definition: SimpleMD.cpp:279
void read_natoms(const string &inputfile, int &natoms)
Definition: SimpleMD.cpp:190
void compute_engkin(const int natoms, const vector< double > &masses, const vector< Vector > &velocities, double &engkin)
Definition: SimpleMD.cpp:314