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 "DumpBench.h"
00027 #include <stdio.h>
00028 #include <ctype.h>
00029 #ifndef WIN32
00030 #include <strings.h>
00031 #endif
00032
00033 #ifdef NAMD_TCL
00034 #define USE_COMPAT_CONST
00035 #include <tcl.h>
00036 #endif
00037
00038
00039 #define MIN_DEBUG_LEVEL 4
00040 #include "Debug.h"
00041
00042 #include <molfile_plugin.h>
00043 #include <libmolfile_plugin.h>
00044
00045 static molfile_plugin_t *dcdplugin;
00046 static int register_cb(void *v, vmdplugin_t *p) {
00047 dcdplugin = (molfile_plugin_t *)p;
00048 return 0;
00049 }
00050
00051
00052
00053
00054 static int numatoms;
00055 static void *filehandle;
00056 static float *coords;
00057 static Vector *vcoords;
00058
00059
00060 void ScriptTcl::suspend() {
00061 BackEnd::suspend();
00062 }
00063
00064 void ScriptTcl::barrier() {
00065 BackEnd::barrier();
00066 }
00067
00068 void ScriptTcl::initcheck() {
00069 if ( runWasCalled == 0 ) {
00070 #ifdef NAMD_TCL
00071 CkPrintf("TCL: Suspending until startup complete.\n");
00072 Tcl_CreateCommand(interp, "param", Tcl_param,
00073 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00074 Tcl_CreateCommand(interp, "unknown", Tcl_param,
00075 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00076 #endif
00077 runWasCalled = 1;
00078
00079 state->configListInit(config);
00080 Node::Object()->saveMolDataPointers(state);
00081 Node::messageStartUp();
00082 suspend();
00083 }
00084 }
00085
00086 void ScriptTcl::runController(int task) {
00087 scriptBarrier.publish(barrierStep++,task);
00088 suspend();
00089 }
00090
00091 void ScriptTcl::setParameter(const char* param, const char* value) {
00092 ScriptParamMsg *msg = new ScriptParamMsg;
00093 strncpy(msg->param,param,MAX_SCRIPT_PARAM_SIZE);
00094 strncpy(msg->value,value,MAX_SCRIPT_PARAM_SIZE);
00095 (CProxy_Node(CkpvAccess(BOCclass_group).node)).scriptParam(msg);
00096 barrier();
00097 }
00098
00099 void ScriptTcl::setParameter(const char* param, int value) {
00100 ScriptParamMsg *msg = new ScriptParamMsg;
00101 strncpy(msg->param,param,MAX_SCRIPT_PARAM_SIZE);
00102 sprintf(msg->value,"%d",value);
00103 (CProxy_Node(CkpvAccess(BOCclass_group).node)).scriptParam(msg);
00104 barrier();
00105 }
00106
00107 void ScriptTcl::reinitAtoms(void) {
00108 Node::Object()->workDistrib->reinitAtoms();
00109 barrier();
00110 }
00111
00112 #ifdef NAMD_TCL
00113
00114 int ScriptTcl::Tcl_exit(ClientData clientData,
00115 Tcl_Interp *, int argc, char *argv[]) {
00116 ScriptTcl *script = (ScriptTcl *)clientData;
00117 script->runController(SCRIPT_END);
00118 BackEnd::exit();
00119 return TCL_OK;
00120 }
00121
00122 int ScriptTcl::Tcl_abort(ClientData,
00123 Tcl_Interp *, int argc, char *argv[]) {
00124 Tcl_DString msg;
00125 Tcl_DStringInit(&msg);
00126 Tcl_DStringAppend(&msg,"TCL:",-1);
00127 for ( int i = 1; i < argc; ++i ) {
00128 Tcl_DStringAppend(&msg," ",-1);
00129 Tcl_DStringAppend(&msg,argv[i],-1);
00130 }
00131 NAMD_die(Tcl_DStringValue(&msg));
00132 Tcl_DStringFree(&msg);
00133 return TCL_OK;
00134 }
00135
00136 int ScriptTcl::Tcl_print(ClientData,
00137 Tcl_Interp *, int argc, char *argv[]) {
00138 Tcl_DString msg;
00139 Tcl_DStringInit(&msg);
00140 for ( int i = 1; i < argc; ++i ) {
00141 Tcl_DStringAppend(&msg," ",-1);
00142 Tcl_DStringAppend(&msg,argv[i],-1);
00143 }
00144 CkPrintf("TCL:%s\n",Tcl_DStringValue(&msg));
00145 Tcl_DStringFree(&msg);
00146 return TCL_OK;
00147 }
00148
00149 int ScriptTcl::Tcl_config(ClientData clientData,
00150 Tcl_Interp *interp, int argc, char *argv[]) {
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 int arglen = 1; int ai;
00173 for (ai=1; ai<argc; ++ai) { arglen += strlen(argv[ai]) + 1; }
00174 char *data = new char[arglen]; *data = 0;
00175
00176
00177 char *name, *s;
00178 name = argv[1];
00179 for ( s = name; *s && *s != '='; ++s );
00180
00181
00182 for (ai=2; ai<argc; ++ai) { if (argv[ai][0] == '#') argc = ai; }
00183
00184
00185 ai = 2;
00186 if ( *s ) { *s = 0; ++s; strcat(data,s); }
00187 else if ( ai < argc && argv[ai][0] == '=' ) {
00188 strcat(data,argv[ai]+1);
00189 ++ai;
00190 }
00191 for ( ; ai<argc; ++ai) {
00192 if ( data[0] ) { strcat(data," "); }
00193 strcat(data,argv[ai]);
00194 }
00195
00196 if ( ! *name || ! *data ) {
00197 delete [] data;
00198 Tcl_SetResult(interp,"error parsing config file",TCL_VOLATILE);
00199 return TCL_ERROR;
00200 }
00201
00202 ScriptTcl *script = (ScriptTcl *)clientData;
00203 script->config->add_element( name, strlen(name), data, strlen(data) );
00204
00205 delete [] data;
00206 return TCL_OK;
00207 }
00208
00209 int ScriptTcl::Tcl_param(ClientData clientData,
00210 Tcl_Interp *interp, int argc, char *argv[]) {
00211 if (argc != 3 && argc != 5) {
00212 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00213 return TCL_ERROR;
00214 }
00215
00216 char *param = argv[1];
00217 if ( strlen(param) + 1 > MAX_SCRIPT_PARAM_SIZE ) {
00218 Tcl_SetResult(interp,"parameter name too long",TCL_VOLATILE);
00219 return TCL_ERROR;
00220 }
00221
00222 char value[MAX_SCRIPT_PARAM_SIZE];
00223 int arglen = strlen(argv[2]) + 1;
00224 if ( argc == 5 ) arglen += strlen(argv[3]) + strlen(argv[4]) + 2;
00225 if ( arglen > MAX_SCRIPT_PARAM_SIZE ) {
00226 Tcl_SetResult(interp,"parameter value too long",TCL_VOLATILE);
00227 return TCL_ERROR;
00228 }
00229 if ( argc == 3 ) sprintf(value,"%s",argv[2]);
00230 if ( argc == 5 ) sprintf(value,"%s %s %s",argv[2],argv[3],argv[4]);
00231
00232 iout << "TCL: Setting parameter " << param << " to " << value << "\n" << endi;
00233
00234 ScriptTcl *script = (ScriptTcl *)clientData;
00235 script->setParameter(param,value);
00236
00237 return TCL_OK;
00238 }
00239
00240 int ScriptTcl::Tcl_reinitvels(ClientData clientData,
00241 Tcl_Interp *interp, int argc, char *argv[]) {
00242 ScriptTcl *script = (ScriptTcl *)clientData;
00243 script->initcheck();
00244 if (argc != 2) {
00245 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00246 return TCL_ERROR;
00247 }
00248 char *temp = argv[1];
00249
00250 script->setParameter("initialTemp",temp);
00251
00252 script->runController(SCRIPT_REINITVELS);
00253
00254 return TCL_OK;
00255 }
00256
00257 int ScriptTcl::Tcl_rescalevels(ClientData clientData,
00258 Tcl_Interp *interp, int argc, char *argv[]) {
00259 ScriptTcl *script = (ScriptTcl *)clientData;
00260 script->initcheck();
00261 if (argc != 2) {
00262 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00263 return TCL_ERROR;
00264 }
00265 char *factor = argv[1];
00266
00267 script->setParameter("scriptArg1",factor);
00268
00269 script->runController(SCRIPT_RESCALEVELS);
00270
00271 return TCL_OK;
00272 }
00273
00274 int ScriptTcl::Tcl_run(ClientData clientData,
00275 Tcl_Interp *interp, int argc, char *argv[]) {
00276 ScriptTcl *script = (ScriptTcl *)clientData;
00277 script->initcheck();
00278 if (argc != 2) {
00279 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00280 return TCL_ERROR;
00281 }
00282 int numsteps;
00283 if (Tcl_GetInt(interp,argv[1],&numsteps) != TCL_OK) {
00284 return TCL_ERROR;
00285 }
00286 if (numsteps < 0) {
00287 Tcl_SetResult(interp,"number of steps must be non-negative",TCL_VOLATILE);
00288 return TCL_ERROR;
00289 }
00290 SimParameters *simParams = Node::Object()->simParameters;
00291 if (numsteps % simParams->stepsPerCycle) {
00292 Tcl_SetResult(interp,"number of steps must be a multiple of stepsPerCycle",TCL_VOLATILE);
00293 return TCL_ERROR;
00294 }
00295 iout << "TCL: Running for " << numsteps << " steps\n" << endi;
00296
00297 script->setParameter("numsteps",simParams->firstTimestep + numsteps);
00298
00299 script->runController(SCRIPT_RUN);
00300
00301 script->setParameter("firsttimestep",simParams->N);
00302
00303 return TCL_OK;
00304 }
00305
00306 int ScriptTcl::Tcl_minimize(ClientData clientData,
00307 Tcl_Interp *interp, int argc, char *argv[]) {
00308 ScriptTcl *script = (ScriptTcl *)clientData;
00309 script->initcheck();
00310 if (argc != 2) {
00311 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00312 return TCL_ERROR;
00313 }
00314 int numsteps;
00315 if (Tcl_GetInt(interp,argv[1],&numsteps) != TCL_OK) {
00316 return TCL_ERROR;
00317 }
00318 if (numsteps < 0) {
00319 Tcl_SetResult(interp,"number of steps must be non-negative",TCL_VOLATILE);
00320 return TCL_ERROR;
00321 }
00322 SimParameters *simParams = Node::Object()->simParameters;
00323 if (numsteps % simParams->stepsPerCycle) {
00324 Tcl_SetResult(interp,"number of steps must be a multiple of stepsPerCycle",TCL_VOLATILE);
00325 return TCL_ERROR;
00326 }
00327 iout << "TCL: Minimizing for " << numsteps << " steps\n" << endi;
00328
00329 script->setParameter("numsteps",simParams->firstTimestep + numsteps);
00330
00331 script->runController(SCRIPT_MINIMIZE);
00332
00333 script->setParameter("firsttimestep",simParams->N);
00334
00335 return TCL_OK;
00336 }
00337
00338
00339 int ScriptTcl::Tcl_moveallby(ClientData clientData,
00340 Tcl_Interp *interp, int argc, char *argv[]) {
00341 ScriptTcl *script = (ScriptTcl *)clientData;
00342 script->initcheck();
00343 if (argc != 2) {
00344 Tcl_SetResult(interp, "wrong # args", TCL_VOLATILE);
00345 return TCL_ERROR;
00346 }
00347 char **fstring;
00348 int fnum;
00349 double x, y, z;
00350 if (Tcl_SplitList(interp, argv[1], &fnum, &fstring) != TCL_OK)
00351 return TCL_ERROR;
00352 if ( (fnum != 3) ||
00353 (Tcl_GetDouble(interp, fstring[0],&x) != TCL_OK) ||
00354 (Tcl_GetDouble(interp, fstring[1],&y) != TCL_OK) ||
00355 (Tcl_GetDouble(interp, fstring[2],&z) != TCL_OK) ) {
00356 Tcl_SetResult(interp,"argument not a vector",TCL_VOLATILE);
00357 Tcl_Free((char*)fstring);
00358 return TCL_ERROR;
00359 }
00360 Tcl_Free((char*)fstring);
00361
00362 MoveAllByMsg *msg = new MoveAllByMsg;
00363 msg->offset = Vector(x,y,z);
00364 (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).moveAllBy(msg);
00365
00366 script->barrier();
00367 return TCL_OK;
00368 }
00369
00370 int ScriptTcl::Tcl_move(ClientData clientData,
00371 Tcl_Interp *interp, int argc, char *argv[]) {
00372 ScriptTcl *script = (ScriptTcl *)clientData;
00373 script->initcheck();
00374 if (argc != 4) {
00375 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00376 return TCL_ERROR;
00377 }
00378 char **fstring; int fnum; int atomid; int moveto; double x, y, z;
00379 if (Tcl_GetInt(interp,argv[1],&atomid) != TCL_OK) return TCL_ERROR;
00380 if (argv[2][0]=='t' && argv[2][1]=='o' && argv[2][2]==0) moveto = 1;
00381 else if (argv[2][0]=='b' && argv[2][1]=='y' && argv[2][2]==0) moveto = 0;
00382 else {
00383 Tcl_SetResult(interp,"syntax is 'move <id> to|by {<x> <y> <z>}'",TCL_VOLATILE);
00384 return TCL_ERROR;
00385 }
00386 if (Tcl_SplitList(interp, argv[3], &fnum, &fstring) != TCL_OK) {
00387 return TCL_ERROR;
00388 }
00389 if ( (fnum != 3) ||
00390 (Tcl_GetDouble(interp, fstring[0],&x) != TCL_OK) ||
00391 (Tcl_GetDouble(interp, fstring[1],&y) != TCL_OK) ||
00392 (Tcl_GetDouble(interp, fstring[2],&z) != TCL_OK) ) {
00393 Tcl_SetResult(interp,"third argument not a vector",TCL_VOLATILE);
00394 Tcl_Free((char*)fstring);
00395 return TCL_ERROR;
00396 }
00397 Tcl_Free((char*)fstring);
00398
00399 SimParameters *simParams = Node::Object()->simParameters;
00400
00401 iout << "TCL: Moving atom " << atomid << " ";
00402 if ( moveto ) iout << "to"; else iout << "by";
00403 iout << " " << Vector(x,y,z) << ".\n" << endi;
00404
00405 MoveAtomMsg *msg = new MoveAtomMsg;
00406 msg->atomid = atomid - 1;
00407 msg->moveto = moveto;
00408 msg->coord = Vector(x,y,z);
00409 (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).moveAtom(msg);
00410
00411 script->barrier();
00412
00413 return TCL_OK;
00414 }
00415
00416 int ScriptTcl::Tcl_output(ClientData clientData,
00417 Tcl_Interp *interp, int argc, char *argv[]) {
00418 ScriptTcl *script = (ScriptTcl *)clientData;
00419 script->initcheck();
00420 if (argc != 2) {
00421 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00422 return TCL_ERROR;
00423 }
00424 if (strlen(argv[1]) > MAX_SCRIPT_PARAM_SIZE) {
00425 Tcl_SetResult(interp,"file name too long",TCL_VOLATILE);
00426 return TCL_ERROR;
00427 }
00428
00429 SimParameters *simParams = Node::Object()->simParameters;
00430
00431 char oldname[MAX_SCRIPT_PARAM_SIZE+1];
00432 strncpy(oldname,simParams->outputFilename,MAX_SCRIPT_PARAM_SIZE);
00433
00434 script->setParameter("outputname",argv[1]);
00435
00436 iout << "TCL: Writing to files with basename " <<
00437 simParams->outputFilename << ".\n" << endi;
00438
00439 script->runController(SCRIPT_OUTPUT);
00440
00441 script->setParameter("outputname",oldname);
00442
00443 return TCL_OK;
00444 }
00445
00446 void ScriptTcl::measure(Vector *c) {
00447 Measure::createCommands(interp);
00448 Node::Object()->coords = c;
00449 measure_result = Tcl_Eval(interp,measure_command);
00450 Node::Object()->coords = 0;
00451 Measure::deleteCommands(interp);
00452 }
00453
00454 int ScriptTcl::Tcl_measure(ClientData clientData,
00455 Tcl_Interp *interp, int argc, char *argv[]) {
00456 ScriptTcl *script = (ScriptTcl *)clientData;
00457 script->initcheck();
00458 if (argc != 2) {
00459 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00460 return TCL_ERROR;
00461 }
00462 script->measure_command = argv[1];
00463
00464 script->runController(SCRIPT_MEASURE);
00465
00466 return script->measure_result;
00467 }
00468
00469 int ScriptTcl::Tcl_checkpoint(ClientData clientData,
00470 Tcl_Interp *interp, int argc, char *argv[]) {
00471 ScriptTcl *script = (ScriptTcl *)clientData;
00472 script->initcheck();
00473 if (argc != 1) {
00474 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00475 return TCL_ERROR;
00476 }
00477
00478 script->runController(SCRIPT_CHECKPOINT);
00479
00480 return TCL_OK;
00481 }
00482
00483 int ScriptTcl::Tcl_revert(ClientData clientData,
00484 Tcl_Interp *interp, int argc, char *argv[]) {
00485 ScriptTcl *script = (ScriptTcl *)clientData;
00486 script->initcheck();
00487 if (argc != 1) {
00488 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00489 return TCL_ERROR;
00490 }
00491
00492 script->runController(SCRIPT_REVERT);
00493
00494 return TCL_OK;
00495 }
00496
00497 int ScriptTcl::Tcl_callback(ClientData clientData,
00498 Tcl_Interp *interp, int argc, char *argv[]) {
00499 ScriptTcl *script = (ScriptTcl *)clientData;
00500 if (argc != 2) {
00501 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00502 return TCL_ERROR;
00503 }
00504
00505 delete [] script->callbackname;
00506 script->callbackname = new char[strlen(argv[1])+1];
00507 strcpy(script->callbackname,argv[1]);
00508
00509 iout << "TCL: Reduction callback proc set to " <<
00510 script->callbackname << "\n" << endi;
00511
00512 return TCL_OK;
00513 }
00514
00515 void ScriptTcl::doCallback(const char *labels, const char *data) {
00516 if ( ! callbackname ) return;
00517 int len = strlen(callbackname) + strlen(labels) + strlen(data) + 7;
00518 char *cmd = new char[len];
00519 sprintf(cmd, "%s {%s} {%s}", callbackname, labels, data);
00520 int rval = Tcl_Eval(interp,cmd);
00521 delete [] cmd;
00522 if (rval != TCL_OK) {
00523 const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
00524 NAMD_die(errorInfo);
00525 }
00526 }
00527
00528 int ScriptTcl::Tcl_reinitatoms(ClientData clientData,
00529 Tcl_Interp *interp, int argc, char *argv[]) {
00530 ScriptTcl *script = (ScriptTcl *)clientData;
00531 script->initcheck();
00532 if (argc != 1) {
00533 Tcl_SetResult(interp,"wrong # args",TCL_VOLATILE);
00534 return TCL_ERROR;
00535 }
00536
00537 iout << "TCL: Reinitializing atom data\n" << endi;
00538 script->reinitAtoms();
00539
00540 return TCL_OK;
00541 }
00542
00543 #define DEG2RAD 3.14159625359/180.0
00544 #define UNITCELLSLOP 0.0001
00545
00546 static int get_lattice_from_ts(Lattice *lattice, const molfile_timestep_t *ts)
00547 {
00548
00549
00550
00551 if (ts->A <= 1 || ts->B <= 1 || ts->C <= 1) return 0;
00552
00553
00554
00555 double epsalpha = DEG2RAD*(ts->alpha-90.0);
00556 double epsbeta = DEG2RAD*(ts->beta-90.0);
00557 double epsgamma = DEG2RAD*(ts->gamma-90.0);
00558 double cosAB = -sin(epsgamma);
00559 double sinAB = cos(epsgamma);
00560 double cosAC = -sin(epsbeta);
00561 double cosBC = -sin(epsalpha);
00562
00563
00564
00565
00566 Vector A(0), B(0), vecC(0);
00567 A.x = ts->A;
00568 B.x = ts->B*cosAB;
00569 B.y = ts->B*sinAB;
00570
00571
00572 vecC.x = ts->C * cosAC;
00573 vecC.y = (ts->B*ts->C*cosBC - B.x*vecC.x)/B.y;
00574 vecC.z = sqrt(ts->C*ts->C - vecC.x*vecC.x - vecC.y*vecC.y);
00575
00576
00577
00578 lattice->set(A, B, vecC, Vector(0));
00579 return 1;
00580 }
00581
00582 int ScriptTcl::Tcl_coorfile(ClientData clientData,
00583 Tcl_Interp *interp, int argc, char *argv[]) {
00584 ScriptTcl *script = (ScriptTcl *)clientData;
00585 script->initcheck();
00586 if (argc == 4 && !strcmp(argv[1], "open")) {
00587 if (strcmp(argv[2], "dcd")) {
00588 NAMD_die("Sorry, coorfile presently supports only DCD files");
00589 }
00590 filehandle = dcdplugin->open_file_read(argv[3], "dcd", &numatoms);
00591 if (!filehandle) {
00592 Tcl_AppendResult(interp, "coorfile: Error opening file ", argv[3], NULL);
00593 return TCL_ERROR;
00594 }
00595 if (numatoms != Node::Object()->pdb->num_atoms()) {
00596 Tcl_AppendResult(interp, "Coordinate file ", argv[3],
00597 "\ncontains the wrong number of atoms.", NULL);
00598 return TCL_ERROR;
00599 }
00600 coords = new float[3*numatoms];
00601 vcoords = new Vector[3*numatoms];
00602 iout << iINFO << "Coordinate file " << argv[3] << " opened for reading.\n"
00603 << endi;
00604 } else if (argc == 2 && !strcmp(argv[1], "read")) {
00605 if (filehandle == NULL) {
00606 Tcl_AppendResult(interp, "coorfile read: Error, no file open for reading",
00607 NULL);
00608 return TCL_ERROR;
00609 }
00610 molfile_timestep_t ts;
00611 ts.coords = coords;
00612 int rc = dcdplugin->read_next_timestep(filehandle, numatoms, &ts);
00613 if (rc) {
00614 Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00615 return TCL_OK;
00616 }
00617 iout << iINFO << "Reading timestep from file.\n" << endi;
00618 Lattice lattice;
00619 if (get_lattice_from_ts(&lattice, &ts)) {
00620 iout << iINFO << "Updating unit cell from timestep.\n" << endi;
00621 if ( lattice.a_p() && ! script->state->lattice.a_p() ||
00622 lattice.b_p() && ! script->state->lattice.b_p() ||
00623 lattice.c_p() && ! script->state->lattice.c_p() ) {
00624 iout << iWARN << "Cell basis vectors should be specified before reading trajectory.\n" << endi;
00625 }
00626
00627 Vector a(0.); if ( script->state->lattice.a_p() ) a = lattice.a();
00628 Vector b(0.); if ( script->state->lattice.b_p() ) b = lattice.b();
00629 Vector c(0.); if ( script->state->lattice.c_p() ) c = lattice.c();
00630 script->state->lattice.set(a,b,c);
00631 SetLatticeMsg *msg = new SetLatticeMsg;
00632 msg->lattice = script->state->lattice;
00633 (CProxy_PatchMgr(CkpvAccess(BOCclass_group).patchMgr)).setLattice(msg);
00634 script->barrier();
00635 }
00636 for (int i=0; i<numatoms; i++) {
00637 vcoords[i].x = coords[3*i+0];
00638 vcoords[i].y = coords[3*i+1];
00639 vcoords[i].z = coords[3*i+2];
00640 }
00641 Node::Object()->pdb->set_all_positions(vcoords);
00642 script->reinitAtoms();
00643 Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00644 } else if (argc == 2 && !strcmp(argv[1], "close")) {
00645 if (!filehandle) {
00646 Tcl_AppendResult(interp, "coorfile close: No file opened for reading!",
00647 NULL);
00648 return TCL_OK;
00649 }
00650 iout << iINFO << "Closing coordinate file.\n" << endi;
00651 dcdplugin->close_file_read(filehandle);
00652 filehandle = NULL;
00653 delete [] coords;
00654 delete [] vcoords;
00655
00656 } else if (argc ==2 && !strcmp(argv[1], "skip")) {
00657 if (filehandle == NULL) {
00658 Tcl_AppendResult(interp, "coorfile skip: Error, no file open for reading",
00659 NULL);
00660 return TCL_ERROR;
00661 }
00662 int rc = dcdplugin->read_next_timestep(filehandle, numatoms, NULL);
00663 if (rc) {
00664 Tcl_SetObjResult(interp, Tcl_NewIntObj(-1));
00665 return TCL_OK;
00666 }
00667 Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
00668
00669 } else {
00670 NAMD_die("Unknown option passed to coorfile");
00671 }
00672 return TCL_OK;
00673 }
00674
00675 int ScriptTcl::Tcl_dumpbench(ClientData clientData,
00676 Tcl_Interp *interp, int argc, char *argv[]) {
00677 ScriptTcl *script = (ScriptTcl *)clientData;
00678 script->initcheck();
00679 if (argc != 2) {
00680 Tcl_AppendResult(interp, "usage: dumpbench <filename>", NULL);
00681 return TCL_ERROR;
00682 }
00683
00684 if ( CkNumPes() != 1 ) {
00685 Tcl_AppendResult(interp, "multiple processors detected; dumpbench only works on serial runs", NULL);
00686 return TCL_ERROR;
00687 }
00688
00689 FILE *file = fopen(argv[1],"w");
00690 if ( ! file ) {
00691 Tcl_AppendResult(interp, "dumpbench: error opening file ", argv[1], NULL);
00692 return TCL_ERROR;
00693 }
00694
00695 if ( dumpbench(file) ) {
00696 Tcl_AppendResult(interp, "dumpbench: error dumping benchmark data", NULL);
00697 return TCL_ERROR;
00698 }
00699
00700 fclose(file);
00701
00702 Tcl_AppendResult(interp, "benchmark data written to file ", argv[1], NULL);
00703 return TCL_OK;
00704 }
00705
00706 #include "ComputeConsForceMsgs.h"
00707
00708 int ScriptTcl::Tcl_consForceConfig(ClientData clientData,
00709 Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) {
00710 ScriptTcl *script = (ScriptTcl *)clientData;
00711 script->initcheck();
00712 if (objc != 3) {
00713 Tcl_WrongNumArgs(interp, 1, objv, (char *)"<atomids> <forces>");
00714 return TCL_ERROR;
00715 }
00716 int natoms, nforces;
00717 Tcl_Obj **atomobjlist, **forceobjlist;
00718 if (Tcl_ListObjGetElements(interp, objv[1], &natoms, &atomobjlist) != TCL_OK ||
00719 Tcl_ListObjGetElements(interp, objv[2], &nforces, &forceobjlist) != TCL_OK) {
00720 return TCL_ERROR;
00721 }
00722 if (natoms != nforces) {
00723 Tcl_AppendResult(interp, (char *)"consforceconfig: atom list and force list not the same size!", NULL);
00724 return TCL_ERROR;
00725 }
00726 ComputeConsForceMsg *msg = new ComputeConsForceMsg;
00727 for (int i=0; i<natoms; i++) {
00728 int atomid;
00729 int nelem;
00730 Tcl_Obj **elemlist;
00731 Vector force;
00732 if (Tcl_GetIntFromObj(interp, atomobjlist[i], &atomid) != TCL_OK)
00733 return TCL_ERROR;
00734 if (Tcl_ListObjGetElements(interp, forceobjlist[i], &nelem, &elemlist) != TCL_OK)
00735 return TCL_ERROR;
00736 if (nelem != 3) {
00737 Tcl_AppendResult(interp, (char *)"consforceconfig: forces must have three elements", NULL);
00738 return TCL_ERROR;
00739 }
00740 if (Tcl_GetDoubleFromObj(interp, elemlist[0], &force.x) != TCL_OK ||
00741 Tcl_GetDoubleFromObj(interp, elemlist[1], &force.y) != TCL_OK ||
00742 Tcl_GetDoubleFromObj(interp, elemlist[2], &force.z) != TCL_OK) {
00743 return TCL_ERROR;
00744 }
00745 msg->aid.add(atomid);
00746 msg->f.add(force);
00747 }
00748 (CProxy_ComputeMgr(CkpvAccess(BOCclass_group).computeMgr)).recvComputeConsForceMsg(msg);
00749 return TCL_OK;
00750 }
00751
00752 int ScriptTcl::Tcl_reloadCharges(ClientData clientData,
00753 Tcl_Interp *interp, int argc, char *argv[]) {
00754 ScriptTcl *script = (ScriptTcl *)clientData;
00755 script->initcheck();
00756 if (argc != 2) {
00757 Tcl_AppendResult(interp, "usage: reloadCharges <filename>", NULL);
00758 return TCL_ERROR;
00759 }
00760
00761 Node::Object()->reloadCharges(argv[1]);
00762
00763 script->runController(SCRIPT_RELOADCHARGES);
00764
00765 return TCL_OK;
00766 }
00767
00768 #endif // NAMD_TCL
00769
00770
00771 ScriptTcl::ScriptTcl() : scriptBarrier(scriptBarrierTag) {
00772 DebugM(3,"Constructing ScriptTcl\n");
00773 #ifdef NAMD_TCL
00774 interp = 0;
00775 callbackname = 0;
00776 #endif
00777 state = new NamdState;
00778 barrierStep = 0;
00779
00780 molfile_dcdplugin_init();
00781 molfile_dcdplugin_register(NULL, register_cb);
00782
00783 runWasCalled = 0;
00784
00785 #ifdef NAMD_TCL
00786 config = new ConfigList;
00787
00788
00789 interp = Tcl_CreateInterp();
00790 Tcl_CreateCommand(interp, "exit", Tcl_exit,
00791 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00792 Tcl_CreateCommand(interp, "abort", Tcl_abort,
00793 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
00794 Tcl_CreateCommand(interp, "print", Tcl_print,
00795 (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
00796 Tcl_CreateCommand(interp, "unknown", Tcl_config,
00797 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00798 Tcl_CreateCommand(interp, "param", Tcl_config,
00799 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00800 Tcl_CreateCommand(interp, "run", Tcl_run,
00801 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00802 Tcl_CreateCommand(interp, "minimize", Tcl_minimize,
00803 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00804 Tcl_CreateCommand(interp, "move", Tcl_move,
00805 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00806 Tcl_CreateCommand(interp, "moveallby", Tcl_moveallby,
00807 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00808 Tcl_CreateCommand(interp, "output", Tcl_output,
00809 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00810 Tcl_CreateCommand(interp, "measure", Tcl_measure,
00811 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00812 Tcl_CreateCommand(interp, "checkpoint", Tcl_checkpoint,
00813 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00814 Tcl_CreateCommand(interp, "revert", Tcl_revert,
00815 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00816 Tcl_CreateCommand(interp, "reinitvels", Tcl_reinitvels,
00817 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00818 Tcl_CreateCommand(interp, "rescalevels", Tcl_rescalevels,
00819 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00820 Tcl_CreateCommand(interp, "reinitatoms", Tcl_reinitatoms,
00821 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00822 Tcl_CreateCommand(interp, "callback", Tcl_callback,
00823 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00824 Tcl_CreateCommand(interp, "coorfile", Tcl_coorfile,
00825 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00826 Tcl_CreateCommand(interp, "dumpbench", Tcl_dumpbench,
00827 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00828 Tcl_CreateObjCommand(interp, "consForceConfig", Tcl_consForceConfig,
00829 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00830 Tcl_CreateCommand(interp, "reloadCharges", Tcl_reloadCharges,
00831 (ClientData) this, (Tcl_CmdDeleteProc *) NULL);
00832 #endif
00833
00834 }
00835
00836 void ScriptTcl::load(char *scriptFile) {
00837
00838 #ifdef NAMD_TCL
00839 int code = Tcl_EvalFile(interp,scriptFile);
00840 const char *result = Tcl_GetStringResult(interp);
00841 if (*result != 0) CkPrintf("TCL: %s\n",result);
00842 if (code != TCL_OK) {
00843 const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
00844 NAMD_die(errorInfo);
00845 }
00846 #else
00847 NAMD_bug("ScriptTcl::load called without Tcl.");
00848 #endif
00849
00850 }
00851
00852 void ScriptTcl::run(char *scriptFile) {
00853
00854 #ifdef NAMD_TCL
00855 int code = Tcl_EvalFile(interp,scriptFile);
00856 const char *result = Tcl_GetStringResult(interp);
00857 if (*result != 0) CkPrintf("TCL: %s\n",result);
00858 if (code != TCL_OK) {
00859 const char *errorInfo = Tcl_GetVar(interp,"errorInfo",0);
00860 NAMD_die(errorInfo);
00861 }
00862
00863 #else
00864 if ( NULL == scriptFile || NULL == (config = new ConfigList(scriptFile)) ) {
00865 NAMD_die("Simulation config file is empty.");
00866 }
00867 #endif
00868
00869 if (runWasCalled == 0) {
00870 initcheck();
00871 SimParameters *simParams = Node::Object()->simParameters;
00872 if ( simParams->minimizeCGOn ) runController(SCRIPT_MINIMIZE);
00873 else runController(SCRIPT_RUN);
00874 }
00875
00876 runController(SCRIPT_END);
00877
00878 }
00879
00880 ScriptTcl::~ScriptTcl() {
00881 DebugM(3,"Destructing ScriptTcl\n");
00882 #ifdef NAMD_TCL
00883 if ( interp ) Tcl_DeleteInterp(interp);
00884 delete [] callbackname;
00885 #endif
00886
00887 molfile_dcdplugin_fini();
00888 }
00889