Beispiel #1
0
def prepare_ga(dbfile='godb.db', splits={(2,): 1}, N=20):

    blocks = [('Pd', 4), ('OH', 8)]  # the building blocks
    volume = 50. * 4 # volume in angstrom^3

    l = [list(Atoms(block).numbers)*count for block, count in blocks]
    stoichiometry = [item for sublist in l for item in sublist]
    atom_numbers = list(set(stoichiometry))

    blmin = closest_distances_generator(atom_numbers=atom_numbers,
                                        ratio_of_covalent_radii=0.6)
    blmin[(1, 8)] = blmin[(8, 1)] = 2.0

    cellbounds = CellBounds(bounds={'phi': [0.2 * 180., 0.8 * 180.],
                                    'chi': [0.2 * 180., 0.8 * 180.],
                                    'psi': [0.2 *180., 0.8 * 180.],
                                    'a': [2, 8], 'b': [2, 8], 'c': [2, 8]})

    # create the starting population
    sg = StartGenerator(blocks, blmin, volume, cellbounds=cellbounds,
                        splits=splits)

    # create the database to store information in
    da = PrepareDB(db_file_name=dbfile, stoichiometry=stoichiometry)

    for i in range(N):
        a = sg.get_new_candidate()
        a.set_initial_magnetic_moments(magmoms=None)
        niggli_reduce(a)
        da.add_unrelaxed_candidate(a)

    return
Beispiel #2
0
    def __init__(self,
                 atoms,
                 kpts=(1, 1, 1),
                 label='cp2k_run',
                 run_type=None,
                 **extra_cp2k_kwargs):
        try:
            niggli_reduce(atoms)
        except RuntimeError:
            pass

        kwargs = {k: None for k in CP2K.default_parameters}
        kwargs['debug'] = False
        kwargs['potential_file'] = 'GTH_POTENTIALS'
        kwargs['pseudo_potential'] = 'GTH-PBE'
        kwargs['basis_set_file'] = 'BASIS_MOLOPT'
        kwargs['basis_set'] = 'DZVP-MOLOPT-SR-GTH'

        if type(kpts) == float or type(kpts) == int:
            mp = kptdensity2monkhorstpack(atoms, kptdensity=kpts, even=False)
            kpts = tuple(mp)
        inp = template.replace('__MPMESH__', ' '.join(map(str, kpts)))
        kwargs['inp'] = inp

        kwargs.update(extra_cp2k_kwargs)

        CP2K.__init__(self, atoms=atoms, label=label, **kwargs)
def relax(atoms, cellbounds=None):
    # Performs a variable-cell relaxation of the structure
    calc = EMT()
    atoms.set_calculator(calc)

    converged = False
    niter = 0
    while not converged and niter < 10:
        if cellbounds is not None:
            cell = atoms.get_cell()
            if not cellbounds.is_within_bounds(cell):
                niggli_reduce(atoms)
            cell = atoms.get_cell()
            if not cellbounds.is_within_bounds(cell):
                # Niggli reduction did not bring the unit cell
                # within the specified bounds; this candidate should
                # be discarded so we set an absurdly high energy
                finalize(atoms, 1e9)
                return

        ecf = ExpCellFilter(atoms)
        dyn = FIRE(ecf, maxmove=0.2, logfile=None, trajectory=None)
        dyn.run(fmax=1e-3, steps=100)

        converged = dyn.converged()
        niter += 1

    dyn = FIRE(atoms, maxmove=0.2, logfile=None, trajectory=None)
    dyn.run(fmax=1e-2, steps=100)

    e = atoms.get_potential_energy()
    f = atoms.get_forces()
    s = atoms.get_stress()
    finalize(atoms, energy=e, forces=f, stress=s)
Beispiel #4
0
def nigglixyzfunc(name, cellABCabc):
    a = read(name)
    a.set_cell(cellABCabc)
    a.set_pbc(True)
    niggli_reduce(a)
    minimize_tilt(a, order=range(0, 3), fold_atoms=True)
    return [a.get_cell(), a.get_chemical_symbols(), a.get_positions()]
Beispiel #5
0
def test_niggli(i):
    cell = cells_in[i]
    conf.set_cell(cell)
    niggli_reduce(conf)
    cell = conf.get_cell()
    diff = np.linalg.norm(cell - cells_out[i])
    assert diff < 1e-5, \
        'Difference between unit cells is too large! ({0})'.format(diff)
