Example #1
0
        private void PrepareSimulation()
        {
            // molecules
            Nmolecules = _molecules.Count;
            int maxatomsincluster = 0;

            for (int i = 0; i < Nmolecules; i++)
            {
                minmass           = Math.Min(minmass, _molecules[i].Mass);
                maxatomsincluster = Math.Max(maxatomsincluster, _molecules[i].MaxAtomsInCluster);
            }

            // labeling positions
            int im;

            labelingpos_cm = new LabelingPositionList();
            labelingpos_cm.AddRange(this._labelingpositions);
            lpossim = new Vector3[labelingpos_cm.Count];
            LtoM    = new int[labelingpos_cm.Count];
            // convert to local coordinates
            for (int i = 0; i < labelingpos_cm.Count; i++)
            {
                im                 = _molecules.FindIndex(labelingpos_cm[i].Molecule);
                LtoM[i]            = im;
                labelingpos_cm[i] -= _molecules[im].CM;
                lpossim[i]         = labelingpos_cm[i];
            }

            // distances
            Distance dist_i;

            DtoL1      = new int[_distances.Count];
            DtoM1      = new int[_distances.Count];
            DtoL2      = new int[_distances.Count];
            DtoM2      = new int[_distances.Count];
            kplus      = new double[_distances.Count];
            kminus     = new double[_distances.Count];
            drmaxplus  = new double[_distances.Count];
            drmaxminus = new double[_distances.Count];
            double minerror = double.MaxValue;

            for (int i = 0; i < _distances.Count; i++)
            {
                DtoL1[i] = labelingpos_cm.FindIndex(_distances[i].Position1);
                DtoM1[i] = _molecules.FindIndex(labelingpos_cm.Find(_distances[i].Position1).Molecule);
                DtoL2[i] = labelingpos_cm.FindIndex(_distances[i].Position2);
                DtoM2[i] = _molecules.FindIndex(labelingpos_cm.Find(_distances[i].Position2).Molecule);

                // check if bond
                dist_i        = _distances[i];
                dist_i.IsBond = (labelingpos_cm[DtoL1[i]].Dye == DyeType.Unknown && labelingpos_cm[DtoL1[i]].AVData.AtomID > 0 &&
                                 labelingpos_cm[DtoL1[i]].AVData.AVType == AVSimlationType.None && labelingpos_cm[DtoL2[i]].Dye == DyeType.Unknown &&
                                 labelingpos_cm[DtoL2[i]].AVData.AtomID > 0 && labelingpos_cm[DtoL2[i]].AVData.AVType == AVSimlationType.None);
                _distances[i] = dist_i;

                // if bond, set small vdW radii to "exclude" from clashing
                if (dist_i.IsBond)
                {
                    foreach (var lp in new[] { labelingpos_cm[DtoL1[i]], labelingpos_cm[DtoL2[i]] })
                    {
                        int m     = _molecules.FindIndex(lp.Molecule);
                        int natom = Array.BinarySearch <int>(_molecules[m].OriginalAtomID, lp.AVData.AtomID);
                        _molecules[m].vdWR[natom] = AtomData.vdWRNoClash;
                        int natom_cluster = Array.FindIndex <int>(_molecules[m].ClusteredAtomOriginalIndex, n => n == natom);
                        if (natom_cluster >= 0)
                        {
                            _molecules[m].ClusteredAtomvdwR[natom_cluster] = AtomData.vdWRNoClash;
                            System.Runtime.InteropServices.Marshal.Copy(new[] { (float)AtomData.vdWRNoClash }, 0,
                                                                        FpsNativeWrapper.Aligned16(_molecules[m].XYZvdwRVectorArray) + (4 * natom_cluster + 3) * sizeof(float), 1);
                        }
                    }
                }

                // "spring constants"
                kplus[i]  = 2.0 / _distances[i].ErrPlus / _distances[i].ErrPlus;
                kminus[i] = 2.0 / _distances[i].ErrMinus / _distances[i].ErrMinus;
                //Console.Out.WriteLine("distance#" + i + " k+= " + kplus[i] + " k-= " + kminus[i] + " err+ " + _distances[i].ErrPlus + " err- " + _distances[i].ErrMinus);

                drmaxplus[i]  = SimulationParameters.MaxForce / kplus[i];
                drmaxminus[i] = -SimulationParameters.MaxForce / kminus[i];
                minerror      = Math.Min(minerror, Math.Min(_distances[i].ErrPlus, _distances[i].ErrMinus));
            }

            // simulation parameters
            kclash     = 2.0 / SimulationParameters.ClashTolerance / SimulationParameters.ClashTolerance;
            drmaxclash = -SimulationParameters.MaxForce / kclash;
            dr4dt      = Math.Min(SimulationParameters.ClashTolerance * 0.5, minerror);
        }
