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

py_imd.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: py_imd.C,v $
00013  *      $Author: dgomes $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.30 $       $Date: 2024/04/26 15:46:00 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Python IMD interface.
00019  ***************************************************************************/
00020 
00021 #include "py_commands.h"
00022 
00023 #ifdef VMDIMD
00024 
00025 #include "CmdIMD.h"
00026 #include "CommandQueue.h"
00027 #include "VMDApp.h"
00028 #include "MoleculeList.h"
00029 #include "IMDMgr.h"
00030 
00031 static const char connect_doc[] =
00032 "Connect to an IMD server\n\n"
00033 "Args:\n"
00034 "    host (str): Server hostname\n"
00035 "    port (int): Port running IMD server";
00036 static PyObject* py_imdconnect(PyObject *self, PyObject *args, PyObject *kwargs) {
00037   const char *kwlist[] = {"host", "port", NULL};
00038   char *host;
00039   int port;
00040 
00041   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si:imd.connect",
00042                                    (char**) kwlist, &host, &port))
00043     return NULL;
00044 
00045   VMDApp *app;
00046   if (!(app = get_vmdapp()))
00047     return NULL;
00048 
00049   Molecule *mol = app->moleculeList->top();
00050   if (!mol) {
00051     PyErr_SetString(PyExc_ValueError, "No molecule loaded");
00052     return NULL;
00053   }
00054 
00055   if (app->imdMgr->connected()) {
00056     PyErr_SetString(PyExc_ValueError, "Can't create new IMD connection: "
00057                     "already connected.");
00058     return NULL;
00059   }
00060 
00061   if (!app->imd_connect(mol->id(), host, port)) {
00062     PyErr_Format(PyExc_RuntimeError, "Unable to connect to IMD server '%s:%d'",
00063                  host, port);
00064     return NULL;
00065   }
00066 
00067   Py_INCREF(Py_None);
00068   return Py_None;
00069 }
00070 
00071 
00072 static const char pause_doc[] =
00073 "Pause a running IMD simulation";
00074 static PyObject* py_imdpause(PyObject *self, PyObject *args) {
00075   VMDApp *app;
00076   if (!(app = get_vmdapp()))
00077     return NULL;
00078 
00079   if (!app->imdMgr->connected()) {
00080     PyErr_SetString(PyExc_ValueError, "Not connected to an IMD server");
00081     return NULL;
00082   }
00083 
00084   app->imdMgr->togglepause();
00085   app->commandQueue->runcommand(new CmdIMDSim(CmdIMDSim::PAUSE_TOGGLE));
00086 
00087   Py_INCREF(Py_None);
00088   return Py_None;
00089 }
00090 
00091 
00092 static const char detach_doc[] =
00093 "Detach from a running IMD simulation";
00094 static PyObject *py_imddetach(PyObject *self, PyObject *args) {
00095   VMDApp *app;
00096   if (!(app = get_vmdapp()))
00097     return NULL;
00098 
00099   if (!app->imdMgr->connected()) {
00100     PyErr_SetString(PyExc_ValueError, "Not connected to an IMD server");
00101     return NULL;
00102   }
00103 
00104   app->imdMgr->detach();
00105   app->commandQueue->runcommand(new CmdIMDSim(CmdIMDSim::DETACH));
00106 
00107   Py_INCREF(Py_None);
00108   return Py_None;
00109 }
00110 
00111 
00112 static const char kill_doc[] =
00113 "Halt a running IMD simulation. Also detaches.";
00114 static PyObject* py_imdkill(PyObject *self, PyObject *args) {
00115   VMDApp *app;
00116   if (!(app = get_vmdapp()))
00117     return NULL;
00118 
00119   if (!app->imdMgr->connected()) {
00120     PyErr_SetString(PyExc_ValueError, "Not connected to an IMD server");
00121     return NULL;
00122   }
00123 
00124   app->imdMgr->kill();
00125   app->commandQueue->runcommand(new CmdIMDSim(CmdIMDSim::KILL));
00126 
00127   Py_INCREF(Py_None);
00128   return Py_None;
00129 }
00130 
00131 
00132 static const char transfer_doc[] =
00133 "Get and/or set how often timesteps are sent to the IMD server\n\n"
00134 "Args:\n"
00135 "    rate (int): New transfer rate, or None to query. Rate must be greater\n"
00136 "        than 0\n"
00137 "Returns:\n"
00138 "    (int): Updated transfer rate";
00139 static PyObject* py_imdtransfer(PyObject *self, PyObject *args,
00140                                 PyObject *kwargs) {
00141   const char *kwlist[] = {"rate", NULL};
00142   PyObject *rateobj = NULL;
00143   int rate;
00144 
00145   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:imd.transfer",
00146                                    (char**) kwlist, &rateobj))
00147     return NULL;
00148 
00149   VMDApp *app;
00150   if (!(app = get_vmdapp()))
00151     return NULL;
00152 
00153   if (rateobj) {
00154     rate = as_int(rateobj);
00155 
00156     if (rate <= 0) {
00157       PyErr_SetString(PyExc_ValueError, "transfer rate must be > 0");
00158       return NULL;
00159     }
00160 
00161     app->imdMgr->set_trans_rate(rate);
00162     app->commandQueue->runcommand(new CmdIMDRate(CmdIMDRate::TRANSFER, rate));
00163   }
00164 
00165   return as_pyint(app->imdMgr->get_trans_rate());
00166 }
00167 
00168 
00169 static const char keep_doc[] =
00170 "Get and/or set how often timesteps are saved.\n\n"
00171 "Args:\n"
00172 "    rate (int): Save frequency, or None to query. Rate must be greater than\n"
00173 "        or equal to 0\n"
00174 "Returns:\n"
00175 "    (int): Updated save frequency";
00176 static PyObject* py_imdkeep(PyObject *self, PyObject *args, PyObject *kwargs) {
00177   const char *kwlist[] = {"rate", NULL};
00178   PyObject *rateobj = NULL;
00179   int rate;
00180 
00181   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:imd.keep",
00182                                    (char**) kwlist, &rateobj))
00183     return NULL;
00184 
00185   VMDApp *app;
00186   if (!(app = get_vmdapp()))
00187     return NULL;
00188 
00189   if (rateobj) {
00190     rate = as_int(rateobj);
00191 
00192     if (rate < 0) {
00193       PyErr_SetString(PyExc_ValueError, "keep value must be >= 0");
00194       return NULL;
00195     }
00196 
00197     app->imdMgr->set_keep_rate(rate);
00198     app->commandQueue->runcommand(new CmdIMDRate(CmdIMDRate::KEEP, rate));
00199   }
00200 
00201   return as_pyint(app->imdMgr->get_keep_rate());
00202 }
00203 
00204 
00205 static const char copy_doc[] =
00206 "Set if unit cell information should be copied from previous frame\n\n"
00207 "Args:\n"
00208 "    copy (bool): If cell information should be copied";
00209 static PyObject* py_copyunitcell(PyObject *self, PyObject *args,
00210                                  PyObject *kwargs) {
00211   const char *kwlist[] = {"copy", NULL};
00212   CmdIMDCopyUnitCell::CmdIMDCopyUnitCellCommand c;
00213   int copy;
00214 
00215   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&:imd.copyunitcell",
00216                                    (char**) kwlist, convert_bool, &copy))
00217     return NULL;
00218 
00219   VMDApp *app;
00220   if (!(app = get_vmdapp()))
00221     return NULL;
00222 
00223   app->imdMgr->set_copyunitcell(copy);
00224   c = copy ? CmdIMDCopyUnitCell::COPYCELL_ON : CmdIMDCopyUnitCell::COPYCELL_OFF;
00225   app->commandQueue->runcommand(new CmdIMDCopyUnitCell(c));
00226 
00227   Py_INCREF(Py_None);
00228   return Py_None;
00229 }
00230 
00231 
00232 static const char connected_doc[] =
00233 "Query if an IMD connection exists\n\n"
00234 "Returns:\n"
00235 "    (bool): True if a connection exists, False otherwise";
00236 static PyObject* py_imdconnected(PyObject *self, PyObject *args) {
00237   VMDApp *app;
00238   if (!(app = get_vmdapp()))
00239     return NULL;
00240 
00241   PyObject *result = app->imdMgr->connected() ? Py_True : Py_False;
00242   Py_INCREF(result);
00243   return result;
00244 }
00245 
00246 static const char sendforces_doc[] =
00247 "Send forces to connected MD engine\n\n"
00248 "Args:\n"
00249 "    indices (list of ints): Atomic indices to which forces will be applied\n"
00250 "    forces (flat nx3 list): forces that will be applied to the individual atoms\n";
00251 static PyObject* py_sendforces(PyObject *self, PyObject *args,
00252                                  PyObject *kwargs) {
00253   VMDApp *app;
00254   if (!(app = get_vmdapp()))
00255     return NULL;
00256   if (! app->imdMgr->connected()) {
00257     PyErr_SetString(PyExc_ValueError, "Not connected to an IMD server");
00258     return NULL;
00259   }
00260   const char *kwlist[] = {"indices", "forces", NULL};
00261   PyObject *idxs, *idxseq;
00262   PyObject *forces, *forceseq;
00263   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO:imd.sendforces",
00264                                    (char**) kwlist, &idxs, &forces))
00265     return NULL;
00266   int n;
00267   if (!(idxseq = PySequence_Fast(idxs, "indices must be a python sequence"))) {
00268     Py_XDECREF(idxseq);
00269     return NULL;
00270   }
00271   if (!(forceseq = PySequence_Fast(forces, "forces must be a python sequence"))) {
00272     Py_XDECREF(idxseq);
00273     Py_XDECREF(forceseq);
00274     return NULL;
00275   }
00276   n = PySequence_Fast_GET_SIZE(idxseq);
00277   if (PySequence_Fast_GET_SIZE(forceseq) != 3 * n) {
00278     Py_XDECREF(idxseq);
00279     Py_XDECREF(forceseq);
00280     PyErr_SetString(PyExc_ValueError, "The force list passed is not 3 times as long as the index list.");
00281     return NULL;
00282   }
00283   int *cidxs = new int[n];
00284   float *cforces = new float[3*n];
00285   for (int i = 0; i < n; i++) {
00286           int result = (int) PyLong_AsLong(PySequence_Fast_GET_ITEM(idxseq,i));
00287           if (result < 0) {
00288                   Py_XDECREF(idxseq);
00289                   Py_XDECREF(forceseq);
00290                   PyErr_SetString(PyExc_ValueError, "A value in the index list is not a positive integer");
00291                   return NULL;
00292           }
00293           cidxs[i] = result;
00294   }
00295   for (int i = 0; i < 3*n; i++) {
00296           cforces[i] = (float) PyFloat_AS_DOUBLE(PySequence_Fast_GET_ITEM(forceseq,i));
00297   }
00298   app->imd_sendforces(n, cidxs, cforces);
00299   delete cidxs;
00300   delete cforces;
00301   Py_XDECREF(idxseq);
00302   Py_XDECREF(forceseq);
00303   Py_INCREF(Py_None);
00304   return Py_None;
00305 }
00306 
00307 static PyMethodDef methods[] = {
00308   {"connected", (PyCFunction)py_imdconnected, METH_NOARGS, connected_doc},
00309   {"connect", (PyCFunction)py_imdconnect, METH_VARARGS | METH_KEYWORDS, connect_doc},
00310   {"pause", (PyCFunction)py_imdpause, METH_NOARGS, pause_doc},
00311   {"detach", (PyCFunction)py_imddetach, METH_NOARGS, detach_doc},
00312   {"kill", (PyCFunction)py_imdkill, METH_NOARGS, kill_doc},
00313   {"transfer", (PyCFunction)py_imdtransfer, METH_VARARGS | METH_KEYWORDS, transfer_doc},
00314   {"keep", (PyCFunction)py_imdkeep, METH_VARARGS | METH_KEYWORDS, keep_doc},
00315   {"copyunitcell", (PyCFunction)py_copyunitcell, METH_VARARGS | METH_KEYWORDS, copy_doc},
00316   {"sendforces", (PyCFunction)py_sendforces, METH_VARARGS | METH_KEYWORDS, sendforces_doc},
00317   {NULL, NULL}
00318 };
00319 
00320 
00321 static const char imd_moddoc[] =
00322 "Methods for controlling interactive molecular dynamics simulations";
00323 
00324 
00325 #if PY_MAJOR_VERSION >= 3
00326 static struct PyModuleDef imddef = {
00327   PyModuleDef_HEAD_INIT,
00328   "imd",
00329   imd_moddoc,
00330   -1,
00331   methods,
00332 };
00333 #endif
00334 
00335 
00336 PyObject* initimd() {
00337 #if PY_MAJOR_VERSION >= 3
00338   PyObject *m = PyModule_Create(&imddef);
00339 #else
00340   PyObject *m = Py_InitModule3("imd", methods, imd_moddoc);
00341 #endif
00342   return m;
00343 }
00344 
00345 #endif
00346 

Generated on Fri Nov 8 02:45:25 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002