Beispiel #6
0
def finalize(atoms, energy=None, forces=None, stress=None):
    niggli_reduce(atoms)
    atoms.wrap()
    calc = SinglePointCalculator(atoms, energy=energy, forces=forces,
                                 stress=stress)
    atoms.calc = calc
    raw_score = -atoms.get_potential_energy()
    set_raw_score(atoms, raw_score)
Beispiel #7
0
def write_permutations_to_db(db_name, ref_xyz_file, symbols):
    atoms = read(ref_xyz_file)
    niggli_reduce(atoms)
    db = connect(db_name)
    for symb_set in symbols:
        for i, symb in enumerate(symb_set):
            atoms[i].symbol = symb
        db.write(atoms)
    print("All intermetallic structures written to {}".format(db_name))
Beispiel #8
0
 def calculate(self,
               atoms=None,
               properties=None,
               system_changes=all_changes):
     try:
         niggli_reduce(atoms)
     except RuntimeError:
         pass
     CP2K.calculate(self, atoms, properties, system_changes)
Beispiel #9
0
def test_attempt_supercell(get_supercell_paths):
    atoms1 = read(get_supercell_paths[0])
    atoms2 = read(get_supercell_paths[1])
    niggli_reduce(atoms1)
    niggli_reduce(atoms2)

    a_1, a_2 = attempt_supercell(atoms1, atoms2)
    assert pytest.approx(a_1.get_cell_lengths_and_angles(),
                         0.001) == a_2.get_cell_lengths_and_angles()
Beispiel #10
0
def create_convergence_database(db_name):
    atoms = read("data/al3mg2_ref.xyz")
    niggli_reduce(atoms)
    atoms[0].symbol = "Mg"
    atoms[1].symbol = "Mg"
    db = connect(db_name)
    kpt = [4, 6, 8, 10, 12, 14]
    for N in kpt:
        db.write(atoms, kpt=N)
    print("Convergence study written to {}".format(db_name))
Beispiel #11
0
def main(fxyz, prefix, stride):
    # read frames
    if fxyz != 'none':
        frames = read(fxyz, ':')
        nframes = len(frames)
        print("read xyz file:", fxyz, ", a total of", nframes, "frames")

    for s in range(0, nframes, stride):
        frame = frames[s]
        niggli_reduce(frame)
        minimize_tilt(frame, order=range(0, 3), fold_atoms=True)
        write(prefix + '-' + str(s) + '.res', frame)
Beispiel #12
0
def main(runId):
    db = connect(DB_NAME)
    row = db.get(id=runId)
    group = row.group
    atoms = row.toatoms()
    niggli_reduce(atoms)
    calc = EMT()
    atoms.set_calculator(calc)
    ucell = UnitCellFilter(atoms)
    opt = PreconLBFGS(ucell)
    opt.run(fmax=0.02, smax=0.003)

    db.write(atoms, group=group, struct_type='relaxed')
Beispiel #13
0
def parse_periodic_case(file_1,
                        file_2,
                        try_supercell: bool = True,
                        pymatgen: bool = False,
                        get_reduced_structure: bool = True):
    """
    Parser for periodic structures, handles two possible cases:
        (1) Structures are supercells (within tolerance), then one cell is multiplied by the scaling factors
        (2) Structures are not supercells of each other, then we rescale on cell to the volume of the other cell
        to make sure we have meaningful comparisons.

    Args:
        file_1 (str/pymatgen structure object): path to first file, in on format that ASE can parse, pymatgen structure
            object in case pymatgen=True
        file_2 (str/pymatgen structure object): path to second file, pymatgen structure object in case pymatgen=True
        try_supercell (bool): if true, we attempt to build a supercell, default: True
        pymatgen (bool): if true, then file_1 and file_2 take pymatgen structure objects
        get_reduced_structure (bool): if true (default) it gets the Niggli reduced cell.

    Returns:
        atomic symbols (list), cartesian positions (list) of structure 1,
        atomic symbols (list), cartesian positions (list) of structure 2

    """

    if pymatgen:
        atoms1 = AseAtomsAdaptor.get_atoms(file_1)
        atoms2 = AseAtomsAdaptor.get_atoms(file_2)
    else:
        atoms1 = read(file_1)
        atoms2 = read(file_2)

    if get_reduced_structure:
        niggli_reduce(atoms1)
        niggli_reduce(atoms2)

    if try_supercell:
        a1, a2 = attempt_supercell(atoms1, atoms2)
    else:
        a1, a2 = rescale_periodic_system(atoms1, atoms2)

    atomic_symbols_1 = a1.get_chemical_symbols()
    positions_1 = a1.get_positions()

    atomic_symbols_2 = a2.get_chemical_symbols()
    positions_2 = a2.get_positions()

    return np.array(atomic_symbols_1), np.array(positions_1), np.array(
        atomic_symbols_2), np.array(positions_2)