Example #2
0
        /// <summary>
        /// Calculate some additional parameters needed for simulations
        /// </summary>
        public void Prepare()
        {
            if (Error != "")
            {
                return;
            }

            // min/max values of local coordinates
            double xmin = 1.0e6, xmax = -1.0e6, ymin = 1.0e6, ymax = -1.0e6, zmin = 1.0e6, zmax = -1.0e6;

            for (int i = 0; i < NAtoms; i++)
            {
                xmin      = Math.Min(xmin, XLocal[i]);
                xmax      = Math.Max(xmax, XLocal[i]);
                ymin      = Math.Min(ymin, YLocal[i]);
                ymax      = Math.Max(ymax, YLocal[i]);
                zmin      = Math.Min(zmin, ZLocal[i]);
                zmax      = Math.Max(zmax, ZLocal[i]);
                MaxRadius = new Vector3(Math.Max(MaxRadius.X, Math.Sqrt(YLocal[i] * YLocal[i] + ZLocal[i] * ZLocal[i]) + vdWR[i]),
                                        Math.Max(MaxRadius.Y, Math.Sqrt(XLocal[i] * XLocal[i] + ZLocal[i] * ZLocal[i]) + vdWR[i]),
                                        Math.Max(MaxRadius.Z, Math.Sqrt(XLocal[i] * XLocal[i] + YLocal[i] * YLocal[i]) + vdWR[i]));
            }

            // moment(s) of inertia
            double ixx = 0.0, iyy = 0.0, izz = 0.0, ixy = 0.0, ixz = 0.0, iyz = 0.0;
            double m = 0.0, x2, y2, z2;

            for (int i = 0; i < NAtoms; i++)
            {
                m    = AtomMass[i];
                x2   = XLocal[i] * XLocal[i]; y2 = YLocal[i] * YLocal[i]; z2 = ZLocal[i] * ZLocal[i];
                ixx += m * (y2 + z2);
                iyy += m * (x2 + z2);
                izz += m * (x2 + y2);
                ixy -= m * XLocal[i] * YLocal[i];
                ixz -= m * XLocal[i] * ZLocal[i];
                iyz -= m * YLocal[i] * ZLocal[i];
            }
            SimpleI = Math.Max(Math.Max(ixx, ixy), ixz);
            FullI   = new Matrix3(ixx, ixy, ixz, ixy, iyy, iyz, ixz, iyz, izz);

            // clusters of clustersize^3 angstrom
            const double clustersize = 10.0;
            int          nx, ny, nz, nxoff, nyoff, nzoff;

            nx    = (int)(Math.Ceiling(xmax / clustersize) + Math.Ceiling(-xmin / clustersize));
            ny    = (int)(Math.Ceiling(ymax / clustersize) + Math.Ceiling(-ymin / clustersize));
            nz    = (int)(Math.Ceiling(zmax / clustersize) + Math.Ceiling(-zmin / clustersize));
            nxoff = (int)Math.Ceiling(-xmin / clustersize);
            nyoff = (int)Math.Ceiling(-ymin / clustersize);
            nzoff = (int)Math.Ceiling(-zmin / clustersize);
            int nclusters = nx * ny * nz;

            AtomCluster[] atomcluster_tmp = new AtomCluster[nx * ny * nz];

            // sort atoms
            // first run: count atoms in each cluster
            int    nc, cNAtomsmax = 0;
            double rcsize = 1.0 / clustersize;

            for (int i = 0; i < NAtoms; i++)
            {
                nc = (int)(ZLocal[i] * rcsize + nzoff) + nz * ((int)(YLocal[i] * rcsize + nyoff)
                                                               + ny * ((int)(XLocal[i] * rcsize + nxoff)));
                atomcluster_tmp[nc].NAtoms++;
                cNAtomsmax = Math.Max(cNAtomsmax, atomcluster_tmp[nc].NAtoms);
            }
            // allocate index arrays
            int ncfull = 0;

            int[][] originalatomindex = new int[nclusters][];
            for (nc = 0; nc < nclusters; nc++)
            {
                if (atomcluster_tmp[nc].NAtoms > 0)
                {
                    originalatomindex[nc] = new int[atomcluster_tmp[nc].NAtoms];
                    ncfull++;
                }
            }

            // fill
            int[] atomcounters = new int[nclusters];
            for (int i = 0; i < NAtoms; i++)
            {
                nc = (int)(ZLocal[i] * rcsize + nzoff) + nz * ((int)(YLocal[i] * rcsize + nyoff)
                                                               + ny * ((int)(XLocal[i] * rcsize + nxoff)));
                originalatomindex[nc][atomcounters[nc]++] = i;
            }
            // remove empty
            AtomClusters = new AtomCluster[ncfull];
            ncfull       = 0;
            for (nc = 0; nc < nclusters; nc++)
            {
                if (atomcluster_tmp[nc].NAtoms > 0)
                {
                    originalatomindex[ncfull] = originalatomindex[nc];
                    AtomClusters[ncfull++]    = atomcluster_tmp[nc];
                }
            }
            // optimize each
            double  rmax, cx, cy, cz;
            int     ilocal;
            Vector3 rlocal;

            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                // get the center
                cx = 0.0; cy = 0.0; cz = 0.0;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    cx    += XLocal[ilocal]; cy += YLocal[ilocal]; cz += ZLocal[ilocal];
                }
                cx /= (double)AtomClusters[nc].NAtoms;
                cy /= (double)AtomClusters[nc].NAtoms;
                cz /= (double)AtomClusters[nc].NAtoms;
                AtomClusters[nc].ClusterCenter = new Vector3(cx, cy, cz);

                // find the most distant atom
                rmax = -1.0;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    rlocal = new Vector3(cx - XLocal[ilocal], cy - YLocal[ilocal], cz - ZLocal[ilocal]);
                    rmax   = Math.Max(Vector3.Abs(rlocal) + vdWR[ilocal], rmax);
                }
                AtomClusters[nc].ClusterRadius = rmax;
            }
            // try an alternative method : find a pair of most distant atoms for each dimension, try as a center
            int    jlocal;
            double absr;

            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                rmax   = -1.0;
                rlocal = AtomClusters[nc];
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    cx     = XLocal[ilocal]; cy = YLocal[ilocal]; cz = ZLocal[ilocal];
                    for (int j = i + 1; j < AtomClusters[nc].NAtoms; j++)
                    {
                        jlocal = originalatomindex[nc][j];
                        rlocal = new Vector3(XLocal[jlocal] - cx, YLocal[jlocal] - cy, ZLocal[jlocal] - cz);
                        absr   = Vector3.Abs(rlocal);
                        if (rmax < absr + vdWR[ilocal] + vdWR[jlocal])
                        {
                            rmax   = absr + vdWR[ilocal] + vdWR[jlocal];
                            rlocal = (absr == 0.0) ? new Vector3(cx, cy, cz) :
                                     new Vector3(cx, cy, cz) + rlocal * ((0.5 * rmax - vdWR[ilocal]) / absr);
                        }
                    }
                }
                // find the most distant atom
                rmax = -1.0;
                cx   = rlocal.X; cy = rlocal.Y; cz = rlocal.Z;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    rlocal = new Vector3(cx - XLocal[ilocal], cy - YLocal[ilocal], cz - ZLocal[ilocal]);
                    rmax   = Math.Max(Vector3.Abs(rlocal) + vdWR[ilocal], rmax);
                }
                if (rmax < AtomClusters[nc].ClusterRadius)
                {
                    AtomClusters[nc].ClusterCenter = new Vector3(cx, cy, cz);
                    AtomClusters[nc].ClusterRadius = rmax;
                }
            }

