Ejemplo n.º 1
0
def _displacement_mic(xyz, pairs, box_vectors, orthogonal):
    """Displacement vector between pairs of points in each frame under the
    minimum image convention for periodic boundary conditions.

    The computation follows scheme B.9 in Tukerman, M. "Statistical
    Mechanics: Theory and Molecular Simulation", 2010.

    This is a very slow pure python implementation, mostly for testing.
    """
    out = np.empty((xyz.shape[0], pairs.shape[0], 3), dtype=np.float32)
    for i in range(len(xyz)):
        bv1, bv2, bv3 = _reduce_box_vectors(box_vectors[i].T)
        hinv = np.linalg.inv(np.array([bv1, bv2, bv3]).T)

        for j, (a,b) in enumerate(pairs):
            r12 = xyz[i,b,:] - xyz[i,a,:]
            r12 -= bv3*round(r12[2]/bv3[2]);
            r12 -= bv2*round(r12[1]/bv2[1]);
            r12 -= bv1*round(r12[0]/bv1[0]);
            min_disp = r12
            dist2 = (r12*r12).sum()
            if not orthogonal:
                for ii in range(-1, 2):
                    v1 = bv1*ii
                    for jj in range(-1, 2):
                        v12 = bv2*jj+v1
                        for kk in range(-1, 2):
                            tmp = r12 + v12 + bv3*kk
                            new_dist2 = (tmp*tmp).sum()
                            if new_dist2 < dist2:
                                dist2 = new_dist2
                                min_disp = tmp
            out[i, j] = min_disp

    return out
Ejemplo n.º 2
0
def _distance_mic(xyz, pairs, box_vectors, orthogonal):
    """Distance between pairs of points in each frame under the minimum image
    convention for periodic boundary conditions.

    The computation follows scheme B.9 in Tukerman, M. "Statistical
    Mechanics: Theory and Molecular Simulation", 2010.

    This is a slow pure python implementation, mostly for testing.
    """
    out = np.empty((xyz.shape[0], pairs.shape[0]), dtype=np.float32)
    for i in range(len(xyz)):
        bv1, bv2, bv3 = _reduce_box_vectors(box_vectors[i].T)

        for j, (a,b) in enumerate(pairs):
            r12 = xyz[i,b,:] - xyz[i,a,:]
            r12 -= bv3*round(r12[2]/bv3[2]);
            r12 -= bv2*round(r12[1]/bv2[1]);
            r12 -= bv1*round(r12[0]/bv1[0]);
            dist = np.linalg.norm(r12)
            if not orthogonal:
                for ii in range(-1, 2):
                    v1 = bv1*ii
                    for jj in range(-1, 2):
                        v12 = bv2*jj + v1
                        for kk in range(-1, 2):
                            new_r12 = r12 + v12 + bv3*kk
                            dist = min(dist, np.linalg.norm(new_r12))
            out[i, j] = dist
    return out
Ejemplo n.º 3
0
def _displacement_mic(xyz, pairs, box_vectors, orthogonal):
    """Displacement vector between pairs of points in each frame under the
    minimum image convention for periodic boundary conditions.

    The computation follows scheme B.9 in Tukerman, M. "Statistical
    Mechanics: Theory and Molecular Simulation", 2010.

    This is a very slow pure python implementation, mostly for testing.
    """
    out = np.empty((xyz.shape[0], pairs.shape[0], 3), dtype=np.float32)
    for i in range(len(xyz)):
        hinv = np.linalg.inv(box_vectors[i])
        bv1, bv2, bv3 = box_vectors[i].T

        for j, (a,b) in enumerate(pairs):
            s1 = np.dot(hinv, xyz[i,a,:])
            s2 = np.dot(hinv, xyz[i,b,:])
            s12 = s2 - s1
            s12 = s12 - np.round(s12)
            disp = np.dot(box_vectors[i], s12)
            min_disp = disp
            dist2 = (disp*disp).sum()
            if not orthogonal:
                for ii in range(-1, 2):
                    v1 = bv1*ii
                    for jj in range(-1, 2):
                        v12 = bv2*jj+v1
                        for kk in range(-1, 2):
                            tmp = disp + v12 + bv3*kk
                            new_dist2 = (tmp*tmp).sum()
                            if new_dist2 < dist2:
                                dist2 = new_dist2
                                min_disp = tmp
            out[i, j] = min_disp

    return out