Beispiel #14
0
def parse_periodic_case(file_1, file_2):
    atoms1 = read(file_1)
    atoms2 = read(file_2)
    niggli_reduce(atoms1)
    niggli_reduce(atoms2)

    a1, a2 = rescale_periodic_system(atoms1, atoms2)

    atomic_symbols_1 = a1.get_chemical_symbols()
    positions_1 = a1.get_positions()

    atomic_symbols_2 = a2.get_chemical_symbols()
    positions_2 = a2.get_positions()

    return atomic_symbols_1, positions_1, atomic_symbols_2, positions_2
Beispiel #15
0
def dcdft():
    """Create delta-codes-DFT collection.

    Data from: https://github.com/molmod/DeltaCodesDFT
    """
    os.environ['USER'] = '******'
    con = ase.db.connect('dcdft.json')
    with open('history/exp.txt') as fd:
        lines = fd.readlines()
    experiment = {}
    for line in lines[2:-1]:
        words = line.split()
        print(words)
        experiment[words[0]] = [float(word) for word in words[1:]]
    with open('WIEN2k.txt') as fd:
        lines = fd.readlines()
    for line in lines[2:73]:
        words = line.split()
        symbol = words.pop(0)
        vol, B, Bp = (float(x) for x in words)
        filename = 'primCIFs/' + symbol + '.cif'
        atoms = read(filename)
        if symbol in ['Li', 'Na']:
            niggli_reduce(atoms)
        M = {
            'Fe': 2.3,
            'Co': 1.2,
            'Ni': 0.6,
            'Cr': 1.5,
            'O': 1.5,
            'Mn': 2.0
        }.get(symbol)
        if M is not None:
            magmoms = [M] * len(atoms)
            if symbol in ['Cr', 'O', 'Mn']:
                magmoms[len(atoms) // 2:] = [-M] * (len(atoms) // 2)
            atoms.set_initial_magnetic_moments(magmoms)

        extra = {}
        exp = experiment.get(symbol, [])
        for key, val in zip(['exp_volume', 'exp_B', 'exp_Bp'], exp):
            extra[key] = val
        con.write(atoms,
                  name=symbol,
                  wien2k_B=B,
                  wien2k_Bp=Bp,
                  wien2k_volume=vol,
                  **extra)
 def get_reduced_structure(self, structure):
     sname = Path(structure).name
     stem = Path(structure).stem
     if self.cached:
         self.reduced_structure_dict = {}
     try:
         # Cif reader in ASE seems more stable to me, especially for CSD data
         atoms = read(structure)
     except Exception:
         logger.error("Could not read structure %s", stem)
     else:
         niggli_reduce(atoms)
         if not self.cached:
             write(os.path.join(self.tempdirpath, sname), atoms)
         else:
             crystal = AseAtomsAdaptor.get_structure(atoms)
             self.reduced_structure_dict[stem] = crystal
     return stem
Beispiel #17
0
def dcdft():
    """Create delta-codes-DFT collection.

    Data from: https://github.com/molmod/DeltaCodesDFT
    """
    os.environ['USER'] = '******'
    con = ase.db.connect('dcdft.json')
    with open('history/exp.txt') as fd:
        lines = fd.readlines()
    experiment = {}
    for line in lines[2:-1]:
        words = line.split()
        print(words)
        experiment[words[0]] = [float(word) for word in words[1:]]
    with open('WIEN2k.txt') as fd:
        lines = fd.readlines()
    for line in lines[2:73]:
        words = line.split()
        symbol = words.pop(0)
        vol, B, Bp = (float(x) for x in words)
        filename = 'primCIFs/' + symbol + '.cif'
        atoms = read(filename)
        if symbol in ['Li', 'Na']:
            niggli_reduce(atoms)
        M = {'Fe': 2.3,
             'Co': 1.2,
             'Ni': 0.6,
             'Cr': 1.5,
             'O': 1.5,
             'Mn': 2.0}.get(symbol)
        if M is not None:
            magmoms = [M] * len(atoms)
            if symbol in ['Cr', 'O', 'Mn']:
                magmoms[len(atoms) // 2:] = [-M] * (len(atoms) // 2)
            atoms.set_initial_magnetic_moments(magmoms)

        extra = {}
        exp = experiment.get(symbol, [])
        for key, val in zip(['exp_volume', 'exp_B', 'exp_Bp'], exp):
            extra[key] = val
        con.write(atoms, name=symbol,
                  wien2k_B=B, wien2k_Bp=Bp, wien2k_volume=vol,
                  **extra)
Beispiel #18
0
    def mutate(self, atoms):
        """ Does the actual mutation. """
        cell_ref = atoms.get_cell()
        pos_ref = atoms.get_positions()
        vol = atoms.get_volume()
        if self.use_tags:
            tags = atoms.get_tags()
            gather_atoms_by_tag(atoms)
            pos = atoms.get_positions()

        mutant = atoms.copy()
        if self.cellbounds is not None:
            if not self.cellbounds.is_within_bounds(cell_ref):
                niggli_reduce(mutant)

        count = 0
        too_close = True
        maxcount = 1000
        while too_close and count < maxcount:
            mutant.set_cell(cell_ref, scale_atoms=False)
            mutant.set_positions(pos_ref)

            # generating the strain matrix:
            strain = np.identity(3)
            for i in range(3):
                for j in range(i + 1):
                    if i == j:
                        strain[i, j] += gauss(0, self.stddev)
                    else:
                        epsilon = 0.5 * gauss(0, self.stddev)
                        strain[i, j] += epsilon
                        strain[j, i] += epsilon

            # applying the strain:
            cell_new = np.dot(strain, cell_ref)

            # volume scaling:
            v = abs(np.linalg.det(cell_new))
            if self.scaling_volume is None:
                cell_new *= (vol / v)**(1. / 3)
            else:
                cell_new *= (self.scaling_volume / v)**(1. / 3)

            # check cell dimensions:
            if not self.cellbounds.is_within_bounds(cell_new):
                continue

            if self.use_tags:
                transfo = np.linalg.solve(cell_ref, cell_new)
                for tag in np.unique(tags):
                    select = np.where(tags == tag)
                    cop = np.mean(pos[select], axis=0)
                    disp = np.dot(cop, transfo) - cop
                    mutant.positions[select] += disp

            mutant.set_cell(cell_new, scale_atoms=not self.use_tags)

            # check distances:
            too_close = atoms_too_close(mutant,
                                        self.blmin,
                                        use_tags=self.use_tags)
            count += 1

        if count == maxcount:
            mutant = None

        return mutant
Beispiel #19
0
      [-4.47766735594495e+00, +1.26866266221366e+01, +0.00000000000000e+00],
      [-3.68163760377696e+00, -5.94997793843316e+00, +1.14910098375475e+01]],
     [[+1.13578166916005e+01, +0.00000000000000e+00, +0.00000000000000e+00],
      [-4.62236725820948e+00, +1.28309672640153e+01, +0.00000000000000e+00],
      [-3.36772471669551e+00, -6.41548363200768e+00, +1.15542200082913e+01]],
     [[+1.18321595661992e+01, +0.00000000000000e+00, +0.00000000000000e+00],
      [-4.71877792223422e+00, +1.29511827614560e+01, +0.00000000000000e+00],
      [-3.55669082198251e+00, -6.47559138072800e+00, +1.16368667031408e+01]],
     [[+4.81947971142972e-03, +0.00000000000000e+00, +0.00000000000000e+00],
      [+4.12397039845618e-03, +4.86743859122682e+01, +0.00000000000000e+00],
      [+4.62732595971025e-03, +1.13797841621313e+01, +6.81149615940608e+01]],
     [[+1.43683914413843e-01, +0.00000000000000e+00, +0.00000000000000e+00],
      [+4.73841211849216e-02, +8.02075186538656e+00, +0.00000000000000e+00],
      [+9.29303317118020e-03, +8.28854375915883e-01, +1.93660401476964e+01]],
     [[+5.02420000000000e+00, +0.00000000000000e+00, +0.00000000000000e+00],
      [-2.40035596861745e+00, +1.25083680303996e+01, +0.00000000000000e+00],
      [-2.37319883118274e+00, -5.49894680458153e+00, +2.86098306766757e+01]],
     [[+5.02419976114664e+00, +0.00000000000000e+00, +0.00000000000000e+00],
      [-2.40036499209593e+00, +1.25083662987906e+01, +0.00000000000000e+00],
      [-2.37320481266200e+00, -5.49892622854049e+00, +2.86097847514890e+01]]])

