Beispiel #1
0
        public static HessInfo GetHessAnm(Universe univ, IList <Vector> coords, double cutoff)
        {
            // cutoff: 4.5    for all atomic model
            //         7 or 8 for CA model (Atilgan01-BiophysJ - Anisotropy of Fluctuation Dynamics of Proteins with an Elastic Network Model)
            HessMatrix hess = GetHessAnm(coords, cutoff);

            Vector lmass = null;

            object[] latoms  = null;
            Vector[] lcoords = null;

            if (univ == null)
            {
                lmass   = Vector.Ones(coords.Count);
                latoms  = null;
                lcoords = coords.HCloneVectors().ToArray();
            }
            else
            {
                lmass   = univ.GetMasses();
                latoms  = univ.atoms.ToArray();
                lcoords = coords.HCloneVectors().ToArray();
            }

            return(new HessInfo
            {
                hess = hess,
                mass = lmass,
                atoms = latoms,
                coords = lcoords,
                numZeroEigval = 6,
            });
        }
Beispiel #2
0
            public static double[] GetRotAngles(Universe univ
                                                , Vector[] coords
                                                , Vector[] dcoords
                                                , MatrixByArr J
                                                , ILinAlg ila
                                                )
            {
                Vector dangles;

                using (ila.NewDisposables())
                {
                    Vector R      = Vector.FromBlockvector(dcoords);
                    Vector M      = univ.GetMasses(3);
                    var    RR     = ila.ToILMat(R).AddDisposable();
                    var    MM     = ila.ToILMat(M).Diag().AddDisposable();
                    var    JJ     = ila.ToILMat(J).AddDisposable();
                    var    invJMJ = ila.Inv(JJ.Tr * MM * JJ).AddDisposable();
                    var    AA     = invJMJ * JJ.Tr * MM * RR;
                    dangles = AA.ToArray().HToArray1D();
                }

                if (HDebug.False && HDebug.IsDebuggerAttached)
                {
                    Vector tdangles = GetRotAngles(univ, coords, dcoords, J);

                    HDebug.Assert(0.9999 < (tdangles.Dist / dangles.Dist), (tdangles.Dist / dangles.Dist) < 1.0001);
                    HDebug.Assert(LinAlg.DotProd(tdangles, dangles) / (tdangles.Dist * dangles.Dist) > 0.9999);
                    HDebug.Assert((tdangles - dangles).Dist / tdangles.Dist < 0.0001);
                }

                return(dangles);
            }
Beispiel #3
0
            public static double[] GetRotAngles(Universe univ
                                                , Vector[] coords
                                                , Vector[] dcoords
                                                , Func <Vector, MatrixByArr> Diag
                                                , Func <MatrixByArr, MatrixByArr> InvSymm
                                                , Func <MatrixByArr, MatrixByArr, MatrixByArr, MatrixByArr> Mul
                                                , MatrixByArr J = null
                                                , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null
                                                , List <Universe.RotableInfo> univ_rotinfos             = null
                                                , Vector[] dcoordsRotated = null
                                                )
            {
                if (J == null)
                {
                    if (univ_rotinfos == null)
                    {
                        if (univ_flexgraph == null)
                        {
                            univ_flexgraph = univ.BuildFlexibilityGraph();
                        }
                        univ_rotinfos = univ.GetRotableInfo(univ_flexgraph);
                    }
                    J = TNM.GetJ(univ, coords, univ_rotinfos);
                }

                Vector dangles;

                {
                    Vector      R      = Vector.FromBlockvector(dcoords);
                    MatrixByArr M      = Diag(univ.GetMasses(3));
                    MatrixByArr Jt     = J.Tr();
                    MatrixByArr invJMJ = InvSymm(Mul(Jt, M, J));
                    Vector      A      = LinAlg.MV(Mul(invJMJ, Jt, M), R); // (6) of TNM paper
                    dangles = A;
                    if (dcoordsRotated != null)
                    {
                        HDebug.Assert(dcoordsRotated.Length == dcoords.Length);
                        Vector dR = LinAlg.MV(J, A);
                        Vector ldcoordsRotated = dR;
                        HDebug.Assert(ldcoordsRotated.Size == dcoordsRotated.Length * 3);
                        for (int i = 0; i < dcoordsRotated.Length; i++)
                        {
                            int i3 = i * 3;
                            dcoordsRotated[i] = new double[] { ldcoordsRotated[i3 + 0], ldcoordsRotated[i3 + 1], ldcoordsRotated[i3 + 2] };
                        }
                    }
                }

                if (HDebug.IsDebuggerAttached)
                {
                    Vector tdangles = GetRotAngles(univ, coords, dcoords, J, univ_flexgraph, univ_rotinfos);

                    HDebug.Assert(0.9999 < (tdangles.Dist / dangles.Dist), (tdangles.Dist / dangles.Dist) < 1.0001);
                    HDebug.Assert(LinAlg.DotProd(tdangles, dangles) / (tdangles.Dist * dangles.Dist) > 0.9999);
                    HDebug.Assert((tdangles - dangles).Dist / tdangles.Dist < 0.0001);
                }

                return(dangles);
            }
