Beispiel #1
0
def ase_atom_my_atom(ase_data):

    lattice = []
    for vector in ase_data.cell:
        lattice.append(tuple(vector))

    # ASE converts basis to cartesian, so convert back
    inv_lattice = np.linalg.inv(np.transpose(np.asarray(ase_data.cell)))

    basis = []
    for pos in ase_data.positions:
        frac_pos = np.matmul(inv_lattice, pos)
        basis.append(tuple(frac_pos))

    atomic_numbers = []
    for an in ase_data.numbers:
        atomic_numbers.append(an)

    # an_to_symbol = atomic_number_symbol_dict()
    n_atoms = len(atomic_numbers)
    molecule = []

    for ia in range(0, n_atoms):
        species = an_to_symbol[atomic_numbers[ia]]
        molecule.append(atoms.Atom(species, basis[ia]))

    return molecule
Beispiel #2
0
def super_cell_from_crystal(rutile: dict, cell_integers: list) -> dict:
    assert rutile['lattice_parameters']['a'].unit == 'angstrom'

    # Extract data
    a = rutile['lattice_parameters']['a'].value
    c = rutile['lattice_parameters']['c'].value
    lattice = bravais.simple_tetragonal(a, c)
    positions_angstrom = [
        np.matmul(lattice, pos) for pos in rutile['fractional']
    ]
    species = rutile['species']

    # Compute supercell
    unit_cell = [
        atoms.Atom(species[ia], positions_angstrom[ia])
        for ia in range(0, len(species))
    ]
    super_cell = supercell.build_supercell(
        unit_cell, supercell.translation_vectors(lattice, cell_integers))
    assert len(super_cell) == np.prod(cell_integers) * len(unit_cell)
    lattice_scell = supercell.get_supercell_vector(lattice, cell_integers)
    #write.xyz('rutile_222.xyz', super_cell)

    # Repackage the information
    inv_lattice_scell = np.linalg.inv(lattice_scell)
    positions_frac = [
        np.matmul(inv_lattice_scell, atom.position) for atom in super_cell
    ]
    species_sc = [atom.species for atom in super_cell]
    a = np.linalg.norm(lattice_scell[:, 0])
    c = np.linalg.norm(lattice_scell[:, 2])
    lattice_parameters = {'a': Set(a, 'angstrom'), 'c': Set(c, 'angstrom')}
    data = {
        'fractional': positions_frac,
        'species': species_sc,
        'lattice_parameters': lattice_parameters,
        'space_group': ('', 136),  #rutile['space_group']
        'n_atoms': len(species_sc)
    }

    return data
Beispiel #3
0
def replace_loose_atoms(unit_cell: list,
                        loose_atom_indices: List[int],
                        equivalent_positions: list,
                        visualise_parts=False) -> list:
    """
    Remove uncoordinated atoms and their equivalents to the unit cell

    :param unit_cell: List of atoms
    :param loose_atom_indices: Indices for uncoordinated atoms
    :param equivalent_positions: List of equivalent positions for uncoordinated atoms.
    of size len(loose_atom_indices)
    :param visualise_parts: bool, output .xyz of original unit_cell, removed atoms and
     replacement atoms
    :return new_unit_cell with no uncoordinated atoms
    """
    assert len(loose_atom_indices) == len(equivalent_positions), "Should be one new (equivalent) " \
                                                                 "position per uncoordinated atom"

    # Can't use pop as it changes the indexing each time
    new_unit_cell = []
    removed_atoms = []
    for ia in range(0, len(unit_cell)):
        if ia not in loose_atom_indices:
            new_unit_cell.append(unit_cell[ia])
        else:
            removed_atoms.append(unit_cell[ia])

    #TODO(Alex) Generalise
    # I know they're all oxygens but should treat this correctly if making general
    replacements = [
        atoms.Atom(position=position, species='O')
        for position in equivalent_positions
    ]

    if visualise_parts:
        output_dir = 'aei_outputs'
        xyz(output_dir + '/' + "aei_central_cell", unit_cell)
        xyz(output_dir + '/' + "aei_replacements_cell", replacements)
        xyz(output_dir + '/' + "aei_removed_atoms", removed_atoms)

    return new_unit_cell + replacements
Beispiel #4
0
from modules.electronic_structure.structure import atoms, bravais, crystals, supercell
from modules.electronic_structure.basis import gfn1

from modules.parameters import crystals as params
from modules.fileio import write
from modules import entos

# Silicon cubic unit cell in angstrom
al = params.silicon['lattice_constant']['angstrom']
fractional_basis_positions = crystals.silicon('conventional')
lattice = bravais.simple_cubic(al)

unit_cell = []
for atom in fractional_basis_positions:
    pos_angstrom = np.matmul(lattice, atom.position)
    unit_cell.append(atoms.Atom(atom.species, pos_angstrom))


