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

Generated on Sat Sep 23 01:17:15 2017 for NAMD by  doxygen 1.4.7