Beispiel #4
0
            public static double[] GetRotAngles(Universe univ
                                                , Vector[] coords
                                                , Vector[] dcoords
                                                , MatrixByArr J = null
                                                , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null
                                                , List <Universe.RotableInfo> univ_rotinfos             = null
                                                , Vector[] dcoordsRotated = null
                                                )
            {
                if (J == null)
                {
                    if (univ_rotinfos == null)
                    {
                        if (univ_flexgraph == null)
                        {
                            univ_flexgraph = univ.BuildFlexibilityGraph();
                        }
                        univ_rotinfos = univ.GetRotableInfo(univ_flexgraph);
                    }
                    J = TNM.GetJ(univ, coords, univ_rotinfos);
                }

                double[] dangles;
                using (new Matlab.NamedLock("TEST"))
                {
                    Matlab.Clear("TEST");
                    Matlab.PutVector("TEST.R", Vector.FromBlockvector(dcoords));
                    Matlab.PutMatrix("TEST.J", J.ToArray(), true);
                    Matlab.PutVector("TEST.M", univ.GetMasses(3));
                    Matlab.Execute("TEST.M = diag(TEST.M);");
                    Matlab.Execute("TEST.invJMJ = inv(TEST.J' * TEST.M * TEST.J);");
                    Matlab.Execute("TEST.A = TEST.invJMJ * TEST.J' * TEST.M * TEST.R;"); // (6) of TNM paper
                    dangles = Matlab.GetVector("TEST.A");
                    if (dcoordsRotated != null)
                    {
                        HDebug.Assert(dcoordsRotated.Length == dcoords.Length);
                        Matlab.Execute("TEST.dR = TEST.J * TEST.A;");
                        Vector ldcoordsRotated = Matlab.GetVector("TEST.dR");
                        HDebug.Assert(ldcoordsRotated.Size == dcoordsRotated.Length * 3);
                        for (int i = 0; i < dcoordsRotated.Length; i++)
                        {
                            int i3 = i * 3;
                            dcoordsRotated[i] = new double[] { ldcoordsRotated[i3 + 0], ldcoordsRotated[i3 + 1], ldcoordsRotated[i3 + 2] };
                        }
                    }
                    Matlab.Clear("TEST");
                }

                return(dangles);
            }
