public void GetForceElements(Vector[] coords, ForceField.IImproper ffimproper, out Tuple <int[], Vector[]>[] frcimproper)
        {
            double energy = 0;

            MatrixByArr[,] lhess = null;

            //lfrcfld = new List<ForceField.IForceField>(); lfrcfld.Add(new ForceField.MindyImproper());
            frcimproper = new Tuple <int[], Vector[]> [impropers.Count];
            {
                //ForceField.MindyImproper ffimproper = new ForceField.MindyImproper();
                for (int i = 0; i < impropers.Count; i++)
                {
                    int[]    ids     = new int[4];
                    Vector[] lcoords = new Vector[4];
                    ids[0] = impropers[i].atoms[0].ID; lcoords[0] = coords[ids[0]];
                    ids[1] = impropers[i].atoms[1].ID; lcoords[1] = coords[ids[1]];
                    ids[2] = impropers[i].atoms[2].ID; lcoords[2] = coords[ids[2]];
                    ids[3] = impropers[i].atoms[3].ID; lcoords[3] = coords[ids[3]];
                    Vector[] lforces = new Vector[4] {
                        new double[3], new double[3], new double[3], new double[3]
                    };
                    ffimproper.Compute(impropers[i], lcoords, ref energy, ref lforces, ref lhess);
                    frcimproper[i] = new Tuple <int[], Vector[]>(ids, lforces);
                }
            }
        }
        public void GetForceElements(Vector[] coords, ForceField.IDihedral ffdihedral, out Tuple <int[], Vector[]>[] frcdihedral)
        {
            double energy = 0;

            MatrixByArr[,] lhess = null;

            //lfrcfld = new List<ForceField.IForceField>(); lfrcfld.Add(new ForceField.MindyDihedral());
            frcdihedral = new Tuple <int[], Vector[]> [dihedrals.Count];
            {
                //ForceField.MindyDihedral ffdihedral = new ForceField.MindyDihedral();
                for (int i = 0; i < dihedrals.Count; i++)
                {
                    int[]    ids     = new int[4];
                    Vector[] lcoords = new Vector[4];
                    ids[0] = dihedrals[i].atoms[0].ID; lcoords[0] = coords[ids[0]];
                    ids[1] = dihedrals[i].atoms[1].ID; lcoords[1] = coords[ids[1]];
                    ids[2] = dihedrals[i].atoms[2].ID; lcoords[2] = coords[ids[2]];
                    ids[3] = dihedrals[i].atoms[3].ID; lcoords[3] = coords[ids[3]];
                    Vector[] lforces = new Vector[4] {
                        new double[3], new double[3], new double[3], new double[3]
                    };
                    ffdihedral.Compute(dihedrals[i], lcoords, ref energy, ref lforces, ref lhess);
                    frcdihedral[i] = new Tuple <int[], Vector[]>(ids, lforces);
                }
            }
        }
        public bool GetHess4PwIntrAct_selftest(List <ForceField.IForceField> frcflds, double frcfactor)
        {
            Vector[] coords = GetCoords();
            Vector[] forces = GetVectorsZero();
            MatrixByArr[,] hessian = new MatrixByArr[size, size];
            {
                for (int c = 0; c < size; c++)
                {
                    for (int r = 0; r < size; r++)
                    {
                        hessian[c, r] = new double[3, 3];
                    }
                }
            }
            Dictionary <string, object> cache = new Dictionary <string, object>();

            cache.Add("all nonbondeds", null);
            PwForceDecomposer forceij = null;
            double            energy  = GetPotentialNonbondeds(frcflds, coords, ref forces, ref hessian, cache, forceij);

            List <ForceField.IForceField> frcflds_nonbondeds = new List <ForceField.IForceField>();

            foreach (ForceField.INonbonded frcfld_nonbonded in SelectInFrcflds(frcflds, new List <ForceField.INonbonded>()))
            {
                frcflds_nonbondeds.Add(frcfld_nonbonded);
            }

            MatrixByArr[,] hess = GetHess4PwIntrAct(frcflds_nonbondeds, frcfactor);
            if (hess.GetLength(0) != hessian.GetLength(0))
            {
                return(false);
            }
            if (hess.GetLength(1) != hessian.GetLength(1))
            {
                return(false);
            }
            for (int i = 0; i < hess.GetLength(0); i++)
            {
                for (int j = 0; j < hess.GetLength(1); j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (hess[i, j].ColSize != hessian[i, j].ColSize)
                    {
                        return(false);
                    }
                    if (hess[i, j].RowSize != hessian[i, j].RowSize)
                    {
                        return(false);
                    }
                    if (HDebug.CheckTolerance(0.00000001, hess[i, j] - hessian[i, j]) == false)
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
        private static MatrixByArr[,] GetMassWeightedHess(MatrixByArr[,] hess, Vector mass, InfoPack extra = null)
        {
            //HDebug.Depreciated();
            HDebug.Assert(hess.GetLength(0) == hess.GetLength(1));
            int n = hess.GetLength(0);

            // mass weighted hessian
            // MH = M^(-1/2) * H * M^(-1/2)
            // MH_ij = H_IJ * sqrt(M[i] * M[j])
            MatrixByArr[,] mwhess = new MatrixByArr[n, n];
            {
                // mass weighted block hessian
                //Matrix[,] mbhess = new Matrix[n, n];
                for (int i = 0; i < n; i++)
                {
                    //mbhess[i, i] = new double[3, 3];
                    for (int j = 0; j < n; j++)
                    {
                        //if(i == j) continue;
                        HDebug.Assert(hess[i, j].ColSize == 3, hess[i, j].RowSize == 3);
                        mwhess[i, j] = hess[i, j] / Math.Sqrt(mass[i] * mass[j]);
                        //mbhess[i, i] -= mbhess[i, j];
                    }
                }
            }

            return(mwhess);
        }
Exemple #5
0
        public void GetPotentialBuildHessian(Vector[] coords, MatrixByArr[,] hess, ref MatrixByArr hessian)
        {
            int size = coords.GetLength(0);

            for (int c = 0; c < size * 3; c++)
            {
                for (int r = 0; r < size * 3; r++)
                {
                    hessian[c, r] = hess[c / 3, r / 3][c % 3, r % 3];
                }
            }

            hessian = (hessian + hessian.Tr()) / 2;

            for (int i = 0; i < size; i++)
            {
                hessian[i * 3 + 0, i *3 + 0] = 0;    hessian[i * 3 + 0, i *3 + 1] = 0;    hessian[i * 3 + 0, i *3 + 2] = 0;
                hessian[i * 3 + 1, i *3 + 0] = 0;    hessian[i * 3 + 1, i *3 + 1] = 0;    hessian[i * 3 + 1, i *3 + 2] = 0;
                hessian[i * 3 + 2, i *3 + 0] = 0;    hessian[i * 3 + 2, i *3 + 1] = 0;    hessian[i * 3 + 2, i *3 + 2] = 0;

                int c = i;
                for (int r = 0; r < size; r++)
                {
                    hessian[i * 3 + 0, i *3 + 0] -= hessian[c * 3 + 0, r *3 + 0]; hessian[i * 3 + 0, i *3 + 1] -= hessian[c * 3 + 0, r *3 + 1]; hessian[i * 3 + 0, i *3 + 2] -= hessian[c * 3 + 0, r *3 + 2];
                    hessian[i * 3 + 1, i *3 + 0] -= hessian[c * 3 + 1, r *3 + 0]; hessian[i * 3 + 1, i *3 + 1] -= hessian[c * 3 + 1, r *3 + 1]; hessian[i * 3 + 1, i *3 + 2] -= hessian[c * 3 + 1, r *3 + 2];
                    hessian[i * 3 + 2, i *3 + 0] -= hessian[c * 3 + 2, r *3 + 0]; hessian[i * 3 + 2, i *3 + 1] -= hessian[c * 3 + 2, r *3 + 1]; hessian[i * 3 + 2, i *3 + 2] -= hessian[c * 3 + 2, r *3 + 2];
                }
            }
        }
Exemple #6
0
        public static double GetPotentialUpdated_Compute <FFUNIT>(FFUNIT ffUnit, GetPotentialUpdated_ComputeFunc <FFUNIT> ffCompute
                                                                  , Vector[] coords0, Vector[] coords
                                                                  , Vector[] dforces
                                                                  , int[] buffIdx, Vector[] buffCoords, Vector[] buffForces
                                                                  , bool compOld, bool compNew
                                                                  )
            where FFUNIT : Universe.AtomPack
        {
            int length = ffUnit.atoms.Length;

            int   [] idx = buffIdx;    for (int i = 0; i < length; i++)
            {
                idx[i] = ffUnit.atoms[i].ID;
            }
            Vector[] lcoords = buffCoords;
            Vector[] lforces = buffForces;
            MatrixByArr[,] lhessian = null;
            double denergy = 0;

            if (compNew) //(compOpt == CompOpt.compBothOldNew || compOpt == CompOpt.compOnlyNew)
            {
                double lenergy = 0;
                for (int i = 0; i < length; i++)
                {
                    lcoords[i] = coords[idx[i]];
                }
                for (int i = 0; i < length; i++)
                {
                    lforces[i].SetZero();
                }
                ffCompute(ffUnit, lcoords, ref lenergy, ref lforces, ref lhessian);
                denergy += lenergy;
                HDebug.AssertTolerance(0.00000001, lforces.Take(length).Mean());
                for (int i = 0; i < length; i++)
                {
                    dforces[idx[i]] += lforces[i];
                }
            }
            if (compOld && coords0 != null) //(coords0 != null && (compOpt == CompOpt.compBothOldNew || compOpt == CompOpt.compOnlyOld))
            {
                double lenergy = 0;
                for (int i = 0; i < length; i++)
                {
                    lcoords[i] = coords0[idx[i]];
                }
                for (int i = 0; i < length; i++)
                {
                    lforces[i].SetZero();
                }
                ffCompute(ffUnit, lcoords, ref lenergy, ref lforces, ref lhessian);
                denergy -= lenergy;
                HDebug.AssertTolerance(0.00000001, lforces.Take(length).Mean());
                for (int i = 0; i < length; i++)
                {
                    dforces[idx[i]] -= lforces[i];
                }
            }
            return(denergy);
        }
Exemple #7
0
        public double GetPotential(List <ForceField.IForceField> frcflds, Vector[] coords, ref Vector[] forces, ref MatrixByArr hessian, Dictionary <string, object> cache, Vector[,] forceij = null, double[,] pwfrc = null, double[,] pwspr = null)
        {
            //forceij = new Vector[size, size];
            MatrixByArr[,] hess = null;
            if (hessian != null)
            {
                int size = coords.GetLength(0);
                hess = LinAlg.CreateMatrixArray(size, size, new double[3, 3]);
            }

            double energy            = 0;
            double energy_bonds      = GetPotentialBonds(frcflds, coords, ref forces, ref hess, cache, forceij, pwfrc, pwspr); energy += energy_bonds;
            double energy_angles     = GetPotentialAngles(frcflds, coords, ref forces, ref hess, cache, forceij, pwfrc, pwspr); energy += energy_angles;
            double energy_dihedrals  = GetPotentialDihedrals(frcflds, coords, ref forces, ref hess, cache, forceij, pwfrc, pwspr); energy += energy_dihedrals;
            double energy_impropers  = GetPotentialImpropers(frcflds, coords, ref forces, ref hess, cache, forceij, pwfrc, pwspr); energy += energy_impropers;
            double energy_nonbondeds = GetPotentialNonbondeds(frcflds, coords, ref forces, ref hess, cache, forceij, pwfrc, pwspr); energy += energy_nonbondeds;
            double energy_customs    = GetPotentialCustoms(frcflds, coords, ref forces, ref hess, cache, forceij, pwfrc, pwspr); energy += energy_customs;

            if (hess != null)
            {
                GetPotentialBuildHessian(coords, hess, ref hessian);
            }

            if (cache != null)
            {
                if (cache.ContainsKey("energy_bonds     ") == false)
                {
                    cache.Add("energy_bonds     ", 0);
                }
                cache["energy_bonds     "] = energy_bonds;
                if (cache.ContainsKey("energy_angles    ") == false)
                {
                    cache.Add("energy_angles    ", 0);
                }
                cache["energy_angles    "] = energy_angles;
                if (cache.ContainsKey("energy_dihedrals ") == false)
                {
                    cache.Add("energy_dihedrals ", 0);
                }
                cache["energy_dihedrals "] = energy_dihedrals;
                if (cache.ContainsKey("energy_impropers ") == false)
                {
                    cache.Add("energy_impropers ", 0);
                }
                cache["energy_impropers "] = energy_impropers;
                if (cache.ContainsKey("energy_nonbondeds") == false)
                {
                    cache.Add("energy_nonbondeds", 0);
                }
                cache["energy_nonbondeds"] = energy_nonbondeds;
                if (cache.ContainsKey("energy_customs   ") == false)
                {
                    cache.Add("energy_customs   ", 0);
                }
                cache["energy_customs   "] = energy_customs;
            }
            return(energy);
        }
        public void GetForceElements(Vector[] coords
                                     , ForceField.INonbonded ffnonbond
                                     , double nonbonds_maxdist
                                     , out Tuple <int[], Vector[]>[] frcnonbond
                                     , out Tuple <int[], Vector[]>[] frcnonbond14
                                     )
        {
            double energy = 0;

            MatrixByArr[,] lhess = null;

            //lfrcfld = new List<ForceField.IForceField>(); lfrcfld.Add(new ForceField.MindyNonbondedLennardJones(false));
            //lfrcfld = new List<ForceField.IForceField>(); lfrcfld.Add(new ForceField.MindyNonbondedElectrostatic());
            List <Tuple <int[], Vector[]> > _frcnonbond   = new List <Tuple <int[], Vector[]> >();
            List <Tuple <int[], Vector[]> > _frcnonbond14 = new List <Tuple <int[], Vector[]> >();

            {
                //List<ForceField.IForceField> frcfld_nonbondeds = new List<ForceField.IForceField>();
                //frcfld_nonbondeds.Add(new ForceField.MindyNonbondedLennardJones(false));
                //frcfld_nonbondeds.Add(new ForceField.MindyNonbondedElectrostatic());
                Universe.Nonbondeds_v1 nonbondeds = new Universe.Nonbondeds_v1(atoms, size, nonbonds_maxdist);
                nonbondeds.UpdateNonbondeds(coords, 0);

                foreach (Universe.Nonbonded nonbond in nonbondeds)
                {
                    int[]    ids     = new int[2];
                    Vector[] lcoords = new Vector[2];
                    ids[0] = nonbond.atoms[0].ID; lcoords[0] = coords[ids[0]];
                    ids[1] = nonbond.atoms[1].ID; lcoords[1] = coords[ids[1]];
                    Vector[] lforces = new Vector[2] {
                        new double[3], new double[3]
                    };
                    ffnonbond.Compute(nonbond, lcoords, ref energy, ref lforces, ref lhess);
                    //if((lforces[0].Dist2 == 0) || (lforces[1].Dist2 == 0))
                    //    continue;
                    _frcnonbond.Add(new Tuple <int[], Vector[]>(ids, lforces));
                }

                foreach (Universe.Nonbonded14 nonbond in nonbonded14s)
                {
                    int[]    ids     = new int[2];
                    Vector[] lcoords = new Vector[2];
                    ids[0] = nonbond.atoms[0].ID; lcoords[0] = coords[ids[0]];
                    ids[1] = nonbond.atoms[1].ID; lcoords[1] = coords[ids[1]];
                    Vector[] lforces = new Vector[2] {
                        new double[3], new double[3]
                    };
                    ffnonbond.Compute(nonbond, lcoords, ref energy, ref lforces, ref lhess);
                    //if((lforces[0].Dist2 == 0) || (lforces[1].Dist2 == 0))
                    //    continue;
                    _frcnonbond14.Add(new Tuple <int[], Vector[]>(ids, lforces));
                }
            }
            frcnonbond   = _frcnonbond.ToArray();
            frcnonbond14 = _frcnonbond14.ToArray();
        }
            public static double ComputeFunc(Vector[] coords, double[] info)
            {
                HDebug.Assert(info.Length == 4);
                double energy = 0;

                Vector[] forces = null;
                MatrixByArr[,] hessian = null;
                Compute(coords, ref energy, ref forces, ref hessian, info[0], info[1], info[2], info[3]);
                return(energy);
            }
Exemple #10
0
        public double GetPotentialBonds(List <ForceField.IForceField> frcflds, Vector[] coords, ref Vector[] forces, ref MatrixByArr[,] hessian,
                                        Dictionary <string, object> cache, PwForceDecomposer forceij, double[,] pwfrc = null, double[,] pwspr = null)
        {
            List <ForceField.IBond> frcfld_bonds = SelectInFrcflds(frcflds, new List <ForceField.IBond>());
            double energy = 0;

            if (frcfld_bonds.Count == 0)
            {
                return(energy);
            }

            double stat_min    = double.MaxValue;
            double stat_max    = double.MinValue;
            double netstat_min = double.MaxValue;
            double netstat_max = double.MinValue;

            Vector[] lcoords = new Vector[2];
            Vector[] lforces = (forces == null) ? null : new Vector[2];
            for (int i = 0; i < bonds.Count; i++)
            {
                int id0 = bonds[i].atoms[0].ID; lcoords[0] = coords[id0];
                int id1 = bonds[i].atoms[1].ID; lcoords[1] = coords[id1];
                foreach (ForceField.IBond frcfld in frcfld_bonds)
                {
                    if (forces != null)
                    {
                        lforces[0] = new double[3];
                        lforces[1] = new double[3];
                    }
                    MatrixByArr[,] lhess = (hessian == null) ? null : LinAlg.CreateMatrixArray(2, 2, new double[3, 3]);
                    frcfld.Compute(bonds[i], lcoords, ref energy, ref lforces, ref lhess, pwfrc, pwspr);
                    HDebug.Assert(double.IsNaN(energy) == false, double.IsInfinity(energy) == false);
                    if (forces != null)
                    {
                        forces[id0] += lforces[0];
                        forces[id1] += lforces[1];
                        forceij.AddBond(id0, id1, lcoords, lforces);
                        HDebug.AssertTolerance(0.00000001, lforces[0].Dist2 - lforces[1].Dist2);
                        double netstat = lforces[0].Dist2 + lforces[1].Dist2;
                        netstat_min = Math.Min(netstat_min, netstat);
                        netstat_max = Math.Max(netstat_max, netstat);
                        stat_min    = Math.Min(stat_min, lforces[0].Dist);
                        stat_max    = Math.Max(stat_max, lforces[0].Dist);
                        stat_min    = Math.Min(stat_min, lforces[1].Dist);
                        stat_max    = Math.Max(stat_max, lforces[1].Dist);
                    }
                    if (hessian != null)
                    {
                        hessian[id0, id0] += lhess[0, 0]; hessian[id0, id1] += lhess[0, 1];
                        hessian[id1, id0] += lhess[1, 0]; hessian[id1, id1] += lhess[1, 1];
                    }
                }
            }
            return(energy);
        }
Exemple #11
0
            public double ComputeFunc(Vector[] coords, double[] info)
            {
                HDebug.Assert(info.Length == 2);
                //Universe.Atom atom1 = (Universe.Atom)info[0];
                //Universe.Atom atom2 = (Universe.Atom)info[1];
                //double        radij = (double       )info[2];
                //double        epsij = (double       )info[3];
                double energy = 0;

                Vector[] forces = null;
                MatrixByArr[,] hessian = null;
                Compute(coords, ref energy, ref forces, ref hessian, info[0], info[1]);
                return(energy);
            }
        static void UpdateMassWeightedHess(Matrix hess, Vector mass)
        {
            if (HDebug.Selftest())
            //if(GetMassWeightedHess_selftest1)
            #region selftest
            {
                //HDebug.ToDo("replace examplt not to use blocked hessian matrix");
                //GetMassWeightedHess_selftest1 = false;
                MatrixByArr[,] _bhess = new MatrixByArr[2, 2];
                _bhess[0, 0]          = new double[3, 3] {
                    { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }
                };
                _bhess[0, 1] = _bhess[0, 0] + 10;
                _bhess[1, 0] = _bhess[0, 0] + 20;
                _bhess[1, 1] = _bhess[0, 0] + 30;
                Vector _mass = new double[2] {
                    2, 3
                };
                MatrixByArr _hess = MatrixByArr.FromMatrixArray(_bhess);

                Matrix _mwhess = GetMassWeightedHess(_hess, _mass);
                MatrixByArr[,] _mwbhess = GetMassWeightedHess(_bhess, _mass);

                HDebug.AssertTolerance(0.00000001, MatrixByArr.FromMatrixArray(_mwbhess) - _mwhess.ToArray());
            }
            #endregion

            HDebug.Exception(hess.ColSize == mass.Size);
            HDebug.Assert(hess.ColSize == hess.RowSize);
            HDebug.Assert(hess.ColSize % 3 == 0);

            Vector mass05 = mass.ToArray().HSqrt();

            // mass weighted hessian
            // MH = M^(-1/2) * H * M^(-1/2)
            // MH_ij = H_IJ * sqrt(M[i] * M[j])
            {
                // mass weighted block hessian
                for (int i = 0; i < hess.ColSize; i++)
                {
                    for (int j = 0; j < hess.RowSize; j++)
                    {
                        //if(i == j) continue;
                        hess[i, j] = hess[i, j] / (mass05[i] * mass05[j]);
                        //mbhess[i, i] -= mbhess[i, j];
                    }
                }
            }
        }
Exemple #13
0
            public static MatrixByArr GetJ(Universe univ, Vector[] coords, List <RotableInfo> rotInfos, string option = null)
            {
                switch (option)
                {
                case "mine":
                {
                    MatrixByArr[,] J = TNM_mine.GetJ(univ, coords, rotInfos, fnInv3x3: null);
                    double tolerance = 0.00001;
                    HDebug.Assert(CheckEckartConditions(univ, coords, rotInfos, J, tolerance: tolerance));
                    //if(Debug.IsDebuggerAttachedWithProb(0.1))
                    //{
                    //    Matrix J0 = Matrix.FromBlockmatrix(J);
                    //    Matrix J1 = Matrix.FromBlockmatrix(GetJ(univ, coords, rotInfos, option:"paper", useNamedLock:false));
                    //    Debug.AssertTolerance(0.00000001, J0 - J1);
                    //}
                    return(MatrixByArr.FromMatrixArray(J));
                }

                case "paper":
                {
                    MatrixByArr[,] J = TNM_paper.GetJ(univ, coords, rotInfos);
                    HDebug.Assert(CheckEckartConditions(univ, coords, rotInfos, J, 0.0000001));
                    return(MatrixByArr.FromMatrixArray(J));
                }

                case "mineopt":
                {
                    MatrixByArr J = TNM_mineopt.GetJ(univ, coords, rotInfos);
                    if (HDebug.IsDebuggerAttached && univ.GetMolecules().Length == 1)
                    {
                        MatrixByArr J0 = TNM.GetJ(univ, coords, rotInfos, option: "paper");
                        MatrixByArr dJ = J - J0;
                        //double tolerance = dJ.ToArray().HAbs().HToArray1D().Mean();
                        //double maxAbsDH  = dJ.ToArray().HAbs().HMax();
                        //if(tolerance == 0)
                        //    tolerance = 0.000001;
                        HDebug.AssertTolerance(0.00000001, dJ);
                    }
                    return(J);
                }

                case null:
                    // my implementation has smaller error while checking Eckart conditions
                    goto case "mineopt";
                }
                return(null);
            }
Exemple #14
0
            public static Vector EckartConditionTrans(Universe univ, MatrixByArr[,] J, int a)
            {
                int n = J.GetLength(0);
                // check Eckart condition
                // http://en.wikipedia.org/wiki/Eckart_conditions
                //////////////////////////////////////////////////////////////////////
                // 1. translational Eckart condition
                //    sum{i=1..n}{mi * Jia} = 0
                Vector mJ = new double[3];

                for (int i = 0; i < n; i++)
                {
                    double mi  = univ.atoms[i].Mass;
                    Vector Jia = J[i, a].HToVector();
                    mJ += mi * Jia;
                }
                return(mJ);
            }
        public void GetForceElements(Vector[] coords, ForceField.IBond ffbond, out Tuple <int[], Vector[]>[] frcbond)
        {
            double energy = 0;

            MatrixByArr[,] lhess = null;

            frcbond = new Tuple <int[], Vector[]> [bonds.Count];
            {
                //ForceField.MindyBond ffbond = new ForceField.MindyBond();
                for (int i = 0; i < bonds.Count; i++)
                {
                    int[]    ids     = new int[2];
                    Vector[] lcoords = new Vector[2];
                    ids[0] = bonds[i].atoms[0].ID; lcoords[0] = coords[ids[0]];
                    ids[1] = bonds[i].atoms[1].ID; lcoords[1] = coords[ids[1]];
                    Vector[] lforces = new Vector[2] {
                        new double[3], new double[3]
                    };
                    ffbond.Compute(bonds[i], lcoords, ref energy, ref lforces, ref lhess);
                    frcbond[i] = new Tuple <int[], Vector[]>(ids, lforces);
                }
            }
        }
        public void GetForceElements(Vector[] coords, ForceField.IAngle ffangle, out Tuple <int[], Vector[]>[] frcangle)
        {
            double energy = 0;

            MatrixByArr[,] lhess = null;

            frcangle = new Tuple <int[], Vector[]> [angles.Count];
            {
                //ForceField.MindyAngle ffangle = new ForceField.MindyAngle();
                for (int i = 0; i < angles.Count; i++)
                {
                    int[]    ids     = new int[3];
                    Vector[] lcoords = new Vector[3];
                    ids[0] = angles[i].atoms[0].ID; lcoords[0] = coords[ids[0]];
                    ids[1] = angles[i].atoms[1].ID; lcoords[1] = coords[ids[1]];
                    ids[2] = angles[i].atoms[2].ID; lcoords[2] = coords[ids[2]];
                    Vector[] lforces = new Vector[3] {
                        new double[3], new double[3], new double[3]
                    };
                    ffangle.Compute(angles[i], lcoords, ref energy, ref lforces, ref lhess);
                    frcangle[i] = new Tuple <int[], Vector[]>(ids, lforces);
                }
            }
        }
        public void GetPotentialParallel_MakeSumZero(MatrixByArr[,] hess)
        {
            HDebug.Assert(false);
            //for(int c=0; c<size*3; c++)
            //    for(int r=0; r<size*3; r++)
            //        hessian[c, r] = hess[c/3, r/3][c%3, r%3];

            //hessian = (hessian + hessian.Transpose())/2;

            //for(int i=0; i<size; i++)
            //{
            //    hessian[i*3+0, i*3+0] = 0; hessian[i*3+0, i*3+1] = 0; hessian[i*3+0, i*3+2] = 0;
            //    hessian[i*3+1, i*3+0] = 0; hessian[i*3+1, i*3+1] = 0; hessian[i*3+1, i*3+2] = 0;
            //    hessian[i*3+2, i*3+0] = 0; hessian[i*3+2, i*3+1] = 0; hessian[i*3+2, i*3+2] = 0;

            //    int c = i;
            //    for(int r=0; r<size; r++)
            //    {
            //        hessian[i*3+0, i*3+0] -= hessian[c*3+0, r*3+0]; hessian[i*3+0, i*3+1] -= hessian[c*3+0, r*3+1]; hessian[i*3+0, i*3+2] -= hessian[c*3+0, r*3+2];
            //        hessian[i*3+1, i*3+0] -= hessian[c*3+1, r*3+0]; hessian[i*3+1, i*3+1] -= hessian[c*3+1, r*3+1]; hessian[i*3+1, i*3+2] -= hessian[c*3+1, r*3+2];
            //        hessian[i*3+2, i*3+0] -= hessian[c*3+2, r*3+0]; hessian[i*3+2, i*3+1] -= hessian[c*3+2, r*3+1]; hessian[i*3+2, i*3+2] -= hessian[c*3+2, r*3+2];
            //    }
            //}
        }
Exemple #18
0
            public virtual void Compute(Universe.Angle angle, Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian, double[,] pwfrc = null, double[,] pwspr = null)
            {
                double Ktheta = angle.Ktheta;
                double Theta0 = angle.Theta0;
                double Kub    = angle.Kub;
                double S0     = angle.S0;

                Compute(coords, ref energy, ref forces, ref hessian, Ktheta, Theta0, Kub, S0, pwfrc, pwspr);
            }
Exemple #19
0
            public static void Compute(Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian,
                                       double Ktheta, double Theta0, double Kub, double S0, double[,] pwfrc = null, double[,] pwspr = null)
            {
                double lenergy, force02, spring02;

                Compute(coords, out lenergy, out force02, out spring02, Ktheta, Theta0, Kub, S0);
                ///////////////////////////////////////////////////////////////////////////////
                // energy
                energy += lenergy;
                ///////////////////////////////////////////////////////////////////////////////
                // force
                if (forces != null)
                {
                    Vector frc0, frc2;
                    GetForceVector(coords[0], coords[2], force02, out frc0, out frc2);
                    forces[0] += frc0;
                    forces[2] += frc2;
                }
                ///////////////////////////////////////////////////////////////////////////////
                // hessian
                if (hessian != null)
                {
                    hessian[0, 2] += GetHessianBlock(coords[0], coords[2], spring02, force02);
                    hessian[2, 0] += GetHessianBlock(coords[2], coords[0], spring02, force02);
                }
            }
Exemple #20
0
            public virtual void Compute(Universe.Nonbonded14 nonbonded, Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian, double[,] pwfrc = null, double[,] pwspr = null)
            {
                Universe.Atom atom1 = nonbonded.atoms[0];
                Universe.Atom atom2 = nonbonded.atoms[1];
                double        radi  = atom1.Rmin2_14; radi = (double.IsNaN(radi) == false) ? radi : atom1.Rmin2;
                double        radj  = atom2.Rmin2_14; radj = (double.IsNaN(radj) == false) ? radj : atom2.Rmin2;
                double        epsi  = atom1.eps_14;   epsi = (double.IsNaN(epsi) == false) ? epsi : atom1.epsilon;
                double        epsj  = atom2.eps_14;   epsj = (double.IsNaN(epsj) == false) ? epsj : atom2.epsilon;
                double        radij = (radi + radj);

                if (divideRadijByTwo)
                {
                    radij = radij / 2;
                }
                double epsij = Math.Sqrt(epsi * epsj);

                if (double.IsNaN(radij) || double.IsNaN(epsij))
                {
                    HDebug.Assert(false);
                    return;
                }
                Compute(coords, ref energy, ref forces, ref hessian, radij, epsij, pwfrc, pwspr);
            }
Exemple #21
0
            public static Vector EckartConditionRotat(Universe univ, Vector[] coords, MatrixByArr[,] J, int a)
            {
                int n = J.GetLength(0);
                // check Eckart condition
                // http://en.wikipedia.org/wiki/Eckart_conditions
                //////////////////////////////////////////////////////////////////////
                // 2. rotational Eckart condition
                //    sum{i=1..n}{mi * r0i x Jia} = 0,
                //    where 'x' is the cross product
                Vector mrJ = new double[3];

                for (int i = 0; i < n; i++)
                {
                    double mi  = univ.atoms[i].Mass;
                    Vector ri  = coords[univ.atoms[i].ID];
                    Vector Jia = J[i, a].HToVector();
                    mrJ += mi * LinAlg.CrossProd3(ri, Jia);
                }
                return(mrJ);
            }
Exemple #22
0
            public static bool CheckEckartConditions(Universe univ, Vector[] coords, List <RotableInfo> rotInfos, MatrixByArr[,] J, double tolerance = 0.00000001)
            {
                int n = univ.atoms.Count;
                int m = rotInfos.Count;

                //
                for (int a = 0; a < m; a++)
                {
                    // check Eckart condition
                    // http://en.wikipedia.org/wiki/Eckart_conditions
                    //////////////////////////////////////////////////////////////////////
                    // 1. translational Eckart condition
                    //    sum{i=1..n}{mi * Jia} = 0
                    Vector mJ = EckartConditionTrans(univ, J, a);
                    //Debug.AssertTolerance(tolerance, mJ);
                    if ((mJ[0] > tolerance) || (mJ[1] > tolerance) || (mJ[2] > tolerance))
                    {
                        return(false);
                    }
                    // 2. rotational Eckart condition
                    //    sum{i=1..n}{mi * r0i x Jia} = 0,
                    //    where 'x' is the cross product
                    Vector mrJ = EckartConditionRotat(univ, coords, J, a);
                    //Debug.AssertTolerance(tolerance, mrJ);
                    if ((mrJ[0] > tolerance) || (mrJ[1] > tolerance) || (mrJ[2] > tolerance))
                    {
                        return(false);
                    }
                }

                return(true);
            }
Exemple #23
0
            void Compute(Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian, double radij, double epsij, double[,] pwfrc = null, double[,] pwspr = null)
            {
                #region original source in mindy
                // if(dist > cut2) continue;
                //
                // double r = sqrt(dist);
                // double r_1 = 1.0/r;
                // double r_2 = r_1*r_1;
                // double r_6 = r_2*r_2*r_2;
                // double r_12 = r_6*r_6;
                // double switchVal = 1, dSwitchVal = 0;
                // if (dist > switch2) {
                //     double c2 = cut2 - dist;
                //     double c4 = c2*(cut2 + 2*dist - 3.0*switch2);
                //     switchVal = c2*c4*c1;
                //     dSwitchVal = c3*r*(c2*c2-c4);
                // }
                //
                // // get VDW constants
                // Index vdwtype2 = mol->atomvdwtype(ind2);
                // const LJTableEntry *entry;
                //
                // if (mol->check14excl(ind1,ind2))
                //     entry = ljTable->table_val_scaled14(vdwtype1, vdwtype2);
                // else
                //     entry = ljTable->table_val(vdwtype1, vdwtype2);
                // double vdwA = entry->A;
                // double vdwB = entry->B;
                // double AmBterm = (vdwA * r_6 - vdwB)*r_6;
                // Evdw += switchVal*AmBterm;
                // double force_r = ( switchVal * 6.0 * (vdwA*r_12 + AmBterm) *
                //                     r_1 - AmBterm*dSwitchVal )*r_1;
                //
                // // Electrostatics
                // double kqq = kq * mol->atomcharge(ind2);
                // double efac = 1.0-dist/cut2;
                // double prefac = kqq * r_1 * efac;
                // Eelec += prefac * efac;
                // force_r += prefac * r_1 * (r_1 + 3.0*r/cut2);
                //
                // tmpf -= force_r * dr;
                // nbrbox[j].force += force_r * dr;
                #endregion
                int idx1 = 0;
                int idx2 = 1;

                Vector diff = (coords[idx2] - coords[idx1]);

                double Evdw    = 0;
                double force_r = 0;

                double dist = diff.Dist2;

                if (dist > cut2)
                {
                    return;                                                        // if(dist > cut2) continue;
                }
                //                                                                 //
                double r = Math.Sqrt(dist);                                        // double r = sqrt(dist);
                double r_1 = 1.0 / r;                                              // double r_1 = 1.0/r;
                double r_2 = r_1 * r_1;                                            // double r_2 = r_1*r_1;
                double r_6 = r_2 * r_2 * r_2;                                      // double r_6 = r_2*r_2*r_2;
                double r_12 = r_6 * r_6;                                           // double r_12 = r_6*r_6;
                double switchVal = 1, dSwitchVal = 0;                              // double switchVal = 1, dSwitchVal = 0;
                if (dist > switch2)                                                // if (dist > switch2) {
                {
                    double c2 = cut2 - dist;                                       //     double c2 = cut2 - dist;
                    double c4 = c2 * (cut2 + 2 * dist - 3.0 * switch2);            //     double c4 = c2*(cut2 + 2*dist - 3.0*switch2);
                    switchVal  = c2 * c4 * c1;                                     //     switchVal = c2*c4*c1;
                    dSwitchVal = c3 * r * (c2 * c2 - c4);                          //     dSwitchVal = c3*r*(c2*c2-c4);
                }                                                                  // }
                //                                                                 //
                // get VDW constants                                               // // get VDW constants
                // Index vdwtype2 = mol->atomvdwtype(ind2);                        // Index vdwtype2 = mol->atomvdwtype(ind2);
                // const LJTableEntry *entry;                                      // const LJTableEntry *entry;
                //                                                                 //
                // if (mol->check14excl(ind1,ind2))                                // if (mol->check14excl(ind1,ind2))
                //     entry = ljTable->table_val_scaled14(vdwtype1, vdwtype2);    //     entry = ljTable->table_val_scaled14(vdwtype1, vdwtype2);
                // else                                                            // else
                //     entry = ljTable->table_val(vdwtype1, vdwtype2);             //     entry = ljTable->table_val(vdwtype1, vdwtype2);
                double vdwA    = 4 * epsij * Math.Pow(radij, 12);                  // double vdwA = entry->A;
                double vdwB    = 4 * epsij * Math.Pow(radij, 6);                   // double vdwB = entry->B;
                double AmBterm = (vdwA * r_6 - vdwB) * r_6;                        // double AmBterm = (vdwA * r_6 - vdwB)*r_6;
                Evdw    += switchVal * AmBterm;                                    // Evdw += switchVal*AmBterm;
                force_r += (switchVal * 6.0 * (vdwA * r_12 + AmBterm) *            // double force_r = ( switchVal * 6.0 * (vdwA*r_12 + AmBterm) *
                            r_1 - AmBterm * dSwitchVal) * r_1;                     //                     r_1 - AmBterm*dSwitchVal )*r_1;
                                                                                   //
                // // Electrostatics                                               // // Electrostatics
                // double kqq = kq * mol->atomcharge(ind2);                        // double kqq = kq * mol->atomcharge(ind2);
                // double efac = 1.0-dist/cut2;                                    // double efac = 1.0-dist/cut2;
                // double prefac = kqq * r_1 * efac;                               // double prefac = kqq * r_1 * efac;
                // Eelec += prefac * efac;                                         // Eelec += prefac * efac;
                // force_r += prefac * r_1 * (r_1 + 3.0*r/cut2);                   // force_r += prefac * r_1 * (r_1 + 3.0*r/cut2);

                HDebug.Assert(double.IsNaN(Evdw) == false, double.IsInfinity(Evdw) == false);
                energy += Evdw;
//System.Console.Write("" + Math.Min(idx1,idx2) + ", " + Math.Max(idx1,idx2) + " - vdw(" + Evdw + "), ");
                ///////////////////////////////////////////////////////////////////////////////
                // force
                if (forces != null)
                {
                    Vector force = diff * force_r;                                      // Vector tmppos = tmpbox[i].pos;
                                                                                        // Vector dr = nbrbox[j].pos - tmppos;
                    forces[idx1] -= force;                                              // tmpf -= force_r * dr;
                    forces[idx2] += force;                                              // nbrbox[j].force += force_r * dr;
                }
                ///////////////////////////////////////////////////////////////////////////////
                // hessian
                if (hessian != null)
                {
                    //Debug.Assert(false);
                    double dcoord = 0.0001;
                    HDebug.Assert(hessian.GetLength(0) == 2, hessian.GetLength(1) == 2);
                    NumericSolver.Derivative2(ComputeFunc, coords, dcoord, ref hessian, radij, epsij);
                }
            }
Exemple #24
0
                public static bool CheckEckartConditions(Universe univ, List <RotableInfo> rotInfos, MatrixByArr[,] J)
                {
                    int n = univ.atoms.Count;
                    int m = rotInfos.Count;

                    //
                    for (int a = 0; a < m; a++)
                    {
                        MatrixByArr mJ = new double[3, 1];
                        for (int i = 0; i < n; i++)
                        {
                            mJ += univ.atoms[i].Mass * J[i, a];
                        }
                        HDebug.AssertTolerance(0.00001, mJ);
                    }

                    return(true);
                }
Exemple #25
0
            public virtual void Compute(Universe.Improper improper, Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian, double[,] pwfrc = null, double[,] pwspr = null)
            {
                double Kchi  = improper.Kpsi;
                int    n     = improper.n;
                double delta = improper.psi0;

                Compute(coords, ref energy, ref forces, ref hessian, Kchi, n, delta, pwfrc, pwspr);
            }
Exemple #26
0
            public virtual void Compute(Universe.Dihedral dihedral, Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian, double[,] pwfrc = null, double[,] pwspr = null)
            {
                double Kchi  = dihedral.Kchi;
                double n     = dihedral.n;
                double delta = dihedral.delta;

                Compute(coords, ref energy, ref forces, ref hessian, Kchi, n, delta, pwfrc, pwspr);
            }
        public static void Derivative2 <INFO>(Func <Vector[], INFO, double> func, Vector[] x, double dx, ref MatrixByArr[,] dy2, INFO info)
        {
            // assume that (x[i].Size == 3)
            int size = x.Length;

            HDebug.Assert(dy2.GetLength(0) == size, dy2.GetLength(1) == size);
            double  dx2 = dx * dx;
            Vectors xx  = x;

            for (int i = 0; i < size; i++)
            {
                for (int di = 0; di < 3; di++)
                {
                    for (int j = 0; j < size; j++)
                    {
                        for (int dj = 0; dj < 3; dj++)
                        {
                            Vector[] x0 = xx.Clone(); x0[i][di] += dx; x0[j][dj] += dx; double y0 = func(x0, info);
                            Vector[] x1 = xx.Clone(); x1[i][di] -= dx; x1[j][dj] += dx; double y1 = func(x1, info);
                            Vector[] x2 = xx.Clone(); x2[i][di] += dx; x2[j][dj] -= dx; double y2 = func(x2, info);
                            Vector[] x3 = xx.Clone(); x3[i][di] -= dx; x3[j][dj] -= dx; double y3 = func(x3, info);
                            double   d2f_didj = (y0 - y1 - y2 + y3) / (4 * dx2);
                            dy2[i, j][di, dj] = d2f_didj;
                        }
                    }
                }
            }
        }
Exemple #28
0
            public static void Compute(Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian,
                                       double Kchi, double n, double delta, double[,] pwfrc = null, double[,] pwspr = null)
            {
                #region original source in mindy
                // double ComputeBonded::compute_dihedrals(const Vector *coords, Vector *f) const {
                //   double energy = 0.0;
                //   DihedralElem *dihedral = dihedrals;
                //   for (int i=0; i<ndihedrals; i++) {
                //     const Vector *pos0 = coords + dihedral->atom1;
                //     const Vector *pos1 = coords + dihedral->atom2;
                //     const Vector *pos2 = coords + dihedral->atom3;
                //     const Vector *pos3 = coords + dihedral->atom4;
                //     const Vector r12 = *pos0 - *pos1;
                //     const Vector r23 = *pos1 - *pos2;
                //     const Vector r34 = *pos2 - *pos3;
                //
                //     Vector dcosdA;
                //     Vector dcosdB;
                //     Vector dsindC;
                //     Vector dsindB;
                //     Vector f1, f2, f3;
                //
                //     Vector A, B, C;
                //     A.cross(r12, r23);
                //     B.cross(r23, r34);
                //     C.cross(r23, A);
                //
                //     double rA = A.length();
                //     double rB = B.length();
                //     double rC = C.length();
                //
                //     double cos_phi = (A*B)/(rA*rB);
                //     double sin_phi = (C*B)/(rC*rB);
                //
                //     // Normalize B
                //     rB = 1.0/rB;
                //     B *= rB;
                //
                //     double phi = -atan2(sin_phi, cos_phi);
                //
                //     if (fabs(sin_phi) > 0.1) {
                //       // Normalize A
                //       rA = 1.0/rA;
                //       A *= rA;
                //       dcosdA = rA*(cos_phi*A-B);
                //       dcosdB = rB*(cos_phi*B-A);
                //     }
                //     else {
                //       // Normalize C
                //       rC = 1.0/rC;
                //       C *= rC;
                //       dsindC = rC*(sin_phi*C-B);
                //       dsindB = rB*(sin_phi*B-C);
                //     }
                //
                //     int mult = dihedral->multiplicity;
                //     for (int j=0; j<mult; j++) {
                //       double k = dihedral->k[j];
                //       double n = dihedral->n[j];
                //       double delta = dihedral->delta[j];
                //       double K, K1;
                //       if (n) {
                //         K = k * (1.0+cos(n*phi + delta));
                //         K1 = -n*k*sin(n*phi + delta);
                //       }
                //       else {
                //         double diff = phi-delta;
                //         if (diff < -M_PI) diff += 2.0*M_PI;
                //         else if (diff > M_PI) diff -= 2.0*M_PI;
                //         K = k*diff*diff;
                //         K1 = 2.0*k*diff;
                //       }
                //       energy += K;
                //
                //       // forces
                //       if (fabs(sin_phi) > 0.1) {
                //         K1 = K1/sin_phi;
                //         f1.x += K1*(r23.y*dcosdA.z - r23.z*dcosdA.y);
                //         f1.y += K1*(r23.z*dcosdA.x - r23.x*dcosdA.z);
                //         f1.z += K1*(r23.x*dcosdA.y - r23.y*dcosdA.x);
                //
                //         f3.x += K1*(r23.z*dcosdB.y - r23.y*dcosdB.z);
                //         f3.y += K1*(r23.x*dcosdB.z - r23.z*dcosdB.x);
                //         f3.z += K1*(r23.y*dcosdB.x - r23.x*dcosdB.y);
                //
                //         f2.x += K1*(r12.z*dcosdA.y - r12.y*dcosdA.z
                //                  + r34.y*dcosdB.z - r34.z*dcosdB.y);
                //         f2.y += K1*(r12.x*dcosdA.z - r12.z*dcosdA.x
                //                  + r34.z*dcosdB.x - r34.x*dcosdB.z);
                //         f2.z += K1*(r12.y*dcosdA.x - r12.x*dcosdA.y
                //                  + r34.x*dcosdB.y - r34.y*dcosdB.x);
                //       }
                //       else {
                //         //  This angle is closer to 0 or 180 than it is to
                //         //  90, so use the cos version to avoid 1/sin terms
                //         K1 = -K1/cos_phi;
                //
                //         f1.x += K1*((r23.y*r23.y + r23.z*r23.z)*dsindC.x
                //                 - r23.x*r23.y*dsindC.y
                //                 - r23.x*r23.z*dsindC.z);
                //         f1.y += K1*((r23.z*r23.z + r23.x*r23.x)*dsindC.y
                //                 - r23.y*r23.z*dsindC.z
                //                 - r23.y*r23.x*dsindC.x);
                //         f1.z += K1*((r23.x*r23.x + r23.y*r23.y)*dsindC.z
                //                 - r23.z*r23.x*dsindC.x
                //                 - r23.z*r23.y*dsindC.y);
                //
                //         f3 += cross(K1,dsindB,r23);
                //
                //         f2.x += K1*(-(r23.y*r12.y + r23.z*r12.z)*dsindC.x
                //                +(2.0*r23.x*r12.y - r12.x*r23.y)*dsindC.y
                //                +(2.0*r23.x*r12.z - r12.x*r23.z)*dsindC.z
                //                +dsindB.z*r34.y - dsindB.y*r34.z);
                //         f2.y += K1*(-(r23.z*r12.z + r23.x*r12.x)*dsindC.y
                //                +(2.0*r23.y*r12.z - r12.y*r23.z)*dsindC.z
                //                +(2.0*r23.y*r12.x - r12.y*r23.x)*dsindC.x
                //                +dsindB.x*r34.z - dsindB.z*r34.x);
                //         f2.z += K1*(-(r23.x*r12.x + r23.y*r12.y)*dsindC.z
                //                +(2.0*r23.z*r12.x - r12.z*r23.x)*dsindC.x
                //                +(2.0*r23.z*r12.y - r12.z*r23.y)*dsindC.y
                //                +dsindB.y*r34.x - dsindB.x*r34.y);
                //       }
                //     }    // end loop over multiplicity
                //     f[dihedral->atom1] += f1;
                //     f[dihedral->atom2] += f2-f1;
                //     f[dihedral->atom3] += f3-f2;
                //     f[dihedral->atom4] += -f3;
                //
                //     dihedral++;
                //   }
                //   return energy;
                // }
                #endregion

                ///////////////////////////////////////////////////////////////////////////////
                // energy
                Vector pos0 = coords[0];                             //     const Vector *pos0 = coords + dihedral->atom1;
                Vector pos1 = coords[1];                             //     const Vector *pos1 = coords + dihedral->atom2;
                Vector pos2 = coords[2];                             //     const Vector *pos2 = coords + dihedral->atom3;
                Vector pos3 = coords[3];                             //     const Vector *pos3 = coords + dihedral->atom4;
                Vector r12  = pos0 - pos1;                           //     const Vector r12 = *pos0 - *pos1;
                Vector r23  = pos1 - pos2;                           //     const Vector r23 = *pos1 - *pos2;
                Vector r34  = pos2 - pos3;                           //     const Vector r34 = *pos2 - *pos3;
                                                                     //
                Vector dcosdA = null;                                //     Vector dcosdA;
                Vector dcosdB = null;                                //     Vector dcosdB;
                Vector dsindC = null;                                //     Vector dsindC;
                Vector dsindB = null;                                //     Vector dsindB;
                                                                     //
                Vector A, B, C;                                      //     Vector A, B, C;
                A = LinAlg.CrossProd(r12, r23);                      //     A.cross(r12, r23);
                B = LinAlg.CrossProd(r23, r34);                      //     B.cross(r23, r34);
                C = LinAlg.CrossProd(r23, A);                        //     C.cross(r23, A);
                //
                double rA = A.Dist;                                  //     double rA = A.length();
                double rB = B.Dist;                                  //     double rB = B.length();
                double rC = C.Dist;                                  //     double rC = C.length();
                //
                double cos_phi = LinAlg.DotProd(A, B) / (rA * rB);   //     double cos_phi = (A*B)/(rA*rB);
                double sin_phi = LinAlg.DotProd(C, B) / (rC * rB);   //     double sin_phi = (C*B)/(rC*rB);
                //
                // Normalize B                                       //     // Normalize B
                rB = 1.0 / rB;                                       //     rB = 1.0/rB;
                B *= rB;                                             //     B *= rB;
                                                                     //
                double phi = -Math.Atan2(sin_phi, cos_phi);          //     double phi = -atan2(sin_phi, cos_phi);
                                                                     //
                if (Math.Abs(sin_phi) > 0.1)                         //     if (fabs(sin_phi) > 0.1) {
                // Normalize A                                       //       // Normalize A
                {
                    rA     = 1.0 / rA;                               //       rA = 1.0/rA;
                    A     *= rA;                                     //       A *= rA;
                    dcosdA = rA * (cos_phi * A - B);                 //       dcosdA = rA*(cos_phi*A-B);
                    dcosdB = rB * (cos_phi * B - A);                 //       dcosdB = rB*(cos_phi*B-A);
                }                                                    //     }
                else                                                 //     else {
                // Normalize C                                       //       // Normalize C
                {
                    rC     = 1.0 / rC;                               //       rC = 1.0/rC;
                    C     *= rC;                                     //       C *= rC;
                    dsindC = rC * (sin_phi * C - B);                 //       dsindC = rC*(sin_phi*C-B);
                    dsindB = rB * (sin_phi * B - C);                 //       dsindB = rB*(sin_phi*B-C);
                }                                                    //     }
                                                                     //
                //int mult = dihedral->multiplicity;                 //     int mult = dihedral->multiplicity;
                //for (int j=0; j<mult; j++) {                       //     for (int j=0; j<mult; j++) {
                //double k = dihedral->k[j];                         //       double k = dihedral->k[j];
                //double n = dihedral->n[j];                         //       double n = dihedral->n[j];
                //double delta = dihedral->delta[j];                 //       double delta = dihedral->delta[j];
                double K, K1;                                        //       double K, K1;
                if (n != 0)                                          //       if (n) {
                {
                    K  = Kchi * (1.0 + Math.Cos(n * phi + delta));   //         K = k * (1.0+cos(n*phi + delta));
                    K1 = -n *Kchi *Math.Sin(n *phi + delta);         //         K1 = -n*k*sin(n*phi + delta);
                }                                                    //       }
                else                                                 //       else {
                {
                    double diff = phi - delta;                       //         double diff = phi-delta;
                    if (diff < -Math.PI)
                    {
                        diff += 2.0 * Math.PI;                       //         if (diff < -M_PI) diff += 2.0*M_PI;
                    }
                    else if (diff > Math.PI)
                    {
                        diff -= 2.0 * Math.PI;                       //         else if (diff > M_PI) diff -= 2.0*M_PI;
                    }
                    K  = Kchi * diff * diff;                         //         K = k*diff*diff;
                    K1 = 2.0 * Kchi * diff;                          //         K1 = 2.0*k*diff;
                }                                                    //       }
                HDebug.Assert(double.IsNaN(K) == false, double.IsInfinity(K) == false);
                energy += K;                                         //       energy += K;
                ///////////////////////////////////////////////////////////////////////////////
                // force
                if (forces != null)
                {
                    Vector f1 = new double[3];                                                        //     Vector f1, f2, f3;
                    Vector f2 = new double[3];                                                        //
                    Vector f3 = new double[3];                                                        //
                    // forces                                                     //       // forces
                    if (Math.Abs(sin_phi) > 0.1)                                                      //       if (fabs(sin_phi) > 0.1) {
                    {
                        K1     = K1 / sin_phi;                                                        //         K1 = K1/sin_phi;
                        f1[0] += K1 * (r23[1] * dcosdA[2] - r23[2] * dcosdA[1]);                      //         f1.x += K1*(r23.y*dcosdA.z - r23.z*dcosdA.y);
                        f1[1] += K1 * (r23[2] * dcosdA[0] - r23[0] * dcosdA[2]);                      //         f1.y += K1*(r23.z*dcosdA.x - r23.x*dcosdA.z);
                        f1[2] += K1 * (r23[0] * dcosdA[1] - r23[1] * dcosdA[0]);                      //         f1.z += K1*(r23.x*dcosdA.y - r23.y*dcosdA.x);
                                                                                                      //
                        f3[0] += K1 * (r23[2] * dcosdB[1] - r23[1] * dcosdB[2]);                      //         f3.x += K1*(r23.z*dcosdB.y - r23.y*dcosdB.z);
                        f3[1] += K1 * (r23[0] * dcosdB[2] - r23[2] * dcosdB[0]);                      //         f3.y += K1*(r23.x*dcosdB.z - r23.z*dcosdB.x);
                        f3[2] += K1 * (r23[1] * dcosdB[0] - r23[0] * dcosdB[1]);                      //         f3.z += K1*(r23.y*dcosdB.x - r23.x*dcosdB.y);
                                                                                                      //
                        f2[0] += K1 * (r12[2] * dcosdA[1] - r12[1] * dcosdA[2]                        //         f2.x += K1*(r12.z*dcosdA.y - r12.y*dcosdA.z
                                       + r34[1] * dcosdB[2] - r34[2] * dcosdB[1]);                    //                  + r34.y*dcosdB.z - r34.z*dcosdB.y);
                        f2[1] += K1 * (r12[0] * dcosdA[2] - r12[2] * dcosdA[0]                        //         f2.y += K1*(r12.x*dcosdA.z - r12.z*dcosdA.x
                                       + r34[2] * dcosdB[0] - r34[0] * dcosdB[2]);                    //                  + r34.z*dcosdB.x - r34.x*dcosdB.z);
                        f2[2] += K1 * (r12[1] * dcosdA[0] - r12[0] * dcosdA[1]                        //         f2.z += K1*(r12.y*dcosdA.x - r12.x*dcosdA.y
                                       + r34[0] * dcosdB[1] - r34[1] * dcosdB[0]);                    //                  + r34.x*dcosdB.y - r34.y*dcosdB.x);
                    }                                                                                 //       }
                    else                                                                              //       else {
                    //  This angle is closer to 0 or 180 than it is to        //         //  This angle is closer to 0 or 180 than it is to
                    //  90, so use the cos version to avoid 1/sin terms       //         //  90, so use the cos version to avoid 1/sin terms
                    {
                        K1 = -K1 / cos_phi;                                                           //         K1 = -K1/cos_phi;
                                                                                                      //
                        f1[0] += K1 * ((r23[1] * r23[1] + r23[2] * r23[2]) * dsindC[0]                //         f1.x += K1*((r23.y*r23.y + r23.z*r23.z)*dsindC.x
                                       - r23[0] * r23[1] * dsindC[1]                                  //                 - r23.x*r23.y*dsindC.y
                                       - r23[0] * r23[2] * dsindC[2]);                                //                 - r23.x*r23.z*dsindC.z);
                        f1[1] += K1 * ((r23[2] * r23[2] + r23[0] * r23[0]) * dsindC[1]                //         f1.y += K1*((r23.z*r23.z + r23.x*r23.x)*dsindC.y
                                       - r23[1] * r23[2] * dsindC[2]                                  //                 - r23.y*r23.z*dsindC.z
                                       - r23[1] * r23[0] * dsindC[0]);                                //                 - r23.y*r23.x*dsindC.x);
                        f1[2] += K1 * ((r23[0] * r23[0] + r23[1] * r23[1]) * dsindC[2]                //         f1.z += K1*((r23.x*r23.x + r23.y*r23.y)*dsindC.z
                                       - r23[2] * r23[0] * dsindC[0]                                  //                 - r23.z*r23.x*dsindC.x
                                       - r23[2] * r23[1] * dsindC[1]);                                //                 - r23.z*r23.y*dsindC.y);
                                                                                                      //
                        f3 += K1 * LinAlg.CrossProd(dsindB, r23);                                     //         f3 += cross(K1,dsindB,r23);
                                                                                                      //
                        f2[0] += K1 * (-(r23[1] * r12[1] + r23[2] * r12[2]) * dsindC[0]               //         f2.x += K1*(-(r23.y*r12.y + r23.z*r12.z)*dsindC.x
                                       + (2.0 * r23[0] * r12[1] - r12[0] * r23[1]) * dsindC[1]        //                +(2.0*r23.x*r12.y - r12.x*r23.y)*dsindC.y
                                       + (2.0 * r23[0] * r12[2] - r12[0] * r23[2]) * dsindC[2]        //                +(2.0*r23.x*r12.z - r12.x*r23.z)*dsindC.z
                                       + dsindB[2] * r34[1] - dsindB[1] * r34[2]);                    //                +dsindB.z*r34.y - dsindB.y*r34.z);
                        f2[1] += K1 * (-(r23[2] * r12[2] + r23[0] * r12[0]) * dsindC[1]               //         f2.y += K1*(-(r23.z*r12.z + r23.x*r12.x)*dsindC.y
                                       + (2.0 * r23[1] * r12[2] - r12[1] * r23[2]) * dsindC[2]        //                +(2.0*r23.y*r12.z - r12.y*r23.z)*dsindC.z
                                       + (2.0 * r23[1] * r12[0] - r12[1] * r23[0]) * dsindC[0]        //                +(2.0*r23.y*r12.x - r12.y*r23.x)*dsindC.x
                                       + dsindB[0] * r34[2] - dsindB[2] * r34[0]);                    //                +dsindB.x*r34.z - dsindB.z*r34.x);
                        f2[2] += K1 * (-(r23[0] * r12[0] + r23[1] * r12[1]) * dsindC[2]               //         f2.z += K1*(-(r23.x*r12.x + r23.y*r12.y)*dsindC.z
                                       + (2.0 * r23[2] * r12[0] - r12[2] * r23[0]) * dsindC[0]        //                +(2.0*r23.z*r12.x - r12.z*r23.x)*dsindC.x
                                       + (2.0 * r23[2] * r12[1] - r12[2] * r23[1]) * dsindC[1]        //                +(2.0*r23.z*r12.y - r12.z*r23.y)*dsindC.y
                                       + dsindB[1] * r34[0] - dsindB[0] * r34[1]);                    //                +dsindB.y*r34.x - dsindB.x*r34.y);
                    }                                                                                 //       }
                    //}    // end loop over multiplicity                          //     }    // end loop over multiplicity
                    forces[0] += f1;                                                                  //     f[dihedral->atom1] += f1;
                    forces[1] += f2 - f1;                                                             //     f[dihedral->atom2] += f2-f1;
                    forces[2] += f3 - f2;                                                             //     f[dihedral->atom3] += f3-f2;
                    forces[3] += -f3;                                                                 //     f[dihedral->atom4] += -f3;
                }
                ///////////////////////////////////////////////////////////////////////////////
                // hessian
                if (hessian != null)
                {
                    //Debug.Assert(false);
                    double dcoord = 0.0001;
                    HDebug.Assert(hessian.GetLength(0) == 4, hessian.GetLength(1) == 4);
                    NumericSolver.Derivative2(ComputeFunc, coords, dcoord, ref hessian, Kchi, n, delta);
                }
            }
            public static void Compute(Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian,
                                       double Ktheta, double Theta0, double Kub, double S0, double[,] pwfrc = null, double[,] pwspr = null)
            {
                #region original source in mindy
                // double ComputeBonded::compute_angles(const Vector *coords, Vector *f) const {
                //   double energy = 0.0;
                //   AngleElem *angle = angles;
                //   for (int i=0; i<nangles; i++) {
                //     Vector f1, f2, f3;
                //     const Vector *pos1 = coords + angle->atom1;
                //     const Vector *pos2 = coords + angle->atom2;
                //     const Vector *pos3 = coords + angle->atom3;
                //     Vector r12 = *pos1 - *pos2;
                //     Vector r32 = *pos3 - *pos2;
                //     double d12 = r12.length();
                //     double d32 = r32.length();
                //     double cos_theta = (r12*r32)/(d12*d32);
                //     if (cos_theta > 1.0) cos_theta = 1.0;
                //     else if (cos_theta < -1.0) cos_theta = -1.0;
                //     double sin_theta = sqrt(1.0 - cos_theta * cos_theta);
                //     double theta = acos(cos_theta);
                //     double diff = theta-angle->theta0;
                //     energy += angle->k * diff * diff;
                //
                //     // forces
                //     double d12inv = 1.0/d12;
                //     double d32inv = 1.0/d32;
                //     diff *= (-2.0*angle->k) / sin_theta;
                //     double c1 = diff * d12inv;
                //     double c2 = diff * d32inv;
                //     Vector f12 = c1*(r12*(d12inv*cos_theta) - r32*d32inv);
                //     f1 = f12;
                //     Vector f32 = c2*(r32*(d32inv*cos_theta) - r12*d12inv);
                //     f3 = f32;
                //     f2 = -f12 - f32;
                //
                //     if (angle->k_ub > 0.0) {
                //       Vector r13 = r12 - r32;
                //       double d13 = r13.length();
                //       diff = d13 - angle->r_ub;
                //       energy += angle->k_ub * diff * diff;
                //
                //       // ub forces
                //       diff *= -2.0*angle->k_ub / d13;
                //       r13 *= diff;
                //       f1 += r13;
                //       f3 -= r13;
                //     }
                //     f[angle->atom1] += f1;
                //     f[angle->atom2] += f2;
                //     f[angle->atom3] += f3;
                //
                //     angle++;
                //   }
                //   return energy;
                // }
                #endregion

                ///////////////////////////////////////////////////////////////////////////////
                // energy
                Vector f1, f2, f3;
                Vector pos1      = coords[0];                               // const Vector *pos1 = coords + angle->atom1;
                Vector pos2      = coords[1];                               // const Vector *pos2 = coords + angle->atom2;
                Vector pos3      = coords[2];                               // const Vector *pos3 = coords + angle->atom3;
                Vector r12       = pos1 - pos2;                             // Vector r12 = *pos1 - *pos2;
                Vector r32       = pos3 - pos2;                             // Vector r32 = *pos3 - *pos2;
                Vector r13       = r12 - r32;                               // Vector r13 = r12 - r32;
                double d12       = r12.Dist;                                // double d12 = r12.length();
                double d32       = r32.Dist;                                // double d32 = r32.length();
                double d13       = r13.Dist;                                // double d13 = r13.length();
                double cos_theta = LinAlg.DotProd(r12, r32) / (d12 * d32);  // double cos_theta = (r12*r32)/(d12*d32);
                if (cos_theta > 1.0)
                {
                    cos_theta = 1.0;                                        // if (cos_theta > 1.0) cos_theta = 1.0;
                }
                else if (cos_theta < -1.0)
                {
                    cos_theta = -1.0;                                       // else if (cos_theta < -1.0) cos_theta = -1.0;
                }
                double sin_theta = Math.Sqrt(1.0 - cos_theta * cos_theta);  // double sin_theta = sqrt(1.0 - cos_theta * cos_theta);
                double theta     = Math.Acos(cos_theta);                    // double theta = acos(cos_theta);
                double diff      = theta - Theta0;                          // double diff = theta-angle->theta0;
                double diff_ub   = d13 - S0;                                // double diff_ub = d13 - angle->r_ub;
                HDebug.Assert(double.IsNaN(Ktheta * diff * diff) == false, double.IsInfinity(Ktheta * diff * diff) == false);
                energy += Ktheta * diff * diff;                             // energy += angle->k * diff * diff;
                if (Kub > 0.0)
                {                                                           //     if (angle->k_ub > 0.0) {
                    energy += Kub * diff_ub * diff_ub;                      //       energy += angle->k_ub * diff_ub * diff_ub;
                }                                                           //     }
                ///////////////////////////////////////////////////////////////////////////////
                // force
                //
                //
                // assume: * angle-change(p1,p2,p3) is close to zero
                //        -> angle-force(p1,p2,p3) is close to arc  p1-p3
                //        -> angle-force(p1,p2,p3) is close to line p1-q
                //        -> force magnitude p2-p1 = force p1-q / sin(p1,p2,p3)
                //           force magnitude p2-p3 = force p1-q / tan(p1,p2,p3)
                //        -> force p2->p1 = f21 = unitvec(p1-p2) * force p1-q / sin(p1,p2,p3)
                //           force p2->p3 = f23 = unitvec(p3-p2) * force p1-q / tan(p1,p2,p3)
                //        -> force p1     = f21
                //           force p3     = f23
                //           force p2     = -f21 + -f23
                //
                //           p1
                //         / |
                //       /   |
                //     /     |
                //  p2 ------+--p3
                //           q
                //
                if (forces != null)
                {
                    // forces                                               //     // forces
                    double d12inv = 1.0 / d12;                                     //     double d12inv = 1.0/d12;
                    double d32inv = 1.0 / d32;                                     //     double d32inv = 1.0/d32;
                    diff *= (-2.0 * Ktheta) / sin_theta;                           //     diff *= (-2.0*angle->k) / sin_theta;
                    double c1  = diff * d12inv;                                    //     double c1 = diff * d12inv;
                    double c2  = diff * d32inv;                                    //     double c2 = diff * d32inv;
                    Vector f12 = c1 * (r12 * (d12inv * cos_theta) - r32 * d32inv); //     Vector f12 = c1*(r12*(d12inv*cos_theta) - r32*d32inv);
                    f1 = f12;                                                      //     f1 = f12;
                    Vector f32 = c2 * (r32 * (d32inv * cos_theta) - r12 * d12inv); //     Vector f32 = c2*(r32*(d32inv*cos_theta) - r12*d12inv);
                    f3 = f32;                                                      //     f3 = f32;
                    f2 = -f12 - f32;                                               //     f2 = -f12 - f32;
                    //
                    if (Kub > 0.0)
                    {                                                       //     if (angle->k_ub > 0.0) {
                        // ub forces                                        //       // ub forces
                        double diff_ub_ = diff_ub * -2.0 * Kub / d13;       //       diff_ub *= -2.0*angle->k_ub / d13;
                        r13 *= diff_ub_;                                    //       r13 *= diff_ub;
                        f1  += r13;                                         //       f1 += r13;
                        f3  -= r13;                                         //       f3 -= r13;
                    }                                                       //     }
                    forces[0] += f1;                                        //     f[angle->atom1] += f1;
                    forces[1] += f2;                                        //     f[angle->atom2] += f2;
                    forces[2] += f3;                                        //     f[angle->atom3] += f3;
                }
                ///////////////////////////////////////////////////////////////////////////////
                // hessian
                if (hessian != null)
                {
                    //// !V(angle) = Ktheta(Theta - Theta0)**2
                    //Debug.Assert(false);
                    //// !V(Urey-Bradley) = Kub(S - S0)**2
                    //hessian[0, 2].Kij += 2 * Kub;
                    //hessian[0, 2].Fij += diff_ub * (2*Kub);
                    //hessian[2, 0].Kij += 2 * Kub;
                    //hessian[2, 0].Fij += diff_ub  * (2*Kub);

                    //Debug.Assert(false);
                    double dcoord = 0.0001;
                    HDebug.Assert(hessian.GetLength(0) == 3, hessian.GetLength(1) == 3);
                    NumericSolver.Derivative2(ComputeFunc, coords, dcoord, ref hessian, Ktheta, Theta0, Kub, S0);
                }
            }
Exemple #30
0
            public static void Compute(Vector[] coords, ref double energy, ref Vector[] forces, ref MatrixByArr[,] hessian,
                                       double Kchi, int n, double delta, double[,] pwfrc = null, double[,] pwspr = null)
            {
                double Kpsi = Kchi;

                HDebug.Assert(n == 0);
                double psi0 = delta;

                double lenergy, force03, spring03;

                Compute(coords, out lenergy, out force03, out spring03, Kpsi, psi0);
                ///////////////////////////////////////////////////////////////////////////////
                // energy
                energy += lenergy;
                ///////////////////////////////////////////////////////////////////////////////
                // force
                if (forces != null)
                {
                    Vector frc0, frc3;
                    GetForceVector(coords[0], coords[3], force03, out frc0, out frc3);
                    forces[0] += frc0;
                    forces[3] += frc3;
                }
                ///////////////////////////////////////////////////////////////////////////////
                // hessian
                if (hessian != null)
                {
                    hessian[0, 3] += GetHessianBlock(coords[0], coords[3], spring03, force03);
                    hessian[3, 0] += GetHessianBlock(coords[3], coords[0], spring03, force03);
                }
            }