Ejemplo n.º 1
0
def test_random(it):
    rng = np.random.RandomState(seed=it)
    B = rng.uniform(-1, 1, (3, 3))
    R, H = minkowski_reduce(B)
    assert_allclose(H @ B, R, atol=TOL)
    assert np.sign(np.linalg.det(B)) == np.sign(np.linalg.det(R))

    norms = np.linalg.norm(R, axis=1)
    assert (np.argsort(norms) == range(3)).all()

    # Test idempotency
    _, _H = minkowski_reduce(R)
    assert (_H == np.eye(3).astype(int)).all()

    rcell, _ = Cell(B).minkowski_reduce()
    assert_allclose(rcell, R, atol=TOL)
Ejemplo n.º 2
0
    def test_pbc(self, pbc):
        lcell = self.lcell
        rcell, op = minkowski_reduce(lcell, pbc=pbc)
        assert_almost_equal(np.linalg.det(rcell), 1)

        rdet = np.linalg.det(rcell)
        ldet = np.linalg.det(lcell)
        assert np.sign(ldet) == np.sign(rdet)
Ejemplo n.º 3
0
    def test_1d(self, axis):
        lcell = self.lcell
        rcell, op = minkowski_reduce(lcell, pbc=np.roll([1, 0, 0], axis))
        assert (rcell == lcell).all()  # 1D reduction does nothing

        zcell = np.zeros((3, 3))
        zcell[0] = lcell[0]
        rcell, _ = Cell(zcell).minkowski_reduce()
        assert_allclose(rcell, zcell, atol=TOL)
Ejemplo n.º 4
0
    def test_2d(self, axis):
        lcell = self.lcell
        pbc = np.roll([0, 1, 1], axis)
        rcell, op = minkowski_reduce(lcell.astype(float), pbc=pbc)
        assert (rcell[axis] == lcell[axis]).all()

        zcell = np.copy(lcell)
        zcell[axis] = 0
        rzcell, _ = Cell(zcell).minkowski_reduce()
        rcell[axis] = 0
        assert_allclose(rzcell, rcell, atol=TOL)
