00001
00007
00008
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>
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
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
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
00261
00262
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
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
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
00325 char *name, *s;
00326 name = argv[1];
00327 for ( s = name; *s && *s != '='; ++s );
00328
00329
00330 for (ai=2; ai<argc; ++ai) { if (argv[ai][0] == '#') argc = ai; }
00331
00332
00333 ai = 2;
00334 if ( *s ) { *s = 0; ++s; strcat(data,s); }
00335 else if ( ai < argc && argv[ai][0] == '=' ) {
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
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
00777
00778
00779 if (ts->A <= 1 || ts->B <= 1 || ts->C <= 1) return 0;
00780
00781
00782
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
00792
00793
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
00799
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
00804
00805
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) {
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
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) {
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
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
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
01009
01010
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
01019 Node::Object()->reloadGridforceGrid(key);
01020 script->barrier();
01021
01022 return TCL_OK;
01023 }
01024
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
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
01113 Tcl_CreateCommand(interp, "reloadGridforceGrid", Tcl_reloadGridforceGrid,
01114 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
01115
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