Пример #1
0
            private static void FourthTerm(IList <Vector> caArray, double Epsilon, HessMatrix hessian, int i, int j)
            {
                int[]    idx      = new int[] { i, j };
                Vector[] lcaArray = new Vector[] { caArray[idx[0]], caArray[idx[1]] };
                Matrix   lhess    = FourthTerm(lcaArray, Epsilon);

                for (int c = 0; c < 2; c++)
                {
                    for (int dc = 0; dc < 3; dc++)
                    {
                        for (int r = 0; r < 2; r++)
                        {
                            for (int dr = 0; dr < 3; dr++)
                            {
                                hessian[idx[c] * 3 + dc, idx[r] * 3 + dr] += lhess[c * 3 + dc, r *3 + dr];
                            }
                        }
                    }
                }

                if (HDebug.IsDebuggerAttachedWithProb(0.1))
                {
                    if (caArray.Count == 2)
                    {
                        // avoid stack overflow
                        return;
                    }
                    HessMatrix lhess0 = new double[6, 6];
                    FourthTerm(lcaArray, Epsilon, lhess0, 0, 1);
                    FourthTerm(lcaArray, Epsilon, lhess0, 1, 0);
                    double r2     = (lcaArray[0] - lcaArray[1]).Dist2;
                    Matrix dhess0 = (120 * Epsilon / r2) * Hess.GetHessAnm(lcaArray, double.PositiveInfinity);
                    HDebug.AssertToleranceMatrix(0.00000001, lhess0 - dhess0);
                }
            }
Пример #2
0
            public static void FirstTerm(IList <Vector> caArray, double K_r, HessMatrix hessian, int i, int j)
            {
                int[]    idx          = new int[] { i, j };
                Vector[] lcaArray     = new Vector[] { caArray[idx[0]], caArray[idx[1]] };
                Matrix   lhess        = FirstTerm(lcaArray, K_r);
                double   maxabs_lhess = lhess.ToArray().HAbs().HMax();

                HDebug.Assert(maxabs_lhess < 10000);

                for (int c = 0; c < 2; c++)
                {
                    for (int dc = 0; dc < 3; dc++)
                    {
                        for (int r = 0; r < 2; r++)
                        {
                            for (int dr = 0; dr < 3; dr++)
                            {
                                hessian[idx[c] * 3 + dc, idx[r] * 3 + dr] += lhess[c * 3 + dc, r *3 + dr];
                            }
                        }
                    }
                }

                if (HDebug.IsDebuggerAttached)
                {
                    Matrix anm = (2 * K_r) * Hess.GetHessAnm(lcaArray, double.PositiveInfinity);
                    HDebug.AssertToleranceMatrix(0.00000001, lhess - anm);
                }
            }
Пример #3
0
        public HessMatrix SubMatrixByAtomsImpl0(IList <int> idxColAtoms, IList <int> idxRowAtoms)
        {
            if (SubMatrixByAtomsImpl0_selftest2)
            {
                SubMatrixByAtomsImpl0_selftest2 = false;
                Matrix thess1 = new double[, ] {
                    { 0, 1, 2, 3, 4, 5 }
                    , { 1, 2, 3, 4, 5, 6 }
                    , { 2, 3, 4, 5, 6, 7 }
                    , { 3, 4, 5, 6, 7, 8 }
                    , { 4, 5, 6, 7, 8, 9 }
                    , { 5, 6, 7, 8, 9, 0 }
                };
                HessMatrix thess2 = HessMatrixDense.FromMatrix(thess1);
                HessMatrix thess3 = thess2.SubMatrixByAtomsImpl0(new int[] { 0 }, new int[] { 1 });
                Matrix     thess4 = new double[, ] {
                    { 3, 4, 5 }
                    , { 4, 5, 6 }
                    , { 5, 6, 7 }
                };
                HDebug.AssertToleranceMatrix(0, thess3 - thess4);
            }
            HessMatrix nhess = Zeros(idxColAtoms.Count * 3, idxRowAtoms.Count * 3);

            for (int nbc = 0; nbc < idxColAtoms.Count; nbc++)
            {
                for (int nbr = 0; nbr < idxRowAtoms.Count; nbr++)
                {
                    int bc = idxColAtoms[nbc]; if (bc < 0)
                    {
                        continue;
                    }
                    int br = idxRowAtoms[nbr]; if (br < 0)
                    {
                        continue;
                    }
                    if (HasBlock(bc, br) == false)
                    {
                        continue;
                    }
                    MatrixByArr block = GetBlock(bc, br).CloneT(); // hessian matrix for interaction between atom i and j
                    HDebug.Assert(block.IsZero() == false);
                    nhess.SetBlock(nbc, nbr, block);
                }
            }

            return(nhess);
        }
Пример #4
0
        public Matrix GetMassMatrix(int dim = 1)
        {
            Matrix masses = atoms.ToArray().GetMassMatrix(dim);

            if (HDebug.IsDebuggerAttached)
            {
                Matrix tmasses = new double[size * dim, size *dim];
                for (int i = 0; i < size; i++)
                {
                    for (int j = 0; j < dim; j++)
                    {
                        tmasses[i * dim + j, i *dim + j] = atoms[i].Mass;
                    }
                }
                HDebug.AssertToleranceMatrix(0, masses - tmasses);
            }
            return(masses);
        }
