Esempio n. 1
0
    def test_multiple_elements(self):
        a = molecule('HCOOH')
        a.center(vacuum=5.0)
        io.write('HCOOH.cfg', a)
        i = neighbour_list("i", a, 1.85)
        self.assertArrayAlmostEqual(np.bincount(i), [2, 3, 1, 1, 1])

        cutoffs = np.zeros([9, 9])
        cutoffs[1, 6] = cutoffs[6, 1] = 1.2
        i = neighbour_list("i", a, cutoffs, np.array(a.numbers,
                                                     dtype=np.int32))
        self.assertArrayAlmostEqual(np.bincount(i), [0, 1, 0, 0, 1])

        cutoffs = np.zeros([9, 9])
        cutoffs[6, 8] = cutoffs[8, 6] = 1.4
        i = neighbour_list("i", a, cutoffs, np.array(a.numbers,
                                                     dtype=np.int32))
        self.assertArrayAlmostEqual(np.bincount(i), [1, 2, 1])

        cutoffs = np.zeros([9, 9])
        cutoffs[1, 6] = cutoffs[6, 1] = 1.2
        cutoffs[6, 8] = cutoffs[8, 6] = 1.4
        i = neighbour_list("i", a, cutoffs, np.array(a.numbers,
                                                     dtype=np.int32))
        self.assertArrayAlmostEqual(np.bincount(i), [1, 3, 1, 0, 1])
Esempio n. 2
0
    def test_out_of_bounds(self):
        nat = 10
        atoms = ase.Atoms(numbers=range(nat),
                          cell=[(0.2, 1.2, 1.4), (1.4, 0.1, 1.6),
                                (1.3, 2.0, -0.1)])
        atoms.set_scaled_positions(3 * np.random.random((nat, 3)) - 1)

        for p1 in range(2):
            for p2 in range(2):
                for p3 in range(2):
                    atoms.set_pbc((p1, p2, p3))
                    i, j, d, D, S = neighbour_list("ijdDS", atoms,
                                                   atoms.numbers * 0.2 + 0.5)
                    c = np.bincount(i)
                    atoms2 = atoms.repeat((p1 + 1, p2 + 1, p3 + 1))
                    i2, j2, d2, D2, S2 = neighbour_list(
                        "ijdDS", atoms2, atoms2.numbers * 0.2 + 0.5)
                    c2 = np.bincount(i2)
                    c2.shape = (-1, nat)
                    dd = d.sum() * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2.sum()
                    dr = np.linalg.solve(atoms.cell.T,
                                         (atoms.positions[1] -
                                          atoms.positions[0]).T).T + np.array(
                                              [0, 0, 3])
                    self.assertTrue(abs(dd) < 1e-10)
                    self.assertTrue(not (c2 - c).any())
Esempio n. 3
0
    def test_out_of_cell_large_cell(self):
        a = ase.Atoms('CC', positions=[[9.5, 0.5, 0.5],
                                       [10.1, 0.5, 0.5]],
                      cell=[10, 10, 10], pbc=False)
        i1, j1, r1 = neighbour_list("ijd", a, 1.1)
        a.set_cell([20, 10, 10])
        i2, j2, r2 = neighbour_list("ijd", a, 1.1)

        self.assertArrayAlmostEqual(i1, i2)
        self.assertArrayAlmostEqual(j1, j2)
        self.assertArrayAlmostEqual(r1, r2)
Esempio n. 4
0
    def test_out_of_cell_large_cell(self):
        a = ase.Atoms('CC', positions=[[9.5, 0.5, 0.5],
                                       [10.1, 0.5, 0.5]],
                      cell=[10, 10, 10], pbc=False)
        i1, j1, r1 = neighbour_list("ijd", a, 1.1)
        a.set_cell([20, 10, 10])
        i2, j2, r2 = neighbour_list("ijd", a, 1.1)

        self.assertArrayAlmostEqual(i1, i2)
        self.assertArrayAlmostEqual(j1, j2)
        self.assertArrayAlmostEqual(r1, r2)
Esempio n. 5
0
def find_triangles_2d(atoms, cutoff, minangle=30*np.pi/180, maxangle=120*np.pi/180,
                      xdim=0, ydim=1):
    """
    Return a list of all triangles of a triangular lattice sitting in the x-y
    plane.
    """
    # Contains atom indices that border the triangle
    corner1 = []
    corner2 = []
    corner3 = []
    # Find triangles
    i, j, D = neighbour_list('ijD', atoms, cutoff)
    coord = np.bincount(i)
    for k in range(len(atoms)):
        firstn = np.searchsorted(i, k, side='left')
        lastn = np.searchsorted(i, k, side='right')
        # Sort six neighbors by angle
        angles = np.arctan2(D[firstn:lastn, xdim], D[firstn:lastn, ydim])
        s = np.argsort(angles)
        # Only pick triangles with angles between min and max angle
        trangles = (angles[np.roll(s, -1)]-angles[s]) % (2*np.pi)
        m = (trangles > minangle) & (trangles < maxangle)
        # Add corners of triangle to lists
        corner1 += list(np.array([k]*(lastn-firstn))[m])
        corner2 += list(j[firstn:lastn][s][m])
        corner3 += list(j[firstn:lastn][np.roll(s, -1)][m])
    # Sort corners
    corner1, corner2, corner3 = np.sort([corner1, corner2, corner3], axis=0)
    # Remove duplicate triangles
    uniqueid = corner3+len(atoms)*(corner2+len(atoms)*corner1)
    _, s = np.unique(uniqueid, return_index=True)
    return corner1[s], corner2[s], corner3[s]
Esempio n. 6
0
def remove_dangling_atoms(atoms, keep_cell=False, write=False):

    if not keep_cell:
        cell0 = atoms.get_cell()
        atoms.set_cell([1000] * 3)
        atoms.set_pbc([True] * 3)

    # atoms.set_cutoff(2.)
    # atoms.calc_connect()

    # remove dangling atoms not in loops
    dropped = 1
    idx = 0
    while dropped > 0:
        # nneighs = np.array([len(atoms.neighbours[i]) for i in atoms.indices]) # quip implementation is slow
        ni = neighbour_list("i", atoms, 2.0)
        nneighs = np.array([(ni == i).sum() for i in range(len(atoms))])
        speciesSi = atoms.get_atomic_numbers() == 14
        mask = np.array([(nneigh < 3) if issilicon else (nneigh < 2) for issilicon, nneigh in zip(speciesSi, nneighs)])
        if write:
            atoms.set_array("remove", mask)
            atoms.write("rem-%03d.xyz" % idx, format="extxyz")
        if type(atoms) == QAtoms:
            atoms.remove_atoms(mask=mask)
        else:
            del atoms[np.where(mask)]
        dropped = mask.sum()
        idx += 1
    if not keep_cell:
        atoms.set_cell(cell0)
    return
Esempio n. 7
0
 def test_hydrogenate(self):
     a = Diamond('Si', size=[2,2,1])
     b = hydrogenate(a, 2.85, 1.0, mask=[True,True,False], vacuum=5.0)
     # Check if every atom is fourfold coordinated
     syms = np.array(b.get_chemical_symbols())
     c = np.bincount(neighbour_list('i', b, 2.4))
     self.assertTrue((c[syms!='H']==4).all())
Esempio n. 8
0
 def test_hexagonal_cell(self):
     for sx in range(3):
         a = ase.lattice.hexagonal.Graphite('C',
                                            latticeconstant=(2.5, 10.0),
                                            size=[sx + 1, sx + 1, 1])
         i = neighbour_list("i", a, 1.85)
         self.assertTrue(np.all(np.bincount(i) == 3))
Esempio n. 9
0
def atoms_to_nxgraph(atoms, cutoff):
    ni, nj = neighbour_list('ij', atoms, cutoff)
    adjacency_matrix = np.zeros((len(atoms), len(atoms))).astype(np.int)
    for i, j in zip (ni, nj):
        adjacency_matrix[i,j] = 1
    graph = nx.from_numpy_matrix(np.array(adjacency_matrix))
    return graph
