public static Matrix3 RepairRotation(Matrix3 R) { Vector3 u; Double theta = Matrix3.AngleAndAxis(R, out u); Double absu = Vector3.Abs(u); u = u * (1.0 / absu); return(Matrix3.Rotation(u, theta)); }
private bool Iterate() { // random subunit int i = _rnd.Next(this.translation.Length); // save initial state this.translationm1[i] = this.translation[i]; this.rotationm1[i] = this.rotation[i]; // random translation double translationstep = 0.05; this.translation[i].X += RandomNorm() * translationstep; this.translation[i].Y += RandomNorm() * translationstep; this.translation[i].Z += RandomNorm() * translationstep; // random rotation double rotationstep = 0.0017; // ~0.1° in rad // random rotation axis (anisotropic, normalized) double phi, rxy; double z0 = -1.0 + 2.0 * _rnd.NextDouble(); rxy = Math.Sqrt(1 - z0 * z0); phi = _rnd.NextDouble() * 2.0 * Math.PI; Vector3 u = new Vector3(Math.Cos(phi) * rxy, Math.Sin(phi) * rxy, z0); // rotation matrix Matrix3 rot = Matrix3.Rotation(u, RandomNorm() * rotationstep); this.rotation[i] = rot * this.rotation[i]; // recalculate "energy" double E = ForceAndTorque(); CheckForClashes(true); E += Eclash; // accept or reject double recipr_kT = this.SimulationParameters.rkT; bool accepted = E < Elast || _rnd.NextDouble() < Math.Exp((Elast - E) * recipr_kT); // revert to previous state if rejected if (!accepted) { this.translation[i] = this.translationm1[i]; this.rotation[i] = this.rotationm1[i]; } else { Elast = E; } return(accepted); }
// calculate <R> public Double AveragedDistance(Vector3[] r1, Vector3[] r2, Double translation, Boolean FRETAveraged, Boolean shuffle, Double R0, Random rnd) { Vector3 rrand; Matrix3 Urand; Double t, uz, uxy, uphi, Emean, Rmean, R06 = Math.Pow(R0, 6.0); if (shuffle) { // random translation of 1 uz = -1.0 + rnd.NextDouble() * 2.0; uxy = Math.Sqrt(1.0 - uz * uz); uphi = rnd.NextDouble() * 2.0 * Math.PI; rrand = new Vector3(uxy * Math.Cos(uphi), uxy * Math.Sin(uphi), uz); rrand = rrand * translation; // random rotation of 2 uz = -1.0 + rnd.NextDouble() * 2.0; uxy = Math.Sqrt(1.0 - uz * uz); uphi = rnd.NextDouble() * 2.0 * Math.PI; Urand = Matrix3.Rotation(new Vector3(uxy * Math.Cos(uphi), uxy * Math.Sin(uphi), uz), 2.0 * Math.PI * rnd.NextDouble()); } else { rrand = new Vector3(); Urand = Matrix3.E; } if (FRETAveraged) { Emean = 0.0; for (Int32 j = 0; j < _nsamples; j++) { t = Vector3.SquareNormDiff(r1[rnd.Next(r1.Length - 1)] + rrand, Urand * r2[rnd.Next(r2.Length - 1)]); Emean += 1.0 / (1.0 + t * t * t / R06); } Emean /= ((Double)_nsamples); Rmean = R0 * Math.Pow((1.0 / Emean - 1.0), 1.0 / 6.0); } else { Rmean = 0.0; for (Int32 j = 0; j < _nsamples; j++) { Rmean += Math.Sqrt(Vector3.SquareNormDiff(r1[rnd.Next(r1.Length - 1)] + rrand, Urand * r2[rnd.Next(r2.Length - 1)])); } Rmean /= ((Double)NSamples); } return(Rmean); }
/// <summary> /// Randomly redistributes subunits until no clashes are detected /// </summary> public override double SetState() { Vector3 tshake; Vector3 ushake; double angleshake, uz, uxy, uphi; Matrix3 rotshake; int lastshaked; PrepareSimulation(); _originalstate = new SimulationResult() { InternalNumber = -1 }; for (int i = 0; i < _molecules.Count; i++) { translation[i] = new Vector3(0.0, 0.0, 0.0); rotation[i] = Matrix3.E; } do { for (int i = 1; i < _molecules.Count; i++) { lastshaked = 0; if (!_molecules[i].Selected) { tshake = (new Vector3(_rnd.NextDouble(), _rnd.NextDouble(), _rnd.NextDouble()) + (-0.5)) * 10.0; translation[i] += tshake; lastshaked = i; uz = -1.0 + _rnd.NextDouble() * 2.0; uxy = Math.Sqrt(1.0 - uz * uz); uphi = _rnd.NextDouble() * 2.0 * Math.PI; ushake = new Vector3(uxy * Math.Cos(uphi), uxy * Math.Sin(uphi), uz); angleshake = 2.0 * Math.PI * _rnd.NextDouble(); rotshake = Matrix3.Rotation(ushake, angleshake); rotation[i] = rotshake * rotation[i]; } else { translation[i] = translation[lastshaked] + _molecules[i].CM - _molecules[lastshaked].CM; rotation[i] = rotation[lastshaked]; } } }while (CheckForClashes(false)); return(ForceAndTorque()); }
/// <summary> /// Do one iteration /// </summary> /// <param name="normF">Sum of F*F</param> /// <param name="normT">Sum of T*T</param> /// <param name="K">Kinetic energy</param> /// <returns>Potential energy (before the iteration)</returns> private double Iterate(out double normF, out double normT, out double K) { double E, theta, thetaw, abst, absw; Molecule m; Vector3 force_i, torque_i, tmpt, v, w; Matrix3 tmpr; E = ForceAndTorque(); CheckForClashes(true); E += Eclash; normF = 0; normT = 0.0; K = 0.0; for (int i = 0; i < Nmolecules; i++) { m = _molecules[i]; tmpt = translationm1[i]; tmpr = rotation[i] * Matrix3.Transpose(rotationm1[i]); translationm1[i] = translation[i]; rotationm1[i] = rotation[i]; force_i = force[i]; normF += force_i * force_i; torque_i = torque[i]; normT += torque_i * torque_i; translation[i] = translation[i] * (2.0 - viscosity) - tmpt * (1.0 - viscosity) + force_i * (dt * dt / m.Mass); v = (translation[i] - tmpt) * 0.5 * rdt; K += 0.5 * m.Mass * (v * v); abst = torque_i.Normalize(); theta = dt * dt * abst / m.SimpleI; thetaw = Matrix3.AngleAndAxis(tmpr, out w); rotation[i] = Matrix3.Rotation(torque_i, theta) * Matrix3.Rotation(w, -thetaw * viscosity) * tmpr * rotation[i]; absw = thetaw * rdt; K += 0.5 * m.SimpleI * absw * absw; } return(E); }
public override SimulationResult Simulate() { double E, K, Etot, theta, abst, normF, normT; Molecule m; Vector3 tnorm; // select dt and do the first time step E = ForceAndTorque(); CheckForClashes(true); E = E + Eclash; dt = dr4dt / Math.Sqrt(2.0 * Math.Max(E, Nmolecules) / minmass) * SimulationParameters.TimeStepFactor; rdt = 1.0 / dt; Etot_last = E; double Mtot = 0.0, ktot = 0.0; for (int i = 0; i < Nmolecules; i++) { Mtot += _molecules[i].Mass; } for (int i = 0; i < kplus.Length; i++) { ktot += Math.Max(kplus[i], kminus[i]); } viscosity_per_dt = SimulationParameters.ViscosityFactor * 2.0 * dt * Math.Sqrt(ktot / Mtot); viscosity = viscosity_per_dt * dt; viscosity = Math.Max(minviscosity, viscosity); viscosity = Math.Min(maxviscosity, viscosity); for (int i = 0; i < Nmolecules; i++) { m = _molecules[i]; translationm1[i] = translation[i]; rotationm1[i] = rotation[i]; translation[i] += force[i] * (0.5 / m.Mass) * dt * dt; abst = Vector3.Abs(torque[i]); tnorm = torque[i] * (1.0 / abst); theta = 0.5 * dt * dt * abst / m.SimpleI; rotation[i] *= Matrix3.Rotation(tnorm, theta); } // main loop int niter = 0, maxniter; optimize_selected_now = (SimulationParameters.OptimizeSelected == OptimizeSelected.Selected || SimulationParameters.OptimizeSelected == OptimizeSelected.SelectedThenAll); if (SimulationParameters.OptimizeSelected == OptimizeSelected.SelectedThenAll) { maxniter = SimulationParameters.MaxIterations / 2; } else { maxniter = SimulationParameters.MaxIterations; } do { E = Iterate(out normF, out normT, out K); Etot = E + K; niter++; if ((niter << 28) == 0 || Eclash > 10.0 || Etot > Etot_last + maxdE) { Cleanup(ref Etot); } Etot_last = Etot; }while (((normF > SimulationParameters.FTolerance) || (normT > SimulationParameters.TTolerance) || (K > SimulationParameters.KTolerance * Nmolecules)) && (niter < maxniter)); // repeat if selected then all if (SimulationParameters.OptimizeSelected == OptimizeSelected.SelectedThenAll) { dt = dr4dt / Math.Sqrt(2.0 * Math.Max(E, Nmolecules) / minmass) * SimulationParameters.TimeStepFactor; rdt = 1.0 / dt; viscosity = SimulationParameters.ViscosityFactor * 2.0 * dt * Math.Sqrt(ktot / Mtot); viscosity = Math.Max(minviscosity, viscosity); viscosity = Math.Min(maxviscosity, viscosity); niter = 0; optimize_selected_now = false; do { E = Iterate(out normF, out normT, out K); Etot = E + K; niter++; if ((niter << 28) == 0 || Eclash > 10.0 || Etot > Etot_last + maxdE) { Cleanup(ref Etot); } Etot_last = Etot; }while (((normF > SimulationParameters.FTolerance) || (normT > SimulationParameters.TTolerance) || (K > SimulationParameters.KTolerance * Nmolecules)) && (niter < maxniter)); } SimulationResult sr = new SimulationResult(); sr.E = E; sr.Eclash = Eclash; sr.Ebond = Ebond; sr.Converged = (niter < SimulationParameters.MaxIterations); sr.Translation = new Vector3[Nmolecules]; sr.Rotation = new Matrix3[Nmolecules]; sr.ParentStructure = _originalstate.InternalNumber; sr.SimulationMethod = _originalstate.SimulationMethod | SimulationMethods.Docking; for (int i = 0; i < Nmolecules; i++) { sr.Translation[i] = Matrix3.Transpose(rotation[0]) * (translation[i] - translation[0]) - _molecules[i].CM + _molecules[0].CM; sr.Rotation[i] = Matrix3.RepairRotation(Matrix3.Transpose(rotation[0]) * rotation[i]); } sr.Molecules = _molecules; sr.CalculateBestFitTranslation(false); return(sr); }