Beispiel #5
0
        public static HessInfo GetHessSsNMA
            (Universe univ
            , IList <Vector> coords
            , IEnumerable <Universe.Bond> bonds
            , IEnumerable <Universe.Angle> angles
            , IEnumerable <Universe.Improper> impropers
            , IEnumerable <Universe.Dihedral> dihedrals
            , IEnumerable <Universe.Nonbonded> nonbondeds
            , IEnumerable <Universe.Nonbonded14> nonbonded14s
            , double?maxAbsSpring = null
            , double?K_r          = 340.00
            , double?K_theta      = 45.00
            , double?K_ub         = 10.00
            , double?K_psi        = 70.00
            , double?K_chi        = 1.00
            , double?n            = 1
            , string k_vdW        = "Unif"
            //, bool setNanForEmptyAtom                         // =true
            )
        {
            bool   vdW       = true;                    // use vdW
            bool   elec      = false;                   // ignore electrostatic
            double D         = double.PositiveInfinity; // dielectric constant for Tinker is "1"
            bool   ignNegSpr = true;                    // ignore negative spring (do not add the spring into hessian matrix)

            //maxAbsSpring = Math.Pow(10, 9);
            HessMatrix hess = null;

            hess = STeM.GetHessBond(coords, bonds, K_r, hessian: hess);
            hess = STeM.GetHessAngle(coords, angles, true, K_theta, K_ub, hessian: hess);
            hess = STeM.GetHessImproper(coords, impropers, K_psi, hessian: hess, useArnaud96: true);
            hess = STeM.GetHessDihedral(coords, dihedrals, K_chi, n, hessian: hess, useAbsSpr: true, useArnaud96: true);
            hess = HessSpr.GetHessNonbond(coords, nonbondeds, D, k_vdW, hessian: hess, vdW: vdW, elec: elec, ignNegSpr: ignNegSpr, maxAbsSpring: maxAbsSpring);
            hess = HessSpr.GetHessNonbond(coords, nonbonded14s, D, k_vdW, hessian: hess, vdW: vdW, elec: elec, ignNegSpr: ignNegSpr, maxAbsSpring: maxAbsSpring);

            //if(setNanForEmptyAtom)
            Hess.UpdateHessNaN(hess, coords);

            return(new HessInfo
            {
                hess = hess,
                mass = univ.GetMasses(),
                atoms = univ.atoms.ToArray(),
                coords = coords.HCloneVectors().ToArray(),
                numZeroEigval = 6,
            });
        }
Beispiel #6
0
        public static HessInfo GetHessEAnm
            (Universe univ
            , IList <Vector> coords
            , IEnumerable <Tuple <int, int, double> > enumKij
            , bool b_bonds
            , bool b_angles
            , bool b_impropers
            , bool b_dihedrals
            )
        {
            //bool vdW  = true;       // use vdW
            //bool elec = false;      // ignore electrostatic
            //double D = double.PositiveInfinity; // dielectric constant for Tinker is "1"
            //bool ignNegSpr = true;  // ignore negative spring (do not add the spring into hessian matrix)

            HessMatrix hess = null;

            hess = Hess.GetHessAnm(coords, enumKij);
            if (b_bonds)
            {
                hess = STeM.GetHessBond(coords, univ.bonds, 340.00, hessian: hess);
            }
            if (b_angles)
            {
                hess = STeM.GetHessAngle(coords, univ.angles, true, 45.00, 10.00, hessian: hess);
            }
            if (b_impropers)
            {
                hess = STeM.GetHessImproper(coords, univ.impropers, 70.00, hessian: hess, useArnaud96: true);
            }
            if (b_dihedrals)
            {
                hess = STeM.GetHessDihedral(coords, univ.dihedrals, 1.00, 1, hessian: hess, useAbsSpr: true, useArnaud96: true);
            }

            Hess.UpdateHessNaN(hess, coords);

            return(new HessInfo
            {
                hess = hess,
                mass = univ.GetMasses(),
                atoms = univ.atoms.ToArray(),
                coords = coords.HCloneVectors().ToArray(),
                numZeroEigval = 6,
            });
        }
Beispiel #7
0
            public static Mode[] GetModeByTorsional(Universe univ
                                                    , HessMatrix hessian
                                                    , List <Universe.RotableInfo> univ_rotinfos = null
                                                    , Matrix J                 = null
                                                    , Vector[] coords          = null
                                                    , HPack <Matrix> optoutJMJ = null // J' M J
                                                    , HPack <Matrix> optoutJM  = null // J' M
                                                    , Func <Matrix, Tuple <Matrix, Vector> > fnEigSymm = null
                                                    , Func <Matrix, Matrix, Matrix, Matrix> fnMul      = null
                                                    )
            {
                if (univ_rotinfos == null)
                {
                    Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = univ.BuildFlexibilityGraph(null as IList <Bond>);
                    if (univ_flexgraph.FindLoops().Count > 0)
                    {
                        // loop should not exist in the flexibility-graph; no-global loop in backbone
                        return(null);
                    }
                    univ_rotinfos = univ.GetRotableInfo(univ_flexgraph);
                }
                if (coords == null)
                {
                    coords = univ.GetCoords();
                }
                if (J == null)
                {
                    J = TNM.GetJ(univ, coords, univ_rotinfos);
                }
                Vector masses = univ.GetMasses();

                Mode[] modes = GetModeByTorsional(hessian, masses, J
                                                  , optoutJMJ: optoutJMJ, optoutJM: optoutJM
                                                  , fnEigSymm: fnEigSymm, fnMul: fnMul
                                                  );
                return(modes);
            }
