Пример #1
0
        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());
        }
Пример #2
0
        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);
        }
Пример #3
0
            public static double[] GetBFactor(Mode[] modes, double[] mass = null)
            {
                if (HDebug.Selftest())
                #region selftest
                {
                    using (new Matlab.NamedLock("SELFTEST"))
                    {
                        Matlab.Clear("SELFTEST");
                        Matlab.Execute("SELFTEST.hess = rand(30);");
                        Matlab.Execute("SELFTEST.hess = SELFTEST.hess + SELFTEST.hess';");
                        Matlab.Execute("SELFTEST.invhess = inv(SELFTEST.hess);");
                        Matlab.Execute("SELFTEST.bfactor3 = diag(SELFTEST.invhess);");
                        Matlab.Execute("SELFTEST.bfactor = SELFTEST.bfactor3(1:3:end) + SELFTEST.bfactor3(2:3:end) + SELFTEST.bfactor3(3:3:end);");
                        MatrixByArr selftest_hess    = Matlab.GetMatrix("SELFTEST.hess");
                        Mode[]      selftest_mode    = Hess.GetModesFromHess(selftest_hess);
                        Vector      selftest_bfactor = BFactor.GetBFactor(selftest_mode);
                        Vector      selftest_check   = Matlab.GetVector("SELFTEST.bfactor");
                        Vector      selftest_diff    = selftest_bfactor - selftest_check;
                        HDebug.AssertTolerance(0.00000001, selftest_diff);
                        Matlab.Clear("SELFTEST");
                    }
                }
                #endregion

                int size = modes[0].size;
                if (mass != null)
                {
                    HDebug.Assert(size == mass.Length);
                }
                double[] bfactor = new double[size];
                for (int i = 0; i < size; i++)
                {
                    foreach (Mode mode in modes)
                    {
                        bfactor[i] += mode.eigvec[i * 3 + 0] * mode.eigvec[i * 3 + 0] / mode.eigval;
                        bfactor[i] += mode.eigvec[i * 3 + 1] * mode.eigvec[i * 3 + 1] / mode.eigval;
                        bfactor[i] += mode.eigvec[i * 3 + 2] * mode.eigvec[i * 3 + 2] / mode.eigval;
                    }
                    if (mass != null)
                    {
                        bfactor[i] /= mass[i];
                    }
                }
                return(bfactor);
            }
Пример #4
0
            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);
            }
Пример #5
0
            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);
            }