def silicon_supercell(n, centred_on_zero=None):
    if centred_on_zero == None:
        centred_on_zero = (n[0] * n[1] * n[2]) % 2 != 0

    translations = supercell.translation_vectors(
        lattice, n, centred_on_zero=centred_on_zero)
    super_cell = supercell.build_supercell(unit_cell, translations)

    # Information
    print('Number of atoms in supercell:', len(super_cell))

    # Find central cell
    icentre = supercell.flatten_supercell_limits(
Beispiel #5
0
def triangle_from(tetrahedron):

    # Separate silicons and oxygens
    triangle = []
    silicon = []
    for atom in tetrahedron:
        if atom.species.lower() == 'si':
            silicon.append(atom)
        elif atom.species.lower() == 'o':
            triangle.append(atom)

    assert len(
        triangle
    ) == 3, "triangle_from function expects tetrahedron containing 3 oxygen"
    assert len(
        silicon
    ) == 1, "triangle_from function expects tetrahedron containing 1 silicon"

    # Define 2 of 3 vertices that form the oxygen triangle
    v01 = triangle[1].position - triangle[0].position
    v12 = triangle[2].position - triangle[1].position

    # Normal to triangle surface
    normal = np.cross(v01, v12)
    unit_normal = normal / np.linalg.norm(normal)
    #print(normal, unit_normal)

    # Silicon - oxygen distances
    si_o_0 = np.linalg.norm(silicon[0].position - triangle[0].position)
    si_o_1 = np.linalg.norm(silicon[0].position - triangle[1].position)
    si_o_2 = np.linalg.norm(silicon[0].position - triangle[2].position)

    # Silicon atom is above the plane and one needs to reverse the norm
    if np.dot(silicon[0].position - triangle[0].position, unit_normal) > 1:
        unit_normal = -unit_normal

    # Progagate si incrementally along unit normal, until distances from all oxy are minimised
    bond_length = si_o_0
    si_0 = np.asarray(silicon[0].position)

    print("bond_length", bond_length)

    # Alt way of stepping
    # sep = 1000
    # pos = np.zeros(shape=(3))
    # for dr in np.linspace(0, bond_length, sep):

    # ang
    step = 0.001 * bond_length
    pos = np.zeros(shape=(3))
    for dr in np.arange(0 + step, bond_length + step, step):
        pos += si_0 + (dr * unit_normal)
        # print("pos,",pos)
        # print(np.linalg.norm(pos - triangle[0].position), \
        #       np.linalg.norm(pos - triangle[1].position), \
        #       np.linalg.norm(pos - triangle[2].position))
        # print(si_o_0, si_o_1, si_o_2)

        if (np.linalg.norm(pos - triangle[0].position) <= si_o_0) and \
           (np.linalg.norm(pos - triangle[1].position) <= si_o_1) and \
           (np.linalg.norm(pos - triangle[2].position) <= si_o_2):
            si_o_0 = np.linalg.norm(pos - triangle[1].position)
            si_o_1 = np.linalg.norm(pos - triangle[1].position)
            si_o_2 = np.linalg.norm(pos - triangle[2].position)
            final_pos = pos
        else:
            break

    triangle.append(atoms.Atom('B', final_pos))
    return triangle
Beispiel #6
0
import numpy as np
import random

from modules.electronic_structure.structure import atoms, bravais

# Central silicon with 4 surrounding oxygen
al = 7.12637
molecule = [
    atoms.Atom('si', al * np.array([0, 0, 0])),
    atoms.Atom('o', al * np.array([0.25, 0.25, 0.25])),
    atoms.Atom('o', al * np.array([0.25, -0.25, -0.25])),
    atoms.Atom('o', al * np.array([-0.25, 0.25, -0.25])),
    atoms.Atom('o', al * np.array([-0.25, -0.25, 0.25]))
]

# Test tetrahedron to triangle operation
#triangle = operations.triangle_from(molecule)
#write.xyz("triangle", triangle)


# For a given tetrahedron, remove one oxygen at random
# and move the silicon into the plane of the remaining 3 atoms
#
#for each step, store norm(atom0_si - atom1), norm(atom0_si - atom2) and norm(atom0_si - atom3)
#these should get smaller. Once they start getting larger, stop. atom_si is now in the plane.
# Maybe a more mathematical way of doing it but should be quite fast
#
# Make more robust to deal with fractional or angstrom
#
def triangle_from(tetrahedron):
import numpy as np

from modules.electronic_structure.structure import atoms, bravais, crystals, supercell
from modules.electronic_structure.basis import gfn1

from modules.parameters import crystals as params
from modules.fileio import write

# Silicon dioxide cubic primitive unit cell. Could be wrong but doesn't matter, just want two atom types
fractional_basis_positions = [
    atoms.Atom('Si', [0, 0, 0]),
    atoms.Atom('O', [0.25, 0.25, 0.25])
]
lattice = bravais.face_centred_cubic(1.)

unit_cell = []
for atom in fractional_basis_positions:
    pos_angstrom = np.matmul(lattice, atom.position)
    unit_cell.append(atoms.Atom(atom.species, pos_angstrom))

# Supercell
# If odd, can centre on T=(0,0,0), else can't
n = [3, 3, 3]
translations = supercell.translation_vectors(lattice, n, centred_on_zero=True)
super_cell = supercell.build_supercell(unit_cell, translations)

# Central cell
icentre = supercell.flatten_supercell_limits([0, 0, 0],
                                             n,
                                             centred_on_zero=True)
cells = supercell.list_global_atom_indices_per_cells(unit_cell, translations)
Beispiel #8
0
import numpy as np

from modules.fileio import read
from modules.electronic_structure.structure import atoms

import read_basis

# Molecule: Positions in angstrom at this point
names, positions = read.xyz("molecules/pyridine.xyz")
molecule = []
for iatom in range(0, len(names)):
    position = positions[iatom]
    molecule.append(atoms.Atom(names[iatom], position))

# Basis sets: https://www.basissetexchange.org
read_basis.sto_3g("basis_sets/STO-3G/sto-3g.1-2.json")

# Integrals

# Symmetric orthogonalisation of the basis

# SCF