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); }
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]; } } }
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); }
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); }
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); }
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]; } } } }
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); }
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]; // } //} }
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); }
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); } }
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); }
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); }
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); }
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); } }
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); }
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); }
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; } } } } }
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); } }
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); } }