Example #1
0
def moleculr_from_indices(species, positions, atomic_indices):
    new_species = []
    new_positions = []
    for ia in atomic_indices:
        new_species.append(species[ia])
        new_positions.append(positions[ia])
    return atoms.Atoms(new_species, new_positions)
Example #2
0
def rhomohedral():
    system_label = 'rhom_mos'
    a = 12.96
    alpha = 0.470
    lattice = bravais.rhombohedral(a, alpha, 'rhom')
    fractional_positions = np.array([[0.000007, 0.000007, 0.000007],
                                     [0.254176, 0.254176, 0.254176],
                                     [0.412458, 0.412458,
                                      0.412458]]).transpose()
    positions = np.matmul(lattice, fractional_positions).transpose()
    unit_cell = atoms.Atoms(['Mo', 'S', 'S'], positions.tolist())
    return System(system_label, unit_cell, lattice)
Example #3
0
def hexagonal():
    system_label = 'hex_bn'
    a = 4.75
    c = 14.56
    lattice = bravais.hexagonal(a, c)
    fractional_positions = np.array([[0.333333, 0.666667, 0.250000],
                                     [0.666667, 0.333333, 0.750000],
                                     [0.333333, 0.666667, 0.750000],
                                     [0.666667, 0.333333,
                                      0.250000]]).transpose()
    positions = np.matmul(lattice, fractional_positions).transpose()
    unit_cell = atoms.Atoms(['B', 'B', 'N', 'N'], positions.tolist())
    return System(system_label, unit_cell, lattice)
Example #4
0
def simple_orthorhombic():
    system_label = 'simple_orth_cdau'
    a = 5.83
    b = 9.30
    c = 9.74
    lattice = bravais.simple_orthorhombic(a, b, c)
    fractional_positions = np.array([[0.00000000, 0.75000000, 0.69415500],
                                     [0.00000000, 0.25000000, 0.30584500],
                                     [0.50000000, 0.75000000, 0.18925900],
                                     [0.50000000, 0.25000000,
                                      0.81074100]]).transpose()
    positions = np.matmul(lattice, fractional_positions).transpose()
    unit_cell = atoms.Atoms(['Cd', 'Cd', 'Au', 'Au'], positions.tolist())
    return System(system_label, unit_cell, lattice)
Example #5
0
def simple_cubic():
    system_label = 'cubic_silicon'
    al = 10.33
    species = ['Si'] * 8
    positions = al * np.array([[0.25000000, 0.75000000, 0.25000000],
                               [0.00000000, 0.00000000, 0.50000000],
                               [0.25000000, 0.25000000, 0.75000000],
                               [0.00000000, 0.50000000, 0.00000000],
                               [0.75000000, 0.75000000, 0.75000000],
                               [0.50000000, 0.00000000, 0.00000000],
                               [0.75000000, 0.25000000, 0.25000000],
                               [0.50000000, 0.50000000, 0.50000000]])
    unit_cell = atoms.Atoms(species, positions)
    lattice = bravais.simple_cubic(al)
    return System(system_label, unit_cell, lattice)
Example #6
0
def simple_tetragonal():
    system_label = 'simple_tet_tio2'
    a = 8.71
    c = 5.65
    lattice = bravais.simple_tetragonal(a, c)
    fractional_positions = np.array([[0.000000, 0.000000, 0.000000],
                                     [0.500000, 0.500000, 0.500000],
                                     [0.695526, 0.695526, 0.000000],
                                     [0.304474, 0.304474, 0.000000],
                                     [0.195526, 0.804474, 0.500000],
                                     [0.804474, 0.195526,
                                      0.500000]]).transpose()
    positions = np.matmul(lattice, fractional_positions).transpose()
    unit_cell = atoms.Atoms(['Ti', 'Ti', 'O', 'O', 'O', 'O'],
                            positions.tolist())
    return System(system_label, unit_cell, lattice)
