示例#1
0
        public static Tuple <Sheet[], Atom[]>[] HSelectAtoms <Atom>(this IList <Sheet> sheets, IList <Atom> atoms)
            where Atom : IAtom
        {
            var chain_resi_atoms = atoms.GroupChainIDResSeq();
            var id_sheets        = sheets.HGroupBySheetID();

            List <Tuple <Sheet[], Atom[]> > list = new List <Tuple <Sheet[], Atom[]> >();

            foreach (string id in id_sheets.Keys)
            {
                Sheet[] idsheets = id_sheets[id];

                List <Atom> idsheets_atoms = new List <Atom>();
                foreach (var sheet in idsheets)
                {
                    HDebug.Exception(sheet.initChainID == sheet.endChainID);
                    char chain = sheet.initChainID;
                    if (chain_resi_atoms.ContainsKey(chain) == false)
                    {
                        continue;
                    }
                    var chainresi_atoms = chain_resi_atoms[chain];

                    int[] resis;
                    resis = new int[] { sheet.initSeqNum, sheet.endSeqNum };
                    resis = resis.HSort();
                    resis = HEnum.HEnumFromTo(resis[0], resis[1]).ToArray();

                    foreach (var resi in resis)
                    {
                        if (chainresi_atoms.ContainsKey(resi) == false)
                        {
                            continue;
                        }
                        idsheets_atoms.AddRange(chainresi_atoms[resi]);
                    }
                }

                list.Add(new Tuple <Sheet[], Atom[]>
                         (
                             idsheets,
                             idsheets_atoms.ToArray()
                         ));
            }

            return(list.ToArray());
        }
            public static CGetHessCoarseResiIterImpl GetHessCoarseResiIterImpl_Matlab_IterLowerTri
                (object[] atoms
                , HessMatrix H
                , List <int>[] lstNewIdxRemv
                , double thres_zeroblk
                , ILinAlg ila
                , bool cloneH
                , string[] options // { "pinv(D)" }
                )
            {
                ila = null;
                if (cloneH)
                {
                    H = H.CloneHess();
                }

                bool process_disp_console = true;

                if (options != null && options.Contains("print process"))
                {
                    process_disp_console = true;
                }

                bool parallel = true;

                /// keep only lower triangle of H (lower block triangles)
                {
                    HashSet <Tuple <int, int, MatrixByArr> > lstUppTrig = new HashSet <Tuple <int, int, MatrixByArr> >();
                    foreach (ValueTuple <int, int, MatrixByArr> bc_br_bval in H.EnumBlocks())
                    {
                        int bc = bc_br_bval.Item1;
                        int br = bc_br_bval.Item2;
                        if (bc < br)
                        {
                            lstUppTrig.Add(bc_br_bval.ToTuple());
                        }
                    }
                    foreach (Tuple <int, int, MatrixByArr> bc_br_bval in lstUppTrig)
                    {
                        int bc = bc_br_bval.Item1;
                        int br = bc_br_bval.Item2;
                        HDebug.Assert(bc < br);
                        H.SetBlock(bc, br, null);
                    }
                }
                GC.Collect();

                List <DateTime> process_time = new List <DateTime>();

                //System.Console.WriteLine("begin coarse-graining");
                List <HessCoarseResiIterInfo> iterinfos = new List <HessCoarseResiIterInfo>();

                for (int iter = lstNewIdxRemv.Length - 1; iter >= 0; iter--)
                {
                    process_time.Clear();
                    if (process_disp_console)
                    {
                        process_time.Add(DateTime.UtcNow);
                        System.Console.Write(" - {0:000} : ", 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);

                    HessCoarseResiIterInfo iterinfo = new HessCoarseResiIterInfo();
                    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;       // HessMatrix    A = H.SubMatrixByAtoms(false, idxkeep, idxkeep);
                                            // HessMatrix    B = H.SubMatrixByAtoms(false, idxkeep, idxremv);
                    HessMatrix C;           // HessMatrix    C = H.SubMatrixByAtoms(false, idxremv, idxkeep, parallel:parallel);
                    HessMatrix D;           // HessMatrix    D = H.SubMatrixByAtoms(false, idxremv, idxremv, parallel:parallel);
                    {
                        C = H.Zeros(idxremv.Length * 3, idxkeep.Length * 3);
                        D = H.Zeros(idxremv.Length * 3, idxremv.Length * 3);

                        //List<Tuple<int, int, MatrixByArr>> lst_bc_br_bval = H.EnumBlocksInCols(idxremv).ToList();
                        //foreach(var bc_br_bval in lst_bc_br_bval)
                        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;

                            H.SetBlock(bc, br, null);
                            if (bc > iremv_max)
                            {
                                HDebug.Assert(false); continue;
                            }
                            if (br > iremv_max)
                            {
                                HDebug.Assert(false); continue;
                            }
                            if (br < iremv_min)
                            {
                                int nc = bc - iremv_min;
                                int nr = br;
                                HDebug.Assert(C.HasBlock(nc, nr) == false);
                                C.SetBlock(nc, nr, bval.CloneT());
                            }
                            else
                            {
                                int nc = bc - iremv_min;
                                int nr = br - iremv_min;
                                HDebug.Assert(D.HasBlock(nc, nr) == false);
                                D.SetBlock(nc, nr, bval);
                                if (nc != nr)
                                {
                                    HDebug.Assert(D.HasBlock(nr, nc) == false);
                                    D.SetBlock(nr, nc, bval.Tr());
                                }
                            }
                        }
                        HDebug.Assert(H.EnumBlocksInCols(idxremv).Count() == 0);
                    }
                    if (process_disp_console)
                    {
                        process_time.Add(DateTime.UtcNow);
                        int ptc = process_time.Count;
                        System.Console.Write("CD({0:00.00} min), ", (process_time[ptc - 1] - process_time[ptc - 2]).TotalMinutes);
                    }

                    ////////////////////////////////////////////////////////////////////////////////////////
                    // Get B.inv(D).C
                    HessMatrix B_invD_C;
                    {
                        {
                            B_invD_C = GetHessCoarseResiIterImpl_Matlab_IterLowerTri_Get_BInvDC(A, C, D, process_disp_console
                                                                                                , options
                                                                                                , thld_BinvDC: thres_zeroblk / lstNewIdxRemv.Length
                                                                                                , parallel: parallel
                                                                                                );
                        }
                        if (process_disp_console)
                        {
                            process_time.Add(DateTime.UtcNow);
                            int ptc = process_time.Count;
                            System.Console.Write("B.invD.C({0:00.00} min), ", (process_time[ptc - 1] - process_time[ptc - 2]).TotalMinutes);
                        }
                        GC.Collect(0);
                    }

                    ////////////////////////////////////////////////////////////////////////////////////////
                    // Get A - B.inv(D).C
                    /// iterinfo.numAddIgnrBlock = A.UpdateAdd(B_invD_C, -1, null, thres_zeroblk/lstNewIdxRemv.Length, parallel:parallel);
                    {
                        HessMatrix __this = A;
                        HessMatrix other  = B_invD_C;
                        double     _thres_NearZeroBlock = thres_zeroblk / lstNewIdxRemv.Length;

                        int[] _count         = new int[1];
                        int[] _count_ignored = new int[1];

                        //foreach(var bc_br_bval in other.EnumBlocks())
                        Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bc_br_bval)
                        {
                            _count[0]++;
                            int         bc         = bc_br_bval.Item1;
                            int         br         = bc_br_bval.Item2;
                            MatrixByArr other_bmat = bc_br_bval.Item3;
                            if (bc < br)
                            {
                                return; // continue;
                            }
                            if (other_bmat.HAbsMax() <= _thres_NearZeroBlock)
                            {
                                /// other_bmat = other_bmat    -other_bmat;
                                /// other_diag = other_diag - (-other_bmat) = other_diag + other_bmat;
                                ///  this_diag =  this_diat - B_invD_C
                                ///            =  this_diat - other_diag
                                ///            =  this_diat - (other_diag + other_bmat)
                                ///            =  this_diat - other_diag  - other_bmat
                                ///            = (this_diat - other_bmat) - other_diag
                                ///            = (this_diat - other_bmat) - (processed later)
                                ///            = (this_diat - other_bmat)
                                MatrixByArr this_diag = __this.GetBlock(bc, bc);
                                MatrixByArr new_diag  = this_diag - other_bmat;
                                __this.SetBlockLock(bc, bc, new_diag);
                                other_bmat = null;
                                lock (_count_ignored)
                                    _count_ignored[0]++;
                            }
                            if (other_bmat != null)
                            {
                                MatrixByArr this_bmat = __this.GetBlock(bc, br);
                                if (this_bmat == null)
                                {
                                    this_bmat = new double[3, 3];
                                }
                                MatrixByArr new_bmat = this_bmat - other_bmat;
                                __this.SetBlockLock(bc, br, new_bmat);
                            }
                        };
                        if (parallel)
                        {
                            HParallel.ForEach(other.EnumBlocks(), func);
                        }
                        else
                        {
                            foreach (var bc_br_bval in other.EnumBlocks())
                            {
                                func(bc_br_bval);
                            }
                        }

                        iterinfo.numAddIgnrBlock = _count_ignored[0];
                    }
                    if (process_disp_console)
                    {
                        process_time.Add(DateTime.UtcNow);
                        int ptc = process_time.Count;
                        System.Console.Write("A-BinvDC({0:00.00} min), ", (process_time[ptc - 1] - process_time[ptc - 2]).TotalMinutes);
                    }
                    //HessMatrix nH = A - B_invD_C;
                    //nH = ((nH + nH.Tr())/2).ToHessMatrix();
                    ////////////////////////////////////////////////////////////////////////////////////////
                    // Replace A -> H
                    H = A;

                    ////////////////////////////////////////////////////////////////////////////////////////
                    // print iteration log
                    iterinfo.usedMemoryByte = GC.GetTotalMemory(false);
                    iterinfo.time1          = DateTime.UtcNow;
                    iterinfos.Add(iterinfo);

                    if (process_disp_console)
                    {
                        System.Console.Write("summary(makezero {0,5}, nonzero {1,5}, numIgnMul {2,7}, numRemvAtoms {3,3}, {4,5:0.00} min, {5} mb, {6}x{6}, nzeroBlk/Atom {7:0.00}), GC("
                                             , iterinfo.numSetZeroBlock
                                             , iterinfo.numNonZeroBlock
                                             , iterinfo.numAddIgnrBlock
                                             , iterinfo.numAtomsRemoved
                                             , iterinfo.compTime.TotalMinutes
                                             , iterinfo.usedMemoryByte / (1024 * 1024)
                                             , (idxkeep.Length * 3)
                                             , ((double)iterinfo.numNonZeroBlock / idxremv.Length)
                                             );
                    }
                    GC.Collect();
                    if (process_disp_console)
                    {
                        System.Console.WriteLine(")");
                    }
                }

                int numca = H.ColBlockSize - lstNewIdxRemv.HListCount().Sum();

                //System.Console.WriteLine("finish coarse-graining");
                {
                    int[] idxkeep = HEnum.HEnumCount(numca).ToArray();
                    H = H.SubMatrixByAtoms(false, idxkeep, idxkeep, false);
                }
                {
                    H.MakeNearZeroBlockAsZero(thres_zeroblk);
                }
                GC.Collect();
                //System.Console.WriteLine("finish resizing");

                return(new CGetHessCoarseResiIterImpl
                {
                    iterinfos = iterinfos,
                    H = H,
                });
            }
            public static CGetHessCoarseResiIterImpl GetHessCoarseResiIterImpl_ILinAlg_20150329(HessMatrix H, List <int>[] lstNewIdxRemv, double thres_zeroblk, ILinAlg ila, bool cloneH)
            {
                if (cloneH)
                {
                    H = H.CloneHess();
                }

                //System.Console.WriteLine("begin coarse-graining");
                List <HessCoarseResiIterInfo> iterinfos = new List <HessCoarseResiIterInfo>();

                for (int iter = lstNewIdxRemv.Length - 1; iter >= 0; iter--)
                {
                    //int[] ikeep = lstNewIdxRemv[iter].Item1;
                    int[] iremv = lstNewIdxRemv[iter].ToArray();
                    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);

                    HessCoarseResiIterInfo iterinfo = new HessCoarseResiIterInfo();
                    iterinfo.sizeHessBlkMat  = idxremv.Max() + 1; // H.ColBlockSize;
                    iterinfo.numAtomsRemoved = idxremv.Length;
                    iterinfo.time0           = DateTime.UtcNow;
                    {
                        //HessMatrix    A = H.SubMatrixByAtoms(false, idxkeep, idxkeep);
                        HessMatrix A = H;
                        //HessMatrix    B = H.SubMatrixByAtoms(false, idxkeep, idxremv);
                        HessMatrix C    = H.SubMatrixByAtoms(false, idxremv, idxkeep);
                        HessMatrix D    = H.SubMatrixByAtoms(false, idxremv, idxremv);
                        HessMatrix invD = new HessMatrixDense {
                            hess = ila.InvSymm(D)
                        };

                        // make B,C sparse
                        //int B_cntzero = B.MakeNearZeroBlockAsZero(thres_zeroblk);
                        iterinfo.numSetZeroBlock = C.MakeNearZeroBlockAsZero(thres_zeroblk);
                        //int B_nzeros = B.NumUsedBlocks; double B_nzeros_ = Math.Sqrt(B_nzeros);
                        iterinfo.numNonZeroBlock = C.NumUsedBlocks;

                        HessMatrix B        = C.Tr();
                        HessMatrix B_invD_C = B * invD * C;
                        iterinfo.numAddIgnrBlock = A.UpdateAdd(B_invD_C, -1, null, thres_zeroblk / lstNewIdxRemv.Length);
                        //HessMatrix nH = A - B_invD_C;
                        //nH = ((nH + nH.Tr())/2).ToHessMatrix();
                        H = A;
                    }
                    iterinfo.usedMemoryByte = GC.GetTotalMemory(false);
                    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)
                    //                        );

                    GC.Collect();
                }

                int numca = H.ColBlockSize - lstNewIdxRemv.HListCount().Sum();

                //System.Console.WriteLine("finish coarse-graining");
                {
                    int[] idxkeep = HEnum.HEnumCount(numca).ToArray();
                    H = H.SubMatrixByAtoms(false, idxkeep, idxkeep, false);
                }
                {
                    H.MakeNearZeroBlockAsZero(thres_zeroblk);
                }
                GC.Collect();
                //System.Console.WriteLine("finish resizing");

                return(new CGetHessCoarseResiIterImpl
                {
                    iterinfos = iterinfos,
                    H = H,
                });
            }
            public static CGetHessCoarseResiIterImpl GetHessCoarseResiIterImpl_ILinAlg(HessMatrix H, List <int>[] lstNewIdxRemv, double thres_zeroblk, ILinAlg ila, bool cloneH)
            {
                if (cloneH)
                {
                    H = H.CloneHess();
                }

                bool process_disp_console = true;

                DateTime[] process_time = new DateTime[7];

                //System.Console.WriteLine("begin coarse-graining");
                List <HessCoarseResiIterInfo> iterinfos = new List <HessCoarseResiIterInfo>();

                for (int iter = lstNewIdxRemv.Length - 1; iter >= 0; iter--)
                {
                    if (process_disp_console)
                    {
                        process_time[0] = DateTime.UtcNow; System.Console.Write(" - {0:000} : ", iter);
                    }

                    //int[] ikeep = lstNewIdxRemv[iter].Item1;
                    int[] iremv = lstNewIdxRemv[iter].ToArray();
                    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);

                    HessCoarseResiIterInfo iterinfo = new HessCoarseResiIterInfo();
                    iterinfo.sizeHessBlkMat  = idxremv.Max() + 1; // H.ColBlockSize;
                    iterinfo.numAtomsRemoved = idxremv.Length;
                    iterinfo.time0           = DateTime.UtcNow;
                    double C_density0 = double.NaN;
                    double C_density1 = double.NaN;
                    {
                        //HessMatrix    A = H.SubMatrixByAtoms(false, idxkeep, idxkeep);
                        HessMatrix A = H;
                        //HessMatrix    B = H.SubMatrixByAtoms(false, idxkeep, idxremv);
                        HessMatrix C = H.SubMatrixByAtoms(false, idxremv, idxkeep);                                      if (process_disp_console)
                        {
                            process_time[1] = DateTime.UtcNow; System.Console.Write("C({0:00.00} min), ", (process_time[1] - process_time[0]).TotalMinutes);
                        }
                        HessMatrix D = H.SubMatrixByAtoms(false, idxremv, idxremv);                                      if (process_disp_console)
                        {
                            process_time[2] = DateTime.UtcNow; System.Console.Write("D({0:00.00} min), ", (process_time[2] - process_time[1]).TotalMinutes);
                        }
                        HessMatrix invD = new HessMatrixDense {
                            hess = ila.InvSymm(D)
                        };                                      if (process_disp_console)
                        {
                            process_time[3] = DateTime.UtcNow; System.Console.Write("invD({0:00.00} min), ", (process_time[3] - process_time[2]).TotalMinutes);
                        }

                        // make B,C sparse
                        //int B_cntzero = B.MakeNearZeroBlockAsZero(thres_zeroblk);
                        C_density0 = C.RatioUsedBlocks;
                        iterinfo.numSetZeroBlock = C.MakeNearZeroBlockAsZero(thres_zeroblk);                                if (process_disp_console)
                        {
                            process_time[4] = DateTime.UtcNow; System.Console.Write("sparseC({0:00.00} min), ", (process_time[4] - process_time[3]).TotalMinutes);
                        }
                        //int B_nzeros = B.NumUsedBlocks; double B_nzeros_ = Math.Sqrt(B_nzeros);
                        iterinfo.numNonZeroBlock = C.NumUsedBlocks;
                        C_density1 = C.RatioUsedBlocks;

                        HessMatrix B        = C.Tr();
                        HessMatrix B_invD_C = HessMatrix.GetMul(ila, B, invD, C); /* B * invD * C;*/ if (process_disp_console)
                        {
                            process_time[5] = DateTime.UtcNow; System.Console.Write("B.invD.C({0:00.00} min), ", (process_time[5] - process_time[4]).TotalMinutes);
                        }
                        iterinfo.numAddIgnrBlock = A.UpdateAdd(B_invD_C, -1, null, thres_zeroblk / lstNewIdxRemv.Length);     if (process_disp_console)
                        {
                            process_time[6] = DateTime.UtcNow; System.Console.Write("A+BinvDC({0:00.00} min), ", (process_time[6] - process_time[5]).TotalMinutes);
                        }
                        //HessMatrix nH = A - B_invD_C;
                        //nH = ((nH + nH.Tr())/2).ToHessMatrix();
                        H = A;
                    }
                    iterinfo.usedMemoryByte = GC.GetTotalMemory(false);
                    iterinfo.time1          = DateTime.UtcNow;
                    iterinfos.Add(iterinfo);

                    if (process_disp_console)
                    {
                        System.Console.WriteLine("summary(makezero {0,5}, nonzero {1,5}, numIgnMul {2,7}, numRemvAtoms {3,3}, {4,5:0.00} sec, {5} mb, {6}x{6}, nzeroBlk/Atom {7:0.00})"
                                                 , iterinfo.numSetZeroBlock
                                                 , iterinfo.numNonZeroBlock
                                                 , iterinfo.numAddIgnrBlock
                                                 , iterinfo.numAtomsRemoved
                                                 , iterinfo.compSec
                                                 , iterinfo.usedMemoryByte / (1024 * 1024)
                                                 , (idxkeep.Length * 3)
                                                 , ((double)iterinfo.numNonZeroBlock / idxremv.Length)
                                                 );
                    }

                    GC.Collect(0);
                }

                int numca = H.ColBlockSize - lstNewIdxRemv.HListCount().Sum();

                //System.Console.WriteLine("finish coarse-graining");
                {
                    int[] idxkeep = HEnum.HEnumCount(numca).ToArray();
                    H = H.SubMatrixByAtoms(false, idxkeep, idxkeep, false);
                }
                {
                    H.MakeNearZeroBlockAsZero(thres_zeroblk);
                }
                GC.Collect(0);
                //System.Console.WriteLine("finish resizing");

                return(new CGetHessCoarseResiIterImpl
                {
                    iterinfos = iterinfos,
                    H = H,
                });
            }