Beispiel #8
0
            public static Vector GetBFactor(Universe univ, HessMatrix hessian, MatrixByArr J)
            {
                Vector masses = univ.GetMasses();

                Mode[] modes = GetModeByTorsional(hessian, masses, J);

                Vector bfactor = new double[univ.size];

                {
                    int m = modes.Length;
                    for (int i = 0; i < univ.size; i++)
                    {
                        bfactor[i] = 0;
                        for (int idx = 0; idx < m; idx++)
                        {
                            double dx = modes[idx].eigvec[i * 3 + 0];                        // tormodes[idx][i*3+0];
                            double dy = modes[idx].eigvec[i * 3 + 1];                        // tormodes[idx][i*3+1];
                            double dz = modes[idx].eigvec[i * 3 + 2];                        // tormodes[idx][i*3+2];
                            bfactor[i] += (dx * dx + dy * dy + dz * dz) / modes[idx].eigval; // (dx*dx + dy*dy + dz*dz) / toreigvals[idx];
                        }
                    }
                }
                return(bfactor);
            }
Beispiel #9
0
            public static double[] GetRotAngles(Universe univ
                                                , Vector[] coords
                                                , MatrixByArr hessian
                                                , Vector[] forces
                                                , MatrixByArr J = null
                                                , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null
                                                , List <Universe.RotableInfo> univ_rotinfos             = null
                                                , Vector[] forceProjectedByTorsional   = null
                                                , HPack <Vector> optEigvalOfTorHessian = null
                                                )
            {
                Vector mass = univ.GetMasses();

                //Vector[] dcoords = new Vector[univ.size];
                //double t2 = t*t;
                //for(int i=0; i<univ.size; i++)
                //    dcoords[i] = forces[i] * (0.5*t2/mass[i]);

                if (J == null)
                {
                    if (univ_rotinfos == null)
                    {
                        if (univ_flexgraph == null)
                        {
                            univ_flexgraph = univ.BuildFlexibilityGraph();
                        }
                        univ_rotinfos = univ.GetRotableInfo(univ_flexgraph);
                    }
                    J = TNM.GetJ(univ, coords, univ_rotinfos);
                }

                double[] dangles;
                using (new Matlab.NamedLock("TEST"))
                {
                    Matlab.Clear("TEST");
                    Matlab.PutVector("TEST.F", Vector.FromBlockvector(forces));
                    Matlab.PutMatrix("TEST.J", J);
                    Matlab.PutMatrix("TEST.H", hessian);
                    Matlab.PutVector("TEST.M", univ.GetMasses(3));
                    Matlab.Execute("TEST.M = diag(TEST.M);");

                    Matlab.Execute("TEST.JHJ = TEST.J' * TEST.H * TEST.J;");
                    Matlab.Execute("TEST.JMJ = TEST.J' * TEST.M * TEST.J;");
                    // (J' H J) tor = J' F
                    // (V' D V) tor = J' F  <= (V,D) are (eigvec,eigval) of generalized eigenvalue problem with (A = JHJ, B = JMJ)
                    // tor = inv(V' D V) J' F
                    Matlab.Execute("[TEST.V, TEST.D] = eig(TEST.JHJ, TEST.JMJ);");
                    if (optEigvalOfTorHessian != null)
                    {
                        optEigvalOfTorHessian.value = Matlab.GetVector("diag(TEST.D)");
                    }
                    {
                        Matlab.Execute("TEST.D = diag(TEST.D);");
                        Matlab.Execute("TEST.D(abs(TEST.D)<1) = 0;"); // remove "eigenvalue < 1" because they will increase
                                                                      // the magnitude of force term too big !!!
                        Matlab.Execute("TEST.D = diag(TEST.D);");
                    }
                    Matlab.Execute("TEST.invJHJ  = TEST.V * pinv(TEST.D) * TEST.V';");
                    Matlab.Execute("TEST.dtor  = TEST.invJHJ * TEST.J' * TEST.F;");
                    /// f = m a
                    /// d = 1/2 a t^2
                    ///   = 0.5 a        : assuming t=1
                    ///   = 0.5 f/m
                    /// f = m a
                    ///   = 2 m d t^-2
                    ///   = 2 m d        : assuming t=1
                    ///
                    /// coord change
                    /// dr = 0.5 a t^2
                    ///    = 0.5 f/m     : assuming t=1
                    ///    = 0.5 M^-1 F  : M is mass matrix, F is the net force of each atom
                    ///
                    /// torsional angle change
                    /// dtor = (J' M J)^-1 J' M * dr                  : (6) of TNM paper
                    ///      = (J' M J)^-1 J' M * 0.5 M^-1 F
                    ///      = 0.5 (J' M J)^-1 J' F
                    ///
                    /// force filtered by torsional ...
                    /// F_tor = ma
                    ///       = 2 M (J dtor)
                    ///       = 2 M J 0.5 (J' M J)^-1 J' F
                    ///       = M J (J' M J)^-1 J' F
                    ///
                    /// H J dtor = F
                    ///          = F_tor                            : update force as the torsional filtered force
                    ///          = M J (J' M J)^-1 J' F
                    /// (J' H J) dtor = (J' M J) (J' M J)^-1 J' F
                    /// (V D V') dtor = (J' M J) (J' M J)^-1 J' F               : eigen decomposition of (J' H J) using
                    ///                                                           generalized eigenvalue problem with (J' M J)
                    ///          dtor = (V D^-1 V') (J' M J) (J' M J)^-1 J' F   : (J' M J) (J' M J)^-1 = I. However, it has
                    ///                                                           the projection effect of J'F into (J' M J)
                    ///                                                           vector space(?). The projection will be taken
                    ///                                                           care by (V D^-1 V')
                    ///               = (V D^-1 V') J' F
                    ///
                    dangles = Matlab.GetVector("TEST.dtor");
                    if (forceProjectedByTorsional != null)
                    {
                        HDebug.Assert(forceProjectedByTorsional.Length == forces.Length);
                        Matlab.Execute("TEST.F_tor = TEST.M * TEST.J * pinv(TEST.JMJ) * TEST.J' * TEST.F;");
                        Vector lforceProjectedByTorsional = Matlab.GetVector("TEST.F_tor");
                        HDebug.Assert(lforceProjectedByTorsional.Size == forceProjectedByTorsional.Length * 3);
                        for (int i = 0; i < forceProjectedByTorsional.Length; i++)
                        {
                            int i3 = i * 3;
                            forceProjectedByTorsional[i] = new double[] { lforceProjectedByTorsional[i3 + 0],
                                                                          lforceProjectedByTorsional[i3 + 1],
                                                                          lforceProjectedByTorsional[i3 + 2], };
                        }
                    }
                    Matlab.Clear("TEST");
                }

                return(dangles);
            }