Esempio n. 10
0
def find_tip_coordination(a, bondlength=2.6, bulk_nn=4):
    """
    Find position of tip in crack cluster from coordination
    """
    i, j = neighbour_list("ij", a, bondlength)
    nn = np.bincount(i, minlength=len(a))

    a.set_array('n_neighb', nn)
    g = a.get_array('groups')

    y = a.positions[:, 1]
    above = (nn < bulk_nn) & (g != 0) & (y > a.cell[1,1]/2.0)
    below = (nn < bulk_nn) & (g != 0) & (y < a.cell[1,1]/2.0)

    a.set_array('above', above)
    a.set_array('below', below)

    bond1 = np.asscalar(above.nonzero()[0][a.positions[above, 0].argmax()])
    bond2 = np.asscalar(below.nonzero()[0][a.positions[below, 0].argmax()])

    # These need to be ints, otherwise they are no JSON serializable.
    a.info['bond1'] = bond1
    a.info['bond2'] = bond2

    return bond1, bond2
Esempio n. 11
0
def spatial_correlation_function_near(atoms,
                                      values,
                                      gridsize=None,
                                      cutoff=None,
                                      norm=False):
    if gridsize is None:
        gridsize = 0.1

    if cutoff is None:
        cutoff = 7.5

    # close range exact calculation
    nbins = int(cutoff / gridsize) + 1
    index1, index2, dist = neighbour_list('ijd', atoms, cutoff=cutoff)
    SCF_near, edges = np.histogram(dist,
                                   bins=bins,
                                   weights=values[index1] * values[index2])
    slice_volume = 4 * np.pi / 3 * (edges[1:]**3 - edges[:-1]**3)
    SCF_near *= atoms.get_volume() / n_atoms**2 / slice_volume
    if norm:
        v_2_mean = (values**2).mean()
        v_mean_2 = (values.mean())**2
        SCF_near = (SCF_near - v_mean_2) / (v_2_mean - v_mean_2)

    return SCF_near, (edges[1:] + edges[:-1]) / 2
Esempio n. 12
0
def find_tip_coordination(a, bondlength=2.6, bulk_nn=4):
    """
    Find position of tip in crack cluster from coordination
    """
    i, j = neighbour_list("ij", a, bondlength)
    nn = np.bincount(i, minlength=len(a))

    a.set_array('n_neighb', nn)
    g = a.get_array('groups')

    y = a.positions[:, 1]
    above = (nn < bulk_nn) & (g != 0) & (y > a.cell[1,1]/2.0)
    below = (nn < bulk_nn) & (g != 0) & (y < a.cell[1,1]/2.0)

    a.set_array('above', above)
    a.set_array('below', below)

    bond1 = np.asscalar(above.nonzero()[0][a.positions[above, 0].argmax()])
    bond2 = np.asscalar(below.nonzero()[0][a.positions[below, 0].argmax()])

    # These need to be ints, otherwise they are no JSON serializable.
    a.info['bond1'] = bond1
    a.info['bond2'] = bond2

    return bond1, bond2
Esempio n. 13
0
 def test_hydrogenate(self):
     a = Diamond('Si', size=[2, 2, 1])
     b = hydrogenate(a, 2.85, 1.0, mask=[True, True, False], vacuum=5.0)
     # Check if every atom is fourfold coordinated
     syms = np.array(b.get_chemical_symbols())
     c = np.bincount(neighbour_list('i', b, 2.4))
     self.assertTrue((c[syms != 'H'] == 4).all())
Esempio n. 14
0
    def test_anisotropic_near_field_solution(self):
        """
        Run an atomistic calculation of a harmonic solid and compare to
        continuum solution.
        """

        for nx in [ 8, 16, 32, 64 ]:
            for calc, a, C11, C12, C44, surface_energy, bulk_coordination in [
                #( atomistica.DoubleHarmonic(k1=1.0, r1=1.0, k2=1.0,
                #                            r2=math.sqrt(2), cutoff=1.6),
                #  clusters.sc('He', 1.0, [nx,nx,1], [1,0,0], [0,1,0]),
                #  3, 1, 1, 0.05, 6 ),
                (
                  #atomistica.Harmonic(k=1.0, r0=1.0, cutoff=1.3, shift=True),
                  IdealBrittleSolid(k=1.0, a=1.0, rc=1.3),
                  clusters.fcc('He', math.sqrt(2.0), [nx,nx,1], [1,0,0],
                               [0,1,0]),
                  math.sqrt(2), 1.0/math.sqrt(2), 1.0/math.sqrt(2), 0.05, 12)
                ]:
                clusters.set_groups(a, (nx, nx, 1), 0.5, 0.5)
                crack = CubicCrystalCrack([1,0,0], [0,1,0], C11, C12, C44)

                a.center(vacuum=20.0, axis=0)
                a.center(vacuum=20.0, axis=1)
                a.set_calculator(calc)

                sx, sy, sz = a.cell.diagonal()
                tip_x = sx/2
                tip_y = sy/2

                k1g = crack.k1g(surface_energy)
                r0 = a.positions.copy()

                u, v = crack.displacements(a.positions[:,0], a.positions[:,1],
                                           tip_x, tip_y, k1g)
                a.positions[:,0] += u
                a.positions[:,1] += v

                g = a.get_array('groups')
                a.set_constraint(FixAtoms(mask=g==0))

                #ase.io.write('initial_{}.xyz'.format(nx), a, format='extxyz', write_results=False)

                x1, y1, z1 = a.positions.copy().T
                FIRE(a, logfile=None).run(fmax=1e-3)
                x2, y2, z2 = a.positions.T

                # Get coordination numbers and find properly coordinated atoms
                i = neighbour_list("i", a, 1.1)
                coord = np.bincount(i, minlength=len(a))
                mask=coord == bulk_coordination

                residual = np.sqrt(((x2-x1)/u)**2 + ((y2-y1)/v)**2)

                #a.set_array('residual', residual)
                #ase.io.write('final_{}.xyz'.format(nx), a, format='extxyz')

                #print(np.max(residual[mask]))
                self.assertTrue(np.max(residual[mask]) < 0.2)
Esempio n. 15
0
 def test_no_angle(self):
     a = ase.Atoms('CC',
                   positions=[[0.5, 0.5, 0.5], [0.5, 0.5, 1.0]],
                   cell=[2, 2, 2],
                   pbc=True)
     i, j, dr = neighbour_list("ijD", a, 1.1)
     hist = angle_distribution(i, j, dr, 20, 1.1)
     self.assertEqual(hist.sum(), 0)
Esempio n. 16
0
def view(a, colour=None, bonds=True, cell=True,
         scale=10.0, cutoff_scale=1.2,
         cmap=None, vmin=None, vmax=None):
    topology = {}
    topology['atom_types'] = a.get_chemical_symbols()

    if bonds:
        n = a.numbers
        maxn = n.max()
        cutoffs = np.zeros([maxn+1, maxn+1])

        for n1, n2 in itertools.product(n, n):
            cutoffs[n1, n2] = cutoff_scale*(covalent_radii[n1]+covalent_radii[n2])

        # Construct a bond list
        i, j, S = neighbour_list('ijS',
                                 a, cutoffs,
                                 np.array(a.numbers, dtype=np.int32))
        m = np.logical_and(i<j, (S==0).all(axis=1))
        i = i[m]
        j = j[m]
        topology['bonds'] = [(x, y) for x, y in zip(i, j)]

    colorlist = None
    if colour is not None:
        colour = np.array(colour, dtype=np.float64)
        if cmap is None:
            from matplotlib.cm import jet
            cmap = jet
        if vmin is None:
            vmin = np.min(colour)
        if vmax is None:
            vmax = np.max(colour)
        colour = (colour - vmin)/(vmax - vmin)
        colorlist = ['0x%02x%02x%02x' % (r*256, g*256, b*256)
                     for (r, g, b, alpha) in cmap(colour)]

    mv = MolecularViewer(a.positions/scale,
                         topology=topology)
    mv.ball_and_sticks(colorlist=colorlist)

    if cell:
        O = np.zeros(3, dtype=np.float32)
        La, Lb, Lc = a.cell.astype(np.float32)/scale
        start = np.r_[O, O, O,
                      O + Lb, O + Lc, O + La,
                      O + Lc, O + La, O + Lb,
                      O + Lb + Lc, O + La + Lc, O + La + Lb]
        end = np.r_[O + La, O + Lb, O + Lc,
                    O + Lb + La, O + Lc + Lb, O + La + Lc,
                    O + Lc + La, O + La + Lb, O + Lb + Lc,
                    O + Lb + Lc + La, O + La + Lc + Lb, O + La + Lb + Lc]
        rgb = [0xFF0000, 0x00FF00, 0x0000FF]*4
        mv.add_representation('lines', {'startCoords': start,
                                        'endCoords': end,
                                        'startColors': rgb,
                                        'endColors': rgb})
    return mv
