def test_lattice_lindep():
    from ase.lattice.cubic import FaceCenteredCubic
    from ase.lattice.hexagonal import HexagonalClosedPacked
    from ase.test import must_raise

    with must_raise(ValueError):
        # The Miller indices of the surfaces are linearly dependent
        atoms = FaceCenteredCubic(symbol='Cu',
                                  miller=[[1, 1, 0], [1, 1, 0], [0, 0, 1]])

    # This one should be OK:
    atoms = FaceCenteredCubic(symbol='Cu',
                              miller=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
    print(atoms.get_cell())

    with must_raise(ValueError):
        # The directions spanning the unit cell are linearly dependent
        atoms = FaceCenteredCubic(symbol='Cu',
                                  directions=[[1, 1, 0], [1, 1, 0], [0, 0, 1]])

    with must_raise(ValueError):
        # The directions spanning the unit cell are linearly dependent
        atoms = FaceCenteredCubic(symbol='Cu',
                                  directions=[[1, 1, 0], [1, 0, 0], [0, 1, 0]])

    # This one should be OK:
    atoms = FaceCenteredCubic(symbol='Cu',
                              directions=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
    print(atoms.get_cell())

    with must_raise((ValueError, NotImplementedError)):
        # The Miller indices of the surfaces are linearly dependent
        atoms = HexagonalClosedPacked(symbol='Mg',
                                      miller=[[1, -1, 0, 0], [1, 0, -1, 0],
                                              [0, 1, -1, 0]])

    # This one should be OK
    #
    # It is not!  The miller argument is broken in hexagonal crystals!
    #
    # atoms = HexagonalClosedPacked(symbol='Mg',
    #                               miller=[[1, -1, 0, 0],
    #                                       [1, 0, -1, 0],
    #                                       [0, 0, 0, 1]])
    # print(atoms.get_cell())

    with must_raise(ValueError):
        # The directions spanning the unit cell are linearly dependent
        atoms = HexagonalClosedPacked(symbol='Mg',
                                      directions=[[1, -1, 0, 0], [1, 0, -1, 0],
                                                  [0, 1, -1, 0]])

    # This one should be OK
    atoms = HexagonalClosedPacked(symbol='Mg',
                                  directions=[[1, -1, 0, 0], [1, 0, -1, 0],
                                              [0, 0, 0, 1]])
    print(atoms.get_cell())
Пример #2
0
    def SurfaceEnergy_Calculator(self, EMT, PARAMETERS):
        """ The Method calculates and returns the surface energy for the given element along the [0,0,1] and [1,1,1] 
            directions in the FCC crystal structure. """
        # The size of the crystals are set " NEED TO THINK ABOUT THESE LATER! "
        S001 = 3, 3, 5
        S111 = 5, 5, 5
        # The surfaces (slabs) are created (pbc=(1,1,0) creates periodic boudry conditions
        # in two of three directions and thus leaves the last direction as two surfaces.
        Surface001 = FaceCenteredCubic(size=S001,
                                       symbol=self.Element,
                                       pbc=(1, 1, 0))
        Surface111 = FaceCenteredCubic(size=S111,
                                       directions=[[1, -1, 0], [1, 1, -2],
                                                   [1, 1, 1]],
                                       symbol=self.Element,
                                       pbc=(1, 1, 0))
        Surface001.set_calculator(EMT)
        Surface111.set_calculator(EMT)

        # A structural relaxsation is run for the surface crystal in order to secure
        # the correct structure of the crystal.
        dyn001 = BFGS(Surface001, trajectory='relaxedsurface001.traj')
        dyn111 = BFGS(Surface111, trajectory='relaxedsurface111.traj')
        dyn001.run(fmax=0.01)
        dyn111.run(fmax=0.01)

        # The referance bulk crystals are created
        Bulk001 = FaceCenteredCubic(size=S001, symbol=self.Element)
        Bulk111 = FaceCenteredCubic(size=S111,
                                    directions=[[1, -1, 0], [1, 1, -2],
                                                [1, 1, 1]],
                                    symbol=self.Element)

        # The calculator is assigned
        Bulk001.set_calculator(EMT)
        Bulk111.set_calculator(EMT)

        # The surface area is calculated
        # The cross product between the x and y axis in the crystal is determined
        Cross001 = numpy.cross(Bulk001.get_cell()[:, 0],
                               Bulk001.get_cell()[:, 1])
        Cross111 = numpy.cross(Bulk111.get_cell()[:, 0],
                               Bulk111.get_cell()[:, 1])
        # The area of the surface is determined from the formular A = |X x Y|.
        area001 = numpy.sqrt(numpy.dot(Cross001, Cross001))
        area111 = numpy.sqrt(numpy.dot(Cross111, Cross111))

        # The surface energy is calculated and returned (two surfaces are present in
        # SurfaceRelaxed)
        return ((Surface001.get_potential_energy() -
                 Bulk001.get_potential_energy()) / 2 / area001,
                (Surface111.get_potential_energy() -
                 Bulk111.get_potential_energy()) / 2 / area111)
Пример #3
0
def atoms():
    # (100) oriented block
    atoms = FaceCenteredCubic(size=(5, 5, 5), symbol=symb, pbc=(1, 1, 0))
    assert len(atoms) == 5 * 5 * 5 * 4
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 2)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(5 * a0 - c[2, 2]) < 1e-10
    return atoms
Пример #4
0
    def C44_Calculator(self, EMT, PARAMETERS):
        # Return 0 is used when the method is not desired to be used
        # return 0
        """ This method uses the given EMT calculator to calculate and return the value of the matrix element C44 for 
            a system of atoms of a given element type. The calculation is done by using that:
            C44 = 1 / Volume * d^2/depsilon^2 (E_system) where epsilon is the displacement in one direction of the 
            system along one axis diveded by the highth of the system. """

        # An atom object is created and the calculator attached
        atoms = FaceCenteredCubic(size=(self.Size, self.Size, self.Size),
                                  symbol=self.Element)
        atoms.set_calculator(EMT)

        # The volume of the sample is calculated
        Vol = atoms.get_volume()

        # The value of the relative displacement, epsilon, is set
        epsilon = 1. / 1000

        # The matrix used to change the unitcell by n*epsilon is initialized
        LMM = numpy.array([[1, 0, -10 * epsilon], [0, 1, 0], [0, 0, 1]])

        # The original unit cell is conserved
        OCell = atoms.get_cell()

        # The array for storing the energies is initialized
        E_calc = numpy.zeros(20)

        # The numerical value of C44 is calculated
        for i in range(20):
            # The new system cell based on the pertubation epsilon is set
            atoms.set_cell(numpy.dot(OCell, LMM), scale_atoms=True)
            # The energy of the system is calculated
            E_calc[i] = atoms.get_potential_energy()
            # The value of LMM is updated
            LMM[0, 2] += epsilon

        # A polynomial fit is made for the energy as a function of epsilon

        # The displaced axis is defined
        da = numpy.arange(-10, 10) * epsilon

        # The fit is made
        Poly = numpyfit.polyfit(da, E_calc, 2)

        # Now C44 can be estimated from this fit by the second derivative of Poly = a * x^2 + b * x + c , multiplied
        # with 1 / (2 * Volume) of system
        C44 = 2. / Vol * Poly[0]

        return C44
def test_minimum_image_convention(dim):
    size = 2
    if dim == 2:
        pbc = [True, True, False]
    else:
        pbc = [True, True, True]
    atoms = FaceCenteredCubic(size=[size, size, size],
                              symbol='Cu',
                              latticeconstant=2,
                              pbc=pbc)
    if dim == 2:
        cell = atoms.cell.uncomplete(atoms.pbc)
        atoms.set_cell(cell, scale_atoms=False)

    d0 = atoms.get_distances(0, np.arange(len(atoms)), mic=True)

    if dim == 2:
        U = np.array([[1, 2, 0], [0, 1, 0], [0, 0, 1]])
    else:
        U = np.array([[1, 2, 2], [0, 1, 2], [0, 0, 1]])
    assert np.linalg.det(U) == 1
    atoms.set_cell(U.T @ atoms.cell, scale_atoms=False)
    atoms.wrap()

    d1 = atoms.get_distances(0, np.arange(len(atoms)), mic=True)
    assert_allclose(d0, d1)

    vnbrlist = NeighborListMic(atoms.get_positions(), atoms.cell, atoms.pbc)
    d2 = np.linalg.norm(vnbrlist, axis=1)
    assert_allclose(d0, d2)

    nl = NeighborList(np.ones(len(atoms)) * 2 * size * np.sqrt(3),
                      bothways=True,
                      primitive=PrimitiveNeighborList)
    nl.update(atoms)
    indices, offsets = nl.get_neighbors(0)

    d3 = float("inf") * np.ones(len(atoms))
    for i, offset in zip(indices, offsets):
        p = atoms.positions[i] + offset @ atoms.get_cell()
        d = np.linalg.norm(p - atoms.positions[0])
        d3[i] = min(d3[i], d)
    assert_allclose(d0, d3)
Пример #6
0
    def Surface110(self, EMT, PARAMETERS):
        """ The Method calculates and returns the surface energy for the given element along the [1,1,0] direction in   
            the FCC crystal structure. """
        # The size of the crystals are set:
        S110 = 3, 5, 5
        # The surfaces (slabs) are created (pbc=(1,1,0) creates periodic boudry conditions
        # in two of three directions and thus leaves the last direction as two surfaces.
        Surface110 = FaceCenteredCubic(size=S110,
                                       directions=[[1, -1, 0], [0, 0, 1],
                                                   [1, 1, 0]],
                                       symbol=self.Element,
                                       pbc=(1, 1, 0))
        Surface110.set_calculator(EMT)

        # A structural relaxsation is run for the surface crystal in order to secure
        # the correct structure of the crystal.
        dyn001 = BFGS(Surface110, logfile=None)
        dyn001.run(fmax=0.01)

        # The referance bulk crystals are created
        Bulk110 = FaceCenteredCubic(size=S110,
                                    directions=[[1, -1, 0], [0, 0, 1],
                                                [1, 1, 0]],
                                    symbol=self.Element)

        # The calculator is assigned
        Bulk110.set_calculator(EMT)

        # The surface area is calculated
        # The cross product between the x and y axis in the crystal is determined
        Cross110 = numpy.cross(Bulk110.get_cell()[:, 0],
                               Bulk110.get_cell()[:, 1])
        # The area of the surface is determined from the formular A = |X x Y|.
        area110 = numpy.sqrt(numpy.dot(Cross110, Cross110))

        # The surface energy is calculated and returned (two surfaces are present in
        # SurfaceRelaxed)
        return ((Surface110.get_potential_energy() -
                 Bulk110.get_potential_energy()) / 2 / area110)
def test_minimum_image_convention():
    import numpy as np
    from numpy.testing import assert_allclose
    from ase.lattice.cubic import FaceCenteredCubic
    from ase.neighborlist import mic as NeighborListMic
    from ase.neighborlist import NeighborList, PrimitiveNeighborList

    size = 2
    atoms = FaceCenteredCubic(size=[size, size, size],
                              symbol='Cu',
                              latticeconstant=2,
                              pbc=(1, 1, 1))

    d0 = atoms.get_distances(0, np.arange(len(atoms)), mic=True)

    U = np.array([[1, 2, 2], [0, 1, 2], [0, 0, 1]])
    assert np.linalg.det(U) == 1
    atoms.set_cell(U.T @ atoms.cell, scale_atoms=False)
    atoms.wrap()

    d1 = atoms.get_distances(0, np.arange(len(atoms)), mic=True)
    assert_allclose(d0, d1)

    vnbrlist = NeighborListMic(atoms.get_positions(), atoms.cell, atoms.pbc)
    d2 = np.linalg.norm(vnbrlist, axis=1)
    assert_allclose(d0, d2)

    nl = NeighborList(np.ones(len(atoms)) * 2 * size * np.sqrt(3),
                      bothways=True,
                      primitive=PrimitiveNeighborList)
    nl.update(atoms)
    indices, offsets = nl.get_neighbors(0)

    d3 = float("inf") * np.ones(len(atoms))
    for i, offset in zip(indices, offsets):
        p = atoms.positions[i] + offset @ atoms.get_cell()
        d = np.linalg.norm(p - atoms.positions[0])
        d3[i] = min(d3[i], d)
    assert_allclose(d0, d3)
Пример #8
0
def MakeAtoms(elem1, elem2=None):
    if elem2 is None:
        elem2 = elem1
    a1 = reference_states[elem1]['a']
    a2 = reference_states[elem2]['a']
    a0 = (0.5 * a1**3 + 0.5 * a2**3)**(1.0 / 3.0) * 1.03
    if ismaster:
        print "Z1 = %i,  Z2 = %i,  a0 = %.5f" % (elem1, elem2, a0)
    # 50*50*50 would be big enough, but some vacancies are nice.
    atoms = FaceCenteredCubic(symbol='Cu', size=(51, 51, 51))
    nremove = len(atoms) - 500000
    assert nremove > 0
    remove = np.random.choice(len(atoms), nremove, replace=False)
    del atoms[remove]
    if elem1 != elem2:
        z = atoms.get_atomic_numbers()
        z[np.random.choice(len(atoms), len(atoms) / 2, replace=False)] = elem2
        atoms.set_atomic_numbers(z)
    if isparallel:
        # Move this contribution into position
        uc = atoms.get_cell()
        x = mpi.world.rank % cpuLayout[0]
        y = (mpi.world.rank // cpuLayout[0]) % cpuLayout[1]
        z = mpi.world.rank // (cpuLayout[0] * cpuLayout[1])
        assert (0 <= x < cpuLayout[0])
        assert (0 <= y < cpuLayout[1])
        assert (0 <= z < cpuLayout[2])
        offset = x * uc[0] + y * uc[1] + z * uc[2]
        new_uc = cpuLayout[0] * uc[0] + cpuLayout[1] * uc[1] + cpuLayout[
            2] * uc[2]
        atoms.set_cell(new_uc, scale_atoms=False)
        atoms.set_positions(atoms.get_positions() + offset)
        # Distribute atoms. Maybe they are all on the wrong cpu, but that will
        # be taken care of.
        atoms = MakeParallelAtoms(atoms, cpuLayout)
    MaxwellBoltzmannDistribution(atoms, T * units.kB)
    return atoms
Пример #9
0
def MakeAtoms(elem1, elem2=None):
    if elem2 is None:
        elem2 = elem1
    a1 = reference_states[elem1]['a']
    a2 = reference_states[elem2]['a']
    a0 = (0.5 * a1**3 + 0.5 * a2**3)**(1.0/3.0) * 1.03
    if ismaster:
        print "Z1 = %i,  Z2 = %i,  a0 = %.5f" % (elem1, elem2, a0)
    # 50*50*50 would be big enough, but some vacancies are nice.
    atoms = FaceCenteredCubic(symbol='Cu', size=(51,51,51))
    nremove = len(atoms) - 500000
    assert nremove > 0
    remove = np.random.choice(len(atoms), nremove, replace=False)
    del atoms[remove]
    if elem1 != elem2:
        z = atoms.get_atomic_numbers()
        z[np.random.choice(len(atoms), len(atoms)/2, replace=False)] = elem2
        atoms.set_atomic_numbers(z)
    if isparallel:
        # Move this contribution into position
        uc = atoms.get_cell()
        x = mpi.world.rank % cpuLayout[0]
        y = (mpi.world.rank // cpuLayout[0]) % cpuLayout[1]
        z = mpi.world.rank // (cpuLayout[0] * cpuLayout[1])
        assert(0 <= x < cpuLayout[0])
        assert(0 <= y < cpuLayout[1])
        assert(0 <= z < cpuLayout[2])
        offset = x * uc[0] + y * uc[1] + z * uc[2]
        new_uc = cpuLayout[0] * uc[0] + cpuLayout[1] * uc[1] + cpuLayout[2] * uc[2]
        atoms.set_cell(new_uc, scale_atoms=False)
        atoms.set_positions(atoms.get_positions() + offset)
        # Distribute atoms. Maybe they are all on the wrong cpu, but that will
        # be taken care of.
        atoms = MakeParallelAtoms(atoms, cpuLayout)
    MaxwellBoltzmannDistribution(atoms, T * units.kB)
    return atoms
Пример #10
0
def test_fcc_directions_ok():
    atoms = FaceCenteredCubic(symbol='Cu',
                              directions=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
    print(atoms.get_cell())
Пример #11
0
def test_fcc_ok():
    atoms = FaceCenteredCubic(symbol='Cu',
                              miller=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
    print(atoms.get_cell())
Пример #12
0
        directed (bool): whether the old one was directed
            or not  
    """
    nbr_list_reverse = torch.stack(
        [nbr_list[:, 0], nbr_list[:, 2], nbr_list[:, 1]], dim=-1)
    new_nbrs = torch.cat([nbr_list, nbr_list_reverse], dim=0)

    return new_nbrs


if __name__ == "__main__":

    from ase.lattice.cubic import FaceCenteredCubic

    atoms = FaceCenteredCubic(symbol='H',
                              size=(3, 3, 3),
                              latticeconstant=1.679,
                              pbc=True)

    from ase.neighborlist import neighbor_list

    i, j, d = neighbor_list("ijD", atoms, cutoff=2.5, self_interaction=False)

    print("ASE calculated {} pairs".format(i.shape[0]))
    xyz = torch.Tensor(atoms.get_positions())
    cell = torch.Tensor(atoms.get_cell())
    cutoff = 2.5

    nbr_list, offsets = generate_nbr_list(xyz, cutoff, cell)

    print("torchmd calculated {} pairs".format(nbr_list.shape[0] * 2))
Пример #13
0
pi = np.pi

d = 4.08
atoms = FaceCenteredCubic('Au',
                          latticeconstant=d,
                          directions=((0, 1, 1), (1, 0, 1), (1, 1, 0)),
                          align=False)

calc = Hotbit(SCC=False, kpts=(8, 8, 8), txt='bs.cal')
atoms.set_calculator(calc)
atoms.get_potential_energy()

# reciprocal lattice vectors
V = atoms.get_volume()
a, b, c = atoms.get_cell()
a_ = 2 * pi / V * np.cross(b, c)
b_ = 2 * pi / V * np.cross(c, a)
c_ = 2 * pi / V * np.cross(a, b)

gamma = np.array((0, 0, 0))

# a path which connects the L-points and gamma-point
kpts, distances, label_points = interpolate_path(
    (-a_ / 2, a_ / 2, gamma, -b_ / 2, b_ / 2, gamma, -c_ / 2, c_ / 2, gamma,
     (-a_ - b_ - c_) / 2, (a_ + b_ + c_) / 2), 500)
labels = [
    "$-a$", '$a$', '$\Gamma$', '$-b$', '$b$', '$\Gamma$', '$-c$', '$c$',
    '$\Gamma$', '$-a-b-c$', '$a+b+c$'
]
Пример #14
0
e3 = atoms.get_potential_energy()
ReportTest("e3 correct", e3, ecorrect, 0.001)

atoms.set_pbc((1,1,0))
atoms.set_positions(atoms.get_positions())
e4 = atoms.get_potential_energy()
ReportTest("e4 correct", e4, ecorrect, 0.001)

print "Repeating tests with an atom outside the unit cell."
for coordinate in (0,1,2):
    print "Using coordinate number", coordinate

    atoms = FaceCenteredCubic(directions=[[1,0,0],[0,1,0],[0,0,1]], size=(6,6,6),
                              symbol="Cu", pbc=(1,1,0))
    r = atoms.get_positions()
    uc = atoms.get_cell()
    r[-1,coordinate] = uc[coordinate,coordinate] * 1.51
    atoms.set_positions(r)
    atoms.set_calculator(EMT())
    ecorrect = atoms.get_potential_energy()

    atoms.set_pbc((0,1,0))
    atoms.set_pbc((1,1,0))
    e2 = atoms.get_potential_energy()
    ReportTest("e2 correct", e2, ecorrect, 0.001)

    atoms.set_pbc((0,1,0))
    dummy =  atoms.get_potential_energy()
    assert(fabs(dummy - ecorrect) > 1.0)
    atoms.set_pbc((1,1,0))
    e3 = atoms.get_potential_energy()
Пример #15
0
import numpy as np
from ase.lattice.cubic import FaceCenteredCubic
ag = FaceCenteredCubic(directions=[[1, 0, 0],
                                   [0, 1, 0],
                                   [0, 0, 1]],
                       size=(1, 1, 1),
                       symbol='Ag',
                       latticeconstant=4.0)
# these are the reciprocal lattice vectors
b1, b2, b3 = np.linalg.inv(ag.get_cell())
'''
g(111) = 1*b1 + 1*b2 + 1*b3
and |g(111)| = 1/d_111
'''
h,k,l = (1, 1, 1)
d = 1./np.linalg.norm(h*b1 + k*b2 + l*b3)
print('d_111 spacing (method 1) = {0:1.3f} Angstroms'.format(d))
# method #2
hkl = np.array([h, k, l])
G = np.array([b1, b2, b3])  # reciprocal unit cell
'''
Gstar is usually defined as this matrix of dot products:
Gstar = np.array([[dot(b1,b1), dot(b1,b2), dot(b1,b3)],
                  [dot(b1,b2), dot(b2,b2), dot(b2,b3)],
                  [dot(b1,b3), dot(b2,b3), dot(b3,b3)]])
but I prefer the notationally more compact:
Gstar = G .dot. transpose(G)
then, 1/d_hkl^2 = hkl .dot. Gstar .dot. hkl
'''
Gstar = np.dot(G, G.T)
id2 = np.dot(hkl, np.dot(Gstar, hkl))
Пример #16
0
#some algebra to determine surface normal and the plane of the surface
d3 = [2, 1, 1]
a1 = np.array([0, 1, 1])
d1 = np.cross(a1, d3)
a2 = np.array([0, -1, 1])
d2 = np.cross(a2, d3)

#create your slab
slab = FaceCenteredCubic(directions=[d1, d2, d3],
                         size=(2, 1, 2),
                         symbol=('Pt'),
                         latticeconstant=3.9)

#add some vacuum to your slab
uc = slab.get_cell()
print(uc)
uc[2] += [0, 0, 10]  #there are ten layers of vacuum
uc = slab.set_cell(uc, scale_atoms=False)
#view the slab to make sure it is how you expect
view(slab)

#some positions needed to place the atom in the correct place
x1 = 1.379
x2 = 4.137
x3 = 2.759
y1 = 0.0
y2 = 2.238
z1 = 7.165
z2 = 6.439
Пример #17
0
def test_center():
    # flake8: noqa
    "Test that atoms.center() works when adding vacuum ()"

    import numpy as np
    from math import pi, sqrt, cos
    from ase import data
    from ase.lattice.cubic import FaceCenteredCubic

    def checkang(a, b, phi):
        "Check the angle between two vectors."
        cosphi = np.dot(a, b) / sqrt(np.dot(a, a) * np.dot(b, b))
        assert np.abs(cosphi - cos(phi)) < 1e-10

    symb = "Cu"
    Z = data.atomic_numbers[symb]
    a0 = data.reference_states[Z]['a']

    # (100) oriented block
    atoms = FaceCenteredCubic(size=(5, 5, 5), symbol="Cu", pbc=(1, 1, 0))
    assert len(atoms) == 5 * 5 * 5 * 4
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 2)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(5 * a0 - c[2, 2]) < 1e-10

    # Add vacuum in one direction
    vac = 10.0
    atoms.center(axis=2, vacuum=vac)
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 2)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(4.5 * a0 + 2 * vac - c[2, 2]) < 1e-10

    # Add vacuum in all directions
    vac = 4.0
    atoms.center(vacuum=vac)
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 2)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(4.5 * a0 + 2 * vac - c[0, 0]) < 1e-10
    assert np.abs(4.5 * a0 + 2 * vac - c[1, 1]) < 1e-10
    assert np.abs(4.5 * a0 + 2 * vac - c[2, 2]) < 1e-10

    # Now a general unit cell
    atoms = FaceCenteredCubic(size=(5, 5, 5),
                              directions=[[1, 0, 0], [0, 1, 0], [1, 0, 1]],
                              symbol="Cu",
                              pbc=(1, 1, 0))
    assert len(atoms) == 5 * 5 * 5 * 2
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 4)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(2.5 * a0 - c[2, 2]) < 1e-10

    # Add vacuum in one direction
    vac = 10.0
    atoms.center(axis=2, vacuum=vac)
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 4)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10

    # Recenter without specifying vacuum
    atoms.center()
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 4)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10

    a2 = atoms.copy()

    # Add vacuum in all directions
    vac = 4.0
    atoms.center(vacuum=vac)
    c = atoms.get_cell()
    checkang(c[0], c[1], pi / 2)
    checkang(c[0], c[2], pi / 4)
    checkang(c[1], c[2], pi / 2)
    assert np.abs(4.5 * a0 + 2 * vac - c[1, 1]) < 1e-10
    assert np.abs(2 * a0 + 2 * vac - c[2, 2]) < 1e-10

    # One axis at the time:
    for i in range(3):
        a2.center(vacuum=vac, axis=i)

    assert abs(atoms.positions - a2.positions).max() < 1e-12
    assert abs(atoms.cell - a2.cell).max() < 1e-12
Пример #18
0
from ase.lattice.cubic import FaceCenteredCubic
from ase.lattice.hexagonal import HexagonalClosedPacked
from ase.test import must_raise

with must_raise(ValueError):
    # The Miller indices of the surfaces are linearly dependent
    atoms = FaceCenteredCubic(symbol='Cu',
                              miller=[[1, 1, 0], [1, 1, 0], [0, 0, 1]])

# This one should be OK:
atoms = FaceCenteredCubic(symbol='Cu',
                          miller=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
print(atoms.get_cell())

with must_raise(ValueError):
    # The directions spanning the unit cell are linearly dependent
    atoms = FaceCenteredCubic(symbol='Cu',
                              directions=[[1, 1, 0], [1, 1, 0], [0, 0, 1]])

with must_raise(ValueError):
    # The directions spanning the unit cell are linearly dependent
    atoms = FaceCenteredCubic(symbol='Cu',
                              directions=[[1, 1, 0], [1, 0, 0], [0, 1, 0]])

# This one should be OK:
atoms = FaceCenteredCubic(symbol='Cu',
                          directions=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
print(atoms.get_cell())

with must_raise((ValueError, NotImplementedError)):
    # The Miller indices of the surfaces are linearly dependent
Пример #19
0
import pylab
from box.interpolation import interpolate_path
pi = np.pi

d = 4.08
atoms = FaceCenteredCubic('Au', latticeconstant=d,
                          directions=((0,1,1),(1,0,1),(1,1,0)),
                          align=False)
                          
calc = Hotbit(SCC=False, kpts=(8,8,8), txt='bs.cal')
atoms.set_calculator(calc)
atoms.get_potential_energy()

# reciprocal lattice vectors
V = atoms.get_volume()
a, b, c = atoms.get_cell()
a_ = 2*pi/V*np.cross(b, c)
b_ = 2*pi/V*np.cross(c, a)
c_ = 2*pi/V*np.cross(a, b)

gamma = np.array( (0,0,0) )

# a path which connects the L-points and gamma-point
kpts, distances, label_points = interpolate_path((-a_/2, a_/2, gamma, -b_/2, b_/2, gamma, -c_/2, c_/2, gamma, (-a_-b_-c_)/2, (a_+b_+c_)/2), 500)
labels = ["$-a$",'$a$','$\Gamma$','$-b$','$b$','$\Gamma$','$-c$','$c$','$\Gamma$','$-a-b-c$','$a+b+c$']


eigs = calc.get_band_energies(kpts,shift=True,rs='k')
e_min = np.min(eigs)
e_max = np.max(eigs)
Пример #20
0
        print "Temperature is now %.2f K" % (T, )
    print "Desired temperature reached!"

    lgv.set_temperature(T_goal * units.kB)

    for i in range(2):
        lgv.run(20)
        s = atoms.get_stress()
        p = -(s[0] + s[1] + s[2]) / 3.0 / units.GPa
        T = atoms.get_kinetic_energy() / (1.5 * atoms.get_number_of_atoms() *
                                          units.kB)
        print "Pressure is %f GPa, desired pressure is %f GPa (T = %.2f K)" % (
            p, p_goal, T)
        dv = (p - p_goal) / bulk
        print "Adjusting volume by", dv
        cell = atoms.get_cell()
        atoms.set_cell(cell * (1.0 + dv / 3.0))

    T = atoms.get_kinetic_energy() / (1.5 * atoms.get_number_of_atoms() *
                                      units.kB)
    print "Temperature is now %.2f K" % (T, )

    stressstate = array([-2, -1, 0, 0, 0, 0]) * p_goal * units.GPa
    dyn = NPT(atoms, 5 * units.fs, T_goal * units.kB, stressstate,
              ttime * units.fs, (ptime * units.fs)**2 * bulk * units.GPa)
    traj = PickleTrajectory("NPT-atoms.traj", "w", atoms)
    #dyntraj = ParallelHooverNPTTrajectory("NPT-dyn-traj.nc", dyn, interval = 50)
    dyn.attach(traj, interval=50)
    #dyn.Attach(dyntraj)

    out = open(out1, "w")
Пример #21
0
    def __init__(self, symbol=None, layers=None, positions=None,
                 latticeconstant=None, symmetry=None, cell=None, 
                 center=None, multiplicity=1, filename=None, debug=0):

        self.debug = debug
        self.multiplicity = multiplicity

        if filename is not None:
            # We skip MonteCarloAtoms.__init__, do it manually.
            self.mc_optim = np.zeros(101, np.intc)
            self.mc_optim[0] = 10000  # MC optim invalid
            self.read(filename)
            return
        
        #Find the atomic number
        if symbol is not None:
            if isinstance(symbol, str):
                self.atomic_number = atomic_numbers[symbol]
            else:
                self.atomic_number = symbol
        else:
            raise Warning('You must specify a atomic symbol or number!')

        #Find the crystal structure
        if symmetry is not None:
            if symmetry.lower() in ['bcc', 'fcc', 'hcp']:
                self.symmetry = symmetry.lower()
            else:
                raise Warning('The %s symmetry does not exist!' % symmetry.lower())
        else:
            self.symmetry = reference_states[self.atomic_number]['symmetry'].lower()

        if self.debug:
            print 'Crystal structure:', self.symmetry

        #Find the lattice constant
        if latticeconstant is None:
            if self.symmetry == 'fcc':
                self.lattice_constant = reference_states[self.atomic_number]['a']
            else:
                raise Warning(('Cannot find the lattice constant ' +
                               'for a %s structure!' % self.symmetry))
        else:
            self.lattice_constant = latticeconstant

        if self.debug:
            print 'Lattice constant(s):', self.lattice_constant

        #Make the cluster of atoms
        if layers is not None and positions is None:
            layers = list(layers)

            #Make base crystal based on the found symmetry
            if self.symmetry == 'fcc':
                if len(layers) != data.lattice[self.symmetry]['surface_count']:
                    raise Warning('Something is wrong with the defined number of layers!')

                xc = int(np.ceil(layers[1] / 2.0)) + 1
                yc = int(np.ceil(layers[3] / 2.0)) + 1
                zc = int(np.ceil(layers[5] / 2.0)) + 1

                xs = xc + int(np.ceil(layers[0] / 2.0)) + 1
                ys = yc + int(np.ceil(layers[2] / 2.0)) + 1
                zs = zc + int(np.ceil(layers[4] / 2.0)) + 1

                center = np.array((xc, yc, zc)) * self.lattice_constant
                size = (xs, ys, zs)

                if self.debug:
                    print 'Base crystal size:', size
                    print 'Center cell position:', center

                atoms = FaceCenteredCubic(symbol=symbol,
                                          size=size,
                                          latticeconstant=self.lattice_constant,
                                          align=False)

            else:
                raise Warning(('The %s crystal structure is not' +
                               ' supported yet.') % self.symmetry)

            positions = atoms.get_positions()
            numbers = atoms.get_atomic_numbers()
            cell = atoms.get_cell()
        elif positions is not None:
            numbers = [self.atomic_number] * len(positions)
        else:
            numbers = None

        #Load the constructed atoms object into this object
        self.set_center(center)
        MonteCarloAtoms.__init__(self, numbers=numbers, positions=positions,
                                 cell=cell, pbc=False)

        #Construct the particle with the assigned surfasces
        if layers is not None:
            self.set_layers(layers)
Пример #22
0
from __future__ import print_function, division
from ase.lattice.cubic import FaceCenteredCubic
from ase.lattice.hexagonal import HexagonalClosedPacked
from ase.test import must_raise

with must_raise(ValueError):
    # The Miller indices of the surfaces are linearly dependent
    atoms = FaceCenteredCubic(symbol='Cu',
                              miller=[[1, 1, 0], [1, 1, 0], [0, 0, 1]])

# This one should be OK:
atoms = FaceCenteredCubic(symbol='Cu',
                          miller=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
print(atoms.get_cell())


with must_raise(ValueError):
    # The directions spanning the unit cell are linearly dependent
    atoms = FaceCenteredCubic(symbol='Cu',
                              directions=[[1, 1, 0], [1, 1, 0], [0, 0, 1]])

with must_raise(ValueError):
    # The directions spanning the unit cell are linearly dependent
    atoms = FaceCenteredCubic(symbol='Cu',
                              directions=[[1, 1, 0], [1, 0, 0], [0, 1, 0]])

# This one should be OK:
atoms = FaceCenteredCubic(symbol='Cu',
                          directions=[[1, 1, 0], [0, 1, 0], [0, 0, 1]])
print(atoms.get_cell())
Пример #23
0
            for i2, p2 in enumerate(positions[:i1]):
                diff = p2 - p1
                d2 = np.dot(diff, diff)
                c6 = (self.sigma**2 / d2)**3
                c12 = c6**2
                if d2 < self.cutoff**2:
                    self.energy += 4 * self.epsilon * (c12 - c6) - self.shift
                F = 24 * self.epsilon * (2 * c12 - c6) / d2 * diff
                self._forces[i1] -= F
                self._forces[i2] += F
        self.positions = positions.copy()



N = 5
ar = FaceCenteredCubic('Ar', pbc=[(0,0,0)], directions=[[1,0,0],[0,1,0],[0,0,1]], size=[N,N,N])
print ar.get_cell()
#view(ar) 

calc1 = KIMCalculator("ex_model_Ar_P_LJ")
ar.set_calculator(calc1)
kim_energy = ar.get_potential_energy()
print "kim energy = ", kim_energy 

calc2 = LennardJones(epsilon=epsilon, sigma=sigma, cutoff=cutoff)
ar.set_calculator(calc2)
ase_energy = ar.get_potential_energy()
print "ase energy = ", ase_energy 

print "difference = ", kim_energy - ase_energy
Пример #24
0
from asap3 import *
from ase.lattice.cubic import FaceCenteredCubic
from asap3.Setup.Dislocation import Dislocation
from ase.visualize.primiplotter import *

print_version(1)

splitting = 5
size = (50, 88, 35)
#size = (30, 25, 7)

Gold = "Au"
slab = FaceCenteredCubic(directions=((1, 1, -2), (-1, 1, 0), (1, 1, 1)),
                         size=size,
                         symbol=Gold)
basis = slab.get_cell()
print basis
print "Number of atoms:", len(slab)

center = 0.5 * array([basis[0, 0], basis[1, 1], basis[2, 2]]) + array(
    [0.1, 0.1, 0.1])
offset = 0.5 * splitting * slab.miller_to_direction((-1, 0, 1))
print center

d1 = Dislocation(center - offset, slab.miller_to_direction((-1, -1, 0)),
                 slab.miller_to_direction((-2, -1, 1)) / 6.0)
d2 = Dislocation(center + offset, slab.miller_to_direction((1, 1, 0)),
                 slab.miller_to_direction((1, 2, 1)) / 6.0)

atoms = Atoms(slab)
(d1 + d2).apply_to(atoms)
Пример #25
0

if __name__ == '__main__':
    from ase.lattice.cubic import FaceCenteredCubic

    from ase.lattice.bravais import cross

    a = np.array([0.5, 0, 0])
    c = np.array([0, 1, 0], dtype=np.float)
    b1 = c - a

    a = np.array([0, 1, 0], np.float)
    c = np.array([0, 0.5, 0.5])
    b2 = c - a

    a3 = np.array([2, 1, 1], np.float)

    a1 = cross(b1, a3)
    a2 = cross(b2, a3)
    v211 = FaceCenteredCubic(directions=[a1, a2, a3],
                             miller=(None, None, [2, 1, 1]),
                             symbol='Pd',
                             size=(1, 1, 2),
                             debug=0)

    uc = v211.get_cell()
    uc[2][2] += 10.0
    v211.set_cell(uc)

    plot_atoms(v211.repeat((2, 2, 1)))
Пример #26
0
import numpy as np
from ase.lattice.cubic import FaceCenteredCubic
ag = FaceCenteredCubic(directions=[[1, 0, 0], [0, 1, 0], [0, 0, 1]],
                       size=(1, 1, 1),
                       symbol='Ag',
                       latticeconstant=4.0)
# these are the reciprocal lattice vectors
b1, b2, b3 = np.linalg.inv(ag.get_cell())
'''
g(111) = 1*b1 + 1*b2 + 1*b3
and |g(111)| = 1/d_111
'''
h, k, l = (1, 1, 1)
d = 1. / np.linalg.norm(h * b1 + k * b2 + l * b3)
print 'd_111 spacing (method 1) = {0:1.3f} Angstroms'.format(d)
#method #2
hkl = np.array([h, k, l])
G = np.array([b1, b2, b3])  #reciprocal unit cell
'''
Gstar is usually defined as this matrix of dot products:
Gstar = np.array([[dot(b1,b1), dot(b1,b2), dot(b1,b3)],
                  [dot(b1,b2), dot(b2,b2), dot(b2,b3)],
                  [dot(b1,b3), dot(b2,b3), dot(b3,b3)]])
but I prefer the notationally more compact:
Gstar = G .dot. transpose(G)
then, 1/d_hkl^2 = hkl .dot. Gstar .dot. hkl
'''
Gstar = np.dot(G, G.T)
id2 = np.dot(hkl, np.dot(Gstar, hkl))
print 'd_111 spacing (method 2) =', np.sqrt(1 / id2)
# http://books.google.com/books?id=nJHSqEseuIUC&lpg=PA118&ots=YA9TBldoVH
Пример #27
0
#some algebra to determine surface normal and the plane of the surface
d3=[2,1,1]
a1=np.array([0,1,1])
d1=np.cross(a1,d3)
a2=np.array([0,-1,1])
d2=np.cross(a2,d3)

#create your slab
slab  =FaceCenteredCubic(directions=[d1,d2,d3],
                         size=(2,1,2),
                         symbol=('Pt'),
                         latticeconstant=3.9)

#add some vacuum to your slab
uc = slab.get_cell()
print(uc)
uc[2] += [0,0,10]  #there are ten layers of vacuum
uc = slab.set_cell(uc,scale_atoms=False)
#view the slab to make sure it is how you expect
view(slab)

#some positions needed to place the atom in the correct place
x1 = 1.379
x2 = 4.137
x3 = 2.759
y1 = 0.0
y2 = 2.238
z1 = 7.165
z2 = 6.439
Пример #28
0
    def __init__(self,
                 symbol=None,
                 layers=None,
                 positions=None,
                 latticeconstant=None,
                 symmetry=None,
                 cell=None,
                 center=None,
                 multiplicity=1,
                 filename=None,
                 debug=0):

        self.debug = debug
        self.multiplicity = multiplicity

        if filename is not None:
            # We skip MonteCarloAtoms.__init__, do it manually.
            self.mc_optim = np.zeros(101, np.intc)
            self.mc_optim[0] = 10000  # MC optim invalid
            self.read(filename)
            return

        #Find the atomic number
        if symbol is not None:
            if isinstance(symbol, str):
                self.atomic_number = atomic_numbers[symbol]
            else:
                self.atomic_number = symbol
        else:
            raise Warning('You must specify a atomic symbol or number!')

        #Find the crystal structure
        if symmetry is not None:
            if symmetry.lower() in ['bcc', 'fcc', 'hcp']:
                self.symmetry = symmetry.lower()
            else:
                raise Warning('The %s symmetry does not exist!' %
                              symmetry.lower())
        else:
            self.symmetry = reference_states[
                self.atomic_number]['symmetry'].lower()

        if self.debug:
            print 'Crystal structure:', self.symmetry

        #Find the lattice constant
        if latticeconstant is None:
            if self.symmetry == 'fcc':
                self.lattice_constant = reference_states[
                    self.atomic_number]['a']
            else:
                raise Warning(('Cannot find the lattice constant ' +
                               'for a %s structure!' % self.symmetry))
        else:
            self.lattice_constant = latticeconstant

        if self.debug:
            print 'Lattice constant(s):', self.lattice_constant

        #Make the cluster of atoms
        if layers is not None and positions is None:
            layers = list(layers)

            #Make base crystal based on the found symmetry
            if self.symmetry == 'fcc':
                if len(layers) != data.lattice[self.symmetry]['surface_count']:
                    raise Warning(
                        'Something is wrong with the defined number of layers!'
                    )

                xc = int(np.ceil(layers[1] / 2.0)) + 1
                yc = int(np.ceil(layers[3] / 2.0)) + 1
                zc = int(np.ceil(layers[5] / 2.0)) + 1

                xs = xc + int(np.ceil(layers[0] / 2.0)) + 1
                ys = yc + int(np.ceil(layers[2] / 2.0)) + 1
                zs = zc + int(np.ceil(layers[4] / 2.0)) + 1

                center = np.array((xc, yc, zc)) * self.lattice_constant
                size = (xs, ys, zs)

                if self.debug:
                    print 'Base crystal size:', size
                    print 'Center cell position:', center

                atoms = FaceCenteredCubic(
                    symbol=symbol,
                    size=size,
                    latticeconstant=self.lattice_constant,
                    align=False)

            else:
                raise Warning(
                    ('The %s crystal structure is not' + ' supported yet.') %
                    self.symmetry)

            positions = atoms.get_positions()
            numbers = atoms.get_atomic_numbers()
            cell = atoms.get_cell()
        elif positions is not None:
            numbers = [self.atomic_number] * len(positions)
        else:
            numbers = None

        #Load the constructed atoms object into this object
        self.set_center(center)
        MonteCarloAtoms.__init__(self,
                                 numbers=numbers,
                                 positions=positions,
                                 cell=cell,
                                 pbc=False)

        #Construct the particle with the assigned surfasces
        if layers is not None:
            self.set_layers(layers)
Пример #29
0
        lgv.run(5)
        T = atoms.get_kinetic_energy() / (1.5 * atoms.get_number_of_atoms() * units.kB)
        print "Temperature is now %.2f K" % (T,)
    print "Desired temperature reached!"

    lgv.set_temperature(T_goal*units.kB)

    for i in range(2):
        lgv.run(20)
        s = atoms.get_stress()
        p = -(s[0] + s[1] + s[2])/3.0 / units.GPa
        T = atoms.get_kinetic_energy() / (1.5 * atoms.get_number_of_atoms() * units.kB)
        print "Pressure is %f GPa, desired pressure is %f GPa (T = %.2f K)" % (p, p_goal, T)
        dv = (p - p_goal) / bulk
        print "Adjusting volume by", dv
        cell = atoms.get_cell()
        atoms.set_cell(cell * (1.0 + dv/3.0))

    T = atoms.get_kinetic_energy() / (1.5 * atoms.get_number_of_atoms() * units.kB)
    print "Temperature is now %.2f K" % (T,)

    stressstate = array([-2, -1, 0, 0, 0, 0])*p_goal*units.GPa
    dyn = NPT(atoms, 5 * units.fs, T_goal*units.kB, stressstate,
              ttime*units.fs, (ptime*units.fs)**2 * bulk * units.GPa)
    traj = PickleTrajectory("NPT-atoms.traj", "w", atoms)
    #dyntraj = ParallelHooverNPTTrajectory("NPT-dyn-traj.nc", dyn, interval = 50)
    dyn.attach(traj, interval=50)
    #dyn.Attach(dyntraj)

    out = open(out1, "w")
Пример #30
0
from ase.lattice.cubic import FaceCenteredCubic


def checkang(a, b, phi):
    "Check the angle between two vectors."
    cosphi = np.dot(a,b) / sqrt(np.dot(a,a) * np.dot(b,b))
    assert np.abs(cosphi - cos(phi)) < 1e-10

symb = "Cu"
Z = data.atomic_numbers[symb]
a0 = data.reference_states[Z]['a']

# (100) oriented block
atoms = FaceCenteredCubic(size=(5,5,5), symbol="Cu", pbc=(1,1,0))
assert len(atoms) == 5*5*5*4
c = atoms.get_cell()
checkang(c[0], c[1], pi/2)
checkang(c[0], c[2], pi/2)
checkang(c[1], c[2], pi/2)
assert np.abs(5 * a0 - c[2,2]) < 1e-10

# Add vacuum in one direction
vac = 10.0
atoms.center(axis=2, vacuum=vac)
c = atoms.get_cell()
checkang(c[0], c[1], pi/2)
checkang(c[0], c[2], pi/2)
checkang(c[1], c[2], pi/2)
assert np.abs(4.5 * a0 + 2* vac - c[2,2]) < 1e-10

# Add vacuum in all directions
Пример #31
0
d0 = atoms.get_distances(0, np.arange(len(atoms)), mic=True)

U = np.array([[1, 2, 2],
              [0, 1, 2],
              [0, 0, 1]])
assert np.linalg.det(U) == 1
atoms.set_cell(U.T @ atoms.cell, scale_atoms=False)
atoms.wrap()

d1 = atoms.get_distances(0, np.arange(len(atoms)), mic=True)
assert_allclose(d0, d1)

vnbrlist = NeighborListMic(atoms.get_positions(), atoms.cell, atoms.pbc)
d2 = np.linalg.norm(vnbrlist, axis=1)
assert_allclose(d0, d2)


nl = NeighborList(np.ones(len(atoms)) * 2 * size * np.sqrt(3),
                  bothways=True,
                  primitive=PrimitiveNeighborList)
nl.update(atoms)
indices, offsets = nl.get_neighbors(0)

d3 = float("inf") * np.ones(len(atoms))
for i, offset in zip(indices, offsets):
	p = atoms.positions[i] + offset @ atoms.get_cell()
	d = np.linalg.norm(p - atoms.positions[0])
	d3[i] = min(d3[i], d)
assert_allclose(d0, d3)