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 "DumpBench.h"
00027 #include <stdio.h>
00028 #include <ctype.h>  // for isspace
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 //#define DEBUGM
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 // XXX static and global variables are unsafe for shared memory builds.
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 // Needs to handle the following cases as passed in by Tcl:
00153 //    name data #comment
00154 //    name=data #comment
00155 //    name= data #comment
00156 //    name =data #comment
00157 //    name = data #comment
00158 //    name data1 data2 data3 #comment
00159 //    name=data1 data2 data3 #comment
00160 //    name= data1 data2 data3 #comment
00161 //    name =data1 data2 data3 #comment
00162 //    name = data1 data2 data3 #comment
00163 //    name { data1 data2 data3 } #comment
00164 //    name { data1 data2 data3 } #comment
00165 //    name { data1 data2 # data3 } #comment
00166 //    name {data1 data2 # data3 } #comment
00167 // Do not try to handle "data#comment" in any form.
00168 // The '#' start of any comments will *always* be a new argv.
00169 // The name will *always* be contained in argv[1].
00170 
00171   // allocate storage for data string
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   // find the end of the name
00177   char *name, *s;
00178   name = argv[1];
00179   for ( s = name; *s && *s != '='; ++s );
00180 
00181   // eliminate any comment
00182   for (ai=2; ai<argc; ++ai) { if (argv[ai][0] == '#') argc = ai; }
00183 
00184   // concatenate all the data items
00185   ai = 2;
00186   if ( *s ) { *s = 0; ++s; strcat(data,s); }  // name=data or name=
00187   else if ( ai < argc && argv[ai][0] == '=' ) {  // name =data or name =
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 // move all atoms by a given vector
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   // Check if valid unit cell data is contained in the timestep.  We don't
00549   // have any formalized way of doing this yet; for now, just check that
00550   // the length of the vector is greater than 1.
00551   if (ts->A <= 1 || ts->B <= 1 || ts->C <= 1) return 0;
00552 
00553   // convert from degrees to radians
00554   // Try to get exact results when the angles are exactly 90.
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   // A will lie along the positive x axis.
00564   // B will lie in the x-y plane
00565   // The origin will be (0,0,0).
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   //if (fabs(B.x) < UNITCELLSLOP) B.x = 0;
00571   //if (fabs(B.y) < UNITCELLSLOP) B.y = 0;
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   //if (fabs(vecC.x) < UNITCELLSLOP) vecC.x = 0;
00576   //if (fabs(vecC.y) < UNITCELLSLOP) vecC.y = 0;
00577   //if (fabs(vecC.z) < UNITCELLSLOP) vecC.z = 0;
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) {  // EOF
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       // update Controller's lattice, but don't change the origin!
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) {  // EOF
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 // consforceconfig <atomids> <forces>
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   // Create interpreter
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 

Generated on Sun Sep 7 04:07:42 2008 for NAMD by  doxygen 1.3.9.1