#if DEBUG
            if (DebugData.SaveAtomClusters)
            {
                // for debugging: save clusters xyz
                using (StreamWriter sw = new StreamWriter(this.Name + ".cluster.xyz", false))
                {
                    sw.WriteLine(AtomClusters.Length.ToString());
                    sw.WriteLine("cluster");
                    for (int i = 0; i < AtomClusters.Length; i++)
                    {
                        sw.WriteLine("L" + i.ToString() + "  " + AtomClusters[i].ClusterCenter.X.ToString("F3") + "  "
                                     + AtomClusters[i].ClusterCenter.Y.ToString("F3") + "  " + AtomClusters[i].ClusterCenter.Z.ToString("F3"));
                    }
                    sw.Close();
                }
                using (StreamWriter sw = new StreamWriter(this.Name + ".cluster.pml", false))
                {
                    sw.WriteLine("select all");
                    sw.WriteLine("translate [" + CM.X.ToString("F3") + "," + CM.Y.ToString("F3")
                                 + "," + CM.Z.ToString("F3") + "]");
                    sw.WriteLine("deselect");
                    for (int i = 0; i < AtomClusters.Length; i++)
                    {
                        sw.WriteLine("alter (name L" + i.ToString() + "), vdw=" + AtomClusters[i].ClusterRadius.ToString("F3"));
                    }
                    sw.Close();
                }
            }
