00001
00007 #include "InfoStream.h"
00008 #include "vmdsock.h"
00009 #include "Node.h"
00010 #include "IMDOutput.h"
00011 #include "imd.h"
00012 #include "SimParameters.h"
00013 #include "UniqueSortedArray.h"
00014 #include "GlobalMaster.h"
00015 #include "GlobalMasterIMD.h"
00016 #include "Vector.h"
00017
00018 #include <errno.h>
00019
00020
00021 #define MIN_DEBUG_LEVEL 1
00022 #include "Debug.h"
00023
00024 struct vmdforce {
00025 int index;
00026 Vector force;
00027 int operator <(const vmdforce& v) {return index < v.index;}
00028
00029 int operator ==(const vmdforce& v) {return index == v.index;}
00030 vmdforce& operator=(const vmdforce& v) {
00031 index=v.index;
00032 force=v.force;
00033 return *this;
00034 }
00035 };
00036
00037
00038
00039
00040
00041 static UniqueSortedArray<vmdforce> vmdforces;
00042
00043
00044
00045
00046 static int find_free_port(void *sock, int defport) {
00047 if (vmdsock_bind(sock, defport)==0) return defport;
00048 for (int port=1025; port < 4096; port++)
00049 if (vmdsock_bind(sock, port)==0) return port;
00050 return -1;
00051 }
00052
00053 GlobalMasterIMD::GlobalMasterIMD() {
00054 DebugM(3,"Constructing\n");
00055 SimParameters *simparams = Node::Object()->simParameters;
00056 int port = simparams->IMDport;
00057 IMDwait = simparams->IMDwait;
00058 IMDignore = simparams->IMDignore;
00059 coordtmp = NULL;
00060 coordtmpsize = 0;
00061
00062 if ( vmdsock_init() ) {
00063 NAMD_die("Unable to initialize socket interface for IMD.\n");
00064 }
00065 sock = vmdsock_create();
00066 int newport = find_free_port(sock, port);
00067 if (newport != port) {
00068 iout << iWARN << "Interactive MD failed to bind to port "
00069 << port << ".\n" << endi;
00070 }
00071 if (newport < 0) {
00072 vmdsock_destroy(sock);
00073 NAMD_die("Interactive MD failed to find free port.\n");
00074 }
00075 vmdsock_listen(sock);
00076 iout << iINFO << "Interactive MD listening on port "
00077 << newport << ".\n" << endi;
00078 DebugM(2,"Done constructing ("<<requestedGroups().size()<<" initial groups)\n");
00079
00080 Node::Object()->imd->use_imd(this);
00081 }
00082
00083 GlobalMasterIMD::~GlobalMasterIMD() {
00084 if (sock)
00085 vmdsock_destroy(sock);
00086 for (int i=0; i<clients.size(); i++)
00087 vmdsock_destroy(clients[i]);
00088 delete [] coordtmp;
00089 }
00090
00091 static int my_imd_connect(void *s) {
00092 if (imd_handshake(s)) {
00093 iout << iWARN << "IMD handshake failed\n" << endi;
00094 return 0;
00095 }
00096
00097
00098 int32 length;
00099 if (vmdsock_selread(s,1) != 1 || imd_recv_header(s, &length) != IMD_GO) {
00100 iout << iWARN << "Incompatible Interactive MD, use VMD v1.4b2 or higher\n"
00101 << endi;
00102 return 0;
00103 }
00104 return 1;
00105 }
00106
00107 void GlobalMasterIMD::calculate() {
00108
00109 if (!IMDignore) {
00110 modifyAppliedForces().resize(0);
00111 modifyForcedAtoms().resize(0);
00112 modifyGroupForces().resize(0);
00113 }
00114
00115
00116 do {
00117 int rc;
00118 if (IMDwait && !clients.size()) {
00119 iout << iINFO << "INTERACTIVE MD AWAITING CONNECTION\n" << endi;
00120 do { rc = vmdsock_selread(sock, 3600); } while (rc <= 0);
00121 } else {
00122 rc = vmdsock_selread(sock, 0);
00123 }
00124 if (rc > 0) {
00125 void *clientsock = vmdsock_accept(sock);
00126 if (!clientsock) {
00127 iout << iWARN << "IMD socket accept failed\n" << endi;
00128 } else {
00129 if (!my_imd_connect(clientsock)) {
00130 iout << iWARN << "IMD connection failed\n" << endi;
00131 vmdsock_destroy(clientsock);
00132 } else {
00133 iout << iINFO << "IMD connection opened\n" <<endi;
00134 clients.add(clientsock);
00135 }
00136 }
00137 }
00138 } while (IMDwait && !clients.size());
00139
00140
00141
00142
00143
00144
00145 get_vmd_forces();
00146
00147
00148
00149
00150
00151
00152
00153 int num = vmdforces.size();
00154
00155 DebugM(2,"Setting " << num << " forces.\n");
00156
00157 if (!IMDignore) {
00158 modifyForcedAtoms().resize(num);
00159 modifyAppliedForces().resize(num);
00160
00161 int i;
00162 UniqueSortedArray<vmdforce>::iterator v_i = vmdforces.begin();
00163 for ( i = 0; i < num; ++i, ++v_i) {
00164 modifyForcedAtoms().item(i) = v_i->index;
00165 modifyAppliedForces().item(i) = v_i->force;
00166 }
00167 }
00168 }
00169
00170 void GlobalMasterIMD::get_vmd_forces() {
00171 IMDType type;
00172 int32 length;
00173 int32 *vmd_atoms;
00174 float *vmd_forces;
00175 int paused = 0;
00176 int warned = 0;
00177 vmdforce *vtest, vnew;
00178
00179
00180
00181
00182
00183
00184
00185
00186 for (int i_client=0; i_client<clients.size(); i_client++) {
00187 void *clientsock = clients[i_client];
00188 while (vmdsock_selread(clientsock,0) > 0 || paused) {
00189 type = imd_recv_header(clientsock, &length);
00190 switch (type) {
00191 case IMD_MDCOMM:
00192
00193
00194
00195 vmd_atoms = new int32[length];
00196 vmd_forces = new float[3*length];
00197 if (imd_recv_mdcomm(clientsock, length, vmd_atoms, vmd_forces)) {
00198 iout << iWARN <<
00199 "Error reading IMD forces, killing connection\n" << endi;
00200 goto vmdDestroySocket;
00201 }
00202 if (IMDignore) {
00203 if ( ! warned ) {
00204 warned = 1;
00205 iout << iWARN << "Ignoring IMD forces due to IMDignore\n" << endi;
00206 }
00207 } else {
00208 for (int i=0; i<length; i++) {
00209 vnew.index = vmd_atoms[i];
00210 if ( (vtest=vmdforces.find(vnew)) != NULL) {
00211
00212 if (vmd_forces[3*i] != 0.0f || vmd_forces[3*i+1] != 0.0f
00213 || vmd_forces[3*i+2] != 0.0f) {
00214 vtest->force.x = vmd_forces[3*i];
00215 vtest->force.y = vmd_forces[3*i+1];
00216 vtest->force.z = vmd_forces[3*i+2];
00217 } else {
00218
00219 vmdforces.del(vnew);
00220 }
00221 }
00222 else {
00223
00224 if (vmd_forces[3*i] != 0.0f || vmd_forces[3*i+1] != 0.0f
00225 || vmd_forces[3*i+2] != 0.0f) {
00226 vnew.force.x = vmd_forces[3*i];
00227 vnew.force.y = vmd_forces[3*i+1];
00228 vnew.force.z = vmd_forces[3*i+2];
00229 vmdforces.add(vnew);
00230 }
00231 }
00232 }
00233 }
00234 delete [] vmd_atoms;
00235 delete [] vmd_forces;
00236 break;
00237 case IMD_TRATE:
00238 iout << iINFO << "Setting transfer rate to " << length<<'\n'<<endi;
00239 Node::Object()->imd->set_transrate(length);
00240 break;
00241 case IMD_PAUSE:
00242 if (IMDignore) {
00243 iout << iWARN << "Ignoring IMD pause due to IMDignore\n" << endi;
00244 break;
00245 }
00246 if ( paused ) {
00247 iout << iINFO << "Resuming IMD\n" << endi;
00248 IMDwait = Node::Object()->simParameters->IMDwait;
00249 }
00250 paused = ! paused;
00251 if ( paused ) {
00252 iout << iINFO << "Pausing IMD\n" << endi;
00253 IMDwait = 1;
00254 }
00255 break;
00256 case IMD_IOERROR:
00257 iout << iWARN << "IMD connection lost\n" << endi;
00258 case IMD_DISCONNECT:
00259 iout << iINFO << "IMD connection detached\n" << endi;
00260 vmdDestroySocket:
00261 vmdsock_destroy(clientsock);
00262 clients.del(i_client);
00263 goto vmdEnd;
00264 case IMD_KILL:
00265 if (IMDignore) {
00266 iout << iWARN << "Ignoring IMD kill due to IMDignore\n" << endi;
00267 break;
00268 }
00269 NAMD_quit("Received IMD kill from client\n");
00270 break;
00271 case IMD_ENERGIES:
00272 IMDEnergies junk;
00273 imd_recv_energies(clientsock, &junk);
00274 break;
00275 case IMD_FCOORDS:
00276 vmd_forces = new float[3*length];
00277 imd_recv_fcoords(clientsock, length, vmd_forces);
00278 delete [] vmd_forces;
00279 break;
00280 default: ;
00281 }
00282 }
00283 vmdEnd: ;
00284 }
00285 }
00286
00287 void GlobalMasterIMD::send_energies(IMDEnergies *energies) {
00288 for (int i=0; i<clients.size(); i++) {
00289 void *clientsock = clients[i];
00290 if (!clientsock || !vmdsock_selwrite(clientsock,0)) continue;
00291 imd_send_energies(clientsock, energies);
00292 }
00293 }
00294
00295 void GlobalMasterIMD::send_fcoords(int N, FloatVector *coords) {
00296 for (int i=0; i<clients.size(); i++) {
00297 void *clientsock = clients[i];
00298 if (!clientsock || !vmdsock_selwrite(clientsock,0)) continue;
00299 if (sizeof(FloatVector) == 3*sizeof(float)) {
00300 imd_send_fcoords(clientsock, N, (float *)coords);
00301 } else {
00302 if (coordtmpsize < N) {
00303 delete [] coordtmp;
00304 coordtmp = new float[3*N];
00305 coordtmpsize = N;
00306 }
00307 for (int i=0; i<N; i++) {
00308 coordtmp[3*i] = coords[i].x;
00309 coordtmp[3*i+1] = coords[i].y;
00310 coordtmp[3*i+2] = coords[i].z;
00311 }
00312 imd_send_fcoords(clientsock, N, coordtmp);
00313 }
00314 }
00315 }