Ejemplo n.º 1
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;
        }
Ejemplo n.º 2
0
        private void SaveSimulationResult(SimulationResult sr, String fname, Boolean addpdbsave)
        {
            String  converged = sr.Converged ? " (converged)" : " (not converged)";
            String  fullfname = fname + ".pml";
            Vector3 u; Double theta;

            using (StreamWriter sw = new StreamWriter(fullfname, false))
            {
                sw.WriteLine("# Energy = " + sr.E.ToString("F8") + converged);
                for (Int32 i = 0; i < molecules.Count; i++)
                {
                    sw.WriteLine("load " + molecules[i].FullFileName);
                }
                for (Int32 i = 1; i < molecules.Count; i++)
                {
                    theta = Matrix3.AngleAndAxis(sr.Rotation[i], out u) * 180.0 / Math.PI;
                    sw.WriteLine("rotate [" + u.ToString() + "], " + theta.ToString("F3")
                                 + ", " + molecules[i].Name + ", origin=[" + molecules[i].CM.ToString() + "]");
                    sw.WriteLine("translate [" + sr.Translation[i].ToString() + "], " + molecules[i].Name);
                }
                if (_bestfit)
                {
                    sw.WriteLine("select all");
                    sw.WriteLine("translate [" + sr.BestFitTranslation.ToString() + "], sele");
                    theta = Matrix3.AngleAndAxis(sr.BestFitRotation, out u) * 180.0 / Math.PI;
                    sw.WriteLine("rotate [" + u.ToString() + "], " + theta.ToString("F3")
                                 + ", sele, origin=[0, 0, 0]");
                }
                if (addpdbsave)
                {
                    sw.WriteLine("select all");
                    sw.WriteLine("save " + fname + ".pdb, sele");
                }
                String lpnames = "";
                if (lpcheckBox.Checked)
                {
                    Int32            im;
                    Vector3          r;
                    LabelingPosition lpref;
                    foreach (LabelingPosition l in labelingpos)
                    {
                        im = molecules.FindIndex(l.Molecule);
                        if ((sr.SimulationMethod & SimulationMethods.Refinement) != 0)
                        {
                            lpref = sr.RefinedLabelingPositions.Find(l.Name);
                        }
                        else
                        {
                            lpref = l;
                        }
                        r = sr.Rotation[im] * (lpref - molecules[im].CM) + molecules[im].CM + sr.Translation[im];
                        sw.WriteLine("pseudoatom " + l.Name + ", pos=[" + r.ToString() + "]");
                        sw.WriteLine("label " + l.Name + ", \"" + l.Name + "\"");
                        sw.WriteLine("show spheres, " + l.Name);
                        if (l.Dye == DyeType.Donor)
                        {
                            sw.WriteLine("color green, " + l.Name);
                        }
                        if (l.Dye == DyeType.Acceptor)
                        {
                            sw.WriteLine("color red, " + l.Name);
                        }
                        lpnames += " + " + l.Name;
                    }
                }
                if (_bestfit && lpnames != String.Empty)
                {
                    sw.WriteLine("deselect");
                    sw.WriteLine("select " + lpnames.Substring(3));
                    sw.WriteLine("translate [" + sr.BestFitTranslation.ToString() + "], sele");
                    theta = Matrix3.AngleAndAxis(sr.BestFitRotation, out u) * 180.0 / Math.PI;
                    sw.WriteLine("rotate [" + u.ToString() + "], " + theta.ToString("F3")
                                 + ", sele, origin=[0, 0, 0]");
                }
                sw.WriteLine("deselect");
                sw.Close();
            }
        }