00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <math.h>
00025 #include "Measure.h"
00026 #include "AtomSel.h"
00027 #include "Matrix4.h"
00028 #include "utilities.h"
00029 #include "fitrms.h"
00030 #include "ResizeArray.h"
00031 #include "SpatialSearch.h"
00032 #include "MoleculeList.h"
00033 #include "Inform.h"
00034 #include "Timestep.h"
00035 #include "VMDApp.h"
00036
00037
00038
00039
00040
00041 void orthonormal_basis(const float b[9], float e[9]) {
00042 float ob[3*3];
00043 vec_copy(ob+0, b+0);
00044 vec_copy(e+0, ob+0);
00045 vec_normalize(e+0);
00046 vec_triad(ob+3, b+3, -dot_prod(e+0, b+3), e+0);
00047 vec_copy(e+3, ob+3);
00048 vec_normalize(e+3);
00049 vec_triad(ob+6, b+6, -dot_prod(e+0, b+6), e+0);
00050 vec_triad(ob+6, ob+6, -dot_prod(e+3, b+6), e+3);
00051 vec_copy(e+6, ob+6);
00052 vec_normalize(e+6);
00053 }
00054
00055
00056
00057
00058
00059
00060 void basis_change(const float *base, const float *obase, float *newcoor, int n) {
00061 int i, j;
00062 for (i=0; i<n; i++) {
00063 for (j=0; j<n; j++) {
00064 newcoor[n*i+j] = dot_prod(&base[n*j], &obase[n*i]);
00065 }
00066 }
00067 }
00068
00069
00070
00071
00072 int measure_pbc2onc(MoleculeList *mlist, int molid, int frame, const float origin[3], Matrix4 &transform) {
00073 int orig_ts, max_ts;
00074
00075 Molecule *mol = mlist->mol_from_id(molid);
00076 if( !mol )
00077 return MEASURE_ERR_NOMOLECULE;
00078
00079
00080 if((orig_ts = mol->frame()) < 0)
00081 return MEASURE_ERR_NOFRAMES;
00082
00083
00084 max_ts = mol->numframes()-1;
00085 if (frame==-2) frame = orig_ts;
00086 else if (frame>max_ts || frame==-1) frame = max_ts;
00087
00088 Timestep *ts = mol->get_frame(frame);
00089
00090 Matrix4 AA, BB, CC;
00091 ts->get_transforms(AA, BB, CC);
00092
00093
00094 float cell[9];
00095 cell[0] = AA.mat[12];
00096 cell[1] = AA.mat[13];
00097 cell[2] = AA.mat[14];
00098 cell[3] = BB.mat[12];
00099 cell[4] = BB.mat[13];
00100 cell[5] = BB.mat[14];
00101 cell[6] = CC.mat[12];
00102 cell[7] = CC.mat[13];
00103 cell[8] = CC.mat[14];
00104
00105 get_transform_to_orthonormal_cell(cell, origin, transform);
00106
00107 return MEASURE_NOERR;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 void get_transform_to_orthonormal_cell(const float *cell, const float *center, Matrix4 &transform) {
00137
00138
00139
00140
00141
00142
00143 float obase[3*3];
00144 orthonormal_basis(cell, obase);
00145
00146
00147
00148 float identity[3*3] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
00149 float obase_cartcoor[3*3];
00150 basis_change(obase, identity, obase_cartcoor, 3);
00151
00152
00153
00154 Matrix4 obase2cartinv;
00155 trans_from_rotate(obase_cartcoor, &obase2cartinv);
00156
00157
00158 Matrix4 obase2cart = obase2cartinv;
00159 obase2cart.inverse();
00160
00161
00162 float m[3*3];
00163 basis_change(cell, obase, m, 3);
00164 Matrix4 rotmat;
00165 trans_from_rotate(m, &rotmat);
00166 rotmat.inverse();
00167
00168
00169
00170
00171
00172
00173 transform = obase2cart;
00174 transform.multmatrix(rotmat);
00175
00176
00177 float origin[3];
00178 vec_copy(origin, center);
00179 vec_scaled_add(origin, -0.5, &cell[0]);
00180 vec_scaled_add(origin, -0.5, &cell[3]);
00181 vec_scaled_add(origin, -0.5, &cell[6]);
00182 vec_negate(origin, origin);
00183
00184 transform.translate(origin);
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 int measure_pbc_neighbors(MoleculeList *mlist, AtomSel *sel, int molid,
00220 int frame, const Matrix4 *alignment,
00221 const float *center, const float *cutoff, const float *box,
00222 ResizeArray<float> *extcoord_array,
00223 ResizeArray<int> *indexmap_array) {
00224 int orig_ts, max_ts;
00225 if (!box && !cutoff[0] && !cutoff[1] && !cutoff[2]) return MEASURE_NOERR;
00226
00227 Molecule *mol = mlist->mol_from_id(molid);
00228 if( !mol )
00229 return MEASURE_ERR_NOMOLECULE;
00230
00231
00232 if((orig_ts = mol->frame()) < 0)
00233 return MEASURE_ERR_NOFRAMES;
00234
00235
00236 max_ts = mol->numframes()-1;
00237 if (frame==-2) frame = orig_ts;
00238 else if (frame>max_ts || frame==-1) frame = max_ts;
00239
00240 Timestep *ts = mol->get_frame(frame);
00241 if (!ts) return MEASURE_ERR_NOMOLECULE;
00242
00243
00244 Matrix4 Tpbc[3][2];
00245 ts->get_transforms(Tpbc[0][1], Tpbc[1][1], Tpbc[2][1]);
00246
00247
00248 Tpbc[0][0] = Tpbc[0][1];
00249 Tpbc[1][0] = Tpbc[1][1];
00250 Tpbc[2][0] = Tpbc[2][1];
00251 Tpbc[0][0].inverse();
00252 Tpbc[1][0].inverse();
00253 Tpbc[2][0].inverse();
00254
00255
00256 float cell[9];
00257 cell[0] = Tpbc[0][1].mat[12];
00258 cell[1] = Tpbc[0][1].mat[13];
00259 cell[2] = Tpbc[0][1].mat[14];
00260 cell[3] = Tpbc[1][1].mat[12];
00261 cell[4] = Tpbc[1][1].mat[13];
00262 cell[5] = Tpbc[1][1].mat[14];
00263 cell[6] = Tpbc[2][1].mat[12];
00264 cell[7] = Tpbc[2][1].mat[13];
00265 cell[8] = Tpbc[2][1].mat[14];
00266
00267 float len[3];
00268 len[0] = sqrtf(dot_prod(&cell[0], &cell[0]));
00269 len[1] = sqrtf(dot_prod(&cell[3], &cell[3]));
00270 len[2] = sqrtf(dot_prod(&cell[6], &cell[6]));
00271
00272
00273 int i;
00274 float minlen = len[0];
00275 if (len[1] && len[1]<minlen) minlen = len[1];
00276 if (len[2] && len[2]<minlen) minlen = len[2];
00277 minlen--;
00278
00279
00280 if (!box && (cutoff[0]>=len[0] || cutoff[1]>=len[1] || cutoff[2]>=len[2])) {
00281 return MEASURE_ERR_BADCUTOFF;
00282 }
00283
00284 bool bigrim = 1;
00285 float corecell[9];
00286 float diag[3];
00287 float origin[3];
00288 memset(origin, 0, 3*sizeof(float));
00289 Matrix4 M_norm;
00290
00291 if (box) {
00292
00293
00294
00295 bigrim = 1;
00296
00297 float vtmp[3];
00298 vec_add(vtmp, &cell[0], &cell[3]);
00299 vec_add(diag, &cell[6], vtmp);
00300
00301
00302
00303 vec_copy(origin, center);
00304 vec_scaled_add(origin, -0.5, &cell[0]);
00305 vec_scaled_add(origin, -0.5, &cell[3]);
00306 vec_scaled_add(origin, -0.5, &cell[6]);
00307 vec_negate(origin, origin);
00308
00309
00310 } else if (2.0f*cutoff[0]<minlen && 2.0f*cutoff[1]<minlen && 2.0f*cutoff[2]<minlen) {
00311
00312
00313
00314
00315
00316
00317 vec_scale(&corecell[0], (len[0]-cutoff[0])/len[0], &cell[0]);
00318 vec_scale(&corecell[3], (len[1]-cutoff[1])/len[1], &cell[3]);
00319 vec_scale(&corecell[6], (len[2]-cutoff[2])/len[2], &cell[6]);
00320 get_transform_to_orthonormal_cell(corecell, center, M_norm);
00321
00322
00323 } else {
00324
00325
00326 get_transform_to_orthonormal_cell(cell, center, M_norm);
00327
00328 bigrim = 1;
00329
00330 }
00331
00332
00333
00334
00335
00336 Matrix4 alignmentinv(*alignment);
00337 alignmentinv.inverse();
00338 Matrix4 M_coretransform(M_norm);
00339 M_coretransform.multmatrix(alignmentinv);
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 int j, u;
00351 Matrix4 Tpbc_aligned[3][2];
00352 if (!box) {
00353 for (i=0; i<3; i++) {
00354 for (j=0; j<2; j++) {
00355 Tpbc_aligned[i][j].loadmatrix(*alignment);
00356 Tpbc_aligned[i][j].multmatrix(Tpbc[i][j]);
00357 Tpbc_aligned[i][j].multmatrix(alignmentinv);
00358 }
00359 }
00360 }
00361
00362 Matrix4 M[3];
00363 float *coords = ts->pos;
00364 float *coor;
00365 float orthcoor[3], wrapcoor[3];
00366
00367
00368
00369 if (box) {
00370 float min_coord[3], max_coord[3];
00371
00372 vec_sub(min_coord, box, cutoff);
00373 vec_add(max_coord, box+3, cutoff);
00374
00375
00376
00377 vec_add(min_coord, min_coord, origin);
00378 vec_add(max_coord, max_coord, origin);
00379
00380 float testcoor[9];
00381 int idx, k;
00382
00383 for (idx=0; idx<ts->num; idx++) {
00384 coor = coords+3*idx;
00385
00386
00387
00388 M_coretransform.multpoint3d(coor, orthcoor);
00389
00390
00391
00392 for (i=-1; i<=1; i++) {
00393
00394 if (i>0) M[0].loadmatrix(Tpbc[0][1]);
00395 else if (i<0) M[0].loadmatrix(Tpbc[0][0]);
00396 else M[0].identity();
00397
00398 M[0].multpoint3d(orthcoor, testcoor);
00399
00400
00401 for (j=-1; j<=1; j++) {
00402
00403 if (j>0) M[1].loadmatrix(Tpbc[1][1]);
00404 else if (j<0) M[1].loadmatrix(Tpbc[1][0]);
00405 else M[1].identity();
00406
00407 M[1].multpoint3d(testcoor, testcoor+3);
00408
00409
00410 for (k=-1; k<=1; k++) {
00411 if(i==0 && j==0 && k==0) continue;
00412
00413
00414 if (k>0) M[2].loadmatrix(Tpbc[2][1]);
00415 else if (k<0) M[2].loadmatrix(Tpbc[2][0]);
00416 else M[2].identity();
00417
00418 M[2].multpoint3d(testcoor+3, testcoor+6);
00419
00420
00421 alignment->multpoint3d(testcoor+6, wrapcoor);
00422
00423 vec_add(testcoor+6, wrapcoor, origin);
00424 if (testcoor[6]<min_coord[0] || testcoor[6]>max_coord[0]) continue;
00425 if (testcoor[7]<min_coord[1] || testcoor[7]>max_coord[1]) continue;
00426 if (testcoor[8]<min_coord[2] || testcoor[8]>max_coord[2]) continue;
00427
00428
00429 for (int n=0; n<3; n++) extcoord_array->append(wrapcoor[n]);
00430 indexmap_array->append(idx);
00431 }
00432 }
00433 }
00434 }
00435
00436 } else if (bigrim) {
00437
00438
00439
00440 float min_coord[3], max_coord[3];
00441 min_coord[0] = -cutoff[0]/len[0];
00442 min_coord[1] = -cutoff[1]/len[1];
00443 min_coord[2] = -cutoff[2]/len[2];
00444 max_coord[0] = 1.0f + cutoff[0]/len[0];
00445 max_coord[1] = 1.0f + cutoff[1]/len[1];
00446 max_coord[2] = 1.0f + cutoff[2]/len[2];
00447
00448 float testcoor[3];
00449 int idx, k;
00450
00451 for (idx=0; idx<ts->num; idx++) {
00452 coor = coords+3*idx;
00453
00454
00455
00456 M_coretransform.multpoint3d(coor, orthcoor);
00457
00458
00459
00460 for (i=-1; i<=1; i++) {
00461 testcoor[0] = orthcoor[0]+(float)(i);
00462 if (testcoor[0]<min_coord[0] || testcoor[0]>max_coord[0]) continue;
00463
00464
00465 if (i>0) M[0].loadmatrix(Tpbc_aligned[0][1]);
00466 else if (i<0) M[0].loadmatrix(Tpbc_aligned[0][0]);
00467 else M[0].identity();
00468
00469
00470 for (j=-1; j<=1; j++) {
00471 testcoor[1] = orthcoor[1]+(float)(j);
00472 if (testcoor[1]<min_coord[1] || testcoor[1]>max_coord[1]) continue;
00473
00474
00475 if (j>0) M[1].loadmatrix(Tpbc_aligned[1][1]);
00476 else if (j<0) M[1].loadmatrix(Tpbc_aligned[1][0]);
00477 else M[1].identity();
00478
00479
00480 for (k=-1; k<=1; k++) {
00481 testcoor[2] = orthcoor[2]+(float)(k);
00482 if (testcoor[2]<min_coord[2] || testcoor[2]>max_coord[2]) continue;
00483
00484 if(i==0 && j==0 && k==0) continue;
00485
00486
00487 if (k>0) M[2].loadmatrix(Tpbc_aligned[2][1]);
00488 else if (k<0) M[2].loadmatrix(Tpbc_aligned[2][0]);
00489 else M[2].identity();
00490
00491 M[0].multpoint3d(coor, wrapcoor);
00492 M[1].multpoint3d(wrapcoor, wrapcoor);
00493 M[2].multpoint3d(wrapcoor, wrapcoor);
00494
00495
00496 for (int n=0; n<3; n++) extcoord_array->append(wrapcoor[n]);
00497 indexmap_array->append(idx);
00498 }
00499 }
00500 }
00501 }
00502
00503 } else {
00504 Matrix4 Mtmp;
00505
00506 for (i=0; i < ts->num; i++) {
00507
00508
00509 M_coretransform.multpoint3d(coords+3*i, orthcoor);
00510
00511
00512 int cellindex[3];
00513 if (orthcoor[0]<0) cellindex[0] = -1;
00514 else if (orthcoor[0]>1) cellindex[0] = 1;
00515 else cellindex[0] = 0;
00516 if (orthcoor[1]<0) cellindex[1] = -1;
00517 else if (orthcoor[1]>1) cellindex[1] = 1;
00518 else cellindex[1] = 0;
00519 if (orthcoor[2]<0) cellindex[2] = -1;
00520 else if (orthcoor[2]>1) cellindex[2] = 1;
00521 else cellindex[2] = 0;
00522
00523
00524 if (!cellindex[0] && !cellindex[1] && !cellindex[2]) continue;
00525
00526
00527 if (orthcoor[0]<0) M[0].loadmatrix(Tpbc_aligned[0][1]);
00528 else if (orthcoor[0]>1) M[0].loadmatrix(Tpbc_aligned[0][0]);
00529 if (orthcoor[1]<0) M[1].loadmatrix(Tpbc_aligned[1][1]);
00530 else if (orthcoor[1]>1) M[1].loadmatrix(Tpbc_aligned[1][0]);
00531 if (orthcoor[2]<0) M[2].loadmatrix(Tpbc_aligned[2][1]);
00532 else if (orthcoor[2]>1) M[2].loadmatrix(Tpbc_aligned[2][0]);
00533
00534
00535
00536 coor = coords+3*i;
00537 for (u=0; u<3; u++) {
00538 if (cellindex[u] && cutoff[u]) {
00539 M[u].multpoint3d(coor, wrapcoor);
00540 for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
00541 indexmap_array->append(i);
00542 }
00543 }
00544
00545 Mtmp = M[0];
00546
00547
00548 if (cellindex[0] && cellindex[1] && cutoff[0] && cutoff[1]) {
00549 M[0].multmatrix(M[1]);
00550 M[0].multpoint3d(coor, wrapcoor);
00551 for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
00552 indexmap_array->append(i);
00553 }
00554
00555
00556 if (cellindex[1] && cellindex[2] && cutoff[1] && cutoff[2]) {
00557 M[1].multmatrix(M[2]);
00558 M[1].multpoint3d(coor, wrapcoor);
00559 for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
00560 indexmap_array->append(i);
00561 }
00562
00563
00564 if (cellindex[0] && cellindex[2] && cutoff[0] && cutoff[2]) {
00565 M[2].multmatrix(Mtmp);
00566 M[2].multpoint3d(coor, wrapcoor);
00567 for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
00568 indexmap_array->append(i);
00569 }
00570
00571
00572 if (cellindex[0] && cellindex[1] && cellindex[2]) {
00573 M[1].multmatrix(Mtmp);
00574 M[1].multpoint3d(coor, wrapcoor);
00575 for (j=0; j<3; j++) extcoord_array->append(wrapcoor[j]);
00576 indexmap_array->append(i);
00577 }
00578
00579 }
00580
00581 }
00582
00583
00584
00585 if (sel) {
00586 int numext = sel->selected+indexmap_array->num();
00587 float *extcoords = new float[3*numext];
00588 int *indexmap = new int[numext];
00589 int *others = new int[numext];
00590 memset(others, 0, numext);
00591
00592
00593 float maxcutoff = cutoff[0];
00594 for (i=1; i<3; i++) {
00595 if (cutoff[i]>maxcutoff) maxcutoff = cutoff[i];
00596 }
00597
00598
00599 j=0;
00600 for (i=0; i < sel->num_atoms; i++) {
00601 if (!sel->on[i]) continue;
00602 extcoords[3*j] = coords[3*i];
00603 extcoords[3*j+1] = coords[3*i+1];
00604 extcoords[3*j+2] = coords[3*i+2];
00605 indexmap[j] = i;
00606 others[j++] = 1;
00607 }
00608 for (i=0; i<indexmap_array->num(); i++) {
00609 extcoords[3*j] = (*extcoord_array)[3*i];
00610 extcoords[3*j+1] = (*extcoord_array)[3*i+1];
00611 extcoords[3*j+2] = (*extcoord_array)[3*i+2];
00612 indexmap[j] = (*indexmap_array)[i];
00613 others[j++] = 0;
00614 }
00615
00616
00617 int *flgs = new int[numext];
00618 for (i=0; i<numext; i++) {
00619 flgs[i] = 1;
00620 }
00621
00622
00623
00624 find_within(extcoords, flgs, others, numext, maxcutoff);
00625
00626 extcoord_array->clear();
00627 indexmap_array->clear();
00628 for (i=sel->selected; i<numext; i++) {
00629 if (!flgs[i]) continue;
00630
00631 extcoord_array->append(extcoords[3*i]);
00632 extcoord_array->append(extcoords[3*i+1]);
00633 extcoord_array->append(extcoords[3*i+2]);
00634 indexmap_array->append(indexmap[i]);
00635 }
00636
00637 }
00638
00639 return MEASURE_NOERR;
00640 }
00641
00642
00643
00644
00645 int compute_pbcminmax(MoleculeList *mlist, int molid, const float *center,
00646 const Matrix4 *transform, float *min, float *max) {
00647 Molecule *mol = mlist->mol_from_id(molid);
00648 if( !mol )
00649 return MEASURE_ERR_NOMOLECULE;
00650
00651 Timestep *ts = mol->get_frame(0);
00652 if (!ts) return MEASURE_ERR_NOFRAMES;
00653
00654
00655 Matrix4 Tpbc[3];
00656 ts->get_transforms(Tpbc[0], Tpbc[1], Tpbc[2]);
00657
00658
00659 float cell[9];
00660 cell[0] = Tpbc[0].mat[12];
00661 cell[1] = Tpbc[0].mat[13];
00662 cell[2] = Tpbc[0].mat[14];
00663 cell[3] = Tpbc[1].mat[12];
00664 cell[4] = Tpbc[1].mat[13];
00665 cell[5] = Tpbc[1].mat[14];
00666 cell[6] = Tpbc[2].mat[12];
00667 cell[7] = Tpbc[2].mat[13];
00668 cell[8] = Tpbc[2].mat[14];
00669
00670 float len[3];
00671 len[0] = sqrtf(dot_prod(&cell[0], &cell[0]));
00672 len[1] = sqrtf(dot_prod(&cell[3], &cell[3]));
00673 len[2] = sqrtf(dot_prod(&cell[6], &cell[6]));
00674
00675
00676 float node[8*3];
00677 int n=0;
00678 float i, j, k;
00679 for (i=-0.5; i<1; i+=1.0) {
00680 for (j=-0.5; j<1; j+=1.0) {
00681 for (k=-0.5; k<1; k+=1.0) {
00682 vec_copy(node+3*n, center);
00683 vec_scaled_add(node+3*n, i, &cell[0]);
00684 vec_scaled_add(node+3*n, j, &cell[3]);
00685 vec_scaled_add(node+3*n, k, &cell[6]);
00686
00687
00688 transform->multpoint3d(node+3*n, node+3*n);
00689 n++;
00690 }
00691 }
00692 }
00693
00694 for (n=0; n<8; n++) {
00695 if (!n || node[3*n] < min[0]) min[0] = node[3*n];
00696 if (!n || node[3*n+1] < min[1]) min[1] = node[3*n+1];
00697 if (!n || node[3*n+2] < min[2]) min[2] = node[3*n+2];
00698 if (!n || node[3*n] > max[0]) max[0] = node[3*n];
00699 if (!n || node[3*n+1] > max[1]) max[1] = node[3*n+1];
00700 if (!n || node[3*n+2] > max[2]) max[2] = node[3*n+2];
00701 }
00702
00703 return MEASURE_NOERR;
00704 }