00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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,
00044 this
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;
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;
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) {
00094 delete [] posbuf1;
00095 delete [] posbuf2;
00096 posbuf1 = new float[3*length];
00097 posbuf2 = new float[3*length];
00098 curbuf = posbuf1;
00099 curpos = posbuf2;
00100 }
00101 numcoords = length;
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
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 ) {
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
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
00156 if (need2flip) swap4_aligned(pos, 3*numcoords);
00157 }
00158
00159 void IMDSimThread::send_forces(int num, int *ind, float *forces) {
00160
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