Beispiel #10
0
            public static double[] GetRotAngles(Universe univ
                                                , Vector[] coords
                                                , Vector[] forces
                                                , double t // 0.1
                                                , MatrixByArr J = null
                                                , Graph <Universe.Atom[], Universe.Bond> univ_flexgraph = null
                                                , List <Universe.RotableInfo> univ_rotinfos             = null
                                                , HPack <Vector[]> forcesProjectedByTorsional           = null
                                                , HPack <Vector[]> dcoordsProjectedByTorsional          = null
                                                )
            {
                Vector mass = univ.GetMasses();
                //Vector[] dcoords = new Vector[univ.size];
                double t2 = t * t;

                //for(int i=0; i<univ.size; i++)
                //    dcoords[i] = forces[i] * (0.5*t2/mass[i]);

                if (J == null)
                {
                    if (univ_rotinfos == null)
                    {
                        if (univ_flexgraph == null)
                        {
                            univ_flexgraph = univ.BuildFlexibilityGraph();
                        }
                        univ_rotinfos = univ.GetRotableInfo(univ_flexgraph);
                    }
                    J = TNM.GetJ(univ, coords, univ_rotinfos);
                }

                double[] dangles;
                using (new Matlab.NamedLock("TEST"))
                {
                    Matlab.Clear("TEST");
                    Matlab.PutVector("TEST.F", Vector.FromBlockvector(forces));
                    Matlab.PutValue("TEST.t2", t2);
                    //Matlab.PutVector("TEST.R", Vector.FromBlockvector(dcoords));
                    Matlab.PutMatrix("TEST.J", J);
                    Matlab.PutVector("TEST.M", univ.GetMasses(3));
                    Matlab.Execute("TEST.M = diag(TEST.M);");
                    /// f = m a
                    /// d = 1/2 a t^2
                    ///   = 0.5 f/m t^2
                    /// f = m a
                    ///   = 2 m d t^-2
                    ///
                    /// coord change
                    /// dcoord = 0.5 a t^2
                    ///        = (0.5 t^2) f/m
                    ///        = (0.5 t^2) M^-1 F  : M is mass matrix, F is the net force of each atom
                    ///
                    /// torsional angle change
                    /// dtor =           (J' M J)^-1 J' M * dcoord                  : (6) of TNM paper
                    ///      =           (J' M J)^-1 J' M * (0.5 t^2) M^-1 F
                    ///      = (0.5 t^2) (J' M J)^-1 J'                    F
                    ///      = (0.5 t^2) (J' M J)^-1 J' F
                    ///      = (0.5 t2)  invJMJ      JF
                    ///
                    /// force filtered by torsional ...
                    /// F_tor = m a
                    ///       = 2 m d t^-2
                    ///       = 2 M (J * dtor) t^-2
                    ///       = 2 M (J * (0.5 t^2) (J' M J)^-1 J' F) t^-2
                    ///       = M J (J' M J)^-1 J' F
                    ///       = MJ  invJMJ      JF
                    ///
                    /// coord change filtered by torsional
                    /// R_tor = (0.5 t^2) M^-1 * F_tor
                    ///       = (0.5 t^2) J (J' M J)^-1 J' F
                    ///       = (0.5 t2)  J invJMJ      JF
                    Matlab.Execute("TEST.JMJ    = TEST.J' * TEST.M * TEST.J;");
                    Matlab.Execute("TEST.invJMJ = inv(TEST.JMJ);");
                    Matlab.Execute("TEST.MJ     = TEST.M * TEST.J;");
                    Matlab.Execute("TEST.JF     = TEST.J' * TEST.F;");
                    Matlab.Execute("TEST.dtor   = (0.5 * TEST.t2) * TEST.invJMJ * TEST.JF;"); // (6) of TNM paper
                    Matlab.Execute("TEST.F_tor  = TEST.MJ * TEST.invJMJ * TEST.JF;");
                    Matlab.Execute("TEST.R_tor  = (0.5 * TEST.t2) * TEST.J * TEST.invJMJ * TEST.JF;");

                    dangles = Matlab.GetVector("TEST.dtor");
                    if (forcesProjectedByTorsional != null)
                    {
                        Vector F_tor = Matlab.GetVector("TEST.F_tor");
                        HDebug.Assert(F_tor.Size == forces.Length * 3);
                        forcesProjectedByTorsional.value = new Vector[forces.Length];
                        for (int i = 0; i < forces.Length; i++)
                        {
                            int i3 = i * 3;
                            forcesProjectedByTorsional.value[i] = new double[] { F_tor[i3 + 0], F_tor[i3 + 1], F_tor[i3 + 2] };
                        }
                    }
                    if (dcoordsProjectedByTorsional != null)
                    {
                        Vector R_tor = Matlab.GetVector("TEST.R_tor");
                        HDebug.Assert(R_tor.Size == coords.Length * 3);
                        dcoordsProjectedByTorsional.value = new Vector[coords.Length];
                        for (int i = 0; i < coords.Length; i++)
                        {
                            int i3 = i * 3;
                            dcoordsProjectedByTorsional.value[i] = new double[] { R_tor[i3 + 0], R_tor[i3 + 1], R_tor[i3 + 2] };
                        }
                    }
                    Matlab.Clear("TEST");
                }

                return(dangles);
            }