Esempio n. 17
0
    def test_multiple_elements(self):
        a = molecule('HCOOH')
        a.center(vacuum=5.0)
        io.write('HCOOH.cfg', a)
        i = neighbour_list("i", a, 1.85)
        self.assertArrayAlmostEqual(np.bincount(i), [2,3,1,1,1])

        cutoffs = {(1, 6): 1.2}
        i = neighbour_list("i", a, cutoffs)
        self.assertArrayAlmostEqual(np.bincount(i), [0,1,0,0,1])

        cutoffs = {(6, 8): 1.4}
        i = neighbour_list("i", a, cutoffs)
        self.assertArrayAlmostEqual(np.bincount(i), [1,2,1])

        cutoffs = {('H', 'C'): 1.2, (6, 8): 1.4}
        i = neighbour_list("i", a, cutoffs)
        self.assertArrayAlmostEqual(np.bincount(i), [1,3,1,0,1])
Esempio n. 18
0
    def test_multiple_elements(self):
        a = molecule('HCOOH')
        a.center(vacuum=5.0)
        io.write('HCOOH.cfg', a)
        i = neighbour_list("i", a, 1.85)
        self.assertArrayAlmostEqual(np.bincount(i), [2,3,1,1,1])

        cutoffs = {(1, 6): 1.2}
        i = neighbour_list("i", a, cutoffs)
        self.assertArrayAlmostEqual(np.bincount(i), [0,1,0,0,1])

        cutoffs = {(6, 8): 1.4}
        i = neighbour_list("i", a, cutoffs)
        self.assertArrayAlmostEqual(np.bincount(i), [1,2,1])

        cutoffs = {('H', 'C'): 1.2, (6, 8): 1.4}
        i = neighbour_list("i", a, cutoffs)
        self.assertArrayAlmostEqual(np.bincount(i), [1,3,1,0,1])
Esempio n. 19
0
 def test_three_angles(self):
     a = ase.Atoms('CCC', positions=[[0.5, 0.5, 0.5], [0.5, 0.5, 1.0],
                                    [0.5, 1.0, 1.0]],
                   cell=[2, 2, 2], pbc=True)
     i, j, dr = neighbour_list("ijD", a, 1.1)
     hist = angle_distribution(i, j, dr, 20)
     #                                                 v 45 degrees
     self.assertArrayAlmostEqual(hist, [0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
                                        2, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Esempio n. 20
0
    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        f = self.f
        nat = len(self.atoms)
        if atoms.has("size"):
            size = self.atoms.get_array("size")
        else:
            raise AttributeError(
                "Attribute error: Unable to load atom sizes from atoms object!"
            )

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list(
            "ijDd", self.atoms,
            f.get_maxSize() * f.get_cutoff())
        ijsize = f.mix_sizes(size[i_n], size[j_n])

        # Mask neighbour list to consider only true neighbors
        mask = abs_dr_n <= f.get_cutoff() * ijsize
        i_n = i_n[mask]
        j_n = j_n[mask]
        dr_nc = dr_nc[mask]
        abs_dr_n = abs_dr_n[mask]
        ijsize = ijsize[mask]
        e_n = f(abs_dr_n, ijsize)
        de_n = f.first_derivative(abs_dr_n, ijsize)

        # Energy
        epot = 0.5 * np.sum(e_n)

        # Forces
        df_nc = 0.5 * de_n.reshape(-1, 1) * dr_nc / abs_dr_n.reshape(-1, 1)

        # Sum for each atom
        fx_i = np.bincount(i_n, weights=df_nc[:, 0], minlength=nat) - \
            np.bincount(j_n, weights=df_nc[:, 0], minlength=nat)
        fy_i = np.bincount(i_n, weights=df_nc[:, 1], minlength=nat) - \
            np.bincount(j_n, weights=df_nc[:, 1], minlength=nat)
        fz_i = np.bincount(i_n, weights=df_nc[:, 2], minlength=nat) - \
            np.bincount(j_n, weights=df_nc[:, 2], minlength=nat)

        # Virial
        virial_v = -np.array([
            dr_nc[:, 0] * df_nc[:, 0],  # xx
            dr_nc[:, 1] * df_nc[:, 1],  # yy
            dr_nc[:, 2] * df_nc[:, 2],  # zz
            dr_nc[:, 1] * df_nc[:, 2],  # yz
            dr_nc[:, 0] * df_nc[:, 2],  # xz
            dr_nc[:, 0] * df_nc[:, 1]
        ]).sum(axis=1)  # xy

        self.results = {
            'energy': epot,
            'stress': virial_v / self.atoms.get_volume(),
            'forces': np.transpose([fx_i, fy_i, fz_i])
        }
Esempio n. 21
0
    def test_direct_evaluation(self):
        a = FaceCenteredCubic('Au', size=[2,2,2])
        a.rattle(0.1)
        calc = EAM('Au-Grochola-JCP05.eam.alloy')
        a.set_calculator(calc)
        f = a.get_forces()

        calc2 = EAM('Au-Grochola-JCP05.eam.alloy')
        i_n, j_n, dr_nc, abs_dr_n = neighbour_list('ijDd', a, cutoff=calc2.cutoff)
        epot, virial, f2 = calc2.energy_virial_and_forces(a.numbers, i_n, j_n, dr_nc, abs_dr_n)
        self.assertArrayAlmostEqual(f, f2)

        a = FaceCenteredCubic('Cu', size=[2,2,2])
        calc = EAM('CuAg.eam.alloy')
        a.set_calculator(calc)
        FIRE(StrainFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001)
        e_Cu = a.get_potential_energy()/len(a)
 
        a = FaceCenteredCubic('Ag', size=[2,2,2])
        a.set_calculator(calc)
        FIRE(StrainFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001)
        e_Ag = a.get_potential_energy()/len(a)
        self.assertTrue(abs(e_Ag+2.85)<1e-6)
 
        a = L1_2(['Ag', 'Cu'], size=[2,2,2], latticeconstant=4.0)
        a.set_calculator(calc)
        FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001)
        e = a.get_potential_energy()
        syms = np.array(a.get_chemical_symbols())
        self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu-
                               (syms=='Ag').sum()*e_Ag)/len(a)-0.096)<0.0005)
 
        a = B1(['Ag', 'Cu'], size=[2,2,2], latticeconstant=4.0)
        a.set_calculator(calc)
        FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001)
        e = a.get_potential_energy()
        syms = np.array(a.get_chemical_symbols())
        self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu-
                               (syms=='Ag').sum()*e_Ag)/len(a)-0.516)<0.0005)
 
        a = B2(['Ag', 'Cu'], size=[2,2,2], latticeconstant=4.0)
        a.set_calculator(calc)
        FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001)
        e = a.get_potential_energy()
        syms = np.array(a.get_chemical_symbols())
        self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu-
                               (syms=='Ag').sum()*e_Ag)/len(a)-0.177)<0.0003)
 
        a = L1_2(['Cu', 'Ag'], size=[2,2,2], latticeconstant=4.0)
        a.set_calculator(calc)
        FIRE(UnitCellFilter(a, mask=[1,1,1,0,0,0]), logfile=None).run(fmax=0.001)
        e = a.get_potential_energy()
        syms = np.array(a.get_chemical_symbols())
        self.assertTrue(abs((e-(syms=='Cu').sum()*e_Cu-
                                (syms=='Ag').sum()*e_Ag)/len(a)-0.083)<0.0005)