Пример #6
0
            public static CGetHessCoarseResiIterImpl GetHessCoarseResiIterImpl_Matlab(HessMatrix H, List <int>[] lstNewIdxRemv, double thres_zeroblk)
            {
                HessMatrix CGH = null;
                List <HessCoarseResiIterInfo> iterinfos = new List <HessCoarseResiIterInfo>();

                using (new Matlab.NamedLock("CGHessIter"))
                {
                    Matlab.PutSparseMatrix("CG.H", H.GetMatrixSparse(), 3, 3);
                    Matlab.PutValue("CG.th", thres_zeroblk);
                    Matlab.PutValue("CG.iter", lstNewIdxRemv.Length);
                    for (int iter = lstNewIdxRemv.Length - 1; iter >= 0; iter--)
                    {
                        int[] iremv   = lstNewIdxRemv[iter].ToArray();
                        int[] idxkeep = HEnum.HEnumFromTo(0, iremv.Min() - 1).ToArray();
                        int[] idxremv = HEnum.HEnumFromTo(iremv.Min(), iremv.Max()).ToArray();
                        Matlab.PutVector("CG.idxkeep", idxkeep);
                        Matlab.PutVector("CG.idxremv", idxremv);
                        Matlab.Execute("CG.idxkeep = sort([CG.idxkeep*3+1; CG.idxkeep*3+2; CG.idxkeep*3+3]);");
                        Matlab.Execute("CG.idxremv = sort([CG.idxremv*3+1; CG.idxremv*3+2; CG.idxremv*3+3]);");

                        HessCoarseResiIterInfo iterinfo = new HessCoarseResiIterInfo();
                        iterinfo.sizeHessBlkMat  = idxremv.Max() + 1; // H.ColBlockSize;
                        iterinfo.numAtomsRemoved = idxremv.Length;
                        iterinfo.idxkeep         = idxkeep.HClone();
                        iterinfo.idxremv         = idxremv.HClone();
                        iterinfo.time0           = DateTime.UtcNow;

                        if (HDebug.IsDebuggerAttached)
                        {
                            int maxkeep = Matlab.GetValueInt("max(CG.idxkeep)");
                            int minremv = Matlab.GetValueInt("min(CG.idxremv)");
                            HDebug.Assert(maxkeep + 1 == minremv);
                            int maxremv = Matlab.GetValueInt("max(CG.idxremv)");
                            int Hsize   = Matlab.GetValueInt("max(size(CG.H))");
                            HDebug.Assert(Hsize == maxremv);
                            int idxsize = Matlab.GetValueInt("length(union(CG.idxkeep,CG.idxremv))");
                            HDebug.Assert(Hsize == idxsize);
                        }
                        Matlab.Execute("CG.A = CG.H(CG.idxkeep, CG.idxkeep);");
                        Matlab.Execute("CG.B = CG.H(CG.idxkeep, CG.idxremv);");
                        //Matlab.Execute("CG.C = CG.H(CG.idxremv, CG.idxkeep);");
                        Matlab.Execute("CG.D = CG.H(CG.idxremv, CG.idxremv);");
                        HDebug.Assert(false);
                        Matlab.Execute("CG.B(abs(CG.B) < CG.th) = 0;");     /// matlab cannot handle this call. Matlab try to use 20G memory.
                        Matlab.Execute("CG.BDC = CG.B * inv(full(CG.D)) * CG.B';");
                        Matlab.Execute("CG.BDC = sparse(CG.BDC);");
                        Matlab.Execute("CG.BDC(abs(CG.BDC) < (CG.th / CG.iter)) = 0;");
                        Matlab.Execute("CG.H = CG.A - sparse(CG.BDC);");

                        iterinfo.numSetZeroBlock = -1;
                        iterinfo.numNonZeroBlock = -1;
                        iterinfo.numAddIgnrBlock = -1;
                        iterinfo.usedMemoryByte  = -1;
                        iterinfo.time1           = DateTime.UtcNow;
                        iterinfos.Add(iterinfo);

                        System.Console.WriteLine(" - {0:000} : makezero {1,5}, nonzero {2,5}, numIgnMul {3,7}, numRemvAtoms {4,3}, {5,5:0.00} sec, {6} mb, {7}x{7}"
                                                 , iter
                                                 , iterinfo.numSetZeroBlock
                                                 , iterinfo.numNonZeroBlock
                                                 , iterinfo.numAddIgnrBlock
                                                 , iterinfo.numAtomsRemoved
                                                 , iterinfo.compSec
                                                 , iterinfo.usedMemoryByte / (1024 * 1024)
                                                 , (idxkeep.Length * 3)
                                                 );
                    }
                    Matrix CG_H = Matlab.GetMatrix("CG.H");
                    CGH = new HessMatrixDense {
                        hess = CG_H
                    };
                }

                return(new CGetHessCoarseResiIterImpl
                {
                    iterinfos = iterinfos,
                    H = CGH,
                });
            }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
            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
                           ));
            }
Пример #10
0
            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);
            }
Пример #11
0
            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);
            }
Пример #12
0
            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);
            }
Пример #13
0
        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
            });
        }
Пример #14
0
        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);
        }
Пример #15
0
        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);
        }
Пример #16
0
            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);
            }
Пример #17
0
            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 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),
                });
            }
Пример #19
0
            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);
            }
Пример #20
0
        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);
        }
            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);
            }
Пример #22
0
            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);
            }
Пример #23
0
        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);
        }
Пример #24
0
        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);
        }