Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

IMDSimThread.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2008 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: IMDSimThread.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.11 $       $Date: 2008/03/27 19:36:40 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  A multithreaded implementation of the interactive MD 
00019  *  coordinate/force communication update loop.
00020  ***************************************************************************/
00021 
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include "vmdsock.h"
00025 #include "IMDMgr.h"
00026 #include "IMDSimThread.h"
00027 #include "Inform.h"
00028 #include "utilities.h"
00029 
00030 IMDSimThread::IMDSimThread(const char *host, int port) : IMDSim(host, port) { 
00031   curpos = curbuf = posbuf1 = posbuf2 = NULL; 
00032   time2die = 0;
00033 
00034   if (!isConnected())
00035     return;
00036 
00037   deadsocket = 0;
00038 
00039   vmd_mutex_init(&sockmutex);
00040   vmd_mutex_init(&coordmutex);
00041 
00042   if (vmd_thread_create(&readerthread,
00043                      reader,        // my thread routine
00044                      this           // context for thread
00045   )) {
00046     msgErr << "IMDSimThread: unable to create thread" << sendmsg;
00047   } else {
00048     msgInfo << "Using multithreaded IMD implementation." << sendmsg;
00049   }
00050 }
00051 
00052 IMDSimThread::~IMDSimThread() {
00053   time2die = 1;        // time2die is modified here only!!!
00054   void *status;
00055   
00056   if (isConnected()) {
00057     if (vmd_thread_join(readerthread, &status)) {
00058       msgErr << "IMDSimThread: unable to join thread" << sendmsg;
00059     }  
00060   }
00061   delete [] posbuf1;
00062   delete [] posbuf2;
00063   disconnect();
00064 }
00065 
00066 void *IMDSimThread::reader(void *v) {
00067   IMDSimThread *self = (IMDSimThread *)v;
00068   
00069   IMDType type;
00070   int32 length;
00071   while (!self->deadsocket && !self->time2die) {
00072     if (!vmdsock_selread(self->sock,0)) {
00073       vmd_msleep(1);
00074       continue;
00075     }
00076     type = imd_recv_header(self->sock, &length);
00077      
00078     switch (type) {
00079       case IMD_FCOORDS: self->process_coordinates(length); break;
00080       case IMD_ENERGIES: self->process_energies(length);   break; 
00081       case IMD_MDCOMM: self->process_mdcomm(length);       break;
00082       case IMD_IOERROR: self->deadsocket = 1; break;
00083       default: break;  // Don't need to read data 
00084     }
00085   }
00086   vmd_mutex_lock(&self->sockmutex);
00087   self->disconnect();
00088   vmd_mutex_unlock(&self->sockmutex);
00089   return NULL;
00090 }
00091 
00092 void IMDSimThread::process_coordinates(int32 length) {
00093   if (numcoords < length) { // Need to resize
00094     delete [] posbuf1;
00095     delete [] posbuf2;
00096     posbuf1 = new float[3*length];
00097     posbuf2 = new float[3*length];
00098     curbuf = posbuf1;
00099     curpos = posbuf2;  // should I lock?
00100   }
00101   numcoords = length; // should I lock?
00102   
00103   int errcode = imd_recv_fcoords(sock, numcoords, curbuf);
00104   
00105   if (errcode) {
00106     msgErr << "Error reading remote coordinates!" << sendmsg;
00107     deadsocket = 1;
00108   } else {
00109     // swap the buffers and announce that new coordinates are ready
00110     vmd_mutex_lock(&coordmutex);
00111     float *tmp = curpos;
00112     curpos = curbuf;
00113     curbuf = tmp;
00114     new_coords_ready = 1;
00115     vmd_mutex_unlock(&coordmutex);
00116   }
00117 }
00118 
00119 void IMDSimThread::process_energies(int32 /* length */) {
00120   vmd_mutex_lock(&coordmutex);
00121 
00122   int errcode = imd_recv_energies(sock, &imdEnergies);
00123 
00124   if (errcode) { 
00125     msgErr << "Error reading energies!" << sendmsg;
00126     deadsocket = 1;
00127   } else {
00128     if (need2flip) swap4_aligned(&imdEnergies, sizeof(imdEnergies) / 4);
00129   }
00130 
00131   vmd_mutex_unlock(&coordmutex);
00132 }
00133 
00134 // This should never happen, but I'll handle it in case it does
00135 void IMDSimThread::process_mdcomm(int32 length) {
00136   int32 *ind = new int32[length];
00137   float *f = new float[3*length];
00138   
00139   int errcode = imd_recv_mdcomm(sock, length, ind, f);
00140 
00141   if (errcode) {
00142     msgErr << "Error reading MDComm-style forces!" << sendmsg;
00143     deadsocket = 1;
00144   }
00145   delete [] ind;
00146   delete [] f;
00147 }
00148 
00149 void IMDSimThread::get_next_ts(float *pos, IMDEnergies *buf) {
00150   vmd_mutex_lock(&coordmutex);
00151   memcpy(pos, curpos, 3*numcoords*sizeof(float));
00152   memcpy(buf, &imdEnergies, sizeof(IMDEnergies));
00153   new_coords_ready = 0;
00154   vmd_mutex_unlock(&coordmutex);
00155   // swap outside of the mutex - yeah baby!
00156   if (need2flip) swap4_aligned(pos, 3*numcoords);
00157 }
00158 
00159 void IMDSimThread::send_forces(int num, int *ind, float *forces) {
00160   // Total data sent will be one int and three floats for each atom 
00161   if (need2flip) {
00162     swap4_aligned(ind, num);
00163     swap4_aligned(forces, 3*num);
00164   }
00165 
00166   vmd_mutex_lock(&sockmutex);   
00167   if (isConnected()) {
00168     if (imd_send_mdcomm(sock, num, ind, forces)) {
00169       msgErr << "Error sending MDComm indices+forces" << sendmsg;
00170       deadsocket = 1;
00171     }
00172   }
00173   vmd_mutex_unlock(&sockmutex);   
00174 }
00175 
00176 void IMDSimThread::pause() {
00177   vmd_mutex_lock(&sockmutex);   
00178   if (isConnected() && (getSimState() == IMDRUNNING)) {
00179     simstate = IMDPAUSED;
00180     imd_pause(sock);
00181   }
00182   vmd_mutex_unlock(&sockmutex);   
00183 }
00184 
00185 void IMDSimThread::unpause() {
00186   vmd_mutex_lock(&sockmutex);   
00187   if (isConnected() && (getSimState() == IMDPAUSED)) {
00188     simstate = IMDRUNNING;
00189     imd_pause(sock);
00190   }
00191   vmd_mutex_unlock(&sockmutex);
00192 }
00193 
00194 void IMDSimThread::detach() {
00195   vmd_mutex_lock(&sockmutex);   
00196   if (isConnected()) {
00197     simstate = IMDOFFLINE;
00198     imd_disconnect(sock);
00199     deadsocket = 1;
00200   }
00201   vmd_mutex_unlock(&sockmutex);   
00202 }
00203 
00204 void IMDSimThread::kill() {
00205   vmd_mutex_lock(&sockmutex);   
00206   if (isConnected()) {
00207     simstate = IMDOFFLINE;
00208     imd_kill(sock);
00209     deadsocket = 1;
00210   }
00211   vmd_mutex_unlock(&sockmutex);   
00212 }
00213 
00214 void IMDSimThread::set_transrate(int rate) {
00215   vmd_mutex_lock(&sockmutex);   
00216   if (isConnected()) {
00217     imd_trate(sock, rate);
00218   }
00219   vmd_mutex_unlock(&sockmutex);   
00220 }
00221 

Generated on Sat Sep 6 01:26:52 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002