Ejemplo n.º 5
0
    def _get_neighbors(self, dx: np.ndarray) -> Iterator[np.ndarray]:
        pbc = self.atoms.pbc
        if self.cell is None or not np.all(self.cell == self.atoms.cell):
            self.cell = self.atoms.cell.array.copy()
            rcell, self.op = minkowski_reduce(complete_cell(self.cell),
                                              pbc=pbc)
            self.rcell = Cell(rcell)
        dx_sc = dx @ self.rcell.reciprocal().T
        offset = np.zeros(3, dtype=np.int32)
        for _ in range(2):
            offset += pbc * ((dx_sc - offset) // 1.).astype(np.int32)

        for ts in product(*[np.arange(-1 * p, p + 1) for p in pbc]):
            yield (np.array(ts) - offset) @ self.op
Ejemplo n.º 6
0
import numpy as np
from ase.geometry import minkowski_reduce
from ase.cell import Cell

tol = 1E-14
rng = np.random.RandomState(0)
np.seterr(all='raise')

cell = Cell([[8.972058879514716, 0.0009788104586639142, 0.0005932485724084841],
             [4.485181755775297, 7.770520334862034, 0.00043663339838788054],
             [4.484671994095723, 2.5902066679984634, 16.25695615743613]])
cell.minkowski_reduce()

for i in range(40):
    B = rng.uniform(-1, 1, (3, 3))
    R, H = minkowski_reduce(B)
    assert np.allclose(H @ B, R, atol=tol)
    assert np.sign(np.linalg.det(B)) == np.sign(np.linalg.det(R))

    norms = np.linalg.norm(R, axis=1)
    assert (np.argsort(norms) == range(3)).all()

    # Test idempotency
    _, _H = minkowski_reduce(R)
    assert (_H == np.eye(3).astype(np.int)).all()

    rcell, _ = Cell(B).minkowski_reduce()
    assert np.allclose(rcell, R, atol=tol)

cell = np.array([[1, 1, 2], [0, 1, 4], [0, 0, 1]])
unimodular = np.array([[1, 2, 2], [0, 1, 2], [0, 0, 1]])
Ejemplo n.º 7
0
    def build(self, pbc, cell, coordinates):
        """Build the list.

        Coordinates are taken to be scaled or not according
        to self.use_scaled_positions.
        """
        self.pbc = pbc = np.array(pbc, copy=True)
        self.cell = cell = Cell(cell)
        self.coordinates = coordinates = np.array(coordinates, copy=True)

        if len(self.cutoffs) != len(coordinates):
            raise ValueError('Wrong number of cutoff radii: {0} != {1}'.format(
                len(self.cutoffs), len(coordinates)))

        if len(self.cutoffs) > 0:
            rcmax = self.cutoffs.max()
        else:
            rcmax = 0.0

        if self.use_scaled_positions:
            positions0 = cell.cartesian_positions(coordinates)
        else:
            positions0 = coordinates

        rcell, op = minkowski_reduce(cell, pbc)
        positions = wrap_positions(positions0, rcell, pbc=pbc, eps=0)

        natoms = len(positions)
        self.nneighbors = 0
        self.npbcneighbors = 0
        self.neighbors = [np.empty(0, int) for a in range(natoms)]
        self.displacements = [np.empty((0, 3), int) for a in range(natoms)]
        self.nupdates += 1
        if natoms == 0:
            return

        N = []
        ircell = np.linalg.pinv(rcell)
        for i in range(3):
            if self.pbc[i]:
                v = ircell[:, i]
                h = 1 / np.linalg.norm(v)
                n = int(2 * rcmax / h) + 1
            else:
                n = 0
            N.append(n)

        tree = cKDTree(positions, copy_data=True)
        offsets = cell.scaled_positions(positions - positions0)
        offsets = offsets.round().astype(np.int)

        for n1, n2, n3 in itertools.product(range(0, N[0] + 1),
                                            range(-N[1], N[1] + 1),
                                            range(-N[2], N[2] + 1)):
            if n1 == 0 and (n2 < 0 or n2 == 0 and n3 < 0):
                continue

            displacement = (n1, n2, n3) @ rcell
            for a in range(natoms):

                indices = tree.query_ball_point(positions[a] - displacement,
                                                r=self.cutoffs[a] + rcmax)
                if not len(indices):
                    continue

                indices = np.array(indices)
                delta = positions[indices] + displacement - positions[a]
                cutoffs = self.cutoffs[indices] + self.cutoffs[a]
                i = indices[np.linalg.norm(delta, axis=1) < cutoffs]
                if n1 == 0 and n2 == 0 and n3 == 0:
                    if self.self_interaction:
                        i = i[i >= a]
                    else:
                        i = i[i > a]

                self.nneighbors += len(i)
                self.neighbors[a] = np.concatenate((self.neighbors[a], i))

                disp = (n1, n2, n3) @ op + offsets[i] - offsets[a]
                self.npbcneighbors += disp.any(1).sum()
                self.displacements[a] = np.concatenate(
                    (self.displacements[a], disp))

        if self.bothways:
            neighbors2 = [[] for a in range(natoms)]
            displacements2 = [[] for a in range(natoms)]
            for a in range(natoms):
                for b, disp in zip(self.neighbors[a], self.displacements[a]):
                    neighbors2[b].append(a)
                    displacements2[b].append(-disp)
            for a in range(natoms):
                nbs = np.concatenate((self.neighbors[a], neighbors2[a]))
                disp = np.array(
                    list(self.displacements[a]) + displacements2[a])
                # Force correct type and shape for case of no neighbors:
                self.neighbors[a] = nbs.astype(int)
                self.displacements[a] = disp.astype(int).reshape((-1, 3))

        if self.sorted:
            for a, i in enumerate(self.neighbors):
                mask = (i < a)
                if mask.any():
                    j = i[mask]
                    offsets = self.displacements[a][mask]
                    for b, offset in zip(j, offsets):
                        self.neighbors[b] = np.concatenate(
                            (self.neighbors[b], [a]))
                        self.displacements[b] = np.concatenate(
                            (self.displacements[b], [-offset]))
                    mask = np.logical_not(mask)
                    self.neighbors[a] = self.neighbors[a][mask]
                    self.displacements[a] = self.displacements[a][mask]
def run():
    tol = 1E-14
    rng = np.random.RandomState(0)

    cell = Cell(
        [[8.972058879514716, 0.0009788104586639142, 0.0005932485724084841],
         [4.485181755775297, 7.770520334862034, 0.00043663339838788054],
         [4.484671994095723, 2.5902066679984634, 16.25695615743613]])
    cell.minkowski_reduce()

    for i in range(40):
        B = rng.uniform(-1, 1, (3, 3))
        R, H = minkowski_reduce(B)
        assert np.allclose(H @ B, R, atol=tol)
        assert np.sign(np.linalg.det(B)) == np.sign(np.linalg.det(R))

        norms = np.linalg.norm(R, axis=1)
        assert (np.argsort(norms) == range(3)).all()

        # Test idempotency
        _, _H = minkowski_reduce(R)
        assert (_H == np.eye(3).astype(np.int)).all()

        rcell, _ = Cell(B).minkowski_reduce()
        assert np.allclose(rcell, R, atol=tol)

    cell = np.array([[1, 1, 2], [0, 1, 4], [0, 0, 1]])
    unimodular = np.array([[1, 2, 2], [0, 1, 2], [0, 0, 1]])
    assert np.linalg.det(unimodular) == 1
    lcell = unimodular.T @ cell

    # test 3D
    rcell, op = minkowski_reduce(lcell)
    assert np.linalg.det(rcell) == 1

    for pbc in [1, True, (1, 1, 1)]:
        rcell, op = minkowski_reduce(lcell, pbc=pbc)
        assert np.linalg.det(rcell) == 1
        assert np.sign(np.linalg.det(rcell)) == np.sign(np.linalg.det(lcell))

    # test 0D
    rcell, op = minkowski_reduce(lcell, pbc=[0, 0, 0])
    assert (rcell == lcell).all()  # 0D reduction does nothing

    # test 1D
    for i in range(3):
        rcell, op = minkowski_reduce(lcell, pbc=np.roll([1, 0, 0], i))
        assert (rcell == lcell).all()  # 1D reduction does nothing

    zcell = np.zeros((3, 3))
    zcell[0] = lcell[0]
    rcell, _ = Cell(zcell).minkowski_reduce()
    assert np.allclose(rcell, zcell, atol=tol)

    # test 2D
    for i in range(3):
        pbc = np.roll([0, 1, 1], i)
        rcell, op = minkowski_reduce(lcell.astype(np.float), pbc=pbc)
        assert (rcell[i] == lcell[i]).all()

        zcell = np.copy(lcell.astype(np.float))
        zcell[i] = 0
        rzcell, _ = Cell(zcell).minkowski_reduce()
        rcell[i] = 0
        assert np.allclose(rzcell, rcell, atol=tol)
Ejemplo n.º 9
0
 def test_3d(self):
     lcell = self.lcell
     rcell, op = minkowski_reduce(lcell)
     assert_almost_equal(np.linalg.det(rcell), 1)
Ejemplo n.º 10
0
 def test_0d(self):
     lcell = self.lcell
     rcell, op = minkowski_reduce(lcell, pbc=[0, 0, 0])
     assert (rcell == lcell).all()  # 0D reduction does nothing
Ejemplo n.º 11
0
def test_cycle():
    # Without cycle-checking in the MR code, this cell causes failure
    a, b, c = 4.374006080444519, 2.0714140579127145, 3.671070851026261
    cell = np.array([[-a, b, c], [a, c, b], [a, b, c]])
    minkowski_reduce(cell)
Ejemplo n.º 12
0
import numpy as np
from ase.geometry import minkowski_reduce

tol = 1E-14
rng = np.random.RandomState(0)

for i in range(40):
    B = rng.uniform(-1, 1, (3, 3))
    R, H = minkowski_reduce(B)
    assert np.allclose(H @ B, R, atol=tol)

    norms = np.linalg.norm(R, axis=1)
    assert (np.argsort(norms) == range(3)).all()

    # Test idempotency
    _, _H = minkowski_reduce(R)
    assert (_H == np.eye(3).astype(np.int)).all()