Esempio n. 22
0
    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        nat = len(self.atoms)
        atnums = self.atoms.numbers
        atnums_in_system = set(atnums)

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list(
            'ijDd', self.atoms, self.dict)

        e_n = np.zeros_like(abs_dr_n)
        de_n = np.zeros_like(abs_dr_n)
        for params, pair in enumerate(self.dict):
            if pair[0] == pair[1]:
                mask1 = atnums[i_n] == pair[0]
                mask2 = atnums[j_n] == pair[0]
                mask = np.logical_and(mask1, mask2)

                e_n[mask] = self.f[pair](abs_dr_n[mask])
                de_n[mask] = self.df[pair](abs_dr_n[mask])

            if pair[0] != pair[1]:
                mask1 = np.logical_and(
                    atnums[i_n] == pair[0], atnums[j_n] == pair[1])
                mask2 = np.logical_and(
                    atnums[i_n] == pair[1], atnums[j_n] == pair[0])
                mask = np.logical_or(mask1, mask2)

                e_n[mask] = self.f[pair](abs_dr_n[mask])
                de_n[mask] = self.df[pair](abs_dr_n[mask])

        epot = 0.5*np.sum(e_n)

        # Forces
        df_nc = -0.5*de_n.reshape(-1, 1)*dr_nc/abs_dr_n.reshape(-1, 1)

        # Sum for each atom
        fx_i = np.bincount(j_n, weights=df_nc[:, 0], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 0], minlength=nat)
        fy_i = np.bincount(j_n, weights=df_nc[:, 1], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 1], minlength=nat)
        fz_i = np.bincount(j_n, weights=df_nc[:, 2], minlength=nat) - \
            np.bincount(i_n, weights=df_nc[:, 2], minlength=nat)

        # Virial
        virial_v = -np.array([dr_nc[:, 0]*df_nc[:, 0],               # xx
                              dr_nc[:, 1]*df_nc[:, 1],               # yy
                              dr_nc[:, 2]*df_nc[:, 2],               # zz
                              dr_nc[:, 1]*df_nc[:, 2],               # yz
                              dr_nc[:, 0]*df_nc[:, 2],               # xz
                              dr_nc[:, 0]*df_nc[:, 1]]).sum(axis=1)  # xy

        self.results = {'energy': epot,
                        'stress': virial_v/self.atoms.get_volume(),
                        'forces': np.transpose([fx_i, fy_i, fz_i])}
Esempio n. 23
0
def find_tip_broken_bonds(atoms, cutoff, bulk_nn=4, boundary_thickness=None):
    """
    Find position of the tip from the atom coordination, i.e. broken bonds.
    Using the C implementation of 'neighbour_list'.
    Returns the tip's position in cartesian coordinates.

    Parameters
    ----------
    atoms : ase.Atoms
        Atomic configuration.
    cutoff : float
        Cutoff distance for neighbour search.
    bulk_nn : integer
        Number of nearest neighbours for the standard bulk configuration.
    boundary_buffer : float
        Thickness of the boundaries.
        Defaults to cutoff distance.

    Returns
    -------
    tip_position : numpy array
        The x and y values are found.
        The z value is calculated as the midpoint of the depth.
    """

    # initialisation of the boundaries
    if boundary_thickness is None:
        boundary_thickness = cutoff

    right_boundary = atoms.positions[(np.argmax(atoms.positions[:,0], axis=0)), 0] - boundary_thickness
    top_boundary = atoms.positions[(np.argmax(atoms.positions[:,1], axis=0)), 1] - boundary_thickness
    bottom_boundary = atoms.positions[(np.argmin(atoms.positions[:,1], axis=0)), 1] + boundary_thickness
    left_boundary = atoms.positions[(np.argmin(atoms.positions[:,0], axis=0)), 0] + boundary_thickness

    # calculating the coordination from the neighbours list
    i = neighbour_list("i", atoms, cutoff)
    coordination_list = np.bincount(i, minlength=len(atoms))

    # list of atom numbers with at least one broken bond
    broken_bonds_array = np.where(coordination_list <= bulk_nn-1)

    # finds the atom number with the most positive x-valued position with a broken bond(s)
    # within the bounded section
    atom_number = 0
    for m in range(0, len(broken_bonds_array[0])):
        temp_atom_pos = atoms.positions[broken_bonds_array[0][m]]
        if temp_atom_pos[0] > atoms.positions[atom_number,0]:
            if left_boundary < temp_atom_pos[0] < right_boundary:
                if bottom_boundary < temp_atom_pos[1] < top_boundary:
                    atom_number = m

    tip_position = atoms.positions[broken_bonds_array[0][atom_number]]

    return np.array((tip_position[0], tip_position[1], atoms.cell[2,2]/2.0))
Esempio n. 24
0
def internal_vector(atoms, at_idx, exponent, r_cut, do_calc_connect=True):
    iv = sp.zeros(3)
    atom, r = neighbour_list("iD", atoms, 8.0)
    r = np.asarray(r)[atom == at_idx]
    # if do_calc_connect:
    #     atoms.set_cutoff(8.0)
    #     atoms.calc_connect()
    # # each copy of each atom within the cutoff radius contribute to iv
    # r = np.asarray([neighbours.diff for neighbours in atoms.neighbours[at_idx]])
    r_mag = np.asarray(map(LA.norm, r))
    return (r / r_mag[:,None] * sp.exp(- (r_mag / r_cut) ** exponent)[:,None]).sum(axis=0)
Esempio n. 25
0
def find_tip_broken_bonds(atoms, cutoff, bulk_nn=4, boundary_thickness=None):
    """
    Find position of the tip from the atom coordination, i.e. broken bonds.
    Using the C implementation of 'neighbour_list'.
    Returns the tip's position in cartesian coordinates.

    Parameters
    ----------
    atoms : ase.Atoms
        Atomic configuration.
    cutoff : float
        Cutoff distance for neighbour search.
    bulk_nn : integer
        Number of nearest neighbours for the standard bulk configuration.
    boundary_buffer : float
        Thickness of the boundaries.
        Defaults to cutoff distance.

    Returns
    -------
    tip_position : numpy array
        The x and y values are found.
        The z value is calculated as the midpoint of the depth.
    """

    # initialisation of the boundaries
    if boundary_thickness is None:
        boundary_thickness = cutoff

    right_boundary = atoms.positions[(np.argmax(atoms.positions[:,0], axis=0)), 0] - boundary_thickness
    top_boundary = atoms.positions[(np.argmax(atoms.positions[:,1], axis=0)), 1] - boundary_thickness
    bottom_boundary = atoms.positions[(np.argmin(atoms.positions[:,1], axis=0)), 1] + boundary_thickness
    left_boundary = atoms.positions[(np.argmin(atoms.positions[:,0], axis=0)), 0] + boundary_thickness

    # calculating the coordination from the neighbours list
    i = neighbour_list("i", atoms, cutoff)
    coordination_list = np.bincount(i, minlength=len(atoms))

    # list of atom numbers with at least one broken bond
    broken_bonds_array = np.where(coordination_list <= bulk_nn-1)

    # finds the atom number with the most positive x-valued position with a broken bond(s)
    # within the bounded section
    atom_number = 0
    for m in range(0, len(broken_bonds_array[0])):
        temp_atom_pos = atoms.positions[broken_bonds_array[0][m]]
        if temp_atom_pos[0] > atoms.positions[atom_number,0]:
            if left_boundary < temp_atom_pos[0] < right_boundary:
                if bottom_boundary < temp_atom_pos[1] < top_boundary:
                    atom_number = m

    tip_position = atoms.positions[broken_bonds_array[0][atom_number]]

    return np.array((tip_position[0], tip_position[1], atoms.cell[2,2]/2.0))