Example #7
0
def get_primitive_unit_cell(directories: Directories, visualise=False):
    """
    Wrapper for reading CIF file, converting it to a primitive unit cell
    and returning it in data structure, along with lattice vectors

    :param directories: Structure, input and output strings
    :param visualise: Output structure as .xyz
    :return: unit_cell, lattice_vectors: Unit cell and lattice vectors
    """
    structure_name = directories.structure
    input_dir = directories.input
    output_dir = directories.output

    ase_input_data = ase.io.read(input_dir + "/" + structure_name + ".cif",
                                 store_tags=False)
    spg_input = ase_to_spglib(ase_input_data)
    print("Number of atoms in input", len(spg_input[2]))

    # Reduce to primitive with SPG
    #print("Find primitive of conventional structure")
    lattice, positions, numbers = spglib.find_primitive(spg_input,
                                                        symprec=1e-5)

    if visualise:
        spg_molecule = (lattice, positions, numbers)
        #spg_show_cell(lattice, positions, numbers)
        spg_write(output_dir + '/' + structure_name + '_primitive_cell.xyz',
                  spg_molecule,
                  pbc=(1, 1, 1))

    # Need lattice vectors column-wise, in np array
    lattice_vectors = np.zeros(shape=(3, 3))
    for i in range(0, 3):
        lattice_vectors[:, i] = lattice[i]

    # Need positions in angstrom, not fractional
    positions_ang = []
    for position in positions:
        positions_ang.append(np.matmul(lattice, position))

    # Need unit cell in my molecule format
    species = [an_to_symbol[an] for an in numbers]
    unit_cell = atoms.Atoms(species=species, positions=positions_ang)

    return unit_cell, lattice_vectors
Example #8
0
def simple_monoclinic():
    system_label = 'simpe_mono_lisn'
    a = 9.79
    b = 6.09
    c = 14.75
    beta = 1.85
    lattice = bravais.simple_monoclinic(a, b, c, beta)
    fractional_positions = np.array([[0.268026, 0.500000, 0.331701],
                                     [0.500000, 0.500000, 0.000000],
                                     [0.731974, 0.500000, 0.668299],
                                     [0.241273, 0.000000, 0.661946],
                                     [0.758727, 0.000000, 0.338054],
                                     [0.000000, 0.000000,
                                      0.000000]]).transpose()
    positions = np.matmul(lattice, fractional_positions).transpose()
    unit_cell = atoms.Atoms(['Li', 'Li', 'Li', 'Sn', 'Sn', 'Sn'],
                            positions.tolist())
    return System(system_label, unit_cell, lattice)
Example #9
0
def fcc():
    system_label = 'fcc_silicon'
    al = 10.26
    unit_cell = atoms.Atoms(['Si', 'Si'], [[0, 0, 0], [0.25 * al] * 3])
    lattice = bravais.face_centred_cubic(al)
    return System(system_label, unit_cell, lattice)
Example #10
0
def bcc():
    system_label = 'bcc_potassium'
    al = 8.612
    unit_cell = atoms.Atoms(['K'], [[0, 0, 0]])
    lattice = bravais.body_centred_cubic(al)
    return System(system_label, unit_cell, lattice)
Example #11
0
def ring_substitutions(aei_ring_unit):
    """
    :brief

    :result
    """
    assert isinstance(aei_ring_unit, list), \
        "aei_ring_unit should be list[atoms.Atom]"
    assert isinstance(aei_ring_unit[0], atoms.Atom), \
        "aei_ring_unit should be list[atoms.Atom]"
    species = [atom.species for atom in aei_ring_unit]
    positions = [atom.position for atom in aei_ring_unit]
    new_species, new_positions = convert_ring(species, positions)
    return atoms.Atoms(new_species, new_positions)


