From: Justin Gullingsrud (justin_at_ks.uiuc.edu)
Date: Mon Mar 31 2003 - 12:12:22 CST

Hi Lars,

Here's what I've got; please let me know if there's anything important that
I've left out.

It should be very straightforward to add IMD capabilities to your MD
code so that it can communicate with VMD. If you download a copy of
the NAMD source code, you'll find files vmdsock.[ch] and imd.[Ch]
(the imd.C file is really C, not C++, so if your code is straight C
you can just change the filename extension). These two files contain
all the API's you would need to communicate with VMD.

Unfortunately there's not a lot of documentation for using these functions
other than existing code, so I'll summarize what you'd need to do to
incorporate IMD into your MD program. In NAMD all the IMD interaction
takes place in the file GlobalMasterIMD.C.

1. Create a socket, bind it to listening port, and make it listen:
   void *sock = vmdsock_create();
   vmdsock_bind(sock, PORT);
   vmdsock_listen(sock);

2. Periodically check for incoming connection requests.
   void *clientsock = NULL;
   int length;
   if (vmdsock_selread(sock, 0) > 0) {
     clientsock = vmdsock_accept(sock);
     if (imd_handshake(sock))
       /* handshake failed */
       clientsock = NULL;
     }
     /* wait a second for VMD to respond */
     sleep(1);
     if (vmdsock_selread(clientsock, 0) != 1 ||
         imd_recv_header(clientsock, &length) != IMD_GO) {
       /* broken protocol */
       clientsock = NULL;
     }
   }
   /* If clientsock is non-NULL, we have a connection */

3. Send energies and coordinates whenever you want.
   IMDEnergies energies;
   get_energies(&energies);
   imd_send_energies(clientsock, &energies);

   float *coords = get_coordinates(); /* Stored as xyzxyzxyz... */
   imd_send_fcoords(clientsock, numatoms, coords);

4. Periodically check for commands from VMD
   
   int type, length;
   while (vmdsock_selread(clientsock, 0) > 0) {
     type = imd_recv_header(clientsock, &length);
     switch (type) {
       case IMD_MDCOMM: {
         /* Get forces on selected atoms */
         int *atoms;
         float *forces;
         atoms = (int *)malloc(length*sizeof(int));
         forces = (float *)malloc(3*length*sizeof(float));
         imd_recv_mdcomm(clientsock, length, atoms, forces);
         }
         break;
       case IMD_TRATE:
         /* length is the desired rate at which coordinates should be sent
          * to VMD.
          */
          break;
        case IMD_PAUSE:
          /* Pause the simulation into the next IMD_PAUSE */
          break;
        case IMD_IOERROR:
          /* Connection was lost */
        case IMD_DISCONNECT: /* fall through */
          vmdsock_destroy(clientsock);
          break;
        case IMD_KILL:
          /* quit the simulation */
          break;
        default:
          /* Uh oh, unhandled case... */
     }
   }

Note that VMD must connect to the machine on the cluster that's got the
open socket. Don't hesitate to ask if you have any problems getting
IMD working with your system.

Cheers,
Justin

-- 
  Justin Gullingsrud        3111 Beckman Institute        217-244-8946
  I been dropping the new science, and I be kicking the new knowledge,
  and I'm seeing to a degree that you can't get in college.  -- b.boys