Skip to content
This repository has been archived by the owner on Oct 9, 2024. It is now read-only.

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ljwoods2 committed Apr 19, 2024
1 parent 82ef7df commit 7a44b30
Show file tree
Hide file tree
Showing 13 changed files with 909 additions and 0 deletions.
3 changes: 3 additions & 0 deletions devtools/conda-envs/test_env.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ dependencies:
# MDAnalysis
- MDAnalysis

# C API
- cython

# Testing
- pytest
- pytest-cov
Expand Down
13 changes: 13 additions & 0 deletions imdapi/imdapi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
##
## Makefile for Simple Interactive MD interface example program
##

CC = cc
CXX = CC

testimd : testimd.c vmdsock.c imd.h imd.c
$(CC) $(CFLAGS) testimd.c vmdsock.c imd.c -o testimd -lnsl -lsocket
@echo "See the README file for info on running this test code..."

clean :
rm -f *.o testimd
24 changes: 24 additions & 0 deletions imdapi/imdapi/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
IMD API example code
--------------------
This is a simple example program that demonstrates how to write the
simulation engine side of an interactive molecular dynamics system using
the IMD interface in VMD. In order to test it out, follow theses steps:
1) Compile the code with the "make" command, edit the compile line
as needed. (some platforms don't need -lnsl or -lsocket...)

2) Once compiled, run the newly compiled "testimd" program

3) Start VMD, and load the "testimd.pdb" molecule, set the
graphical representation to "VDW" so you can see the simulated
atom.

4) While the "testimd" binary is running, and the "testimd.pdb" is loaded
into VMD, type the following command into your VMD text console to
cause VMD to connect to the test simulation:
imd connect localhost 54321

5) Go ahead and play around.

6) quit VMD, or type "imd detach" to disconnect from the test program.


237 changes: 237 additions & 0 deletions imdapi/imdapi/imd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@


#include "imd.h"
#include "vmdsock.h"
#include <string.h>
#include <errno.h>
#include <stdlib.h>

typedef struct {
int32 type;
int32 length;
} IMDheader;

#define HEADERSIZE 8
#define IMDVERSION 2

static void swap4(char *data, int ndata) {
int i;
char *dataptr;
char b0, b1;

dataptr = data;
for (i=0; i<ndata; i+=4) {
b0 = dataptr[0];
b1 = dataptr[1];
dataptr[0] = dataptr[3];
dataptr[1] = dataptr[2];
dataptr[2] = b1;
dataptr[3] = b0;
dataptr += 4;
}
}

static int32 imd_htonl(int32 h) {
int32 n;
((char *)&n)[0] = (h >> 24) & 0x0FF;
((char *)&n)[1] = (h >> 16) & 0x0FF;
((char *)&n)[2] = (h >> 8) & 0x0FF;
((char *)&n)[3] = h & 0x0FF;
return n;
}

typedef struct {
unsigned int highest : 8;
unsigned int high : 8;
unsigned int low : 8;
unsigned int lowest : 8;
} netint;

static int32 imd_ntohl(int32 n) {
int32 h = 0;
netint net;
net = *((netint *)&n);
h |= net.highest << 24 | net.high << 16 | net.low << 8 | net.lowest;
return h;
}

static void fill_header(IMDheader *header, IMDType type, int32 length) {
header->type = imd_htonl((int32)type);
header->length = imd_htonl(length);
}

static void swap_header(IMDheader *header) {
header->type = imd_ntohl(header->type);
header->length= imd_ntohl(header->length);
}

