00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: TclFastPBC.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.5 $ $Date: 2021年10月29日 04:51:39 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Fast PBC wrapping code 00019 ***************************************************************************/ 00020 00021 #include <stdlib.h> 00022 #include <stdio.h> 00023 #include <tcl.h> 00024 // #include <ctype.h> 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 //Compound is the type of compounding: 1=fragment, 2=residue. 00037 //mol is the molecule we are operating on. Should come from app->moleculeList->mol_from_id(sel->molid()); 00038 //sel is the atomselection we are working on. 00039 //indexlist and fragmentmap are the output pointers. NOTE: It is the caller's responsibility to delete indexlist and fragmentmap. 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 //This should never happen. Ever. 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; //start with first frame by default 00154 int last = -1; //finish with last frame by default 00155 int i, j; 00156 bool gpu = true; 00157 int compound = 0; 00158 float center[3] = {0,0,0}; 00159 //Parse arguments! 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 //Find the center for this timestep and atomselection. 00240 weight = new float[centersel->selected]; 00241 { 00242 int ret_val = tcl_get_weights(interp, app, centersel, Tcl_NewStringObj("mass0円",-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 //End parse arguments. 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 // if compound, moving will require mass weighting. find the array storing mass values 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 //Create the indexlist 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 //Force a redraw since the atoms have moved. 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; // start with first frame by default 00328 int last = -1; // finish with last frame by default 00329 int i, j; 00330 bool gpu = true; 00331 //parameter handling 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 //Begin unwrapping! 00381 //Keep the current and previous timesteps, and make sure that every atom jumps by no more than half the boxlength. 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 //Force a redraw since the atoms have moved. 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; // start with first frame by default 00413 int last = -1; // finish with last frame by default 00414 int i; 00415 bool gpu = true; 00416 int compound = 1; //Default to fragment. 00417 //Deal with input. 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 //Force a redraw since the atoms have moved. 00482 mol->force_recalc(DrawMolItem::MOL_REGEN); 00483 return TCL_OK; 00484 } 00485 //recenter <sel> <centersel> [first <first>] [last <last>] [compound residue/fragment] 00486 static int fpbc_recenter(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) { 00487 int first = 0; // start with first frame by default 00488 int last = -1; // finish with last frame by default 00489 int i, j; 00490 bool gpu = true; 00491 int compound = 0; //Default to atomic wrap. 00492 //Deal with input. 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("mass0円",-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 // if compound, moving will require mass weighting. find the array storing mass values 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 //Create the indexlist 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 //Force a redraw since the atoms have moved. 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