Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

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 "Controller.h"
00021 #include "SimParameters.h"
00022 #include "Thread.h"
00023 #include "ProcessorPrivate.h"
00024 #include "PatchMgr.h"
00025 #include "Measure.h"
00026 #include "colvarmodule.h"
00027 #include "DumpBench.h"
00028 #include <stdio.h>
00029 #include <ctype.h>  // for isspace
00030 #ifndef WIN32
00031 #include <strings.h>
00032 #endif
00033 
00034 #ifdef NAMD_TCL
00035 #define USE_COMPAT_CONST
00036 #include <tcl.h>
00037 #endif
00038 #include "TclCommands.h"
00039 
00040 //#define DEBUGM
00041 #define MIN_DEBUG_LEVEL 4
00042 #include "Debug.h"
00043 
00044 #include <molfile_plugin.h>
00045 #include <libmolfile_plugin.h>
00046 
00047 static molfile_plugin_t *dcdplugin;
00048 static int register_cb(void *v, vmdplugin_t *p) {
00049         dcdplugin = (molfile_plugin_t *)p;
00050         return 0;
00051 }
00052 
00053 //
00054 // XXX static and global variables are unsafe for shared memory builds.
00055 //
00056 static int numatoms;
00057 static void *filehandle;
00058 static float *coords;
00059 static Vector *vcoords;
00060 
00061 
00062 void ScriptTcl::suspend() {
00063   BackEnd::suspend();
00064 }
00065 
00066 void ScriptTcl::barrier() {
00067   BackEnd::barrier();
00068 }
00069 
00070 void ScriptTcl::initcheck() {
00071   if ( initWasCalled == 0 ) {
00072 #ifdef NAMD_TCL
00073     CkPrintf("TCL: Suspending until startup complete.\n");
00074     Tcl_CreateCommand(interp, "param", Tcl_param,
00075       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00076     Tcl_CreateCommand(interp, "unknown", Tcl_param,
00077       (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00078 #endif
00079     initWasCalled = 1;
00080 
00081     state->configListInit(config);
00082     Node::Object()->saveMolDataPointers(state);
00083 #ifdef NAMD_TCL
00084     SimParameters *simParams = Node::Object()->simParameters;
00085     simParams->tclIsThreaded =
00086       ! ! Tcl_GetVar2(interp, "tcl_platform", "threaded", TCL_GLOBAL_ONLY);
00087 #endif
00088     Node::messageStartUp();
00089     suspend();
00090   }
00091 }
00092 
00093 void ScriptTcl::runController(int task) {
00094   scriptBarrier.publish(barrierStep++,task);
00095   suspend();
00096 #ifdef NAMD_TCL
00097   if ( task == SCRIPT_RUN || task == SCRIPT_MINIMIZE  ) {
00098     doCallback(state->callback_labelstring.c_str(),
00099                state->callback_valuestring.c_str());
00100   }
00101 #endif
00102 }
00103 
00104 void ScriptTcl::setParameter(const char* param, const char* value) {
00105   ScriptParamMsg *msg = new ScriptParamMsg;
00106   strncpy(msg->param,param,MAX_SCRIPT_PARAM_SIZE);
00107   strncpy(msg->value,value,MAX_SCRIPT_PARAM_SIZE);
00108   (CProxy_Node(CkpvAccess(BOCclass_group).node)).scriptParam(msg);
00109   barrier();
00110 }
00111 
00112 void ScriptTcl::setParameter(const char* param, int value) {
00113   ScriptParamMsg *msg = new ScriptParamMsg;
00114   strncpy(msg->param,param,MAX_SCRIPT_PARAM_SIZE);
00115   sprintf(msg->value,"%d",value);
00116   (CProxy_Node(CkpvAccess(BOCclass_group).node)).scriptParam(msg);
00117   barrier();
00118 }
00119 
00120 void ScriptTcl::reinitAtoms(void) {
00121   Node::Object()->workDistrib->reinitAtoms();
00122   barrier();
00123 }
00124 
00125 #ifdef NAMD_TCL
00126 
00127 int ScriptTcl::Tcl_exit(ClientData clientData,
00128         Tcl_Interp *, int argc, char *argv[]) {
00129   ScriptTcl *script = (ScriptTcl *)clientData;
00130   script->initcheck();
00131   CkPrintf("TCL: Exiting due to exit command.\n");
00132   script->runController(SCRIPT_END);
00133   BackEnd::exit();
00134   return TCL_OK;
00135 }
00136 
00137 int ScriptTcl::Tcl_abort(ClientData,
00138         Tcl_Interp *, int argc, char *argv[]) {
00139   Tcl_DString msg;
00140   Tcl_DStringInit(&msg);
00141   Tcl_DStringAppend(&msg,"TCL:",-1);
00142   for ( int i = 1; i < argc; ++i ) {
00143     Tcl_DStringAppend(&msg," ",-1);
00144     Tcl_DStringAppend(&msg,argv[i],-1);
00145   }
00146   NAMD_die(Tcl_DStringValue(&msg));
00147   Tcl_DStringFree(&msg);
00148   return TCL_OK;
00149 }
00150 
00151 int ScriptTcl::Tcl_numPes(ClientData, Tcl_Interp *interp, int argc, char **) {
00152   if ( argc > 1 ) {
00153     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00154     return TCL_ERROR;
00155   }
00156   Tcl_SetObjResult(interp, Tcl_NewIntObj(CkNumPes()));
00157   return TCL_OK;
00158 }
00159 
00160 int ScriptTcl::Tcl_numNodes(ClientData, Tcl_Interp *interp, int argc, char **) {
00161   if ( argc > 1 ) {
00162     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00163     return TCL_ERROR;
00164   }
00165   Tcl_SetObjResult(interp, Tcl_NewIntObj(CkNumNodes()));
00166   return TCL_OK;
00167 }
00168 
00169 int ScriptTcl::Tcl_numPhysicalNodes(ClientData, Tcl_Interp *interp, int argc, char **) {
00170   if ( argc > 1 ) {
00171     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00172     return TCL_ERROR;
00173   }
00174   Tcl_SetObjResult(interp, Tcl_NewIntObj(CmiNumPhysicalNodes()));
00175   return TCL_OK;
00176 }
00177 
00178 #if CMK_REPLICAS
00179 extern "C" {
00180 int CmiNumReplicas();
00181 int CmiMyReplica();
00182 void CmiReplicaSendrecv(void *sendbuf, int sendcount, int dest, void *recvbuf, int recvcount, int source);
00183 void CmiReplicaSend(void *buf, int count, int dest);
00184 void CmiReplicaRecv(void *buf, int count, int source);
00185 void CmiReplicaBarrier();
00186 }
00187 #endif
00188 
00189 int ScriptTcl::Tcl_numReplicas(ClientData, Tcl_Interp *interp, int argc, char **) {
00190   if ( argc > 1 ) {
00191     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00192     return TCL_ERROR;
00193   }
00194 #if CMK_REPLICAS
00195   Tcl_SetObjResult(interp, Tcl_NewIntObj(CmiNumReplicas()));
00196 #else
00197   Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
00198 #endif
00199   return TCL_OK;
00200 }
00201 
00202 int ScriptTcl::Tcl_myReplica(ClientData, Tcl_Interp *interp, int argc, char **) {
00203   if ( argc > 1 ) {
00204     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00205     return TCL_ERROR;
00206   }
00207 #if CMK_REPLICAS
00208   Tcl_SetObjResult(interp, Tcl_NewIntObj(CmiMyReplica()));
00209 #else
00210   Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00211 #endif
00212   return TCL_OK;
00213 }
00214 
00215 int ScriptTcl::Tcl_replicaSendrecv(ClientData, Tcl_Interp *interp, int argc, char **argv) {
00216   if ( argc < 3 || argc > 4 ) {
00217     Tcl_SetResult(interp,"args: data dest ?source?",TCL_VOLATILE);
00218     return TCL_ERROR;
00219   }
00220   Tcl_DString recvstr;
00221   Tcl_DStringInit(&recvstr);
00222   int sendcount = strlen(argv[1]);
00223   int recvcount = 0;
00224   int dest = atoi(argv[2]);
00225   int source = -1;
00226   if ( argc > 3 ) source = atoi(argv[3]);
00227 #if CMK_REPLICAS
00228   CmiReplicaSendrecv(&sendcount,sizeof(int),dest,&recvcount,sizeof(int),source);
00229   Tcl_DStringSetLength(&recvstr,recvcount);
00230   CmiReplicaSendrecv(argv[1],sendcount,dest,Tcl_DStringValue(&recvstr),recvcount,source);
00231 #endif
00232   Tcl_DStringResult(interp, &recvstr);
00233   Tcl_DStringFree(&recvstr);
00234   return TCL_OK;
00235 }
00236 
00237 int ScriptTcl::Tcl_replicaSend(ClientData, Tcl_Interp *interp, int argc, char **argv) {
00238   if ( argc != 3 ) {
00239     Tcl_SetResult(interp,"args: data dest",TCL_VOLATILE);
00240     return TCL_ERROR;
00241   }
00242   int sendcount = strlen(argv[1]);
00243   int dest = atoi(argv[2]);
00244 #if CMK_REPLICAS
00245   CmiReplicaSend(&sendcount,sizeof(int),dest);
00246   CmiReplicaSend(argv[1],sendcount,dest);
00247 #endif
00248   return TCL_OK;
00249 }
00250 
00251 int ScriptTcl::Tcl_replicaRecv(ClientData, Tcl_Interp *interp, int argc, char **argv) {
00252   if (argc != 2 ) {
00253     Tcl_SetResult(interp,"args: source",TCL_VOLATILE);
00254     return TCL_ERROR;
00255   }
00256   Tcl_DString recvstr;
00257   Tcl_DStringInit(&recvstr);
00258   int recvcount = 0;
00259   int source = atoi(argv[1]);
00260   // Source required to avoid race condition when receiving multiple messages.
00261   // This could be avoided by adding tags to CmiReplica arguments
00262   // to distinguish size messages and including source in size message.
00263 #if CMK_REPLICAS
00264   CmiReplicaRecv(&recvcount,sizeof(int),source);
00265   Tcl_DStringSetLength(&recvstr,recvcount);
00266   CmiReplicaRecv(Tcl_DStringValue(&recvstr),recvcount,source);
00267 #endif
00268   Tcl_DStringResult(interp, &recvstr);
00269   Tcl_DStringFree(&recvstr);
00270   return TCL_OK;
00271 }
00272 
00273 int ScriptTcl::Tcl_replicaBarrier(ClientData, Tcl_Interp *interp, int argc, char **) {
00274   if ( argc > 1 ) {
00275     Tcl_SetResult(interp,"no arguments needed",TCL_VOLATILE);
00276     return TCL_ERROR;
00277   }
00278 #if CMK_REPLICAS
00279   CmiReplicaBarrier();
00280 #endif
00281   return TCL_OK;
00282 }
00283 
00284 int ScriptTcl::Tcl_print(ClientData,
00285         Tcl_Interp *, int argc, char *argv[]) {
00286   Tcl_DString msg;
00287   Tcl_DStringInit(&msg);
00288   for ( int i = 1; i < argc; ++i ) {
00289     Tcl_DStringAppend(&msg," ",-1);
00290     Tcl_DStringAppend(&msg,argv[i],-1);
00291   }
00292   CkPrintf("TCL:%s\n",Tcl_DStringValue(&msg));
00293   Tcl_DStringFree(&msg);
00294   return TCL_OK;
00295 }
00296 
00297 int ScriptTcl::Tcl_config(ClientData clientData,
00298         Tcl_Interp *interp, int argc, char *argv[]) {
00299 
00300 // Needs to handle the following cases as passed in by Tcl:
00301 //    name data #comment
00302 //    name=data #comment
00303 //    name= data #comment
00304 //    name =data #comment
00305 //    name = data #comment
00306 //    name data1 data2 data3 #comment
00307 //    name=data1 data2 data3 #comment
00308 //    name= data1 data2 data3 #comment
00309 //    name =data1 data2 data3 #comment
00310 //    name = data1 data2 data3 #comment
00311 //    name { data1 data2 data3 } #comment
00312 //    name { data1 data2 data3 } #comment
00313 //    name { data1 data2 # data3 } #comment
00314 //    name {data1 data2 # data3 } #comment
00315 // Do not try to handle "data#comment" in any form.
00316 // The '#' start of any comments will *always* be a new argv.
00317 // The name will *always* be contained in argv[1].
00318 
00319   // allocate storage for data string
00320   int arglen = 1;  int ai;
00321   for (ai=1; ai<argc; ++ai) { arglen += strlen(argv[ai]) + 1; }
00322   char *data = new char[arglen];  *data = 0;
00323 
00324   // find the end of the name
00325   char *name, *s;
00326   name = argv[1];
00327   for ( s = name; *s && *s != '='; ++s );
00328 
00329   // eliminate any comment
00330   for (ai=2; ai<argc; ++ai) { if (argv[ai][0] == '#') argc = ai; }
00331 
00332   // concatenate all the data items
00333   ai = 2;
00334   if ( *s ) { *s = 0; ++s; strcat(data,s); }  // name=data or name=
00335   else if ( ai < argc && argv[ai][0] == '=' ) {  // name =data or name =
00336     strcat(data,argv[ai]+1);
00337     ++ai;
00338   }
00339   for ( ; ai<argc; ++ai) {
00340     if ( data[0] ) { strcat(data," "); }
00341     strcat(data,argv[ai]);
00342   }
00343 
00344   if ( ! *name || ! *data ) {
00345     delete [] data;
00346     Tcl_SetResult(interp,"error parsing config file",TCL_VOLATILE);
00347     return TCL_ERROR;
00348   }
00349 
00350   ScriptTcl *script = (ScriptTcl *)clientData;
00351   script->config->add_element( name, strlen(name), data, strlen(data) );
00352 
00353   delete [] data;
00354   return TCL_OK;
00355 }
00356 
00357 int ScriptTcl::Tcl_param(ClientData clientData,
00358         Tcl_Interp *interp, int argc, char *argv[]) {
00359   if (argc != 3 && argc != 5) {
00360     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00361     return TCL_ERROR;
00362   }
00363 
00364   char *param = argv[1];
00365   if ( strlen(param) + 1 > MAX_SCRIPT_PARAM_SIZE ) {
00366     Tcl_SetResult(interp,"parameter name too long",TCL_VOLATILE);
00367     return TCL_ERROR;
00368   }
00369 
00370   char value[MAX_SCRIPT_PARAM_SIZE];
00371   int arglen = strlen(argv[2]) + 1;
00372   if ( argc == 5 ) arglen += strlen(argv[3]) + strlen(argv[4]) + 2;
00373   if ( arglen > MAX_SCRIPT_PARAM_SIZE ) {
00374     Tcl_SetResult(interp,"parameter value too long",TCL_VOLATILE);
00375     return TCL_ERROR;
00376   }
00377   if ( argc == 3 ) sprintf(value,"%s",argv[2]);
00378   if ( argc == 5 ) sprintf(value,"%s %s %s",argv[2],argv[3],argv[4]);
00379 
00380   iout << "TCL: Setting parameter " << param << " to " << value << "\n" << endi;
00381 
00382   ScriptTcl *script = (ScriptTcl *)clientData;
00383   script->setParameter(param,value);
00384 
00385   return TCL_OK;
00386 }
00387 
00388 int ScriptTcl::Tcl_reinitvels(ClientData clientData,
00389         Tcl_Interp *interp, int argc, char *argv[]) {
00390   ScriptTcl *script = (ScriptTcl *)clientData;
00391   script->initcheck();
00392   if (argc != 2) {
00393     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00394     return TCL_ERROR;
00395   }
00396   char *temp = argv[1];
00397 
00398   script->setParameter("initialTemp",temp);
00399 
00400   script->runController(SCRIPT_REINITVELS);
00401 
00402   return TCL_OK;
00403 }
00404 
00405 int ScriptTcl::Tcl_rescalevels(ClientData clientData,
00406         Tcl_Interp *interp, int argc, char *argv[]) {
00407   ScriptTcl *script = (ScriptTcl *)clientData;
00408   script->initcheck();
00409   if (argc != 2) {
00410     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00411     return TCL_ERROR;
00412   }
00413   char *factor = argv[1];
00414 
00415   script->setParameter("scriptArg1",factor);
00416 
00417   script->runController(SCRIPT_RESCALEVELS);
00418 
00419   return TCL_OK;
00420 }
00421 
00422 int ScriptTcl::Tcl_run(ClientData clientData,
00423         Tcl_Interp *interp, int argc, char *argv[]) {
00424   ScriptTcl *script = (ScriptTcl *)clientData;
00425   script->initcheck();
00426   if (argc != 2) {
00427     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00428     return TCL_ERROR;
00429   }
00430   int numsteps;
00431   if (Tcl_GetInt(interp,argv[1],&numsteps) != TCL_OK) {
00432     return TCL_ERROR;
00433   }
00434   if (numsteps < 0) {
00435     Tcl_SetResult(interp,"number of steps must be non-negative",TCL_VOLATILE);
00436     return TCL_ERROR;
00437   }
00438   SimParameters *simParams = Node::Object()->simParameters;
00439   if (numsteps && simParams->firstTimestep % simParams->stepsPerCycle) {
00440     Tcl_SetResult(interp,"firstTimestep must be a multiple of stepsPerCycle",TCL_VOLATILE);
00441     return TCL_ERROR;
00442   }
00443   if (numsteps % simParams->stepsPerCycle) {
00444     Tcl_SetResult(interp,"number of steps must be a multiple of stepsPerCycle",TCL_VOLATILE);
00445     return TCL_ERROR;
00446   }
00447   if ( simParams->N != simParams->firstTimestep ) {
00448     iout << "TCL: Original numsteps " << simParams->N
00449          << " will be ignored.\n";
00450   }
00451   iout << "TCL: Running for " << numsteps << " steps\n" << endi;
00452 
00453   script->setParameter("numsteps",simParams->firstTimestep + numsteps);
00454 
00455   script->runController(SCRIPT_RUN);
00456   script->runWasCalled = 1;
00457 
00458   script->setParameter("firsttimestep",simParams->N);
00459 
00460   return TCL_OK;
00461 }
00462 
00463 int ScriptTcl::Tcl_minimize(ClientData clientData,
00464         Tcl_Interp *interp, int argc, char *argv[]) {
00465   ScriptTcl *script = (ScriptTcl *)clientData;
00466   script->initcheck();
00467   if (argc != 2) {
00468     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00469     return TCL_ERROR;
00470   }
00471   int numsteps;
00472   if (Tcl_GetInt(interp,argv[1],&numsteps) != TCL_OK) {
00473     return TCL_ERROR;
00474   }
00475   if (numsteps < 0) {
00476     Tcl_SetResult(interp,"number of steps must be non-negative",TCL_VOLATILE);
00477     return TCL_ERROR;
00478   }
00479   SimParameters *simParams = Node::Object()->simParameters;
00480   if (numsteps && simParams->firstTimestep % simParams->stepsPerCycle) {
00481     Tcl_SetResult(interp,"firstTimestep must be a multiple of stepsPerCycle",TCL_VOLATILE);
00482     return TCL_ERROR;
00483   }
00484   if (numsteps % simParams->stepsPerCycle) {
00485     Tcl_SetResult(interp,"number of steps must be a multiple of stepsPerCycle",TCL_VOLATILE);
00486     return TCL_ERROR;
00487   }
00488   if ( simParams->N != simParams->firstTimestep ) {
00489     iout << "TCL: Original numsteps " << simParams->N
00490          << " will be ignored.\n";
00491   }
00492   iout << "TCL: Minimizing for " << numsteps << " steps\n" << endi;
00493 
00494   script->setParameter("numsteps",simParams->firstTimestep + numsteps);
00495 
00496   script->runController(SCRIPT_MINIMIZE);
00497   script->runWasCalled = 1;
00498 
00499   script->setParameter("firsttimestep",simParams->N);
00500 
00501   return TCL_OK;
00502 }
00503 
00504 // move all atoms by a given vector
00505 int ScriptTcl::Tcl_moveallby(ClientData clientData,
00506         Tcl_Interp *interp, int argc, char *argv[]) {
00507   ScriptTcl *script = (ScriptTcl *)clientData;
00508   script->initcheck();
00509   if (argc != 2) {
00510     Tcl_SetResult(interp, "wrong # args", TCL_VOLATILE);
00511     return TCL_ERROR;
00512   }
00513   char **fstring;
00514   int fnum;
00515   double x, y, z;
00516   if (Tcl_SplitList(interp, argv[1], &fnum, &fstring) != TCL_OK)
00517     return TCL_ERROR;
00518   if ( (fnum != 3) ||
00519        (Tcl_GetDouble(interp, fstring[0],&x) != TCL_OK) ||
00520        (Tcl_GetDouble(interp, fstring[1],&y) != TCL_OK) ||
00521        (Tcl_GetDouble(interp, fstring[2],&z) != TCL_OK) ) {
00522     Tcl_SetResult(interp,"argument not a vector",TCL_VOLATILE);
00523     Tcl_Free((char*)fstring);
00524     return TCL_ERROR;
00525   }
00526   Tcl_Free((char*)fstring);
00527 
00528   MoveAllByMsg *msg = new MoveAllByMsg;
00529   msg->offset = Vector(x,y,z);
00530   (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).moveAllBy(msg);
00531 
00532   script->barrier();
00533   return TCL_OK;
00534 }
00535 
00536 int ScriptTcl::Tcl_move(ClientData clientData,
00537         Tcl_Interp *interp, int argc, char *argv[]) {
00538   ScriptTcl *script = (ScriptTcl *)clientData;
00539   script->initcheck();
00540   if (argc != 4) {
00541     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00542     return TCL_ERROR;
00543   }
00544   char **fstring;  int fnum;  int atomid;  int moveto;  double x, y, z;
00545   if (Tcl_GetInt(interp,argv[1],&atomid) != TCL_OK) return TCL_ERROR;
00546   if (argv[2][0]=='t' && argv[2][1]=='o' && argv[2][2]==0) moveto = 1;
00547   else if (argv[2][0]=='b' && argv[2][1]=='y' && argv[2][2]==0) moveto = 0;
00548   else {
00549     Tcl_SetResult(interp,"syntax is 'move <id> to|by {<x> <y> <z>}'",TCL_VOLATILE);
00550     return TCL_ERROR;
00551   }
00552   if (Tcl_SplitList(interp, argv[3], &fnum, &fstring) != TCL_OK) {
00553     return TCL_ERROR;
00554   }
00555   if ( (fnum != 3) ||
00556        (Tcl_GetDouble(interp, fstring[0],&x) != TCL_OK) ||
00557        (Tcl_GetDouble(interp, fstring[1],&y) != TCL_OK) ||
00558        (Tcl_GetDouble(interp, fstring[2],&z) != TCL_OK) ) {
00559     Tcl_SetResult(interp,"third argument not a vector",TCL_VOLATILE);
00560     Tcl_Free((char*)fstring);
00561     return TCL_ERROR;
00562   }
00563   Tcl_Free((char*)fstring);
00564 
00565   SimParameters *simParams = Node::Object()->simParameters;
00566 
00567   iout << "TCL: Moving atom " << atomid << " ";
00568   if ( moveto ) iout << "to"; else iout << "by";
00569   iout << " " << Vector(x,y,z) << ".\n" << endi;
00570 
00571   MoveAtomMsg *msg = new MoveAtomMsg;
00572   msg->atomid = atomid - 1;
00573   msg->moveto = moveto;
00574   msg->coord = Vector(x,y,z);
00575   (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).moveAtom(msg);
00576 
00577   script->barrier();
00578 
00579   return TCL_OK;
00580 }
00581 
00582 int ScriptTcl::Tcl_output(ClientData clientData,
00583         Tcl_Interp *interp, int argc, char *argv[]) {
00584   ScriptTcl *script = (ScriptTcl *)clientData;
00585   script->initcheck();
00586   if (argc < 2) {
00587     Tcl_SetResult(interp,"too few args",TCL_VOLATILE);
00588     return TCL_ERROR;
00589   }
00590   if (argc > 3) {
00591     Tcl_SetResult(interp,"too many args",TCL_VOLATILE);
00592     return TCL_ERROR;
00593   }
00594   int filenamearg = argc-1;
00595   if (strlen(argv[filenamearg]) > MAX_SCRIPT_PARAM_SIZE) {
00596     Tcl_SetResult(interp,"file name too long",TCL_VOLATILE);
00597     return TCL_ERROR;
00598   }
00599   int dorestart = 1;
00600   int doforces = 0;
00601   if (argc == 3) {
00602     if ( ! strcmp(argv[1], "withforces") ) {
00603       doforces = 1;
00604     } else if ( ! strcmp(argv[1], "onlyforces") ) {
00605       dorestart = 0;
00606       doforces = 1;
00607     }  else {
00608       Tcl_SetResult(interp,
00609         "first arg not withforces or onlyforces",TCL_VOLATILE);
00610       return TCL_ERROR;
00611     }
00612   }
00613 
00614   SimParameters *simParams = Node::Object()->simParameters;
00615 
00616   char oldname[MAX_SCRIPT_PARAM_SIZE+1];
00617   strncpy(oldname,simParams->outputFilename,MAX_SCRIPT_PARAM_SIZE);
00618 
00619   script->setParameter("outputname",argv[filenamearg]);
00620 
00621   iout << "TCL: Writing to files with basename " <<
00622                 simParams->outputFilename << ".\n" << endi;
00623 
00624   if ( doforces && ! script->runWasCalled ) NAMD_die(
00625     "No forces to output; must call run or minimize first.");
00626 
00627   if ( dorestart ) script->runController(SCRIPT_OUTPUT);
00628   if ( doforces ) script->runController(SCRIPT_FORCEOUTPUT);
00629 
00630   script->setParameter("outputname",oldname);
00631 
00632   return TCL_OK;
00633 }
00634 
00635 void ScriptTcl::measure(Vector *c) {
00636   Measure::createCommands(interp);
00637   Node::Object()->coords = c;
00638   measure_result = Tcl_Eval(interp,measure_command);
00639   Node::Object()->coords = 0;
00640   Measure::deleteCommands(interp);
00641 }
00642 
00643 int ScriptTcl::Tcl_measure(ClientData clientData,
00644         Tcl_Interp *interp, int argc, char *argv[]) {
00645   ScriptTcl *script = (ScriptTcl *)clientData;
00646   script->initcheck();
00647   if (argc != 2) {
00648     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00649     return TCL_ERROR;
00650   }
00651   script->measure_command = argv[1];
00652 
00653   script->runController(SCRIPT_MEASURE);
00654 
00655   return script->measure_result;
00656 }
00657 
00658 int ScriptTcl::Tcl_colvarbias(ClientData clientData,
00659         Tcl_Interp *interp, int argc, char *argv[]) {
00660   ScriptTcl *script = (ScriptTcl *)clientData;
00661   script->initcheck();
00662   if (argc < 4 || argc % 2) {
00663     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00664     return TCL_ERROR;
00665   }
00666   colvarmodule *colvars = Node::Object()->colvars;
00667   if ( ! colvars ) {
00668     Tcl_SetResult(interp,"colvars module not active",TCL_VOLATILE);
00669     return TCL_ERROR;
00670   }
00671   if ( ! strcmp(argv[1],"changeconfig") ) {
00672     for ( int i=2; i<argc; i+=2 ) {
00673       std::string name(argv[i]);
00674       std::string conf(argv[i+1]);
00675       colvars->change_configuration(name,conf);
00676     }
00677     return TCL_OK;
00678   } else if ( ! strcmp(argv[1],"energydiff") ) {
00679     if ( ! script->runWasCalled ) {
00680       Tcl_SetResult(interp,"energydiff requires a previous timestep",TCL_VOLATILE);
00681       return TCL_ERROR;
00682     }
00683     double ediff = 0.;
00684     for ( int i=2; i<argc; i+=2 ) {
00685       std::string name(argv[i]);
00686       std::string conf(argv[i+1]);
00687       ediff += colvars->energy_difference(name,conf);
00688     }
00689     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ediff));
00690     return TCL_OK;
00691   } else {
00692     Tcl_SetResult(interp,"unknown colvarbias operation",TCL_VOLATILE);
00693     return TCL_ERROR;
00694   }
00695 }
00696 
00697 int ScriptTcl::Tcl_checkpoint(ClientData clientData,
00698         Tcl_Interp *interp, int argc, char *argv[]) {
00699   ScriptTcl *script = (ScriptTcl *)clientData;
00700   script->initcheck();
00701   if (argc != 1) {
00702     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00703     return TCL_ERROR;
00704   }
00705 
00706   script->runController(SCRIPT_CHECKPOINT);
00707 
00708   return TCL_OK;
00709 }
00710 
00711 int ScriptTcl::Tcl_revert(ClientData clientData,
00712         Tcl_Interp *interp, int argc, char *argv[]) {
00713   ScriptTcl *script = (ScriptTcl *)clientData;
00714   script->initcheck();
00715   if (argc != 1) {
00716     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00717     return TCL_ERROR;
00718   }
00719 
00720   script->runController(SCRIPT_REVERT);
00721 
00722   return TCL_OK;
00723 }
00724 
00725 int ScriptTcl::Tcl_callback(ClientData clientData,
00726         Tcl_Interp *interp, int argc, char *argv[]) {
00727   ScriptTcl *script = (ScriptTcl *)clientData;
00728   if (argc != 2) {
00729     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00730     return TCL_ERROR;
00731   }
00732 
00733   delete [] script->callbackname;
00734   script->callbackname = new char[strlen(argv[1])+1];
00735   strcpy(script->callbackname,argv[1]);
00736 
00737   iout << "TCL: Reduction callback proc set to " <<
00738                         script->callbackname << "\n" << endi;
00739 
00740   return TCL_OK;
00741 }
00742 
00743 void ScriptTcl::doCallback(const char *labels, const char *data) {
00744   if ( ! callbackname ) return;
00745   int len = strlen(callbackname) + strlen(labels) + strlen(data) + 7;
00746   char *cmd = new char[len];
00747   sprintf(cmd, "%s {%s} {%s}", callbackname, labels, data);
00748   int rval = Tcl_Eval(interp,cmd);
00749   delete [] cmd;
00750   if (rval != TCL_OK) {
00751     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
00752     NAMD_die(errorInfo);
00753   }
00754 }
00755 
00756 int ScriptTcl::Tcl_reinitatoms(ClientData clientData,
00757         Tcl_Interp *interp, int argc, char *argv[]) {
00758   ScriptTcl *script = (ScriptTcl *)clientData;
00759   script->initcheck();
00760   if (argc != 1) {
00761     Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00762     return TCL_ERROR;
00763   }
00764 
00765   iout << "TCL: Reinitializing atom data\n" << endi;
00766   script->reinitAtoms();
00767 
00768   return TCL_OK;
00769 }
00770 
00771 #define DEG2RAD 3.14159625359/180.0
00772 #define UNITCELLSLOP 0.0001
00773 
00774 static int get_lattice_from_ts(Lattice *lattice, const molfile_timestep_t *ts)
00775 {
00776   // Check if valid unit cell data is contained in the timestep.  We don't
00777   // have any formalized way of doing this yet; for now, just check that
00778   // the length of the vector is greater than 1.
00779   if (ts->A <= 1 || ts->B <= 1 || ts->C <= 1) return 0;
00780 
00781   // convert from degrees to radians
00782   // Try to get exact results when the angles are exactly 90.
00783   double epsalpha = DEG2RAD*(ts->alpha-90.0);
00784   double epsbeta  = DEG2RAD*(ts->beta-90.0);
00785   double epsgamma = DEG2RAD*(ts->gamma-90.0);
00786   double cosAB = -sin(epsgamma);
00787   double sinAB = cos(epsgamma);
00788   double cosAC = -sin(epsbeta);
00789   double cosBC = -sin(epsalpha);
00790 
00791   // A will lie along the positive x axis.
00792   // B will lie in the x-y plane
00793   // The origin will be (0,0,0).
00794   Vector A(0), B(0), vecC(0);
00795   A.x = ts->A;
00796   B.x = ts->B*cosAB;
00797   B.y = ts->B*sinAB;
00798   //if (fabs(B.x) < UNITCELLSLOP) B.x = 0;
00799   //if (fabs(B.y) < UNITCELLSLOP) B.y = 0;
00800   vecC.x = ts->C * cosAC;
00801   vecC.y = (ts->B*ts->C*cosBC - B.x*vecC.x)/B.y;
00802   vecC.z = sqrt(ts->C*ts->C - vecC.x*vecC.x - vecC.y*vecC.y);
00803   //if (fabs(vecC.x) < UNITCELLSLOP) vecC.x = 0;
00804   //if (fabs(vecC.y) < UNITCELLSLOP) vecC.y = 0;
00805   //if (fabs(vecC.z) < UNITCELLSLOP) vecC.z = 0;
00806   lattice->set(A, B, vecC, Vector(0));
00807   return 1;
00808 }
00809 
00810 int ScriptTcl::Tcl_coorfile(ClientData clientData,
00811         Tcl_Interp *interp, int argc, char *argv[]) {
00812   ScriptTcl *script = (ScriptTcl *)clientData;
00813   script->initcheck();
00814   if (argc == 4 && !strcmp(argv[1], "open")) {
00815     if (strcmp(argv[2], "dcd")) {
00816       NAMD_die("Sorry, coorfile presently supports only DCD files");
00817     }
00818     filehandle = dcdplugin->open_file_read(argv[3], "dcd", &numatoms);
00819     if (!filehandle) {
00820       Tcl_AppendResult(interp, "coorfile: Error opening file ", argv[3], NULL);
00821       return TCL_ERROR;
00822     }
00823     if (numatoms != Node::Object()->pdb->num_atoms()) {
00824       Tcl_AppendResult(interp, "Coordinate file ", argv[3], 
00825         "\ncontains the wrong number of atoms.", NULL);
00826       return TCL_ERROR;
00827     }
00828     coords = new float[3*numatoms];
00829     vcoords = new Vector[3*numatoms];
00830     iout << iINFO << "Coordinate file " << argv[3] << " opened for reading.\n"
00831          << endi;
00832   } else if (argc == 2 && !strcmp(argv[1], "read")) {
00833     if (filehandle == NULL) {
00834       Tcl_AppendResult(interp, "coorfile read: Error, no file open for reading",
00835         NULL);
00836       return TCL_ERROR;
00837     }
00838     molfile_timestep_t ts;
00839     ts.coords = coords;
00840     int rc = dcdplugin->read_next_timestep(filehandle, numatoms, &ts);
00841     if (rc) {  // EOF
00842       Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00843       return TCL_OK;
00844     }
00845     iout << iINFO << "Reading timestep from file.\n" << endi;
00846     Lattice lattice;
00847     if (get_lattice_from_ts(&lattice, &ts)) {
00848       iout << iINFO << "Updating unit cell from timestep.\n" << endi;
00849       if ( lattice.a_p() && ! script->state->lattice.a_p() ||
00850            lattice.b_p() && ! script->state->lattice.b_p() ||
00851            lattice.c_p() && ! script->state->lattice.c_p() ) {
00852         iout << iWARN << "Cell basis vectors should be specified before reading trajectory.\n" << endi;
00853       }
00854       // update Controller's lattice, but don't change the origin!
00855       Vector a(0.);  if ( script->state->lattice.a_p() ) a = lattice.a();
00856       Vector b(0.);  if ( script->state->lattice.b_p() ) b = lattice.b();
00857       Vector c(0.);  if ( script->state->lattice.c_p() ) c = lattice.c();
00858       script->state->lattice.set(a,b,c);
00859       SetLatticeMsg *msg = new SetLatticeMsg;
00860       msg->lattice = script->state->lattice;
00861       (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).setLattice(msg);
00862       script->barrier();
00863     }
00864     for (int i=0; i<numatoms; i++) {
00865       vcoords[i].x = coords[3*i+0];
00866       vcoords[i].y = coords[3*i+1];
00867       vcoords[i].z = coords[3*i+2];
00868     }
00869     Node::Object()->pdb->set_all_positions(vcoords);
00870     script->reinitAtoms();
00871     Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00872   } else if (argc == 2 && !strcmp(argv[1], "close")) {
00873     if (!filehandle) {
00874       Tcl_AppendResult(interp, "coorfile close: No file opened for reading!", 
00875         NULL);
00876       return TCL_OK;
00877     }
00878     iout << iINFO << "Closing coordinate file.\n" << endi; 
00879     dcdplugin->close_file_read(filehandle);
00880     filehandle = NULL;
00881     delete [] coords;
00882     delete [] vcoords;
00883 
00884   } else if (argc ==2 && !strcmp(argv[1], "skip")) {
00885     if (filehandle == NULL) {
00886       Tcl_AppendResult(interp, "coorfile skip: Error, no file open for reading",
00887         NULL);
00888       return TCL_ERROR;
00889     }
00890     int rc = dcdplugin->read_next_timestep(filehandle, numatoms, NULL);
00891     if (rc) {  // EOF
00892       Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00893       return TCL_OK;
00894     }
00895     Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00896 
00897   } else {
00898     NAMD_die("Unknown option passed to coorfile");
00899   }
00900   return TCL_OK;
00901 }
00902 
00903 int ScriptTcl::Tcl_dumpbench(ClientData clientData,
00904         Tcl_Interp *interp, int argc, char *argv[]) {
00905   ScriptTcl *script = (ScriptTcl *)clientData;
00906   script->initcheck();
00907   if (argc != 2) {
00908     Tcl_AppendResult(interp, "usage: dumpbench <filename>", NULL);
00909     return TCL_ERROR;
00910   }
00911 
00912   if ( CkNumPes() != 1 ) {
00913     Tcl_AppendResult(interp, "multiple processors detected; dumpbench only works on serial runs", NULL);
00914     return TCL_ERROR;
00915   }
00916 
00917   FILE *file = fopen(argv[1],"w");
00918   if ( ! file ) {
00919     Tcl_AppendResult(interp, "dumpbench: error opening file ", argv[1], NULL);
00920     return TCL_ERROR;
00921   }
00922 
00923   if ( dumpbench(file) ) {
00924     Tcl_AppendResult(interp, "dumpbench: error dumping benchmark data", NULL);
00925     return TCL_ERROR;
00926   }
00927 
00928   fclose(file);
00929 
00930   Tcl_AppendResult(interp, "benchmark data written to file ", argv[1], NULL);
00931   return TCL_OK;
00932 }
00933 
00934 #include "ComputeConsForceMsgs.h"
00935 // consforceconfig <atomids> <forces>
00936 int ScriptTcl::Tcl_consForceConfig(ClientData clientData,
00937     Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
00938   ScriptTcl *script = (ScriptTcl *)clientData;
00939   script->initcheck();
00940   if ( ! Node::Object()->simParameters->consForceOn ) {
00941     Tcl_AppendResult(interp, "consForceConfig requires constantForce on", NULL);
00942     return TCL_ERROR;
00943   }
00944   if (objc != 3) {
00945     Tcl_WrongNumArgs(interp, 1, objv, (char *)"<atomids> <forces>");
00946     return TCL_ERROR;
00947   }
00948   int natoms, nforces;
00949   Tcl_Obj **atomobjlist, **forceobjlist;
00950   if (Tcl_ListObjGetElements(interp, objv[1], &natoms, &atomobjlist) != TCL_OK ||
00951       Tcl_ListObjGetElements(interp, objv[2], &nforces, &forceobjlist) != TCL_OK) {
00952     return TCL_ERROR;
00953   }
00954   if (natoms != nforces) {
00955     Tcl_AppendResult(interp, (char *)"consforceconfig: atom list and force list not the same size!", NULL);
00956     return TCL_ERROR;
00957   }
00958   ComputeConsForceMsg *msg = new ComputeConsForceMsg;
00959   for (int i=0; i<natoms; i++) {
00960     int atomid;
00961     int nelem;
00962     Tcl_Obj **elemlist;
00963     Vector force;
00964     if (Tcl_GetIntFromObj(interp, atomobjlist[i], &atomid) != TCL_OK) 
00965       return TCL_ERROR;
00966     if (Tcl_ListObjGetElements(interp, forceobjlist[i], &nelem, &elemlist) != TCL_OK)
00967       return TCL_ERROR;
00968     if (nelem != 3) {
00969       Tcl_AppendResult(interp, (char *)"consforceconfig: forces must have three elements", NULL);
00970       return TCL_ERROR;
00971     }
00972     if (Tcl_GetDoubleFromObj(interp, elemlist[0], &force.x) != TCL_OK ||
00973         Tcl_GetDoubleFromObj(interp, elemlist[1], &force.y) != TCL_OK ||
00974         Tcl_GetDoubleFromObj(interp, elemlist[2], &force.z) != TCL_OK) {
00975       return TCL_ERROR;
00976     }
00977     msg->aid.add(atomid);
00978     msg->f.add(force);
00979   }
00980   (CProxy_ComputeMgr(CkpvAccess(BOCclass_group).computeMgr)).recvComputeConsForceMsg(msg);
00981   return TCL_OK;
00982 }
00983 
00984 int ScriptTcl::Tcl_reloadCharges(ClientData clientData,
00985         Tcl_Interp *interp, int argc, char *argv[]) {
00986   ScriptTcl *script = (ScriptTcl *)clientData;
00987   script->initcheck();
00988   if (argc != 2) {
00989     Tcl_AppendResult(interp, "usage: reloadCharges <filename>", NULL);
00990     return TCL_ERROR;
00991   }
00992 
00993   Node::Object()->reloadCharges(argv[1]);
00994 
00995   script->runController(SCRIPT_RELOADCHARGES);
00996 
00997   return TCL_OK;
00998 }
00999 
01000 // BEGIN gf
01001 int ScriptTcl::Tcl_reloadGridforceGrid(ClientData clientData,
01002         Tcl_Interp *interp, int argc, char *argv[]) {
01003   ScriptTcl *script = (ScriptTcl *)clientData;
01004   script->initcheck();
01005   
01006   char *key = NULL;
01007   if (argc == 1) {
01008       // nothing ... key is NULL, then Node::reloadGridforceGrid uses the
01009       // default key, which is used internally when the gridforce*
01010       // keywords are used (as opposed to the mgridforce* keywords)
01011   } else if (argc == 2) {
01012       key = argv[1];
01013   } else {
01014       Tcl_AppendResult(interp, "usage: reloadGridforceGrid [<gridkey>]", NULL);
01015       return TCL_ERROR;
01016   }
01017   
01018   //(CProxy_Node(CkpvAccess(BOCclass_group).node)).reloadGridforceGrid(key);
01019   Node::Object()->reloadGridforceGrid(key);
01020   script->barrier();
01021   
01022   return TCL_OK;
01023 }
01024 // END gf
01025 
01026 #endif  // NAMD_TCL
01027 
01028 
01029 ScriptTcl::ScriptTcl() : scriptBarrier(scriptBarrierTag) {
01030   DebugM(3,"Constructing ScriptTcl\n");
01031 #ifdef NAMD_TCL
01032   interp = 0;
01033   callbackname = 0;
01034 #endif
01035   state = new NamdState;
01036   barrierStep = 0;
01037 
01038   molfile_dcdplugin_init();
01039   molfile_dcdplugin_register(NULL, register_cb);
01040 
01041   initWasCalled = 0;
01042   runWasCalled = 0;
01043 
01044 #ifdef NAMD_TCL
01045   config = new ConfigList;
01046 
01047   // Create interpreter
01048   interp = Tcl_CreateInterp();
01049   tcl_vector_math_init(interp);
01050   Tcl_CreateCommand(interp, "exit", Tcl_exit,
01051     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01052   Tcl_CreateCommand(interp, "abort", Tcl_abort,
01053     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01054   Tcl_CreateCommand(interp, "numPes", Tcl_numPes,
01055     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01056   Tcl_CreateCommand(interp, "numNodes", Tcl_numNodes,
01057     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01058   Tcl_CreateCommand(interp, "numPhysicalNodes", Tcl_numPhysicalNodes,
01059     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01060   Tcl_CreateCommand(interp, "numReplicas", Tcl_numReplicas,
01061     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01062   Tcl_CreateCommand(interp, "myReplica", Tcl_myReplica,
01063     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01064   Tcl_CreateCommand(interp, "replicaSendrecv", Tcl_replicaSendrecv,
01065     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01066   Tcl_CreateCommand(interp, "replicaSend", Tcl_replicaSend,
01067     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01068   Tcl_CreateCommand(interp, "replicaRecv", Tcl_replicaRecv,
01069     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01070   Tcl_CreateCommand(interp, "replicaBarrier", Tcl_replicaBarrier,
01071     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01072   Tcl_CreateCommand(interp, "print", Tcl_print,
01073     (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
01074   Tcl_CreateCommand(interp, "unknown", Tcl_config,
01075     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01076   Tcl_CreateCommand(interp, "param", Tcl_config,
01077     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01078   Tcl_CreateCommand(interp, "run", Tcl_run,
01079     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01080   Tcl_CreateCommand(interp, "minimize", Tcl_minimize,
01081     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01082   Tcl_CreateCommand(interp, "move", Tcl_move,
01083     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01084   Tcl_CreateCommand(interp, "moveallby", Tcl_moveallby,
01085     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01086   Tcl_CreateCommand(interp, "output", Tcl_output,
01087     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01088   Tcl_CreateCommand(interp, "measure", Tcl_measure,
01089     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01090   Tcl_CreateCommand(interp, "colvarbias", Tcl_colvarbias,
01091     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01092   Tcl_CreateCommand(interp, "checkpoint", Tcl_checkpoint,
01093     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01094   Tcl_CreateCommand(interp, "revert", Tcl_revert,
01095     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01096   Tcl_CreateCommand(interp, "reinitvels", Tcl_reinitvels,
01097     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01098   Tcl_CreateCommand(interp, "rescalevels", Tcl_rescalevels,
01099     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01100   Tcl_CreateCommand(interp, "reinitatoms", Tcl_reinitatoms,
01101     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01102   Tcl_CreateCommand(interp, "callback", Tcl_callback,
01103     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01104   Tcl_CreateCommand(interp, "coorfile", Tcl_coorfile,
01105     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01106   Tcl_CreateCommand(interp, "dumpbench", Tcl_dumpbench,
01107     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01108   Tcl_CreateObjCommand(interp, "consForceConfig", Tcl_consForceConfig, 
01109     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01110   Tcl_CreateCommand(interp, "reloadCharges", Tcl_reloadCharges,
01111     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01112   // BEGIN gf
01113   Tcl_CreateCommand(interp, "reloadGridforceGrid", Tcl_reloadGridforceGrid,
01114     (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01115   // END gf
01116 #endif
01117 
01118 }
01119 
01120 void ScriptTcl::eval(char *script) {
01121 
01122 #ifdef NAMD_TCL
01123   int code = Tcl_Eval(interp,script);
01124   const char *result = Tcl_GetStringResult(interp);
01125   if (*result != 0) CkPrintf("TCL: %s\n",result);
01126   if (code != TCL_OK) {
01127     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
01128     NAMD_die(errorInfo);
01129   }
01130 #else
01131   NAMD_bug("ScriptTcl::eval called without Tcl.");
01132 #endif
01133 
01134 }
01135 
01136 void ScriptTcl::load(char *scriptFile) {
01137 
01138 #ifdef NAMD_TCL
01139   int code = Tcl_EvalFile(interp,scriptFile);
01140   const char *result = Tcl_GetStringResult(interp);
01141   if (*result != 0) CkPrintf("TCL: %s\n",result);
01142   if (code != TCL_OK) {
01143     const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
01144     NAMD_die(errorInfo);
01145   }
01146 #else
01147   NAMD_bug("ScriptTcl::load called without Tcl.");
01148 #endif
01149 
01150 }
01151 
01152 #ifdef NAMD_TCL
01153 void ScriptTcl::run() {
01154 #else
01155 void ScriptTcl::run(char *scriptFile) {
01156 
01157   if ( NULL == scriptFile || NULL == (config = new ConfigList(scriptFile)) ) {
01158     NAMD_die("Simulation config file is empty.");
01159   }
01160 #endif
01161 
01162   if (runWasCalled == 0) {
01163     initcheck();
01164     SimParameters *simParams = Node::Object()->simParameters;
01165     if ( simParams->minimizeCGOn ) runController(SCRIPT_MINIMIZE);
01166     else runController(SCRIPT_RUN);
01167     runWasCalled = 1;
01168   }
01169 
01170   runController(SCRIPT_END);
01171 
01172 }
01173 
01174 ScriptTcl::~ScriptTcl() {
01175   DebugM(3,"Destructing ScriptTcl\n");
01176 #ifdef NAMD_TCL
01177   if ( interp ) Tcl_DeleteInterp(interp);
01178   delete [] callbackname;
01179 #endif
01180 
01181   molfile_dcdplugin_fini();
01182 }
01183 

Generated on Fri May 25 04:07:17 2012 for NAMD by  doxygen 1.3.9.1