Example #1
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);
        }