conf = Atoms(pbc=True)

for i, cell in enumerate(cells_in):
    conf.set_cell(cell)
    niggli_reduce(conf)
    cell = conf.get_cell()
    diff = np.linalg.norm(cell - cells_out[i])
    assert diff < 1e-5, \
        'Difference between unit cells is too large! ({0})'.format(diff)
Beispiel #20
0
    def __init__(self, fxyz=None, stride=1, periodic=True, fileformat=None):
        # compile a list of matching xyz files
        # in fact they don't strictly need to be xyz format, anything that can be read by ASE is fine
        # a list of possible file formats: https://wiki.fysik.dtu.dk/ase/ase/io/io.html
        if '*' in fxyz:
            self.fxyz = glob.glob(fxyz)
            print("Find matching input files with coordinates: ", self.fxyz)
        else:
            self.fxyz = fxyz
        # essential
        self.stride = stride
        self.periodic = periodic
        if fileformat is not None:
            import ast
            self.fileformat = ast.literal_eval(fileformat)
        else:
            self.fileformat = {}

        # store the xyz file
        self.frames = None
        self.nframes = 0
        self.natom_list = []  # number of atoms for each frame
        self.total_natoms = 0  # total number of atoms for all frames
        self.global_species = []  # list of elements contains in all frames

        # record the state of the computation, e.g. which descriptors have been computed
        self.computed_desc_dict = {'data': {'fxyz': fxyz}}
        self.computed_desc_dict = {'descriptors': {}}
        # the conversion between tag of the descriptors and their acronyms
        self.tag_to_acronym = {'global': {}, 'atomic': {}}

        # we make a dictionary to store the computed descriptors
        self.global_desc = {}
        # this is for the atomic ones
        self.atomic_desc = {}

        # try to read the xyz file
        try:
            if isinstance(self.fxyz, (tuple, list)):
                self.frames = []
                for f in self.fxyz:
                    self.frames += read(f, slice(0, None, self.stride), **self.fileformat)
            else:
                self.frames = read(self.fxyz, slice(0, None, self.stride), **self.fileformat)
        except:
            raise ValueError('Exception occurred when loading the input file')

        self.nframes = len(self.frames)
        all_species = []
        for i, frame in enumerate(self.frames):
            # record the total number of atoms
            self.natom_list.append(len(frame.get_positions()))
            all_species.extend(frame.get_atomic_numbers())
            if frame.get_pbc()[0] and frame.get_pbc()[1] and frame.get_pbc()[2]:
                # niggli_reduce
                niggli_reduce(frame)
            if not self.periodic or not np.sum(frame.get_cell()) > 0:
                frame.set_pbc([False, False, False])
            # we also initialize the descriptor dictionary for each frame
            self.global_desc[i] = {}
            self.atomic_desc[i] = {}

        self.total_natoms = np.sum(self.natom_list)
        self.max_atoms = max(self.natom_list)
        # Keep things in plain python for serialisation
        self.global_species = np.unique(all_species).tolist()
        print('load xyz file: ', self.fxyz,
              ', a total of ', str(self.nframes), 'frames',
              ', a total of ', str(self.total_natoms), 'atoms',
              ', with elements: ', self.global_species, '.')