Esempio n. 26
0
def calc_rdf(Cell, rdf_cutoff, rdf_nbins):
    # use ase object for calculating rdf.
    r = neighbour_list('d', Cell, cutoff=rdf_cutoff)
    rdf, bin_edges = np.histogram(r, bins=rdf_nbins, range=(0, rdf_cutoff))
    # normalize by bin volume and total number of atoms
    rdf = rdf / (len(Cell) * 4 * np.pi / 3 *
                 (bin_edges[1:]**3 - bin_edges[:-1]**3))
    # normalize by cell volume
    rdf /= len(Cell) / Cell.get_volume()
    bin_centers = (bin_edges[1:] + bin_edges[:-1]) / 2
    return bin_centers, rdf
Esempio n. 27
0
    def test_small_cell(self):
        a = ase.Atoms('C', positions=[[0.5, 0.5, 0.5]], cell=[1, 1, 1],
                      pbc=True)
        i, j, dr, shift = neighbour_list("ijDS", a, 1.1)
        assert np.bincount(i)[0] == 6
        assert (dr == shift).all()

        i, j = neighbour_list("ij", a, 1.5)
        assert np.bincount(i)[0] == 18

        a.set_pbc(False)
        i = neighbour_list("i", a, 1.1)
        assert len(i) == 0

        a.set_pbc([True, False, False])
        i = neighbour_list("i", a, 1.1)
        assert np.bincount(i)[0] == 2

        a.set_pbc([True, False, True])
        i = neighbour_list("i", a, 1.1)
        assert np.bincount(i)[0] == 4
Esempio n. 28
0
    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        # construct neighbor list
        i_p, j_p, r_p, r_pc = neighbour_list('ijdD',
                                             atoms=atoms,
                                             cutoff=self.cutoff)

        nb_atoms = len(self.atoms)
        nb_pairs = len(i_p)

        # normal vectors
        n_pc = (r_pc.T / r_p).T
        nx_p, ny_p, nz_p = n_pc.T

        # construct triplet list
        first_i = first_neighbours(nb_atoms, i_p)
        ij_t, ik_t = triplet_list(first_i)

        # calculate energy
        G_t = self.G(r_pc[ij_t], r_pc[ik_t])
        xi_p = np.bincount(ij_t, weights=G_t, minlength=nb_pairs)
        F_p = self.F(r_p, xi_p)
        epot = 0.5 * np.sum(F_p)

        d1G_t = self.d1G(r_pc[ij_t], r_pc[ik_t])
        d2F_d2G_t = (self.d2F(r_p[ij_t], xi_p[ij_t]) *
                     self.d2G(r_pc[ij_t], r_pc[ik_t]).T).T
        # calculate forces (per pair)
        fx_p = \
            self.d1F(r_p, xi_p) * n_pc[:, 0] + \
            self.d2F(r_p, xi_p) * np.bincount(ij_t, d1G_t[:, 0], minlength=nb_pairs) + \
            np.bincount(ik_t, d2F_d2G_t[:, 0], minlength=nb_pairs)
        fy_p = \
            self.d1F(r_p, xi_p) * n_pc[:, 1] + \
            self.d2F(r_p, xi_p) * np.bincount(ij_t, d1G_t[:, 1], minlength=nb_pairs) + \
            np.bincount(ik_t, d2F_d2G_t[:, 1], minlength=nb_pairs)
        fz_p = \
            self.d1F(r_p, xi_p) * n_pc[:, 2] + \
            self.d2F(r_p, xi_p) * np.bincount(ij_t, d1G_t[:, 2], minlength=nb_pairs) + \
            np.bincount(ik_t, d2F_d2G_t[:, 2], minlength=nb_pairs)

        # collect atomic forces
        fx_n = 0.5 * (np.bincount(i_p, weights=fx_p) -
                      np.bincount(j_p, weights=fx_p))
        fy_n = 0.5 * (np.bincount(i_p, weights=fy_p) -
                      np.bincount(j_p, weights=fy_p))
        fz_n = 0.5 * (np.bincount(i_p, weights=fz_p) -
                      np.bincount(j_p, weights=fz_p))

        f_n = np.transpose([fx_n, fy_n, fz_n])

        self.results = {'energy': epot, 'forces': f_n}
Esempio n. 29
0
    def test_small_cell(self):
        a = ase.Atoms('C', positions=[[0.5, 0.5, 0.5]], cell=[1, 1, 1],
                      pbc=True)
        i, j, dr, shift = neighbour_list("ijDS", a, 1.1)
        assert np.bincount(i)[0] == 6
        assert (dr == shift).all()

        i, j = neighbour_list("ij", a, 1.5)
        assert np.bincount(i)[0] == 18

        a.set_pbc(False)
        i = neighbour_list("i", a, 1.1)
        assert len(i) == 0

        a.set_pbc([True, False, False])
        i = neighbour_list("i", a, 1.1)
        assert np.bincount(i)[0] == 2

        a.set_pbc([True, False, True])
        i = neighbour_list("i", a, 1.1)
        assert np.bincount(i)[0] == 4
Esempio n. 30
0
 def test_out_of_bounds(self):
     nat = 10
     atoms = ase.Atoms(numbers=range(nat),
                       cell=[(0.2, 1.2, 1.4),
                             (1.4, 0.1, 1.6),
                             (1.3, 2.0, -0.1)])
     atoms.set_scaled_positions(3 * np.random.random((nat, 3)) - 1)
     
     for p1 in range(2):
         for p2 in range(2):
             for p3 in range(2):
                 atoms.set_pbc((p1, p2, p3))
                 i, j, d, D, S = neighbour_list("ijdDS", atoms, atoms.numbers * 0.2 + 0.5)
                 c = np.bincount(i)
                 atoms2 = atoms.repeat((p1 + 1, p2 + 1, p3 + 1))
                 i2, j2, d2, D2, S2 = neighbour_list("ijdDS", atoms2, atoms2.numbers * 0.2 + 0.5)
                 c2 = np.bincount(i2)
                 c2.shape = (-1, nat)
                 dd = d.sum() * (p1 + 1) * (p2 + 1) * (p3 + 1) - d2.sum()
                 dr = np.linalg.solve(atoms.cell.T, (atoms.positions[1]-atoms.positions[0]).T).T+np.array([0,0,3])
                 self.assertTrue(abs(dd) < 1e-10)
                 self.assertTrue(not (c2 - c).any())
Esempio n. 31
0
 def test_wrong_number_of_cutoffs(self):
     nat = 10
     atoms = ase.Atoms(numbers=range(nat),
                       cell=[(0.2, 1.2, 1.4),
                             (1.4, 0.1, 1.6),
                             (1.3, 2.0, -0.1)])
     atoms.set_scaled_positions(3 * np.random.random((nat, 3)) - 1)
     exception_thrown = False
     try:
         i, j, d, D, S = neighbour_list("ijdDS", atoms, np.ones(len(atoms)-1))
     except TypeError:
         exception_thrown = True
     self.assertTrue(exception_thrown)
Esempio n. 32
0
 def test_wrong_number_of_cutoffs(self):
     nat = 10
     atoms = ase.Atoms(numbers=range(nat),
                       cell=[(0.2, 1.2, 1.4), (1.4, 0.1, 1.6),
                             (1.3, 2.0, -0.1)])
     atoms.set_scaled_positions(3 * np.random.random((nat, 3)) - 1)
     exception_thrown = False
     try:
         i, j, d, D, S = neighbour_list("ijdDS", atoms,
                                        np.ones(len(atoms) - 1))
     except TypeError:
         exception_thrown = True
     self.assertTrue(exception_thrown)
