00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdlib.h>
00022 #include <stdio.h>
00023 #include <tcl.h>
00024
00025 #include "TclCommands.h"
00026 #include "AtomSel.h"
00027 #include "VMDApp.h"
00028 #include "MoleculeList.h"
00029 #include "utilities.h"
00030 #include "config.h"
00031 #include "Atom.h"
00032 #include "Molecule.h"
00033 #include "Measure.h"
00034 #include "FastPBC.h"
00035
00036
00037
00038
00039
00040 static int compoundmapper (int compound, Molecule *mol, AtomSel *sel, int *&indexlist, int *&fragmentmap) {
00041 indexlist = new int[sel->selected];
00042 switch (compound) {
00043 case 1:
00044 fragmentmap = new int[mol->nFragments+1]; break;
00045 case 2:
00046 fragmentmap = new int[mol->nResidues+1]; break;
00047 default:
00048
00049 printf("This should have never happened. Josh is sorry.\n Compound was passed with argument %d\n", compound);
00050 return TCL_ERROR;
00051 }
00052 int *idxptr = indexlist;
00053 int *frag = fragmentmap;
00054 *frag = 0;
00055 int i, j, k, l;
00056 int count;
00057 if (compound == 1) {
00058 for (i = 0; (i < mol->nFragments); i++) {
00059 count = 0;
00060 Fragment *f = mol->fragment(i);
00061 for (j = 0; j < f->residues.num(); j++) {
00062 Residue *r = mol->residue(f->residues[j]);
00063 for (k = 0; k < r->atoms.num(); k++) {
00064 l = r->atoms[k];
00065 if (sel->on[l]) {
00066 count++;
00067 *idxptr = l;
00068 idxptr++;
00069 }
00070 }
00071 }
00072 if (count > 0) {
00073 frag++;
00074 *frag = count + *(frag-1);
00075 }
00076 }
00077 } else if (compound == 2) {
00078 for (j = 0; j < mol->nResidues; j++) {
00079 count = 0;
00080 Residue *r = mol->residue(j);
00081 for (k = 0; k < r->atoms.num(); k++) {
00082 l = r->atoms[k];
00083 if (sel->on[l]) {
00084 count++;
00085 *idxptr = l;
00086 idxptr++;
00087 }
00088 }
00089 if (count > 0) {
00090 frag++;
00091 *frag = count + *(frag-1);
00092 }
00093 }
00094 }
00095 return (frag - fragmentmap);
00096 }
00097
00098 int check_timesteps(Tcl_Interp *interp, Molecule *mol, int first, int last){
00099 int maxframes = mol->numframes();
00100
00101 if (maxframes == 0 || first < 0 || first > last ||
00102 last >= maxframes) {
00103 Tcl_AppendResult(interp, "fastpbc wrap: invalid frame range: ", first, " to ", last, NULL);
00104 return TCL_ERROR;
00105 }
00106 Timestep *ts;
00107 int f;
00108 for (f=first; f<=last; f++) {
00109 ts = mol->get_frame(f);
00110 if (ts->a_length <= 0 || ts->b_length <= 0 || ts->c_length <= 0) {
00111 Tcl_AppendResult(interp, "fastpbc: frame : ", f, " has no periodic box defined", NULL);
00112 return TCL_ERROR;
00113 }
00114 if (ts->alpha != 90 || ts->beta != 90 || ts->gamma != 90) {
00115 Tcl_AppendResult(interp, "fastpbc: frame : ", f, " has a non-orthogonal box!", NULL);
00116 return TCL_ERROR;
00117 }
00118 }
00119 return TCL_OK;
00120 }
00121
00152 static int fpbc_wrap(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00153 int first = 0;
00154 int last = -1;
00155 int i, j;
00156 bool gpu = true;
00157 int compound = 0;
00158 float center[3] = {0,0,0};
00159
00160 if (argc < 2) {
00161 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [first <first>] [last <last>] [center [list x y z]]");
00162 return TCL_ERROR;
00163 }
00164 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00165 AtomSel *centersel = NULL;
00166 if (!sel) {
00167 Tcl_SetResult(interp, (char *) "fastpbc wrap: no atom selection", TCL_STATIC);
00168 return TCL_ERROR;
00169 }
00170 for (i=2; i<argc; i+=2) {
00171 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00172 if (!strupncmp(argvcur, "first", CMDLEN)) {
00173 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00174 Tcl_AppendResult(interp, "fastpbc wrap: bad first frame value", NULL);
00175 return TCL_ERROR;
00176 }
00177 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00178 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00179 Tcl_AppendResult(interp, "fastpbc wrap: bad last frame value", NULL);
00180 return TCL_ERROR;
00181 }
00182 } else if (!strupncmp(argvcur, "center", CMDLEN)) {
00183 int num_vect;
00184 Tcl_Obj **vec;
00185 Tcl_Obj *vecobj = objv[i+1];
00186 if (Tcl_ListObjGetElements(interp, vecobj, &num_vect, &vec) != TCL_OK) {
00187 return TCL_ERROR;
00188 }
00189 if (num_vect != 3) {
00190 Tcl_SetResult(interp, (char *) "fastpbc wrap: center vector can only be of length 3", TCL_STATIC);
00191 return TCL_ERROR;
00192 }
00193 for (j=0; j<3; j++) {
00194 double tmp;
00195 if (Tcl_GetDoubleFromObj(interp, vec[j], &tmp) != TCL_OK) {
00196 Tcl_SetResult(interp, (char *)"fastpbc wrap: non-numeric in vector", TCL_STATIC);
00197 return TCL_ERROR;
00198 }
00199 center[j] = (float)tmp;
00200 }
00201 } else if (!strupncmp(argvcur, "centersel", CMDLEN)) {
00202 centersel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[i+1],NULL));
00203 if (!centersel) {
00204 Tcl_SetResult(interp, (char *) "fastpbc wrap: no atom selection for centersel", TCL_STATIC);
00205 return TCL_ERROR;
00206 }
00207
00208 } else if (!strupncmp(argvcur, "nogpu", CMDLEN)) {
00209 i--;
00210 gpu = false;
00211 } else if (!strupncmp(argvcur, "compound", CMDLEN)) {
00212 char *compoundarg = Tcl_GetStringFromObj(objv[i+1],NULL);
00213 if (!strupncmp(compoundarg, "fragment", CMDLEN)) {
00214 compound=1;
00215 } else if (!strupncmp(compoundarg, "residue", CMDLEN)) {
00216 compound=2;
00217 } else {
00218 Tcl_AppendResult(interp, "fastpbc wrap: invalid compound syntax, no such keyword: ", compoundarg, NULL);
00219 return TCL_ERROR;
00220 }
00221 } else {
00222 Tcl_AppendResult(interp, "fastpbc wrap: invalid syntax, no such keyword: ", argvcur, NULL);
00223 return TCL_ERROR;
00224 }
00225 }
00226 Molecule *mol = app->moleculeList->mol_from_id(sel->molid());
00227 int maxframes = mol->numframes();
00228 if (last < 0)
00229 last = maxframes-1;
00230 int err = check_timesteps(interp, mol, first, last);
00231 if (err == TCL_ERROR)
00232 return TCL_ERROR;
00233 float *weight = NULL;
00234 if (centersel != NULL) {
00235 if (centersel->molid() != sel->molid()) {
00236 Tcl_AppendResult(interp, "fastpbc wrap: selections are from different molecules", NULL);
00237 return TCL_ERROR;
00238 }
00239
00240 weight = new float[centersel->selected];
00241 {
00242 int ret_val = tcl_get_weights(interp, app, centersel, Tcl_NewStringObj("mass\0",-1), weight);
00243 if (ret_val < 0) {
00244 Tcl_AppendResult(interp, "fastpbc wrap: ", measure_error(ret_val),
00245 NULL);
00246 delete [] weight;
00247 return TCL_ERROR;
00248 }
00249 }
00250 }
00251
00252 int *indexlist = NULL;
00253 int *compoundmap = NULL;
00254 int fnum = 0;
00255 if (compound) {
00256 fnum = compoundmapper (compound, mol, sel, indexlist, compoundmap);
00257 }
00258
00259 float *massarr;
00260 if (compound) { massarr = mol->mass(); }
00261 if (compound) {
00262 if (gpu)
00263 fpbc_exec_wrapcompound(mol, first, last, fnum, compoundmap, sel->selected, indexlist, weight, centersel, center, massarr);
00264 else
00265 fpbc_exec_wrapcompound_cpu(mol, first, last, fnum, compoundmap, sel->selected, indexlist, weight, centersel, center, massarr);
00266 }
00267 else {
00268
00269 indexlist = new int[sel->selected];
00270 j = 0;
00271 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00272 if (sel->on[i]) {
00273 indexlist[j++] = i;
00274 }
00275 }
00276 if (gpu)
00277 fpbc_exec_wrapatomic(mol, first, last, sel->selected, indexlist, weight, centersel, center);
00278 else
00279 fpbc_exec_wrapatomic_cpu(mol, first, last, sel->selected, indexlist, weight, centersel, center);
00280 }
00281 if (weight != NULL) {
00282 delete [] weight;
00283 }
00284 if (indexlist != NULL) {
00285 delete [] indexlist;
00286 }
00287 if (compoundmap != NULL) {
00288 delete [] compoundmap;
00289 }
00290
00291 mol->force_recalc(DrawMolItem::MOL_REGEN);
00292 return TCL_OK;
00293 }
00294
00295
00296
00297
00298
00299
00326 static int fpbc_unwrap(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00327 int first = 0;
00328 int last = -1;
00329 int i, j;
00330 bool gpu = true;
00331
00332 if (argc < 2) {
00333 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [first <first>] [last <last>]");
00334 return TCL_ERROR;
00335 }
00336 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00337 if (!sel) {
00338 Tcl_SetResult(interp, (char *) "fastpbc unwrap: no atom selection", TCL_STATIC);
00339 return TCL_ERROR;
00340 }
00341
00342 for (i=2; i<argc; i+=2) {
00343 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00344 if (!strupncmp(argvcur, "first", CMDLEN)) {
00345 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00346 Tcl_AppendResult(interp, "fastpbc unwrap: bad first frame value", NULL);
00347 return TCL_ERROR;
00348 }
00349 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00350 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00351 Tcl_AppendResult(interp, "fastpbc unwrap: bad last frame value", NULL);
00352 return TCL_ERROR;
00353 }
00354 } else if (!strupncmp(argvcur, "nogpu", CMDLEN)) {
00355 i--;
00356 gpu = false;
00357 } else {
00358 Tcl_AppendResult(interp, "fastpbc unwrap: invalid syntax, no such keyword: ", argvcur, NULL);
00359 return TCL_ERROR;
00360 }
00361 }
00362 Molecule *mol = app->moleculeList->mol_from_id(sel->molid());
00363 int maxframes = mol->numframes();
00364 if (last < 0)
00365 last = maxframes-1;
00366 if (last == first) {
00367 Tcl_AppendResult(interp, "fastpbc unwrap: first and last frames must be distinct", NULL);
00368 return TCL_ERROR;
00369 }
00370 int err = check_timesteps(interp, mol, first, last);
00371 if (err == TCL_ERROR)
00372 return TCL_ERROR;
00373 int *indexlist = new int[sel->selected];
00374 j = 0;
00375 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00376 if (sel->on[i]) {
00377 indexlist[j++] = i;
00378 }
00379 }
00380
00381
00382 if (gpu)
00383 fpbc_exec_unwrap(mol, first, last, sel->selected, indexlist);
00384 else
00385 fpbc_exec_unwrap_cpu(mol, first, last, sel->selected, indexlist);
00386 if (indexlist != NULL) {
00387 delete [] indexlist;
00388 }
00389
00390 mol->force_recalc(DrawMolItem::MOL_REGEN);
00391 return TCL_OK;
00392 }
00393
00411 static int fpbc_join(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00412 int first = 0;
00413 int last = -1;
00414 int i;
00415 bool gpu = true;
00416 int compound = 1;
00417
00418 if (argc < 2) {
00419 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [first <first>] [last <last>] [compound residue/fragment]");
00420 return TCL_ERROR;
00421 }
00422 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00423 if (!sel) {
00424 Tcl_SetResult(interp, (char *) "fastpbc join: no atom selection", TCL_STATIC);
00425 return TCL_ERROR;
00426 }
00427
00428 for (i=2; i<argc; i+=2) {
00429 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00430 if (!strupncmp(argvcur, "first", CMDLEN)) {
00431 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00432 Tcl_AppendResult(interp, "fastpbc join: bad first frame value", NULL);
00433 return TCL_ERROR;
00434 }
00435 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00436 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00437 Tcl_AppendResult(interp, "fastpbc join: bad last frame value", NULL);
00438 return TCL_ERROR;
00439 }
00440 } else if (!strupncmp(argvcur, "nogpu", CMDLEN)) {
00441 i--;
00442 gpu = false;
00443 } else if (!strupncmp(argvcur, "compound", CMDLEN)) {
00444 char *compoundarg = Tcl_GetStringFromObj(objv[i+1],NULL);
00445 if (!strupncmp(compoundarg, "fragment", CMDLEN)) {
00446 compound=1;
00447 } else if (!strupncmp(compoundarg, "residue", CMDLEN)) {
00448 compound=2;
00449 } else {
00450 Tcl_AppendResult(interp, "fastpbc join: invalid compound syntax, no such keyword: ", compoundarg, NULL);
00451 return TCL_ERROR;
00452 }
00453 } else {
00454 Tcl_AppendResult(interp, "fastpbc join: invalid syntax, no such keyword: ", argvcur, NULL);
00455 return TCL_ERROR;
00456 }
00457 }
00458 Molecule *mol = app->moleculeList->mol_from_id(sel->molid());
00459 int maxframes = mol->numframes();
00460 if (last < 0)
00461 last = maxframes-1;
00462 int err = check_timesteps(interp, mol, first, last);
00463 if (err == TCL_ERROR)
00464 return TCL_ERROR;
00465 int *indexlist = NULL;
00466 int *compoundmap = NULL;
00467 int fnum = 0;
00468 if (compound) {
00469 fnum = compoundmapper (compound, mol, sel, indexlist, compoundmap);
00470 }
00471 if (gpu)
00472 fpbc_exec_join(mol, first, last, fnum, compoundmap, sel->selected, indexlist);
00473 else
00474 fpbc_exec_join_cpu(mol, first, last, fnum, compoundmap, sel->selected, indexlist);
00475 if (indexlist != NULL) {
00476 delete [] indexlist;
00477 }
00478 if (compoundmap != NULL) {
00479 delete [] compoundmap;
00480 }
00481
00482 mol->force_recalc(DrawMolItem::MOL_REGEN);
00483 return TCL_OK;
00484 }
00485
00486 static int fpbc_recenter(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00487 int first = 0;
00488 int last = -1;
00489 int i, j;
00490 bool gpu = true;
00491 int compound = 0;
00492
00493 if (argc < 3) {
00494 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> <centersel> [first <first>] [last <last>] [compound residue/fragment]");
00495 return TCL_ERROR;
00496 }
00497 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00498 if (!sel) {
00499 Tcl_SetResult(interp, (char *) "fastpbc recenter: no atom selection", TCL_STATIC);
00500 return TCL_ERROR;
00501 }
00502 AtomSel *csel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
00503 if (!sel) {
00504 Tcl_SetResult(interp, (char *) "fastpbc recenter: no center atom selection", TCL_STATIC);
00505 return TCL_ERROR;
00506 }
00507 for (i=3; i<argc; i+=2) {
00508 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00509 if (!strupncmp(argvcur, "first", CMDLEN)) {
00510 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00511 Tcl_AppendResult(interp, "fastpbc recenter: bad first frame value", NULL);
00512 return TCL_ERROR;
00513 }
00514 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00515 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00516 Tcl_AppendResult(interp, "fastpbc recenter: bad last frame value", NULL);
00517 return TCL_ERROR;
00518 }
00519 } else if (!strupncmp(argvcur, "nogpu", CMDLEN)) {
00520 i--;
00521 gpu = false;
00522 } else if (!strupncmp(argvcur, "compound", CMDLEN)) {
00523 char *compoundarg = Tcl_GetStringFromObj(objv[i+1],NULL);
00524 if (!strupncmp(compoundarg, "fragment", CMDLEN)) {
00525 compound=1;
00526 } else if (!strupncmp(compoundarg, "residue", CMDLEN)) {
00527 compound=2;
00528 } else {
00529 Tcl_AppendResult(interp, "fastpbc recenter: invalid compound syntax, no such keyword: ", compoundarg, NULL);
00530 return TCL_ERROR;
00531 }
00532 } else {
00533 Tcl_AppendResult(interp, "fastpbc recenter: invalid syntax, no such keyword: ", argvcur, NULL);
00534 return TCL_ERROR;
00535 }
00536 }
00537
00538 Molecule *mol = app->moleculeList->mol_from_id(sel->molid());
00539 int maxframes = mol->numframes();
00540 if (last < 0)
00541 last = maxframes-1;
00542
00543 int err = check_timesteps(interp, mol, first, last);
00544 if (err == TCL_ERROR)
00545 return TCL_ERROR;
00546 if (csel->molid() != sel->molid()) {
00547 Tcl_AppendResult(interp, "fastpbc recenter: selections are from different molecules", NULL);
00548 return TCL_ERROR;
00549 }
00550 float *weight = new float[csel->selected];
00551 int ret_val = tcl_get_weights(interp, app, csel, Tcl_NewStringObj("mass\0",-1), weight);
00552 if (ret_val < 0) {
00553 Tcl_AppendResult(interp, "fastpbc recenter: ", measure_error(ret_val),NULL);
00554 delete [] weight;
00555 return TCL_ERROR;
00556 }
00557 int *indexlist = NULL;
00558 int *centeridxlist = new int[csel->selected];
00559 j = 0;
00560 for (i=csel->firstsel; i<=csel->lastsel; i++) {
00561 if (csel->on[i]) {
00562 centeridxlist[j++] = i;
00563 }
00564 }
00565
00566 float *massarr = NULL;
00567 if (compound) { massarr = mol->mass(); }
00568 int *compoundmap = NULL;
00569 int fnum = 0;
00570 if (compound) {
00571 fnum = compoundmapper (compound, mol, sel, indexlist, compoundmap);
00572 }
00573 else {
00574
00575 indexlist = new int[sel->selected];
00576 j = 0;
00577 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00578 if (sel->on[i]) {
00579 indexlist[j++] = i;
00580 }
00581 }
00582 }
00583 if (gpu)
00584 fpbc_exec_recenter(mol, first, last, csel->selected, centeridxlist, fnum, compoundmap, sel->selected, indexlist, weight, csel, massarr);
00585 else
00586 fpbc_exec_recenter_cpu(mol, first, last, csel->selected, centeridxlist, fnum, compoundmap, sel->selected, indexlist, weight, csel, massarr);
00587 if (weight != NULL) {
00588 delete [] weight;
00589 }
00590 if (indexlist != NULL) {
00591 delete [] indexlist;
00592 }
00593 if (centeridxlist != NULL) {
00594 delete [] centeridxlist;
00595 }
00596 if (compoundmap != NULL) {
00597 delete [] compoundmap;
00598 }
00599
00600 mol->force_recalc(DrawMolItem::MOL_REGEN);
00601 return TCL_OK;
00602 }
00614 int obj_fastpbc(ClientData cd, Tcl_Interp *interp, int argc,
00615 Tcl_Obj * const objv[]) {
00616 if (argc < 2) {
00617 Tcl_SetResult(interp,
00618 (char *) "usage: fastpbc <command> [args...]\n"
00619 "\nFastPBC Commands:\n"
00620 " wrap <sel> [first <first>] [last <last>] [center [list x y z]] [centersel <sel>]\n"
00621 " [compound residue/fragment]-- (re)wraps trajectory\n"
00622 " unwrap <sel> [first <first>] [last <last>] -- prevents atoms from \"jumping\" during\n"
00623 " a trajectory across a periodic boundary\n"
00624 " join <sel> [first <first>] [last <last>] [compound residue/fragment]\n"
00625 " -- Eliminates long bonds within a compound (by default, by fragment)\n"
00626 " recenter <sel> <centersel> [first <first>] [last <last>] [compound residue/fragment]\n"
00627 " --Identical to an unwrap followed by a wrap. The unwrap is applied only to centersel,\n"
00628 " and the wrap is also centered on centersel\n",
00629 TCL_STATIC);
00630 return TCL_ERROR;
00631 }
00632 VMDApp *app = (VMDApp *)cd;
00633 char *argv1 = Tcl_GetStringFromObj(objv[1],NULL);
00634 if (!strupncmp(argv1, "wrap", CMDLEN))
00635 return fpbc_wrap(app, argc-1, objv+1, interp);
00636 else if (!strupncmp(argv1, "unwrap", CMDLEN))
00637 return fpbc_unwrap(app, argc-1, objv+1, interp);
00638 else if (!strupncmp(argv1, "join", CMDLEN))
00639 return fpbc_join(app, argc-1, objv+1, interp);
00640 else if (!strupncmp(argv1, "recenter", CMDLEN))
00641 return fpbc_recenter(app, argc-1, objv+1, interp);
00642 Tcl_SetResult(interp, (char *) "Type 'fastpbc' for summary of usage\n", TCL_VOLATILE);
00643 return TCL_OK;
00644 }
00645
00646
00647