# # Simple hack as I know the structure beforehand
# # If in the correct spatial region and is bonded (could remove the 2nd assertion)
# def ring_indices(unit_cell, in_ring):
#
#     positions = [atom.position for atom in unit_cell]
#     d = spatial.distance_matrix(positions, positions)
#     max_bond_length = 1.7
#
#     indices = []
#     for ia in range(0, len(unit_cell)):
#         if in_ring(positions[ia]):
#             neighbours = np.where((d[ia, :] > 0.) & (d[ia, :] <= max_bond_length))[0]
#             if len(neighbours) > 0:
#                 indices.append(ia)
#     return indices
#
#
# def get_ring(ring_indices, unit_cell):
#     species = []
#     positions = []
#     for i in ring_indices:
#         species.append(unit_cell[i].species)
#         positions.append(unit_cell[i].position)
#     return species, positions
#
#
# def swap_ring(ring_indices, unit_cell):
#     species, positions = get_ring(ring_indices, unit_cell)
#     # write.xyz("extracted_ring.xyz", atoms.Atoms(species, positions))
#     new_species, new_positions = convert_ring(species, positions)
#     converted_ring = atoms.Atoms(new_species, new_positions)
#
#     # New structure, with old ring swapped out for the new
#     unit_cell_minus_ring = []
#     for i, atom in enumerate(unit_cell):
#         if i not in ring_indices:
#             unit_cell_minus_ring.append(atom)
#
#     return unit_cell_minus_ring + converted_ring
#
#

# -------------------
# Main routine
# -------------------

# Read in CIF and convert to primitive cell
# directories = cell_operations.Directories(structure='aei',
#                                           input='inputs',
#                                           output='aei_outputs')
#
# unit_cell, lattice_vectors = cell_operations.get_primitive_unit_cell(directories)
# translations = cell_operations.translations_for_fully_coordinated_unit(unit_cell, lattice_vectors)
# coordinating_atoms = cell_operations.find_atoms_neighbouring_central_cell(
#     unit_cell, translations)
#
# # Breaks the ring routine if I add coordinating_atoms here
# #unit_cell = unit_cell + coordinating_atoms
#
# # For AEI primitive cell, the rings are:
# # Every connected atom above x value of 11.52979
# # Every connected atom below an x value of 7
# top_ring_indices = ring_indices(unit_cell, lambda pos: pos[0] > 11.5)
#
# structure = swap_ring(top_ring_indices, unit_cell)
# bottom_ring_indices = ring_indices(structure, lambda pos: pos[0] <= 7)
# structure = swap_ring(bottom_ring_indices, structure)
#
# write.xyz("new_ring.xyz", structure)

# def ring_test():
#     species, positions = read.xyz("inputs/ring.xyz")
#     new_species, new_positions = convert_ring(species, positions)
#     molecule = atoms.Atoms(new_species, new_positions)
#     write.xyz("one_unit.xyz", molecule)
#