Esempio n. 33
0
    def test_dsygv_dgelsd(self):
        a = Diamond('C', size=[4,4,4])
        b = a.copy()
        b.positions += (np.random.random(b.positions.shape)-0.5)*0.1
        i, j = neighbour_list("ij", b, 1.85)

        dr_now = mic(b.positions[i] - b.positions[j], b.cell)
        dr_old = mic(a.positions[i] - a.positions[j], a.cell)

        dgrad1 = get_delta_plus_epsilon_dgesv(len(b), i, dr_now, dr_old)
        dgrad2 = get_delta_plus_epsilon(len(b), i, dr_now, dr_old)

        self.assertArrayAlmostEqual(dgrad1, dgrad2)
Esempio n. 34
0
def find_bonds(atoms, cutoffs_dict):
    """Returns a set of (frozen)sets of indices,
    where each set represents a bond, and the two
    values in the set represent the indices of the
    atoms in the system.

    ARGUMENTS
    ---------
    atoms        :    <ase.atoms.Atoms> object
    cutoffs_dict :    <dict> of cutoffs with the form
                        { (species tuple) : cutoff }

                      Example:
                      --------  
                        cutoffs_dict = {
                            ('C', 'C') : 1.8,
                            ('C', 'H') : 1.3,
                            ('H', 'H') : 0.9
                        }

    COMMENTS
    --------
    - Matscipy is used to generate the neighbour lists,
    which are determined by simple cutoffs. The function
    assumes that two atoms form a `bond' if they are within
    the cutoff length corresponding to that bond type.

    - By returning a `set', it is ensured that there are
    no redundant bonds, since {a, b} == {b, a}.

    - This function can also be used to find bond events by
    comparing the bond sets from consecutive simulation
    steps and taking the symmetric difference between the two.
    Note that the order *does* matter!
    
    For example:
    >>> bonds_initial = find_bonds( atoms_initial, cutoffs )
    >>> bonds_final   = find_bonds( atoms_final, cutoffs )
    >>>
    >>> bonds_final - bonds_initial
    {frozenset({74, 29})
     frozenset({104, 19})}
    >>> # two bonds have been created
    >>> 
    >>> bonds_initial - bonds_final
    {frozenset({31, 78})}
    >>> # one bond has been broken
    """
    i, j = neighbour_list('ij', atoms, cutoffs_dict)

    return set(frozenset({x, y}) for x, y in zip(i, j))
Esempio n. 35
0
def complete_Si_tetrahedrons(atoms, cutoff=2.0):
    """
    Every 3-coordinated Si atom gets an extra O atom to complete the tetrahedron.
    """
    species = atoms.get_atomic_numbers()
    ii, jj, DD, SS = neighbour_list("ijDS", atoms, cutoff)
    for i in range(len(atoms)):
        if species[i] == 14:
            neighbours = np.where(ii == i)[0]
            distances = DD[neighbours]
            if len(neighbours) == 3:
                pos4thO = tetrahedron_4th_position(np.zeros(3), distances)
                atoms.append(Atom(symbol="O", position=pos4thO + atoms.get_positions()[i]))
    return
Esempio n. 36
0
def find_crack_tip(atoms, dt=None, store=True, results=None):
    """
    Return atom at the crack tip and its x-coordinate
    
    Crack tip is defined to be location of rightmost atom
    whose nearest neighbour is at distance > 2.5*a
    """
    calc = atoms.get_calculator()
    a = calc.parameters['a']
    rc = calc.parameters['rc']
    
    i = neighbour_list('i', atoms, rc)
    nn = np.bincount(i) # number of nearest neighbours, equal to 6 in bulk
    
    x = atoms.positions[:, 0]
    y = atoms.positions[:, 1]

    bottom = y.min()
    left = x.min()
    width = x.max() - x.min()
    height = y.max() - y.min()
    old_tip_x = atoms.info.get('tip_x', left + 0.3*width)

    # crack cannot have advanced more than c_R*dt
    if dt is not None:
        cl, ct, cR = calc.get_wave_speeds(atoms)
        tip_max_x = old_tip_x + 10.0*cR*dt # FIXME definition of cR seems wrong, shouldn't need factor of 10 here...
    else:
        tip_max_x = left + 0.8*width
    
    broken = ((nn != 6) &
              (x > left + 0.2*width) & (x < tip_max_x) &
              (y > bottom + 0.1*height) & (y < bottom + 0.9*height))
        
    index = atoms.positions[broken, 0].argmax()
    tip_atom = broken.nonzero()[0][index]
    tip_x = atoms.positions[tip_atom, 0]

    strain = get_strain(atoms)
    eps_G = atoms.info['eps_G']
    print 'tip_x: %.3f strain: %.4f delta: %.3f' % (tip_x, strain, strain/eps_G)

    if store:
        atoms.info['tip_atom'] = tip_atom
        atoms.info['tip_x'] = tip_x

    if results is not None:
        results.append(tip_x)
    
    return (tip_atom, tip_x, broken)
Esempio n. 37
0
def find_crack_tip(atoms, dt=None, store=True, results=None):
    """
    Return atom at the crack tip and its x-coordinate

    Crack tip is defined to be location of rightmost atom
    whose nearest neighbour is at distance > 2.5*a
    """
    calc = atoms.get_calculator()
    a = calc.parameters['a']
    rc = calc.parameters['rc']

    i = neighbour_list('i', atoms, rc)
    nn = np.bincount(i)  # number of nearest neighbours, equal to 6 in bulk

    x = atoms.positions[:, 0]
    y = atoms.positions[:, 1]

    bottom = y.min()
    left = x.min()
    width = x.max() - x.min()
    height = y.max() - y.min()
    old_tip_x = atoms.info.get('tip_x', left + 0.3 * width)

    # crack cannot have advanced more than c_R*dt
    if dt is not None:
        cl, ct, cR = calc.get_wave_speeds(atoms)
        tip_max_x = old_tip_x + 10.0 * cR * dt  # FIXME definition of cR seems wrong, shouldn't need factor of 10 here...
    else:
        tip_max_x = left + 0.8 * width

    broken = ((nn != 6) & (x > left + 0.2 * width) & (x < tip_max_x) &
              (y > bottom + 0.1 * height) & (y < bottom + 0.9 * height))

    index = atoms.positions[broken, 0].argmax()
    tip_atom = broken.nonzero()[0][index]
    tip_x = atoms.positions[tip_atom, 0]

    strain = get_strain(atoms)
    eps_G = atoms.info['eps_G']
    print('tip_x: %.3f strain: %.4f delta: %.3f' %
          (tip_x, strain, strain / eps_G))

    if store:
        atoms.info['tip_atom'] = tip_atom
        atoms.info['tip_x'] = tip_x

    if results is not None:
        results.append(tip_x)

    return (tip_atom, tip_x, broken)
Esempio n. 38
0
    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        i_n, j_n, dr_nc, abs_dr_n = neighbour_list('ijDd', self.atoms,
                                                   self._db_cutoff)

        epot, virial_v, forces_ic = self.energy_virial_and_forces(
            self.atoms.numbers, i_n, j_n, dr_nc, abs_dr_n)

        self.results = {
            'energy': epot,
            'free_energy': epot,
            'stress': virial_v / self.atoms.get_volume(),
            'forces': forces_ic
        }