Beispiel #11
0
            public static HessInfo GetHessSbNMA
                (Universe univ
                , IList <Vector> coords
                , double nbondMaxDist // =12
                , double?maxAbsSpring
                , bool b_bonds
                , bool b_angles
                , bool b_impropers
                , bool b_dihedrals
                , bool b_nonbondeds
                , bool b_nonbonded14s
                , double?sca_bonds
                , double?sca_angles
                , double?sca_impropers
                , double?sca_dihedrals
                , double?sca_nonbondeds
                , double?sca_nonbonded14s
                , Action <Universe.Atom, Vector, Universe.Atom, Vector, double> collectorBond
                , Action <Universe.Atom, Vector, Universe.Atom, Vector, Universe.Atom, Vector, double, double> collectorAngle
                , Action <Universe.Atom, Vector, Universe.Atom, Vector, Universe.Atom, Vector, Universe.Atom, Vector, double, double> collectorImproper
                , Action <Universe.Atom, Vector, Universe.Atom, Vector, Universe.Atom, Vector, Universe.Atom, Vector, double, double> collectorDihedral
                , Action <Universe.Atom, Vector, Universe.Atom, Vector, double> collectorNonbonded
                , Action <Universe.Atom, Vector, Universe.Atom, Vector, double> collectorNonbonded14
                , Func <HessSpr.CustomKijInfo, double> GetCustomKij = null
                , params string[] options
                )
            {
                IEnumerable <Universe.Nonbonded>   nonbondeds   = null;
                IEnumerable <Universe.Nonbonded14> nonbonded14s = univ.nonbonded14s.GetEnumerable();

                if (options.Contains("TIP3P: tetrahedral hydrogen bonds"))
                {
                    nonbondeds = EnumNonbondeds(univ.atoms, coords, univ.size, nbondMaxDist, ListTip3pTetraHBond, options);
                }
                else if (options.Contains("TIP3P: near waters"))
                {
                    nonbondeds = EnumNonbondeds(univ.atoms, coords, univ.size, nbondMaxDist, ListTip3pNears, options);
                }
                else
                {
                    nonbondeds = EnumNonbondeds(univ.atoms, coords, univ.size, nbondMaxDist);
                }

                bool   vdW       = true;                    // use vdW
                bool   elec      = false;                   // ignore electrostatic
                double D         = double.PositiveInfinity; // dielectric constant for Tinker is "1"
                bool   ignNegSpr = true;                    // ignore negative spring (do not add the spring into hessian matrix)

                double?K_r     = null;                      // null for sbNMA, and 340.00  for ssNMA
                double?K_theta = null;                      // null for sbNMA, and 45.00   for ssNMA
                double?K_ub    = null;                      // null for sbNMA, and 10.00   for ssNMA
                double?K_psi   = null;                      // null for sbNMA, and 70.00   for ssNMA
                double?K_chi   = null;                      // null for sbNMA, and 1.00    for ssNMA
                double?n       = null;                      // null for sbNMA, and 1       for ssNMA
                string K_nbnd  = null;                      // null for sbNMA, and "Unif"  for ssNMA

                if (options.Contains("TIP3P: (vdW+elec) for OH,OO,HH"))
                {
                    K_nbnd = "TIP3P: (vdW+elec) for OH,OO,HH";
                }
                if (options.Contains("TIP3P: (vdW+elec) for OH"))
                {
                    K_nbnd = "TIP3P: (vdW+elec) for OH";
                }
                if (options.Contains("vdW:L79"))
                {
                    K_nbnd = "L79";
                }
                if (options.Contains("vdW:UnifSgn"))
                {
                    K_nbnd = "UnifSgn";
                }
                if (options.Contains("K_chi:1"))
                {
                    K_chi = 1;
                }

                HessMatrix hess = null;

                if (b_bonds)
                {
                    hess = STeM.GetHessBond(coords, univ.bonds, K_r: K_r, hessian: hess, collector: collectorBond);
                }
                if (b_angles)
                {
                    hess = STeM.GetHessAngle(coords, univ.angles, true, K_theta: K_theta, K_ub: K_ub, hessian: hess, collector: collectorAngle);
                }
                if (b_impropers)
                {
                    hess = STeM.GetHessImproper(coords, univ.impropers, K_psi: K_psi, hessian: hess, useArnaud96: true, collector: collectorImproper);
                }
                if (b_dihedrals)
                {
                    hess = STeM.GetHessDihedral(coords, univ.dihedrals, K_chi: K_chi, n: n, hessian: hess, useAbsSpr: true, useArnaud96: true, collector: collectorDihedral);
                }
                if (b_nonbondeds)
                {
                    hess = HessSpr.GetHessNonbond(coords, nonbondeds, D, K_nbnd: K_nbnd, hessian: hess, vdW: vdW, elec: elec, ignNegSpr: ignNegSpr, maxAbsSpring: maxAbsSpring, collector: collectorNonbonded, GetCustomKij: GetCustomKij);
                }
                if (b_nonbonded14s)
                {
                    hess = HessSpr.GetHessNonbond(coords, nonbonded14s, D, K_nbnd: K_nbnd, hessian: hess, vdW: vdW, elec: elec, ignNegSpr: ignNegSpr, maxAbsSpring: maxAbsSpring, collector: collectorNonbonded14, GetCustomKij: GetCustomKij);
                }

                if (sca_bonds != null)
                {
                    if (sca_bonds.Value != 1)
                    {
                        hess += (sca_bonds.Value - 1) * STeM.GetHessBond(coords, univ.bonds, K_r: K_r, hessian: null);
                    }
                }
                if (sca_angles != null)
                {
                    if (sca_angles.Value != 1)
                    {
                        hess += (sca_angles.Value - 1) * STeM.GetHessAngle(coords, univ.angles, true, K_theta: K_theta, K_ub: K_ub, hessian: null);
                    }
                }
                if (sca_impropers != null)
                {
                    if (sca_impropers.Value != 1)
                    {
                        hess += (sca_impropers.Value - 1) * STeM.GetHessImproper(coords, univ.impropers, K_psi: K_psi, hessian: null, useArnaud96: true);
                    }
                }
                if (sca_dihedrals != null)
                {
                    if (sca_dihedrals.Value != 1)
                    {
                        hess += (sca_dihedrals.Value - 1) * STeM.GetHessDihedral(coords, univ.dihedrals, K_chi: K_chi, n: n, hessian: null, useAbsSpr: true, useArnaud96: true);
                    }
                }
                if (sca_nonbondeds != null)
                {
                    if (sca_nonbondeds.Value != 1)
                    {
                        hess += (sca_nonbondeds.Value - 1) * HessSpr.GetHessNonbond(coords, nonbondeds, D, K_nbnd: K_nbnd, hessian: null, vdW: vdW, elec: elec, ignNegSpr: ignNegSpr, maxAbsSpring: maxAbsSpring);
                    }
                }
                if (sca_nonbonded14s != null)
                {
                    if (sca_nonbonded14s.Value != 1)
                    {
                        hess += (sca_nonbonded14s.Value - 1) * HessSpr.GetHessNonbond(coords, nonbonded14s, D, K_nbnd: K_nbnd, hessian: null, vdW: vdW, elec: elec, ignNegSpr: ignNegSpr, maxAbsSpring: maxAbsSpring);
                    }
                }

                //Hess.UpdateHessNaN(hess, coords);
                {
                    foreach (var bc_br_bval in hess.EnumBlocks())
                    {
                        int bc   = bc_br_bval.Item1;
                        int br   = bc_br_bval.Item2;
                        var bval = bc_br_bval.Item3;

                        if (coords[bc] == null)
                        {
                            throw new HException("have hess block for null-coord");
                        }
                        if (coords[br] == null)
                        {
                            throw new HException("have hess block for null-coord");
                        }
                        if (bval == null)
                        {
                            throw new HException();
                        }
                        for (int c = 0; c < bval.ColSize; c++)
                        {
                            for (int r = 0; r < bval.RowSize; r++)
                            {
                                double val = bval[c, r];
                                if (double.IsNaN(val))
                                {
                                    throw new HException("hess has nan element");
                                }
                                if (double.IsPositiveInfinity(val))
                                {
                                    throw new HException("hess has pos-inf element");
                                }
                                if (double.IsNegativeInfinity(val))
                                {
                                    throw new HException("hess has neg-inf element");
                                }
                            }
                        }
                    }
                }

                return(new HessInfo
                {
                    hess = hess,
                    mass = univ.GetMasses(),
                    atoms = univ.atoms.ToArray(),
                    coords = coords.HCloneVectors().ToArray(),
                    numZeroEigval = 6,
                });
            }