All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ActionIMD.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 "../core/ActionRegister.h"
23 #include "../core/ActionAtomistic.h"
24 #include "../core/ActionPilot.h"
25 #include "../core/PlumedMain.h"
26 #include "../core/Atoms.h"
27 #include "../tools/Exception.h"
28 #include <unistd.h>
29 
30 extern "C" {
31 #include "vmdsock.h"
32 #include "imd.h"
33 }
34 
35 
36 namespace PLMD {
37 
38 //+PLUMEDOC GENERIC IMD
39 /*
40 Use interactive molecular dynamics with VMD
41 
42 \par Examples
43 
44 \verbatim
45 # listen to port 1112 of localhost
46 IMD PORT=1112
47 \endverbatim
48 \verbatim
49 # listen to port 1112 of pippo
50 IMD HOST=pippo PORT=1112
51 \endverbatim
52 \verbatim
53 # listen to port 1112 of localhost and run only when connected
54 IMD PORT=1112 WAIT
55 \endverbatim
56 
57 \attention
58 The IMB object only works if the IMD routines have been downloaded
59 and properly linked with PLUMED
60 
61 */
62 //+ENDPLUMEDOC
63 
64 class IMD :
65  public ActionAtomistic,
66  public ActionPilot
67  {
68  std::string host;
69  int port;
70  bool wait;
71  bool wrap;
72  void* sock;
73  void* clientsock;
74  bool connected;
75  std::vector<float> coord;
76  std::vector<double> forces;
77  int natoms;
79  double fscale;
80  void connect();
81  void receive();
82  void sendCoordinates();
83 public:
84  static void registerKeywords( Keywords& keys );
85  void calculate();
86  void apply();
87  IMD(const ActionOptions&);
88  ~IMD(){};
89 };
90 
91 PLUMED_REGISTER_ACTION(IMD,"IMD")
92 
93 void IMD::registerKeywords( Keywords& keys ){
94  keys.addFlag("WAIT",false,"");
95  keys.addFlag("NOWAIT",true,"");
96  keys.addFlag("WRAP",false,"");
97  keys.add("compulsory","HOST","");
98  keys.add("compulsory","PORT","");
99  keys.add("compulsory","FSCALE","1.0","");
100 }
101 
103  Action(ao),
104  ActionAtomistic(ao),
105  ActionPilot(ao),
106  host("localhost"),
107  port(0),
108  wait(false),
109  wrap(false),
110  sock(NULL),
111  clientsock(NULL),
112  connected(false),
113  transferRate(100),
114  fscale(1.0)
115 {
116  natoms=plumed.getAtoms().getNatoms();
117 
118  std::vector<AtomNumber> index(natoms);
119  for(int i=0;i<natoms;i++) index[i].setIndex(i);
120  requestAtoms(index);
121  coord.resize(natoms*3,float(0.0));
122  forces.resize(natoms*3,0.0);
123 
124  parseFlag("WAIT",wait);
125  bool nowait=false;
126  parseFlag("NOWAIT",nowait);
127  if(nowait)wait=false;
128  parseFlag("WRAP",wrap);
129  parse("PORT",port);
130  parse("HOST",host);
131  parse("FSCALE",fscale);
132 
133  checkRead();
134 
135  log.printf(" with host %s\n",host.c_str());
136  log.printf(" with port %d\n",port);
137  if(wait) log.printf(" waiting for a connection\n");
138  else log.printf(" not waiting for a connection\n");
139  if(wrap) log.printf(" wrapping atoms\n");
140  else log.printf(" not wrapping atoms\n");
141  log.printf(" WMD forces will be scaled by %f\n",fscale);
142 
143  if(comm.Get_rank()==0){
144  vmdsock_init();
145  sock = vmdsock_create();
146  vmdsock_bind(sock, port);
147  vmdsock_listen(sock);
148  }
149 
150  connect();
151 }
152 
154  if(comm.Get_rank()==0) {
155  if(wait && clientsock==NULL)
156  fprintf(stderr,"Waiting for IMD connection on %s:%d...\n", host.c_str(), port);
157  do{
158  if (vmdsock_selread(sock,00) > 0) {
159  clientsock = vmdsock_accept(sock);
160  if (imd_handshake(clientsock)) {
161  clientsock = NULL;
162  };
163  sleep(1);
164  int length;
165  if(clientsock){
166  if (vmdsock_selread(clientsock, 0) != 1 ||
167  imd_recv_header(clientsock, &length) != IMD_GO) {
168  clientsock = NULL;
169  }
170  }
171  }
172  } while(wait && clientsock==NULL);
173  connected=(clientsock!=NULL);
174  int c=connected;
175  comm.Bcast(&c,1,0);
176  } else {
177  int c;
178  comm.Bcast(&c,1,0);
179  connected=c;
180  }
181 }
182 
184 
185  if(!connected) return;
186 
187  if(clientsock){
188  IMDType type;
189  int length;
190  int itype;
191  while (vmdsock_selread(clientsock,0) > 0) {
192  type = imd_recv_header(clientsock, &length);
193  if(type==IMD_MDCOMM){
194  int32* vmd_atoms = new int32[length];
195  float* vmd_forces = new float[3*length];
196  imd_recv_mdcomm(clientsock, length, vmd_atoms, vmd_forces);
197  for(int i=0;i<length;i++){
198  forces[3*vmd_atoms[i]+0]=vmd_forces[3*i+0];
199  forces[3*vmd_atoms[i]+1]=vmd_forces[3*i+1];
200  forces[3*vmd_atoms[i]+2]=vmd_forces[3*i+2];
201  }
202  delete [] vmd_atoms;
203  delete [] vmd_forces;
204  itype=0;
205  comm.Bcast(&itype,1,0);
206  comm.Bcast(&forces[0],forces.size(),0);
207  }else if(type==IMD_DISCONNECT){
208  vmdsock_destroy(clientsock);
209  clientsock=NULL;
210  for(unsigned i=0;i<forces.size();i++) forces[i]=0.0;
211  connected=false;
212  itype=1;
213  comm.Bcast(&itype,1,0);
214  break;
215  }else if(type==IMD_TRATE){
216  if(length<1) length=1;
217  itype=2;
218  log.printf("IMD: setting transfer rate to %d\n",length);
219  transferRate=length;
220  comm.Bcast(&itype,1,0);
221  comm.Bcast(&transferRate,1,0);
222  }else if(type==IMD_KILL){
223  log.printf("IMD: killing simulation\n");
224  itype=3;
225  comm.Bcast(&itype,1,0);
226  plumed.exit();
227  }
228  }
229  itype=-1;
230  comm.Bcast(&itype,1,0);
231  }
232 
233  if(comm.Get_rank()!=0){
234  int itype;
235  while(true){
236  comm.Bcast(&itype,1,0);
237  if(itype==-1)break;
238  else if(itype==0) comm.Bcast(&forces[0],forces.size(),0);
239  else if(itype==1) {
240  for(unsigned i=0;i<forces.size();i++) forces[i]=0.0;
241  connected=false;
242  }
243  else if(itype==2) comm.Bcast(&transferRate,1,0);
244  else if(itype==3) plumed.exit();
245  else plumed_error();
246  }
247  }
248 
249 }
250 
252  if(comm.Get_rank()==0 && connected && plumed.getStep()%transferRate==0 && vmdsock_selwrite(clientsock,0)) {
253  double scale=10.0*plumed.getAtoms().getUnits().getLength();
254  Vector ref;
255  for(int i=0;i<natoms;i++){
256  Vector pos=getPosition(i);
257  if(wrap) pos=pbcDistance(ref,pos);
258  coord[3*i+0]=static_cast<float>((pos[0]*scale));
259  coord[3*i+1]=static_cast<float>((pos[1]*scale));
260  coord[3*i+2]=static_cast<float>((pos[2]*scale));
261  }
262  imd_send_fcoords(clientsock,natoms,&coord[0]);
263  }
264 }
265 
266 void IMD::apply(){
267 
268  std::vector<Vector> & f(modifyForces());
269 
270  const double scale=4.184/plumed.getAtoms().getUnits().getEnergy()
271  /(0.1/plumed.getAtoms().getUnits().getLength())*fscale;
272 
273  for(unsigned i=0;i<f.size();i++){
274  f[i][0]=forces[3*i+0]*getStride()*scale;
275  f[i][1]=forces[3*i+1]*getStride()*scale;
276  f[i][2]=forces[3*i+2]*getStride()*scale;
277  }
278 
279  connect();
280  receive();
281 
282 }
283 
284 
285 }
286 
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
Log & log
Reference to the log stream.
Definition: Action.h:93
std::vector< float > coord
Definition: ActionIMD.cpp:75
This is used to create PLMD::Action objects that are run with some set frequency. ...
Definition: ActionPilot.h:39
void calculate()
Calculate an Action.
Definition: ActionIMD.cpp:251
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
IMD(const ActionOptions &)
Definition: ActionIMD.cpp:102
void Bcast(T *, int, int)
Definition: Communicator.h:134
void apply()
Apply an Action.
Definition: ActionIMD.cpp:266
void checkRead()
Check if Action was properly read.
Definition: Action.cpp:161
Communicator & comm
Definition: Action.h:158
bool wrap
Definition: ActionIMD.cpp:71
Provides the keyword IMD
Definition: ActionIMD.cpp:64
int getStride() const
Definition: ActionPilot.cpp:42
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
std::vector< double > forces
Definition: ActionIMD.cpp:76
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
Action used to create objects that access the positions of the atoms from the MD code.
int natoms
Definition: ActionIMD.cpp:77
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
void * clientsock
Definition: ActionIMD.cpp:73
Base class for all the input Actions.
Definition: Action.h:60
void * sock
Definition: ActionIMD.cpp:72
void connect()
Definition: ActionIMD.cpp:153
bool connected
Definition: ActionIMD.cpp:74
bool wait
Definition: ActionIMD.cpp:70
void sendCoordinates()
void receive()
Definition: ActionIMD.cpp:183
Vector pbcDistance(const Vector &, const Vector &) const
Compute the pbc distance between two positions.
int transferRate
Definition: ActionIMD.cpp:78
static void registerKeywords(Keywords &keys)
Definition: ActionIMD.cpp:93
void requestAtoms(const std::vector< AtomNumber > &a)
Request an array of atoms.
Main plumed object.
Definition: Plumed.h:201
std::vector< Vector > & modifyForces()
Get a reference to forces array.
double fscale
Definition: ActionIMD.cpp:79
std::string host
Definition: ActionIMD.cpp:68