// **************************************************************************** // Compute the (thin) singular value decomposition of a matrix A (size: rows x cols). // I.e. it finds U, D and V such that: // U.D.transpose(V) = A // V.transpose(V) = I // U.transpose(U) = I (if rows = cols) // The matricies U, D, V must already be allocated prior to calling this function. // Their required sizes are: U (rows x cols), D (cols x cols), V(cols x cols) // The contents of A are not changed. // **************************************************************************** void svd(double *A, long int rows, long int cols, double *U, double *D, double *V) { double **a, **v, *d; long int r, c; // Allocate the data structures which the core function expects a=dmatrix(1, rows, 1, cols); v=dmatrix(1, cols, 1, cols); d=dvector(1, cols); // Copy the input data into the core data structures for (r=1; r<=rows; r++) { for (c=1; c<=cols; c++) { a[r][c]=A[(r-1)*cols+(c-1)]; } } // Call the core function dsvdcmp(a, rows, cols, d, v); // Copy the output data into the output data structures for (r=1; r<=rows; r++) { for (c=1; c<=cols; c++) { U[(r-1)*cols+(c-1)]=a[r][c]; } } for (r=1; r<=cols; r++) { for (c=1; c<=cols; c++) { V[(r-1)*cols+(c-1)]=v[r][c]; } } for (r=1; r<=cols; r++) { for (c=1; c<=cols; c++) { if (r==c) D[(r-1)*cols+(c-1)]=d[c]; else D[(r-1)*cols+(c-1)]=0.0; } } // Free the core data structures free_dvector(d, 1, cols); free_dmatrix(v, 1, cols, 1, cols); free_dmatrix(a, 1, rows, 1, cols); return; }
/* "dblock_projections2" CALCULATES THE PROJECTION FROM FULL RESIDUE SPACE TO RIGID BLOCK SPACE */ int dblock_projections2(dSparse_Matrix *PP,PDB_File *PDB, int nres,int nblx,int bmx) { double **X,**I,**IC,*CM,*W,**A,**ISQT; double x,tr,dd,df; int *IDX,nbp,b,i,j,k,ii,jj,aa,bb,elm; /* INITIALIZE BLOCK ARRAYS */ elm=0; X=dmatrix(1,bmx,1,3); IDX=ivector(1,bmx); CM=dvector(1,3); I=dmatrix(1,3,1,3); IC=dmatrix(1,3,1,3); W=dvector(1,3); A=dmatrix(1,3,1,3); ISQT=dmatrix(1,3,1,3); /* CYCLE THROUGH BLOCKS */ for(b=1;b<=nblx;b++){ /* CLEAR MATRICES */ for(j=1;j<=3;j++){ CM[j]=0.0; for(i=1;i<=3;i++) I[i][j]=0.0; for(i=1;i<=bmx;i++) X[i][j]=0.0; } /* STORE VALUES FOR CURRENT BLOCK */ nbp=0; for(i=1;i<=nres;i++){ if(PDB->atom[i].model==b){ IDX[++nbp]=i; for(j=1;j<=3;j++){ x=(double)PDB->atom[i].X[j-1]; X[nbp][j]=x; CM[j]+=x; } } } /* TRANSLATE BLOCK CENTER OF MASS TO ORIGIN */ for(j=1;j<=3;j++) CM[j]/=(double)nbp; for(i=1;i<=nbp;i++) for(j=1;j<=3;j++) X[i][j]-=CM[j]; /* CALCULATE INERTIA TENSOR */ for(k=1;k<=nbp;k++){ dd=0.0; for(j=1;j<=3;j++){ df=X[k][j]; dd+=df*df; } for(i=1;i<=3;i++){ I[i][i]+=(dd-X[k][i]*X[k][i]); for(j=i+1;j<=3;j++){ I[i][j]-=X[k][i]*X[k][j]; I[j][i]=I[i][j]; } } } /* DIAGONALIZE INERTIA TENSOR */ for(i=1;i<=3;i++) for(j=1;j<=3;j++) IC[i][j]=I[i][j]; dsvdcmp(IC,3,3,W,A); deigsrt(W,A,3); righthand2(W,A,3); /* FIND ITS SQUARE ROOT */ for(i=1;i<=3;i++) for(j=1;j<=3;j++){ dd=0.0; for(k=1;k<=3;k++) dd+=A[i][k]*A[j][k]/sqrt(W[k]); ISQT[i][j]=dd; } /* UPDATE PP WITH THE RIGID MOTIONS OF THE BLOCK */ tr=1.0/sqrt((double)nbp); for(i=1;i<=nbp;i++){ /* TRANSLATIONS: 3*(IDX[i]-1)+1 = x-COORDINATE OF RESIDUE IDX[i]; 6*(b-1)+1 = x-COORDINATE OF BLOCK b */ for(j=1;j<=3;j++){ elm++; PP->IDX[elm][1] = 3*(IDX[i]-1)+j; PP->IDX[elm][2] = 6*(b-1)+j; PP->X[elm] = tr; } /* ROTATIONS */ if(nbp>1){ for(ii=1;ii<=3;ii++){ for(jj=1;jj<=3;jj++){ if(jj==1) {aa=2; bb=3;} else if(jj==2) {aa=3; bb=1;} else {aa=1; bb=2;} dd=ISQT[ii][aa]*X[i][bb]-ISQT[ii][bb]*X[i][aa]; elm++; PP->IDX[elm][1] = 3*(IDX[i]-1)+jj; PP->IDX[elm][2] = 6*(b-1)+3+ii; PP->X[elm] = dd; } } } } } free_dmatrix(X,1,bmx,1,3); free_ivector(IDX,1,bmx); free_dvector(CM,1,3); free_dmatrix(I,1,3,1,3); free_dmatrix(IC,1,3,1,3); free_dvector(W,1,3); free_dmatrix(A,1,3,1,3); free_dmatrix(ISQT,1,3,1,3); return elm; }