# quit()
#
# first_boron_index = next(i for i,symbol in enumerate(new_species) if symbol == 'B')
#
# #TODO(Alex) This doesn't work properly
# # Find 2nd-shortest B-B bond length.
# n_atoms = len(new_species)
# boron_indices = [i for i in range(0, n_atoms) if new_species[i] == 'B']
# new_positions = np.asarray(new_positions)
# new_species = np.asarray(new_species)
# boron_positions = new_positions[boron_indices]
# d_boron = spatial.distance_matrix(boron_positions, boron_positions)
# molecule = atoms.Atoms(new_species[boron_indices], boron_positions)
# write.xyz("borons.xyz", molecule)
#
# # This gets lucky
# second_shortest_distance = np.sort(d_boron[0,:])[2]
#
# # Create list of pairs
# boron_pairs = []
# for i in range(0, len(boron_indices)):
#     j = np.where(d_boron[i,:] == second_shortest_distance)
#     print(j)
#     boron_pairs.append([i,j])
#
# # Put oxygens between these boron pairs
#
#
# molecule = atoms.Atoms(new_species, new_positions)
# write.xyz("one_unit.xyz", molecule)
#
#
#
# # TODO(Alex)
# # Deal with si-o-o and, potentially
# # Need to write something to identify the rings in the primitive cell: Just list manually.
#
#
#
#
# quit()
# # Move each atom out along vector with ring centre
# l = 5
# new_positions = []
# for ia in range(0, len(species)):
#     position = positions[ia]
#     # Point outwards from the centre
#     radial_vector = np.asarray(position) - ring_centre
#     unit_radial_vector = radial_vector / np.linalg.norm(radial_vector)
#     scaled_radial_vector = l * unit_radial_vector
#     assert( np.isclose(np.linalg.norm(scaled_radial_vector), l) )
#     new_positions.append(scaled_radial_vector + position)
#
# molecule = atoms.Atoms(species, new_positions)
# write.xyz("test.xyz", molecule)
Example #12
0
def convert_ring(species, positions):

    n_atoms = len(species)
    ring_centre = geometry.find_centre(positions)
    si_oo_units, oxy_ring_atoms = identify_si_o_o_units(species,
                                                        positions,
                                                        plane_index=0)
    # Else same atom will get shifted for each time it reappears in a unit
    si_oo_units = remove_sharing_oxygens(si_oo_units)

    # Move each si_oo_unit, length found from trial and error (specific to AEI)
    length = 8
    for unit in si_oo_units:
        # Find unit centre
        unit_centre = geometry.find_centre(
            [positions[iatom] for iatom in unit])
        # Point outwards from the ring centre
        radial_vector = np.asarray(unit_centre) - ring_centre
        scaled_radial_vector = scaled_vector(length, radial_vector)
        # Update each position
        for atom in unit:
            positions[atom] = scaled_radial_vector + positions[atom]

    # Move each oxy atom in the ring
    oxy_ring_positions = move_atoms_radially(oxy_ring_atoms, positions,
                                             ring_centre, 2)  # 5
    cnt = 0
    for iatom in oxy_ring_atoms:
        positions[iatom] = oxy_ring_positions[cnt]
        cnt += 1

    print_intermediate = True
    if print_intermediate:
        molecule = atoms.Atoms(species, positions)
        write.xyz("select.xyz", molecule)

    quit('up to here - looks like things move unexpectedly')

    # Assume Br-O bond length
    bond_length_bo = 1.7

    # For each Si-O-O of a former tetrahedron, move a unit towards each of the two closest ring oxygens
    # cleave off one of the oxy and convert Si -> Br
    translated_species = []
    translated_positions = []

    for si_oo_unit in si_oo_units:
        neighbouring_ring_atoms = find_closest_ring_oxygens(
            species, positions, si_oo_unit)
        ts, tp = translate_si_o_o_unit(species, positions, si_oo_unit,
                                       neighbouring_ring_atoms)
        translated_species += ts
        translated_positions += tp

    # Remove old atoms
    atom_indices = np.delete(np.arange(0, n_atoms), flatten(si_oo_units))
    new_species = []
    new_positions = []
    for iatom in atom_indices:
        new_species.append(species[iatom])
        new_positions.append(positions[iatom])

    # Add new atoms
    assert len(translated_species) % 2 == 0
    for iatom in range(0, len(translated_species)):
        new_species.append(translated_species[iatom])
        new_positions.append(translated_positions[iatom])

    assert (len(new_species) == len(new_positions))

    # Smart way to do this is to create sets of pair indices from the translated silicons,
    # then put oxygens between them
    # I always do operations in pairs, so should go [b,o,b,o,b,o...] => elements 0 and 2 are a pair in the ring.
    n_atoms = len(new_species)
    boron_indices = [i for i in range(0, n_atoms) if new_species[i] == 'B']

    # Create list of pairs
    boron_pairs = []
    for i in range(0, len(boron_indices), 2):
        boron_A = boron_indices[i]
        boron_B = boron_indices[i + 1]
        print(new_species[boron_A], new_species[boron_B])
        boron_pairs.append([boron_A, boron_B])

    # Put oxygens between these pairs
    for pair in boron_pairs:
        pos_A = np.asarray(new_positions[pair[0]])
        pos_B = np.asarray(new_positions[pair[1]])
        print(np.linalg.norm(pos_A - pos_B))
        pos_oxy = 0.5 * (pos_A + pos_B)
        new_positions.append(pos_oxy.tolist())
        new_species.append('O')

    return new_species, new_positions
Example #13
0
def dummy_fcc():
    system_label = 'dummy_fcc'
    al = 10
    unit_cell = atoms.Atoms(['Si'], [[0, 0, 0]])
    lattice_vectors = bravais.face_centred_cubic(al)
    return System(system_label, unit_cell, lattice_vectors, al)