def test_get_lattices(self): sm = StructureMatcher(ltol=0.2, stol=0.3, angle_tol=5, primitive_cell=True, scale=True, attempt_supercell=False) l1 = Lattice.from_lengths_and_angles([1, 2.1, 1.9], [90, 89, 91]) l2 = Lattice.from_lengths_and_angles([1.1, 2, 2], [89, 91, 90]) s1 = Structure(l1, [], []) s2 = Structure(l2, [], []) lattices = list(sm._get_lattices(s=s1, target_lattice=s2.lattice)) self.assertEqual(len(lattices), 16) l3 = Lattice.from_lengths_and_angles([1.1, 2, 20], [89, 91, 90]) s3 = Structure(l3, [], []) lattices = list(sm._get_lattices(s=s1, target_lattice=s3.lattice)) self.assertEqual(len(lattices), 0)
def from_string(header_str): """ Reads Header string and returns Header object if header was generated by pymatgen. Note: Checks to see if generated by pymatgen, if not it is impossible to generate structure object so it is not possible to generate header object and routine ends Args: header_str: pymatgen generated feff.inp header Returns: Structure object. """ lines = tuple(clean_lines(header_str.split("\n"), False)) comment1 = lines[0] feffpmg = comment1.find("pymatgen") if feffpmg: comment2 = ' '.join(lines[1].split()[2:]) source = ' '.join(lines[2].split()[2:]) basis_vec = lines[6].split(":")[-1].split() # a, b, c a = float(basis_vec[0]) b = float(basis_vec[1]) c = float(basis_vec[2]) lengths = [a, b, c] # alpha, beta, gamma basis_ang = lines[7].split(":")[-1].split() alpha = float(basis_ang[0]) beta = float(basis_ang[1]) gamma = float(basis_ang[2]) angles = [alpha, beta, gamma] lattice = Lattice.from_lengths_and_angles(lengths, angles) natoms = int(lines[8].split(":")[-1].split()[0]) atomic_symbols = [] for i in range(9, 9 + natoms): atomic_symbols.append(lines[i].split()[2]) # read the atomic coordinates coords = [] for i in range(natoms): toks = lines[i + 9].split() coords.append([float(s) for s in toks[3:]]) struct = Structure(lattice, atomic_symbols, coords, False, False, False) h = Header(struct, source, comment2) return h else: return "Header not generated by pymatgen, cannot return header object"
def setUp(self): self.cubic = Structure( Lattice.from_lengths_and_angles( [1.0, 1.0, 1.0], [90.0, 90.0, 90.0]), ["H"], [[0.0, 0.0, 0.0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.bcc = Structure( Lattice.from_lengths_and_angles( [1.0, 1.0, 1.0], [90.0, 90.0, 90.0]), ["H", "H"], [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.fcc = Structure( Lattice.from_lengths_and_angles( [1.0, 1.0, 1.0], [90.0, 90.0, 90.0]), ["H", "H", "H", "H"], [[0.0, 0.0, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.hcp = Structure( Lattice.from_lengths_and_angles( [1.0, 1.0, 1.633], [90.0, 90.0, 120.0]), ["H", "H"], [[0.3333, 0.6667, 0.25], [0.6667, 0.3333, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.diamond = Structure( Lattice.from_lengths_and_angles( [1.0, 1.0, 1.0], [90.0, 90.0, 90.0]), ["H", "H", "H", "H", "H", "H", "H", "H"], [[0.0, 0.0, 0.5], [0.75, 0.75, 0.75], [0.0, 0.5, 0.0], [0.75, 0.25, 0.25], [0.5, 0.0, 0.0], [0.25, 0.75, 0.25], [0.5, 0.5, 0.5], [0.25, 0.25, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None)
def setUp(self): self.silicon = Structure( Lattice.from_lengths_and_angles( [5.47, 5.47, 5.47], [90.0, 90.0, 90.0]), ["Si", "Si", "Si", "Si", "Si", "Si", "Si", "Si"], [[0.000000, 0.000000, 0.500000], [0.750000, 0.750000, 0.750000], [0.000000, 0.500000, 1.000000], [0.750000, 0.250000, 0.250000], [0.500000, 0.000000, 1.000000], [0.250000, 0.750000, 0.250000], [0.500000, 0.500000, 0.500000], [0.250000, 0.250000, 0.750000]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.diamond = Structure( Lattice([[2.189, 0, 1.264], [0.73, 2.064, 1.264], [0, 0, 2.528]]), ["C0+", "C0+"], [[2.554, 1.806, 4.423], [0.365, 0.258, 0.632]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.nacl = Structure( Lattice([[3.485, 0, 2.012], [1.162, 3.286, 2.012], [0, 0, 4.025]]), ["Na1+", "Cl1-"], [[0, 0, 0], [2.324, 1.643, 4.025]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.cscl = Structure( Lattice([[4.209, 0, 0], [0, 4.209, 0], [0, 0, 4.209]]), ["Cl1-", "Cs1+"], [[2.105, 2.105, 2.105], [0, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square_pyramid = Structure( Lattice([[100, 0, 0], [0, 100, 0], [0, 0, 100]]), ["C", "C", "C", "C", "C", "C"], [ [0, 0, 0], [1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], \ [0, 0, 1]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_bipyramid = Structure( Lattice([[100, 0, 0], [0, 100, 0], [0, 0, 100]]), ["P", "Cl", "Cl", "Cl", "Cl", "Cl"], [ [0, 0, 0], [0, 0, 2.14], [0, 2.02, 0], [1.74937, -1.01, 0], \ [-1.74937, -1.01, 0], [0, 0, -2.14]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None)
def setUp(self): self.single_bond = Structure( Lattice.from_lengths_and_angles( [10, 10, 10], [90, 90, 90]), ["H", "H", "H"], [[1, 0, 0], [0, 0, 0], [6, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.linear = Structure( Lattice.from_lengths_and_angles( [10, 10, 10], [90, 90, 90]), ["H", "H", "H"], [[1, 0, 0], [0, 0, 0], [2, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.bent45 = Structure( Lattice.from_lengths_and_angles( [10, 10, 10], [90, 90, 90]), ["H", "H", "H"], [[0, 0, 0], [0.707, 0.707, 0], [0.707, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.cubic = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H"], [[0, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.bcc = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H", "H"], [[0, 0, 0], [0.5, 0.5, 0.5]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.fcc = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H", "H", "H", "H"], [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.hcp = Structure( Lattice.from_lengths_and_angles( [1, 1, 1.633], [90, 90, 120]), ["H", "H"], [[0.3333, 0.6667, 0.25], [0.6667, 0.3333, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.diamond = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H", "H", "H", "H", "H", "H", "H", "H"], [[0, 0, 0.5], [0.75, 0.75, 0.75], [0, 0.5, 0], [0.75, 0.25, 0.25], [0.5, 0, 0], [0.25, 0.75, 0.25], [0.5, 0.5, 0.5], [0.25, 0.25, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.trigonal_off_plane = Structure( Lattice.from_lengths_and_angles( [100, 100, 100], [90, 90, 90]), ["H", "H", "H", "H"], [[0.50, 0.50, 0.50], [0.25, 0.75, 0.25], \ [0.25, 0.25, 0.75], [0.75, 0.25, 0.25]], \ validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.regular_triangle = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H"], [[15, 15.28867, 15.65], [14.5, 15, 15], [15.5, 15, 15], \ [15, 15.866, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_planar = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H"], [[15, 15.28867, 15], [14.5, 15, 15], [15.5, 15, 15], \ [15, 15.866, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square_planar = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H"], [[15, 15, 15], [14.75, 14.75, 15], [14.75, 15.25, 15], \ [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H"], [[15, 15, 15.707], [14.75, 14.75, 15], [14.75, 15.25, 15], \ [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.T_shape = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H"], [[15, 15, 15], [15, 15, 15.5], [15, 15.5, 15], [15, 14.5, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square_pyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H", "H"], [[15, 15, 15], [15, 15, 15.3535], [14.75, 14.75, 15], [14.75, 15.25, 15], [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.pentagonal_planar = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["Xe", "F", "F", "F", "F", "F"], [[0, -1.6237, 0], [1.17969, 0, 0], [-1.17969, 0, 0], \ [1.90877, -2.24389, 0], [-1.90877, -2.24389, 0], [0, -3.6307, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.pentagonal_pyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["Xe", "F", "F", "F", "F", "F", "F"], [[0, -1.6237, 0], [0, -1.6237, 1.17969], [1.17969, 0, 0], \ [-1.17969, 0, 0], [1.90877, -2.24389, 0], \ [-1.90877, -2.24389, 0], [0, -3.6307, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.pentagonal_bipyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["Xe", "F", "F", "F", "F", "F", "F", "F"], [[0, -1.6237, 0], [0, -1.6237, -1.17969], \ [0, -1.6237, 1.17969], [1.17969, 0, 0], \ [-1.17969, 0, 0], [1.90877, -2.24389, 0], \ [-1.90877, -2.24389, 0], [0, -3.6307, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.hexagonal_pyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), \ ["H", "Li", "C", "C", "C", "C", "C", "C"], [[0, 0, 0], [0, 0, 1.675], [0.71, 1.2298, 0], \ [-0.71, 1.2298, 0], [0.71, -1.2298, 0], [-0.71, -1.2298, 0], \ [1.4199, 0, 0], [-1.4199, 0, 0]], \ validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.hexagonal_bipyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), \ ["H", "Li", "Li", "C", "C", "C", "C", "C", "C"], [[0, 0, 0], [0, 0, 1.675], [0, 0, -1.675], \ [0.71, 1.2298, 0], [-0.71, 1.2298, 0], \ [0.71, -1.2298, 0], [-0.71, -1.2298, 0], \ [1.4199, 0, 0], [-1.4199, 0, 0]], \ validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_pyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["P", "Cl", "Cl", "Cl", "Cl"], [[0, 0, 0], [0, 0, 2.14], [0, 2.02, 0], [1.74937, -1.01, 0], [-1.74937, -1.01, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.trigonal_bipyramidal = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["P", "Cl", "Cl", "Cl", "Cl", "Cl"], [[0, 0, 0], [0, 0, 2.14], [0, 2.02, 0], [1.74937, -1.01, 0], [-1.74937, -1.01, 0], [0, 0, -2.14]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.cuboctahedron = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H"], [[15, 15, 15], [15, 14.5, 14.5], [15, 14.5, 15.5], [15, 15.5, 14.5], [15, 15.5, 15.5], [14.5, 15, 14.5], [14.5, 15, 15.5], [15.5, 15, 14.5], [15.5, 15, 15.5], [14.5, 14.5, 15], [14.5, 15.5, 15], [15.5, 14.5, 15], [15.5, 15.5, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.see_saw = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H"], [[15, 15, 15], [15, 15, 14], [15, 15, 16], [15, 14, 15], [14, 15, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None)
def setUp(self): self.linear = Structure( Lattice.from_lengths_and_angles( [10, 10, 10], [90, 90, 90]), ["H", "H", "H"], [[1, 0, 0], [0, 0, 0], [2, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.bent45 = Structure( Lattice.from_lengths_and_angles( [10, 10, 10], [90, 90, 90]), ["H", "H", "H"], [[0, 0, 0], [0.707, 0.707, 0], [0.707, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.cubic = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H"], [[0, 0, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.bcc = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H", "H"], [[0, 0, 0], [0.5, 0.5, 0.5]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.fcc = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H", "H", "H", "H"], [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.hcp = Structure( Lattice.from_lengths_and_angles( [1, 1, 1.633], [90, 90, 120]), ["H", "H"], [[0.3333, 0.6667, 0.25], [0.6667, 0.3333, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.diamond = Structure( Lattice.from_lengths_and_angles( [1, 1, 1], [90, 90, 90]), ["H", "H", "H", "H", "H", "H", "H", "H"], [[0, 0, 0.5], [0.75, 0.75, 0.75], [0, 0.5, 0], [0.75, 0.25, 0.25], [0.5, 0, 0], [0.25, 0.75, 0.25], [0.5, 0.5, 0.5], [0.25, 0.25, 0.75]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None) self.regular_triangle = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H"], [[15, 15.28867, 15.65], [14.5, 15, 15], [15.5, 15, 15], \ [15, 15.866, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H"], [[15, 15, 15.707], [14.75, 14.75, 15], [14.75, 15.25, 15], \ [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None) self.square_pyramid = Structure( Lattice.from_lengths_and_angles( [30, 30, 30], [90, 90, 90]), ["H", "H", "H", "H", "H", "H"], [[15, 15, 15], [15, 15, 15.3535], [14.75, 14.75, 15], [14.75, 15.25, 15], [15.25, 14.75, 15], [15.25, 15.25, 15]], validate_proximity=False, to_unit_cell=False, coords_are_cartesian=True, site_properties=None)
def lat_in_to_sqs(atat_lattice_in, rename=True): """ Convert a string-like ATAT-style lattice.in to an abstract SQS. Parameters ---------- atat_lattice_in : str String-like of a lattice.in in the ATAT format. rename : bool If True, SQS format element names will be renamed, e.g. `a_B` -> `Xab`. Default is True. Returns ------- SQS Abstract SQS. """ # TODO: handle numeric species, e.g. 'g1'. # Problems: parser has trouble with matching next line and we have to rename it so pymatgen # doesn't think it's a charge. # parse the data parsed_data = _parse_atat_lattice(atat_lattice_in) atat_coord_system = parsed_data[0] atat_lattice = parsed_data[1] atat_atoms = parsed_data[2] # create the lattice if len(atat_coord_system) == 3: # we have a coordinate system matrix coord_system = Lattice(list(atat_coord_system)).matrix else: # we have length and angles coord_system = Lattice.from_lengths_and_angles(list(atat_coord_system[0]), list(atat_coord_system[1])).matrix direct_lattice = Lattice(list(atat_lattice)) lattice = coord_system.dot(direct_lattice.matrix) # create the list of atoms, converted to the right coordinate system species_list = [] species_positions = [] subl_model = {} # format {'subl_name': 'atoms_found_in_subl, e.g. "aaabbbb"'} for position, atoms in atat_atoms: # atoms can be a list of atoms, e.g. for not abstract SQS if len(atoms) > 1: raise NotImplementedError('Cannot parse atom list {} because the sublattice is unclear.\nParsed data: {}'.format(atoms, atat_atoms)) atom = atoms[0] if rename: # change from `a_B` style to `Xab` atom = atom.lower().split('_') else: raise NotImplementedError('Cannot rename because the atom name and sublattice name may be ambigous.') # add the abstract atom to the sublattice model subl = atom[0] subl_atom = atom[1] subl_model[subl] = subl_model.get(subl, set()).union({subl_atom}) # add the species and position to the lists species_list.append('X'+subl+subl_atom) species_positions.append(list(position)) # create the structure sublattice_model = [[e for e in sorted(list(set(subl_model[s])))] for s in sorted(subl_model.keys())] sublattice_names = [s for s in sorted(subl_model.keys())] sqs = AbstractSQS(direct_lattice, species_list, species_positions, coords_are_cartesian=True, sublattice_model=sublattice_model, sublattice_names=sublattice_names) sqs.modify_lattice(Lattice(lattice)) return sqs
#%% import math from pymatgen import Structure, Molecule, Lattice import os os.chdir( '/home/jinho93/oxides/perobskite/lanthanum-aluminate/slab/gulp/nonstochio/La-vac/two' ) m = Molecule.from_file('tail.xyz') l = Lattice.from_lengths_and_angles([11.46615, 15.2882, 50], [90, 90, 90]) s = Structure(l, m.species, m.cart_coords, coords_are_cartesian=True) s.make_supercell([[4, 0, 0], [0, 3, 0], [0, 0, 1]]) s.make_supercell([[1, 1, 0], [1, -1, 0], [0, 0, 1]]) s.sort() # ll = Lattice.from_lengths_and_angles([s.lattice.a / 2, s.lattice.b / 2, s.lattice.c], s.lattice.angles) ll = Lattice.from_lengths_and_angles(s.lattice.abc, s.lattice.angles) s = Structure(ll, s.species, s.cart_coords, coords_are_cartesian=True) indi = [] for i, site in enumerate(s.sites): if site.x + site.y < ll.b / math.sqrt(2): indi.append(i) # s.remove_sites(indi) # s = Structure(ll, s.species, s.cart_coords, coords_are_cartesian=True) # s.to('POSCAR', 'POSCAR')
def _parse(self): float_patt = re.compile(r"[+-]?\d+\.\d+[EFD]?[+-]?\d+") # -9.3892E+02 start_patt = re.compile(r"^\s*EEEEEEEEEE STARTING DATE \d+") coord_patt = re.compile(r"^\s+(\d+)\s+(?P<aunit>[TF])\s+(?P<Z>\d+)\s+" r"(?P<specie>\w+)\s+(?P<x>[+-]?\d+\.\d+E[+-]?\d+)" r"\s+(?P<y>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<z>[+-]?\d+\.\d+E[+-]?\d+)") coord_nanotube_patt = re.compile(r"^\s+(\d+)\s+(?P<aunit>[TF])\s+(?P<Z>\d+)\s+" r"(?P<specie>\w+)\s+(?P<x>[+-]?\d+\.\d+E[+-]?\d+)" r"\s+(?P<y>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<z>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<radius>\d+\.\d+)") forces_patt = re.compile(r"^\s+(?P<iat>\d+)\s+(?P<Z>\d+)\s+" r"(?P<x>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<y>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<z>[+-]?\d+\.\d+E[+-]?\d+)") max_grad_patt = re.compile(r"^\sMAX GRADIENT\s+(?P<max_grad>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<max_grad_thr>\d+\.\d+)") rms_grad_patt = re.compile(r"^\sRMS GRADIENT\s+(?P<rms_grad>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<rms_grad_thr>\d+\.\d+)") max_displac_patt = re.compile(r"^\sMAX DISPLAC\.\s+(?P<max_displac>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<max_displac_thr>\d+\.\d+)") rms_displac_patt = re.compile(r"^\sRMS DISPLAC\.\s+(?P<rms_displac>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<rms_displac_thr>\d+\.\d+)") norm_grad_patt = re.compile(r"^\s+GRADIENT NORM\s+(?P<norm_grad>\d+\.\d+)" r"\s+GRADIENT THRESHOLD\s+(?P<norm_grad_thr>\d+\.\d+)") self.title = "" self.system = "" self.group = "" self.slab = False self.nanotube = False self.volumes = list() self.energies = list() self.forces = list() self.convergence_data = list() self.geometry_converge = False self.scf_converge = False external_geometry = False with open(self.filename, "r", encoding=self.encoding) as f: # look for starting message for line in f: if start_patt.match(line): self.title = f.readline().strip() break # ------------------------------------------------------------------ # first, read the initial geometry & identify the type of structure # ------------------------------------------------------------------ for line in f: if re.match(r"^\sGEOMETRY INPUT FROM EXTERNAL FILE", line): external_geometry = True line = f.readline() if "SLAB" in line: self.slab = True if "NANOTUBE" in line: self.nanotube = True print("WARNING: Geometry from an external file.") break if re.match(r"^\sSLAB CALCULATION", line): self.slab = True system_patt = re.compile(r"^\sSYSTEM AND LATTICE") group_patt = re.compile(r" PLANE GROUP N.") break if re.match(r"^\sCRYSTAL CALCULATION", line): system_patt = re.compile(r"^\sCRYSTAL FAMILY") group_patt = re.compile(r"^\sSPACE GROUP") break # look for initial geometry: GEOMETRY FOR WAVEFUNCTION # read group and crystallographic system # check if a SLAB or NANOTUBE is built by GEOMETRY EDITING geom_for_wf = False for line in f: if not external_geometry and system_patt.search(line): self.system = line.split(":")[1].strip() if not external_geometry and group_patt.search(line): self.group = line.split(":")[1].strip() if " SLAB GENERATED " in line: self.slab = True # group and system no more relevant self.group = "" self.system = "" if "CONSTRUCTION OF A NANOTUBE FROM A SLAB" in line: self.nanotube = True self.slab = False # group and system no more relevant self.group = "" self.system = "" if re.match(r"^\sGEOMETRY FOR WAVE FUNCTION", line): geom_for_wf = True break if line == "": # end of file, geometry for wavefunction not found break if not geom_for_wf: # STOP case, add TESTGEOM to d12 raise ValueError("GEOMETRY FOR WAVEFUNCTION NOT FOUND.\n" "Please, add TESTGEOM in the d12 input file.") # read until calculation start # read starting geometry and look for PRIMITIVE or CRYSTALLOGRAPHIC read_geom = False while "CRYSTAL - SCF - TYPE OF CALCULATION" not in line: line = f.readline() if line == "": raise ValueError("End of file.") # search PRIMITIVE CELL if re.match(r"^\sPRIMITIVE CELL", line): read_geom = True geom_patt = re.compile(r"^\sPRIMITIVE CELL") # search CRYSTALLOGRAPHIC CELL if exist if re.match(r"^\sCRYSTALLOGRAPHIC CELL", line): read_geom = True geom_patt = re.compile(r"^\sCRYSTALLOGRAPHIC CELL") if read_geom: if not self.slab and not self.nanotube: volume = float(line.split("=")[1].split()[0].strip(")")) self.volumes.append(volume) f.readline() # lattice parameters line = f.readline() params = [float(val) for val in re.findall(r"\d+\.\d+", line)] lattice = Lattice.from_lengths_and_angles(params[0:3], params[3:]) # step on for 4 lines [f.readline() for _ in range(4)] # read coordinates species = list() # atom names uniq = list() # True if atom belong to the asymmetric unit radius = list() # distance from the axes of the nanotube coords = list() while line != "\n": read = False line = f.readline() if self.nanotube and coord_nanotube_patt.match(line): data = coord_nanotube_patt.match(line).groupdict() read = True elif coord_patt.match(line): data = coord_patt.match(line).groupdict() read = True if read: specie = data["specie"] specie = specie if len(specie) == 1 else specie[0] + specie[1].lower() species.append(specie) coord = [float(data[k]) for k in "xyz"] uniq.append(True if data["aunit"] == "T" else False) if self.slab: coord[2] /= lattice.c elif self.nanotube: coord[1] /= lattice.b coord[2] /= lattice.c radius.append(float(data["radius"])) coords.append(coord) self.structures = [Structure(lattice, species, coords, site_properties={"aunit": uniq})] read_geom = False # ------------------------------------------------------------------ # from that point, SCF, or structure optimization start ! # continue up to the end of file # ------------------------------------------------------------------ n_geom = 0 cvg_data = dict() while line != "": line = f.readline() if " TOTAL ENERGY" in line: self.energies.append(float(float_patt.findall(line)[0])) self.scf_converge = True if "CARTESIAN FORCES IN HARTREE/BOHR" in line: # WARNING: Forces are not printed at each geom step line = f.readline() forces = list() for _ in range(self.initial_structure.num_sites): data = forces_patt.match(f.readline()).groupdict() forces.append([float(data[c]) for c in "xyz"]) self.forces.append(np.array(forces)) if max_grad_patt.match(line): cvg_data.update(max_grad_patt.match(line).groupdict()) if rms_grad_patt.match(line): cvg_data.update(rms_grad_patt.match(line).groupdict()) if max_displac_patt.match(line): cvg_data.update(max_displac_patt.match(line).groupdict()) if rms_displac_patt.match(line): cvg_data.update(rms_displac_patt.match(line).groupdict()) if norm_grad_patt.match(line): cvg_data.update(norm_grad_patt.match(line).groupdict()) if line == "": # end of file ? break if "COORDINATE AND CELL OPTIMIZATION" in line: cvg_data = {k: float(v) for k, v in cvg_data.items()} # end of optimization cycle self.convergence_data.append(cvg_data) n_geom += 1 cvg_data = dict() if "FINAL OPTIMIZED GEOMETRY" in line: self.geometry_converge = True n_geom += 1 # search structure data if geom_patt.match(line): # PRIMITVE or CRYSTALLOGRAPHIC depending on what is present read_geom = True if read_geom: if not self.slab and not self.nanotube: volume = float(line.split("=")[1].split()[0].strip(")")) self.volumes.append(volume) f.readline() # lattice parameters line = f.readline() params = [float(val) for val in re.findall(r"\d+\.\d+", line)] lattice = Lattice.from_lengths_and_angles(params[0:3], params[3:]) # step on for 4 lines [f.readline() for _ in range(4)] # read coordinates species = list() # atom names uniq = list() # True if atom belong to the asymmetric unit radius = list() # distance from the axes of the nanotube coords = list() while line != "\n": read = False line = f.readline() if self.nanotube and coord_nanotube_patt.match(line): data = coord_nanotube_patt.match(line).groupdict() read = True elif coord_patt.match(line): data = coord_patt.match(line).groupdict() read = True if read: specie = data["specie"] specie = specie if len(specie) == 1 else specie[0] + specie[1].lower() species.append(specie) coord = [float(data[k]) for k in "xyz"] uniq.append(True if data["aunit"] == "T" else False) if self.slab: coord[2] /= lattice.c elif self.nanotube: coord[1] /= lattice.b coord[2] /= lattice.c radius.append(float(data["radius"])) coords.append(coord) self.structures.append(Structure(lattice, species, coords, site_properties={"aunit": uniq})) read_geom = False
def _parse(self): float_patt = re.compile(r"[+-]?\d+\.\d+[EFD]?[+-]?\d+") # -9.3892E+02 start_patt = re.compile(r"^\s*EEEEEEEEEE STARTING DATE \d+") coord_patt = re.compile( r"^\s+(\d+)\s+(?P<aunit>[TF])\s+(?P<Z>\d+)\s+" r"(?P<specie>\w+)\s+(?P<x>[+-]?\d+\.\d+E[+-]?\d+)" r"\s+(?P<y>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<z>[+-]?\d+\.\d+E[+-]?\d+)") coord_nanotube_patt = re.compile( r"^\s+(\d+)\s+(?P<aunit>[TF])\s+(?P<Z>\d+)\s+" r"(?P<specie>\w+)\s+(?P<x>[+-]?\d+\.\d+E[+-]?\d+)" r"\s+(?P<y>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<z>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<radius>\d+\.\d+)") forces_patt = re.compile(r"^\s+(?P<iat>\d+)\s+(?P<Z>\d+)\s+" r"(?P<x>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<y>[+-]?\d+\.\d+E[+-]?\d+)\s+" r"(?P<z>[+-]?\d+\.\d+E[+-]?\d+)") max_grad_patt = re.compile( r"^\sMAX GRADIENT\s+(?P<max_grad>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<max_grad_thr>\d+\.\d+)") rms_grad_patt = re.compile( r"^\sRMS GRADIENT\s+(?P<rms_grad>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<rms_grad_thr>\d+\.\d+)") max_displac_patt = re.compile( r"^\sMAX DISPLAC\.\s+(?P<max_displac>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<max_displac_thr>\d+\.\d+)") rms_displac_patt = re.compile( r"^\sRMS DISPLAC\.\s+(?P<rms_displac>\d+\.\d+)" r"\s+THRESHOLD\s+(?P<rms_displac_thr>\d+\.\d+)") norm_grad_patt = re.compile( r"^\s+GRADIENT NORM\s+(?P<norm_grad>\d+\.\d+)" r"\s+GRADIENT THRESHOLD\s+(?P<norm_grad_thr>\d+\.\d+)") self.title = "" self.system = "" self.group = "" self.slab = False self.nanotube = False self.volumes = list() self.energies = list() self.forces = list() self.convergence_data = list() self.geometry_converge = False self.scf_converge = False external_geometry = False with open(self.filename, "r", encoding=self.encoding) as f: # look for starting message for line in f: if start_patt.match(line): self.title = f.readline().strip() break # ------------------------------------------------------------------ # first, read the initial geometry & identify the type of structure # ------------------------------------------------------------------ for line in f: if re.match(r"^\sGEOMETRY INPUT FROM EXTERNAL FILE", line): external_geometry = True line = f.readline() if "SLAB" in line: self.slab = True if "NANOTUBE" in line: self.nanotube = True print("WARNING: Geometry from an external file.") break if re.match(r"^\sSLAB CALCULATION", line): self.slab = True system_patt = re.compile(r"^\sSYSTEM AND LATTICE") group_patt = re.compile(r" PLANE GROUP N.") break if re.match(r"^\sCRYSTAL CALCULATION", line): system_patt = re.compile(r"^\sCRYSTAL FAMILY") group_patt = re.compile(r"^\sSPACE GROUP") break # look for initial geometry: GEOMETRY FOR WAVEFUNCTION # read group and crystallographic system # check if a SLAB or NANOTUBE is built by GEOMETRY EDITING geom_for_wf = False for line in f: if not external_geometry and system_patt.search(line): self.system = line.split(":")[1].strip() if not external_geometry and group_patt.search(line): self.group = line.split(":")[1].strip() if " SLAB GENERATED " in line: self.slab = True # group and system no more relevant self.group = "" self.system = "" if "CONSTRUCTION OF A NANOTUBE FROM A SLAB" in line: self.nanotube = True self.slab = False # group and system no more relevant self.group = "" self.system = "" if re.match(r"^\sGEOMETRY FOR WAVE FUNCTION", line): geom_for_wf = True break if line == "": # end of file, geometry for wavefunction not found break if not geom_for_wf: # STOP case, add TESTGEOM to d12 raise ValueError("GEOMETRY FOR WAVEFUNCTION NOT FOUND.\n" "Please, add TESTGEOM in the d12 input file.") # read until calculation start # read starting geometry and look for PRIMITIVE or CRYSTALLOGRAPHIC read_geom = False while "CRYSTAL - SCF - TYPE OF CALCULATION" not in line: line = f.readline() if line == "": raise ValueError("End of file.") # search PRIMITIVE CELL if re.match(r"^\sPRIMITIVE CELL", line): read_geom = True geom_patt = re.compile(r"^\sPRIMITIVE CELL") # search CRYSTALLOGRAPHIC CELL if exist if re.match(r"^\sCRYSTALLOGRAPHIC CELL", line): read_geom = True geom_patt = re.compile(r"^\sCRYSTALLOGRAPHIC CELL") if read_geom: if not self.slab and not self.nanotube: volume = float( line.split("=")[1].split()[0].strip(")")) self.volumes.append(volume) f.readline() # lattice parameters line = f.readline() params = [ float(val) for val in re.findall(r"\d+\.\d+", line) ] lattice = Lattice.from_lengths_and_angles( params[0:3], params[3:]) # step on for 4 lines [f.readline() for _ in range(4)] # read coordinates species = list() # atom names uniq = list() # True if atom belong to the asymmetric unit radius = list() # distance from the axes of the nanotube coords = list() while line != "\n": read = False line = f.readline() if self.nanotube and coord_nanotube_patt.match(line): data = coord_nanotube_patt.match(line).groupdict() read = True elif coord_patt.match(line): data = coord_patt.match(line).groupdict() read = True if read: specie = data["specie"] specie = specie if len( specie ) == 1 else specie[0] + specie[1].lower() species.append(specie) coord = [float(data[k]) for k in "xyz"] uniq.append(True if data["aunit"] == "T" else False) if self.slab: coord[2] /= lattice.c elif self.nanotube: coord[1] /= lattice.b coord[2] /= lattice.c radius.append(float(data["radius"])) coords.append(coord) self.structures = [ Structure(lattice, species, coords, site_properties={"aunit": uniq}) ] read_geom = False # ------------------------------------------------------------------ # from that point, SCF, or structure optimization start ! # continue up to the end of file # ------------------------------------------------------------------ n_geom = 0 cvg_data = dict() while line != "": line = f.readline() if " TOTAL ENERGY" in line: self.energies.append(float(float_patt.findall(line)[0])) self.scf_converge = True if "CARTESIAN FORCES IN HARTREE/BOHR" in line: # WARNING: Forces are not printed at each geom step line = f.readline() forces = list() for _ in range(self.initial_structure.num_sites): data = forces_patt.match(f.readline()).groupdict() forces.append([float(data[c]) for c in "xyz"]) self.forces.append(np.array(forces)) if max_grad_patt.match(line): cvg_data.update(max_grad_patt.match(line).groupdict()) if rms_grad_patt.match(line): cvg_data.update(rms_grad_patt.match(line).groupdict()) if max_displac_patt.match(line): cvg_data.update(max_displac_patt.match(line).groupdict()) if rms_displac_patt.match(line): cvg_data.update(rms_displac_patt.match(line).groupdict()) if norm_grad_patt.match(line): cvg_data.update(norm_grad_patt.match(line).groupdict()) if line == "": # end of file ? break if "COORDINATE AND CELL OPTIMIZATION" in line: cvg_data = {k: float(v) for k, v in cvg_data.items()} # end of optimization cycle self.convergence_data.append(cvg_data) n_geom += 1 cvg_data = dict() if "FINAL OPTIMIZED GEOMETRY" in line: self.geometry_converge = True n_geom += 1 # search structure data if geom_patt.match(line): # PRIMITVE or CRYSTALLOGRAPHIC depending on what is present read_geom = True if read_geom: if not self.slab and not self.nanotube: volume = float( line.split("=")[1].split()[0].strip(")")) self.volumes.append(volume) f.readline() # lattice parameters line = f.readline() params = [ float(val) for val in re.findall(r"\d+\.\d+", line) ] lattice = Lattice.from_lengths_and_angles( params[0:3], params[3:]) # step on for 4 lines [f.readline() for _ in range(4)] # read coordinates species = list() # atom names uniq = list() # True if atom belong to the asymmetric unit radius = list() # distance from the axes of the nanotube coords = list() while line != "\n": read = False line = f.readline() if self.nanotube and coord_nanotube_patt.match(line): data = coord_nanotube_patt.match(line).groupdict() read = True elif coord_patt.match(line): data = coord_patt.match(line).groupdict() read = True if read: specie = data["specie"] specie = specie if len( specie ) == 1 else specie[0] + specie[1].lower() species.append(specie) coord = [float(data[k]) for k in "xyz"] uniq.append(True if data["aunit"] == "T" else False) if self.slab: coord[2] /= lattice.c elif self.nanotube: coord[1] /= lattice.b coord[2] /= lattice.c radius.append(float(data["radius"])) coords.append(coord) self.structures.append( Structure(lattice, species, coords, site_properties={"aunit": uniq})) read_geom = False
def build_gb(self, vacuum=0.0, add_if_dist=0.0, to_primitive=True, delete_layer="0b0t0b0t", tol=0.25): """ Build the GB based on the given crystal, uc of grain A and B, if_model, vacuum thickness, distance between two grains and tolerance factor. Args: vacuum (float), Angstrom: Vacuum thickness for GB. Default to 0.0 add_if_dist (float), Angstrom: Add extra distance at the interface between two grains. Default to 0.0 to_primitive (bool): Whether to get primitive structure of GB. Default to true. delete_layer (str): Delete interface layers on both sides of each grain. 8 characters in total. The first 4 characters is for grain A and the other 4 is for grain B. "b" means bottom layer and "t" means top layer. Integer represents the number of layers to be deleted. Default to "0b0t0b0t", which means no deletion of layers. The direction of top and bottom layers is based on gb_direction. tol (float), Angstrom: Tolerance factor to determine whether two atoms are at the same plane. Default to 0.25 Returns: GB structure (Grain) """ ind = self.gb_direction delete_layer = delete_layer.lower() delete = re.findall('(\d+)(\w)', delete_layer) if len(delete) != 4: raise ValueError( "'%s' is not supported. Please make sure the format " "is 0b0t0b0t.") for i, v in enumerate(delete): for j in range(int(v[0])): if i <= 1: self.grain_a.delete_bt_layer(v[1], tol, ind) else: self.grain_b.delete_bt_layer(v[1], tol, ind) abc_a = list(self.grain_a.lattice.abc) abc_b, angles = self.grain_b.lattice.lengths_and_angles if ind == 1: l = (abc_a[ind] + add_if_dist) * sin(radians(angles[2])) else: l = abc_a[ind] + add_if_dist abc_a[ind] += abc_b[ind] + 2 * add_if_dist + vacuum new_lat = Lattice.from_lengths_and_angles(abc_a, angles) a_fcoords = new_lat.get_fractional_coords(self.grain_a.cart_coords) grain_a = Grain(new_lat, self.grain_a.species, a_fcoords) l_vector = [0, 0] l_vector.insert(ind, l) b_fcoords = new_lat.get_fractional_coords(self.grain_b.cart_coords + l_vector) grain_b = Grain(new_lat, self.grain_b.species, b_fcoords) gb = Grain.from_sites(grain_a[:] + grain_b[:]) gb = gb.get_sorted_structure() if to_primitive: gb = gb.get_primitive_structure() return gb