#endif

            /////////////////////////////////////////////////////////////////////////////////////////

            // remove atoms which can never be approached
            int       nnbr, nblocked = 0;
            double[]  xLocalnbr = new double[NAtoms];
            double[]  yLocalnbr = new double[NAtoms];
            double[]  zLocalnbr = new double[NAtoms];
            double[]  rthresh2 = new double[NAtoms];
            double[]  z2plus = new double[NAtoms];
            double[]  z2minus = new double[NAtoms];
            double    x0, y0, z0, rmin = AtomData.vdWRMin;
            Boolean[] atom_blocked = new Boolean[NAtoms];
            Boolean   accesible, zplus_blocked, zminus_blocked;

            double xg, yg, zg, rg, rxy, drmax, dtheta, dphi;

            for (int i = 0; i < NAtoms; i++)
            {
                accesible = false;
                x0        = XLocal[i]; y0 = YLocal[i]; z0 = ZLocal[i];
                rmax      = 2.0 * rmin + vdWR[i];
                // select neighbours within r1 + r2 + 2rmin
                nnbr = 0;
                for (int j = 0; j < NAtoms; j++)
                {
                    x2 = (XLocal[j] - x0) * (XLocal[j] - x0);
                    y2 = (YLocal[j] - y0) * (YLocal[j] - y0);
                    z2 = (ZLocal[j] - z0) * (ZLocal[j] - z0);
                    if (x2 + y2 + z2 < (rmax + vdWR[j]) * (rmax + vdWR[j]))
                    {
                        xLocalnbr[nnbr]  = XLocal[j] - x0;
                        yLocalnbr[nnbr]  = YLocal[j] - y0;
                        zLocalnbr[nnbr]  = ZLocal[j] - z0;
                        rthresh2[nnbr++] = (0.9 * rmin + vdWR[j]) * (0.9 * rmin + vdWR[j]);
                    }
                }
                // spherical grid
                rg     = vdWR[i] + rmin;
                drmax  = 0.1 * rmin / rg;
                nz     = (int)Math.Ceiling(Math.PI / drmax);
                dtheta = Math.PI / nz;
                for (double theta = Math.PI / 2.0; theta >= 0.0; theta -= dtheta)
                {
                    zg = rg * Math.Sin(theta);
                    for (int j = 0; j < nnbr; j++)
                    {
                        z2plus[j]  = (zLocalnbr[j] - zg) * (zLocalnbr[j] - zg);
                        z2minus[j] = (zLocalnbr[j] + zg) * (zLocalnbr[j] + zg);
                    }
                    rxy  = rg * Math.Cos(theta);
                    dphi = (rxy > 0.05 * rmin / Math.PI) ? 0.1 * rmin / rxy : 2.0 * Math.PI;
                    for (double phi = 0.0; phi <= 2.0 * Math.PI; phi += dphi)
                    {
                        xg = rxy * Math.Cos(phi);
                        yg = rxy * Math.Sin(phi);

                        // check all neighbours at zg and -zg
                        zplus_blocked  = false;
                        zminus_blocked = false;
                        for (int j = 0; j < nnbr; j++)
                        {
                            x2             = (xLocalnbr[j] - xg) * (xLocalnbr[j] - xg);
                            y2             = (yLocalnbr[j] - yg) * (yLocalnbr[j] - yg);
                            zplus_blocked  = zplus_blocked || (x2 + y2 + z2plus[j] < rthresh2[j]);
                            zminus_blocked = zminus_blocked || (x2 + y2 + z2minus[j] < rthresh2[j]);
                            if (zplus_blocked && zminus_blocked)
                            {
                                break;
                            }
                        }
                        accesible = accesible || (!zplus_blocked) || (!zminus_blocked);
                        if (accesible)
                        {
                            break;
                        }
                    }
                    if (accesible)
                    {
                        break;
                    }
                }
                atom_blocked[i] = !accesible;
                nblocked        = accesible ? nblocked : nblocked + 1;
            }

            // finally remove blocked atoms and reorder
            int ai = 0, unblocked = NAtoms - nblocked;
            MaxAtomsInCluster = 0;
            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                // first run: count blocked atoms
                nblocked = 0; // now in cluster nc
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    nblocked = atom_blocked[originalatomindex[nc][i]] ? nblocked + 1 : nblocked;
                }

                // second run: fill
                ai = 0;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    if (!atom_blocked[ilocal])
                    {
                        originalatomindex[nc][ai++] = ilocal;
                    }
                }
                AtomClusters[nc].NAtoms -= nblocked;
                MaxAtomsInCluster        = Math.Max(MaxAtomsInCluster, AtomClusters[nc].NAtoms);
            }

            // fill cluster arrays
            this.ClusteredAtomXYZ           = new Vector3[unblocked];
            this.ClusteredAtomvdwR          = new double[unblocked];
            this.ClusteredAtomOriginalIndex = new int[unblocked];
            if (XYZvdwRVectorArray != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(XYZvdwRVectorArray);
            }
            XYZvdwRVectorArray = Marshal.AllocHGlobal((unblocked + 1) * sizeof(float) * 4);
            float[] XYZvdwRdata = new float[unblocked * 4];
            int     idata = 0, idata4 = 0, oi;
            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                AtomClusters[nc].StartIndexInClusterArrays = idata;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    oi = originalatomindex[nc][i];
                    ClusteredAtomXYZ[idata]             = new Vector3(XLocal[oi], YLocal[oi], ZLocal[oi]);
                    ClusteredAtomvdwR[idata]            = vdWR[oi];
                    ClusteredAtomOriginalIndex[idata++] = oi;
                    XYZvdwRdata[idata4++] = (float)XLocal[oi];
                    XYZvdwRdata[idata4++] = (float)YLocal[oi];
                    XYZvdwRdata[idata4++] = (float)ZLocal[oi];
                    XYZvdwRdata[idata4++] = (float)vdWR[oi];
                }
            }
            Marshal.Copy(XYZvdwRdata, 0, FpsNativeWrapper.Aligned16(XYZvdwRVectorArray), XYZvdwRdata.Length);
            Prepared = true;
        }
