ScriptTcl.C

Go to the documentation of this file.
00001 
00007 /*
00008    Modifies SimParameters settings during run.
00009 */
00010 
00011 #include "InfoStream.h"
00012 #include "BackEnd.h"
00013 #include "ScriptTcl.h"
00014 #include "Broadcasts.h"
00015 #include "ConfigList.h"
00016 #include "Node.h"
00017 #include "PDB.h"
00018 #include "WorkDistrib.h"
00019 #include "NamdState.h"
00020 #include "Output.h"
00021 #include "Controller.h"
00022 #include "SimParameters.h"
00023 #include "Thread.h"
00024 #include "ProcessorPrivate.h"
00025 #include "PatchMgr.h"
00026 #include "PatchMap.h"
00027 #include "Measure.h"
00028 #include "colvarmodule.h"
00029 #include "colvarscript.h"
00030 #include "DumpBench.h"
00031 #include <errno.h>
00032 #include <stdio.h>
00033 #include <ctype.h>  // for isspace
00034 #ifndef WIN32
00035 #include <strings.h>
00036 #endif
00037 
00038 #include "qd.h"
00039 
00040 #ifdef NAMD_TCL
00041 #include <tcl.h>
00042 #endif
00043 #include "TclCommands.h"
00044 
00045 #include "ProcessorPrivate.h"
00046 #include "DataExchanger.h"
00047 
00048 //#define DEBUGM
00049 #define MIN_DEBUG_LEVEL 4
00050 #include "Debug.h"
00051 
00052 #include "molfile_plugin.h"
00053 #include "libmolfile_plugin.h"
00054 
00055 static molfile_plugin_t *dcdplugin;
00056 static int register_cb(void *v, vmdplugin_t *p) {
00057         dcdplugin = (molfile_plugin_t *)p;
00058         return 0;
00059 }
00060 
00061 //
00062 // XXX static and global variables are unsafe for shared memory builds.
00063 //
00064 static int numatoms;
00065 static void *filehandle;
00066 static float *coords;
00067 static Vector *vcoords;
00068 
00069 
00070 void ScriptTcl::suspend() {
00071   BackEnd::suspend();
00072 }
00073 
00074 void ScriptTcl::barrier() {
00075   BackEnd::barrier();
00076 }
00077 
00078 void ScriptTcl::initcheck() {
00079   if ( initWasCalled == 0 ) {
00080 #ifdef NAMD_TCL
00081     CkPrintf("TCL: Suspending until startup complete.\n");
00082     Tcl_CreateCommand(interp, "param", Tcl_param,
00083       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00084     Tcl_CreateCommand(interp, "unknown", Tcl_param,
00085       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00086     Tcl_CreateCommand(interp, "isset", Tcl_isset_param,
00087       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00088     Tcl_CreateCommand(interp, "istrue", Tcl_istrue_param,
00089       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00090     Tcl_CreateCommand(interp, "structure", Tcl_reloadStructure,
00091       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00092 #endif
00093     initWasCalled = 1;
00094 
00095     state->configListInit(config);
00096     Node::Object()->saveMolDataPointers(state);
00097 #ifdef NAMD_TCL
00098     SimParameters *simParams = Node::Object()->simParameters;
00099     simParams->tclIsThreaded =
00100       ! ! Tcl_GetVar2(interp, "tcl_platform", "threaded", TCL_GLOBAL_ONLY);
00101 #endif
00102     Node::messageStartUp();
00103     suspend();
00104   }
00105 }
00106 
00107 void ScriptTcl::runController(int task) {
00108   scriptBarrier.publish(barrierStep++,task);
00109   suspend();
00110 #ifdef NAMD_TCL
00111   if ( task == SCRIPT_RUN || task == SCRIPT_CONTINUE || task == SCRIPT_MINIMIZE  ) {
00112     doCallback(state->callback_labelstring.c_str(),
00113                state->callback_valuestring.c_str());
00114   }
00115 #endif
00116 }
00117 
00118 void ScriptTcl::setParameter(const char* param, const char* value) {
00119   ScriptParamMsg *msg = new ScriptParamMsg;
00120   strncpy(msg->param,param,MAX_SCRIPT_PARAM_SIZE);
00121   strncpy(msg->value,value,MAX_SCRIPT_PARAM_SIZE);
00122   (CProxy_Node(CkpvAccess(BOCclass_group).node)).scriptParam(msg);
00123   barrier();
00124 }
00125 
00126 void ScriptTcl::setParameter(const char* param, int value) {
00127   ScriptParamMsg *msg = new ScriptParamMsg;
00128   strncpy(msg->param,param,MAX_SCRIPT_PARAM_SIZE);
00129   sprintf(msg->value,"%d",value);
00130   (CProxy_Node(CkpvAccess(BOCclass_group).node)).scriptParam(msg);
00131   barrier();
00132 }
00133 
00134 void ScriptTcl::reinitAtoms(const char *basename) {
00135   Node::Object()->workDistrib->reinitAtoms(basename);
00136   barrier();
00137 }
00138 
00139 #ifdef NAMD_TCL
00140 
00141 #ifdef NAMD_PYTHON
00142 #include <Python.h>
00143 
00144 static Tcl_Obj* python_tcl_convert(PyObject *obj) {
00145   if ( PyInt_Check(obj) ) {
00146     return Tcl_NewLongObj(PyInt_AsLong(obj));
00147   }
00148   if ( PyFloat_Check(obj) ) {
00149     return Tcl_NewDoubleObj(PyFloat_AsDouble(obj));
00150   }
00151   if ( PyString_Check(obj) ) {
00152     return Tcl_NewStringObj(PyString_AsString(obj), -1);
00153   }
00154   if ( PySequence_Check(obj) ) {
00155     PyObject *iter = PyObject_GetIter(obj);
00156     if ( ! iter ) NAMD_bug("python_tcl_convert failed to get iterator");
00157     Tcl_Obj *rlist = Tcl_NewListObj(0,0);
00158     while ( PyObject *item = PyIter_Next(iter) ) {
00159       Tcl_ListObjAppendElement(0, rlist, python_tcl_convert(item));
00160       Py_DECREF(item);
00161     }
00162     Py_DECREF(iter);
00163     return rlist;
00164   }
00165   PyObject *str = PyObject_Str(obj);
00166   Tcl_Obj *robj = Tcl_NewStringObj(PyString_AsString(str), -1);
00167   Py_DECREF(str);
00168   return robj;
00169 }
00170 
00171 static int atoBool(const char *s);
00172 
00173 static PyObject* tcl_python_convert(Tcl_Obj *obj) {
00174   long rlong;
00175   if ( TCL_OK == Tcl_GetLongFromObj(0, obj, &rlong) )
00176     return Py_BuildValue("l", rlong);
00177   double rdouble;
00178   if ( TCL_OK == Tcl_GetDoubleFromObj(0, obj, &rdouble) )
00179     return Py_BuildValue("d", rdouble);
00180   const char *rstring = Tcl_GetString(obj);
00181   if ( rstring[0] == '\0' )
00182     return Py_None;
00183   int rbool = atoBool(rstring);
00184   if ( rbool >= 0 )
00185     return PyBool_FromLong(rbool);
00186   return Py_BuildValue("s", rstring);
00187 }
00188 
00189 static Tcl_Interp *static_interp;
00190 
00191 static PyObject* python_tcl_call(PyObject *self, PyObject *args) {
00192   Tcl_Interp *interp = static_interp;
00193   Tcl_Obj *command = python_tcl_convert(args);
00194   Tcl_IncrRefCount(command);
00195   if ( TCL_OK != Tcl_EvalObjEx(interp,command,TCL_EVAL_DIRECT) ) {
00196     PyErr_SetString(PyExc_RuntimeError, Tcl_GetStringResult(interp));
00197     Tcl_DecrRefCount(command);
00198     return 0;
00199   }
00200   Tcl_DecrRefCount(command);
00201   return tcl_python_convert(Tcl_GetObjResult(interp));
00202 }
00203 
00204 static PyObject* python_tcl_eval(PyObject *self, PyObject *args) {
00205   Tcl_Interp *interp = static_interp;
00206   const char *command;
00207   if ( ! PyArg_ParseTuple(args, "s", &command) ) return 0;
00208   if ( TCL_OK != Tcl_EvalEx(interp,command,-1,TCL_EVAL_DIRECT) ) {
00209     PyErr_SetString(PyExc_RuntimeError, Tcl_GetStringResult(interp));
00210     return 0;
00211   }
00212   return tcl_python_convert(Tcl_GetObjResult(interp));
00213 }
00214 
00215 static PyObject* python_tcl_write(PyObject *self, PyObject *args) {
00216   const char *string;
00217   if ( ! PyArg_ParseTuple(args, "s", &string) ) return 0;
00218   CkPrintf("%s", string);
00219   return Py_None;
00220 }
00221 
00222 static PyMethodDef methods[] = {
00223   {"eval", python_tcl_eval, METH_VARARGS,
00224    "Evaluate string in Tcl interpreter."},
00225   {"call", python_tcl_call, METH_VARARGS,
00226    "Call command and arguments in Tcl interpreter."},
00227   {"write", python_tcl_write, METH_VARARGS,
00228    "Write string using CkPrintf."},
00229   {NULL, NULL, 0, NULL}
00230 };
00231 
00232 static void namd_python_initialize(void *interp) {
00233   if ( static_interp ) return;
00234   static_interp = (Tcl_Interp*) interp;
00235   Py_InitializeEx(0);  // do not initialize signal handlers
00236   Py_InitModule("tcl", methods);
00237 
00238   const char * python_code = "\n"
00239 "import sys\n"
00240 "import tcl\n"
00241 "sys.stdout = tcl\n"
00242 "\n"
00243 "class _namd_wrapper:\n"
00244 "  class _wrapped:\n"
00245 "    def __init__(self,_name):\n"
00246 "      self.name = _name\n"
00247 "    def __call__(self,*args):\n"
00248 "      return tcl.call(self.name,*args)\n"
00249 "  def __getattr__(self,name):\n"
00250 "    if tcl.call('info','commands',name) == name:\n"
00251 "      return self._wrapped(name)\n"
00252 "    else:\n"
00253 "      return tcl.call('param',name)\n"
00254 "  def __setattr__(self,name,val):\n"
00255 "    if tcl.call('info','commands',name) == name:\n"
00256 "      raise AttributeError\n"
00257 "    return tcl.call('param',name,val)\n"
00258 "  def __call__(self, **args):\n"
00259 "    for (name,val) in args.items():\n"
00260 "      tcl.call('param',name,val)\n"
00261 "\n"
00262 "namd = _namd_wrapper()\n"
00263 "\n";
00264 
00265   if ( TCL_OK != PyRun_SimpleString(python_code) ) {
00266     NAMD_bug("namd_python_initialize failed");
00267   }
00268 }
00269 
00270 int ScriptTcl::Tcl_python(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00271   if ( argc < 2 ) {
00272     Tcl_SetResult(interp,"args: script",TCL_VOLATILE);
00273     return TCL_ERROR;
00274   }
00275   namd_python_initialize(interp);
00276   PyObject *dict = PyModule_GetDict(PyImport_AddModule("__main__"));
00277 
00278   const char *script = argv[1];
00279   int token = Py_eval_input;
00280 
00281   Tcl_DString scr;
00282   Tcl_DStringInit(&scr);
00283   if ( argc > 2 ) {
00284     Tcl_DStringAppend(&scr,argv[1],-1);
00285     for ( int i = 2; i < argc; ++i ) {
00286       Tcl_DStringAppend(&scr," ",-1);
00287       Tcl_DStringAppend(&scr,argv[i],-1);
00288     }
00289     script = Tcl_DStringValue(&scr);
00290   } else {
00291     while ( script[0] == ' ' || script[0] == '\t' ) ++script;
00292     for ( int i=0; script[i]; ++i ) {
00293       if ( script[i] == '\n' ) {
00294         token = Py_file_input;
00295         script = argv[1];
00296         break;
00297       }
00298     }
00299   }
00300 
00301   PyObject *result = PyRun_String(script, token, dict, dict);
00302   Tcl_ResetResult(interp);  // Python may have called Tcl
00303   Tcl_DStringFree(&scr);
00304 
00305   if ( PyErr_Occurred() ) {
00306     if ( result ) NAMD_bug("PyErr_Occurred indicates error but PyRun does not");
00307     // PyErr_Print();
00308     Tcl_AppendResult(interp, "error from python interpreter\n", NULL);
00309     PyObject *type, *value, *traceback, *str;
00310     PyErr_Fetch(&type, &value, &traceback);
00311 
00312     if ( ! traceback ) {
00313       traceback = Py_None;
00314       Py_INCREF(Py_None);
00315     }
00316 
00317     PyObject *mod = PyImport_ImportModule("traceback");
00318     if ( ! mod ) return TCL_ERROR;
00319 
00320     PyObject *func = PyObject_GetAttrString(mod, "format_exception");
00321     if ( ! func ) return TCL_ERROR;
00322 
00323     PyObject *list = PyObject_CallFunctionObjArgs(func, type, value, traceback, NULL);
00324     Py_DECREF(mod);
00325     Py_DECREF(func);
00326     Py_DECREF(type);
00327     Py_DECREF(value);
00328     Py_DECREF(traceback);
00329 
00330     PyObject *iter = PyObject_GetIter(list);
00331     if ( ! iter ) return TCL_ERROR;
00332     while ( PyObject *item = PyIter_Next(iter) ) {
00333       str = PyObject_Str(item);
00334       Tcl_AppendResult(interp, PyString_AsString(str), "\n", NULL);
00335       Py_DECREF(str);
00336       Py_DECREF(item);
00337     }
00338     Py_DECREF(iter);
00339     Py_DECREF(list);
00340 
00341     return TCL_ERROR;
00342   } else if ( ! result ) {
00343     NAMD_bug("PyRun indicates error but PyErr_Occurred does not");
00344   }
00345   if ( result != Py_None ) {
00346     Tcl_SetObjResult(interp, python_tcl_convert(result));
00347   }
00348   Py_DECREF(result);
00349   return TCL_OK;
00350 }
00351 
00352 #else // NAMD_PYTHON
00353 
00354 int ScriptTcl::Tcl_python(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00355   Tcl_SetResult(interp,"python not enabled",TCL_VOLATILE);
00356   return TCL_ERROR;
00357 }
00358 
00359 #endif // NAMD_PYTHON
00360 
00361 int ScriptTcl::Tcl_startup(ClientData clientData,
00362         Tcl_Interp *interp, int argc, const char *argv[]) {
00363   if ( argc > 1 ) {
00364     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00365     return TCL_ERROR;
00366   }
00367   ScriptTcl *script = (ScriptTcl *)clientData;
00368   script->initcheck();
00369   return TCL_OK;
00370 }
00371 
00372 int ScriptTcl::Tcl_exit(ClientData clientData,
00373         Tcl_Interp *, int argc, const char *argv[]) {
00374   ScriptTcl *script = (ScriptTcl *)clientData;
00375   if ( CmiNumPartitions() > 1 ) {
00376     if ( ! script->initWasCalled ) CkPrintf("TCL: Running startup before exit due to replicas.\n");
00377     script->initcheck();
00378   }
00379   CkPrintf("TCL: Exiting due to exit command.\n");
00380 #if CMK_HAS_PARTITION
00381   replica_barrier();
00382 #endif
00383   if ( script->runWasCalled ) script->runController(SCRIPT_END);
00384   BackEnd::exit();
00385   return TCL_OK;
00386 }
00387 
00388 int ScriptTcl::Tcl_abort(ClientData,
00389         Tcl_Interp *, int argc, const char *argv[]) {
00390   Tcl_DString msg;
00391   Tcl_DStringInit(&msg);
00392   Tcl_DStringAppend(&msg,"TCL:",-1);
00393   for ( int i = 1; i < argc; ++i ) {
00394     Tcl_DStringAppend(&msg," ",-1);
00395     Tcl_DStringAppend(&msg,argv[i],-1);
00396   }
00397   NAMD_die(Tcl_DStringValue(&msg));
00398   Tcl_DStringFree(&msg);
00399   return TCL_OK;
00400 }
00401 
00402 int ScriptTcl::Tcl_numPes(ClientData, Tcl_Interp *interp, int argc, const char **) {
00403   if ( argc > 1 ) {
00404     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00405     return TCL_ERROR;
00406   }
00407   Tcl_SetObjResult(interp, Tcl_NewIntObj(CkNumPes()));
00408   return TCL_OK;
00409 }
00410 
00411 int ScriptTcl::Tcl_numNodes(ClientData, Tcl_Interp *interp, int argc, const char **) {
00412   if ( argc > 1 ) {
00413     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00414     return TCL_ERROR;
00415   }
00416   Tcl_SetObjResult(interp, Tcl_NewIntObj(CkNumNodes()));
00417   return TCL_OK;
00418 }
00419 
00420 int ScriptTcl::Tcl_numPhysicalNodes(ClientData, Tcl_Interp *interp, int argc, const char **) {
00421   if ( argc > 1 ) {
00422     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00423     return TCL_ERROR;
00424   }
00425   Tcl_SetObjResult(interp, Tcl_NewIntObj(CmiNumPhysicalNodes()));
00426   return TCL_OK;
00427 }
00428 
00429 int ScriptTcl::Tcl_numReplicas(ClientData, Tcl_Interp *interp, int argc, const char **) {
00430   if ( argc > 1 ) {
00431     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00432     return TCL_ERROR;
00433   }
00434   Tcl_SetObjResult(interp, Tcl_NewIntObj(CmiNumPartitions()));
00435   return TCL_OK;
00436 }
00437 
00438 int ScriptTcl::Tcl_myReplica(ClientData, Tcl_Interp *interp, int argc, const char **) {
00439   if ( argc > 1 ) {
00440     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00441     return TCL_ERROR;
00442   }
00443   Tcl_SetObjResult(interp, Tcl_NewIntObj(CmiMyPartition()));
00444   return TCL_OK;
00445 }
00446 
00447 #define CHECK_REPLICA(REP) do {\
00448   if ( (REP) < 0 ) { \
00449     Tcl_SetResult(interp,"negative replica index",TCL_VOLATILE); \
00450     return TCL_ERROR; \
00451   } \
00452   if ( (REP) >= CmiNumPartitions() ) { \
00453     Tcl_SetResult(interp,"non-existent replica index",TCL_VOLATILE); \
00454     return TCL_ERROR; \
00455   } \
00456 } while ( 0 )
00457 
00458 int ScriptTcl::Tcl_replicaEval(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00459   if ( argc != 3 ) {
00460     Tcl_SetResult(interp,"args: dest script",TCL_VOLATILE);
00461     return TCL_ERROR;
00462   }
00463   int dest = atoi(argv[1]);
00464   CHECK_REPLICA(dest);
00465 #if CMK_HAS_PARTITION
00466   Tcl_DString recvstr;
00467   Tcl_DStringInit(&recvstr);
00468   DataMessage *recvMsg = NULL;
00469   replica_eval(argv[2], dest, CkMyPe(), &recvMsg);
00470   CmiAssert(recvMsg != NULL);
00471   int code = recvMsg->code;
00472   Tcl_DStringAppend(&recvstr, recvMsg->data, recvMsg->size);
00473   Tcl_DStringResult(interp, &recvstr);
00474   Tcl_DStringFree(&recvstr);
00475   CmiFree(recvMsg);
00476   return code;
00477 #else
00478   return Tcl_EvalEx(interp,argv[2],-1,TCL_EVAL_GLOBAL);
00479 #endif
00480 }
00481 
00482 int ScriptTcl::Tcl_replicaYield(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00483   if ( argc > 2 ) {
00484     Tcl_SetResult(interp,"args: ?seconds?",TCL_VOLATILE);
00485     return TCL_ERROR;
00486   }
00487   double time = 0.;
00488   if ( argc == 2 ) {
00489     if ( sscanf(argv[1],"%lf",&time) != 1 ) {
00490       Tcl_SetResult(interp,"args: ?seconds?",TCL_VOLATILE);
00491       return TCL_ERROR;
00492     }
00493   }
00494   if ( time > 0. ) {
00495     time += CmiWallTimer();
00496     do { CsdSchedulePoll(); } while ( CmiWallTimer() < time );
00497   } else {
00498     CsdSchedulePoll();
00499   }
00500   return TCL_OK;
00501 }
00502 
00503 
00504 int ScriptTcl::Tcl_replicaSendrecv(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00505   if ( argc < 3 || argc > 4 ) {
00506     Tcl_SetResult(interp,"args: data dest ?source?",TCL_VOLATILE);
00507     return TCL_ERROR;
00508   }
00509   Tcl_DString recvstr;
00510   Tcl_DStringInit(&recvstr);
00511   int sendcount = strlen(argv[1]);
00512   int recvcount = 0;
00513   int dest = atoi(argv[2]);
00514   int source = -1;
00515   if ( argc > 3 ) source = atoi(argv[3]);
00516 #if CMK_HAS_PARTITION
00517   if (dest == CmiMyPartition()) {
00518     Tcl_DStringSetLength(&recvstr,sendcount);
00519     memcpy(Tcl_DStringValue(&recvstr),argv[1],sendcount);
00520   } else {
00521     DataMessage *recvMsg = NULL;
00522     replica_sendRecv(argv[1], sendcount, dest, CkMyPe(), &recvMsg, source, CkMyPe());
00523     CmiAssert(recvMsg != NULL);
00524     Tcl_DStringAppend(&recvstr, recvMsg->data, recvMsg->size);
00525     CmiFree(recvMsg);
00526   }
00527 #endif
00528   Tcl_DStringResult(interp, &recvstr);
00529   Tcl_DStringFree(&recvstr);
00530   return TCL_OK;
00531 }
00532 
00533 int ScriptTcl::Tcl_replicaSend(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00534   if ( argc != 3 ) {
00535     Tcl_SetResult(interp,"args: data dest",TCL_VOLATILE);
00536     return TCL_ERROR;
00537   }
00538   int sendcount = strlen(argv[1]);
00539   int dest = atoi(argv[2]);
00540 #if CMK_HAS_PARTITION
00541   replica_send(argv[1], sendcount, dest, CkMyPe());
00542 #endif
00543   return TCL_OK;
00544 }
00545 
00546 int ScriptTcl::Tcl_replicaRecv(ClientData, Tcl_Interp *interp, int argc, const char **argv) {
00547   if (argc != 2 ) {
00548     Tcl_SetResult(interp,"args: source",TCL_VOLATILE);
00549     return TCL_ERROR;
00550   }
00551   Tcl_DString recvstr;
00552   Tcl_DStringInit(&recvstr);
00553   int recvcount = 0;
00554   int source = atoi(argv[1]);
00555 #if CMK_HAS_PARTITION
00556   DataMessage *recvMsg = NULL;
00557   replica_recv(&recvMsg, source, CkMyPe());
00558   CmiAssert(recvMsg != NULL);
00559   Tcl_DStringAppend(&recvstr, recvMsg->data, recvMsg->size);
00560   CmiFree(recvMsg);
00561 #endif
00562   Tcl_DStringResult(interp, &recvstr);
00563   Tcl_DStringFree(&recvstr);
00564   return TCL_OK;
00565 }
00566 
00567 int ScriptTcl::Tcl_replicaBarrier(ClientData, Tcl_Interp *interp, int argc, const char **) {
00568   if ( argc > 1 ) {
00569     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00570     return TCL_ERROR;
00571   }
00572 #if CMK_HAS_PARTITION
00573   replica_barrier();
00574 #endif
00575   return TCL_OK;
00576 }
00577 
00578 int ScriptTcl::Tcl_replicaAtomSendrecv(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv) {
00579   ScriptTcl *script = (ScriptTcl *)clientData;
00580   script->initcheck();
00581   if ( ! Node::Object()->simParameters->replicaUniformPatchGrids ) {
00582     Tcl_SetResult(interp,"replicaUniformPatchGrids is required for atom exchange",TCL_VOLATILE);
00583     return TCL_ERROR;
00584   }
00585   if ( argc < 2 || argc > 3 ) {
00586     Tcl_SetResult(interp,"bad arg count; args: dest ?source?",TCL_VOLATILE);
00587     return TCL_ERROR;
00588   }
00589   int dest = -1;
00590   if ( sscanf(argv[1], "%d", &dest) != 1 ) {
00591     Tcl_SetResult(interp,"bad dest; args: dest ?source?",TCL_VOLATILE);
00592     return TCL_ERROR;
00593   }
00594   int source = -1;
00595   if ( argc == 3 ) {
00596     if ( sscanf(argv[2], "%d", &source) != 1 ) {
00597       Tcl_SetResult(interp,"bad source; args: dest ?source?",TCL_VOLATILE);
00598       return TCL_ERROR;
00599     }
00600   }
00601 
00602 #if CMK_HAS_PARTITION
00603   if (dest != CmiMyPartition()) {
00604     DataMessage *recvMsg = NULL;
00605     replica_sendRecv((char*)&(script->state->lattice), sizeof(Lattice), dest, CkMyPe(), &recvMsg, source, CkMyPe());
00606     CmiAssert(recvMsg != NULL);
00607     memcpy(&(script->state->lattice), recvMsg->data, recvMsg->size);
00608     CmiFree(recvMsg);
00609   }
00610 #endif
00611 
00612   char str[40];
00613   sprintf(str, "%d", dest);
00614   script->setParameter("scriptArg1", str);
00615   sprintf(str, "%d", source);
00616   script->setParameter("scriptArg2", str);
00617 
00618   CkpvAccess(_qd)->create(2 * PatchMap::Object()->numPatches());
00619 
00620   script->runController(SCRIPT_ATOMSENDRECV);
00621 
00622 #if CMK_HAS_PARTITION
00623   if (dest != CmiMyPartition()) {
00624     DataMessage *recvMsg = NULL;
00625     ControllerState *cstate = script->state->controller;
00626     replica_sendRecv((char*)cstate, sizeof(ControllerState), dest, CkMyPe(), &recvMsg, source, CkMyPe());
00627     CmiAssert(recvMsg != NULL);
00628     memcpy(cstate, recvMsg->data, recvMsg->size);
00629     CmiFree(recvMsg);
00630   }
00631 #endif
00632 
00633   return TCL_OK;
00634 }
00635 
00636 int ScriptTcl::Tcl_replicaAtomSend(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv) {
00637   ScriptTcl *script = (ScriptTcl *)clientData;
00638   script->initcheck();
00639   if ( ! Node::Object()->simParameters->replicaUniformPatchGrids ) {
00640     Tcl_SetResult(interp,"replicaUniformPatchGrids is required for atom exchange",TCL_VOLATILE);
00641     return TCL_ERROR;
00642   }
00643   if ( argc != 2 ) {
00644     Tcl_SetResult(interp,"bad arg count; args: dest",TCL_VOLATILE);
00645     return TCL_ERROR;
00646   }
00647   int dest = -1;
00648   if ( sscanf(argv[1], "%d", &dest) != 1 ) {
00649     Tcl_SetResult(interp,"bad dest; args: dest",TCL_VOLATILE);
00650     return TCL_ERROR;
00651   }
00652 
00653 #if CMK_HAS_PARTITION
00654   replica_send((char*)&(script->state->lattice), sizeof(Lattice), dest, CkMyPe());
00655 #endif
00656 
00657   char str[40];
00658   sprintf(str, "%d", dest);
00659   script->setParameter("scriptArg1", str);
00660 
00661   CkpvAccess(_qd)->create(PatchMap::Object()->numPatches());
00662 
00663   script->runController(SCRIPT_ATOMSEND);
00664 
00665 #if CMK_HAS_PARTITION
00666   ControllerState *cstate = script->state->controller;
00667   replica_send((char*)cstate, sizeof(ControllerState), dest, CkMyPe());
00668 #endif
00669 
00670   return TCL_OK;
00671 }
00672 
00673 int ScriptTcl::Tcl_replicaAtomRecv(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv) {
00674   ScriptTcl *script = (ScriptTcl *)clientData;
00675   script->initcheck();
00676   if ( ! Node::Object()->simParameters->replicaUniformPatchGrids ) {
00677     Tcl_SetResult(interp,"replicaUniformPatchGrids is required for atom exchange",TCL_VOLATILE);
00678     return TCL_ERROR;
00679   }
00680   if ( argc > 2 ) {
00681     Tcl_SetResult(interp,"bad arg count; args: ?source?",TCL_VOLATILE);
00682     return TCL_ERROR;
00683   }
00684   int source = -1;
00685   if ( argc == 2 ) {
00686     if ( sscanf(argv[1], "%d", &source) != 1 ) {
00687       Tcl_SetResult(interp,"bad source; args: ?source?",TCL_VOLATILE);
00688       return TCL_ERROR;
00689     }
00690   }
00691 
00692 #if CMK_HAS_PARTITION
00693   DataMessage *recvMsg = NULL;
00694   replica_recv(&recvMsg, source, CkMyPe());
00695   CmiAssert(recvMsg != NULL);
00696   memcpy(&(script->state->lattice), recvMsg->data, recvMsg->size);
00697   CmiFree(recvMsg);
00698 #endif
00699 
00700   char str[40];
00701   sprintf(str, "%d", source);
00702   script->setParameter("scriptArg2", str);
00703 
00704   CkpvAccess(_qd)->create(PatchMap::Object()->numPatches());
00705 
00706   script->runController(SCRIPT_ATOMRECV);
00707 
00708 #if CMK_HAS_PARTITION
00709   recvMsg = NULL;
00710   ControllerState *cstate = script->state->controller;
00711   replica_recv(&recvMsg, source, CkMyPe());
00712   CmiAssert(recvMsg != NULL);
00713   memcpy(cstate, recvMsg->data, recvMsg->size);
00714   CmiFree(recvMsg);
00715 #endif
00716 
00717   return TCL_OK;
00718 }
00719 
00720 
00721 int ScriptTcl::Tcl_stdout(ClientData,
00722         Tcl_Interp *interp, int argc, const char *argv[]) {
00723   if (argc != 2) {
00724     Tcl_SetResult(interp, "wrong # args", TCL_VOLATILE);
00725     return TCL_ERROR;
00726   }
00727 
00728   const char *filename= argv[1];
00729   CkPrintf("TCL: redirecting stdout to file %s\n", filename);
00730 
00731   if ( ! freopen(filename, "a", stdout) ) {
00732     Tcl_SetResult(interp, strerror(errno), TCL_VOLATILE);
00733     return TCL_ERROR;
00734   }
00735   return TCL_OK;
00736 }
00737 
00738 int ScriptTcl::Tcl_print(ClientData,
00739         Tcl_Interp *, int argc, const char *argv[]) {
00740   Tcl_DString msg;
00741   Tcl_DStringInit(&msg);
00742   for ( int i = 1; i < argc; ++i ) {
00743     Tcl_DStringAppend(&msg," ",-1);
00744     Tcl_DStringAppend(&msg,argv[i],-1);
00745   }
00746   CkPrintf("TCL:%s\n",Tcl_DStringValue(&msg));
00747   Tcl_DStringFree(&msg);
00748   return TCL_OK;
00749 }
00750 
00751 int ScriptTcl::Tcl_config(ClientData clientData,
00752         Tcl_Interp *interp, int argc, const char *argv[]) {
00753 
00754 // Needs to handle the following cases as passed in by Tcl:
00755 //    name data #comment
00756 //    name=data #comment
00757 //    name= data #comment
00758 //    name =data #comment
00759 //    name = data #comment
00760 //    name data1 data2 data3 #comment
00761 //    name=data1 data2 data3 #comment
00762 //    name= data1 data2 data3 #comment
00763 //    name =data1 data2 data3 #comment
00764 //    name = data1 data2 data3 #comment
00765 //    name { data1 data2 data3 } #comment
00766 //    name { data1 data2 data3 } #comment
00767 //    name { data1 data2 # data3 } #comment
00768 //    name {data1 data2 # data3 } #comment
00769 // Do not try to handle "data#comment" in any form.
00770 // The '#' start of any comments will *always* be a new argv.
00771 // The name will *always* be contained in argv[1].
00772 
00773   // allocate storage for data string
00774   int arglen = 1;  int ai;
00775   for (ai=1; ai<argc; ++ai) { arglen += strlen(argv[ai]) + 1; }
00776   char *data = new char[arglen];  *data = 0;
00777   char *name = new char[arglen];  *name = 0;
00778 
00779   // find the end of the name
00780   const char *s = argv[1];
00781   char *sn = name;
00782   for ( ; *s && *s != '='; *(sn++) = *(s++) );
00783   *sn = 0;
00784 
00785   // eliminate any comment
00786   for (ai=2; ai<argc; ++ai) { if (argv[ai][0] == '#') argc = ai; }
00787 
00788   // concatenate all the data items
00789   ai = 2;
00790   if ( *s ) { ++s; strcat(data,s); }  // name=data or name=
00791   else if ( ai < argc && argv[ai][0] == '=' ) {  // name =data or name =
00792     strcat(data,argv[ai]+1);
00793     ++ai;
00794   }
00795   for ( ; ai<argc; ++ai) {
00796     if ( data[0] ) { strcat(data," "); }
00797     strcat(data,argv[ai]);
00798   }
00799 
00800   if ( ! *name ) {
00801     delete [] data;
00802     delete [] name;
00803     Tcl_SetResult(interp,"error parsing config file",TCL_VOLATILE);
00804     return TCL_ERROR;
00805   }
00806 
00807   ScriptTcl *script = (ScriptTcl *)clientData;
00808 
00809   if ( *data ) {
00810     script->config->add_element( name, strlen(name), data, strlen(data) );
00811     delete [] data;
00812     delete [] name;
00813     return TCL_OK;
00814   }
00815   delete [] data;
00816 
00817   StringList *strlist = script->config->find(name);
00818   delete [] name;
00819 
00820   if ( ! strlist ) {
00821     Tcl_SetResult(interp,"tried before startup to read config file parameter that was not set",TCL_VOLATILE);
00822     return TCL_ERROR;
00823   }
00824   Tcl_SetResult(interp,strlist->data,TCL_VOLATILE);
00825   return TCL_OK;
00826 }
00827 
00828 int ScriptTcl::Tcl_isset_config(ClientData clientData,
00829         Tcl_Interp *interp, int argc, const char *argv[]) {
00830   if (argc != 2) {
00831     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00832     return TCL_ERROR;
00833   }
00834 
00835   const char *param = argv[1];
00836   ScriptTcl *script = (ScriptTcl *)clientData;
00837   StringList *strlist = script->config->find(param);
00838   Tcl_SetResult(interp, (char*)(strlist ? "1" : "0"), TCL_VOLATILE);
00839   return TCL_OK;
00840 }
00841 
00842 static int atoBool(const char *s)
00843 {
00844    if (!strcasecmp(s, "on")) return 1;
00845    if (!strcasecmp(s, "off")) return 0;
00846    if (!strcasecmp(s, "true")) return 1;
00847    if (!strcasecmp(s, "false")) return 0;
00848    if (!strcasecmp(s, "yes")) return 1;
00849    if (!strcasecmp(s, "no")) return 0;
00850    if (!strcasecmp(s, "1")) return 1;
00851    if (!strcasecmp(s, "0")) return 0;
00852    return -1;
00853 }
00854 
00855 int ScriptTcl::Tcl_istrue_config(ClientData clientData,
00856         Tcl_Interp *interp, int argc, const char *argv[]) {
00857   if (argc != 2) {
00858     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00859     return TCL_ERROR;
00860   }
00861 
00862   const char *param = argv[1];
00863   ScriptTcl *script = (ScriptTcl *)clientData;
00864   StringList *strlist = script->config->find(param);
00865   if ( ! strlist ) {
00866     Tcl_SetResult(interp,"parameter value is not set",TCL_VOLATILE);
00867     return TCL_ERROR;
00868   }
00869   int val = atoBool(strlist->data);
00870   if ( val < 0 ) {
00871     Tcl_SetResult(interp,"parameter value is not boolean",TCL_VOLATILE);
00872     return TCL_ERROR;
00873   }
00874   Tcl_SetResult(interp, (char*)(val ? "1" : "0"), TCL_VOLATILE);
00875   return TCL_OK;
00876 }
00877 
00878 int ScriptTcl::Tcl_istrue_param(ClientData clientData,
00879         Tcl_Interp *interp, int argc, const char *argv[]) {
00880   if (argc != 2) {
00881     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00882     return TCL_ERROR;
00883   }
00884 
00885   const char *param = argv[1];
00886   SimParameters *simParams = Node::Object()->simParameters;
00887   int val = simParams->istrueinparseopts(param);
00888   if ( val == -1 ) {
00889     Tcl_SetResult(interp,"unknown parameter",TCL_VOLATILE);
00890     return TCL_ERROR;
00891   }
00892   if ( val == -2 ) {
00893     Tcl_SetResult(interp,"parameter is not boolean",TCL_VOLATILE);
00894     return TCL_ERROR;
00895   }
00896   if ( val == -3 ) {
00897     Tcl_SetResult(interp,"parameter value is not set",TCL_VOLATILE);
00898     return TCL_ERROR;
00899   }
00900   if ( val != 0 && val != 1 ) {
00901     Tcl_SetResult(interp,"bug in Tcl_istrue_param",TCL_VOLATILE);
00902     return TCL_ERROR;
00903   }
00904   Tcl_SetResult(interp, (char*)(val ? "1" : "0"), TCL_VOLATILE);
00905   return TCL_OK;
00906 }
00907 
00908 int ScriptTcl::Tcl_isset_param(ClientData clientData,
00909         Tcl_Interp *interp, int argc, const char *argv[]) {
00910   if (argc != 2) {
00911     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00912     return TCL_ERROR;
00913   }
00914 
00915   const char *param = argv[1];
00916   SimParameters *simParams = Node::Object()->simParameters;
00917   int val = simParams->issetinparseopts(param);
00918   if ( val < 0 ) {
00919     Tcl_SetResult(interp,"unknown parameter",TCL_VOLATILE);
00920     return TCL_ERROR;
00921   }
00922   Tcl_SetResult(interp, (char*)(val ? "1" : "0"), TCL_VOLATILE);
00923   return TCL_OK;
00924 }
00925 
00926 int ScriptTcl::Tcl_param(ClientData clientData,
00927         Tcl_Interp *interp, int argc, const char *argv[]) {
00928   if (argc != 2 && argc != 3 && argc != 5) {
00929     Tcl_SetResult(interp,"wrong # args for NAMD config parameter",TCL_VOLATILE);
00930     return TCL_ERROR;
00931   }
00932 
00933   const char *param = argv[1];
00934   if ( strlen(param) + 1 > MAX_SCRIPT_PARAM_SIZE ) {
00935     Tcl_SetResult(interp,"parameter name too long for NAMD config parameter",TCL_VOLATILE);
00936     return TCL_ERROR;
00937   }
00938 
00939   if ( argc == 2 ) { // get param value
00940     char buf[MAX_SCRIPT_PARAM_SIZE];
00941     SimParameters *simParams = Node::Object()->simParameters;
00942     char *result = simParams->getfromparseopts(param,buf);
00943     if ( result ) {
00944       Tcl_SetResult(interp, result,TCL_VOLATILE);
00945       return TCL_OK;
00946     } else {
00947       Tcl_SetResult(interp,"parameter unknown for NAMD config parameter",TCL_VOLATILE);
00948       return TCL_ERROR;
00949     }
00950   }
00951 
00952   char value[MAX_SCRIPT_PARAM_SIZE];
00953   int arglen = strlen(argv[2]) + 1;
00954   if ( argc == 5 ) arglen += strlen(argv[3]) + strlen(argv[4]) + 2;
00955   if ( arglen > MAX_SCRIPT_PARAM_SIZE ) {
00956     Tcl_SetResult(interp,"parameter value too long for NAMD config parameter",TCL_VOLATILE);
00957     return TCL_ERROR;
00958   }
00959   if ( argc == 3 ) sprintf(value,"%s",argv[2]);
00960   if ( argc == 5 ) sprintf(value,"%s %s %s",argv[2],argv[3],argv[4]);
00961 
00962   iout << "TCL: Setting parameter " << param << " to " << value << "\n" << endi;
00963 
00964   ScriptTcl *script = (ScriptTcl *)clientData;
00965   script->setParameter(param,value);
00966 
00967   // deal with some possible specifics
00968   if ( ! strncasecmp(param,"soluteScalingFactor",MAX_SCRIPT_PARAM_SIZE) ||
00969        ! strncasecmp(param,"soluteScalingFactorCharge",MAX_SCRIPT_PARAM_SIZE)) {
00970     script->runController(SCRIPT_RESCALESOLUTECHARGES);
00971   }
00972 
00973   return TCL_OK;
00974 }
00975 
00976 int ScriptTcl::Tcl_reinitvels(ClientData clientData,
00977         Tcl_Interp *interp, int argc, const char *argv[]) {
00978   ScriptTcl *script = (ScriptTcl *)clientData;
00979   script->initcheck();
00980   if (argc != 2) {
00981     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00982     return TCL_ERROR;
00983   }
00984   const char *temp = argv[1];
00985 
00986   script->setParameter("initialTemp",temp);
00987 
00988   script->runController(SCRIPT_REINITVELS);
00989 
00990   return TCL_OK;
00991 }
00992 
00993 int ScriptTcl::Tcl_rescalevels(ClientData clientData,
00994         Tcl_Interp *interp, int argc, const char *argv[]) {
00995   ScriptTcl *script = (ScriptTcl *)clientData;
00996   script->initcheck();
00997   if (argc != 2) {
00998     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00999     return TCL_ERROR;
01000   }
01001   const char *factor = argv[1];
01002 
01003   script->setParameter("scriptArg1",factor);
01004 
01005   script->runController(SCRIPT_RESCALEVELS);
01006 
01007   return TCL_OK;
01008 }
01009 
01010 int ScriptTcl::Tcl_run(ClientData clientData,
01011         Tcl_Interp *interp, int argc, const char *argv[]) {
01012   ScriptTcl *script = (ScriptTcl *)clientData;
01013   script->initcheck();
01014   if (argc < 2) {
01015     Tcl_SetResult(interp,"too few args",TCL_VOLATILE);
01016     return TCL_ERROR;
01017   }
01018   if (argc > 3) {
01019     Tcl_SetResult(interp,"too many args",TCL_VOLATILE);
01020     return TCL_ERROR;
01021   }
01022   int norepeat = 0;
01023   if (argc == 3) {
01024     if ( ! strcmp(argv[1], "norepeat") ) {
01025       if ( script->runWasCalled ) { norepeat = 1; }
01026     } else {
01027       Tcl_SetResult(interp,
01028         "first arg not norepeat",TCL_VOLATILE);
01029       return TCL_ERROR;
01030     }
01031   }
01032   int numstepsarg = argc-1;
01033   int numsteps;
01034   if (Tcl_GetInt(interp,argv[numstepsarg],&numsteps) != TCL_OK) {
01035     return TCL_ERROR;
01036   }
01037   if (numsteps < 0) {
01038     Tcl_SetResult(interp,"number of steps must be non-negative",TCL_VOLATILE);
01039     return TCL_ERROR;
01040   }
01041   SimParameters *simParams = Node::Object()->simParameters;
01042   if (numsteps && simParams->firstTimestep % simParams->stepsPerCycle) {
01043     Tcl_SetResult(interp,"firstTimestep must be a multiple of stepsPerCycle",TCL_VOLATILE);
01044     return TCL_ERROR;
01045   }
01046   if (numsteps % simParams->stepsPerCycle) {
01047     Tcl_SetResult(interp,"number of steps must be a multiple of stepsPerCycle",TCL_VOLATILE);
01048     return TCL_ERROR;
01049   }
01050   if ( simParams->minimizeCGOn ) {
01051     Tcl_SetResult(interp,"run called with minimization enabled; use minimize command instead",TCL_VOLATILE);
01052     return TCL_ERROR;
01053   }
01054   if ( simParams->N != simParams->firstTimestep ) {
01055     iout << "TCL: Original numsteps " << simParams->N
01056          << " will be ignored.\n";
01057   }
01058   iout << "TCL: Running for " << numsteps << " steps";
01059   if ( norepeat ) iout << " without repeating first step";
01060   iout << "\n" << endi;
01061 
01062   script->setParameter("numsteps",simParams->firstTimestep + numsteps);
01063 
01064   script->runController(norepeat ? SCRIPT_CONTINUE : SCRIPT_RUN);
01065   script->runWasCalled = 1;
01066 
01067   script->setParameter("firsttimestep",simParams->N);
01068 
01069   return TCL_OK;
01070 }
01071 
01072 int ScriptTcl::Tcl_minimize(ClientData clientData,
01073         Tcl_Interp *interp, int argc, const char *argv[]) {
01074   ScriptTcl *script = (ScriptTcl *)clientData;
01075   script->initcheck();
01076   if (argc != 2) {
01077     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01078     return TCL_ERROR;
01079   }
01080   int numsteps;
01081   if (Tcl_GetInt(interp,argv[1],&numsteps) != TCL_OK) {
01082     return TCL_ERROR;
01083   }
01084   if (numsteps < 0) {
01085     Tcl_SetResult(interp,"number of steps must be non-negative",TCL_VOLATILE);
01086     return TCL_ERROR;
01087   }
01088   SimParameters *simParams = Node::Object()->simParameters;
01089   if (numsteps && simParams->firstTimestep % simParams->stepsPerCycle) {
01090     Tcl_SetResult(interp,"firstTimestep must be a multiple of stepsPerCycle",TCL_VOLATILE);
01091     return TCL_ERROR;
01092   }
01093   if (numsteps % simParams->stepsPerCycle) {
01094     Tcl_SetResult(interp,"number of steps must be a multiple of stepsPerCycle",TCL_VOLATILE);
01095     return TCL_ERROR;
01096   }
01097   if ( simParams->N != simParams->firstTimestep ) {
01098     iout << "TCL: Original numsteps " << simParams->N
01099          << " will be ignored.\n";
01100   }
01101   iout << "TCL: Minimizing for " << numsteps << " steps\n" << endi;
01102 
01103   script->setParameter("numsteps",simParams->firstTimestep + numsteps);
01104 
01105   script->runController(SCRIPT_MINIMIZE);
01106   script->runWasCalled = 1;
01107 
01108   script->setParameter("firsttimestep",simParams->N);
01109 
01110   return TCL_OK;
01111 }
01112 
01113 // move all atoms by a given vector
01114 int ScriptTcl::Tcl_moveallby(ClientData clientData,
01115         Tcl_Interp *interp, int argc, const char *argv[]) {
01116   ScriptTcl *script = (ScriptTcl *)clientData;
01117   script->initcheck();
01118   if (argc != 2) {
01119     Tcl_SetResult(interp, "wrong # args", TCL_VOLATILE);
01120     return TCL_ERROR;
01121   }
01122   const char **fstring;
01123   int fnum;
01124   double x, y, z;
01125   if (Tcl_SplitList(interp, argv[1], &fnum, &fstring) != TCL_OK)
01126     return TCL_ERROR;
01127   if ( (fnum != 3) ||
01128        (Tcl_GetDouble(interp, fstring[0],&x) != TCL_OK) ||
01129        (Tcl_GetDouble(interp, fstring[1],&y) != TCL_OK) ||
01130        (Tcl_GetDouble(interp, fstring[2],&z) != TCL_OK) ) {
01131     Tcl_SetResult(interp,"argument not a vector",TCL_VOLATILE);
01132     Tcl_Free((char*)fstring);
01133     return TCL_ERROR;
01134   }
01135   Tcl_Free((char*)fstring);
01136 
01137   MoveAllByMsg *msg = new MoveAllByMsg;
01138   msg->offset = Vector(x,y,z);
01139   (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).moveAllBy(msg);
01140 
01141   script->barrier();
01142   return TCL_OK;
01143 }
01144 
01145 int ScriptTcl::Tcl_move(ClientData clientData,
01146         Tcl_Interp *interp, int argc, const char *argv[]) {
01147   ScriptTcl *script = (ScriptTcl *)clientData;
01148   script->initcheck();
01149   if (argc != 4) {
01150     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01151     return TCL_ERROR;
01152   }
01153   const char **fstring;  int fnum;  int atomid;  int moveto;  double x, y, z;
01154   if (Tcl_GetInt(interp,argv[1],&atomid) != TCL_OK) return TCL_ERROR;
01155   if (argv[2][0]=='t' && argv[2][1]=='o' && argv[2][2]==0) moveto = 1;
01156   else if (argv[2][0]=='b' && argv[2][1]=='y' && argv[2][2]==0) moveto = 0;
01157   else {
01158     Tcl_SetResult(interp,"syntax is 'move <id> to|by {<x> <y> <z>}'",TCL_VOLATILE);
01159     return TCL_ERROR;
01160   }
01161   if (Tcl_SplitList(interp, argv[3], &fnum, &fstring) != TCL_OK) {
01162     return TCL_ERROR;
01163   }
01164   if ( (fnum != 3) ||
01165        (Tcl_GetDouble(interp, fstring[0],&x) != TCL_OK) ||
01166        (Tcl_GetDouble(interp, fstring[1],&y) != TCL_OK) ||
01167        (Tcl_GetDouble(interp, fstring[2],&z) != TCL_OK) ) {
01168     Tcl_SetResult(interp,"third argument not a vector",TCL_VOLATILE);
01169     Tcl_Free((char*)fstring);
01170     return TCL_ERROR;
01171   }
01172   Tcl_Free((char*)fstring);
01173 
01174   SimParameters *simParams = Node::Object()->simParameters;
01175 
01176   iout << "TCL: Moving atom " << atomid << " ";
01177   if ( moveto ) iout << "to"; else iout << "by";
01178   iout << " " << Vector(x,y,z) << ".\n" << endi;
01179 
01180   MoveAtomMsg *msg = new MoveAtomMsg;
01181   msg->atomid = atomid - 1;
01182   msg->moveto = moveto;
01183   msg->coord = Vector(x,y,z);
01184   (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).moveAtom(msg);
01185 
01186   script->barrier();
01187 
01188   return TCL_OK;
01189 }
01190 
01191 int ScriptTcl::Tcl_output(ClientData clientData,
01192         Tcl_Interp *interp, int argc, const char *argv[]) {
01193   ScriptTcl *script = (ScriptTcl *)clientData;
01194   script->initcheck();
01195   if (argc < 2) {
01196     Tcl_SetResult(interp,"too few args",TCL_VOLATILE);
01197     return TCL_ERROR;
01198   }
01199   if (argc > 3) {
01200     Tcl_SetResult(interp,"too many args",TCL_VOLATILE);
01201     return TCL_ERROR;
01202   }
01203   int filenamearg = argc-1;
01204   if (strlen(argv[filenamearg]) > MAX_SCRIPT_PARAM_SIZE) {
01205     Tcl_SetResult(interp,"file name too long",TCL_VOLATILE);
01206     return TCL_ERROR;
01207   }
01208   int dorestart = 1;
01209   int doforces = 0;
01210   if (argc == 3) {
01211     if ( ! strcmp(argv[1], "withforces") ) {
01212       doforces = 1;
01213     } else if ( ! strcmp(argv[1], "onlyforces") ) {
01214       dorestart = 0;
01215       doforces = 1;
01216     } else {
01217       Tcl_SetResult(interp,
01218         "first arg not withforces or onlyforces",TCL_VOLATILE);
01219       return TCL_ERROR;
01220     }
01221   }
01222 
01223   SimParameters *simParams = Node::Object()->simParameters;
01224 
01225   char oldname[MAX_SCRIPT_PARAM_SIZE+1];
01226   strncpy(oldname,simParams->outputFilename,MAX_SCRIPT_PARAM_SIZE);
01227 
01228   script->setParameter("outputname",argv[filenamearg]);
01229 
01230   iout << "TCL: Writing to files with basename " <<
01231                 simParams->outputFilename << ".\n" << endi;
01232 
01233   if ( doforces && ! script->runWasCalled ) NAMD_die(
01234     "No forces to output; must call run or minimize first.");
01235 
01236   if ( dorestart ) script->runController(SCRIPT_OUTPUT);
01237   if ( doforces ) script->runController(SCRIPT_FORCEOUTPUT);
01238 
01239   script->setParameter("outputname",oldname);
01240 
01241   return TCL_OK;
01242 }
01243 
01244 void ScriptTcl::measure(Vector *c) {
01245   Measure::createCommands(interp);
01246   Node::Object()->coords = c;
01247   measure_result = Tcl_Eval(interp,measure_command);
01248   Node::Object()->coords = 0;
01249   Measure::deleteCommands(interp);
01250 }
01251 
01252 int ScriptTcl::Tcl_measure(ClientData clientData,
01253         Tcl_Interp *interp, int argc, const char *argv[]) {
01254   ScriptTcl *script = (ScriptTcl *)clientData;
01255   script->initcheck();
01256   if (argc != 2) {
01257     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01258     return TCL_ERROR;
01259   }
01260   script->measure_command = argv[1];
01261 
01262   script->runController(SCRIPT_MEASURE);
01263 
01264   return script->measure_result;
01265 }
01266 
01267 // NOTE: This interface is DEPRECATED
01268 // Please use the "cv bias" interface instead:
01269 
01270 // Replace "colvarbias changeconfig" with:
01271 // cv bias <name> delete
01272 // cv config <new_config_string>
01273 
01274 // Replace "colvarbias energydiff" with:
01275 // cv bias config <config_string_with_tempBias>
01276 // set ediff [expr [cv bias tempBias energy] - [cv bias refBias energy]]
01277 // cv bias tempBias delete
01278 
01279 int ScriptTcl::Tcl_colvarbias(ClientData clientData,
01280         Tcl_Interp *interp, int argc, const char *argv[]) {
01281   ScriptTcl *script = (ScriptTcl *)clientData;
01282   script->initcheck();
01283   if (argc < 4 || argc % 2) {
01284     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01285     return TCL_ERROR;
01286   }
01287   colvarmodule *colvars = Node::Object()->colvars;
01288   if ( ! colvars ) {
01289     Tcl_SetResult(interp,"colvars module not active",TCL_VOLATILE);
01290     return TCL_ERROR;
01291   }
01292   if ( ! strcmp(argv[1],"changeconfig") ) {
01293     for ( int i=2; i<argc; i+=2 ) {
01294       std::string name(argv[i]);
01295       std::string conf(argv[i+1]);
01296       colvars->change_configuration(name,conf);
01297     }
01298     return TCL_OK;
01299   } else if ( ! strcmp(argv[1],"energydiff") ) {
01300     if ( ! script->runWasCalled ) {
01301       Tcl_SetResult(interp,"energydiff requires a previous timestep",TCL_VOLATILE);
01302       return TCL_ERROR;
01303     }
01304     double ediff = 0.;
01305     for ( int i=2; i<argc; i+=2 ) {
01306       std::string name(argv[i]);
01307       std::string conf(argv[i+1]);
01308       ediff += colvars->energy_difference(name,conf);
01309     }
01310     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ediff));
01311     return TCL_OK;
01312   } else {
01313     Tcl_SetResult(interp,"unknown colvarbias operation",TCL_VOLATILE);
01314     return TCL_ERROR;
01315   }
01316 }
01317 
01318 // NOTE: This interface is DEPRECATED
01319 // Please use the "cv colvar" interface instead
01320 
01321 int ScriptTcl::Tcl_colvarvalue(ClientData clientData,
01322         Tcl_Interp *interp, int argc, const char *argv[]) {
01323   ScriptTcl *script = (ScriptTcl *)clientData;
01324   script->initcheck();
01325   if (argc != 2) {
01326     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01327     return TCL_ERROR;
01328   }
01329   colvarmodule *colvars = Node::Object()->colvars;
01330   if ( ! colvars ) {
01331     Tcl_SetResult(interp,"colvars module not active",TCL_VOLATILE);
01332     return TCL_ERROR;
01333   }
01334   // Pass the colvarvalue to Tcl
01335   std::string name(argv[1]);
01336   std::string value = colvars->read_colvar(name);
01337   // Process from a colvar list to a Tcl compatible list
01338   size_t found;
01339   do {
01340     found = value.find("(");
01341     if (found != std::string::npos) {
01342       value.replace(found, 1, " ");
01343     } else {
01344       break;
01345     }
01346   } while (true);
01347   do {
01348     found = value.find(")");
01349     if (found != std::string::npos) {
01350       value.replace(found, 1, " ");
01351     } else {
01352       break;
01353     }
01354   } while (true);
01355   do {
01356     found = value.find(",");
01357     if (found != std::string::npos) {
01358       value.replace(found, 1, " ");
01359     } else {
01360       break;
01361     }
01362   } while (true);
01363   // Send the result to Tcl
01364   Tcl_DString recvstr;
01365   Tcl_DStringInit(&recvstr);
01366   Tcl_DStringAppend(&recvstr,value.c_str(), -1);
01367   Tcl_DStringResult(interp, &recvstr);
01368   Tcl_DStringFree(&recvstr);
01369   return TCL_OK;
01370 }
01371 
01372 int ScriptTcl::Tcl_colvarfreq(ClientData clientData,
01373         Tcl_Interp *interp, int argc, const char *argv[]) {
01374   ScriptTcl *script = (ScriptTcl *)clientData;
01375   script->initcheck();
01376   if (argc != 2) {
01377     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01378     return TCL_ERROR;
01379   }
01380   colvarmodule *colvars = Node::Object()->colvars;
01381   if ( ! colvars ) {
01382     Tcl_SetResult(interp,"colvars module not active",TCL_VOLATILE);
01383     return TCL_ERROR;
01384   }
01385   int new_freq;
01386   if (Tcl_GetInt(interp,argv[1],&new_freq) != TCL_OK) {
01387     return TCL_ERROR;
01388   }
01389   colvars->cv_traj_freq = new_freq;
01390   return TCL_OK;
01391 }
01392 
01393 int ScriptTcl::Tcl_colvars(ClientData clientData,
01394                            Tcl_Interp *interp,
01395                            int objc,
01396                            Tcl_Obj *const objv[])
01397 {
01398   ScriptTcl *script = (ScriptTcl *) clientData;
01399   script->initcheck();
01400   colvarmodule *colvars = Node::Object()->colvars;
01401   if ( ! colvars ) {
01402     Tcl_SetResult(interp,"colvars module not active",TCL_VOLATILE);
01403     return TCL_ERROR;
01404   }
01405   colvarscript *cvscript = colvars->proxy->script;
01406   int retval = cvscript->run(objc, reinterpret_cast<unsigned char * const *>(objv));
01407 
01408   bool const no_errors = (retval == COLVARSCRIPT_OK) &&
01409     (cvm::get_error() == COLVARS_OK);
01410 
01411   Tcl_Obj *obj = Tcl_NewStringObj(cvscript->result.c_str(),
01412                                   cvscript->result.length());
01413   Tcl_SetObjResult(interp, obj);
01414 
01415   if (no_errors) {
01416     return TCL_OK;
01417   } else {
01418     return TCL_ERROR;
01419   }
01420 }
01421 
01422 int ScriptTcl::Tcl_checkpoint(ClientData clientData,
01423         Tcl_Interp *interp, int argc, const char *argv[]) {
01424   ScriptTcl *script = (ScriptTcl *)clientData;
01425   script->initcheck();
01426   if (argc != 1) {
01427     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01428     return TCL_ERROR;
01429   }
01430 
01431   script->runController(SCRIPT_CHECKPOINT);
01432 
01433   return TCL_OK;
01434 }
01435 
01436 int ScriptTcl::Tcl_revert(ClientData clientData,
01437         Tcl_Interp *interp, int argc, const char *argv[]) {
01438   ScriptTcl *script = (ScriptTcl *)clientData;
01439   script->initcheck();
01440   if (argc != 1) {
01441     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01442     return TCL_ERROR;
01443   }
01444 
01445   script->runController(SCRIPT_REVERT);
01446 
01447   return TCL_OK;
01448 }
01449 
01450 static int replica_hash(const char *key) {
01451   unsigned int hash = 0;
01452 
01453   while (*key) {
01454     hash *= 73;
01455     hash += *key++;
01456   }
01457 
01458   return hash % CmiNumPartitions();
01459 }
01460 
01461 int ScriptTcl::Tcl_checkpointReplica(ClientData clientData,
01462         Tcl_Interp *interp, int argc, const char *argv[]) {
01463   ScriptTcl *script = (ScriptTcl *)clientData;
01464   script->initcheck();
01465   if (argc < 2 || argc > 3) {
01466     Tcl_SetResult(interp,"args: <key> ?<replica> or global?",TCL_VOLATILE);
01467     return TCL_ERROR;
01468   }
01469   script->setParameter("scriptStringArg1", argv[1]);
01470   int replica = CmiMyPartition();
01471   if ( argc == 3 ) {
01472     if ( ! strcmp(argv[2],"global") ) {
01473       replica = replica_hash(argv[1]);
01474     } else if ( sscanf(argv[2],"%d",&replica) != 1 ) {
01475       Tcl_SetResult(interp,"args: <key> ?<replica> or global?",TCL_VOLATILE);
01476       return TCL_ERROR;
01477     }
01478   }
01479   if ( replica != CmiMyPartition() ) {
01480     if ( ! Node::Object()->simParameters->replicaUniformPatchGrids ) {
01481       Tcl_SetResult(interp,"replicaUniformPatchGrids is required for checkpointing on other replicas",TCL_VOLATILE);
01482       return TCL_ERROR;
01483     }
01484   }
01485 
01486   CHECK_REPLICA(replica);
01487   char str[40];
01488   sprintf(str, "%d", replica);
01489   script->setParameter("scriptIntArg1", str);
01490 
01491   CkpvAccess(_qd)->create(PatchMap::Object()->numPatches());
01492   if ( replica != CmiMyPartition() ) CkpvAccess(_qd)->create(1);
01493 
01494   if ( ! strcmp(argv[0],"checkpointStore") ) script->runController(SCRIPT_CHECKPOINT_STORE);
01495   else if ( ! strcmp(argv[0],"checkpointLoad") ) script->runController(SCRIPT_CHECKPOINT_LOAD);
01496   else if ( ! strcmp(argv[0],"checkpointSwap") ) script->runController(SCRIPT_CHECKPOINT_SWAP);
01497   else if ( ! strcmp(argv[0],"checkpointFree") ) script->runController(SCRIPT_CHECKPOINT_FREE);
01498   else {
01499     Tcl_SetResult(interp,"checkpointStore/Load/Swap/Free called via unrecognized name",TCL_VOLATILE);
01500     return TCL_ERROR;
01501   }
01502 
01503   return TCL_OK;
01504 }
01505 
01506 int ScriptTcl::Tcl_replicaDcdFile(ClientData clientData,
01507         Tcl_Interp *interp, int argc, const char *argv[]) {
01508 #ifdef MEM_OPT_VERSION
01509   Tcl_SetResult(interp,"replicaDcdFile not supported in memory-optimized builds",TCL_VOLATILE);
01510   return TCL_ERROR;
01511 #endif
01512   ScriptTcl *script = (ScriptTcl *)clientData;
01513   script->initcheck();
01514   int index;
01515   int cmpoff;
01516   if (argc < 2 || argc > 3 || ((cmpoff = strcmp(argv[1],"off")) != 0 && sscanf(argv[1],"%d",&index) != 1) ) {
01517     Tcl_SetResult(interp,"args: <index>|off ?<filename>?",TCL_VOLATILE);
01518     return TCL_ERROR;
01519   }
01520   if ( argc == 2 ) {
01521     if ( cmpoff == 0 ) Node::Object()->output->replicaDcdOff();
01522     else Node::Object()->output->setReplicaDcdIndex(index);
01523   } else if ( argc == 3 ) {
01524     Node::Object()->output->replicaDcdInit(index,argv[2]);
01525     script->barrier();
01526   }
01527   return TCL_OK;
01528 }
01529 
01530 int ScriptTcl::Tcl_callback(ClientData clientData,
01531         Tcl_Interp *interp, int argc, const char *argv[]) {
01532   ScriptTcl *script = (ScriptTcl *)clientData;
01533   if (argc != 2) {
01534     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01535     return TCL_ERROR;
01536   }
01537 
01538   delete [] script->callbackname;
01539   script->callbackname = new char[strlen(argv[1])+1];
01540   strcpy(script->callbackname,argv[1]);
01541 
01542   iout << "TCL: Reduction callback proc set to " <<
01543                         script->callbackname << "\n" << endi;
01544 
01545   return TCL_OK;
01546 }
01547 
01548 void ScriptTcl::doCallback(const char *labels, const char *data) {
01549   if ( ! callbackname ) return;
01550   int len = strlen(callbackname) + strlen(labels) + strlen(data) + 7;
01551   char *cmd = new char[len];
01552   sprintf(cmd, "%s {%s} {%s}", callbackname, labels, data);
01553   int rval = Tcl_Eval(interp,cmd);
01554   delete [] cmd;
01555   if (rval != TCL_OK) {
01556     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
01557     NAMD_die(errorInfo ? errorInfo : "Unknown Tcl error");
01558   }
01559 }
01560 
01561 extern void read_binary_coors(char *fname, PDB *pdbobj);
01562 
01563 int ScriptTcl::Tcl_reinitatoms(ClientData clientData,
01564         Tcl_Interp *interp, int argc, const char *argv[]) {
01565   ScriptTcl *script = (ScriptTcl *)clientData;
01566   script->initcheck();
01567   if (argc > 2) {
01568     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
01569     return TCL_ERROR;
01570   }
01571 
01572   if (argc == 1 ) {
01573     iout << "TCL: Reinitializing atom data\n" << endi;
01574     SimParameters *simParams = Node::Object()->simParameters;
01575     Controller *c = script->state->controller;
01576     script->state->lattice = c->origLattice;
01577     c->langevinPiston_strainRate = c->langevinPiston_origStrainRate;
01578     c->rescaleVelocities_sumTemps = 0;  c->rescaleVelocities_numTemps = 0;
01579     c->berendsenPressure_avg = 0; c->berendsenPressure_count = 0;
01580     SetLatticeMsg *msg = new SetLatticeMsg;
01581     msg->lattice = script->state->lattice;
01582     (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).setLattice(msg);
01583     script->barrier();
01584     if ( ! simParams->binaryOutput ) {  // output may have overwritten data in PDB
01585       StringList *coordinateFilename = script->state->configList->find("bincoordinates");
01586       if ( coordinateFilename ) {
01587         read_binary_coors(coordinateFilename->data, script->state->pdb);
01588       } else if (coordinateFilename = script->state->configList->find("coordinates")) {
01589         PDB coordpdb(coordinateFilename->data);
01590         if ( coordpdb.num_atoms() != script->state->pdb->num_atoms() ) {
01591           NAMD_die("inconsistent atom count on re-reading coordinates pdb file");
01592         }
01593         Vector *positions = new Position[coordpdb.num_atoms()];
01594         coordpdb.get_all_positions(positions);
01595         script->state->pdb->set_all_positions(positions);
01596         delete [] positions;
01597       } else {
01598         iout << iWARN << "reinitatoms may fail if pdb-format output has occurred\n" << endi;
01599       }
01600     }
01601     script->reinitAtoms();
01602     return TCL_OK;
01603   }
01604 
01605   iout << "TCL: Reinitializing atom data from files with basename " << argv[1] << "\n" << endi;
01606   SimParameters *simParams = Node::Object()->simParameters;
01607   simParams->readExtendedSystem((std::string(argv[1])+".xsc").c_str(), &(script->state->lattice));
01608   Controller *c = script->state->controller;
01609   c->langevinPiston_strainRate =
01610       Tensor::symmetric(simParams->strainRate,simParams->strainRate2);
01611   c->rescaleVelocities_sumTemps = 0;  c->rescaleVelocities_numTemps = 0;
01612   c->berendsenPressure_avg = 0; c->berendsenPressure_count = 0;
01613   SetLatticeMsg *msg = new SetLatticeMsg;
01614   msg->lattice = script->state->lattice;
01615   (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).setLattice(msg);
01616   script->barrier();
01617   script->reinitAtoms(argv[1]);
01618 
01619   return TCL_OK;
01620 }
01621 
01622 #define DEG2RAD 3.14159625359/180.0
01623 #define UNITCELLSLOP 0.0001
01624 
01625 static int get_lattice_from_ts(Lattice *lattice, const molfile_timestep_t *ts)
01626 {
01627   // Check if valid unit cell data is contained in the timestep.  We don't
01628   // have any formalized way of doing this yet; for now, just check that
01629   // the length of the vector is greater than 1.
01630   if (ts->A <= 1 || ts->B <= 1 || ts->C <= 1) return 0;
01631 
01632   // convert from degrees to radians
01633   // Try to get exact results when the angles are exactly 90.
01634   double epsalpha = DEG2RAD*(ts->alpha-90.0);
01635   double epsbeta  = DEG2RAD*(ts->beta-90.0);
01636   double epsgamma = DEG2RAD*(ts->gamma-90.0);
01637   double cosAB = -sin(epsgamma);
01638   double sinAB = cos(epsgamma);
01639   double cosAC = -sin(epsbeta);
01640   double cosBC = -sin(epsalpha);
01641 
01642   // A will lie along the positive x axis.
01643   // B will lie in the x-y plane
01644   // The origin will be (0,0,0).
01645   Vector A(0), B(0), vecC(0);
01646   A.x = ts->A;
01647   B.x = ts->B*cosAB;
01648   B.y = ts->B*sinAB;
01649   //if (fabs(B.x) < UNITCELLSLOP) B.x = 0;
01650   //if (fabs(B.y) < UNITCELLSLOP) B.y = 0;
01651   vecC.x = ts->C * cosAC;
01652   vecC.y = (ts->B*ts->C*cosBC - B.x*vecC.x)/B.y;
01653   vecC.z = sqrt(ts->C*ts->C - vecC.x*vecC.x - vecC.y*vecC.y);
01654   //if (fabs(vecC.x) < UNITCELLSLOP) vecC.x = 0;
01655   //if (fabs(vecC.y) < UNITCELLSLOP) vecC.y = 0;
01656   //if (fabs(vecC.z) < UNITCELLSLOP) vecC.z = 0;
01657   lattice->set(A, B, vecC, Vector(0));
01658   return 1;
01659 }
01660 
01661 int ScriptTcl::Tcl_coorfile(ClientData clientData,
01662         Tcl_Interp *interp, int argc, const char *argv[]) {
01663   ScriptTcl *script = (ScriptTcl *)clientData;
01664   script->initcheck();
01665   if (argc == 4 && !strcmp(argv[1], "open")) {
01666     if (strcmp(argv[2], "dcd")) {
01667       NAMD_die("Sorry, coorfile presently supports only DCD files");
01668     }
01669     filehandle = dcdplugin->open_file_read(argv[3], "dcd", &numatoms);
01670     if (!filehandle) {
01671       Tcl_AppendResult(interp, "coorfile: Error opening file ", argv[3], NULL);
01672       return TCL_ERROR;
01673     }
01674     if (numatoms != Node::Object()->pdb->num_atoms()) {
01675       Tcl_AppendResult(interp, "Coordinate file ", argv[3],
01676         "\ncontains the wrong number of atoms.", NULL);
01677       return TCL_ERROR;
01678     }
01679     coords = new float[3*numatoms];
01680     vcoords = new Vector[3*numatoms];
01681     iout << iINFO << "Coordinate file " << argv[3] << " opened for reading.\n"
01682          << endi;
01683   } else if (argc == 2 && !strcmp(argv[1], "read")) {
01684     if (filehandle == NULL) {
01685       Tcl_AppendResult(interp, "coorfile read: Error, no file open for reading",
01686         NULL);
01687       return TCL_ERROR;
01688     }
01689     molfile_timestep_t ts;
01690     ts.coords = coords;
01691     int rc = dcdplugin->read_next_timestep(filehandle, numatoms, &ts);
01692     if (rc) {  // EOF
01693       Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
01694       return TCL_OK;
01695     }
01696     iout << iINFO << "Reading timestep from file.\n" << endi;
01697     Lattice lattice;
01698     if (get_lattice_from_ts(&lattice, &ts)) {
01699       iout << iINFO << "Updating unit cell from timestep.\n" << endi;
01700       if ( lattice.a_p() && ! script->state->lattice.a_p() ||
01701            lattice.b_p() && ! script->state->lattice.b_p() ||
01702            lattice.c_p() && ! script->state->lattice.c_p() ) {
01703         iout << iWARN << "Cell basis vectors should be specified before reading trajectory.\n" << endi;
01704       }
01705       // update Controller's lattice, but don't change the origin!
01706       Vector a(0.);  if ( script->state->lattice.a_p() ) a = lattice.a();
01707       Vector b(0.);  if ( script->state->lattice.b_p() ) b = lattice.b();
01708       Vector c(0.);  if ( script->state->lattice.c_p() ) c = lattice.c();
01709       script->state->lattice.set(a,b,c);
01710       SetLatticeMsg *msg = new SetLatticeMsg;
01711       msg->lattice = script->state->lattice;
01712       (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).setLattice(msg);
01713       script->barrier();
01714     }
01715     for (int i=0; i<numatoms; i++) {
01716       vcoords[i].x = coords[3*i+0];
01717       vcoords[i].y = coords[3*i+1];
01718       vcoords[i].z = coords[3*i+2];
01719     }
01720     Node::Object()->pdb->set_all_positions(vcoords);
01721     script->reinitAtoms();
01722     Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
01723   } else if (argc == 2 && !strcmp(argv[1], "close")) {
01724     if (!filehandle) {
01725       Tcl_AppendResult(interp, "coorfile close: No file opened for reading!",
01726         NULL);
01727       return TCL_OK;
01728     }
01729     iout << iINFO << "Closing coordinate file.\n" << endi;
01730     dcdplugin->close_file_read(filehandle);
01731     filehandle = NULL;
01732     delete [] coords;
01733     delete [] vcoords;
01734 
01735   } else if (argc ==2 && !strcmp(argv[1], "skip")) {
01736     if (filehandle == NULL) {
01737       Tcl_AppendResult(interp, "coorfile skip: Error, no file open for reading",
01738         NULL);
01739       return TCL_ERROR;
01740     }
01741     int rc = dcdplugin->read_next_timestep(filehandle, numatoms, NULL);
01742     if (rc) {  // EOF
01743       Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
01744       return TCL_OK;
01745     }
01746     Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
01747 
01748   } else {
01749     NAMD_die("Unknown option passed to coorfile");
01750   }
01751   return TCL_OK;
01752 }
01753 
01754 int ScriptTcl::Tcl_dumpbench(ClientData clientData,
01755         Tcl_Interp *interp, int argc, const char *argv[]) {
01756   ScriptTcl *script = (ScriptTcl *)clientData;
01757   script->initcheck();
01758   if (argc != 2) {
01759     Tcl_AppendResult(interp, "usage: dumpbench <filename>", NULL);
01760     return TCL_ERROR;
01761   }
01762 
01763   if ( CkNumPes() != 1 ) {
01764     Tcl_AppendResult(interp, "multiple processors detected; dumpbench only works on serial runs", NULL);
01765     return TCL_ERROR;
01766   }
01767 
01768   FILE *file = fopen(argv[1],"w");
01769   if ( ! file ) {
01770     Tcl_AppendResult(interp, "dumpbench: error opening file ", argv[1], NULL);
01771     return TCL_ERROR;
01772   }
01773 
01774   if ( dumpbench(file) ) {
01775     Tcl_AppendResult(interp, "dumpbench: error dumping benchmark data", NULL);
01776     return TCL_ERROR;
01777   }
01778 
01779   fclose(file);
01780 
01781   Tcl_AppendResult(interp, "benchmark data written to file ", argv[1], NULL);
01782   return TCL_OK;
01783 }
01784 
01785 #include "ComputeConsForceMsgs.h"
01786 // consforceconfig <atomids> <forces>
01787 int ScriptTcl::Tcl_consForceConfig(ClientData clientData,
01788     Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
01789   ScriptTcl *script = (ScriptTcl *)clientData;
01790   script->initcheck();
01791   if ( ! Node::Object()->simParameters->consForceOn ) {
01792     Tcl_AppendResult(interp, "consForceConfig requires constantForce on", NULL);
01793     return TCL_ERROR;
01794   }
01795   if (objc != 3) {
01796     Tcl_WrongNumArgs(interp, 1, objv, (char *)"<atomids> <forces>");
01797     return TCL_ERROR;
01798   }
01799   int natoms, nforces;
01800   Tcl_Obj **atomobjlist, **forceobjlist;
01801   if (Tcl_ListObjGetElements(interp, objv[1], &natoms, &atomobjlist) != TCL_OK ||
01802       Tcl_ListObjGetElements(interp, objv[2], &nforces, &forceobjlist) != TCL_OK) {
01803     return TCL_ERROR;
01804   }
01805   if (natoms != nforces) {
01806     Tcl_AppendResult(interp, (char *)"consforceconfig: atom list and force list not the same size!", NULL);
01807     return TCL_ERROR;
01808   }
01809   ComputeConsForceMsg *msg = new ComputeConsForceMsg;
01810   for (int i=0; i<natoms; i++) {
01811     int atomid;
01812     int nelem;
01813     Tcl_Obj **elemlist;
01814     Vector force;
01815     if (Tcl_GetIntFromObj(interp, atomobjlist[i], &atomid) != TCL_OK)
01816       return TCL_ERROR;
01817     if (Tcl_ListObjGetElements(interp, forceobjlist[i], &nelem, &elemlist) != TCL_OK)
01818       return TCL_ERROR;
01819     if (nelem != 3) {
01820       Tcl_AppendResult(interp, (char *)"consforceconfig: forces must have three elements", NULL);
01821       return TCL_ERROR;
01822     }
01823     if (Tcl_GetDoubleFromObj(interp, elemlist[0], &force.x) != TCL_OK ||
01824         Tcl_GetDoubleFromObj(interp, elemlist[1], &force.y) != TCL_OK ||
01825         Tcl_GetDoubleFromObj(interp, elemlist[2], &force.z) != TCL_OK) {
01826       return TCL_ERROR;
01827     }
01828     msg->aid.add(atomid);
01829     msg->f.add(force);
01830   }
01831   (CProxy_ComputeMgr(CkpvAccess(BOCclass_group).computeMgr)).recvComputeConsForceMsg(msg);
01832   return TCL_OK;
01833 }
01834 
01835 int ScriptTcl::Tcl_reloadCharges(ClientData clientData,
01836         Tcl_Interp *interp, int argc, const char *argv[]) {
01837   ScriptTcl *script = (ScriptTcl *)clientData;
01838   script->initcheck();
01839   if (argc != 2) {
01840     Tcl_AppendResult(interp, "usage: reloadCharges <filename>", NULL);
01841     return TCL_ERROR;
01842   }
01843 
01844   Node::Object()->reloadCharges(argv[1]);
01845 
01846   script->runController(SCRIPT_RELOADCHARGES);
01847 
01848   return TCL_OK;
01849 }
01850 
01851 // BEGIN gf
01852 int ScriptTcl::Tcl_reloadGridforceGrid(ClientData clientData,
01853         Tcl_Interp *interp, int argc, const char *argv[]) {
01854   ScriptTcl *script = (ScriptTcl *)clientData;
01855   script->initcheck();
01856 
01857   const char *key = NULL;
01858   if (argc == 1) {
01859       // nothing ... key is NULL, then Node::reloadGridforceGrid uses the
01860       // default key, which is used internally when the gridforce*
01861       // keywords are used (as opposed to the mgridforce* keywords)
01862   } else if (argc == 2) {
01863       key = argv[1];
01864   } else {
01865       Tcl_AppendResult(interp, "usage: reloadGridforceGrid [<gridkey>]", NULL);
01866       return TCL_ERROR;
01867   }
01868 
01869   //(CProxy_Node(CkpvAccess(BOCclass_group).node)).reloadGridforceGrid(key);
01870   Node::Object()->reloadGridforceGrid(key);
01871   script->barrier();
01872 
01873   return TCL_OK;
01874 }
01875 
01876 int ScriptTcl::Tcl_updateGridScale(ClientData clientData,
01877         Tcl_Interp *interp, int argc, const char *argv[]) {
01878   ScriptTcl *script = (ScriptTcl *)clientData;
01879   script->initcheck();
01880 
01881   Vector scale(1.0f,1.0f,1.0f);
01882   const char *key = NULL;
01883   if (argc == 4) {
01884       // nothing ... key is NULL, then Node::updateGridScale uses the
01885       // default key, which is used internally when the gridforce*
01886       // keywords are used (as opposed to the mgridforce* keywords)
01887       scale.x = atof( argv[1] );
01888       scale.y = atof( argv[2] );
01889       scale.z = atof( argv[3] );
01890   } else if (argc == 5) {
01891       key = argv[1];
01892       scale.x = atof( argv[2] );
01893       scale.y = atof( argv[3] );
01894       scale.z = atof( argv[4] );
01895   } else {
01896       Tcl_AppendResult(interp, "usage: updateGridforceGrid [<gridkey>] scaleX scaleY scaleZ", NULL);
01897       return TCL_ERROR;
01898   }
01899 
01900   //(CProxy_Node(CkpvAccess(BOCclass_group).node)).reloadGridforceGrid(key);
01901   Node::Object()->updateGridScale(key,scale);
01902   script->barrier();
01903 
01904   return TCL_OK;
01905 }
01906 // END gf
01907 
01908 int ScriptTcl::Tcl_reloadStructure(ClientData clientData,
01909         Tcl_Interp *interp, int argc, const char *argv[]) {
01910   ScriptTcl *script = (ScriptTcl *)clientData;
01911   script->initcheck();
01912 
01913   if ( argc == 1 ) { // get param value
01914     char buf[MAX_SCRIPT_PARAM_SIZE];
01915     SimParameters *simParams = Node::Object()->simParameters;
01916     char *result = simParams->getfromparseopts("structure",buf);
01917     if ( result ) {
01918       Tcl_SetResult(interp, result,TCL_VOLATILE);
01919       return TCL_OK;
01920     } else {
01921       Tcl_SetResult(interp,"unknown structure",TCL_VOLATILE);
01922       return TCL_ERROR;
01923     }
01924   }
01925 
01926   int ok = 0;
01927   if (argc == 2) ok = 1;
01928   if (argc == 4 && ! strcmp(argv[2],"pdb")) ok = 1;
01929   if (! ok) {
01930     Tcl_AppendResult(interp, "usage: structure <filename> [pdb] <filename>", NULL);
01931     return TCL_ERROR;
01932   }
01933 
01934   iout << "TCL: Reloading molecular structure from file " << argv[1];
01935   if ( argc == 4 ) iout << " and pdb file " << argv[3];
01936   iout << "\n" << endi;
01937   script->config->find("structure")->set(argv[1]);
01938   if (argc == 4) script->config->find("coordinates")->set(argv[3]);
01939   Node::Object()->reloadStructure(argv[1], (argc == 4) ? argv[3] : 0);
01940 
01941   script->barrier();
01942 
01943   // return Tcl_reinitatoms(clientData, interp, argc-1, argv+1);
01944 
01945   return TCL_OK;
01946 }
01947 
01948 
01949 extern "C" void newhandle_msg(void *v, const char *msg) {
01950   CkPrintf("psfgen) %s\n",msg);
01951 }
01952 
01953 extern "C" void newhandle_msg_ex(void *v, const char *msg, int prepend, int newline) {
01954   CkPrintf("%s%s%s", (prepend ? "psfgen) " : ""), msg, (newline ? "\n" : ""));
01955 }
01956 
01957 extern "C" int psfgen_static_init(Tcl_Interp *);
01958 
01959 int eabf_static_init(Tcl_Interp *);
01960 
01961 
01962 #endif  // NAMD_TCL
01963 
01964 
01965 ScriptTcl::ScriptTcl() : scriptBarrier(scriptBarrierTag) {
01966   DebugM(3,"Constructing ScriptTcl\n");
01967 #ifdef NAMD_TCL
01968   interp = 0;
01969   callbackname = 0;
01970 #endif
01971   state = new NamdState;
01972   barrierStep = 0;
01973 
01974   molfile_dcdplugin_init();
01975   molfile_dcdplugin_register(NULL, register_cb);
01976 
01977   initWasCalled = 0;
01978   runWasCalled = 0;
01979 
01980 #ifdef NAMD_TCL
01981   config = new ConfigList;
01982 
01983   // Create interpreter
01984   interp = Tcl_CreateInterp();
01985   psfgen_static_init(interp);
01986   eabf_static_init(interp);
01987   tcl_vector_math_init(interp);
01988   Tcl_CreateCommand(interp, "python", Tcl_python,
01989     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01990   Tcl_CreateCommand(interp, "startup", Tcl_startup,
01991     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01992   Tcl_CreateCommand(interp, "exit", Tcl_exit,
01993     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01994   Tcl_CreateCommand(interp, "abort", Tcl_abort,
01995     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01996   Tcl_CreateCommand(interp, "numPes", Tcl_numPes,
01997     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01998   Tcl_CreateCommand(interp, "numNodes", Tcl_numNodes,
01999     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02000   Tcl_CreateCommand(interp, "numPhysicalNodes", Tcl_numPhysicalNodes,
02001     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02002   Tcl_CreateCommand(interp, "numReplicas", Tcl_numReplicas,
02003     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02004   Tcl_CreateCommand(interp, "myReplica", Tcl_myReplica,
02005     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02006   Tcl_CreateCommand(interp, "replicaEval", Tcl_replicaEval,
02007     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02008   Tcl_CreateCommand(interp, "replicaYield", Tcl_replicaYield,
02009     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02010   Tcl_CreateCommand(interp, "replicaSendrecv", Tcl_replicaSendrecv,
02011     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02012   Tcl_CreateCommand(interp, "replicaSend", Tcl_replicaSend,
02013     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02014   Tcl_CreateCommand(interp, "replicaRecv", Tcl_replicaRecv,
02015     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02016   Tcl_CreateCommand(interp, "replicaBarrier", Tcl_replicaBarrier,
02017     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02018   Tcl_CreateCommand(interp, "replicaAtomSendrecv", Tcl_replicaAtomSendrecv,
02019     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02020   Tcl_CreateCommand(interp, "replicaAtomSend", Tcl_replicaAtomSend,
02021     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02022   Tcl_CreateCommand(interp, "replicaAtomRecv", Tcl_replicaAtomRecv,
02023     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02024   Tcl_CreateCommand(interp, "stdout", Tcl_stdout,
02025     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02026   Tcl_CreateCommand(interp, "print", Tcl_print,
02027     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
02028   Tcl_CreateCommand(interp, "unknown", Tcl_config,
02029     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02030   Tcl_CreateCommand(interp, "param", Tcl_config,
02031     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02032   Tcl_CreateCommand(interp, "isset", Tcl_isset_config,
02033     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02034   Tcl_CreateCommand(interp, "istrue", Tcl_istrue_config,
02035     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02036   Tcl_CreateCommand(interp, "run", Tcl_run,
02037     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02038   Tcl_CreateCommand(interp, "minimize", Tcl_minimize,
02039     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02040   Tcl_CreateCommand(interp, "move", Tcl_move,
02041     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02042   Tcl_CreateCommand(interp, "moveallby", Tcl_moveallby,
02043     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02044   Tcl_CreateCommand(interp, "output", Tcl_output,
02045     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02046   Tcl_CreateCommand(interp, "measure", Tcl_measure,
02047     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02048   Tcl_CreateCommand(interp, "colvarbias", Tcl_colvarbias,
02049     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02050   Tcl_CreateCommand(interp, "colvarvalue", Tcl_colvarvalue,
02051     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02052   Tcl_CreateObjCommand(interp, "cv", Tcl_colvars,
02053     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02054   Tcl_CreateCommand(interp, "colvarfreq", Tcl_colvarfreq,
02055     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02056   Tcl_CreateCommand(interp, "checkpoint", Tcl_checkpoint,
02057     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02058   Tcl_CreateCommand(interp, "revert", Tcl_revert,
02059     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02060   Tcl_CreateCommand(interp, "checkpointStore", Tcl_checkpointReplica,
02061     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02062   Tcl_CreateCommand(interp, "checkpointLoad", Tcl_checkpointReplica,
02063     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02064   Tcl_CreateCommand(interp, "checkpointSwap", Tcl_checkpointReplica,
02065     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02066   Tcl_CreateCommand(interp, "checkpointFree", Tcl_checkpointReplica,
02067     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02068   Tcl_CreateCommand(interp, "reinitvels", Tcl_reinitvels,
02069     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02070   Tcl_CreateCommand(interp, "rescalevels", Tcl_rescalevels,
02071     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02072   Tcl_CreateCommand(interp, "reinitatoms", Tcl_reinitatoms,
02073     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02074   Tcl_CreateCommand(interp, "replicaDcdFile", Tcl_replicaDcdFile,
02075     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02076   Tcl_CreateCommand(interp, "callback", Tcl_callback,
02077     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02078   Tcl_CreateCommand(interp, "coorfile", Tcl_coorfile,
02079     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02080   Tcl_CreateCommand(interp, "dumpbench", Tcl_dumpbench,
02081     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02082   Tcl_CreateObjCommand(interp, "consForceConfig", Tcl_consForceConfig,
02083     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02084   Tcl_CreateCommand(interp, "reloadCharges", Tcl_reloadCharges,
02085     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02086   // BEGIN gf
02087   Tcl_CreateCommand(interp, "reloadGridforceGrid", Tcl_reloadGridforceGrid,
02088     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02089   Tcl_CreateCommand(interp, "updateGridScale", Tcl_updateGridScale,
02090     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
02091   // END gf
02092 #endif
02093 
02094 }
02095 
02096 int ScriptTcl::eval(const char *script, const char **resultPtr) {
02097 
02098 #ifdef NAMD_TCL
02099   int code = Tcl_EvalEx(interp,script,-1,TCL_EVAL_GLOBAL);
02100   *resultPtr = Tcl_GetStringResult(interp);
02101   return code;
02102 #else
02103   NAMD_bug("ScriptTcl::eval called without Tcl.");
02104   return -1;  // appease compiler
02105 #endif
02106 }
02107 
02108 void ScriptTcl::eval(char *script) {
02109 
02110 #ifdef NAMD_TCL
02111   int code = Tcl_Eval(interp,script);
02112   const char *result = Tcl_GetStringResult(interp);
02113   if (*result != 0) CkPrintf("TCL: %s\n",result);
02114   if (code != TCL_OK) {
02115     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
02116     NAMD_die(errorInfo ? errorInfo : "Unknown Tcl error");
02117   }
02118 #else
02119   NAMD_bug("ScriptTcl::eval called without Tcl.");
02120 #endif
02121 
02122 }
02123 
02124 
02125 #ifdef NAMD_TCL
02126 int ScriptTcl::tclsh(int argc, char **argv) {
02127   Tcl_Interp *interp = Tcl_CreateInterp();
02128   psfgen_static_init(interp);
02129   eabf_static_init(interp);
02130   tcl_vector_math_init(interp);
02131   Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY);
02132   Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc-1), TCL_GLOBAL_ONLY);
02133   Tcl_Obj *argvPtr = Tcl_NewListObj(0, NULL);
02134   for ( int i=1; i<argc; ++i ) {
02135     Tcl_ListObjAppendElement(NULL, argvPtr, Tcl_NewStringObj(argv[i],-1));
02136   }
02137   Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
02138   int code = Tcl_EvalFile(interp,argv[0]);
02139   if (code != TCL_OK) {
02140     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
02141     fprintf(stderr,"%s\n",(errorInfo ? errorInfo : "Unknown Tcl error"));
02142     return -1;
02143   }
02144   return 0;
02145 }
02146 
02147 
02148 void ScriptTcl::tclmain(int argc, char **argv) {
02149   Tcl_SetVar(interp, "argv0", argv[0], TCL_GLOBAL_ONLY);
02150   Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewIntObj(argc-1), TCL_GLOBAL_ONLY);
02151   Tcl_Obj *argvPtr = Tcl_NewListObj(0, NULL);
02152   for ( int i=1; i<argc; ++i ) {
02153     Tcl_ListObjAppendElement(NULL, argvPtr, Tcl_NewStringObj(argv[i],-1));
02154   }
02155   Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY);
02156   int code = Tcl_EvalFile(interp,argv[0]);
02157   if (code != TCL_OK) {
02158     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
02159     NAMD_die(errorInfo ? errorInfo : "Unknown Tcl error");
02160   }
02161 }
02162 #endif
02163 
02164 
02165 void ScriptTcl::load(char *scriptFile) {
02166 
02167 #ifdef NAMD_TCL
02168   int code = Tcl_EvalFile(interp,scriptFile);
02169   const char *result = Tcl_GetStringResult(interp);
02170   if (*result != 0) CkPrintf("TCL: %s\n",result);
02171   if (code != TCL_OK) {
02172     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
02173     NAMD_die(errorInfo ? errorInfo : "Unknown Tcl error");
02174   }
02175 #else
02176   NAMD_bug("ScriptTcl::load called without Tcl.");
02177 #endif
02178 
02179 }
02180 
02181 #ifdef NAMD_TCL
02182 void ScriptTcl::run() {
02183 #else
02184 void ScriptTcl::run(char *scriptFile) {
02185 
02186   if ( NULL == scriptFile || NULL == (config = new ConfigList(scriptFile)) ) {
02187     NAMD_die("Simulation config file is empty.");
02188   }
02189 #endif
02190 
02191   if (runWasCalled == 0) {
02192     initcheck();
02193     SimParameters *simParams = Node::Object()->simParameters;
02194     if ( simParams->minimizeCGOn ) runController(SCRIPT_MINIMIZE);
02195     else runController(SCRIPT_RUN);
02196     runWasCalled = 1;
02197   }
02198 
02199 #if CMK_HAS_PARTITION
02200   replica_barrier();
02201 #endif
02202   runController(SCRIPT_END);
02203 
02204 }
02205 
02206 ScriptTcl::~ScriptTcl() {
02207   DebugM(3,"Destructing ScriptTcl\n");
02208 #ifdef NAMD_TCL
02209   if ( interp ) Tcl_DeleteInterp(interp);
02210   delete [] callbackname;
02211 #endif
02212 
02213   molfile_dcdplugin_fini();
02214 }
02215 

Generated on Tue Sep 25 01:17:15 2018 for NAMD by  doxygen 1.4.7