Beispiel #21
0
    def cross(self, a1, a2):
        """Crosses the two atoms objects and returns one"""

        if len(a1) != len(a2):
            raise ValueError('The two structures do not have the same length')

        N = len(a1) if self.n_top is None else self.n_top
        slab = a1[:len(a1) - N]
        a1 = a1[-N:]
        a2 = a2[-N:]

        if not np.array_equal(a1.numbers, a2.numbers):
            err = 'Trying to pair two structures with different stoichiometry'
            raise ValueError(err)

        if self.use_tags and not np.array_equal(a1.get_tags(), a2.get_tags()):
            err = 'Trying to pair two structures with different tags'
            raise ValueError(err)

        a1_copy = a1.copy()
        a2_copy = a2.copy()

        if self.cellbounds is not None:
            if not self.cellbounds.is_within_bounds(a1_copy.get_cell()):
                niggli_reduce(a1_copy)
            if not self.cellbounds.is_within_bounds(a2_copy.get_cell()):
                niggli_reduce(a2_copy)

        pos1_ref = a1_copy.get_positions()
        pos2_ref = a2_copy.get_positions()

        invalid = True
        counter = 0
        maxcount = 1000

        # Run until a valid pairing is made or 1000 pairings are tested.
        while invalid and counter < maxcount:
            counter += 1

            # Choose direction of cutting plane normal (0, 1, or 2):
            direction = randrange(3)

            # Randomly translate parent structures:
            for a, pos in zip([a1_copy, a2_copy], [pos1_ref, pos2_ref]):
                a.set_positions(pos)
                cell = a.get_cell()

                for i in range(3):
                    r = random()
                    cond1 = i == direction and r < self.p1
                    cond2 = i != direction and r < self.p2
                    if cond1 or cond2:
                        a.positions += random() * cell[i, :]

                if self.use_tags:
                    gather_atoms_by_tag(a)
                else:
                    a.wrap()

            # Perform the pairing:
            fraction = random()
            child = self._get_pairing(a1_copy,
                                      a2_copy,
                                      direction=direction,
                                      fraction=fraction)
            if child is None:
                continue

            # Verify whether the atoms are too close or not:
            invalid = atoms_too_close(child,
                                      self.blmin,
                                      use_tags=self.use_tags)
            if invalid:
                continue
            elif self.test_dist_to_slab:
                invalid = atoms_too_close_two_sets(slab, child, self.blmin)

        if counter == maxcount:
            return None

        return child
