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

IMDSimThread.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 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.18 $       $Date: 2019/01/17 21:20:59 $
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 extern "C" void * imdreaderthread(void *v) {
00031   IMDSimThread *st = (IMDSimThread *)v;
00032   return st->reader(v);
00033 }
00034 
00035 IMDSimThread::IMDSimThread(const char *host, int port) : IMDSim(host, port) { 
00036   curpos = curbuf = posbuf1 = posbuf2 = NULL; 
00037   time2die = 0;
00038 
00039   if (!isConnected())
00040     return;
00041 
00042   deadsocket = 0;
00043 
00044   wkf_mutex_init(&sockmutex);
00045   wkf_mutex_init(&coordmutex);
00046 
00047   if (wkf_thread_create(&readerthread,
00048                      imdreaderthread, // my thread routine
00049                      this             // context for thread
00050   )) {
00051     msgErr << "IMDSimThread: unable to create thread" << sendmsg;
00052   } else {
00053     msgInfo << "Using multithreaded IMD implementation." << sendmsg;
00054   }
00055 }
00056 
00057 IMDSimThread::~IMDSimThread() {
00058   time2die = 1;        // time2die is modified here only!!!
00059   void *status;
00060   
00061   if (isConnected()) {
00062     if (wkf_thread_join(readerthread, &status)) {
00063       msgErr << "IMDSimThread: unable to join thread" << sendmsg;
00064     }  
00065   }
00066   delete [] posbuf1;
00067   delete [] posbuf2;
00068   disconnect();
00069 }
00070 
00071 void *IMDSimThread::reader(void *) {
00072   IMDType type;
00073   int32 length;
00074   while (!deadsocket && !time2die) {
00075     if (!vmdsock_selread(sock, 0)) {
00076       vmd_msleep(1);
00077       continue;
00078     }
00079     type = imd_recv_header(sock, &length);
00080      
00081     switch (type) {
00082       case IMD_FCOORDS: process_coordinates(length); break;
00083       case IMD_ENERGIES: process_energies(length);   break; 
00084       case IMD_MDCOMM: process_mdcomm(length);       break;
00085       case IMD_IOERROR: deadsocket = 1;              break;
00086       default: break;  // Don't need to read data 
00087     }
00088   }
00089   wkf_mutex_lock(&sockmutex);
00090   disconnect();
00091   wkf_mutex_unlock(&sockmutex);
00092   return NULL;
00093 }
00094 
00095 void IMDSimThread::process_coordinates(int32 length) {
00096   if (numcoords < length) { // Need to resize
00097     delete [] posbuf1;
00098     delete [] posbuf2;
00099     posbuf1 = new float[3L*length];
00100     posbuf2 = new float[3L*length];
00101     curbuf = posbuf1;
00102     curpos = posbuf2;  // should I lock?
00103   }
00104   numcoords = length; // should I lock?
00105   
00106   int errcode = imd_recv_fcoords(sock, numcoords, curbuf);
00107   
00108   if (errcode) {
00109     msgErr << "Error reading remote coordinates!" << sendmsg;
00110     deadsocket = 1;
00111   } else {
00112     // swap the buffers and announce that new coordinates are ready
00113     wkf_mutex_lock(&coordmutex);
00114     float *tmp = curpos;
00115     curpos = curbuf;
00116     curbuf = tmp;
00117     new_coords_ready = 1;
00118     wkf_mutex_unlock(&coordmutex);
00119   }
00120 }
00121 
00122 void IMDSimThread::process_energies(int32 /* length */) {
00123   wkf_mutex_lock(&coordmutex);
00124 
00125   int errcode = imd_recv_energies(sock, &imdEnergies);
00126 
00127   if (errcode) { 
00128     msgErr << "Error reading energies!" << sendmsg;
00129     deadsocket = 1;
00130   } else {
00131     if (need2flip) swap4_aligned(&imdEnergies, sizeof(imdEnergies) / 4);
00132   }
00133 
00134   wkf_mutex_unlock(&coordmutex);
00135 }
00136 
00137 // This should never happen, but I'll handle it in case it does
00138 void IMDSimThread::process_mdcomm(int32 length) {
00139   int32 *ind = new int32[length];
00140   float *f = new float[3L*length];
00141   
00142   int errcode = imd_recv_mdcomm(sock, length, ind, f);
00143 
00144   if (errcode) {
00145     msgErr << "Error reading MDComm-style forces!" << sendmsg;
00146     deadsocket = 1;
00147   }
00148   delete [] ind;
00149   delete [] f;
00150 }
00151 
00152 void IMDSimThread::get_next_ts(float *pos, IMDEnergies *buf) {
00153   wkf_mutex_lock(&coordmutex);
00154   memcpy(pos, curpos, 3L*numcoords*sizeof(float));
00155   memcpy(buf, &imdEnergies, sizeof(IMDEnergies));
00156   new_coords_ready = 0;
00157   wkf_mutex_unlock(&coordmutex);
00158   // swap outside of the mutex - yeah baby!
00159   if (need2flip) swap4_aligned(pos, 3L*numcoords);
00160 }
00161 
00162 void IMDSimThread::send_forces(int num, int *ind, float *forces) {
00163   // Total data sent will be one int and three floats for each atom 
00164   if (need2flip) {
00165     swap4_aligned(ind, num);
00166     swap4_aligned(forces, 3L*num);
00167   }
00168 
00169   wkf_mutex_lock(&sockmutex);   
00170   if (isConnected()) {
00171     if (imd_send_mdcomm(sock, num, ind, forces)) {
00172       msgErr << "Error sending MDComm indices+forces" << sendmsg;
00173       deadsocket = 1;
00174     }
00175   }
00176   wkf_mutex_unlock(&sockmutex);   
00177 }
00178 
00179 void IMDSimThread::pause() {
00180   wkf_mutex_lock(&sockmutex);   
00181   if (isConnected() && (getSimState() == IMDRUNNING)) {
00182     simstate = IMDPAUSED;
00183     imd_pause(sock);
00184   }
00185   wkf_mutex_unlock(&sockmutex);   
00186 }
00187 
00188 void IMDSimThread::unpause() {
00189   wkf_mutex_lock(&sockmutex);   
00190   if (isConnected() && (getSimState() == IMDPAUSED)) {
00191     simstate = IMDRUNNING;
00192     imd_pause(sock);
00193   }
00194   wkf_mutex_unlock(&sockmutex);
00195 }
00196 
00197 void IMDSimThread::detach() {
00198   wkf_mutex_lock(&sockmutex);   
00199   if (isConnected()) {
00200     simstate = IMDOFFLINE;
00201     imd_disconnect(sock);
00202     deadsocket = 1;
00203   }
00204   wkf_mutex_unlock(&sockmutex);   
00205 }
00206 
00207 void IMDSimThread::kill() {
00208   wkf_mutex_lock(&sockmutex);   
00209   if (isConnected()) {
00210     simstate = IMDOFFLINE;
00211     imd_kill(sock);
00212     deadsocket = 1;
00213   }
00214   wkf_mutex_unlock(&sockmutex);   
00215 }
00216 
00217 void IMDSimThread::set_transrate(int rate) {
00218   wkf_mutex_lock(&sockmutex);   
00219   if (isConnected()) {
00220     imd_trate(sock, rate);
00221   }
00222   wkf_mutex_unlock(&sockmutex);   
00223 }
00224 

Generated on Thu Apr 25 02:42:43 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002