Example #3
0
        // two molecules
        private Boolean CheckForClashes(int im1, int im2)
        {
            Molecule m1 = _molecules[im1];
            Molecule m2 = _molecules[im2];
            Vector3  dcm = translation[im1] - translation[im2], rc1, rc2;

            // check clusters
            Vector3[]   rc2cache = new Vector3[m2.AtomClusters.Length];
            double      sumr, dsq, dx2, dy2, dz2;
            Vector3     sumrv;
            AtomCluster c1, c2;
            Matrix3     rot1to2 = Matrix3.Transpose(rotation[im2]) * rotation[im1];
            Matrix3     rot2to1 = Matrix3.Transpose(rot1to2);
            Vector3     dcm1t   = Matrix3.Transpose(rotation[im1]) * dcm;
            Vector3     dcm2t   = Matrix3.Transpose(rotation[im2]) * dcm;

            int[] c2tocheck = new int[m2.AtomClusters.Length];
            int   j2, n2tocheck;

            int[] mustbechecked1 = new int[m1.AtomClusters.Length];
            int[] mustbechecked2 = new int[m2.AtomClusters.Length];

            // check if we can skip some of m2
            n2tocheck = 0;
            for (int j = 0; j < m2.AtomClusters.Length; j++)
            {
                c2    = m2.AtomClusters[j];
                rc2   = rot2to1 * c2 - dcm1t;
                dx2   = rc2.X * rc2.X;
                dy2   = rc2.Y * rc2.Y;
                dz2   = rc2.Z * rc2.Z;
                sumrv = m1.MaxRadius + c2.ClusterRadius;
                if ((dy2 + dz2 <= sumrv.X * sumrv.X) && (dx2 + dz2 <= sumrv.Y * sumrv.Y) && (dx2 + dy2 <= sumrv.Z * sumrv.Z))
                {
                    rc2cache[n2tocheck]    = c2;
                    c2tocheck[n2tocheck++] = j;
                }
            }

            for (int i = 0; i < m1.AtomClusters.Length; i++)
            {
                c1  = m1.AtomClusters[i];
                rc1 = rot1to2 * c1 + dcm2t;
                // if completely out of reach, skip the check
                dx2   = rc1.X * rc1.X;
                dy2   = rc1.Y * rc1.Y;
                dz2   = rc1.Z * rc1.Z;
                sumrv = m2.MaxRadius + c1.ClusterRadius;
                if ((dy2 + dz2 > sumrv.X * sumrv.X) || (dx2 + dz2 > sumrv.Y * sumrv.Y) || (dx2 + dy2 > sumrv.Z * sumrv.Z))
                {
                    continue;
                }
                // otherwise check selected clusters from m2
                for (int j = 0; j < n2tocheck; j++)
                {
                    j2   = c2tocheck[j];
                    rc2  = rc2cache[j];
                    c2   = m2.AtomClusters[j2];
                    dsq  = Vector3.SquareNormDiff(rc1, rc2);
                    sumr = c1.ClusterRadius + c2.ClusterRadius;
                    if (dsq < sumr * sumr) // clusters overlap, check all atoms
                    {
                        mustbechecked1[i]  = 1;
                        mustbechecked2[j2] = 1;
                        // clash |= CheckForClashes(c1, c2, im1, im2, dcm); // => replaced with unmanaged
                    }
                }
            }

            // this runs in m1's coordinate system!
            Vector3 fclash = new Vector3(), tclash1 = new Vector3(), tclash2 = new Vector3();
            double  dEClash = FpsNativeWrapper.CheckForClashes(FpsNativeWrapper.Aligned16(m1.XYZvdwRVectorArray),
                                                               FpsNativeWrapper.Aligned16(m2.XYZvdwRVectorArray), m1.AtomClusters, m2.AtomClusters,
                                                               m1.AtomClusters.Length, m2.AtomClusters.Length, mustbechecked1, mustbechecked2,
                                                               rot2to1, -dcm1t, kclash, ref fclash, ref tclash1, ref tclash2);

            force[im1]  += rotation[im1] * fclash;
            force[im2]  -= rotation[im1] * fclash;
            torque[im1] += rotation[im1] * tclash1;
            torque[im2] += rotation[im1] * tclash2;
            Eclash      += dEClash;

            return(dEClash > 1.0e-8);
        }