Esempio n. 39
0
    def calculate(self,
                  atoms=None,
                  properties=None,
                  system_changes=all_changes):
        if properties is None:
            properties = ['energy', 'local_energy']
        Calculator.calculate(self, atoms, properties, system_changes)
        if atoms is None:
            atoms = self.atoms
        natoms = len(atoms)

        D = self.parameters.D
        alpha = self.parameters.alpha
        r0 = self.parameters.r0
        rc = self.parameters.rc

        i, j, dr, r = neighbour_list('ijDd', atoms, rc)
        tmp = np.exp(-alpha * (r - r0))
        de = 0.5 * D * (tmp * tmp - 2.0 * tmp)
        local_energy = np.bincount(i, de, minlength=natoms)
        energy = local_energy.sum()

        tmpd = -alpha * tmp
        df = (D * (2.0 * tmp * tmpd - 2.0 * tmpd) / r)[:, np.newaxis] * dr
        forces = np.zeros((natoms, 3))
        for kk in range(3):
            forces[:, kk] = np.bincount(i, weights=df[:, kk], minlength=natoms)

        if 'stress' in properties:
            if self.atoms.number_of_lattice_vectors == 3:
                virial = np.zeros(6)
                if len(i) > 0:
                    virial = 0.5 * np.array([
                        dr[:, 0] * df[:, 0],  # xx
                        dr[:, 1] * df[:, 1],  # yy
                        dr[:, 2] * df[:, 2],  # zz
                        dr[:, 1] * df[:, 2],  # yz
                        dr[:, 0] * df[:, 2],  # xz
                        dr[:, 0] * df[:, 1]
                    ]).sum(axis=1)  # xy
                self.results['stress'] = virial / atoms.get_volume()
            else:
                raise PropertyNotImplementedError

        self.results['energy'] = energy
        self.results['free_energy'] = energy
        self.results['forces'] = forces
        self.results['local_energy'] = local_energy
Esempio n. 40
0
    def test_neighbour_list(self):
        a = io.read('aC.cfg')
        j, dr, i, abs_dr = neighbour_list("jDid", a, 1.85)

        self.assertTrue((np.bincount(i) == np.bincount(j)).all())

        r = a.get_positions()
        dr_direct = mic(r[j] - r[i], a.cell)

        abs_dr_from_dr = np.sqrt(np.sum(dr * dr, axis=1))
        abs_dr_direct = np.sqrt(np.sum(dr_direct * dr_direct, axis=1))

        self.assertTrue(np.all(np.abs(abs_dr - abs_dr_from_dr) < 1e-12))
        self.assertTrue(np.all(np.abs(abs_dr - abs_dr_direct) < 1e-12))

        self.assertTrue(np.all(np.abs(dr - dr_direct) < 1e-12))
Esempio n. 41
0
    def test_neighbour_list(self):
        a = io.read('aC.cfg')
        j, dr, i, abs_dr = neighbour_list("jDid", a, 1.85)

        self.assertTrue((np.bincount(i) == np.bincount(j)).all())

        r = a.get_positions()
        dr_direct = mic(r[j]-r[i], a.cell)

        abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1))
        abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1))

        self.assertTrue(np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12))
        self.assertTrue(np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12))

        self.assertTrue(np.all(np.abs(dr-dr_direct) < 1e-12))
Esempio n. 42
0
    def test_shrink_wrapped_direct_call(self):
        a = io.read('aC.cfg')
        r = a.positions
        j, dr, i, abs_dr, shift = neighbour_list("jDidS",
                                                 positions=r,
                                                 cutoff=1.85)

        self.assertTrue((np.bincount(i) == np.bincount(j)).all())

        dr_direct = r[j] - r[i]
        abs_dr_from_dr = np.sqrt(np.sum(dr * dr, axis=1))
        abs_dr_direct = np.sqrt(np.sum(dr_direct * dr_direct, axis=1))

        self.assertTrue(np.all(np.abs(abs_dr - abs_dr_from_dr) < 1e-12))
        self.assertTrue(np.all(np.abs(abs_dr - abs_dr_direct) < 1e-12))

        self.assertTrue(np.all(np.abs(dr - dr_direct) < 1e-12))
Esempio n. 43
0
    def test_neighbour_list(self):
        for pbc in [True, False, [True, False, True]]:
            a = io.read('aC.cfg')
            a.set_pbc(pbc)
            j, dr, i, abs_dr, shift = neighbour_list("jDidS", a, 1.85)

            self.assertTrue((np.bincount(i) == np.bincount(j)).all())

            r = a.get_positions()
            dr_direct = mic(r[j]-r[i], a.cell)
            self.assertArrayAlmostEqual(r[j]-r[i]+shift.dot(a.cell), dr_direct)

            abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1))
            abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1))

            self.assertTrue(np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12))
            self.assertTrue(np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12))

            self.assertTrue(np.all(np.abs(dr-dr_direct) < 1e-12))
Esempio n. 44
0
def get_angle_distribution(at, cutoff=1.98):

    from matscipy.neighbours import neighbour_list
    from itertools import combinations

    ii, jj, DD = neighbour_list('ijD', at, cutoff) 

    angles = []
    for atom in at:
        if atom.number == 8:
            neighs = np.where(ii == atom.index)[0]
            # Si_1, Si_2 = jj[neighs]
            # D_1, D_2 = DD[neighs]
            # print(np.linalg.norm(D_2 - D_1))
            # print(Si_1, Si_2)
            for Si_1, Si_2 in combinations(jj[neighs], 2):
                angle = at.get_angle([Si_1, atom.index, Si_2])
                angles.append(angle)
    return np.array(angles)
Esempio n. 45
0
def atomic_strain(atoms_now, atoms_old, cutoff=None, neighbours=None):
    """
    Calculate deformation gradient tensor and D^2_min measure for non-affine
    displacements.
    See: Falk, Langer, Phys. Rev. B 57, 7192 (1998)

    Parameters:
    -----------
    atoms_now : ase.Atoms
        Current atomic configuration
    atoms_old : ase.Atoms
        Reference atomic configuration
    cutoff : float
        Neighbor list cutoff.
    neighbours : ( array_like, array_like )
        Neighbor list. Automatically computed if not provided.

    Returns:
    --------
    delta_plus_epsilon : array
        3x3 deformation gradient tensor for each atom.
    residual : array
        D^2_min norm for each atom
    """

    if neighbours is None:
        if cutoff is None:
            raise ValueError('Please provide either neighbor list or neighbor '
                             'list cutoff.')

        # Get neighbours
        i_now, j_now = neighbour_list("ij", atoms_now, cutoff)
    elif cutoff is not None:
        raise ValueError('Please provide either neighbor list or neighbor '
                         'list cutoff, not both.')
    else:
        i_now, j_now = neighbours

    # Get strain gradient tensor and D square values
    delta_plus_epsilon, residual = get_D_square_min(atoms_now, atoms_old,
                                                    i_now, j_now)

    return delta_plus_epsilon, residual
Esempio n. 46
0
    def test_single_ring(self):
        a = ase.build.molecule('C6H6')
        a = a[a.numbers==6]
        a.center(vacuum=5)

        i, j, r = neighbour_list('ijD', a, 1.85)
        d = distances_on_graph(i, j)

        self.assertEqual(d.shape, (6,6))

        self.assertArrayAlmostEqual(d-d.T, np.zeros_like(d))

        dcheck = np.arange(len(a))
        dcheck = np.abs(dcheck.reshape(1,-1)-dcheck.reshape(-1,1))
        dcheck = np.where(dcheck > len(a)/2, len(a)-dcheck, dcheck)
        self.assertArrayAlmostEqual(d, dcheck)

        r = find_sp_rings(i, j, r, d)
        self.assertArrayAlmostEqual(r, [0,0,0,0,0,0,1])
Esempio n. 47
0
def atomic_strain(atoms_now, atoms_old, cutoff=None, neighbours=None):
    """
    Calculate deformation gradient tensor and D^2_min measure for non-affine
    displacements.
    See: Falk, Langer, Phys. Rev. B 57, 7192 (1998)

    Parameters:
    -----------
    atoms_now : ase.Atoms
        Current atomic configuration
    atoms_old : ase.Atoms
        Reference atomic configuration
    cutoff : float
        Neighbor list cutoff.
    neighbours : ( array_like, array_like )
        Neighbor list. Automatically computed if not provided.

    Returns:
    --------
    delta_plus_epsilon : array
        3x3 deformation gradient tensor for each atom.
    residual : array
        D^2_min norm for each atom
    """

    if neighbours is None:
        if cutoff is None:
            raise ValueError('Please provide either neighbor list or neighbor '
                             'list cutoff.')

        # Get neighbours
        i_now, j_now = neighbour_list("ij", atoms_now, cutoff)
    elif cutoff is not None:
        raise ValueError('Please provide either neighbor list or neighbor '
                         'list cutoff, not both.')
    else:
        i_now, j_now = neighbours

    # Get strain gradient tensor and D square values
    delta_plus_epsilon, residual = get_D_square_min(atoms_now, atoms_old, i_now,
                                                    j_now)

    return delta_plus_epsilon, residual