Ejemplo n.º 4
0
def _displacement_mic(xyz, pairs, box_vectors, orthogonal):
    """Displacement vector between pairs of points in each frame under the
    minimum image convention for periodic boundary conditions.

    The computation follows scheme B.9 in Tukerman, M. "Statistical
    Mechanics: Theory and Molecular Simulation", 2010.

    This is a very slow pure python implementation, mostly for testing.
    """
    out = np.empty((xyz.shape[0], pairs.shape[0], 3), dtype=np.float32)
    for i in range(len(xyz)):
        hinv = np.linalg.inv(box_vectors[i])
        bv1, bv2, bv3 = box_vectors[i].T

        for j, (a, b) in enumerate(pairs):
            s1 = np.dot(hinv, xyz[i, a, :])
            s2 = np.dot(hinv, xyz[i, b, :])
            s12 = s2 - s1
            s12 = s12 - np.round(s12)
            disp = np.dot(box_vectors[i], s12)
            min_disp = disp
            dist2 = (disp * disp).sum()
            if not orthogonal:
                for ii in range(-1, 2):
                    v1 = bv1 * ii
                    for jj in range(-1, 2):
                        v12 = bv2 * jj + v1
                        for kk in range(-1, 2):
                            tmp = disp + v12 + bv3 * kk
                            new_dist2 = (tmp * tmp).sum()
                            if new_dist2 < dist2:
                                dist2 = new_dist2
                                min_disp = tmp
            out[i, j] = min_disp

    return out
Ejemplo n.º 5
0
def compute_distances(traj, atom_pairs, periodic=True, opt=True):
    """Compute the distances between pairs of atoms in each frame.

    Parameters
    ----------
    traj : Trajectory
        An mtraj trajectory.
    atom_pairs : np.ndarray, shape=(num_pairs, 2), dtype=int
        Each row gives the indices of two atoms involved in the interaction.
    periodic : bool, default=True
        If `periodic` is True and the trajectory contains unitcell
        information, we will compute distances under the minimum image
        convention.
    opt : bool, default=True
        Use an optimized native library to calculate distances. Our optimized
        SSE minimum image convention calculation implementation is over 1000x
        faster than the naive numpy implementation.

    Returns
    -------
    distances : np.ndarray, shape=(n_frames, num_pairs), dtype=float
        The distance, in each frame, between each pair of atoms.
    """
    xyz = ensure_type(traj.xyz,
                      dtype=np.float32,
                      ndim=3,
                      name='traj.xyz',
                      shape=(None, None, 3),
                      warn_on_cast=False)
    pairs = ensure_type(atom_pairs,
                        dtype=np.int32,
                        ndim=2,
                        name='atom_pairs',
                        shape=(None, 2),
                        warn_on_cast=False)
    if not np.all(np.logical_and(pairs < traj.n_atoms, pairs >= 0)):
        raise ValueError('atom_pairs must be between 0 and %d' % traj.n_atoms)

    if len(pairs) == 0:
        return np.zeros((len(xyz), 0), dtype=np.float32)

    if periodic and traj._have_unitcell:
        out = np.empty((xyz.shape[0], pairs.shape[0]), dtype=np.float32)
        a = traj.unitcell_lengths[0][0] * 10.0
        b = traj.unitcell_lengths[0][1] * 10.0
        c = traj.unitcell_lengths[0][2] * 10.0
        cosalpha = math.cos(math.radians(traj.unitcell_angles[0][0]))
        cosbeta = math.cos(math.radians(traj.unitcell_angles[0][1]))
        cosgamma = math.cos(math.radians(traj.unitcell_angles[0][2]))
        for i in range(len(xyz)):
            for j, (ta, tb) in enumerate(pairs):
                x1 = xyz[0, ta, 0] * 10.0
                y1 = xyz[0, ta, 1] * 10.0
                z1 = xyz[0, ta, 2] * 10.0
                x2 = xyz[0, tb, 0] * 10.0
                y2 = xyz[0, tb, 1] * 10.0
                z2 = xyz[0, tb, 2] * 10.0
                #get min dist from all images
                dist = cal_dist(x1, y1, z1, x2, y2, z2, a, b, c, cosalpha,
                                cosbeta, cosgamma)
                dist = min(
                    dist,
                    cal_dist(x1 + 1, y1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1 - 1, y1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1, y1 + 1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1, y1 - 1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1 + 1, y1 + 1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1 + 1, y1 - 1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1 - 1, y1 + 1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                dist = min(
                    dist,
                    cal_dist(x1 - 1, y1 - 1, z1, x2, y2, z2, a, b, c, cosalpha,
                             cosbeta, cosgamma))
                #print("pair:", ta, tb)
                #print("final dist:",dist)
                out[i, j] = dist

        return out
    else:
        out = np.empty((xyz.shape[0], pairs.shape[0]), dtype=np.float32)
        return out