示例#5
0
            public static HessInfoCoarseResiIter GetHessCoarseResiIter
                (Hess.HessInfo hessinfo
                , Vector[] coords
                , FuncGetIdxKeepListRemv GetIdxKeepListRemv
                , ILinAlg ila
                , double thres_zeroblk = 0.001
                , IterOption iteropt   = IterOption.Matlab_experimental
                , string[] options     = null
                )
            {
                bool rediag = true;

                HessMatrix H = null;

                List <int>[] lstNewIdxRemv = null;
                int          numca         = 0;

                double[] reMass   = null;
                object[] reAtoms  = null;
                Vector[] reCoords = null;
                Tuple <int[], int[][]> idxKeepRemv = null;

                //System.Console.WriteLine("begin re-indexing hess");
                {
                    object[] atoms = hessinfo.atoms;
                    idxKeepRemv = GetIdxKeepListRemv(atoms, coords);
                    int[]   idxKeep  = idxKeepRemv.Item1;
                    int[][] idxsRemv = idxKeepRemv.Item2;
                    {
                        List <int> check = new List <int>();
                        check.AddRange(idxKeep);
                        foreach (int[] idxRemv in idxsRemv)
                        {
                            check.AddRange(idxRemv);
                        }
                        check = check.HToHashSet().ToList();
                        if (check.Count != coords.Length)
                        {
                            throw new Exception("the re-index contains the duplicated atoms or the missing atoms");
                        }
                    }
                    List <int> idxs = new List <int>();
                    idxs.AddRange(idxKeep);
                    foreach (int[] idxRemv in idxsRemv)
                    {
                        idxs.AddRange(idxRemv);
                    }
                    HDebug.Assert(idxs.Count == idxs.HToHashSet().Count);

                    H        = hessinfo.hess.ReshapeByAtom(idxs);
                    numca    = idxKeep.Length;
                    reMass   = hessinfo.mass.ToArray().HSelectByIndex(idxs);
                    reAtoms  = hessinfo.atoms.ToArray().HSelectByIndex(idxs);
                    reCoords = coords.HSelectByIndex(idxs);

                    int nidx = idxKeep.Length;
                    lstNewIdxRemv = new List <int> [idxsRemv.Length];
                    for (int i = 0; i < idxsRemv.Length; i++)
                    {
                        lstNewIdxRemv[i] = new List <int>();
                        foreach (var idx in idxsRemv[i])
                        {
                            lstNewIdxRemv[i].Add(nidx);
                            nidx++;
                        }
                    }
                    HDebug.Assert(nidx == lstNewIdxRemv.Last().Last() + 1);
                    HDebug.Assert(nidx == idxs.Count);
                }
                GC.Collect(0);
                HDebug.Assert(numca == H.ColBlockSize - lstNewIdxRemv.HListCount().Sum());

                //if(bool.Parse("false"))
                {
                    if (bool.Parse("false"))
                    #region
                    {
                        int[]      idxKeep  = idxKeepRemv.Item1;
                        int[][]    idxsRemv = idxKeepRemv.Item2;
                        Pdb.Atom[] pdbatoms = hessinfo.atomsAsUniverseAtom.ListPdbAtoms();
                        Pdb.ToFile(@"C:\temp\coarse-keeps.pdb", pdbatoms.HSelectByIndex(idxKeep), false);
                        if (HFile.Exists(@"C:\temp\coarse-graining.pdb"))
                        {
                            HFile.Delete(@"C:\temp\coarse-graining.pdb");
                        }
                        foreach (int[] idxremv in idxsRemv.Reverse())
                        {
                            List <Pdb.Element> delatoms = new List <Pdb.Element>();
                            foreach (int idx in idxremv)
                            {
                                if (pdbatoms[idx] == null)
                                {
                                    continue;
                                }
                                string   line    = pdbatoms[idx].GetUpdatedLine(coords[idx]);
                                Pdb.Atom delatom = Pdb.Atom.FromString(line);
                                delatoms.Add(delatom);
                            }
                            Pdb.ToFile(@"C:\temp\coarse-graining.pdb", delatoms.ToArray(), true);
                        }
                    }
                    #endregion

                    if (bool.Parse("false"))
                    #region
                    {
                        // export matrix to matlab, so the matrix can be checked in there.
                        int[] idxca  = HEnum.HEnumCount(numca).ToArray();
                        int[] idxoth = HEnum.HEnumFromTo(numca, coords.Length - 1).ToArray();
                        Matlab.Register(@"C:\temp\");
                        Matlab.PutSparseMatrix("H", H.GetMatrixSparse(), 3, 3);
                        Matlab.Execute("figure; spy(H)");
                        Matlab.Clear();
                    }
                    #endregion

                    if (bool.Parse("false"))
                    #region
                    {
                        HDirectory.CreateDirectory(@"K:\temp\$coarse-graining\");
                        {   // export original hessian matrix
                            List <int> cs = new List <int>();
                            List <int> rs = new List <int>();
                            foreach (ValueTuple <int, int, MatrixByArr> bc_br_bval in hessinfo.hess.EnumBlocks())
                            {
                                cs.Add(bc_br_bval.Item1);
                                rs.Add(bc_br_bval.Item2);
                            }
                            Matlab.Clear();
                            Matlab.PutVector("cs", cs.ToArray());
                            Matlab.PutVector("rs", rs.ToArray());
                            Matlab.Execute("hess = sparse(cs+1, rs+1, ones(size(cs)));");
                            Matlab.Execute("hess = float(hess);");
                            Matlab.Execute("figure; spy(hess)");
                            Matlab.Execute("cs = int32(cs+1);");
                            Matlab.Execute("rs = int32(rs+1);");
                            Matlab.Execute(@"save('K:\temp\$coarse-graining\hess-original.mat', 'cs', 'rs', '-v6');");
                            Matlab.Clear();
                        }
                        {   // export reshuffled hessian matrix
                            List <int> cs = new List <int>();
                            List <int> rs = new List <int>();
                            foreach (ValueTuple <int, int, MatrixByArr> bc_br_bval in H.EnumBlocks())
                            {
                                cs.Add(bc_br_bval.Item1);
                                rs.Add(bc_br_bval.Item2);
                            }
                            Matlab.Clear();
                            Matlab.PutVector("cs", cs.ToArray());
                            Matlab.PutVector("rs", rs.ToArray());
                            Matlab.Execute("H = sparse(cs+1, rs+1, ones(size(cs)));");
                            Matlab.Execute("H = float(H);");
                            Matlab.Execute("figure; spy(H)");
                            Matlab.Execute("cs = int32(cs+1);");
                            Matlab.Execute("rs = int32(rs+1);");
                            Matlab.Execute(@"save('K:\temp\$coarse-graining\hess-reshuffled.mat', 'cs', 'rs', '-v6');");
                            Matlab.Clear();
                        }
                    }
                    #endregion

                    if (bool.Parse("false"))
                    #region
                    {
                        int[] idxca  = HEnum.HEnumCount(numca).ToArray();
                        int[] idxoth = HEnum.HEnumFromTo(numca, coords.Length - 1).ToArray();

                        HessMatrix A = H.SubMatrixByAtoms(false, idxca, idxca);
                        HessMatrix B = H.SubMatrixByAtoms(false, idxca, idxoth);
                        HessMatrix C = H.SubMatrixByAtoms(false, idxoth, idxca);
                        HessMatrix D = H.SubMatrixByAtoms(false, idxoth, idxoth);
                        Matlab.Clear();
                        Matlab.PutSparseMatrix("A", A.GetMatrixSparse(), 3, 3);
                        Matlab.PutSparseMatrix("B", B.GetMatrixSparse(), 3, 3);
                        Matlab.PutSparseMatrix("C", C.GetMatrixSparse(), 3, 3);
                        Matlab.PutSparseMatrix("D", D.GetMatrixSparse(), 3, 3);
                        Matlab.Clear();
                    }
                    #endregion
                }

                List <HessCoarseResiIterInfo> iterinfos = null;
                {
                    object[] atoms = reAtoms; // reAtoms.HToType(null as Universe.Atom[]);
                    CGetHessCoarseResiIterImpl info = null;
                    switch (iteropt)
                    {
                    case IterOption.ILinAlg_20150329: info = GetHessCoarseResiIterImpl_ILinAlg_20150329(H, lstNewIdxRemv, thres_zeroblk, ila, false);                    break;

                    case IterOption.ILinAlg: info = GetHessCoarseResiIterImpl_ILinAlg(H, lstNewIdxRemv, thres_zeroblk, ila, false);                             break;

                    case IterOption.Matlab: info = GetHessCoarseResiIterImpl_Matlab(atoms, H, lstNewIdxRemv, thres_zeroblk, ila, false, options);              break;

                    case IterOption.Matlab_experimental: info = GetHessCoarseResiIterImpl_Matlab_experimental(atoms, H, lstNewIdxRemv, thres_zeroblk, ila, false, options); break;

                    case IterOption.Matlab_IterLowerTri: info = GetHessCoarseResiIterImpl_Matlab_IterLowerTri(atoms, H, lstNewIdxRemv, thres_zeroblk, ila, false, options); break;

                    case IterOption.LinAlg_IterLowerTri: info = GetHessCoarseResiIterImpl_LinAlg_IterLowerTri.Do(atoms, H, lstNewIdxRemv, thres_zeroblk, ila, false, options); break;
                    }
                    ;
                    H         = info.H;
                    iterinfos = info.iterinfos;
                }
                //{
                //    var info = GetHessCoarseResiIterImpl_Matlab(H, lstNewIdxRemv, thres_zeroblk);
                //    H = info.H;
                //}
                GC.Collect(0);

                if (HDebug.IsDebuggerAttached)
                {
                    int   nidx  = 0;
                    int[] ikeep = idxKeepRemv.Item1;
                    foreach (int idx in ikeep)
                    {
                        bool equal = object.ReferenceEquals(hessinfo.atoms[idx], reAtoms[nidx]);
                        if (equal == false)
                        {
                            HDebug.Assert(false);
                        }
                        HDebug.Assert(equal);
                        nidx++;
                    }
                }

                if (rediag)
                {
                    H = H.CorrectHessDiag();
                }
                //System.Console.WriteLine("finish fixing diag");

                return(new HessInfoCoarseResiIter
                {
                    hess = H,
                    mass = reMass.HSelectCount(numca),
                    atoms = reAtoms.HSelectCount(numca),
                    coords = reCoords.HSelectCount(numca),
                    numZeroEigval = 6,
                    iterinfos = iterinfos,
                });
            }
示例#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 CGetHessCoarseResiIterImpl GetHessCoarseResiIterImpl_Matlab_experimental
                (object[] atoms
                , HessMatrix H
                , List <int>[] lstNewIdxRemv
                , double thres_zeroblk
                , ILinAlg ila
                , bool cloneH
                , string[] options
                )
            {
                ila = null;
                if (cloneH)
                {
                    H = H.CloneHess();
                }

                bool process_disp_console = true;

                if (options != null && options.Contains("print process"))
                {
                    process_disp_console = true;
                }

                bool parallel = true;

                GC.Collect(0);

                DateTime[] process_time = new DateTime[6];

                //System.Console.WriteLine("begin coarse-graining");
                List <HessCoarseResiIterInfo> iterinfos = new List <HessCoarseResiIterInfo>();

                for (int iter = lstNewIdxRemv.Length - 1; iter >= 0; iter--)
                {
                    if (process_disp_console)
                    {
                        process_time[0] = DateTime.UtcNow;
                        System.Console.Write(" - {0:000} : ", iter);
                    }

                    //int[] ikeep = lstNewIdxRemv[iter].Item1;
                    int[] iremv = lstNewIdxRemv[iter].ToArray();
                    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);

                    HessCoarseResiIterInfo iterinfo = new HessCoarseResiIterInfo();
                    iterinfo.sizeHessBlkMat  = idxremv.Max() + 1; // H.ColBlockSize;
                    iterinfo.numAtomsRemoved = idxremv.Length;
                    iterinfo.time0           = DateTime.UtcNow;
                    double C_density0 = double.NaN;
                    double C_density1 = double.NaN;
                    {
                        //HessMatrix    A = H.SubMatrixByAtoms(false, idxkeep, idxkeep);
                        HessMatrix A = H;
                        //HessMatrix    B = H.SubMatrixByAtoms(false, idxkeep, idxremv);

                        HessMatrix C, D;
                        /// HessMatrix    C = H.SubMatrixByAtoms(false, idxremv, idxkeep, parallel:parallel);
                        /// HessMatrix    D = H.SubMatrixByAtoms(false, idxremv, idxremv, parallel:parallel);
                        {
                            C = H.Zeros(idxremv.Length * 3, idxkeep.Length * 3);
                            D = H.Zeros(idxremv.Length * 3, idxremv.Length * 3);
                            int iremv_min = iremv.Min();
                            int iremv_max = iremv.Max();

                            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 (bc > iremv_max)
                                {
                                    continue;
                                }
                                if (br > iremv_max)
                                {
                                    continue;
                                }
                                if (br < iremv_min)
                                {
                                    int nc = bc - iremv_min;
                                    int nr = br;
                                    C.SetBlock(nc, nr, bval.CloneT());
                                }
                                else
                                {
                                    int nc = bc - iremv_min;
                                    int nr = br - iremv_min;
                                    D.SetBlock(nc, nr, bval.CloneT());
                                }
                            }
                        }
                        if (process_disp_console)
                        {
                            process_time[1] = process_time[2] = DateTime.UtcNow;
                            System.Console.Write("CD({0:00.00} min), ", (process_time[2] - process_time[0]).TotalMinutes);
                        }

                        // make B,C sparse
                        //int B_cntzero = B.MakeNearZeroBlockAsZero(thres_zeroblk);
                        C_density0 = C.RatioUsedBlocks;
                        /// iterinfo.numSetZeroBlock = C.MakeNearZeroBlockAsZero(thres_zeroblk);
                        {
                            double thres_absmax = thres_zeroblk;

                            List <Tuple <int, int> > lstIdxToMakeZero = new List <Tuple <int, int> >();
                            foreach (var bc_br_bval in C.EnumBlocks())
                            {
                                int    bc          = bc_br_bval.Item1;
                                int    br          = bc_br_bval.Item2;
                                var    bval        = bc_br_bval.Item3;
                                double absmax_bval = bval.HAbsMax();
                                if (absmax_bval < thres_absmax)
                                {
                                    lstIdxToMakeZero.Add(new Tuple <int, int>(bc, br));
                                }
                            }
                            foreach (var bc_br in lstIdxToMakeZero)
                            {
                                int cc   = bc_br.Item1;
                                int cr   = bc_br.Item2;
                                var Cval = C.GetBlock(cc, cr);
                                C.SetBlock(cc, cr, null);
                                var Dval = D.GetBlock(cc, cc);              // nCval = Cval    -Cval
                                D.SetBlock(cc, cc, Dval + Cval);            // nDval = Dval - (-Cval) = Dval + Cval
                                int bc   = cr;
                                int br   = cc;
                                var Bval = Cval.Tr();
                                var Aval = A.GetBlock(bc, bc);              // nBval = Bval    -Bval
                                A.SetBlock(bc, bc, Aval + Bval);            // nAval = Aval - (-Bval) = Aval + Bval
                            }
                            iterinfo.numSetZeroBlock = lstIdxToMakeZero.Count;
                        }
                        //int B_nzeros = B.NumUsedBlocks; double B_nzeros_ = Math.Sqrt(B_nzeros);
                        iterinfo.numNonZeroBlock = C.NumUsedBlocks;
                        C_density1 = C.RatioUsedBlocks;


                        HessMatrix B_invD_C = Get_BInvDC(A, C, D, process_disp_console
                                                         , options
                                                         , parallel: parallel
                                                         );
                        if (process_disp_console)
                        {
                            process_time[4] = DateTime.UtcNow;
                            System.Console.Write("B.invD.C({0:00.00} min), ", (process_time[4] - process_time[3]).TotalMinutes);
                        }

                        /// iterinfo.numAddIgnrBlock = A.UpdateAdd(B_invD_C, -1, null, thres_zeroblk/lstNewIdxRemv.Length, parallel:parallel);
                        {
                            HessMatrix _this = A;
                            HessMatrix other = B_invD_C;
                            double     thres_NearZeroBlock = thres_zeroblk / lstNewIdxRemv.Length;

                            int count         = 0;
                            int count_ignored = 0;
                            foreach (var bc_br_bval in other.EnumBlocks())
                            {
                                count++;
                                int         bc         = bc_br_bval.Item1;
                                int         br         = bc_br_bval.Item2;
                                MatrixByArr other_bmat = bc_br_bval.Item3;
                                if (other_bmat.HAbsMax() <= thres_NearZeroBlock)
                                {
                                    // other_bmat = other_bmat    -other_bmat;
                                    // other_diag = other_diag - (-other_bmat) = other_diag + other_bmat;
                                    //  this_diag =  this_diat - B_invD_C
                                    //            =  this_diat - other_diag
                                    //            =  this_diat - (other_diag + other_bmat)
                                    //            =  this_diat - other_diag  - other_bmat
                                    //            = (this_diat - other_bmat) - other_diag
                                    //            = (this_diat - other_bmat) - (processed later)
                                    //            = (this_diat - other_bmat)
                                    MatrixByArr this_diag = _this.GetBlock(bc, bc);
                                    MatrixByArr new_diag  = this_diag - other_bmat;
                                    _this.SetBlock(bc, bc, new_diag);
                                    other_bmat = null;
                                    count_ignored++;
                                }
                                if (other_bmat != null)
                                {
                                    MatrixByArr this_bmat = _this.GetBlock(bc, br);
                                    MatrixByArr new_bmat  = this_bmat - other_bmat;
                                    _this.SetBlock(bc, br, new_bmat);
                                }
                            }
                            iterinfo.numAddIgnrBlock = count_ignored;
                        }
                        //HessMatrix nH = A - B_invD_C;
                        //nH = ((nH + nH.Tr())/2).ToHessMatrix();
                        H = A;
                    }
                    iterinfo.usedMemoryByte = GC.GetTotalMemory(false);
                    iterinfo.time1          = DateTime.UtcNow;
                    iterinfos.Add(iterinfo);

                    if (process_disp_console)
                    {
                        System.Console.WriteLine("summary(makezero {0,5}, nonzero {1,5}, numIgnMul {2,7}, numRemvAtoms {3,3}, {4,5:0.00} sec, {5} mb, {6}x{6}, nzeroBlk/Atom {7:0.00})"
                                                 , iterinfo.numSetZeroBlock
                                                 , iterinfo.numNonZeroBlock
                                                 , iterinfo.numAddIgnrBlock
                                                 , iterinfo.numAtomsRemoved
                                                 , iterinfo.compSec
                                                 , iterinfo.usedMemoryByte / (1024 * 1024)
                                                 , (idxkeep.Length * 3)
                                                 , ((double)iterinfo.numNonZeroBlock / idxremv.Length)
                                                 );
                    }

                    GC.Collect(0);
                }

                int numca = H.ColBlockSize - lstNewIdxRemv.HListCount().Sum();

                //System.Console.WriteLine("finish coarse-graining");
                {
                    int[] idxkeep = HEnum.HEnumCount(numca).ToArray();
                    H = H.SubMatrixByAtoms(false, idxkeep, idxkeep, false);
                }
                {
                    H.MakeNearZeroBlockAsZero(thres_zeroblk);
                }
                GC.Collect(0);
                //System.Console.WriteLine("finish resizing");

                return(new CGetHessCoarseResiIterImpl
                {
                    iterinfos = iterinfos,
                    H = H,
                });
            }
            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),
                });
            }