Beispiel #22
0
from ase.build import niggli_reduce
from ase import Atoms
from ase.io import write as aseWrite
from ioAndInterfaces import ccdcCrystalToASE
from ccdc.io import CrystalReader

#example input and outputs to test this
inputRes, outputRes = 'testingScripts/new.res', 'temp070917.res'

myCell = CrystalReader(inputRes)[0]
myASECell = ccdcCrystalToASE(myCell)
myASECell.set_pbc(True)
niggli_reduce(myASECell)

aseWrite(outputRes, myASECell)

print 'issue with this is that crystal optimiser wants labels etc, and probably fussy with res file format'
#could attach labels or something if can be bothered

print 'another issue is that the cell may not have the same convention, so would have to reset rather
       than just changing angles etc'
Beispiel #23
0
N = int(sys.argv[1])  # NxNx1 supercell
h = 0.15

a = 2.51026699
cell = [[a, 0., 0.],
        [-a / 2, np.sqrt(3) / 2 * a, 0.],
        [0., 0., c]]
scaled_positions = [[2. / 3, 1. / 3, 0.5],
                    [1. / 3, 2. / 3, 0.5]]

system = Atoms('BN',
               cell=cell,
               scaled_positions=scaled_positions,
               pbc=[1, 1, 1])
system = system.repeat((2, 1, 1))
niggli_reduce(system)

defect = system.repeat((N, N, 1))
defect[0].symbol = 'C'
defect[1].magmom = 1

q = +1  # Defect charge

calc = GPAW(mode='fd',
            kpts={'size': (4, 4, 1)},
            xc='PBE',
            charge=q,
            occupations=FermiDirac(0.01),
            txt='BN{0}{0}.CB_charged.txt'.format(N))