Esempio n. 48
0
    def test_neighbour_list(self):
        for pbc in [True, False, [True, False, True]]:
            a = io.read('aC.cfg')
            a.set_pbc(pbc)
            j, dr, i, abs_dr, shift = neighbour_list("jDidS", a, 1.85)

            self.assertTrue((np.bincount(i) == np.bincount(j)).all())

            r = a.get_positions()
            dr_direct = mic(r[j]-r[i], a.cell)
            self.assertArrayAlmostEqual(r[j]-r[i]+shift.dot(a.cell), dr_direct)

            abs_dr_from_dr = np.sqrt(np.sum(dr*dr, axis=1))
            abs_dr_direct = np.sqrt(np.sum(dr_direct*dr_direct, axis=1))

            self.assertTrue(np.all(np.abs(abs_dr-abs_dr_from_dr) < 1e-12))
            self.assertTrue(np.all(np.abs(abs_dr-abs_dr_direct) < 1e-12))

            self.assertTrue(np.all(np.abs(dr-dr_direct) < 1e-12))
Esempio n. 49
0
def hydrogenate_Os(atoms, OHdistance=0.98, cutoff=2.0, mask=None):
    """
    Every Oxygen atom that sticks out undercoordinated gets a H atom.
    Orientation of O--H bond is rather arbitrary.
    """

    if mask is None:
        mask = np.ones(len(atoms))

    ii, jj, DD, SS = neighbour_list("ijDS", atoms, cutoff)

    species = atoms.get_atomic_numbers()
    for i, yes in zip(range(len(atoms)), mask):
        if species[i] == 8 and yes:
            neighbours = np.where(ii == i)[0]
            if len(neighbours) == 1:
                distance = DD[neighbours].flatten()
                posH = atoms.get_positions()[i] - OHdistance * distance / LA.norm(distance)
                atoms.append(Atom(symbol="H", position=posH))
    return
Esempio n. 50
0
    def calculate(self, atoms, properties, system_changes):
        Calculator.calculate(self, atoms, properties, system_changes)

        a = self.parameters['a']
        rc = self.parameters['rc']
        k = self.parameters['k']
        beta = self.parameters['beta']

        energies = np.zeros(len(atoms))
        forces = np.zeros((len(atoms), 3))
        velocities = (atoms.get_momenta().T/atoms.get_masses()).T
                
        i, j, dr, r = neighbour_list('ijDd', atoms, rc)
        if len(i) > 0:
            dr_hat = (dr.T/r).T
            dv = velocities[j] - velocities[i]

            de = 0.5*k*(r - a)**2 # spring energies
            e = 0.5*de # half goes to each end of spring
            f = (k*(r - a)*dr_hat.T).T + beta*dv

            energies[:] = np.bincount(i, e)            
            for kk in range(3):
                forces[:, kk] = np.bincount(i, weights=f[:, kk])

        energy = energies.sum()
            
        # add energy 0.5*k*(rc - a)**2 for each broken bond
        if len(i) < self.crystal_bonds:
            de = 0.5*k*(rc - a)**2
            energy += 0.5*de*(self.crystal_bonds - len(i))

        # Stokes dissipation
        if 'stokes' in atoms.arrays:
            b = atoms.get_array('stokes')
            forces -= (velocities.T*b).T
        
        self.results = {'energy':   energy,
                        'forces':   forces}
def spatial_correlation_function_near(atoms, values, gridsize=None,
                                      cutoff=None, norm=False):
    if gridsize is None:
        gridsize = 0.1

    if cutoff is None:
        cutoff = 7.5

    # close range exact calculation
    nbins = int(cutoff/gridsize)+1
    index1,index2,dist = neighbour_list('ijd', atoms, cutoff=cutoff)
    SCF_near, edges = np.histogram(dist, bins=bins,
                                   weights=values[index1]
                                   *values[index2])
    slice_volume = 4*np.pi/3 * (edges[1:]**3-edges[:-1]**3)
    SCF_near *= atoms.get_volume()/n_atoms**2 / slice_volume
    if norm:
        v_2_mean = (values**2).mean()
        v_mean_2 = (values.mean())**2
        SCF_near = (SCF_near-v_mean_2)/(v_2_mean-v_mean_2)

    return SCF_near, (edges[1:]+edges[:-1])/2
Esempio n. 52
0
def ring_statistics(a, cutoff, maxlength=-1):
    """
    Compute number of shortest path rings in sample.
    See: D.S. Franzblau, Phys. Rev. B 44, 4925 (1991)

    Parameters
    ----------
    a : ase.Atoms
        Atomic configuration.
    cutoff : float
        Cutoff for neighbor counting.
    maxlength : float, optional
        Maximum ring length. Search for rings will stop at this length. This
        is useful to speed up calculations for large systems.

    Returns
    -------
    ringstat : array
        Array with number of shortest path rings.
    """
    i, j, r = neighbour_list('ijD', a, cutoff)
    d = _matscipy.distances_on_graph(i, j)
    return _matscipy.find_sp_rings(i, j, r, d, maxlength)
from fundef import minimal_cycles
from itertools import combinations
import _matscipy

########################################################################
########################################################################


at = aseread('../data/bilayer_TSmin.xyz', format='extxyz')

top = at[np.where(at.positions[:,2] > -.5)[0]]
top_si = top[np.where(top.get_atomic_numbers() == 14)[0]]
top_o = top[np.where(top.get_atomic_numbers() == 8)[0]]

cutoff = 1.97
ii, jj = neighbour_list('ij', top, cutoff)
neighbour_si = []
neighbour_o = []
angles = []
graph = nx.Graph()
for atom in top:
    if atom.number == 8:
        neighs = np.where(ii == atom.index)[0]
        for Si_1, Si_2 in combinations(jj[neighs], 2):
            graph.add_edge(Si_1, Si_2)
            graph[Si_1][Si_2]['oxygen'] = atom.index
            neighbour_o.append(atom.index)
            neighbour_si.append([Si_1, Si_2])
            angle = at.get_angle([Si_1, atom.index, Si_2])
            angles.append(angle)
Esempio n. 54
0
# Center notched configuration in simulation cell and ensure enough vacuum.
oldr = a[0].position.copy()
a.center(vacuum=params.vacuum, axis=0)
a.center(vacuum=params.vacuum, axis=1)
tip_x += a[0].position[0] - oldr[0]
tip_y += a[0].position[1] - oldr[1]

# Choose which bond to break.
bond1, bond2 = parameter('bond',
                         crack.find_tip_coordination(a, bondlength=bondlength))

# Hydrogenate?
if parameter('hydrogenate', False):
    # Get surface atoms of cluster with crack
    coord = np.bincount(neighbour_list('i', a, bondlength), minlength=len(a))
    # Exclude all atoms of the crack face from hydrogenation
    exclude = np.logical_and(a.get_array('groups')==1, coord!=4)
    a.set_array('coord', coord)
    a.set_array('exclude', exclude)
    a = hydrogenate(cryst, bondlength, parameter('XH_bondlength'), b=a,
                    exclude=exclude)
    g = a.get_array('groups')
    g[np.array(a.get_chemical_symbols())=='H'] = -1
    a.set_array('groups', g)
    ase.io.write('{0}_hydrogenated.cfg'.format(basename), a)

# Move reference crystal by same amount
cryst.set_cell(a.cell)
cryst.set_pbc([False, False, True])
cryst.translate(a[0].position - oldr)