Пример #5
0
        public static Matrix GetInvSprTensorSymm(Matrix H, Matrix S, ILinAlg ila)
        {
            // check H be symmetric
            HDebug.AssertToleranceMatrix(0.00000001, H - H.Tr());

            Matrix invK = GetInvSprTensor(H, S, ila);

            if (HDebug.IsDebuggerAttached && ila != null)
            {
                HDebug.AssertToleranceMatrix(0.00000001, invK - invK.Tr()); // check symmetric
                var invKK = ila.ToILMat(invK);
                var VVDD  = ila.EigSymm(invKK);
                foreach (double d in VVDD.Item2)
                {
                    HDebug.Assert(d > -0.00000001);
                }
            }
            return(invK);
        }
Пример #6
0
            public static Matrix ThirdTerm(IList <Vector> caArray_, double K_phi
                                           , bool useArnaud96     = false
                                           , bool checkComputable = true)
            {
                //HDebug.Assert(useArnaud96 == true); // convert to use Arnaud96
                if (useArnaud96)
                {
                    HessMatrix hess3 = Paper.Arnaud96.HessSpring(caArray_, 2 * K_phi).ToArray();
                    //if(HDebug.IsDebuggerAttached)
                    if (ThirdTerm_selftest)
                    {
                        ThirdTerm_selftest = false;
                        Matrix hess3_ = ThirdTerm(caArray_, K_phi, useArnaud96: false, checkComputable: false);
                        Matrix dhess3 = hess3 - hess3_;
                        if (hess3_.IsComputable())
                        {
                            Vector v0     = caArray_[0];
                            Vector v1     = caArray_[1];
                            Vector v2     = caArray_[2];
                            Vector v3     = caArray_[3];
                            Vector A012   = LinAlg.CrossProd(v0 - v1, v1 - v2).UnitVector();
                            Vector B123   = LinAlg.CrossProd(v1 - v2, v2 - v3).UnitVector();
                            double AB     = LinAlg.VtV(A012, B123);
                            double acosAB = Math.Acos(AB);

                            double hess3max = hess3_.ToArray().HAbs().HMax();
                            if (Math.Abs(AB) < 0.999999)
                            {
                                HDebug.AssertToleranceMatrix(hess3max * 0.0001, dhess3);
                            }
                        }
                    }
                    return(hess3);
                }

                VECTORS caArray = new VECTORS(caArray_);
                MATRIX  hessian = new MATRIX(new double[12, 12]);

                {
                    int i = 1;
                    int j = 2;
                    int k = 3;
                    int l = 4;

                    double Xi   = caArray[i, 1];
                    double Yi   = caArray[i, 2];
                    double Zi   = caArray[i, 3];
                    double Xj   = caArray[j, 1];
                    double Yj   = caArray[j, 2];
                    double Zj   = caArray[j, 3];
                    double Xk   = caArray[k, 1];
                    double Yk   = caArray[k, 2];
                    double Zk   = caArray[k, 3];
                    double Xl   = caArray[l, 1];
                    double Yl   = caArray[l, 2];
                    double Zl   = caArray[l, 3];
                    Vector a    = caArray.GetRow(j) - caArray.GetRow(i);
                    Vector b    = caArray.GetRow(k) - caArray.GetRow(j);
                    Vector c    = caArray.GetRow(l) - caArray.GetRow(k);
                    Vector v1   = cross(a, b);
                    Vector v2   = cross(b, c);
                    double lv1l = glength(v1);
                    double lv2l = glength(v2);
                    double G    = dot(v1, v2) / (lv1l * lv2l);

                    /* dv1/dXi */ Vector dv1dXi = new double[] { 0, Zk - Zj, Yj - Yk };
                    /* dv1/dYi */ Vector dv1dYi = new double[] { Zj - Zk, 0, Xk - Xj };
                    /* dv1/dZi */ Vector dv1dZi = new double[] { Yk - Yj, Xj - Xk, 0 };

                    /* dv1/dXj */ Vector dv1dXj = new double[] { 0, Zi - Zk, Yk - Yi };
                    /* dv1/dYj */ Vector dv1dYj = new double[] { Zk - Zi, 0, Xi - Xk };
                    /* dv1/dZj */ Vector dv1dZj = new double[] { Yi - Yk, Xk - Xi, 0 };

                    /* dv1/dXk */ Vector dv1dXk = new double[] { 0, Zj - Zi, Yi - Yj };
                    /* dv2/dYk */ Vector dv1dYk = new double[] { Zi - Zj, 0, Xj - Xi };
                    /* dv2/dZk */ Vector dv1dZk = new double[] { Yj - Yi, Xi - Xj, 0 };

                    /* dv1/dXl */ Vector dv1dXl = new double[] { 0, 0, 0 };
                    /* dv1/dYl */ Vector dv1dYl = new double[] { 0, 0, 0 };
                    /* dv1/dZl */ Vector dv1dZl = new double[] { 0, 0, 0 };

                    /* dv2/dXi */ Vector dv2dXi = new double[] { 0, 0, 0 };
                    /* dv2/dYi */ Vector dv2dYi = new double[] { 0, 0, 0 };
                    /* dv2/dZi */ Vector dv2dZi = new double[] { 0, 0, 0 };

                    /* dv2/dXj */ Vector dv2dXj = new double[] { 0, Zl - Zk, Yk - Yl };
                    /* dv2/dYj */ Vector dv2dYj = new double[] { Zk - Zl, 0, Xl - Xk };
                    /* dv2/dZj */ Vector dv2dZj = new double[] { Yl - Yk, Xk - Xl, 0 };

                    /* dv2/dXk */ Vector dv2dXk = new double[] { 0, Zj - Zl, Yl - Yj };
                    /* dv2/dYk */ Vector dv2dYk = new double[] { Zl - Zj, 0, Xj - Xl };
                    /* dv2/dZk */ Vector dv2dZk = new double[] { Yj - Yl, Xl - Xj, 0 };

                    /* dv2/dXl */ Vector dv2dXl = new double[] { 0, Zk - Zj, Yj - Yk };
                    /* dv2/dYl */ Vector dv2dYl = new double[] { Zj - Zk, 0, Xk - Xj };
                    /* dv2/dZl */ Vector dv2dZl = new double[] { Yk - Yj, Xj - Xk, 0 };

                    double K1 = (Yj - Yi) * (Zk - Zj) - (Yk - Yj) * (Zj - Zi); double K1_2 = K1 * K1;
                    double K2 = (Xk - Xj) * (Zj - Zi) - (Xj - Xi) * (Zk - Zj); double K2_2 = K2 * K2;
                    double K3 = (Xj - Xi) * (Yk - Yj) - (Xk - Xj) * (Yj - Yi); double K3_2 = K3 * K3;

                    /* dlv1l/dXi */ double dlv1ldXi = (2 * K2 * (Zk - Zj) + 2 * K3 * (Yj - Yk)) / (2 * sqrt(K1_2 + K2_2 + K3_2));
                    /* dlv1l/dYi */ double dlv1ldYi = (2 * K1 * (Zj - Zk) + 2 * K3 * (Xk - Xj)) / (2 * sqrt(K1_2 + K2_2 + K3_2));
                    /* dlv1l/dZi */ double dlv1ldZi = (2 * K1 * (Yk - Yj) + 2 * K2 * (Xj - Xk)) / (2 * sqrt(K1_2 + K2_2 + K3_2));

                    /* dlv1ldXj */ double dlv1ldXj = (2 * K2 * (Zi - Zk) + 2 * K3 * (Yk - Yi)) / (2 * sqrt(K1_2 + K2_2 + K3_2));
                    /* dlv1ldYj */ double dlv1ldYj = (2 * K1 * (Zk - Zi) + 2 * K3 * (Xi - Xk)) / (2 * sqrt(K1_2 + K2_2 + K3_2));
                    /* dlv1ldZj */ double dlv1ldZj = (2 * K1 * (Yi - Yk) + 2 * K2 * (Xk - Xi)) / (2 * sqrt(K1_2 + K2_2 + K3_2));

                    /* dlv1ldXk */ double dlv1ldXk = (2 * K2 * (Zj - Zi) + 2 * K3 * (Yi - Yj)) / (2 * sqrt(K1_2 + K2_2 + K3_2));
                    /* dlv1ldYk */ double dlv1ldYk = (2 * K1 * (Zi - Zj) + 2 * K3 * (Xj - Xi)) / (2 * sqrt(K1_2 + K2_2 + K3_2));
                    /* dlv1ldZk */ double dlv1ldZk = (2 * K1 * (Yj - Yi) + 2 * K2 * (Xi - Xj)) / (2 * sqrt(K1_2 + K2_2 + K3_2));

                    /* dlv1ldXl */ double dlv1ldXl = 0;
                    /* dlv1ldYl */ double dlv1ldYl = 0;
                    /* dlv1ldZl */ double dlv1ldZl = 0;

                    double L1 = (Yk - Yj) * (Zl - Zk) - (Yl - Yk) * (Zk - Zj); double L1_2 = L1 * L1;
                    double L2 = (Xl - Xk) * (Zk - Zj) - (Xk - Xj) * (Zl - Zk); double L2_2 = L2 * L2;
                    double L3 = (Xk - Xj) * (Yl - Yk) - (Xl - Xk) * (Yk - Yj); double L3_2 = L3 * L3;

                    /* dlv2l/dXi */ double dlv2ldXi = 0;
                    /* dlv2l/dYi */ double dlv2ldYi = 0;
                    /* dlv2l/dZi */ double dlv2ldZi = 0;

                    /* dlv2l/dXj */ double dlv2ldXj = (2 * L2 * (Zl - Zk) + 2 * L3 * (Yk - Yl)) / (2 * sqrt(L1_2 + L2_2 + L3_2));
                    /* dlv2l/dYj */ double dlv2ldYj = (2 * L1 * (Zk - Zl) + 2 * L3 * (Xl - Xk)) / (2 * sqrt(L1_2 + L2_2 + L3_2));
                    /* dlv2l/dZj */ double dlv2ldZj = (2 * L1 * (Yl - Yk) + 2 * L2 * (Xk - Xl)) / (2 * sqrt(L1_2 + L2_2 + L3_2));

                    /* dlv2l/dXk */ double dlv2ldXk = (2 * L2 * (Zj - Zl) + 2 * L3 * (Yl - Yj)) / (2 * sqrt(L1_2 + L2_2 + L3_2));
                    /* dlv2l/dYk */ double dlv2ldYk = (2 * L1 * (Zl - Zj) + 2 * L3 * (Xj - Xl)) / (2 * sqrt(L1_2 + L2_2 + L3_2));
                    /* dlv2l/dZk */ double dlv2ldZk = (2 * L1 * (Yj - Yl) + 2 * L2 * (Xl - Xj)) / (2 * sqrt(L1_2 + L2_2 + L3_2));

                    /* dlv2l/dXl */ double dlv2ldXl = (2 * L2 * (Zk - Zj) + 2 * L3 * (Yj - Yk)) / (2 * sqrt(L1_2 + L2_2 + L3_2));
                    /* dlv2l/dYl */ double dlv2ldYl = (2 * L1 * (Zj - Zk) + 2 * L3 * (Xk - Xj)) / (2 * sqrt(L1_2 + L2_2 + L3_2));
                    /* dlv2l/dZl */ double dlv2ldZl = (2 * L1 * (Yk - Yj) + 2 * L2 * (Xj - Xk)) / (2 * sqrt(L1_2 + L2_2 + L3_2));

                    /* dG/dXi */ double dGdXi = ((dot(dv1dXi, v2) + dot(dv2dXi, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldXi * lv2l + dlv2ldXi * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dYi */ double dGdYi = ((dot(dv1dYi, v2) + dot(dv2dYi, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldYi * lv2l + dlv2ldYi * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dZi */ double dGdZi = ((dot(dv1dZi, v2) + dot(dv2dZi, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldZi * lv2l + dlv2ldZi * lv1l)) / pow(lv1l * lv2l);

                    /* dG/dXj */ double dGdXj = ((dot(dv1dXj, v2) + dot(dv2dXj, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldXj * lv2l + dlv2ldXj * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dYj */ double dGdYj = ((dot(dv1dYj, v2) + dot(dv2dYj, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldYj * lv2l + dlv2ldYj * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dZj */ double dGdZj = ((dot(dv1dZj, v2) + dot(dv2dZj, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldZj * lv2l + dlv2ldZj * lv1l)) / pow(lv1l * lv2l);

                    /* dG/dXk */ double dGdXk = ((dot(dv1dXk, v2) + dot(dv2dXk, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldXk * lv2l + dlv2ldXk * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dYk */ double dGdYk = ((dot(dv1dYk, v2) + dot(dv2dYk, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldYk * lv2l + dlv2ldYk * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dZk */ double dGdZk = ((dot(dv1dZk, v2) + dot(dv2dZk, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldZk * lv2l + dlv2ldZk * lv1l)) / pow(lv1l * lv2l);

                    /* dG/dXl */ double dGdXl = ((dot(dv1dXl, v2) + dot(dv2dXl, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldXl * lv2l + dlv2ldXl * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dYl */ double dGdYl = ((dot(dv1dYl, v2) + dot(dv2dYl, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldYl * lv2l + dlv2ldYl * lv1l)) / pow(lv1l * lv2l);
                    /* dG/dZl */ double dGdZl = ((dot(dv1dZl, v2) + dot(dv2dZl, v1)) * lv1l * lv2l - dot(v1, v2) * (dlv1ldZl * lv2l + dlv2ldZl * lv1l)) / pow(lv1l * lv2l);

                    //Hij
                    //d^2V/dXidXj  d^2V/dXidYj  d^2V/dXidZj
                    //d^2V/dYidXj  d^2V/dYidYj  d^2V/dYidZj
                    //d^2V/dZidXj  d^2V/dZidYj  d^2V/dZidZj

                    // diagonals of off-diagonal super elements

                    hessian[3 * i - 2, 3 * j - 2] += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdXj;
                    hessian[3 * i - 1, 3 * j - 1] += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdYj;
                    hessian[3 * i, 3 * j]         += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdZj;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * i - 2, 3 * j - 1] += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdYj;
                    hessian[3 * i - 2, 3 * j]     += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdZj;
                    hessian[3 * i - 1, 3 * j - 2] += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdXj;
                    hessian[3 * i - 1, 3 * j]     += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdZj;
                    hessian[3 * i, 3 * j - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdXj;
                    hessian[3 * i, 3 * j - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdYj;

                    //Hji
                    // diagonals of off-diagonal super elements
                    hessian[3 * j - 2, 3 * i - 2] += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdXi;
                    hessian[3 * j - 1, 3 * i - 1] += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdYi;
                    hessian[3 * j, 3 * i]         += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdZi;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * j - 2, 3 * i - 1] += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdYi;
                    hessian[3 * j - 2, 3 * i]     += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdZi;
                    hessian[3 * j - 1, 3 * i - 2] += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdXi;
                    hessian[3 * j - 1, 3 * i]     += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdZi;
                    hessian[3 * j, 3 * i - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdXi;
                    hessian[3 * j, 3 * i - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdYi;

                    //Hil

                    // diagonals of off-diagonal super elements

                    hessian[3 * i - 2, 3 * l - 2] += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdXl;
                    hessian[3 * i - 1, 3 * l - 1] += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdYl;
                    hessian[3 * i, 3 * l]         += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdZl;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * i - 2, 3 * l - 1] += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdYl;
                    hessian[3 * i - 2, 3 * l]     += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdZl;
                    hessian[3 * i - 1, 3 * l - 2] += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdXl;
                    hessian[3 * i - 1, 3 * l]     += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdZl;
                    hessian[3 * i, 3 * l - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdXl;
                    hessian[3 * i, 3 * l - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdYl;

                    //Hli
                    // diagonals of off-diagonal super elements
                    hessian[3 * l - 2, 3 * i - 2] += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdXi;
                    hessian[3 * l - 1, 3 * i - 1] += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdYi;
                    hessian[3 * l, 3 * i]         += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdZi;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * l - 2, 3 * i - 1] += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdYi;
                    hessian[3 * l - 2, 3 * i]     += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdZi;
                    hessian[3 * l - 1, 3 * i - 2] += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdXi;
                    hessian[3 * l - 1, 3 * i]     += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdZi;
                    hessian[3 * l, 3 * i - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdXi;
                    hessian[3 * l, 3 * i - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdYi;

                    //Hkj
                    // diagonals of off-diagonal super elements

                    hessian[3 * k - 2, 3 * j - 2] += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdXj;
                    hessian[3 * k - 1, 3 * j - 1] += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdYj;
                    hessian[3 * k, 3 * j]         += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdZj;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * k - 2, 3 * j - 1] += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdYj;
                    hessian[3 * k - 2, 3 * j]     += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdZj;
                    hessian[3 * k - 1, 3 * j - 2] += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdXj;
                    hessian[3 * k - 1, 3 * j]     += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdZj;
                    hessian[3 * k, 3 * j - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdXj;
                    hessian[3 * k, 3 * j - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdYj;

                    //Hjk
                    // diagonals of off-diagonal super elements
                    hessian[3 * j - 2, 3 * k - 2] += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdXk;
                    hessian[3 * j - 1, 3 * k - 1] += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdYk;
                    hessian[3 * j, 3 * k]         += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdZk;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * j - 2, 3 * k - 1] += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdYk;
                    hessian[3 * j - 2, 3 * k]     += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdZk;
                    hessian[3 * j - 1, 3 * k - 2] += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdXk;
                    hessian[3 * j - 1, 3 * k]     += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdZk;
                    hessian[3 * j, 3 * k - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdXk;
                    hessian[3 * j, 3 * k - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdYk;

                    //Hik
                    // diagonals of off-diagonal super elements

                    hessian[3 * i - 2, 3 * k - 2] += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdXk;
                    hessian[3 * i - 1, 3 * k - 1] += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdYk;
                    hessian[3 * i, 3 * k]         += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdZk;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * i - 2, 3 * k - 1] += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdYk;
                    hessian[3 * i - 2, 3 * k]     += +(2 * K_phi) / (1 - G * G) * dGdXi * dGdZk;
                    hessian[3 * i - 1, 3 * k - 2] += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdXk;
                    hessian[3 * i - 1, 3 * k]     += +(2 * K_phi) / (1 - G * G) * dGdYi * dGdZk;
                    hessian[3 * i, 3 * k - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdXk;
                    hessian[3 * i, 3 * k - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZi * dGdYk;

                    //Hki
                    // diagonals of off-diagonal super elements
                    hessian[3 * k - 2, 3 * i - 2] += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdXi;
                    hessian[3 * k - 1, 3 * i - 1] += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdYi;
                    hessian[3 * k, 3 * i]         += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdZi;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * k - 2, 3 * i - 1] += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdYi;
                    hessian[3 * k - 2, 3 * i]     += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdZi;
                    hessian[3 * k - 1, 3 * i - 2] += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdXi;
                    hessian[3 * k - 1, 3 * i]     += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdZi;
                    hessian[3 * k, 3 * i - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdXi;
                    hessian[3 * k, 3 * i - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdYi;

                    //Hlj
                    // diagonals of off-diagonal super elements

                    hessian[3 * l - 2, 3 * j - 2] += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdXj;
                    hessian[3 * l - 1, 3 * j - 1] += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdYj;
                    hessian[3 * l, 3 * j]         += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdZj;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * l - 2, 3 * j - 1] += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdYj;
                    hessian[3 * l - 2, 3 * j]     += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdZj;
                    hessian[3 * l - 1, 3 * j - 2] += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdXj;
                    hessian[3 * l - 1, 3 * j]     += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdZj;
                    hessian[3 * l, 3 * j - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdXj;
                    hessian[3 * l, 3 * j - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdYj;

                    //Hjl
                    // diagonals of off-diagonal super elements
                    hessian[3 * j - 2, 3 * l - 2] += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdXl;
                    hessian[3 * j - 1, 3 * l - 1] += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdYl;
                    hessian[3 * j, 3 * l]         += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdZl;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * j - 2, 3 * l - 1] += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdYl;
                    hessian[3 * j - 2, 3 * l]     += +(2 * K_phi) / (1 - G * G) * dGdXj * dGdZl;
                    hessian[3 * j - 1, 3 * l - 2] += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdXl;
                    hessian[3 * j - 1, 3 * l]     += +(2 * K_phi) / (1 - G * G) * dGdYj * dGdZl;
                    hessian[3 * j, 3 * l - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdXl;
                    hessian[3 * j, 3 * l - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZj * dGdYl;

                    //Hlk
                    // diagonals of off-diagonal super elements

                    hessian[3 * l - 2, 3 * k - 2] += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdXk;
                    hessian[3 * l - 1, 3 * k - 1] += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdYk;
                    hessian[3 * l, 3 * k]         += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdZk;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * l - 2, 3 * k - 1] += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdYk;
                    hessian[3 * l - 2, 3 * k]     += +(2 * K_phi) / (1 - G * G) * dGdXl * dGdZk;
                    hessian[3 * l - 1, 3 * k - 2] += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdXk;
                    hessian[3 * l - 1, 3 * k]     += +(2 * K_phi) / (1 - G * G) * dGdYl * dGdZk;
                    hessian[3 * l, 3 * k - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdXk;
                    hessian[3 * l, 3 * k - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZl * dGdYk;

                    //Hkl
                    // diagonals of off-diagonal super elements
                    hessian[3 * k - 2, 3 * l - 2] += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdXl;
                    hessian[3 * k - 1, 3 * l - 1] += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdYl;
                    hessian[3 * k, 3 * l]         += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdZl;

                    // off-diagonals of off-diagonal super elements

                    hessian[3 * k - 2, 3 * l - 1] += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdYl;
                    hessian[3 * k - 2, 3 * l]     += +(2 * K_phi) / (1 - G * G) * dGdXk * dGdZl;
                    hessian[3 * k - 1, 3 * l - 2] += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdXl;
                    hessian[3 * k - 1, 3 * l]     += +(2 * K_phi) / (1 - G * G) * dGdYk * dGdZl;
                    hessian[3 * k, 3 * l - 2]     += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdXl;
                    hessian[3 * k, 3 * l - 1]     += +(2 * K_phi) / (1 - G * G) * dGdZk * dGdYl;

                    //Hii
                    //update the diagonals of diagonal super elements

                    hessian[3 * i - 2, 3 * i - 2] += +2 * K_phi / (1 - G * G) * dGdXi * dGdXi;
                    hessian[3 * i - 1, 3 * i - 1] += +2 * K_phi / (1 - G * G) * dGdYi * dGdYi;
                    hessian[3 * i, 3 * i]         += +2 * K_phi / (1 - G * G) * dGdZi * dGdZi;

                    // update the off-diagonals of diagonal super elements
                    hessian[3 * i - 2, 3 * i - 1] += +2 * K_phi / (1 - G * G) * dGdXi * dGdYi;
                    hessian[3 * i - 2, 3 * i]     += +2 * K_phi / (1 - G * G) * dGdXi * dGdZi;
                    hessian[3 * i - 1, 3 * i - 2] += +2 * K_phi / (1 - G * G) * dGdYi * dGdXi;
                    hessian[3 * i - 1, 3 * i]     += +2 * K_phi / (1 - G * G) * dGdYi * dGdZi;
                    hessian[3 * i, 3 * i - 2]     += +2 * K_phi / (1 - G * G) * dGdZi * dGdXi;
                    hessian[3 * i, 3 * i - 1]     += +2 * K_phi / (1 - G * G) * dGdZi * dGdYi;

                    //Hjj
                    //update the diagonals of diagonal super elements

                    hessian[3 * j - 2, 3 * j - 2] += +2 * K_phi / (1 - G * G) * dGdXj * dGdXj;
                    hessian[3 * j - 1, 3 * j - 1] += +2 * K_phi / (1 - G * G) * dGdYj * dGdYj;
                    hessian[3 * j, 3 * j]         += +2 * K_phi / (1 - G * G) * dGdZj * dGdZj;

                    // update the off-diagonals of diagonal super elements
                    hessian[3 * j - 2, 3 * j - 1] += +2 * K_phi / (1 - G * G) * dGdXj * dGdYj;
                    hessian[3 * j - 2, 3 * j]     += +2 * K_phi / (1 - G * G) * dGdXj * dGdZj;
                    hessian[3 * j - 1, 3 * j - 2] += +2 * K_phi / (1 - G * G) * dGdYj * dGdXj;
                    hessian[3 * j - 1, 3 * j]     += +2 * K_phi / (1 - G * G) * dGdYj * dGdZj;
                    hessian[3 * j, 3 * j - 2]     += +2 * K_phi / (1 - G * G) * dGdZj * dGdXj;
                    hessian[3 * j, 3 * j - 1]     += +2 * K_phi / (1 - G * G) * dGdZj * dGdYj;

                    //Hkk
                    //update the diagonals of diagonal super elements

                    hessian[3 * k - 2, 3 * k - 2] += +2 * K_phi / (1 - G * G) * dGdXk * dGdXk;
                    hessian[3 * k - 1, 3 * k - 1] += +2 * K_phi / (1 - G * G) * dGdYk * dGdYk;
                    hessian[3 * k, 3 * k]         += +2 * K_phi / (1 - G * G) * dGdZk * dGdZk;

                    // update the off-diagonals of diagonal super elements
                    hessian[3 * k - 2, 3 * k - 1] += +2 * K_phi / (1 - G * G) * dGdXk * dGdYk;
                    hessian[3 * k - 2, 3 * k]     += +2 * K_phi / (1 - G * G) * dGdXk * dGdZk;
                    hessian[3 * k - 1, 3 * k - 2] += +2 * K_phi / (1 - G * G) * dGdYk * dGdXk;
                    hessian[3 * k - 1, 3 * k]     += +2 * K_phi / (1 - G * G) * dGdYk * dGdZk;
                    hessian[3 * k, 3 * k - 2]     += +2 * K_phi / (1 - G * G) * dGdZk * dGdXk;
                    hessian[3 * k, 3 * k - 1]     += +2 * K_phi / (1 - G * G) * dGdZk * dGdYk;

                    //Hll
                    //update the diagonals of diagonal super elements

                    hessian[3 * l - 2, 3 * l - 2] += +2 * K_phi / (1 - G * G) * dGdXl * dGdXl;
                    hessian[3 * l - 1, 3 * l - 1] += +2 * K_phi / (1 - G * G) * dGdYl * dGdYl;
                    hessian[3 * l, 3 * l]         += +2 * K_phi / (1 - G * G) * dGdZl * dGdZl;

                    // update the off-diagonals of diagonal super elements
                    hessian[3 * l - 2, 3 * l - 1] += +2 * K_phi / (1 - G * G) * dGdXl * dGdYl;
                    hessian[3 * l - 2, 3 * l]     += +2 * K_phi / (1 - G * G) * dGdXl * dGdZl;
                    hessian[3 * l - 1, 3 * l - 2] += +2 * K_phi / (1 - G * G) * dGdYl * dGdXl;
                    hessian[3 * l - 1, 3 * l]     += +2 * K_phi / (1 - G * G) * dGdYl * dGdZl;
                    hessian[3 * l, 3 * l - 2]     += +2 * K_phi / (1 - G * G) * dGdZl * dGdXl;
                    hessian[3 * l, 3 * l - 1]     += +2 * K_phi / (1 - G * G) * dGdZl * dGdYl;
                }
                if (checkComputable)
                {
                    HDebug.Assert(hessian.matrix.IsComputable());
                }
                return(hessian.matrix);
            }
Пример #7
0
        public int UpdateAdd(HessMatrix other, double mul_other, IList <int> idxOther, double thres_NearZeroBlock, bool parallel = false)
        {
            Matrix debug_updateadd = null;

            if (UpdateAdd_SelfTest && idxOther == null && thres_NearZeroBlock == 0)
            {
                if ((100 < ColBlockSize) && (ColBlockSize < 1000) &&
                    (100 < RowBlockSize) && (RowBlockSize < 1000) &&
                    (other.NumUsedBlocks > 20))
                {
                    UpdateAdd_SelfTest = false;
                    debug_updateadd    = this.ToArray();
                    debug_updateadd.UpdateAdd(other, mul_other);
                }
            }

            int[] idx_other;
            if (idxOther == null)
            {
                //HDebug.Exception(ColSize == other.ColSize);
                //HDebug.Exception(RowSize == other.RowSize);
                idx_other = HEnum.HEnumCount(other.ColSize).ToArray();
            }
            else
            {
                idx_other = idxOther.ToArray();
            }

            int count         = 0;
            int count_ignored = 0;

            object _lock         = new object();
            object _lock_ignored = new object();
            Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bc_br_bval)
            {
                count++;
                int         other_bc   = bc_br_bval.Item1;
                int         other_br   = bc_br_bval.Item2;
                MatrixByArr other_bmat = bc_br_bval.Item3;
                if (other_bmat.HAbsMax() <= thres_NearZeroBlock)
                {
                    lock (_lock_ignored)
                        count_ignored++;
                    //continue;
                    return;
                }
                int bc = idx_other[other_bc];
                int br = idx_other[other_br];
                lock (_lock)
                {
                    MatrixByArr this_bmat = GetBlock(bc, br);
                    MatrixByArr new_bmat;
                    if (this_bmat == null)
                    {
                        if (other_bmat == null)
                        {
                            new_bmat = null;
                        }
                        else
                        {
                            new_bmat = mul_other * other_bmat;
                        }
                    }
                    else
                    {
                        if (other_bmat == null)
                        {
                            new_bmat = this_bmat.CloneT();
                        }
                        else
                        {
                            new_bmat = this_bmat + mul_other * other_bmat;
                        }
                    }
                    SetBlock(bc, br, new_bmat);
                }
            };

            if (parallel)
            {
                Parallel.ForEach(other.EnumBlocks(), func);
            }
            else
            {
                foreach (var bc_br_bval in other.EnumBlocks())
                {
                    func(bc_br_bval);
                }
            }

            if (debug_updateadd != null)
            {
                Matrix debug_diff   = debug_updateadd - this;
                double debug_absmax = debug_diff.HAbsMax();
                HDebug.AssertToleranceMatrix(0, debug_diff);
            }

            return(count_ignored);
        }
Пример #8
0
        static HessMatrix GetMulImpl(HessMatrix left, HessMatrix right, ILinAlg ila, bool warning)
        {
            if (HDebug.Selftest())
            {
                Matrix h1 = new double[, ] {
                    { 0, 1, 2, 3, 4, 5 }
                    , { 1, 2, 3, 4, 5, 6 }
                    , { 2, 3, 4, 5, 6, 7 }
                    , { 3, 4, 5, 6, 7, 8 }
                    , { 4, 5, 6, 7, 8, 9 }
                    , { 5, 6, 7, 8, 9, 0 }
                };
                HessMatrix h2    = HessMatrixSparse.FromMatrix(h1);
                Matrix     h11   = Matrix.GetMul(h1, h1);
                HessMatrix h22   = HessMatrix.GetMulImpl(h2, h2, null, false);
                Matrix     hdiff = h11 - h22;
                HDebug.AssertToleranceMatrix(0, hdiff);
            }
            if ((left is HessMatrixDense) && (right is HessMatrixDense))
            {
                if (ila != null)
                {
                    return(new HessMatrixDense {
                        hess = ila.Mul(left, right)
                    });
                }
                if (warning)
                {
                    HDebug.ToDo("Check (HessMatrixDense * HessMatrixDense) !!!");
                }
            }

            Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > > left_ic_rows = new Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > >();

            foreach (var ic_row in left.EnumRowBlocksAll())
            {
                left_ic_rows.Add(ic_row.Item1, ic_row.Item2.HToDictionaryWithKeyItem2());
            }

            Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > > right_ir_cols = new Dictionary <int, Dictionary <int, Tuple <int, int, MatrixByArr> > >();

            foreach (var ir_col in right.EnumColBlocksAll())
            {
                right_ir_cols.Add(ir_col.Item1, ir_col.Item2.HToDictionaryWithKeyItem1());
            }

            HessMatrix mul = null;

            if ((left is HessMatrixDense) && (right is HessMatrixDense))
            {
                mul = HessMatrixDense.ZerosDense(left.ColSize, right.RowSize);
            }
            else
            {
                mul = HessMatrixSparse.ZerosSparse(left.ColSize, right.RowSize);
            }
            for (int ic = 0; ic < left.ColBlockSize; ic++)
            {
                var left_row = left_ic_rows[ic];
                if (left_row.Count == 0)
                {
                    continue;
                }
                for (int ir = 0; ir < right.RowBlockSize; ir++)
                {
                    var right_col = right_ir_cols[ir];
                    if (right_col.Count == 0)
                    {
                        continue;
                    }
                    foreach (var left_ck in left_row)
                    {
                        int ik = left_ck.Key;
                        HDebug.Assert(ic == left_ck.Value.Item1);
                        HDebug.Assert(ik == left_ck.Value.Item2);
                        if (right_col.ContainsKey(ik))
                        {
                            var right_kr = right_col[ik];
                            HDebug.Assert(ik == right_kr.Item1);
                            HDebug.Assert(ir == right_kr.Item2);
                            MatrixByArr mul_ckr = mul.GetBlock(ic, ir) + left_ck.Value.Item3 * right_kr.Item3;
                            mul.SetBlock(ic, ir, mul_ckr);
                        }
                    }
                }
            }

            return(mul);
        }
Пример #9
0
        public HessMatrix SubMatrixByAtomsImpl
            (bool ignNegIdx         // [false]
            , IList <int> idxColAtoms
            , IList <int> idxRowAtoms
            , bool bCloneBlock
            , bool parallel = false
            )
        {
            Dictionary <int, int[]> col_idx2nidx = new Dictionary <int, int[]>();
            HashSet <int>           col_idxs     = new HashSet <int>();

            for (int nidx = 0; nidx < idxColAtoms.Count; nidx++)
            {
                int idx = idxColAtoms[nidx];
                if (idx < 0)
                {
                    if (ignNegIdx)
                    {
                        continue;
                    }
                    throw new IndexOutOfRangeException();
                }
                if (col_idx2nidx.ContainsKey(idx) == false)
                {
                    col_idx2nidx.Add(idx, new int[0]);
                }
                col_idx2nidx[idx] = col_idx2nidx[idx].HAdd(nidx);
                col_idxs.Add(idx);
            }
            Dictionary <int, int[]> row_idx2nidx = new Dictionary <int, int[]>();

            for (int nidx = 0; nidx < idxRowAtoms.Count; nidx++)
            {
                int idx = idxRowAtoms[nidx];
                if (idx < 0)
                {
                    if (ignNegIdx)
                    {
                        continue;
                    }
                    throw new IndexOutOfRangeException();
                }
                if (row_idx2nidx.ContainsKey(idx) == false)
                {
                    row_idx2nidx.Add(idx, new int[0]);
                }
                row_idx2nidx[idx] = row_idx2nidx[idx].HAdd(nidx);
            }

            HessMatrix nhess = Zeros(idxColAtoms.Count * 3, idxRowAtoms.Count * 3);

            {
                Action <ValueTuple <int, int, MatrixByArr> > func = delegate(ValueTuple <int, int, MatrixByArr> bc_br_bval)
                {
                    int bc = bc_br_bval.Item1; if (col_idx2nidx.ContainsKey(bc) == false)
                    {
                        return;
                    }
                    int br = bc_br_bval.Item2; if (row_idx2nidx.ContainsKey(br) == false)
                    {
                        return;
                    }
                    var bval = bc_br_bval.Item3;
                    if (bCloneBlock)
                    {
                        foreach (int nbc in col_idx2nidx[bc])
                        {
                            foreach (int nbr in row_idx2nidx[br])
                            {
                                lock (nhess)
                                    nhess.SetBlock(nbc, nbr, bval.CloneT());
                            }
                        }
                    }
                    else
                    {
                        foreach (int nbc in col_idx2nidx[bc])
                        {
                            foreach (int nbr in row_idx2nidx[br])
                            {
                                lock (nhess)
                                    nhess.SetBlock(nbc, nbr, bval);
                            }
                        }
                    }
                };

                if (parallel)
                {
                    Parallel.ForEach(EnumBlocksInCols(col_idxs.ToArray()), func);
                }
                else
                {
                    foreach (var bc_br_bval in EnumBlocksInCols(col_idxs.ToArray()))
                    {
                        func(bc_br_bval);
                    }
                }
            }
            if (SubMatrixByAtomsImpl_selftest2)
            {
                SubMatrixByAtomsImpl_selftest2 = false;
                HessMatrix tnhess = SubMatrixByAtomsImpl0(idxColAtoms, idxRowAtoms);
                HDebug.Assert(HessMatrix.HessMatrixSparseEqual(nhess, tnhess));
                //////////////////////////////////////////
                Matrix thess1 = new double[, ] {
                    { 0, 1, 2, 3, 4, 5 }
                    , { 1, 2, 3, 4, 5, 6 }
                    , { 2, 3, 4, 5, 6, 7 }
                    , { 3, 4, 5, 6, 7, 8 }
                    , { 4, 5, 6, 7, 8, 9 }
                    , { 5, 6, 7, 8, 9, 0 }
                };
                HessMatrix thess2 = HessMatrixDense.FromMatrix(thess1);
                HessMatrix thess3 = thess2.SubMatrixByAtomsImpl(false, new int[] { 0 }, new int[] { 1 }, true);
                Matrix     thess4 = new double[, ] {
                    { 3, 4, 5 }
                    , { 4, 5, 6 }
                    , { 5, 6, 7 }
                };
                HDebug.AssertToleranceMatrix(0, thess3 - thess4);
            }

            return(nhess);
        }