static int32 imd_readn(void *s, char *ptr, int32 n) {
int32 nleft;
int32 nread;

nleft = n;
while (nleft > 0) {
if ((nread = vmdsock_read(s, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0; /* and call read() again */
else
return -1;
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return n-nleft;
}

static int32 imd_writen(void *s, const char *ptr, int32 n) {
int32 nleft;
int32 nwritten;

nleft = n;
while (nleft > 0) {
if ((nwritten = vmdsock_write(s, ptr, nleft)) <= 0) {
if (errno == EINTR)
nwritten = 0;
else
return -1;
}
nleft -= nwritten;
ptr += nwritten;
}
return n;
}


int imd_disconnect(void *s) {
IMDheader header;
fill_header(&header, IMD_DISCONNECT, 0);
return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
}

int imd_pause(void *s) {
IMDheader header;
fill_header(&header, IMD_PAUSE, 0);
return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
}

int imd_kill(void *s) {
IMDheader header;
fill_header(&header, IMD_KILL, 0);
return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
}

static int imd_go(void *s) {
IMDheader header;
fill_header(&header, IMD_GO, 0);
return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
}


int imd_handshake(void *s) {
IMDheader header;
fill_header(&header, IMD_HANDSHAKE, 1);
header.length = IMDVERSION; /* Not byteswapped! */
return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
}

int imd_trate(void *s, int32 rate) {
IMDheader header;
fill_header(&header, IMD_TRATE, rate);
return (imd_writen(s, (char *)&header, HEADERSIZE) != HEADERSIZE);
}

/* Data methods */
int imd_send_mdcomm(void *s,int32 n,const int32 *indices,const float *forces) {
int rc;
int32 size = HEADERSIZE+16*n;
char *buf = (char *) malloc(sizeof(char) * size);
fill_header((IMDheader *)buf, IMD_MDCOMM, n);
memcpy(buf+HEADERSIZE, indices, 4*n);
memcpy(buf+HEADERSIZE+4*n, forces, 12*n);
rc = (imd_writen(s, buf, size) != size);
free(buf);
return rc;
}

int imd_send_energies(void *s, const IMDEnergies *energies) {
int rc;
int32 size = HEADERSIZE+sizeof(IMDEnergies);
char *buf = (char *) malloc(sizeof(char) * size);
fill_header((IMDheader *)buf, IMD_ENERGIES, 1);
memcpy(buf+HEADERSIZE, energies, sizeof(IMDEnergies));
rc = (imd_writen(s, buf, size) != size);
free(buf);
return rc;
}

int imd_send_fcoords(void *s, int32 n, const float *coords) {
int rc;
int32 size = HEADERSIZE+12*n;
char *buf = (char *) malloc(sizeof(char) * size);
fill_header((IMDheader *)buf, IMD_FCOORDS, n);
memcpy(buf+HEADERSIZE, coords, 12*n);
rc = (imd_writen(s, buf, size) != size);
free(buf);
return rc;
}

/* The IMD receive functions */
IMDType imd_recv_header_nolengthswap(void *s, int32 *length) {
IMDheader header;
if (imd_readn(s, (char *)&header, HEADERSIZE) != HEADERSIZE)
return IMD_IOERROR;
*length = header.length;
swap_header(&header);
return (IMDType) header.type;
}

IMDType imd_recv_header(void *s, int32 *length) {
IMDheader header;
if (imd_readn(s, (char *)&header, HEADERSIZE) != HEADERSIZE)
return IMD_IOERROR;
swap_header(&header);
*length = header.length;
return (IMDType) header.type;
}

int imd_recv_handshake(void *s) {
int32 buf;
IMDType type;

/* Wait up to 5 seconds for the handshake to come */
if (vmdsock_selread(s, 5) != 1) return -1;

/* Check to see that a valid handshake was received */
type = imd_recv_header_nolengthswap(s, &buf);
if (type != IMD_HANDSHAKE) return -1;

/* Check its endianness, as well as the IMD version. */
if (buf == IMDVERSION) {
if (!imd_go(s)) return 0;
return -1;
}
swap4((char *)&buf, 4);
if (buf == IMDVERSION) {
if (!imd_go(s)) return 1;
}

/* We failed to determine endianness. */
return -1;
}

int imd_recv_mdcomm(void *s, int32 n, int32 *indices, float *forces) {
if (imd_readn(s, (char *)indices, 4*n) != 4*n) return 1;
if (imd_readn(s, (char *)forces, 12*n) != 12*n) return 1;
return 0;
}

int imd_recv_energies(void *s, IMDEnergies *energies) {
return (imd_readn(s, (char *)energies, sizeof(IMDEnergies))
!= sizeof(IMDEnergies));
}

int imd_recv_fcoords(void *s, int32 n, float *coords) {
return (imd_readn(s, (char *)coords, 12*n) != 12*n);
}

110 changes: 110 additions & 0 deletions imdapi/imdapi/imd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/***************************************************************************
*cr
*cr (C) Copyright 1995-2003 The Board of Trustees of the
*cr University of Illinois
*cr All Rights Reserved
*cr
***************************************************************************/

/***************************************************************************
* RCS INFORMATION:
*
* $RCSfile: imd.h,v $
* $Author: johns $ $Locker: $ $State: Exp $
* $Revision: 1.1 $ $Date: 2003/09/12 18:30:46 $
*
***************************************************************************/

#ifndef IMD_H__
#define IMD_H__

#include <limits.h>

#if ( INT_MAX == 2147483647 )
typedef int int32;
#else
typedef short int32;
#endif

typedef enum IMDType_t {
IMD_DISCONNECT, /**< close IMD connection, leaving sim running */
IMD_ENERGIES, /**< energy data block */
IMD_FCOORDS, /**< atom coordinates */
IMD_GO, /**< start the simulation */
IMD_HANDSHAKE, /**< endianism and version check message */
IMD_KILL, /**< kill the simulation job, shutdown IMD */
IMD_MDCOMM, /**< MDComm style force data */
IMD_PAUSE, /**< pause the running simulation */
IMD_TRATE, /**< set IMD update transmission rate */
IMD_IOERROR /**< indicate an I/O error */
} IMDType;

typedef struct {
int32 tstep; /**< integer timestep index */
float T; /**< Temperature in degrees Kelvin */
float Etot; /**< Total energy, in Kcal/mol */
float Epot; /**< Potential energy, in Kcal/mol */
float Evdw; /**< Van der Waals energy, in Kcal/mol */
float Eelec; /**< Electrostatic energy, in Kcal/mol */
float Ebond; /**< Bond energy, Kcal/mol */
float Eangle; /**< Angle energy, Kcal/mol */
float Edihe; /**< Dihedral energy, Kcal/mol */
float Eimpr; /**< Improper energy, Kcal/mol */
} IMDEnergies; /**< */

/* Send control messages - these consist of a header with no subsequent data */
extern int imd_disconnect(void *); /**< leave sim running but close IMD */
extern int imd_pause(void *); /**< pause simulation */
extern int imd_kill(void *); /**< kill simulation, shutdown IMD */
extern int imd_handshake(void *); /**< check endianness, version compat */
extern int imd_trate(void *, int32); /**< set IMD update transmission rate */

/* Send data update messages */
/**
* Send MDComm compatible forces
* Forces are in Kcal/mol/angstrom
*/
extern int imd_send_mdcomm(void *, int32, const int32 *, const float *);

/**
* Send energies
*/
extern int imd_send_energies(void *, const IMDEnergies *);

/**
* Send atom forces and coordinates
* Forces are in Kcal/mol/angstrom
*/
extern int imd_send_fcoords(void *, int32, const float *);

/**
* recv_handshake returns 0 if server and client have the same relative
* endianism; returns 1 if they have opposite endianism, and -1 if there
* was an error in the handshake process.
*/
extern int imd_recv_handshake(void *);

/**
* Receive header and data
*/
extern IMDType imd_recv_header(void *, int32 *);

/**
* Receive MDComm-style forces
* Forces are in Kcal/mol/angstrom
*/
extern int imd_recv_mdcomm(void *, int32, int32 *, float *);

/**
* Receive energies
*/
extern int imd_recv_energies(void *, IMDEnergies *);

/**
* Receive atom coordinates and forces
* Forces are in Kcal/mol/angstrom
*/
extern int imd_recv_fcoords(void *, int32, float *);

#endif

Loading

0 comments on commit 7a44b30

Please sign in to comment.