Beispiel #24
0
    def __init__(self, structures=[],
                 info={},
                 cell_reduce=False,
                 progress=False, suppress_ase_warnings=True):
        """
        Initialize the AtomsCollection

        | Args:
        |    structures (list[str] or list[ase.Atoms]): list of file names or
        |                                               Atoms that will form
        |                                               the collection
        |    info (dict): dictionary of general information to attach
        |                 to this collection
        |    cell_reduce (bool): if True, perform a Niggli cell reduction on
        |                        all loaded structures
        |    progress (bool): visualize a progress bar for the loading process
        |    suppress_ase_warnings (bool): suppress annoying ASE warnings when
        |                                  loading files (default is True)
        """

        # Start by parsing out the structures
        self.structures = []

        if isinstance(structures, ase.Atoms):
            # Well, it's just one...
            structures = [structures]
        elif inspect.isgenerator(structures):
            # Let's unravel it
            iter_structs = structures
            structures = []
            for s in iter_structs:
                structures.append(s)

        if progress:
            sys.stdout.write("Loading collection...\n")
        s_n = len(structures)
        for s_i, struct in enumerate(structures):
            if progress:
                # Progress bar
                sys.stdout.write("\rLoading: {0}".format(utils.progbar(s_i+1,
                                                                       s_n)))
            # Is it an Atoms object?
            if type(struct) is ase.Atoms:
                self.structures.append(ase.Atoms(struct))
                # Copy all arrays
                for k in struct.arrays.keys():
                    if not self.structures[-1].has(k):
                        self.structures[-1].new_array(k, struct.get_array(k))
                if struct.calc is not None:
                    # Prevents pointless attempts at re-calculating
                    self.structures[-1].calc._old_atoms = self.structures[-1]
            # Or is it a string?
            elif utils.is_string(struct):
                with utils.silence_stdio(suppress_ase_warnings,
                                         suppress_ase_warnings):
                    self.structures.append(ase_io.read(str(struct)))
                # If there's no name, give it the filename
                if 'name' not in self.structures[-1].info:
                    self.structures[-1].info['name'] = utils.seedname(struct)
            else:
                raise TypeError('Structures must be Atoms objects or valid '
                                'file names,'
                                ' not {0}'.format(type(struct).__name__))
            if cell_reduce:
                # Here we must keep the energy if it was present
                # We do this by hand because ASE has its good reasons
                # for severing the atoms-calculator connection when changing
                # the unit cell.
                try:
                    _E = self.structures[-1].calc.results['energy']
                except (KeyError, AttributeError):
                    _E = None
                niggli_reduce(self.structures[-1])
                if _E is not None:
                    _calc = SinglePointCalculator(self.structures[-1],
                                                  energy=_E)
                    self.structures[-1].set_calculator(_calc)

        if progress:
            sys.stdout.write('\nLoaded {0} structures\n'.format(s_n))

        self._all = _AllCaller(self.structures, ase.Atoms)

        self._arrays = {}

        # Now assign the info
        if type(info) is not dict:
            raise TypeError('Info must be dict,'
                            ' not {0}'.format(type(info).__name__))
        else:
            self.info = info.copy()
Beispiel #25
0
     [-4.47766735594495e+00, +1.26866266221366e+01, +0.00000000000000e+00],
     [-3.68163760377696e+00, -5.94997793843316e+00, +1.14910098375475e+01]],
    [[+1.13578166916005e+01, +0.00000000000000e+00, +0.00000000000000e+00],
     [-4.62236725820948e+00, +1.28309672640153e+01, +0.00000000000000e+00],
     [-3.36772471669551e+00, -6.41548363200768e+00, +1.15542200082913e+01]],
    [[+1.18321595661992e+01, +0.00000000000000e+00, +0.00000000000000e+00],
     [-4.71877792223422e+00, +1.29511827614560e+01, +0.00000000000000e+00],
     [-3.55669082198251e+00, -6.47559138072800e+00, +1.16368667031408e+01]],
    [[+4.81947971142972e-03, +0.00000000000000e+00, +0.00000000000000e+00],
     [+4.12397039845618e-03, +4.86743859122682e+01, +0.00000000000000e+00],
     [+4.62732595971025e-03, +1.13797841621313e+01, +6.81149615940608e+01]],
    [[+1.43683914413843e-01, +0.00000000000000e+00, +0.00000000000000e+00],
     [+4.73841211849216e-02, +8.02075186538656e+00, +0.00000000000000e+00],
     [+9.29303317118020e-03, +8.28854375915883e-01, +1.93660401476964e+01]],
    [[+5.02420000000000e+00, +0.00000000000000e+00, +0.00000000000000e+00],
     [-2.40035596861745e+00, +1.25083680303996e+01, +0.00000000000000e+00],
     [-2.37319883118274e+00, -5.49894680458153e+00, +2.86098306766757e+01]],
    [[+5.02419976114664e+00, +0.00000000000000e+00, +0.00000000000000e+00],
     [-2.40036499209593e+00, +1.25083662987906e+01, +0.00000000000000e+00],
     [-2.37320481266200e+00, -5.49892622854049e+00, +2.86097847514890e+01]]])

conf = Atoms(pbc=True)

for i, cell in enumerate(cells_in):
    conf.set_cell(cell)
    niggli_reduce(conf)
    cell = conf.get_cell()
    diff = np.linalg.norm(cell - cells_out[i])
    assert diff < 1e-5, \
        'Difference between unit cells is too large! ({0})'.format(diff)