public static Mode[] GetModesFromHess(Matrix hess, ILinAlg la) { List <Mode> modes; { Matrix V; Vector D; switch (la) { case null: using (new Matlab.NamedLock("")) { Matlab.PutMatrix("H", hess, true); Matlab.Execute("H = (H + H')/2;"); Matlab.Execute("[V,D] = eig(H);"); Matlab.Execute("D = diag(D);"); V = Matlab.GetMatrix("V", true); D = Matlab.GetVector("D", true); } break; default: { var H = la.ToILMat(hess); H = (H + H.Tr) / 2; var VD = la.EigSymm(H); V = VD.Item1.ToMatrix(); D = VD.Item2; H.Dispose(); VD.Item1.Dispose(); } break; } int[] idxs = D.ToArray().HAbs().HIdxSorted(); modes = new List <Mode>(idxs.Length); //foreach(int idx in idxs) for (int th = 0; th < idxs.Length; th++) { int idx = idxs[th]; Mode mode = new Mode { th = (th + 1), eigval = D[idx], eigvec = V.GetColVector(idx) }; modes.Add(mode); } } System.GC.Collect(); return(modes.ToArray()); }
public static double[] GetRotAngles(Universe univ , Vector[] coords , Vector[] dcoords , MatrixByArr J = null , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null , List <Universe.RotableInfo> univ_rotinfos = null , Vector[] dcoordsRotated = null ) { if (J == null) { if (univ_rotinfos == null) { if (univ_flexgraph == null) { univ_flexgraph = univ.BuildFlexibilityGraph(); } univ_rotinfos = univ.GetRotableInfo(univ_flexgraph); } J = TNM.GetJ(univ, coords, univ_rotinfos); } double[] dangles; using (new Matlab.NamedLock("TEST")) { Matlab.Clear("TEST"); Matlab.PutVector("TEST.R", Vector.FromBlockvector(dcoords)); Matlab.PutMatrix("TEST.J", J.ToArray(), true); Matlab.PutVector("TEST.M", univ.GetMasses(3)); Matlab.Execute("TEST.M = diag(TEST.M);"); Matlab.Execute("TEST.invJMJ = inv(TEST.J' * TEST.M * TEST.J);"); Matlab.Execute("TEST.A = TEST.invJMJ * TEST.J' * TEST.M * TEST.R;"); // (6) of TNM paper dangles = Matlab.GetVector("TEST.A"); if (dcoordsRotated != null) { HDebug.Assert(dcoordsRotated.Length == dcoords.Length); Matlab.Execute("TEST.dR = TEST.J * TEST.A;"); Vector ldcoordsRotated = Matlab.GetVector("TEST.dR"); HDebug.Assert(ldcoordsRotated.Size == dcoordsRotated.Length * 3); for (int i = 0; i < dcoordsRotated.Length; i++) { int i3 = i * 3; dcoordsRotated[i] = new double[] { ldcoordsRotated[i3 + 0], ldcoordsRotated[i3 + 1], ldcoordsRotated[i3 + 2] }; } } Matlab.Clear("TEST"); } return(dangles); }
public static Matrix GetCorrMatrixMatlab(this IList <Mode> modes) { if (HDebug.Selftest()) { HDebug.Assert(GetCorrMatrix_SelfTest(modes, GetCorrMatrixMatlab)); } // Dii = zeros(n, 1); // For[i=1, i<=nmodes, i++, // Dii = Dii + Table[Dot[vec,vec],{vec,modei}]/eigvi; // ]; // Dij = zeros(n, n); // For[i=1, i<=nmodes, i++, // Dijx = Dijx + modei_x.Transpose[modei_x] / eigvi; // Dijy = Dijy + modei_y.Transpose[modei_y] / eigvi; // Dijz = Dijz + modei_z.Transpose[modei_z] / eigvi; // Dii = Dii + Table[Dot[vec,vec],{vec,modei}]/eigvi; // ]; // Dij = Dij / nmodes; // Dii = Dii / nmodes; // Cij = Dij / Sqrt[Transpose[{Dii}].{Dii}]; // corr = Cij; Matrix MD = modes.ListEigvec().ToMatrix(); Vector EV = modes.ListEigval().ToArray(); Matrix corrmat; using (new Matlab.NamedLock("")) { Matlab.Clear(); Matlab.PutMatrix("MD", MD, true); Matlab.PutVector("EV", EV); Matlab.Execute("nmodes = length(EV);"); Matlab.Execute("iEV = diag(1 ./ EV);"); Matlab.Execute("Dijx = MD(1:3:end,:); Dijx = Dijx*iEV*Dijx'; Dij= Dijx; clear Dijx;"); Matlab.Execute("Dijy = MD(2:3:end,:); Dijy = Dijy*iEV*Dijy'; Dij=Dij+Dijy; clear Dijy;"); Matlab.Execute("Dijz = MD(3:3:end,:); Dijz = Dijz*iEV*Dijz'; Dij=Dij+Dijz; clear Dijz;"); Matlab.Execute("clear MD; clear EV; clear iEV;"); Matlab.Execute("Dij = Dij / nmodes;"); Matlab.Execute("Dii = diag(Dij);"); Matlab.Execute("Dij = Dij ./ sqrt(Dii*Dii');"); corrmat = Matlab.GetMatrix("Dij", true); } return(corrmat); }
public Mode[] GetAllModes() { if (_allmodes == null) { Mode[] rtbmodes = GetRtbModes(); Matrix M = rtbmodes.ListEigvecAsMatrix(); if (HDebug.IsDebuggerAttached) #region check if each colume of M is same to its corresponding eigvector { for (int r = 0; r < M.RowSize; r++) { Vector colvec_r = M.GetColVector(r); double err = (colvec_r - rtbmodes[r].eigvec).ToArray().HAbs().Max(); HDebug.Assert(err == 0); } } #endregion Matrix PM = null; using (new Matlab.NamedLock("")) { Matlab.PutMatrix("P", P, true); Matlab.PutMatrix("M", M, true); PM = Matlab.GetMatrix("P*M", true); } _allmodes = new Mode[rtbmodes.Length]; for (int i = 0; i < rtbmodes.Length; i++) { _allmodes[i] = new Mode { th = rtbmodes[i].th, eigval = rtbmodes[i].eigval, eigvec = PM.GetColVector(i), }; // mass-weighted, mass-reduced is already handled in GetRtbModes() using "PMP" and "PMPih". // HDebug.ToDo("check if each mode should be devided by masses (or not)"); // //for(int j=0; j<_allmodes[i].eigvec.Size; j++) // // _allmodes[i].eigvec[j] = _allmodes[i].eigvec[j] / masses[j/3]; } } return(_allmodes); }
public static double SimFluc(IList <Mode> modes1, IList <Mode> modes2) { /// need to confirm again... /// Matrix M1 = modes1.ToModeMatrix(); Vector V1 = modes1.ToArray().ListEigval(); Matrix M2 = modes2.ToModeMatrix(); Vector V2 = modes2.ToArray().ListEigval(); using (new Matlab.NamedLock("SimFluc")) { Matlab.Execute(""); Matlab.Execute("clear"); Matlab.PutMatrix("MM1", M1); Matlab.PutVector("VV1", V1); Matlab.PutMatrix("MM2", M2); Matlab.PutVector("VV2", V2); Matlab.Execute("[U2,S2,V2] = svd(MM2);"); Matlab.Execute("U2 = U2(:, 1:length(VV2));"); Matlab.Execute("S2 = S2(1:length(VV2), :);"); Matlab.Execute("invSV2 = diag(1./diag(S2))*V2';"); // covariance of mode2 Matlab.Execute("C2 = invSV2*diag(1./VV2)*invSV2';"); Matlab.Execute("C2 = (C2 + C2')/2;"); // covariance of mode 1 projected onto U2 Matlab.Execute("C1 = U2'*(MM1*diag(VV1)*MM1')*U2;"); Matlab.Execute("C1 = pinv((C1 + C1')/2);"); Matlab.Execute("C1 = (C1 + C1')/2;"); // compute the fluctuation similarity Matlab.Execute("detInvC1 = det(inv(C1));"); Matlab.Execute("detInvC2 = det(inv(C2));"); Matlab.Execute("detInvC1InvC2 = det((inv(C1)+inv(C2))/2);"); Matlab.Execute("simfluc0 = ((detInvC1*detInvC2)^0.25);"); Matlab.Execute("simfluc1 = (detInvC1InvC2)^0.5;"); Matlab.Execute("simfluc = simfluc0 / simfluc1;"); double simfluc = Matlab.GetValue("simfluc"); Matlab.Execute("clear"); return(simfluc); } }
public Mode[] GetRtbModes() { if (_rtbmodes == null) { Matrix eigvec; double[] eigval; using (new Matlab.NamedLock("")) { // solve [eigvec, eigval] = eig(PHP, PMP) { // PMPih = 1/sqrt(PMP) where "ih" stands for "Inverse Half" -1/2 Matlab.PutMatrix("PMP", PMP); Matlab.Execute("PMP = (PMP + PMP')/2;"); Matlab.Execute("[PMPih.V, PMPih.D] = eig(PMP); PMPih.D = diag(PMPih.D);"); Matlab.Execute("PMPih.Dih = 1.0 ./ sqrt(PMPih.D);"); // PMPih.Dih = PMPih.D ^ -1/2 if (HDebug.IsDebuggerAttached) { double err = Matlab.GetValue("max(abs(1 - PMPih.D .* PMPih.Dih .* PMPih.Dih))"); HDebug.AssertTolerance(0.00000001, err); } Matlab.Execute("PMPih = PMPih.V * diag(PMPih.Dih) * PMPih.V';"); if (HDebug.IsDebuggerAttached) { double err = Matlab.GetValue("max(max(abs(eye(size(PMP)) - (PMP * PMPih * PMPih))))"); HDebug.AssertTolerance(0.00000001, err); } Matlab.Execute("clear PMP;"); } { // to solve [eigvec, eigval] = eig(PHP, PMP) // 1. H = PMP^-1/2 * PHP * PMP^-1/2 // 2. [V,D] = eig(H) // 3. V = PMP^-1/2 * V Matlab.PutMatrix("PHP", PHP); // put RTB Hess Matlab.Execute("PHP = (PHP + PHP')/2;"); Matlab.Execute("PHP = PMPih * PHP * PMPih; PHP = (PHP + PHP')/2;"); // mass-weighted Hess Matlab.Execute("[V,D] = eig(PHP); D=diag(D); clear PHP;"); // mass-weighted modes, eigenvalues Matlab.Execute("V = PMPih * V; clear PMPih;"); // mass-reduced modes } eigvec = Matlab.GetMatrix("V"); eigval = Matlab.GetVector("D"); Matlab.Execute("clear;"); } List <Mode> modes; { // sort by eigenvalues int[] idx = eigval.HIdxSorted(); modes = new List <Mode>(idx.Length); for (int i = 0; i < eigval.Length; i++) { Mode mode = new Mode { th = i + 1, eigval = eigval[idx[i]], eigvec = eigvec.GetColVector(idx[i]), }; modes.Add(mode); } } _rtbmodes = modes.ToArray(); } return(_rtbmodes); }
public static bool GetHessGnmSelfTest() { if (HDebug.Selftest() == false) { return(true); } Pdb pdb = Pdb.FromPdbid("1MJC"); for (int i = 0; i < pdb.atoms.Length; i++) { HDebug.Assert(pdb.atoms[0].altLoc == pdb.atoms[i].altLoc); HDebug.Assert(pdb.atoms[0].chainID == pdb.atoms[i].chainID); } List <Vector> coords = pdb.atoms.ListCoord(); double cutoff = 13; Matlab.Execute("clear"); Matlab.PutMatrix("x", MatrixByArr.FromRowVectorList(coords).ToArray()); Matlab.PutValue("cutoffR", cutoff); Matlab.Execute(@"% function cx = contactsNew(x, cutoffR) % Contact matrix within cutoff distance. % Author: Guang Song % New: 10/25/2006 % %n = size(x,1); % Method 1: slow %for i=1:n % center = x(i,:); % distSqr(:,i) = sum((x-center(ones(n,1),:)).^2,2); %end %cx = sparse(distSqr<=cutoffR^2); % Method 2: fast! about 28 times faster when array size is 659x3 %tot = zeros(n,n); %for i=1:3 % xi = x(:,ones(n,1)*i); % %tmp = (xi - xi.').^2; % %tot = tot + tmp; % tot = tot + (xi - xi.').^2; %end %cx = sparse(tot<=cutoffR^2); % Method 3: this implementation is the shortest! but sligtly slower than % method 2 %xn = x(:,:,ones(n,1)); % create n copy x %xnp = permute(xn,[3,2,1]); %tot = sum((xn-xnp).^2,2); % sum along x, y, z %cx = sparse(permute(tot,[1,3,2])<=cutoffR^2); % put it into one line like below actually slows it down. Don't do that. %cx = sparse(permute(sum((xn-permute(xn,[3,2,1])).^2,2),[1,3,2])<=cutoffR^2); %Method 4: using function pdist, which I just know % this one line implementation is even faster. 2 times than method 2. cx = sparse(squareform(pdist(x)<=cutoffR)); "); Matlab.Execute(@"% function gnm = kirchhoff(cx) % the returned gnm provide the kirchhoff matrix % cx is the contact map. % Guang Song % 11/09/06 gnm = diag(sum(cx)) - cx; "); Matlab.Execute("gnm = full(gnm);"); Matrix gnm_gsong = Matlab.GetMatrix("gnm"); Matlab.Execute("clear;"); Matrix gnm = GetHessGnm(coords.ToArray(), cutoff); if (gnm_gsong.RowSize != gnm.RowSize) { HDebug.Assert(false); return(false); } if (gnm_gsong.ColSize != gnm.ColSize) { HDebug.Assert(false); return(false); } for (int c = 0; c < gnm.ColSize; c++) { for (int r = 0; r < gnm.RowSize; r++) { if (Math.Abs(gnm_gsong[c, r] - gnm[c, r]) >= 0.00000001) { HDebug.Assert(false); return(false); } } } return(true); }
public static ValueTuple <HessMatrix, Vector> Get_BInvDC_BInvDG_Simple (HessMatrix CC , HessMatrix DD , Vector GG , bool process_disp_console , double?thld_BinvDC = null , bool parallel = false ) { HessMatrix BB_invDD_CC; Vector BB_invDD_GG; using (new Matlab.NamedLock("")) { Matlab.Execute("clear;"); if (process_disp_console) { System.Console.Write("matlab("); } Matlab.PutMatrix("C", CC); if (process_disp_console) { System.Console.Write("C"); //Matlab.PutSparseMatrix("C", C.GetMatrixSparse(), 3, 3); } Matlab.PutMatrix("D", DD); if (process_disp_console) { System.Console.Write("D"); } Matlab.PutVector("G", GG); if (process_disp_console) { System.Console.Write("G"); } // Matlab.Execute("BinvDC = C' * inv(D) * C;"); { Matlab.Execute("BinvDC = C' * inv(D);"); Matlab.Execute("BinvD_G = BinvDC * G;"); Matlab.Execute("BinvDC = BinvDC * C;"); } BB_invDD_GG = Matlab.GetVector("BinvD_G"); //Matrix BBinvDDCC = Matlab.GetMatrix("BinvDC", true); if (thld_BinvDC != null) { Matlab.Execute("BinvDC(find(abs(BinvDC) < " + thld_BinvDC.ToString() + ")) = 0;"); } Func <int, int, HessMatrix> Zeros = delegate(int colsize, int rowsize) { return(HessMatrixDense.ZerosDense(colsize, rowsize)); }; BB_invDD_CC = Matlab.GetMatrix("BinvDC", Zeros, true); if (process_disp_console) { System.Console.Write("Y), "); } Matlab.Execute("clear;"); } //GC.Collect(0); return(new ValueTuple <HessMatrix, Vector> (BB_invDD_CC , BB_invDD_GG )); }
public static double[] GetRotAngles(Universe univ , Vector[] coords , Vector[] forces , double t // 0.1 , MatrixByArr J = null , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null , List <Universe.RotableInfo> univ_rotinfos = null , HPack <Vector[]> forcesProjectedByTorsional = null , HPack <Vector[]> dcoordsProjectedByTorsional = null ) { Vector mass = univ.GetMasses(); //Vector[] dcoords = new Vector[univ.size]; double t2 = t * t; //for(int i=0; i<univ.size; i++) // dcoords[i] = forces[i] * (0.5*t2/mass[i]); if (J == null) { if (univ_rotinfos == null) { if (univ_flexgraph == null) { univ_flexgraph = univ.BuildFlexibilityGraph(); } univ_rotinfos = univ.GetRotableInfo(univ_flexgraph); } J = TNM.GetJ(univ, coords, univ_rotinfos); } double[] dangles; using (new Matlab.NamedLock("TEST")) { Matlab.Clear("TEST"); Matlab.PutVector("TEST.F", Vector.FromBlockvector(forces)); Matlab.PutValue("TEST.t2", t2); //Matlab.PutVector("TEST.R", Vector.FromBlockvector(dcoords)); Matlab.PutMatrix("TEST.J", J); Matlab.PutVector("TEST.M", univ.GetMasses(3)); Matlab.Execute("TEST.M = diag(TEST.M);"); /// f = m a /// d = 1/2 a t^2 /// = 0.5 f/m t^2 /// f = m a /// = 2 m d t^-2 /// /// coord change /// dcoord = 0.5 a t^2 /// = (0.5 t^2) f/m /// = (0.5 t^2) M^-1 F : M is mass matrix, F is the net force of each atom /// /// torsional angle change /// dtor = (J' M J)^-1 J' M * dcoord : (6) of TNM paper /// = (J' M J)^-1 J' M * (0.5 t^2) M^-1 F /// = (0.5 t^2) (J' M J)^-1 J' F /// = (0.5 t^2) (J' M J)^-1 J' F /// = (0.5 t2) invJMJ JF /// /// force filtered by torsional ... /// F_tor = m a /// = 2 m d t^-2 /// = 2 M (J * dtor) t^-2 /// = 2 M (J * (0.5 t^2) (J' M J)^-1 J' F) t^-2 /// = M J (J' M J)^-1 J' F /// = MJ invJMJ JF /// /// coord change filtered by torsional /// R_tor = (0.5 t^2) M^-1 * F_tor /// = (0.5 t^2) J (J' M J)^-1 J' F /// = (0.5 t2) J invJMJ JF Matlab.Execute("TEST.JMJ = TEST.J' * TEST.M * TEST.J;"); Matlab.Execute("TEST.invJMJ = inv(TEST.JMJ);"); Matlab.Execute("TEST.MJ = TEST.M * TEST.J;"); Matlab.Execute("TEST.JF = TEST.J' * TEST.F;"); Matlab.Execute("TEST.dtor = (0.5 * TEST.t2) * TEST.invJMJ * TEST.JF;"); // (6) of TNM paper Matlab.Execute("TEST.F_tor = TEST.MJ * TEST.invJMJ * TEST.JF;"); Matlab.Execute("TEST.R_tor = (0.5 * TEST.t2) * TEST.J * TEST.invJMJ * TEST.JF;"); dangles = Matlab.GetVector("TEST.dtor"); if (forcesProjectedByTorsional != null) { Vector F_tor = Matlab.GetVector("TEST.F_tor"); HDebug.Assert(F_tor.Size == forces.Length * 3); forcesProjectedByTorsional.value = new Vector[forces.Length]; for (int i = 0; i < forces.Length; i++) { int i3 = i * 3; forcesProjectedByTorsional.value[i] = new double[] { F_tor[i3 + 0], F_tor[i3 + 1], F_tor[i3 + 2] }; } } if (dcoordsProjectedByTorsional != null) { Vector R_tor = Matlab.GetVector("TEST.R_tor"); HDebug.Assert(R_tor.Size == coords.Length * 3); dcoordsProjectedByTorsional.value = new Vector[coords.Length]; for (int i = 0; i < coords.Length; i++) { int i3 = i * 3; dcoordsProjectedByTorsional.value[i] = new double[] { R_tor[i3 + 0], R_tor[i3 + 1], R_tor[i3 + 2] }; } } Matlab.Clear("TEST"); } return(dangles); }
public static Vector[] GetRotate(Vector[] coords, Vector cent, int[] block) { throw new Exception("this implementation is wrong. Use the following algorithm to get rotation modes for RTB."); double[] io_mass = null; if (HDebug.IsDebuggerAttached) { using (var temp = new HTempDirectory(@"K:\temp\", null)) { temp.EnterTemp(); HFile.WriteAllText("rtbProjection.m", @" function [P, xyz] = rtbProjection(xyz, mass) % the approach is to find the inertia. compute the principal axes. and then use them to determine directly translation or rotation. n = size(xyz, 1); % n: the number of atoms if nargin == 1 mass = ones(n,1); end M = sum(mass); % find the mass center. m3 = repmat(mass, 1, 3); center = sum (xyz.*m3)/M; xyz = xyz - center(ones(n, 1), :); mwX = sqrt (m3).*xyz; inertia = sum(sum(mwX.^2))*eye(3) - mwX'*mwX; [V,D] = eig(inertia); tV = V'; % tV: transpose of V. Columns of V are principal axes. for i=1:3 trans{i} = tV(ones(n,1)*i, :); % the 3 translations are along principal axes end P = zeros(n*3, 6); for i=1:3 rotate{i} = cross(trans{i}, xyz); temp = mat2vec(trans{i}); P(:,i) = temp/norm(temp); temp = mat2vec(rotate{i}); P(:,i+3) = temp/norm(temp); end m3 = mat2vec(sqrt(m3)); P = repmat (m3(:),1,size(P,2)).*P; % now normalize columns of P P = P*diag(1./normMat(P,1)); function vec = mat2vec(mat) % convert a matrix to a vector, extracting data *row-wise*. vec = reshape(mat',1,prod(size(mat))); "); Matlab.Execute("cd \'" + temp.dirinfo.FullName + "\'"); Matlab.PutMatrix("xyz", coords.ToMatrix(false)); Matlab.PutVector("mass", io_mass); temp.QuitTemp(); } } HDebug.Assert(coords.Length == io_mass.Length); Vector mwcenter = new double[3]; for (int i = 0; i < coords.Length; i++) { mwcenter += (coords[i] * io_mass[i]); } mwcenter /= io_mass.Sum(); Vector[] mwcoords = new Vector[coords.Length]; for (int i = 0; i < coords.Length; i++) { mwcoords[i] = (coords[i] - mwcenter) * io_mass[i]; } Matrix mwPCA = new double[3, 3]; for (int i = 0; i < coords.Length; i++) { mwPCA += LinAlg.VVt(mwcoords[i], mwcoords[i]); } var V_D = LinAlg.Eig(mwPCA.ToArray()); var V = V_D.Item1; Vector[] rotvecs = new Vector[3]; for (int i = 0; i < 3; i++) { Vector rotaxis = new double[] { V[0, i], V[1, i], V[2, i] }; Vector[] rotveci = new Vector[coords.Length]; for (int j = 0; j < coords.Length; j++) { rotveci[j] = LinAlg.CrossProd(rotaxis, mwcoords[i]); } rotvecs[i] = rotveci.ToVector().UnitVector(); } if (HDebug.IsDebuggerAttached) { double dot01 = LinAlg.VtV(rotvecs[0], rotvecs[1]); double dot02 = LinAlg.VtV(rotvecs[0], rotvecs[2]); double dot12 = LinAlg.VtV(rotvecs[1], rotvecs[2]); HDebug.Assert(Math.Abs(dot01) < 0.0000001); HDebug.Assert(Math.Abs(dot02) < 0.0000001); HDebug.Assert(Math.Abs(dot12) < 0.0000001); } return(rotvecs); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// from song: rtbProjection.m //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// function [P, xyz] = rtbProjection(xyz, mass) /// % the approach is to find the inertia. compute the principal axes. and then use them to determine directly translation or rotation. /// /// n = size(xyz, 1); % n: the number of atoms /// if nargin == 1 /// mass = ones(n,1); /// end /// /// M = sum(mass); /// % find the mass center. /// m3 = repmat(mass, 1, 3); /// center = sum (xyz.*m3)/M; /// xyz = xyz - center(ones(n, 1), :); /// /// mwX = sqrt (m3).*xyz; /// inertia = sum(sum(mwX.^2))*eye(3) - mwX'*mwX; /// [V,D] = eig(inertia); /// tV = V'; % tV: transpose of V. Columns of V are principal axes. /// for i=1:3 /// trans{i} = tV(ones(n,1)*i, :); % the 3 translations are along principal axes /// end /// P = zeros(n*3, 6); /// for i=1:3 /// rotate{i} = cross(trans{i}, xyz); /// temp = mat2vec(trans{i}); /// P(:,i) = temp/norm(temp); /// temp = mat2vec(rotate{i}); /// P(:,i+3) = temp/norm(temp); /// end /// m3 = mat2vec(sqrt(m3)); /// P = repmat (m3(:),1,size(P,2)).*P; /// % now normalize columns of P /// P = P*diag(1./normMat(P,1)); /// /// function vec = mat2vec(mat) /// % convert a matrix to a vector, extracting data *row-wise*. /// vec = reshape(mat',1,prod(size(mat))); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// rotx[t_ ] := { { 1,0,0,0},{ 0,Cos[t],-Sin[t],0},{ 0,Sin[t],Cos[t],0},{ 0,0,0,1} }; /// roty[t_ ] := { { Cos[t],0,Sin[t],0},{ 0,1,0,0},{ -Sin[t],0,Cos[t],0},{ 0,0,0,1} }; /// rotz[t_ ] := { { Cos[t],-Sin[t],0,0},{ Sin[t],Cos[t],0,0},{ 0,0,1,0},{ 0,0,0,1} }; /// tran[tx_, ty_, tz_] := { { 1,0,0,tx},{ 0,1,0,ty},{ 0,0,1,tz},{ 0,0,0,1} }; /// pt = Transpose[{{px,py,pz,1}}]; /// /// point : (px,py,pz) /// center : (cx,cy,cz) /// angle : t /// /// tran[cx, cy, cz].rotx[t].tran[-cx, -cy, -cz].pt = {{px}, {cy - cy Cos[t] + py Cos[t] + cz Sin[t] - pz Sin[t]}, {cz - cz Cos[t] + pz Cos[t] - cy Sin[t] + py Sin[t]}, {1}} /// tran[cx, cy, cz].roty[t].tran[-cx, -cy, -cz].pt = {{cx - cx Cos[t] + px Cos[t] - cz Sin[t] + pz Sin[t]}, {py}, {cz - cz Cos[t] + pz Cos[t] + cx Sin[t] - px Sin[t]}, {1}} /// tran[cx, cy, cz].rotz[t].tran[-cx, -cy, -cz].pt = {{cx - cx Cos[t] + px Cos[t] + cy Sin[t] - py Sin[t]}, {cy - cy Cos[t] + py Cos[t] - cx Sin[t] + px Sin[t]}, {pz}, {1}} /// /// D[tran[cx, cy, cz].rotx[t].tran[-cx, -cy, -cz].pt, t] = {{0}, {cz Cos[t] - pz Cos[t] + cy Sin[t] - py Sin[t]}, {-cy Cos[t] + py Cos[t] + cz Sin[t] - pz Sin[t]}, {0}} /// D[tran[cx, cy, cz].roty[t].tran[-cx, -cy, -cz].pt, t] = {{-cz Cos[t] + pz Cos[t] + cx Sin[t] - px Sin[t]}, {0}, {cx Cos[t] - px Cos[t] + cz Sin[t] - pz Sin[t]}, {0}} /// D[tran[cx, cy, cz].rotz[t].tran[-cx, -cy, -cz].pt, t] = {{cy Cos[t] - py Cos[t] + cx Sin[t] - px Sin[t]}, {-cx Cos[t] + px Cos[t] + cy Sin[t] - py Sin[t]}, {0}, {0}} /// /// D[tran[cx,cy,cz].rotx[a].tran[-cx,-cy,-cz].pt,a]/.a->0 = {{0}, {cz - pz}, {-cy + py}, {0}} /// D[tran[cx,cy,cz].roty[a].tran[-cx,-cy,-cz].pt,a]/.a->0 = {{-cz + pz}, {0}, {cx - px}, {0}} /// D[tran[cx,cy,cz].rotz[a].tran[-cx,-cy,-cz].pt,a]/.a->0 = {{cy - py}, {-cx + px}, {0}, {0}} /// rotx of atom (px,py,pz) with center (cx,cy,cz): {{0}, {cz - pz}, {-cy + py}, {0}} = { 0, cz - pz, -cy + py, 0 } => { 0, cz - pz, -cy + py } /// rotx of atom (px,py,pz) with center (cx,cy,cz): {{-cz + pz}, {0}, {cx - px}, {0}} = { -cz + pz, 0, cx - px, 0 } => { -cz + pz, 0, cx - px } /// rotx of atom (px,py,pz) with center (cx,cy,cz): {{cy - py}, {-cx + px}, {0}, {0}} = { cy - py, -cx + px, 0, 0 } => { cy - py, -cx + px, 0 } /// int leng = coords.Length; Vector[] rots; { Vector[] rotbyx = new Vector[leng]; Vector[] rotbyy = new Vector[leng]; Vector[] rotbyz = new Vector[leng]; double cx = cent[0]; double cy = cent[1]; double cz = cent[2]; for (int i = 0; i < leng; i++) { double px = coords[i][0]; double py = coords[i][1]; double pz = coords[i][2]; rotbyx[i] = new double[] { 0, cz - pz, -cy + py }; rotbyy[i] = new double[] { -cz + pz, 0, cx - px }; rotbyz[i] = new double[] { cy - py, -cx + px, 0 }; } rots = new Vector[] { rotbyx.ToVector().UnitVector(), rotbyy.ToVector().UnitVector(), rotbyz.ToVector().UnitVector(), }; } if (HDebug.IsDebuggerAttached) { Vector[] rotbyx = new Vector[leng]; Vector[] rotbyy = new Vector[leng]; Vector[] rotbyz = new Vector[leng]; Vector zeros = new double[3]; for (int i = 0; i < leng; i++) { rotbyx[i] = rotbyy[i] = rotbyz[i] = zeros; } Vector rx = new double[3] { 1, 0, 0 }; Vector ry = new double[3] { 0, 1, 0 }; Vector rz = new double[3] { 0, 0, 1 }; Func <Vector, Vector, Vector> GetTangent = delegate(Vector pt, Vector axisdirect) { /// Magnitude of rotation tangent is proportional to the distance from the point to the axis. /// Ex) when a point is in x-axis (r,0), rotating along z-axis by θ is: (r*sin(θ), 0) /// /// | /// | ^ sin(θ) /// | | /// -+-----------------r---------- /// Vector rot1 = cent; Vector rot2 = cent + axisdirect; double dist = Geometry.DistancePointLine(pt, rot1, rot2); Vector tan = Geometry.RotateTangentUnit(pt, rot1, rot2) * dist; return(tan); }; IEnumerable <int> enumblock = block; if (block != null) { enumblock = block; } else { enumblock = HEnum.HEnumCount(leng); } foreach (int i in enumblock) { Vector pt = coords[i]; rotbyx[i] = GetTangent(pt, rx); rotbyy[i] = GetTangent(pt, ry); rotbyz[i] = GetTangent(pt, rz); } Vector[] trots = new Vector[3] { rotbyx.ToVector().UnitVector(), rotbyy.ToVector().UnitVector(), rotbyz.ToVector().UnitVector(), }; double test0 = LinAlg.VtV(rots[0], trots[0]); double test1 = LinAlg.VtV(rots[1], trots[1]); double test2 = LinAlg.VtV(rots[2], trots[2]); HDebug.Assert(Math.Abs(test0 - 1) < 0.00000001); HDebug.Assert(Math.Abs(test1 - 1) < 0.00000001); HDebug.Assert(Math.Abs(test2 - 1) < 0.00000001); } return(rots); }
public static Vector[] GetRotTran(Vector[] coords, double[] masses) { #region source rtbProjection.m /// rtbProjection.m ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// function [P, xyz] = rtbProjection(xyz, mass) /// % the approach is to find the inertia. compute the principal axes. and then use them to determine directly translation or rotation. /// /// n = size(xyz, 1); % n: the number of atoms /// if nargin == 1 /// mass = ones(n,1); /// end /// /// M = sum(mass); /// % find the mass center. /// m3 = repmat(mass, 1, 3); /// center = sum (xyz.*m3)/M; /// xyz = xyz - center(ones(n, 1), :); /// /// mwX = sqrt (m3).*xyz; /// inertia = sum(sum(mwX.^2))*eye(3) - mwX'*mwX; /// [V,D] = eig(inertia); /// tV = V'; % tV: transpose of V. Columns of V are principal axes. /// for i=1:3 /// trans{i} = tV(ones(n,1)*i, :); % the 3 translations are along principal axes /// end /// P = zeros(n*3, 6); /// for i=1:3 /// rotate{i} = cross(trans{i}, xyz); /// temp = mat2vec(trans{i}); /// P(:,i) = temp/norm(temp); /// temp = mat2vec(rotate{i}); /// P(:,i+3) = temp/norm(temp); /// end /// m3 = mat2vec(sqrt(m3)); /// P = repmat (m3(:),1,size(P,2)).*P; /// % now normalize columns of P /// P = P*diag(1./normMat(P,1)); /// /// function vec = mat2vec(mat) /// % convert a matrix to a vector, extracting data *row-wise*. /// vec = reshape(mat',1,prod(size(mat))); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endregion if (HDebug.Selftest()) #region selftest { // get test coords and masses Vector[] tcoords = Pdb.FromLines(SelftestData.lines_1EVC_pdb).atoms.ListCoord().ToArray(); double[] tmasses = new double[tcoords.Length]; for (int i = 0; i < tmasses.Length; i++) { tmasses[i] = 1; } // get test rot/trans RTB vectors Vector[] trottra = GetRotTran(tcoords, tmasses); HDebug.Assert(trottra.Length == 6); // get test ANM var tanm = Hess.GetHessAnm(tcoords); // size of vec_i == 1 for (int i = 0; i < trottra.Length; i++) { double dist = trottra[i].Dist; HDebug.Assert(Math.Abs(dist - 1) < 0.00000001); } // vec_i and vec_j must be orthogonal for (int i = 0; i < trottra.Length; i++) { for (int j = i + 1; j < trottra.Length; j++) { double dot = LinAlg.VtV(trottra[i], trottra[j]); HDebug.Assert(Math.Abs(dot) < 0.00000001); } } // vec_i' * ANM * vec_i == 0 for (int i = 0; i < trottra.Length; i++) { double eigi = LinAlg.VtMV(trottra[i], tanm, trottra[i]); HDebug.Assert(Math.Abs(eigi) < 0.00000001); Vector tvecx = trottra[i].Clone(); tvecx[1] += (1.0 / tvecx.Size) * Math.Sign(tvecx[1]); tvecx = tvecx.UnitVector(); double eigix = LinAlg.VtMV(tvecx, tanm, tvecx); HDebug.Assert(Math.Abs(eigix) > 0.00000001); } } #endregion Vector[] rottran; using (new Matlab.NamedLock("")) { Matlab.PutMatrix("xyz", coords.ToMatrix(), true); Matlab.Execute("xyz = xyz';"); Matlab.PutVector("mass", masses); //Matlab.Execute("function [P, xyz] = rtbProjection(xyz, mass) "); //Matlab.Execute("% the approach is to find the inertia. compute the principal axes. and then use them to determine directly translation or rotation. "); Matlab.Execute(" "); Matlab.Execute("n = size(xyz, 1); % n: the number of atoms "); //Matlab.Execute("if nargin == 1; "); //Matlab.Execute(" mass = ones(n,1); "); //Matlab.Execute("end "); Matlab.Execute(" "); Matlab.Execute("M = sum(mass); "); Matlab.Execute("% find the mass center. "); Matlab.Execute("m3 = repmat(mass, 1, 3); "); Matlab.Execute("center = sum (xyz.*m3)/M; "); Matlab.Execute("xyz = xyz - center(ones(n, 1), :); "); Matlab.Execute(" "); Matlab.Execute("mwX = sqrt (m3).*xyz; "); Matlab.Execute("inertia = sum(sum(mwX.^2))*eye(3) - mwX'*mwX; "); Matlab.Execute("[V,D] = eig(inertia); "); Matlab.Execute("tV = V'; % tV: transpose of V. Columns of V are principal axes. "); Matlab.Execute("for i=1:3 \n" + " trans{i} = tV(ones(n,1)*i, :); % the 3 translations are along principal axes \n" + "end \n"); Matlab.Execute("P = zeros(n*3, 6); "); Matlab.Execute("mat2vec = @(mat) reshape(mat',1,prod(size(mat))); "); Matlab.Execute("for i=1:3 \n" + " rotate{i} = cross(trans{i}, xyz); \n" + " temp = mat2vec(trans{i}); \n" + " P(:,i) = temp/norm(temp); \n" + " temp = mat2vec(rotate{i}); \n" + " P(:,i+3) = temp/norm(temp); \n" + "end "); Matlab.Execute("m3 = mat2vec(sqrt(m3)); "); Matlab.Execute("P = repmat (m3(:),1,size(P,2)).*P; "); //Matlab.Execute("% now normalize columns of P "); // already normalized //Matlab.Execute("normMat = @(x) sqrt(sum(x.^2,2)); "); // already normalized //Matlab.Execute("P = P*diag(1./normMat(P,1)); "); // already normalized //Matlab.Execute(" "); // already normalized ////////////////////////////////////////////////////////////////////////////////////////////////////// //Matlab.Execute("function vec = mat2vec(mat) "); //Matlab.Execute("% convert a matrix to a vector, extracting data *row-wise*. "); //Matlab.Execute("vec = reshape(mat',1,prod(size(mat))); "); ////////////////////////////////////////////////////////////////////////////////////////////////////// //Matlab.Execute("function amp = normMat(x) "); //Matlab.Execute("amp = sqrt(sum(x.^2,2)); "); Matrix xyz = Matlab.GetMatrix("xyz", true); Matrix P = Matlab.GetMatrix("P", true); rottran = P.GetColVectorList(); } return(rottran); }
public static TorEigen[] GetEigenTorsional(HessMatrix hessian, Vector masses, Matrix J) { int n = J.ColSize; int m = J.RowSize; //Matrix M = massmat; // univ.GetMassMatrix(3); Matrix JMJ; using (new Matlab.NamedLock("GetModeByTor")) { Matlab.PutMatrix("GetModeByTor.J", J); //Matlab.PutMatrix("GetModeByTor.M", M); Matlab.PutVector("GetModeByTor.m", masses); // ex: m = [1,2,...,n] Matlab.Execute("GetModeByTor.m3 = kron(GetModeByTor.m,[1;1;1]);"); // ex: m3 = [1,1,1,2,2,2,...,n,n,n] Matlab.Execute("GetModeByTor.M = diag(GetModeByTor.m3);"); Matlab.Execute("GetModeByTor.JMJ = GetModeByTor.J' * GetModeByTor.M * GetModeByTor.J;"); JMJ = Matlab.GetMatrix("GetModeByTor.JMJ"); Matlab.Clear("GetModeByTor"); } Matrix JHJ; using (new Matlab.NamedLock("GetModeByTor")) { Matlab.PutMatrix("GetModeByTor.J", J); Matlab.PutMatrix("GetModeByTor.H", hessian); Matlab.Execute("GetModeByTor.JHJ = GetModeByTor.J' * GetModeByTor.H * GetModeByTor.J;"); JHJ = Matlab.GetMatrix("GetModeByTor.JHJ"); Matlab.Clear("GetModeByTor"); } TorEigen[] toreigens = new TorEigen[m]; using (new Matlab.NamedLock("GetModeByTor")) { Matlab.PutMatrix("GetModeByTor.JHJ", JHJ); Matlab.PutMatrix("GetModeByTor.JMJ", JMJ); Matlab.PutMatrix("GetModeByTor.J", J); Matlab.Execute("[GetModeByTor.V, GetModeByTor.D] = eig(GetModeByTor.JHJ, GetModeByTor.JMJ);"); Matlab.Execute("GetModeByTor.D = diag(GetModeByTor.D);"); Matrix V = Matlab.GetMatrix("GetModeByTor.V"); Vector D = Matlab.GetVector("GetModeByTor.D"); Matlab.Clear("GetModeByTor"); for (int i = 0; i < m; i++) { toreigens[i] = new TorEigen(); toreigens[i].th = i; toreigens[i].eigval = D[i]; toreigens[i].eigvec = V.GetColVector(i); } } if (HDebug.IsDebuggerAttached) { Mode[] modes0 = GetModeByTorsional(hessian, masses, J); Mode[] modes1 = GetModeByTorsional(toreigens, J); HDebug.Assert(modes0.Length == modes1.Length); for (int i = 0; i < modes1.Length; i++) { HDebug.Assert(modes0[i].th == modes1[i].th); HDebug.AssertTolerance(0.000000001, modes0[i].eigval - modes1[i].eigval); HDebug.AssertTolerance(0.000000001, modes0[i].eigvec - modes1[i].eigvec); } } return(toreigens); }
public static HessMatrixDense GetHessCoarseBlkmat(HessMatrix hess, IList <int> idx_heavy, string invopt = "inv") { /// Hess = [ HH HL ] = [ A B ] /// [ LH LL ] [ C D ] /// /// Hess_HH = HH - HL * LL^-1 * LH /// = A - B * D^-1 * C Matrix hess_HH; using (new Matlab.NamedLock("")) { Matlab.Clear(); if (hess is HessMatrixSparse) { Matlab.PutSparseMatrix("H", hess.GetMatrixSparse(), 3, 3); } else { Matlab.PutMatrix("H", hess, true); } Matlab.Execute("H = (H + H')/2;"); int[] idx0 = new int[idx_heavy.Count * 3]; for (int i = 0; i < idx_heavy.Count; i++) { idx0[i * 3 + 0] = idx_heavy[i] * 3 + 0; idx0[i * 3 + 1] = idx_heavy[i] * 3 + 1; idx0[i * 3 + 2] = idx_heavy[i] * 3 + 2; } Matlab.PutVector("idx0", idx0); Matlab.Execute("idx0 = idx0+1;"); Matlab.PutValue("idx1", hess.ColSize); Matlab.Execute("idx1 = setdiff(1:idx1, idx0)';"); HDebug.Assert(Matlab.GetValueInt("length(union(idx0,idx1))") == hess.ColSize); Matlab.Execute("A = full(H(idx0,idx0));"); Matlab.Execute("B = H(idx0,idx1) ;"); Matlab.Execute("C = H(idx1,idx0) ;"); Matlab.Execute("D = full(H(idx1,idx1));"); Matlab.Execute("clear H;"); object linvopt = null; switch (invopt) { case "B/D": Matlab.Execute("bhess = A -(B / D)* C;"); break; case "inv": Matlab.Execute("D = inv(D);"); Matlab.Execute("bhess = A - B * D * C;"); break; case "pinv": Matlab.Execute("D = pinv(D);"); Matlab.Execute("bhess = A - B * D * C;"); break; case "_eig": bool bCheckInv = false; if (bCheckInv) { Matlab.Execute("Dbak = D;"); } Matlab.Execute("[D,DD] = eig(D);"); if (HDebug.False) { Matlab.Execute("DD(abs(DD)<" + linvopt + ") = 0;"); Matlab.Execute("DD = pinv(DD);"); } else { Matlab.Execute("DD = diag(DD);"); Matlab.Execute("DDidx = abs(DD)<" + linvopt + ";"); Matlab.Execute("DD = 1./DD;"); Matlab.Execute("DD(DDidx) = 0;"); Matlab.Execute("DD = diag(DD);"); Matlab.Execute("clear DDidx;"); } Matlab.Execute("D = D * DD * D';"); if (bCheckInv) { double err0 = Matlab.GetValue("max(max(abs(eye(size(D)) - Dbak * D)))"); } if (bCheckInv) { double err1 = Matlab.GetValue("max(max(abs(eye(size(D)) - D * Dbak)))"); } if (bCheckInv) { Matlab.Execute("clear Dbak;"); } Matlab.Execute("clear DD;"); Matlab.Execute("bhess = A - B * D * C;"); break; default: { if (invopt.StartsWith("eig(threshold:") && invopt.EndsWith(")")) { // ex: "eig(threshold:0.000000001)" linvopt = invopt.Replace("eig(threshold:", "").Replace(")", ""); linvopt = double.Parse(linvopt as string); goto case "_eig"; } } throw new HException(); } Matlab.Execute("clear A; clear B; clear C; clear D;"); Matlab.Execute("bhess = (bhess + bhess')/2;"); hess_HH = Matlab.GetMatrix("bhess", Matrix.Zeros, true); Matlab.Clear(); } return(new HessMatrixDense { hess = hess_HH }); }
public static Dictionary <double, double> GetDegeneracyOverlap(IList <Mode> modes1, IList <Mode> modes2, IList <double> masses, double domega) { List <double> invmasses = new List <double>(); foreach (var mass in masses) { invmasses.Add(1 / mass); } List <Vector> modes1_massweighted = new List <Vector>(); foreach (var mode in modes1) { modes1_massweighted.Add(mode.GetMassReduced(invmasses).eigvec); } List <Vector> modes2_massweighted = new List <Vector>(); foreach (var mode in modes2) { modes2_massweighted.Add(mode.GetMassReduced(invmasses).eigvec); } Matrix modemat1_massweighted = Matrix.FromColVectorList(modes1_massweighted); Matrix modemat2_massweighted = Matrix.FromColVectorList(modes2_massweighted); Matlab.Clear(); Matlab.PutMatrix("m1", modemat1_massweighted, true); Matlab.PutMatrix("m2", modemat2_massweighted, true); Matlab.Execute("dot12 = m1' * m2;"); Matrix dot12 = Matlab.GetMatrix("dot12", Matrix.Zeros, true); Matlab.Clear(); List <double> freqs2 = modes2.ListFreq().ToList(); Dictionary <double, double> freq1_dovlp = new Dictionary <double, double>(); for (int i1 = 0; i1 < modes1.Count; i1++) { double freq1 = modes1[i1].freq; int idx0 = freqs2.BinarySearch(freq1 - domega); int idx1 = freqs2.BinarySearch(freq1 + domega); // The zero-based index of item in the sorted System.Collections.Generic.List`1, // if item is found; otherwise, a negative number that is the bitwise complement // of the index of the next element that is larger than item or, if there is no // larger element, the bitwise complement of System.Collections.Generic.List`1.Count. if (idx0 < 0) { idx0 = Math.Abs(idx0); } if (idx1 < 0) { idx1 = Math.Min(Math.Abs(idx1) - 1, freqs2.Count - 1); } double dovlp = 0; for (int i2 = idx0; i2 <= idx1; i2++) { double dot12_i1_i2 = dot12[i1, i2]; dovlp += dot12_i1_i2 * dot12_i1_i2; } dovlp = Math.Sqrt(dovlp); freq1_dovlp.Add(freq1, dovlp); } //modes1.GetMassReduced return(freq1_dovlp); }
public static Matrix GetInvSprTensor(Matrix H, Matrix S, ILinAlg ila) { Matrix invH; string optInvH = "EigSymmTol"; optInvH += ((ila == null) ? "-matlab" : "-ilnum"); switch (optInvH) { case "InvSymm-ilnum": HDebug.Assert(false); invH = ila.InvSymm(H); break; case "PInv-ilnum": invH = ila.PInv(H); break; case "EigSymm-ilnum": { var HH = ila.ToILMat(H); var VVDD = ila.EigSymm(HH); var VV = VVDD.Item1; for (int i = 0; i < VVDD.Item2.Length; i++) { VVDD.Item2[i] = 1 / VVDD.Item2[i]; } for (int i = 0; i < 6; i++) { VVDD.Item2[i] = 0; } var DD = ila.ToILMat(VVDD.Item2).Diag(); var invHH = ila.Mul(VV, DD, VV.Tr); invH = invHH.ToArray(); //var check = (H * invH).ToArray(); GC.Collect(); } break; case "EigSymmTol-matlab": { using (new Matlab.NamedLock("")) { Matlab.PutMatrix("invHH.HH", H); Matlab.Execute("invHH.HH = (invHH.HH + invHH.HH')/2;"); Matlab.Execute("[invHH.VV, invHH.DD] = eig(invHH.HH);"); Matlab.Execute("invHH.DD = diag(invHH.DD);"); Matlab.Execute("invHH.DD(abs(invHH.DD)<0.00001) = 0;"); Matlab.Execute("invHH.DD = pinv(diag(invHH.DD));"); Matlab.Execute("invHH = invHH.VV * invHH.DD * invHH.VV';"); invH = Matlab.GetMatrix("invHH"); Matlab.Execute("clear invHH;"); } GC.Collect(); } break; case "EigSymmTol-ilnum": { var HH = ila.ToILMat(H); var VVDD = ila.EigSymm(HH); var VV = VVDD.Item1; for (int i = 0; i < VVDD.Item2.Length; i++) { if (Math.Abs(VVDD.Item2[i]) < 0.00001) { VVDD.Item2[i] = 0; } else { VVDD.Item2[i] = 1 / VVDD.Item2[i]; } } var DD = ila.ToILMat(VVDD.Item2).Diag(); var invHH = ila.Mul(VV, DD, VV.Tr); invH = invHH.ToArray(); //var check = (H * invH).ToArray(); GC.Collect(); } break; default: throw new NotImplementedException(); } Matrix invkij = 0.5 * (S.Tr() * invH * S); //HDebug.Assert(invkij >= 0); return(invkij); }
public static HessRTB GetHessRTB(HessMatrix hess, Vector[] coords, double[] masses, IList <int[]> blocks, string opt) { #region check pre-condition { HDebug.Assert(coords.Length == hess.ColBlockSize); // check hess matrix HDebug.Assert(coords.Length == hess.RowBlockSize); // check hess matrix HDebug.Assert(coords.Length == blocks.HMerge().HToHashSet().Count); // check hess contains all blocks HDebug.Assert(coords.Length == blocks.HMerge().Count); // no duplicated index in blocks } #endregion List <Vector> Ps = new List <Vector>(); foreach (int[] block in blocks) { List <Vector> PBlk = new List <Vector>(); switch (opt) { case "v1": // GetRotate is incorrect PBlk.AddRange(GetTrans(coords, masses, block)); PBlk.AddRange(GetRotate(coords, masses, block)); break; case "v2": PBlk.AddRange(GetRotTran(coords, masses, block)); break; case null: goto case "v2"; } { // PBlk = ToOrthonormal (coords, masses, block, PBlk.ToArray()).ToList(); /// /// Effect of making orthonormal is not significant as below table, but consumes time by calling SVD /// Therefore, skip making orthonormal /// ========================================================================================================================================================= /// model | making orthonormal?| | MSF corr , check sparsity , overlap weighted by eigval : overlap of mode 1-1, 2-2, 3-3, ... /// ========================================================================================================================================================= /// NMA | orthonormal by SVD | RTB | corr 0.9234, spcty(all NaN, ca NaN), wovlp 0.5911 : 0.82,0.79,0.74,0.69,0.66,0.63,0.60,0.59,0.56,0.54) /// | orthogonal | RTB | corr 0.9230, spcty(all NaN, ca NaN), wovlp 0.5973 : 0.83,0.80,0.75,0.70,0.67,0.64,0.60,0.59,0.58,0.55) /// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// scrnNMA | orthonormal by SVD | RTB | corr 0.9245, spcty(all NaN, ca NaN), wovlp 0.5794 : 0.83,0.78,0.73,0.68,0.65,0.62,0.60,0.58,0.55,0.55) /// | orthogonal | RTB | corr 0.9243, spcty(all NaN, ca NaN), wovlp 0.5844 : 0.83,0.78,0.73,0.68,0.66,0.62,0.60,0.58,0.55,0.55) /// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// sbNMA | orthonormal by SVD | RTB | corr 0.9777, spcty(all NaN, ca NaN), wovlp 0.6065 : 0.93,0.89,0.86,0.81,0.75,0.71,0.69,0.66,0.63,0.62) /// | orthogonal | RTB | corr 0.9776, spcty(all NaN, ca NaN), wovlp 0.6175 : 0.94,0.90,0.87,0.82,0.76,0.73,0.71,0.69,0.66,0.63) /// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// ssNMA | orthonormal by SVD | RTB | corr 0.9677, spcty(all NaN, ca NaN), wovlp 0.5993 : 0.92,0.87,0.83,0.77,0.72,0.69,0.66,0.63,0.60,0.59) /// | orthogonal | RTB | corr 0.9675, spcty(all NaN, ca NaN), wovlp 0.6076 : 0.92,0.88,0.84,0.78,0.73,0.70,0.67,0.64,0.62,0.60) /// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// eANM | orthonormal by SVD | RTB | corr 0.9870, spcty(all NaN, ca NaN), wovlp 0.5906 : 0.95,0.91,0.87,0.83,0.77,0.73,0.71,0.68,0.66,0.61) /// | orthogonal | RTB | corr 0.9869, spcty(all NaN, ca NaN), wovlp 0.6014 : 0.95,0.92,0.88,0.84,0.78,0.74,0.73,0.70,0.67,0.65) /// --------------------------------------------------------------------------------------------------------------------------------------------------------- /// AA-ANM | orthonormal by SVD | RTB | corr 0.9593, spcty(all NaN, ca NaN), wovlp 0.4140 : 0.94,0.90,0.85,0.78,0.74,0.72,0.66,0.64,0.61,0.61) /// | orthogonal | RTB | corr 0.9589, spcty(all NaN, ca NaN), wovlp 0.4204 : 0.94,0.91,0.85,0.80,0.76,0.73,0.68,0.66,0.63,0.61) } Ps.AddRange(PBlk); } Matrix P = Matrix.FromColVectorList(Ps); Matrix PHP; Matrix PMP; using (new Matlab.NamedLock("")) { if (hess is HessMatrixSparse) { Matlab.PutSparseMatrix("H", hess.GetMatrixSparse(), 3, 3); } else if (hess is HessMatrixDense) { Matlab.PutMatrix("H", hess, true); } else { HDebug.Exception(); } Matlab.PutMatrix("P", P, true); Matlab.PutVector("M", masses); Matlab.Execute("M=diag(reshape([M,M,M]',length(M)*3,1));"); Matlab.Execute("PHP = P'*H*P; PHP = (PHP + PHP')/2;"); Matlab.Execute("PMP = P'*M*P; PMP = (PMP + PMP')/2;"); PHP = Matlab.GetMatrix("PHP", true); PMP = Matlab.GetMatrix("PMP", true); } return(new HessRTB { hess = hess, coords = coords, masses = masses, blocks = blocks, P = P, PHP = PHP, PMP = PMP, }); }
public static Vector[] ToOrthonormal(Vector[] coords, double[] masses, int[] block, Vector[] PBlk) { if (HDebug.IsDebuggerAttached) #region check if elements in non-block are zeros. { int leng = coords.Length; foreach (int i in HEnum.HEnumCount(leng).HEnumExcept(block.HToHashSet())) { for (int r = 0; r < PBlk.Length; r++) { int c0 = i * 3; HDebug.Assert(PBlk[r][c0 + 0] == 0); HDebug.Assert(PBlk[r][c0 + 1] == 0); HDebug.Assert(PBlk[r][c0 + 2] == 0); } } } #endregion Matrix Pmat = new double[block.Length * 3, PBlk.Length]; for (int r = 0; r < PBlk.Length; r++) { for (int i = 0; i < block.Length; i++) { int i0 = i * 3; int c0 = block[i] * 3; Pmat[i0 + 0, r] = PBlk[r][c0 + 0]; Pmat[i0 + 1, r] = PBlk[r][c0 + 1]; Pmat[i0 + 2, r] = PBlk[r][c0 + 2]; } } using (new Matlab.NamedLock("")) { Matlab.PutValue("n", PBlk.Length); Matlab.PutMatrix("P", Pmat); Matlab.Execute("[U,S,V] = svd(P);"); Matlab.Execute("U = U(:,1:n);"); if (HDebug.IsDebuggerAttached) { Matlab.Execute("SV = S(1:n,1:n)*V';"); double err = Matlab.GetValue("max(max(abs(P - U*SV)))"); HDebug.Assert(Math.Abs(err) < 0.00000001); } Pmat = Matlab.GetMatrix("U"); } Vector[] PBlkOrth = new Vector[PBlk.Length]; for (int r = 0; r < PBlk.Length; r++) { Vector PBlkOrth_r = new double[PBlk[r].Size]; for (int i = 0; i < block.Length; i++) { int i0 = i * 3; int c0 = block[i] * 3; PBlkOrth_r[c0 + 0] = Pmat[i0 + 0, r]; PBlkOrth_r[c0 + 1] = Pmat[i0 + 1, r]; PBlkOrth_r[c0 + 2] = Pmat[i0 + 2, r]; } PBlkOrth[r] = PBlkOrth_r; } if (HDebug.IsDebuggerAttached) #region checi the orthonormal condition, and rot/trans condition (using ANM) { { // check if all trans/rot modes are orthonormal for (int i = 0; i < PBlkOrth.Length; i++) { HDebug.Exception(Math.Abs(PBlkOrth[i].Dist - 1) < 0.00000001); for (int j = i + 1; j < PBlkOrth.Length; j++) { double dot = LinAlg.VtV(PBlkOrth[i], PBlkOrth[j]); HDebug.Exception(Math.Abs(dot) < 0.00000001); } } } { // check if this is true rot/trans modes using ANM Vector[] anmcoords = coords.HClone(); int leng = coords.Length; foreach (int i in HEnum.HEnumCount(leng).HEnumExcept(block.HToHashSet())) { anmcoords[i] = null; } HessMatrix H = GetHessAnm(anmcoords, 100); Matrix PHP; using (new Matlab.NamedLock("")) { Matlab.PutSparseMatrix("H", H.GetMatrixSparse(), 3, 3); Matlab.PutMatrix("P", PBlkOrth.ToMatrix(true)); PHP = Matlab.GetMatrix("P'*H*P"); } double maxerr = PHP.HAbsMax(); HDebug.Exception(Math.Abs(maxerr) < 0.00000001); } } #endregion return(PBlkOrth); }
public static Mode[] GetModeByTorsional(HessMatrix hessian, Vector masses, Matrix J , HPack <Matrix> optoutJMJ = null // J' M J , HPack <Matrix> optoutJM = null // J' M , Func <Matrix, Tuple <Matrix, Vector> > fnEigSymm = null , Func <Matrix, Matrix, Matrix, Matrix> fnMul = null ) { string opt; opt = "eig(JMJ^-1/2 * JHJ * JMJ^-1/2)"; //opt = "mwhess->tor->eig(H)->cart->mrmode"; if ((fnEigSymm != null) && (fnMul != null)) { opt = "fn-" + opt; } switch (opt) { case "mwhess->tor->eig(H)->cart->mrmode": /// http://www.lct.jussieu.fr/manuels/Gaussian03/g_whitepap/vib.htm /// http://www.lct.jussieu.fr/manuels/Gaussian03/g_whitepap/vib/vib.pdf /// does not work properly. HDebug.Assert(false); using (new Matlab.NamedLock("GetModeByTor")) { int n = J.ColSize; int m = J.RowSize; //Matrix M = massmat; // univ.GetMassMatrix(3); Vector[] toreigvecs = new Vector[m]; Vector[] tormodes = new Vector[m]; double[] toreigvals = new double[m]; Mode[] modes = new Mode[m]; { Matlab.Clear("GetModeByTor"); Matlab.PutMatrix("GetModeByTor.H", hessian); Matlab.PutMatrix("GetModeByTor.J", J); //Matlab.PutMatrix("GetModeByTor.M", M); Matlab.PutVector("GetModeByTor.m", masses); // ex: m = [1,2,...,n] Matlab.Execute("GetModeByTor.m3 = kron(GetModeByTor.m,[1;1;1]);"); // ex: m3 = [1,1,1,2,2,2,...,n,n,n] Matlab.Execute("GetModeByTor.M = diag(GetModeByTor.m3);"); Matlab.Execute("GetModeByTor.m = diag(1 ./ sqrt(diag(GetModeByTor.M)));"); Matlab.Execute("GetModeByTor.mHm = GetModeByTor.m * GetModeByTor.H * GetModeByTor.m;"); Matlab.Execute("GetModeByTor.JmHmJ = GetModeByTor.J' * GetModeByTor.mHm * GetModeByTor.J;"); Matlab.Execute("[GetModeByTor.V, GetModeByTor.D] = eig(GetModeByTor.JmHmJ);"); Matlab.Execute("GetModeByTor.JV = GetModeByTor.m * GetModeByTor.J * GetModeByTor.V;"); Matrix V = Matlab.GetMatrix("GetModeByTor.V"); Vector D = Matlab.GetVector("diag(GetModeByTor.D)"); Matrix JV = Matlab.GetMatrix("GetModeByTor.JV"); Matlab.Clear("GetModeByTor"); for (int i = 0; i < m; i++) { toreigvecs[i] = V.GetColVector(i); toreigvals[i] = D[i]; tormodes[i] = JV.GetColVector(i); modes[i] = new Mode(); modes[i].eigval = toreigvals[i]; modes[i].eigvec = tormodes[i]; modes[i].th = i; } } return(modes); } case "eig(JMJ^-1/2 * JHJ * JMJ^-1/2)": /// Solve the problem of using eng(H,M). /// /// eig(H,M) => H.v = M.v.l /// H.(M^-1/2 . M^1/2).v = (M^1/2 . M^1/2).v.l /// M^-1/2 . H.(M^-1/2 . M^1/2).v = M^1/2 .v.l /// (M^-1/2 . H . M^-1/2) . (M^1/2.v) = (M^1/2.v).l /// (M^-1/2 . H . M^-1/2) . w = w.l /// where (M^1/2.v) = w /// v = M^-1/2 . w /// where M = V . D . V' /// M^-1/2 = V . (1/sqrt(D)) . V' /// M^-1/2 . M^-1/2 . M = (V . (1/sqrt(D)) . V') . (V . (1/sqrt(D)) . V') . (V . D . V') /// = V . (1/sqrt(D)) . (1/sqrt(D)) . D . V' /// = V . I . V' /// = I using (new Matlab.NamedLock("GetModeByTor")) { int n = J.ColSize; int m = J.RowSize; //Matrix M = massmat; // univ.GetMassMatrix(3); Vector[] toreigvecs = new Vector[m]; Vector[] tormodes = new Vector[m]; double[] toreigvals = new double[m]; Mode[] modes = new Mode[m]; { Matlab.Clear("GetModeByTor"); Matlab.PutMatrix("GetModeByTor.J", J.ToArray(), true); //Matlab.PutMatrix("GetModeByTor.M", M , true); //Matlab.PutMatrix("GetModeByTor.H", hessian, true); Matlab.PutSparseMatrix("GetModeByTor.H", hessian.GetMatrixSparse(), 3, 3); if (HDebug.IsDebuggerAttached && hessian.ColSize < 10000) { Matlab.PutMatrix("GetModeByTor.Htest", hessian.ToArray(), true); double dHessErr = Matlab.GetValue("max(max(abs(GetModeByTor.H - GetModeByTor.Htest)))"); Matlab.Execute("clear GetModeByTor.Htest"); HDebug.Assert(dHessErr == 0); } Matlab.PutVector("GetModeByTor.m", masses); // ex: m = [1,2,...,n] Matlab.Execute("GetModeByTor.m3 = kron(GetModeByTor.m,[1;1;1]);"); // ex: m3 = [1,1,1,2,2,2,...,n,n,n] Matlab.Execute("GetModeByTor.M = diag(GetModeByTor.m3);"); Matlab.Execute("GetModeByTor.JMJ = GetModeByTor.J' * GetModeByTor.M * GetModeByTor.J;"); Matlab.Execute("GetModeByTor.JHJ = GetModeByTor.J' * GetModeByTor.H * GetModeByTor.J;"); Matlab.Execute("[GetModeByTor.V, GetModeByTor.D] = eig(GetModeByTor.JMJ);"); Matlab.Execute("GetModeByTor.jmj = GetModeByTor.V * diag(1 ./ sqrt(diag(GetModeByTor.D))) * GetModeByTor.V';"); // jmj = sqrt(JMJ) //Matlab.Execute("max(max(abs(JMJ*jmj*jmj - eye(size(JMJ)))));"); // for checking //Matlab.Execute("max(max(abs(jmj*JMJ*jmj - eye(size(JMJ)))));"); // for checking //Matlab.Execute("max(max(abs(jmj*jmj*JMJ - eye(size(JMJ)))));"); // for checking Matlab.Execute("[GetModeByTor.V, GetModeByTor.D] = eig(GetModeByTor.jmj * GetModeByTor.JHJ * GetModeByTor.jmj);"); Matlab.Execute("GetModeByTor.D = diag(GetModeByTor.D);"); Matlab.Execute("GetModeByTor.V = GetModeByTor.jmj * GetModeByTor.V;"); Matlab.Execute("GetModeByTor.JV = GetModeByTor.J * GetModeByTor.V;"); Matrix V = Matlab.GetMatrix("GetModeByTor.V", true); Vector D = Matlab.GetVector("GetModeByTor.D"); Matrix JV = Matlab.GetMatrix("GetModeByTor.JV", true); if (optoutJMJ != null) { optoutJMJ.value = Matlab.GetMatrix("GetModeByTor.JMJ", true); } if (optoutJM != null) { optoutJM.value = Matlab.GetMatrix("GetModeByTor.J' * GetModeByTor.M", true); } Matlab.Clear("GetModeByTor"); for (int i = 0; i < m; i++) { toreigvecs[i] = V.GetColVector(i); toreigvals[i] = D[i]; tormodes[i] = JV.GetColVector(i); modes[i] = new Mode(); modes[i].eigval = toreigvals[i]; modes[i].eigvec = tormodes[i]; modes[i].th = i; } } return(modes); } case "fn-eig(JMJ^-1/2 * JHJ * JMJ^-1/2)": /// Solve the problem of using eng(H,M). /// /// eig(H,M) => H.v = M.v.l /// H.(M^-1/2 . M^1/2).v = (M^1/2 . M^1/2).v.l /// M^-1/2 . H.(M^-1/2 . M^1/2).v = M^1/2 .v.l /// (M^-1/2 . H . M^-1/2) . (M^1/2.v) = (M^1/2.v).l /// (M^-1/2 . H . M^-1/2) . w = w.l /// where (M^1/2.v) = w /// v = M^-1/2 . w /// where M = V . D . V' /// M^-1/2 = V . (1/sqrt(D)) . V' /// M^-1/2 . M^-1/2 . M = (V . (1/sqrt(D)) . V') . (V . (1/sqrt(D)) . V') . (V . D . V') /// = V . (1/sqrt(D)) . (1/sqrt(D)) . D . V' /// = V . I . V' /// = I { int n = J.ColSize; int m = J.RowSize; //Matrix M = massmat; // univ.GetMassMatrix(3); Vector[] toreigvecs = new Vector[m]; Vector[] tormodes = new Vector[m]; double[] toreigvals = new double[m]; Mode[] modes = new Mode[m]; { Matrix H = hessian; HDebug.Assert(hessian.ColSize == hessian.RowSize); Matrix M = Matrix.Zeros(hessian.ColSize, hessian.RowSize); HDebug.Assert(3 * masses.Size == M.ColSize, M.ColSize == M.RowSize); for (int i = 0; i < M.ColSize; i++) { M[i, i] = masses[i / 3]; } Matrix Jt = J.Tr(); Matrix JMJ = fnMul(Jt, M, J); // JMJ = J' * M * J Matrix JHJ = fnMul(Jt, H, J); // JHJ = J' * H * J Matrix V; Vector D; { // [V, D] = eig(JMJ) var VD = fnEigSymm(JMJ); V = VD.Item1; D = VD.Item2; } Matrix jmj; { // jmj = sqrt(JMJ) Vector isD = new double[D.Size]; for (int i = 0; i < isD.Size; i++) { isD[i] = 1 / Math.Sqrt(D[i]); } jmj = fnMul(V, LinAlg.Diag(isD), V.Tr()); } { // [V, D] = eig(jmj * JHJ * jmj) Matrix jmj_JHJ_jmj = fnMul(jmj, JHJ, jmj); var VD = fnEigSymm(jmj_JHJ_jmj); V = VD.Item1; D = VD.Item2; } V = fnMul(jmj, V, null); // V = jmj * V Matrix JV = fnMul(J, V, null); // JV = J * V if (optoutJMJ != null) { optoutJMJ.value = JMJ; } if (optoutJM != null) { optoutJM.value = fnMul(Jt, M, null); // J' * M } for (int i = 0; i < m; i++) { toreigvecs[i] = V.GetColVector(i); toreigvals[i] = D[i]; tormodes[i] = JV.GetColVector(i); modes[i] = new Mode(); modes[i].eigval = toreigvals[i]; modes[i].eigvec = tormodes[i]; modes[i].th = i; } } //if(Debug.IsDebuggerAttached) //{ // Mode[] tmodes = GetModeByTorsional(hessian, masses, J); // Debug.Assert(modes.Length == tmodes.Length); // for(int i=0; i<modes.Length; i++) // { // Debug.AssertTolerance(0.00001, modes[i].eigval - tmodes[i].eigval); // Debug.AssertTolerance(0.00001, modes[i].eigvec - tmodes[i].eigvec); // } //} return(modes); } case "eig(JHJ,JMJ)": /// Generalized eigendecomposition does not guarantee that the eigenvalue be normalized. /// This becomes a problem when a B-factor (determined using eig(H,M)) is compared with another B-factor (determined using eig(M^-1/2 H M^-1/2)). /// This problem is being solved using case "eig(JMJ^-1/2 * JHJ * JMJ^-1/2)" using (new Matlab.NamedLock("GetModeByTor")) { int n = J.ColSize; int m = J.RowSize; //Matrix M = massmat; // univ.GetMassMatrix(3); Matrix JMJ; { Matlab.PutMatrix("GetModeByTor.J", J); //Matlab.PutMatrix("GetModeByTor.M", M); Matlab.PutVector("GetModeByTor.m", masses); // ex: m = [1,2,...,n] Matlab.Execute("GetModeByTor.m3 = kron(GetModeByTor.m,[1;1;1]);"); // ex: m3 = [1,1,1,2,2,2,...,n,n,n] Matlab.Execute("GetModeByTor.M = diag(GetModeByTor.m3);"); Matlab.Execute("GetModeByTor.JMJ = GetModeByTor.J' * GetModeByTor.M * GetModeByTor.J;"); JMJ = Matlab.GetMatrix("GetModeByTor.JMJ"); Matlab.Clear("GetModeByTor"); } Matrix JHJ; { Matlab.PutMatrix("GetModeByTor.J", J); Matlab.PutMatrix("GetModeByTor.H", hessian); Matlab.Execute("GetModeByTor.JHJ = GetModeByTor.J' * GetModeByTor.H * GetModeByTor.J;"); JHJ = Matlab.GetMatrix("GetModeByTor.JHJ"); Matlab.Clear("GetModeByTor"); } Vector[] toreigvecs = new Vector[m]; Vector[] tormodes = new Vector[m]; double[] toreigvals = new double[m]; Mode[] modes = new Mode[m]; { Matlab.PutMatrix("GetModeByTor.JHJ", JHJ); Matlab.PutMatrix("GetModeByTor.JMJ", JMJ); Matlab.PutMatrix("GetModeByTor.J", J); Matlab.Execute("[GetModeByTor.V, GetModeByTor.D] = eig(GetModeByTor.JHJ, GetModeByTor.JMJ);"); Matlab.Execute("GetModeByTor.D = diag(GetModeByTor.D);"); Matlab.Execute("GetModeByTor.JV = GetModeByTor.J * GetModeByTor.V;"); Matrix V = Matlab.GetMatrix("GetModeByTor.V"); Vector D = Matlab.GetVector("GetModeByTor.D"); Matrix JV = Matlab.GetMatrix("GetModeByTor.JV"); Matlab.Clear("GetModeByTor"); for (int i = 0; i < m; i++) { toreigvecs[i] = V.GetColVector(i); toreigvals[i] = D[i]; tormodes[i] = JV.GetColVector(i); modes[i] = new Mode(); modes[i].eigval = toreigvals[i]; modes[i].eigvec = tormodes[i]; modes[i].th = i; } } return(modes); } } return(null); }
public static HessForcInfo GetCoarseHessForcSubSimple (object[] atoms , HessMatrix hess , Vector[] forc , List <int>[] lstNewIdxRemv , double thres_zeroblk , ILinAlg ila , bool cloneH , string[] options // { "pinv(D)" } ) { HessMatrix H = hess; Vector F = forc.ToVector(); if (cloneH) { H = H.CloneHess(); } bool process_disp_console = false; bool parallel = true; for (int iter = lstNewIdxRemv.Length - 1; iter >= 0; iter--) { //int[] ikeep = lstNewIdxRemv[iter].Item1; int[] iremv = lstNewIdxRemv[iter].ToArray(); int iremv_min = iremv.Min(); int iremv_max = iremv.Max(); HDebug.Assert(H.ColBlockSize == H.RowBlockSize); int blksize = H.ColBlockSize; //HDebug.Assert(ikeep.Max() < blksize); //HDebug.Assert(iremv.Max() < blksize); //HDebug.Assert(iremv.Max()+1 == blksize); //HDebug.Assert(iremv.Max() - iremv.Min() + 1 == iremv.Length); int[] idxkeep = HEnum.HEnumFromTo(0, iremv_min - 1).ToArray(); int[] idxremv = HEnum.HEnumFromTo(iremv_min, iremv_max).ToArray(); //HDebug.Assert(idxkeep.HUnionWith(idxremv).Length == blksize); IterInfo iterinfo = new IterInfo(); iterinfo.sizeHessBlkMat = idxremv.Max() + 1; // H.ColBlockSize; iterinfo.numAtomsRemoved = idxremv.Length; iterinfo.time0 = DateTime.UtcNow; //////////////////////////////////////////////////////////////////////////////////////// // make C sparse double C_density0; double C_density1; { double thres_absmax = thres_zeroblk; C_density0 = 0; List <Tuple <int, int> > lstIdxToMakeZero = new List <Tuple <int, int> >(); foreach (var bc_br_bval in H.EnumBlocksInCols(idxremv)) { int bc = bc_br_bval.Item1; int br = bc_br_bval.Item2; var bval = bc_br_bval.Item3; if (br >= iremv_min) { // bc_br is in D, not in C continue; } C_density0++; double absmax_bval = bval.HAbsMax(); if (absmax_bval < thres_absmax) { lstIdxToMakeZero.Add(new Tuple <int, int>(bc, br)); } } C_density1 = C_density0 - lstIdxToMakeZero.Count; foreach (var bc_br in lstIdxToMakeZero) { int bc = bc_br.Item1; int br = bc_br.Item2; HDebug.Assert(bc > br); var Cval = H.GetBlock(bc, br); var Dval = H.GetBlock(bc, bc); var Aval = H.GetBlock(br, br); var Bval = Cval.Tr(); H.SetBlock(bc, br, null); // nCval = Cval -Cval H.SetBlock(bc, bc, Dval + Cval); // nDval = Dval - (-Cval) = Dval + Cval // nBval = Bval -Bval H.SetBlock(br, br, Aval + Bval); // nAval = Aval - (-Bval) = Aval + Bval } iterinfo.numSetZeroBlock = lstIdxToMakeZero.Count; iterinfo.numNonZeroBlock = (int)C_density1; C_density0 /= (idxkeep.Length * idxremv.Length); C_density1 /= (idxkeep.Length * idxremv.Length); } //////////////////////////////////////////////////////////////////////////////////////// // get A, B, C, D HessMatrix A = H.SubMatrixByAtoms(false, idxkeep, idxkeep); HessMatrix B = H.SubMatrixByAtoms(false, idxkeep, idxremv); HessMatrix C = H.SubMatrixByAtoms(false, idxremv, idxkeep); HessMatrix D = H.SubMatrixByAtoms(false, idxremv, idxremv); Vector nF; Vector nG; { nF = new double[idxkeep.Length * 3]; nG = new double[idxremv.Length * 3]; for (int i = 0; i < idxkeep.Length * 3; i++) { nF[i] = F[i]; } for (int i = 0; i < idxremv.Length * 3; i++) { nG[i] = F[i + nF.Size]; } } Matlab.PutMatrix("A", A, true); Matlab.PutMatrix("B", B, true); Matlab.PutMatrix("C", C, true); Matlab.PutMatrix("D", D, true); Matlab.PutVector("F", nF); Matlab.PutVector("G", nG); //////////////////////////////////////////////////////////////////////////////////////// // Get B.inv(D).C // // var BInvDC_BInvDG = Get_BInvDC_BInvDG_WithSqueeze(C, D, nG, process_disp_console // , options // , thld_BinvDC: thres_zeroblk/lstNewIdxRemv.Length // , parallel: parallel // ); // HessMatrix B_invD_C = BInvDC_BInvDG.Item1; // Vector B_invD_G = BInvDC_BInvDG.Item2; // GC.Collect(0); Matlab.Execute("BinvD = B * inv(D);"); Matlab.Execute("clear B, D;"); Matlab.Execute("BinvDC = BinvD * C;"); Matlab.Execute("BinvDG = BinvD * G;"); //////////////////////////////////////////////////////////////////////////////////////// // Get A - B.inv(D).C // F - B.inv(D).G Matlab.Execute("HH = A - BinvDC;"); Matlab.Execute("FF = F - BinvDG;"); //////////////////////////////////////////////////////////////////////////////////////// // Replace A -> H H = Matlab.GetMatrix("HH", H.Zeros, true); F = Matlab.GetVector("FF"); Matlab.Execute("clear;"); { ValueTuple <HessMatrix, Vector> BBInvDDCC_BBInvDDGG = Get_BInvDC_BInvDG_Simple (C , D , nG , process_disp_console: process_disp_console , thld_BinvDC: thres_zeroblk / lstNewIdxRemv.Length , parallel: parallel ); HessMatrix HH = A - BBInvDDCC_BBInvDDGG.Item1; Vector FF = nF - BBInvDDCC_BBInvDDGG.Item2; double dbg_HH = (HH - H).HAbsMax(); double dbg_FF = (FF - F).ToArray().MaxAbs(); HDebug.Assert(Math.Abs(dbg_HH) < 0.00000001); HDebug.Assert(Math.Abs(dbg_FF) < 0.00000001); } { ValueTuple <HessMatrix, Vector> BBInvDDCC_BBInvDDGG = Get_BInvDC_BInvDG (C , D , nG , process_disp_console: process_disp_console , options: new string[0] , thld_BinvDC: thres_zeroblk / lstNewIdxRemv.Length , parallel: parallel ); HessMatrix HH = A - BBInvDDCC_BBInvDDGG.Item1; Vector FF = nF - BBInvDDCC_BBInvDDGG.Item2; double dbg_HH = (HH - H).HAbsMax(); double dbg_FF = (FF - F).ToArray().MaxAbs(); HDebug.Assert(Math.Abs(dbg_HH) < 0.00000001); HDebug.Assert(Math.Abs(dbg_FF) < 0.00000001); } { ValueTuple <HessMatrix, Vector> BBInvDDCC_BBInvDDGG = Get_BInvDC_BInvDG_WithSqueeze (C , D , nG , process_disp_console: process_disp_console , options: new string[0] , thld_BinvDC: thres_zeroblk / lstNewIdxRemv.Length , parallel: parallel ); HessMatrix HH = A - BBInvDDCC_BBInvDDGG.Item1; Vector FF = nF - BBInvDDCC_BBInvDDGG.Item2; double dbg_HH = (HH - H).HAbsMax(); double dbg_FF = (FF - F).ToArray().MaxAbs(); HDebug.Assert(Math.Abs(dbg_HH) < 0.00000001); HDebug.Assert(Math.Abs(dbg_FF) < 0.00000001); } GC.Collect(); } HDebug.Assert(H.ColSize == H.RowSize); HDebug.Assert(H.ColSize == F.Size); return(new HessForcInfo { hess = H, forc = F.ToVectors(3), }); }
public static Matrix[] GetAnisou(Matrix hessMassWeighted, double[] mass, double scale = 10000 *1000) { /// Estimation of "anisotropic temperature factors" (ANISOU) /// /// delta = hess^-1 * force /// = (0 + V7*V7'/L7 + V8*V8'/L8 + V9*V9'/L9 + ...) * force (* assume that 1-6 eigvecs/eigvals are ignored, because rot,trans *) /// /// Assume that force[i] follows gaussian distributions N(0,1). Here, if there are 1000 samples, let denote i-th force as fi, and its j-th element as fi[j] /// Then, $V7' * fi = si7, V8' * fi = si8, ...$ follows gaussian distribution N(0,1), too. /// Its moved position by k-th eigen component is determined then, as /// dik = (Vk * Vk' / Lk) * Fi /// = Vk / Lk * (Vk' * Fi) /// = Vk / Lk * Sik. /// Additionally, the moved position j-th atom is: /// dik[j] = Vk[j] / Lk[j] * Sik. /// and its correlation matrix is written as (because its mean position is 0 !!!): /// Cik[j] = dik[j] * dik[j]' /// = [dik[j]_x * dik[j]_x dik[j]_x * dik[j]_y dik[j]_x * dik[j]_z] /// [dik[j]_y * dik[j]_x dik[j]_y * dik[j]_y dik[j]_y * dik[j]_z] /// [dik[j]_z * dik[j]_x dik[j]_z * dik[j]_y dik[j]_z * dik[j]_z] /// = (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik). /// /// Note that Sik*Sik follows the chi-square distribution, because Sik follows the gaussian distribution N(0,1). /// Additionally, note that the thermal fluctuation is (not one projection toward k-th eigen component with only i-th force, but) the results of 1..i.. forced movements and 1..k.. eigen components. /// Therefore, for j-th atom, the accumulation of the correlation over all forces (1..i..) with all eigen components (1..k..) is: /// C[j] = sum_{i,k} {(Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik)}. /// /// Here, Sik is normal distribution independent to i and k. Therefore, the mean of C[j] is /// E(C[j]) = E( sum_{i,k} {(Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik)} ) /// = sum_{i,k} E( (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik) ) /// = sum_{i,k} { (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * E(Sik*Sik) } /// = sum_{i,k} { (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * 1 } (* because mean of E(x*x)=1 where x~N(0,1) *) /// = sum_{k} { (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) } /// /// Note that E(C[j]) is same to the j-th diagonal component of inverse hessian matrix (except, the eigenvalues are squared). /// /// Fixation: Gromacx generate the ensemble X by /// X[j] = sum_{k} {Vk / sqrt(Lk[j]) / sqrt(mass[j]) * x_k}, /// where x~N(0,1). However, the above is assumed as /// X[j] = sum_{k} {Vk / Lk[j] * x_k}. /// In order to apply the assumption by the Gromacs ensemble, The equation should be fixed as /// E(C[j]) = sum_{k} { (Vk[j] * Vk[j]') / (sqrt(Lk[j])*sqrt(Lk[j])) } /// = sum_{k} { (Vk[j] * Vk[j]') / Lk[j] / mass[j] } /// // anisotropic temperature factors int size = mass.Length; HDebug.Assert(hessMassWeighted.RowSize == size * 3, hessMassWeighted.ColSize == size * 3); Matrix[] anisous = new Matrix[size]; using (new Matlab.NamedLock("ANISOU")) { Matlab.Clear("ANISOU"); Matlab.PutMatrix("ANISOU.H", hessMassWeighted); Matlab.Execute("[ANISOU.V,ANISOU.D] = eig(ANISOU.H);"); Matlab.Execute("ANISOU.D = diag(ANISOU.D);"); Matlab.Execute("ANISOU.D = ANISOU.D(7:end);"); //Matlab.Execute("ANISOU.D = ANISOU.D .^ 2;"); // assume the gromacs ensemble condition Matlab.Execute("ANISOU.V = ANISOU.V(:,7:end);"); Matlab.Execute("ANISOU.invH = ANISOU.V * pinv(diag(ANISOU.D)) * ANISOU.V';"); for (int i = 0; i < size; i++) { string idx = string.Format("{0}:{1}", i * 3 + 1, i * 3 + 3); anisous[i] = Matlab.GetMatrix("ANISOU.invH(" + idx + "," + idx + ")"); } for (int i = 0; i < size; i++) { anisous[i] *= (scale / mass[i]); } Matlab.Clear("ANISOU"); } return(anisous); }
public void __MinimizeTNM(List <ForceField.IForceField> frcflds) { HDebug.Assert(false); // do not use this, because not finished yet Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = this.BuildFlexibilityGraph(); List <Universe.RotableInfo> univ_rotinfos = this.GetRotableInfo(univ_flexgraph); Vector[] coords = this.GetCoords(); double tor_normInf = double.PositiveInfinity; //double maxRotAngle = 0.1; Vector[] forces = null; MatrixByArr hessian = null; double forces_normsInf = 1; int iter = 0; double scale = 1; this._SaveCoordsToPdb(iter.ToString("0000") + ".pdb", coords); while (true) { iter++; forces = this.GetVectorsZero(); hessian = new double[size * 3, size *3]; Dictionary <string, object> cache = new Dictionary <string, object>(); double energy = this.GetPotential(frcflds, coords, ref forces, ref hessian, cache); forces_normsInf = (new Vectors(forces)).NormsInf().ToArray().Max(); //System.Console.WriteLine("iter {0:###}: frcnrminf {1}, energy {2}, scale {3}", iter, forces_normsInf, energy, scale); //if(forces_normsInf < 0.001) //{ // break; //} Vector torz = null; double maxcarz = 1; Vector car = null; //double using (new Matlab.NamedLock("TEST")) { MatrixByArr H = hessian; MatrixByArr J = Paper.TNM.GetJ(this, this.GetCoords(), univ_rotinfos); Vector m = this.GetMasses(3); Matlab.PutVector("TEST.F", Vector.FromBlockvector(forces)); Matlab.PutMatrix("TEST.J", J); Matlab.PutMatrix("TEST.H", H); Matlab.PutVector("TEST.M", m); Matlab.Execute("TEST.M = diag(TEST.M);"); Matlab.Execute("TEST.JMJ = TEST.J' * TEST.M * TEST.J;"); Matlab.Execute("TEST.JHJ = TEST.J' * TEST.H * TEST.J;"); // (J' H J) tor = J' F // (V' D V) tor = J' F <= (V,D) are (eigvec,eigval) of generalized eigenvalue problem with (A = JHJ, B = JMJ) // tor = inv(V' D V) J' F Matlab.Execute("[TEST.V, TEST.D] = eig(TEST.JHJ, TEST.JMJ);"); //Matlab.Execute("TEST.zidx = 3:end;"); Matlab.Execute("TEST.invJHJ = TEST.V * pinv(TEST.D ) * TEST.V';"); Matlab.Execute("TEST.tor = TEST.invJHJ * TEST.J' * TEST.F;"); Matlab.Execute("TEST.car = TEST.J * TEST.tor;"); car = Matlab.GetVector("TEST.car"); Matlab.Execute("[TEST.DS, TEST.DSI] = sort(abs(diag(TEST.D)));"); Matlab.Execute("TEST.zidx = TEST.DSI(6:end);"); Matlab.Execute("TEST.Dz = TEST.D;"); //Matlab.Execute("TEST.Dz(TEST.zidx,TEST.zidx) = 0;"); Matlab.Execute("TEST.invJHJz = TEST.V * pinv(TEST.Dz) * TEST.V';"); Matlab.Execute("TEST.torz = TEST.invJHJz * TEST.J' * TEST.F;"); Matlab.Execute("TEST.carz = TEST.J * TEST.torz;"); torz = Matlab.GetVector("TEST.torz"); maxcarz = Matlab.GetValue("max(max(abs(TEST.carz)))"); scale = 1; if (maxcarz > 0.01) { scale = scale * 0.01 / maxcarz; } Matlab.Clear("TEST"); }; tor_normInf = torz.NormInf(); double frcnrinf = car.ToArray().HAbs().Max(); if (maxcarz < 0.001) { break; } System.Console.WriteLine("iter {0:###}: frcnrminf {1}, tor(frcnrinf) {2}, energy {3}, scale {4}", iter, forces_normsInf, frcnrinf, energy, scale); HDebug.Assert(univ_rotinfos.Count == torz.Size); for (int i = 0; i < univ_rotinfos.Count; i++) { Universe.RotableInfo rotinfo = univ_rotinfos[i]; Vector rotOrigin = coords[rotinfo.bondedAtom.ID]; double rotAngle = torz[i] * scale; // (maxRotAngle / tor_normInf); if (rotAngle == 0) { continue; } Vector rotAxis = coords[rotinfo.bond.atoms[1].ID] - coords[rotinfo.bond.atoms[0].ID]; Quaternion rot = new Quaternion(rotAxis, rotAngle); MatrixByArr rotMat = rot.RotationMatrix; foreach (Atom atom in rotinfo.rotAtoms) { int id = atom.ID; Vector coord = rotMat * (coords[id] - rotOrigin) + rotOrigin; coords[id] = coord; } } this._SaveCoordsToPdb(iter.ToString("0000") + ".pdb", coords); } }
public Mode[] GetModesMassReduced(bool delhess, int?numModeReturn, Dictionary <string, object> secs) { HessMatrix mwhess_ = GetHessMassWeighted(delhess); IMatrix <double> mwhess = mwhess_; bool bsparse = (mwhess_ is HessMatrixSparse); Mode[] modes; using (new Matlab.NamedLock("")) { string msg = ""; { if (bsparse) { Matlab.PutSparseMatrix("V", mwhess_.GetMatrixSparse(), 3, 3); } else { Matlab.PutMatrix("V", ref mwhess, true, true); } } msg += Matlab.Execute("tic;"); msg += Matlab.Execute("V = (V+V')/2; "); // make symmetric { // eigen-decomposition if (bsparse) { if (numModeReturn != null) { int numeig = numModeReturn.Value; string cmd = "eigs(V," + numeig + ",'sm')"; msg += Matlab.Execute("[V,D] = " + cmd + "; "); } else { msg += Matlab.Execute("[V,D] = eig(full(V)); "); } } else { msg += Matlab.Execute("[V,D] = eig(V); "); } } msg += Matlab.Execute("tm=toc; "); if (secs != null) { int numcore = Matlab.Environment.NumCores; double tm = Matlab.GetValue("tm"); secs.Clear(); secs.Add("num cores", numcore); secs.Add("secs multi-threaded", tm); secs.Add("secs estimated single-threaded", tm * Math.Sqrt(numcore)); /// x=[]; for i=1:20; tic; H=rand(100*i); [V,D]=eig(H+H'); xx=toc; x=[x;i,xx]; fprintf('%d, %f\n',i,xx); end; x /// /// http://www.mathworks.com/help/matlab/ref/matlabwindows.html /// run matlab in single-thread: matlab -nodesktop -singleCompThread /// multi-thread: matlab -nodesktop /// /// my computer, single thread: cst1={0.0038,0.0106,0.0277,0.0606,0.1062,0.1600,0.2448,0.3483,0.4963,0.6740,0.9399,1.1530,1.4568,1.7902,2.1794,2.6387,3.0510,3.6241,4.2203,4.8914}; /// 2 cores: cst2={0.0045,0.0098,0.0252,0.0435,0.0784,0.1203,0.1734,0.2382,0.3316,0.4381,0.5544,0.6969,1.0170,1.1677,1.4386,1.7165,2.0246,2.4121,2.8124,3.2775}; /// scale: (cst1.cst2)/(cst1.cst1) = 0.663824 /// approx: (cst1.cst2)/(cst1.cst1)*Sqrt[2.2222] = 0.989566 /// my computer, single thread: cst1={0.0073,0.0158,0.0287,0.0573,0.0998,0.1580,0.2377,0.3439,0.4811,0.6612,0.8738,1.0974,1.4033,1.7649,2.1764,2.6505,3.1142,3.5791,4.1910,4.8849}; /// 2 cores: cst2={0.0085,0.0114,0.0250,0.0475,0.0719,0.1191,0.1702,0.2395,0.3179,0.4319,0.5638,0.7582,0.9454,1.1526,1.4428,1.7518,2.0291,2.4517,2.8200,3.3090}; /// scale: (cst1.cst2)/(cst1.cst1) = 0.671237 /// approx: (cst1.cst2)/(cst1.cst1)*Sqrt[2.2222] = 1.00062 /// ts4-stat , singhe thread: cst1={0.0048,0.0213,0.0641,0.1111,0.1560,0.2013,0.3307,0.3860,0.4213,0.8433,1.0184,1.3060,1.9358,2.2699,2.1718,3.0149,3.1081,4.3594,5.0356,5.5260}; /// 12 cores: cst2={0.2368,0.0614,0.0235,0.1321,0.0574,0.0829,0.1078,0.1558,0.1949,0.3229,0.4507,0.3883,0.4685,0.6249,0.6835,0.8998,0.9674,1.1851,1.3415,1.6266}; /// scale: (cst1.cst2)/(cst1.cst1) = 0.286778 /// (cst1.cst2)/(cst1.cst1)*Sqrt[12*1.1111] = 1.04716 /// ts4-stat , singhe thread: cst1={0.0138,0.0215,0.0522,0.0930,0.1783,0.2240,0.2583,0.4054,0.4603,0.9036,0.9239,1.5220,1.9443,2.1042,2.3583,3.0208,3.5507,3.8810,3.6943,6.2085}; /// 12 cores: cst2={0.1648,0.1429,0.1647,0.0358,0.0561,0.0837,0.1101,0.1525,0.2084,0.2680,0.3359,0.4525,0.4775,0.7065,0.6691,0.9564,1.0898,1.2259,1.2926,1.5879}; /// scale: (cst1.cst2)/(cst1.cst1) = 0.294706 /// (cst1.cst2)/(cst1.cst1)*Sqrt[12] = 1.02089 /// ts4-stat , singhe thread: cst1={0.0126,0.0183,0.0476,0.0890,0.1353,0.1821,0.2265,0.3079,0.4551,0.5703,1.0009,1.2175,1.5922,1.8805,2.1991,2.3096,3.7680,3.7538,3.9216,5.2899,5.6737,7.0783,8.8045,9.0091,9.9658,11.6888,12.8311,14.4933,17.2462,17.5660}; /// 12 cores: cst2={0.0690,0.0117,0.0275,0.0523,0.0819,0.1071,0.1684,0.1984,0.1974,0.2659,0.3305,0.4080,0.4951,0.7089,0.9068,0.7936,1.2632,1.0708,1.3187,1.6106,1.7216,2.1114,2.8249,2.7840,2.8259,3.3394,4.3092,4.2708,5.3358,5.7479}; /// scale: (cst1.cst2)/(cst1.cst1) = 0.311008 /// (cst1.cst2)/(cst1.cst1)*Sqrt[12] = 1.07736 /// Therefore, the speedup using multi-core could be sqrt(#core) } msg += Matlab.Execute("D = diag(D); "); if (msg.Trim() != "") { System.Console.WriteLine(); bool domanual = HConsole.ReadValue <bool>("possibly failed. Will you do ((('V = (V+V')/2;[V,D] = eig(V);D = diag(D);))) manually ?", false, null, false, true); if (domanual) { Matlab.Clear(); Matlab.PutMatrix("V", ref mwhess, true, true); System.Console.WriteLine("cleaning working-space and copying V in matlab are done."); System.Console.WriteLine("do V = (V+V')/2; [V,D]=eig(V); D=diag(D);"); while (HConsole.ReadValue <bool>("V and D are ready to use in matlab?", false, null, false, true) == false) { ; } //string path_V = HConsole.ReadValue<string>("path V.mat", @"C:\temp\V.mat", null, false, true); //Matlab.Execute("clear;"); //Matlab.PutMatrix("V", ref mwhess, true, true); //Matlab.Execute(string.Format("save('{0}', '-V7.3');", path_V)); //while(HConsole.ReadValue<bool>("ready for VD.mat containing V and D?", false, null, false, true) == false) ; //string path_VD = HConsole.ReadValue<string>("path VD.mat", @"C:\temp\VD.mat", null, false, true); //Matlab.Execute(string.Format("load '{0}';", path_V)); } } if (numModeReturn != null) { Matlab.PutValue("nmode", numModeReturn.Value); Matlab.Execute("V = V(:,1:nmode);"); Matlab.Execute("D = D(1:nmode);"); } MatrixByRowCol V = Matlab.GetMatrix("V", MatrixByRowCol.Zeros, true, true); Vector D = Matlab.GetVector("D"); HDebug.Assert(V.RowSize == D.Size); modes = new Mode[D.Size]; for (int i = 0; i < D.Size; i++) { Vector eigvec = V.GetColVector(i); double eigval = D[i]; modes[i] = new Mode { th = i, eigval = eigval, eigvec = eigvec, }; } V = null; } System.GC.Collect(); modes.UpdateMassReduced(mass.ToArray()); return(modes); }
public static double[] GetRotAngles(Universe univ , Vector[] coords , MatrixByArr hessian , Vector[] forces , MatrixByArr J = null , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null , List <Universe.RotableInfo> univ_rotinfos = null , Vector[] forceProjectedByTorsional = null , HPack <Vector> optEigvalOfTorHessian = null ) { Vector mass = univ.GetMasses(); //Vector[] dcoords = new Vector[univ.size]; //double t2 = t*t; //for(int i=0; i<univ.size; i++) // dcoords[i] = forces[i] * (0.5*t2/mass[i]); if (J == null) { if (univ_rotinfos == null) { if (univ_flexgraph == null) { univ_flexgraph = univ.BuildFlexibilityGraph(); } univ_rotinfos = univ.GetRotableInfo(univ_flexgraph); } J = TNM.GetJ(univ, coords, univ_rotinfos); } double[] dangles; using (new Matlab.NamedLock("TEST")) { Matlab.Clear("TEST"); Matlab.PutVector("TEST.F", Vector.FromBlockvector(forces)); Matlab.PutMatrix("TEST.J", J); Matlab.PutMatrix("TEST.H", hessian); Matlab.PutVector("TEST.M", univ.GetMasses(3)); Matlab.Execute("TEST.M = diag(TEST.M);"); Matlab.Execute("TEST.JHJ = TEST.J' * TEST.H * TEST.J;"); Matlab.Execute("TEST.JMJ = TEST.J' * TEST.M * TEST.J;"); // (J' H J) tor = J' F // (V' D V) tor = J' F <= (V,D) are (eigvec,eigval) of generalized eigenvalue problem with (A = JHJ, B = JMJ) // tor = inv(V' D V) J' F Matlab.Execute("[TEST.V, TEST.D] = eig(TEST.JHJ, TEST.JMJ);"); if (optEigvalOfTorHessian != null) { optEigvalOfTorHessian.value = Matlab.GetVector("diag(TEST.D)"); } { Matlab.Execute("TEST.D = diag(TEST.D);"); Matlab.Execute("TEST.D(abs(TEST.D)<1) = 0;"); // remove "eigenvalue < 1" because they will increase // the magnitude of force term too big !!! Matlab.Execute("TEST.D = diag(TEST.D);"); } Matlab.Execute("TEST.invJHJ = TEST.V * pinv(TEST.D) * TEST.V';"); Matlab.Execute("TEST.dtor = TEST.invJHJ * TEST.J' * TEST.F;"); /// f = m a /// d = 1/2 a t^2 /// = 0.5 a : assuming t=1 /// = 0.5 f/m /// f = m a /// = 2 m d t^-2 /// = 2 m d : assuming t=1 /// /// coord change /// dr = 0.5 a t^2 /// = 0.5 f/m : assuming t=1 /// = 0.5 M^-1 F : M is mass matrix, F is the net force of each atom /// /// torsional angle change /// dtor = (J' M J)^-1 J' M * dr : (6) of TNM paper /// = (J' M J)^-1 J' M * 0.5 M^-1 F /// = 0.5 (J' M J)^-1 J' F /// /// force filtered by torsional ... /// F_tor = ma /// = 2 M (J dtor) /// = 2 M J 0.5 (J' M J)^-1 J' F /// = M J (J' M J)^-1 J' F /// /// H J dtor = F /// = F_tor : update force as the torsional filtered force /// = M J (J' M J)^-1 J' F /// (J' H J) dtor = (J' M J) (J' M J)^-1 J' F /// (V D V') dtor = (J' M J) (J' M J)^-1 J' F : eigen decomposition of (J' H J) using /// generalized eigenvalue problem with (J' M J) /// dtor = (V D^-1 V') (J' M J) (J' M J)^-1 J' F : (J' M J) (J' M J)^-1 = I. However, it has /// the projection effect of J'F into (J' M J) /// vector space(?). The projection will be taken /// care by (V D^-1 V') /// = (V D^-1 V') J' F /// dangles = Matlab.GetVector("TEST.dtor"); if (forceProjectedByTorsional != null) { HDebug.Assert(forceProjectedByTorsional.Length == forces.Length); Matlab.Execute("TEST.F_tor = TEST.M * TEST.J * pinv(TEST.JMJ) * TEST.J' * TEST.F;"); Vector lforceProjectedByTorsional = Matlab.GetVector("TEST.F_tor"); HDebug.Assert(lforceProjectedByTorsional.Size == forceProjectedByTorsional.Length * 3); for (int i = 0; i < forceProjectedByTorsional.Length; i++) { int i3 = i * 3; forceProjectedByTorsional[i] = new double[] { lforceProjectedByTorsional[i3 + 0], lforceProjectedByTorsional[i3 + 1], lforceProjectedByTorsional[i3 + 2], }; } } Matlab.Clear("TEST"); } return(dangles); }
public static bool GetHessAnmSelfTest() { if (HDebug.Selftest() == false) { return(true); } string pdbpath = @"C:\Users\htna\svn\htnasvn_htna\VisualStudioSolutions\Library2\HTLib2.Bioinfo\Bioinfo.Data\pdb\1MJC.pdb"; if (HFile.Exists(pdbpath) == false) { return(false); } Pdb pdb = Pdb.FromFile(pdbpath); for (int i = 0; i < pdb.atoms.Length; i++) { HDebug.Assert(pdb.atoms[0].altLoc == pdb.atoms[i].altLoc); HDebug.Assert(pdb.atoms[0].chainID == pdb.atoms[i].chainID); } List <Vector> coords = pdb.atoms.ListCoord(); double cutoff = 13; Matlab.Execute("clear"); Matlab.PutMatrix("x", Matrix.FromRowVectorList(coords).ToArray()); Matlab.PutValue("cutoffR", cutoff); Matlab.Execute(@"% function cx = contactsNew(x, cutoffR) % Contact matrix within cutoff distance. % Author: Guang Song % New: 10/25/2006 % %n = size(x,1); % Method 1: slow %for i=1:n % center = x(i,:); % distSqr(:,i) = sum((x-center(ones(n,1),:)).^2,2); %end %cx = sparse(distSqr<=cutoffR^2); % Method 2: fast! about 28 times faster when array size is 659x3 %tot = zeros(n,n); %for i=1:3 % xi = x(:,ones(n,1)*i); % %tmp = (xi - xi.').^2; % %tot = tot + tmp; % tot = tot + (xi - xi.').^2; %end %cx = sparse(tot<=cutoffR^2); % Method 3: this implementation is the shortest! but sligtly slower than % method 2 %xn = x(:,:,ones(n,1)); % create n copy x %xnp = permute(xn,[3,2,1]); %tot = sum((xn-xnp).^2,2); % sum along x, y, z %cx = sparse(permute(tot,[1,3,2])<=cutoffR^2); % put it into one line like below actually slows it down. Don't do that. %cx = sparse(permute(sum((xn-permute(xn,[3,2,1])).^2,2),[1,3,2])<=cutoffR^2); %Method 4: using function pdist, which I just know % this one line implementation is even faster. 2 times than method 2. cx = sparse(squareform(pdist(x)<=cutoffR)); "); Matlab.Execute(@"% function [anm,xij,normxij] = baseHess(x,cx) % Basic Hessian Matrix % Author: Guang Song % Created: Feb 23, 2005 % Rev: 11/09/06 % % cx is the contact map. Also with gama info (new! 02/23/05) dim = size(x,1); nx = x(:,:,ones(1,dim)); xij = permute(nx,[3,1,2]) - permute(nx,[1,3,2]); % xj - xi for any i j normxij = squareform(pdist(x)) + diag(ones(1,dim)); % + diag part added to avoid divided by zero. anm = zeros(3*dim,3*dim); for i=1:3 for j=1:3 tmp = xij(:,:,i).*xij(:,:,j).*cx./normxij.^2; tmp = diag(sum(tmp)) - tmp; anm(i:3:3*dim,j:3:3*dim) = tmp; end end % if dR is scalar, then dR = 1, back to GNM. %if abs(i-j) == 1 % virtual bonds. should stay around 3.81 A % K33 = K33*100; %end anm = (anm+anm')/2; % make sure return matrix is symmetric (fix numeric error) "); Matrix anm_gsong = Matlab.GetMatrix("anm"); Matlab.Execute("clear;"); Matrix anm = GetHessAnm(coords.ToArray(), cutoff); if (anm_gsong.RowSize != anm.RowSize) { HDebug.Assert(false); return(false); } if (anm_gsong.ColSize != anm.ColSize) { HDebug.Assert(false); return(false); } for (int c = 0; c < anm.ColSize; c++) { for (int r = 0; r < anm.RowSize; r++) { if (Math.Abs(anm_gsong[c, r] - anm[c, r]) >= 0.00000001) { HDebug.Assert(false); return(false); } } } return(true); }
private static HessMatrix GetHessCoarseResiIterImpl_Matlab_IterLowerTri_Get_BInvDC (HessMatrix A , HessMatrix C , HessMatrix D , bool process_disp_console , string[] options , double?thld_BinvDC = null , bool parallel = false ) { if (options == null) { options = new string[0]; } HessMatrix B_invD_C; Dictionary <int, int> Cbr_CCbr = new Dictionary <int, int>(); List <int> CCbr_Cbr = new List <int>(); foreach (ValueTuple <int, int, MatrixByArr> bc_br_bval in C.EnumBlocks()) { int Cbr = bc_br_bval.Item2; if (Cbr_CCbr.ContainsKey(Cbr) == false) { HDebug.Assert(Cbr_CCbr.Count == CCbr_Cbr.Count); int CCbr = Cbr_CCbr.Count; Cbr_CCbr.Add(Cbr, CCbr); CCbr_Cbr.Add(Cbr); HDebug.Assert(CCbr_Cbr[CCbr] == Cbr); } } HessMatrix CC = C.Zeros(C.ColSize, Cbr_CCbr.Count * 3); { Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bc_br_bval) { int Cbc = bc_br_bval.Item1; int CCbc = Cbc; int Cbr = bc_br_bval.Item2; int CCbr = Cbr_CCbr[Cbr]; var bval = bc_br_bval.Item3; lock (CC) CC.SetBlock(CCbc, CCbr, bval); }; if (parallel) { Parallel.ForEach(C.EnumBlocks(), func); } else { foreach (var bc_br_bval in C.EnumBlocks()) { func(bc_br_bval); } } } if (process_disp_console) { System.Console.Write("squeezeC({0,6}->{1,6} blk), ", C.RowBlockSize, CC.RowBlockSize); } { /// If a diagonal element of D is null, that row and column should be empty. /// This assume that the atom is removed. In this case, the removed diagonal block /// is replace as the 3x3 identity matrix. /// /// [B1 0] [ A 0 ]^-1 [C1 C2 C3] = [B1 0] [ A^-1 0 ] [C1 C2 C3] /// [B2 0] [ 0 I ] [ 0 0 0] [B2 0] [ 0 I^-1 ] [ 0 0 0] /// [B3 0] [B3 0] /// = [B1.invA 0] [C1 C2 C3] /// [B2.invA 0] [ 0 0 0] /// [B3.invA 0] /// = [B1.invA.C1 B1.invA.C2 B1.invA.C3] /// [B2.invA.C1 B2.invA.C2 B2.invA.C3] /// [B3.invA.C1 B3.invA.C2 B3.invA.C3] /// { //HDebug.Exception(D.ColBlockSize == D.RowBlockSize); for (int bi = 0; bi < D.ColBlockSize; bi++) { if (D.HasBlock(bi, bi) == true) { continue; } //for(int bc=0; bc< D.ColBlockSize; bc++) HDebug.Exception( D.HasBlock(bc, bi) == false); //for(int br=0; br< D.RowBlockSize; br++) HDebug.Exception( D.HasBlock(bi, br) == false); //for(int br=0; br<CC.RowBlockSize; br++) HDebug.Exception(CC.HasBlock(bi, br) == false); D.SetBlock(bi, bi, new double[3, 3] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }); } } HessMatrix BB_invDD_CC; using (new Matlab.NamedLock("")) { Matlab.Execute("clear;"); if (process_disp_console) { System.Console.Write("matlab("); } Matlab.PutMatrix("C", CC); if (process_disp_console) { System.Console.Write("C"); //Matlab.PutSparseMatrix("C", CC.GetMatrixSparse(), 3, 3); } Matlab.PutMatrix("D", D); if (process_disp_console) { System.Console.Write("D"); } // Matlab.Execute("BinvDC = (C' / D) * C;"); { if (options.Contains("pinv(D)")) { Matlab.Execute("BinvDC = C' * pinv(D) * C;"); } if (options.Contains("/D -> pinv(D)")) { string msg = Matlab.Execute("BinvDC = (C' / D) * C;", true); if (msg != "") { Matlab.Execute("BinvDC = C' * pinv(D) * C;"); } } else if (options.Contains("/D")) { Matlab.Execute("BinvDC = (C' / D) * C;"); } else { Matlab.Execute("BinvDC = (C' / D) * C;"); } } if (process_disp_console) { System.Console.Write("X"); } //Matrix BBinvDDCC = Matlab.GetMatrix("BinvDC", true); if (thld_BinvDC != null) { Matlab.Execute("BinvDC(find(BinvDC < " + thld_BinvDC.ToString() + ")) = 0;"); } if (Matlab.GetValue("nnz(BinvDC)/numel(BinvDC)") > 0.5 || HDebug.True) { Func <int, int, HessMatrix> Zeros = delegate(int colsize, int rowsize) { return(HessMatrixDense.ZerosDense(colsize, rowsize)); }; BB_invDD_CC = Matlab.GetMatrix("BinvDC", Zeros, true); if (process_disp_console) { System.Console.Write("Y), "); } } else { Matlab.Execute("[i,j,s] = find(sparse(BinvDC));"); TVector <int> listi = Matlab.GetVectorLargeInt("i", true); TVector <int> listj = Matlab.GetVectorLargeInt("j", true); TVector <double> lists = Matlab.GetVectorLarge("s", true); int colsize = Matlab.GetValueInt("size(BinvDC,1)"); int rowsize = Matlab.GetValueInt("size(BinvDC,2)"); Dictionary <ValueTuple <int, int>, MatrixByArr> lst_bc_br_bval = new Dictionary <ValueTuple <int, int>, MatrixByArr>(); for (long i = 0; i < listi.SizeLong; i++) { int c = listi[i] - 1; int bc = c / 3; int ic = c % 3; int r = listj[i] - 1; int br = r / 3; int ir = r % 3; double v = lists[i]; ValueTuple <int, int> bc_br = new ValueTuple <int, int>(bc, br); if (lst_bc_br_bval.ContainsKey(bc_br) == false) { lst_bc_br_bval.Add(bc_br, new double[3, 3]); } lst_bc_br_bval[bc_br][ic, ir] = v; } // Matrix BBinvDDCC = Matrix.Zeros(colsize, rowsize); // for(int i=0; i<listi.Length; i++) // BBinvDDCC[listi[i]-1, listj[i]-1] = lists[i]; // //GC.Collect(0); BB_invDD_CC = D.Zeros(colsize, rowsize); foreach (var bc_br_bval in lst_bc_br_bval) { int bc = bc_br_bval.Key.Item1; int br = bc_br_bval.Key.Item2; var bval = bc_br_bval.Value; BB_invDD_CC.SetBlock(bc, br, bval); } if (process_disp_console) { System.Console.Write("Z), "); } if (HDebug.IsDebuggerAttached) { for (int i = 0; i < listi.Size; i++) { int c = listi[i] - 1; int r = listj[i] - 1; double v = lists[i]; HDebug.Assert(BB_invDD_CC[c, r] == v); } } } Matlab.Execute("clear;"); } //GC.Collect(0); B_invD_C = A.Zeros(C.RowSize, C.RowSize); { // for(int bcc=0; bcc<CCbr_Cbr.Count; bcc++) // { // int bc = CCbr_Cbr[bcc]; // for(int brr=0; brr<CCbr_Cbr.Count; brr++) // { // int br = CCbr_Cbr[brr]; // HDebug.Assert(B_invD_C.HasBlock(bc, br) == false); // if(BB_invDD_CC.HasBlock(bcc, brr) == false) // continue; // var bval = BB_invDD_CC.GetBlock(bcc, brr); // B_invD_C.SetBlock(bc, br, bval); // HDebug.Exception(A.HasBlock(bc, bc)); // HDebug.Exception(A.HasBlock(br, br)); // } // } Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bcc_brr_bval) { int bcc = bcc_brr_bval.Item1; int brr = bcc_brr_bval.Item2; var bval = bcc_brr_bval.Item3; int bc = CCbr_Cbr[bcc]; int br = CCbr_Cbr[brr]; //lock(B_invD_C) B_invD_C.SetBlockLock(bc, br, bval); }; if (parallel) { Parallel.ForEach(BB_invDD_CC.EnumBlocks(), func); } else { foreach (var bcc_brr_bval in BB_invDD_CC.EnumBlocks()) { func(bcc_brr_bval); } } } } GC.Collect(0); return(B_invD_C); }
private static HessMatrix Get_BInvDC (HessMatrix A , HessMatrix C , HessMatrix D , bool process_disp_console , string[] options , bool parallel = false ) { HessMatrix B_invD_C; Dictionary <int, int> Cbr_CCbr = new Dictionary <int, int>(); List <int> CCbr_Cbr = new List <int>(); foreach (ValueTuple <int, int, MatrixByArr> bc_br_bval in C.EnumBlocks()) { int Cbr = bc_br_bval.Item2; if (Cbr_CCbr.ContainsKey(Cbr) == false) { HDebug.Assert(Cbr_CCbr.Count == CCbr_Cbr.Count); int CCbr = Cbr_CCbr.Count; Cbr_CCbr.Add(Cbr, CCbr); CCbr_Cbr.Add(Cbr); HDebug.Assert(CCbr_Cbr[CCbr] == Cbr); } } HessMatrix CC = HessMatrixSparse.ZerosSparse(C.ColSize, Cbr_CCbr.Count * 3); { Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bc_br_bval) { int Cbc = bc_br_bval.Item1; int CCbc = Cbc; int Cbr = bc_br_bval.Item2; int CCbr = Cbr_CCbr[Cbr]; var bval = bc_br_bval.Item3; lock (CC) CC.SetBlock(CCbc, CCbr, bval); }; if (parallel) { Parallel.ForEach(C.EnumBlocks(), func); } else { foreach (var bc_br_bval in C.EnumBlocks()) { func(bc_br_bval); } } } if (process_disp_console) { System.Console.Write("squeezeC({0,6}->{1,6} blk), ", C.RowBlockSize, CC.RowBlockSize); } { /// If a diagonal element of D is null, that row and column should be empty. /// This assume that the atom is removed. In this case, the removed diagonal block /// is replace as the 3x3 identity matrix. /// /// [B1 0] [ A 0 ]^-1 [C1 C2 C3] = [B1 0] [ A^-1 0 ] [C1 C2 C3] /// [B2 0] [ 0 I ] [ 0 0 0] [B2 0] [ 0 I^-1 ] [ 0 0 0] /// [B3 0] [B3 0] /// = [B1.invA 0] [C1 C2 C3] /// [B2.invA 0] [ 0 0 0] /// [B3.invA 0] /// = [B1.invA.C1 B1.invA.C2 B1.invA.C3] /// [B2.invA.C1 B2.invA.C2 B2.invA.C3] /// [B3.invA.C1 B3.invA.C2 B3.invA.C3] /// { //HDebug.Exception(D.ColBlockSize == D.RowBlockSize); for (int bi = 0; bi < D.ColBlockSize; bi++) { if (D.HasBlock(bi, bi) == true) { continue; } //for(int bc=0; bc< D.ColBlockSize; bc++) HDebug.Exception( D.HasBlock(bc, bi) == false); //for(int br=0; br< D.RowBlockSize; br++) HDebug.Exception( D.HasBlock(bi, br) == false); //for(int br=0; br<CC.RowBlockSize; br++) HDebug.Exception(CC.HasBlock(bi, br) == false); D.SetBlock(bi, bi, new double[3, 3] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }); } } HessMatrixSparse BB_invDD_CC; using (new Matlab.NamedLock("")) { Matlab.Execute("clear;"); if (process_disp_console) { System.Console.Write("matlab("); } Matlab.PutMatrix("C", CC); if (process_disp_console) { System.Console.Write("C"); //Matlab.PutSparseMatrix("C", CC.GetMatrixSparse(), 3, 3); } Matlab.PutMatrix("D", D); if (process_disp_console) { System.Console.Write("D"); } { // Matlab.Execute("BinvDC = (C' / D) * C;"); if (options != null && options.Contains("pinv(D)")) { string msg = Matlab.Execute("BinvDC = (C' / D) * C;", true); if (msg != "") { Matlab.Execute("BinvDC = C' * pinv(D) * C;"); } } else { Matlab.Execute("BinvDC = (C' / D) * C;"); } } if (process_disp_console) { System.Console.Write("X"); } /// » whos /// Name Size Bytes Class Attributes /// // before compressing C matrix /// C 1359x507 5512104 double // C 1359x1545 16797240 double /// CC 1359x507 198464 double sparse // CC 1359x1545 206768 double sparse /// D 1359x1359 14775048 double // D 1359x1359 14775048 double /// DD 1359x1359 979280 double sparse // DD 1359x1359 979280 double sparse /// ans 1x1 8 double /// /// » tic; for i=1:30; A=(C' / D) * C; end; toc dense * dense * dense => 8.839463 seconds. (win) /// Elapsed time is 8.839463 seconds. /// » tic; for i=1:30; AA=(CC' / DD) * CC; end; toc sparse * sparse * sparse => 27.945534 seconds. /// Elapsed time is 27.945534 seconds. /// » tic; for i=1:30; AAA=(C' / DD) * C; end; toc sparse * dense * sparse => 29.136144 seconds. /// Elapsed time is 29.136144 seconds. /// » /// » tic; for i=1:30; A=(C' / D) * C; end; toc dense * dense * dense => 8.469071 seconds. (win) /// Elapsed time is 8.469071 seconds. /// » tic; for i=1:30; AA=(CC' / DD) * CC; end; toc sparse * sparse * sparse => 28.309953 seconds. /// Elapsed time is 28.309953 seconds. /// » tic; for i=1:30; AAA=(C' / DD) * C; end; toc sparse * dense * sparse => 28.586375 seconds. /// Elapsed time is 28.586375 seconds. Matrix BBinvDDCC = Matlab.GetMatrix("BinvDC", true); if (process_disp_console) { System.Console.Write("Y"); } //Matlab.Execute("[i,j,s] = find(sparse(BinvDC));"); //int[] listi = Matlab.GetVectorInt("i"); //int[] listj = Matlab.GetVectorInt("j"); //double[] lists = Matlab.GetVector("s"); //int colsize = Matlab.GetValueInt("size(BinvDC,1)"); //int rowsize = Matlab.GetValueInt("size(BinvDC,2)"); //Matrix BBinvDDCC = Matrix.Zeros(colsize, rowsize); //for(int i=0; i<listi.Length; i++) // BBinvDDCC[listi[i], listj[i]] = lists[i]; //GC.Collect(0); BB_invDD_CC = HessMatrixSparse.FromMatrix(BBinvDDCC, parallel); if (process_disp_console) { System.Console.Write("Z), "); } Matlab.Execute("clear;"); } //GC.Collect(0); B_invD_C = HessMatrixSparse.ZerosSparse(C.RowSize, C.RowSize); { // for(int bcc=0; bcc<CCbr_Cbr.Count; bcc++) // { // int bc = CCbr_Cbr[bcc]; // for(int brr=0; brr<CCbr_Cbr.Count; brr++) // { // int br = CCbr_Cbr[brr]; // HDebug.Assert(B_invD_C.HasBlock(bc, br) == false); // if(BB_invDD_CC.HasBlock(bcc, brr) == false) // continue; // var bval = BB_invDD_CC.GetBlock(bcc, brr); // B_invD_C.SetBlock(bc, br, bval); // HDebug.Exception(A.HasBlock(bc, bc)); // HDebug.Exception(A.HasBlock(br, br)); // } // } Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bcc_brr_bval) { int bcc = bcc_brr_bval.Item1; int brr = bcc_brr_bval.Item2; var bval = bcc_brr_bval.Item3; int bc = CCbr_Cbr[bcc]; int br = CCbr_Cbr[brr]; lock (B_invD_C) B_invD_C.SetBlock(bc, br, bval); }; if (parallel) { Parallel.ForEach(BB_invDD_CC.EnumBlocks(), func); } else { foreach (var bcc_brr_bval in BB_invDD_CC.EnumBlocks()) { func(bcc_brr_bval); } } } } GC.Collect(0); return(B_invD_C); }
public static Anisou[] FromHessian(MatrixByArr hessMassWeighted, double[] mass, double scale = 10000 *1000 , string cachepath = null ) { /// Estimation of "anisotropic temperature factors" (ANISOU) /// /// delta = hess^-1 * force /// = (0 + V7*V7'/L7 + V8*V8'/L8 + V9*V9'/L9 + ...) * force (* assume that 1-6 eigvecs/eigvals are ignored, because rot,trans *) /// /// Assume that force[i] follows gaussian distributions N(0,1). Here, if there are 1000 samples, let denote i-th force as fi, and its j-th element as fi[j] /// Then, $V7' * fi = si7, V8' * fi = si8, ...$ follows gaussian distribution N(0,1), too. /// Its moved position by k-th eigen component is determined then, as /// dik = (Vk * Vk' / Lk) * Fi /// = Vk / Lk * (Vk' * Fi) /// = Vk / Lk * Sik. /// Additionally, the moved position j-th atom is: /// dik[j] = Vk[j] / Lk[j] * Sik. /// and its correlation matrix is written as (because its mean position is 0 !!!): /// Cik[j] = dik[j] * dik[j]' /// = [dik[j]_x * dik[j]_x dik[j]_x * dik[j]_y dik[j]_x * dik[j]_z] /// [dik[j]_y * dik[j]_x dik[j]_y * dik[j]_y dik[j]_y * dik[j]_z] /// [dik[j]_z * dik[j]_x dik[j]_z * dik[j]_y dik[j]_z * dik[j]_z] /// = (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik). /// /// Note that Sik*Sik follows the chi-square distribution, because Sik follows the gaussian distribution N(0,1). /// Additionally, note that the thermal fluctuation is (not one projection toward k-th eigen component with only i-th force, but) the results of 1..i.. forced movements and 1..k.. eigen components. /// Therefore, for j-th atom, the accumulation of the correlation over all forces (1..i..) with all eigen components (1..k..) is: /// C[j] = sum_{i,k} {(Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik)}. /// /// Here, Sik is normal distribution independent to i and k. Therefore, the mean of C[j] is /// E(C[j]) = E( sum_{i,k} {(Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik)} ) /// = sum_{i,k} E( (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * (Sik*Sik) ) /// = sum_{i,k} { (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * E(Sik*Sik) } /// = sum_{i,k} { (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) * 1 } (* because mean of E(x*x)=1 where x~N(0,1) *) /// = sum_{k} { (Vk[j] * Vk[j]') / (Lk[j]*Lk[j]) } /// /// Note that E(C[j]) is same to the j-th diagonal component of inverse hessian matrix (except, the eigenvalues are squared). /// /// Fixation: Gromacx generate the ensemble X by /// X[j] = sum_{k} {Vk / sqrt(Lk[j]) / sqrt(mass[j]) * x_k}, /// where x~N(0,1). However, the above is assumed as /// X[j] = sum_{k} {Vk / Lk[j] * x_k}. /// In order to apply the assumption by the Gromacs ensemble, The equation should be fixed as /// E(C[j]) = sum_{k} { (Vk[j] * Vk[j]') / (sqrt(Lk[j])*sqrt(Lk[j])) } /// = sum_{k} { (Vk[j] * Vk[j]') / Lk[j] / mass[j] } /// int size = mass.Length; HDebug.Assert(hessMassWeighted.RowSize == size * 3, hessMassWeighted.ColSize == size * 3); Anisou[] anisous = new Anisou[size]; if (cachepath != null && HFile.Exists(cachepath)) { List <Anisou> lstanisou; HDebug.Verify(HSerialize.Deserialize <List <Anisou> >(cachepath, null, out lstanisou)); anisous = lstanisou.ToArray(); return(anisous); } // anisotropic temperature factors using (new Matlab.NamedLock("ANISOU")) { Matlab.Clear("ANISOU"); Matlab.PutMatrix("ANISOU.H", hessMassWeighted); Matlab.Execute("[ANISOU.V,ANISOU.D] = eig(ANISOU.H);"); Matlab.Execute("ANISOU.D = diag(ANISOU.D);"); // get diagonal { Matlab.Execute("[ANISOU.sortD, ANISOU.sortIdxD] = sort(abs(ANISOU.D));"); // sorted index of abs(D) Matlab.Execute("ANISOU.D(ANISOU.sortIdxD(1:6)) = 0;"); // set the 6 smallest eigenvalues as zero //Matlab.Execute("ANISOU.D(ANISOU.D < 0) = 0;"); // set negative eigenvalues as zero } //{ // Matlab.Execute("ANISOU.D(1:6) = 0;"); //} Matlab.Execute("ANISOU.invD = 1 ./ ANISOU.D;"); // set invD Matlab.Execute("ANISOU.invD(ANISOU.D == 0) = 0;"); // set Inf (by divided by zero) as zero //Matlab.Execute("ANISOU.D = ANISOU.D .^ 2;"); // assume the gromacs ensemble condition Matlab.Execute("ANISOU.invH = ANISOU.V * diag(ANISOU.invD) * ANISOU.V';"); for (int i = 0; i < size; i++) { string idx = string.Format("{0}:{1}", i * 3 + 1, i * 3 + 3); MatrixByArr U = Matlab.GetMatrix("ANISOU.invH(" + idx + "," + idx + ")"); U *= (scale / mass[i]); anisous[i] = Anisou.FromMatrix(U); } Matlab.Clear("ANISOU"); } if (cachepath != null) { HSerialize.Serialize(cachepath, null, new List <Anisou>(anisous)); } return(anisous); }
public static Mode[] PCA(Matrix cov, int numconfs, Func <Matrix, Tuple <Matrix, Vector> > fnEig = null) { HDebug.Assert(cov.RowSize == cov.ColSize); int size3 = cov.ColSize; if (fnEig == null) { fnEig = delegate(Matrix A) { using (new Matlab.NamedLock("TEST")) { Matlab.Clear("TEST"); Matlab.PutMatrix("TEST.H", A); Matlab.Execute("TEST.H = (TEST.H + TEST.H')/2;"); Matlab.Execute("[TEST.V, TEST.D] = eig(TEST.H);"); Matlab.Execute("TEST.D = diag(TEST.D);"); //Matlab.Execute("TEST.idx = find(TEST.D>0.00000001);"); //Matrix leigvecs = Matlab.GetMatrix("TEST.V(:,TEST.idx)"); //Vector leigvals = Matlab.GetVector("TEST.D(TEST.idx)"); Matrix leigvecs = Matlab.GetMatrix("TEST.V"); Vector leigvals = Matlab.GetVector("TEST.D"); Matlab.Clear("TEST"); return(new Tuple <Matrix, Vector>(leigvecs, leigvals)); } } } ; Tuple <Matrix, Vector> eigs = fnEig(cov); Matrix eigvecs = eigs.Item1; Vector eigvals = eigs.Item2; HDebug.Assert(eigvecs.ColSize == size3, eigvals.Size == eigvecs.RowSize); Mode[] modes = new Mode[eigvals.Size]; for (int im = 0; im < modes.Length; im++) { modes[im] = new Mode { eigvec = eigvecs.GetColVector(im), eigval = 1.0 / eigvals[im], th = im } } ; int maxNumEigval = Math.Min(numconfs - 1, size3); HDebug.Assert(maxNumEigval >= 0); HDebug.Assert(eigvals.Size == size3); if (maxNumEigval < size3) { modes = modes.SortByEigvalAbs().ToArray(); modes = modes.Take(maxNumEigval).ToArray(); foreach (var mode in modes) { HDebug.Assert(mode.eigval >= 0); } //Tuple<Mode[], Mode[]> nzmodes_zeromodes = modes.SeparateTolerants(); //Mode[] modesNonzero = nzmodes_zeromodes.Item1; //Mode[] modesZero = nzmodes_zeromodes.Item2; //modes = modesZero; } HDebug.Assert(modes.Length == maxNumEigval); return(modes); }