Esempio n. 1
0
    def __init__(self, atoms, **kwargs):
        """Initialize with an ASE atoms object and keyword arguments."""
        self._atoms = atoms
        for key in kwargs:
            if key not in self._default_settings:
                raise RuntimeError('Unknown keyword: %s' % key)
        for k, v in self._default_settings.items():
            setattr(self, '_%s' % k, kwargs.pop(k, v))

        # when a MD sim. has passed a local minimum:
        self._passedminimum = PassedMinimum()

        # Misc storage.
        self._previous_optimum = None
        self._previous_energy = None
        self._temperature = self._T0
        self._Ediff = self._Ediff0

        #Oganov fingerprints for structure comparison
        self._comp = OFPComparator(dE=1.0,
                                   cos_dist_max=5e-3,
                                   rcut=20.,
                                   binwidth=0.05,
                                   pbc=[True, True, True],
                                   sigma=0.05,
                                   nsigma=4,
                                   recalculate=False)
def run_ga(n_to_test):
    """
    This method specifies how to run the GA once the
    initial random structures have been stored in godb.db.
    """
    # Various initializations:
    population_size = 10  # maximal size of the population
    da = DataConnection('godb.db')
    atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()  # = [14] * 7
    n_to_optimize = len(atom_numbers_to_optimize)  # = 7
    # This defines how close the Si atoms are allowed to get
    # in candidate structures generated by the genetic operators:
    blmin = closest_distances_generator(atom_numbers_to_optimize,
                                        ratio_of_covalent_radii=0.4)
    # This is our OFPComparator instance which will be
    # used to judge whether or not two structures are identical:
    comparator = OFPComparator(n_top=None, dE=1.0, cos_dist_max=1e-3,
                               rcut=10., binwidth=0.05, pbc=[False]*3,
                               sigma=0.1, nsigma=4, recalculate=False)

    # Defining a typical combination of genetic operators:
    pairing = CutAndSplicePairing(da.get_slab(), n_to_optimize, blmin)
    rattlemut = RattleMutation(blmin, n_to_optimize, rattle_prop=0.8,
                               rattle_strength=1.5)
    operators = OperationSelector([2., 1.], [pairing, rattlemut])

    # Relax the randomly generated initial candidates:
    while da.get_number_of_unrelaxed_candidates() > 0:
        a = da.get_an_unrelaxed_candidate()
        a = relax_one(a)
        da.add_relaxed_step(a)

    # Create the population
    population = Population(data_connection=da,
                            population_size=population_size,
                            comparator=comparator,
                            logfile='log.txt')
    current_pop = population.get_current_population()

    # Test n_to_test new candidates
    for step in range(n_to_test):
        print('Starting configuration number %d' % step, flush=True)

        a3 = None
        while a3 is None:
            a1, a2 = population.get_two_candidates()
            a3, description = operators.get_new_individual([a1, a2])

        da.add_unrelaxed_candidate(a3, description=description)
        a3 = relax_one(a3)
        da.add_relaxed_step(a3)

        population.update()
        best = population.get_current_population()[0]
        print('Highest raw score at this point: %.3f' % get_raw_score(best))

    print('GA finished after step %d' % step)
    write('all_candidates.traj', da.get_all_relaxed_candidates())
    write('current_population.traj', population.get_current_population())
Esempio n. 3
0
    def __init__(self, atoms, **kwargs):
        """Initialize with an ASE atoms object and keyword arguments."""
        self._atoms = atoms
        for key in kwargs:
            if key not in self._default_settings:
                raise RuntimeError('Unknown keyword: %s' % key)
        for k, v in self._default_settings.items():
            setattr(self, '_%s' % k, kwargs.pop(k, v))

        # when a MD sim. has passed a local minimum:
        self._passedminimum = PassedMinimum()

        # Misc storage.
        self._previous_optimum = None
        self._previous_energy = None
        self._temperature = self._T0
        self._Ediff = self._Ediff0

        #Oganov fingerprints for structure comparison
        self._comp = OFPComparator(dE=10.0,
                     cos_dist_max=self._minima_threshold, rcut=20., binwidth=0.05,
                     pbc=[True, True, True], sigma=0.05, nsigma=4,
                     recalculate=False)

        #inorganic indices and positions for Hookean constraints
        self._Pb_indices = np.where(self._atoms.symbols == 'Pb')[0]
        self._Pb_positions = self._atoms.positions[self._Pb_indices]
        self._Br_indices = np.where(self._atoms.symbols == 'Br')[0]
        self._Br_positions = self._atoms.positions[self._Br_indices]
        self._inorganic_indices = np.concatenate((self._Pb_indices, self._Br_indices))
        self._inorganic_positions = self._atoms.positions[self._inorganic_indices]
        #make list for distances of Pb atoms and 4 surrounding Br
#        self._distances_list = np.empty((len(self._Pb_indices), 6))
        self._indices_list = np.empty((len(self._Pb_indices), 6), dtype='int')

        for i in range(len(self._Pb_indices)):
            distances = self._atoms.get_distances(self._Pb_indices[i], self._Br_indices, mic=True)
#            self._distances_list[i] = distances[np.argsort(distances)[:6]]
            self._indices_list[i] = self._Br_indices[np.argsort(distances)[:6]]
blmin_soft = closest_distances_generator(atom_numbers_to_optimize, 0.8)
softmut = SoftMutation(blmin_soft, bounds=[2., 5.], use_tags=True)

operators = OperationSelector([5, 1, 1, 1, 1, 1], [pairing, rattlemut,
                                                   strainmut, rotmut, rattlerotmut, softmut])

# Relaxing the initial candidates
while da.get_number_of_unrelaxed_candidates() > 0:
    a = da.get_an_unrelaxed_candidate()
    relax(a)
    da.add_relaxed_step(a)

# The structure comparator for the population
comp = OFPComparator(n_top=n_top, dE=1.0, cos_dist_max=5e-3, rcut=10.,
                     binwidth=0.05, pbc=[True, True, True], sigma=0.05,
                     nsigma=4, recalculate=False)

# The population
population = Population(data_connection=da,
                        population_size=10,
                        comparator=comp,
                        logfile='log.txt')

current_pop = population.get_current_population()
strainmut.update_scaling_volume(current_pop, w_adapt=0.5, n_adapt=4)
pairing.update_scaling_volume(current_pop, w_adapt=0.5, n_adapt=4)

# Test a few new candidates
n_to_test = 10
Esempio n. 5
0
    cell = a3.get_cell()
    assert cellbounds.is_within_bounds(cell)
    assert np.all(a3.numbers == a.numbers)
    assert not atoms_too_close(a3, blmin, use_tags=True)

modes_file = 'modes.txt'
softmut_with = SoftMutation(blmin,
                            bounds=[2., 5.],
                            use_tags=True,
                            used_modes_file=modes_file)
no_muts = 3
for _ in range(no_muts):
    softmut_with.get_new_individual([a1])
softmut_with.read_used_modes(modes_file)
assert len(list(softmut_with.used_modes.values())[0]) == no_muts
os.remove(modes_file)

comparator = OFPComparator(recalculate=True)
gold = bulk('Au') * (2, 2, 2)
assert comparator.looks_like(gold, gold)

# This move should not exceed the default threshold
gc = gold.copy()
gc[0].x += .1
assert comparator.looks_like(gold, gc)

# An additional step will exceed the threshold
gc[0].x += .2
assert not comparator.looks_like(gold, gc)
Esempio n. 6
0
                              atoms_too_close)
from ase.ga.offspring_creator import OperationSelector
from ase.ga.ofp_comparator import OFPComparator
from ase.ga.bulk_utilities import CellBounds
from ase.ga.bulk_startgenerator import StartGenerator
from ase.ga.bulk_crossovers import CutAndSplicePairing
from ase.ga.bulk_mutations import *
from ase.ga.standardmutations import RattleMutation
from tango.relax_utils import push_apart, relax_precon, finalize
from tango.calculators import DftbPlusCalculator

comparator = OFPComparator(n_top=None,
                           dE=1.0,
                           cos_dist_max=5e-2,
                           rcut=10.,
                           binwidth=0.05,
                           pbc=[True] * 3,
                           sigma=0.1,
                           nsigma=4,
                           recalculate=False)


def penalize(t):
    # penalize explosion:
    raw_score = get_raw_score(t)
    max_volume_per_atom = 50.
    if t.get_volume() / len(t) >= max_volume_per_atom:
        raw_score -= 1e9
    set_raw_score(t, raw_score)

    def __init__(self, atoms, **kwargs):
        """Initialize with an ASE atoms object and keyword arguments."""
        self._atoms = atoms
        for key in kwargs:
            if key not in self._default_settings:
                raise RuntimeError('Unknown keyword: %s' % key)
        for k, v in self._default_settings.items():
            setattr(self, '_%s' % k, kwargs.pop(k, v))

        # when a MD sim. has passed a local minimum:
        self._passedminimum = PassedMinimum()

        # Misc storage.
        self._previous_optimum = None
        self._previous_energy = None
        self._temperature = self._T0
        self._Ediff = self._Ediff0

        #Oganov fingerprints for structure comparison
        self._comp = OFPComparator(dE=10.0,
                                   cos_dist_max=self._minima_threshold,
                                   rcut=20.,
                                   binwidth=0.05,
                                   pbc=[True, True, True],
                                   sigma=0.05,
                                   nsigma=4,
                                   recalculate=False)

        #inorganic indices and positions for Hookean constraints
        self._Pb_indices = np.where(self._atoms.symbols == 'Pb')[0]
        self._Pb_positions = self._atoms.positions[self._Pb_indices]
        self._Br_indices = np.where(self._atoms.symbols == 'Br')[0]
        self._Br_positions = self._atoms.positions[self._Br_indices]
        self._inorganic_indices = np.concatenate(
            (self._Pb_indices, self._Br_indices))
        self._inorganic_positions = self._atoms.positions[
            self._inorganic_indices]
        #make list for distances of Pb atoms and 6 surrounding Br
        #        self._distances_list = np.empty((len(self._Pb_indices), 6))
        self._indices_list = np.empty((len(self._Pb_indices), 6), dtype='int')

        for i in range(len(self._Pb_indices)):
            distances = self._atoms.get_distances(self._Pb_indices[i],
                                                  self._Br_indices,
                                                  mic=True)
            #            self._distances_list[i] = distances[np.argsort(distances)[:6]]
            self._indices_list[i] = self._Br_indices[np.argsort(distances)[:6]]

        #find pairs of 2 Br's closest in z-direction and furthest in z-direction
        average_Br_z = np.average(self._Br_positions[:, 2])
        top_Br = self._Br_indices[np.where(
            self._Br_positions[:, 2] > average_Br_z)]
        bottom_Br = self._Br_indices[np.where(
            self._Br_positions[:, 2] < average_Br_z)]
        #Br groups are labelled 1,2,3,4 from bottom to top so 1-4 and 2-3 should be paired
        Br_group1 = bottom_Br[np.argsort(
            self._atoms.positions[bottom_Br][:, 2])[:4]]
        Br_group2 = bottom_Br[np.argsort(
            self._atoms.positions[bottom_Br][:, 2])[-4:]]
        Br_group3 = top_Br[np.argsort(self._atoms.positions[top_Br][:, 2])[:4]]
        Br_group4 = top_Br[np.argsort(self._atoms.positions[top_Br][:,
                                                                    2])[-4:]]

        self._Br_index1 = int(Br_group1[0])
        Br_relative1 = self._atoms.positions[
            self._Br_index1] - self._atoms.positions[Br_group4]
        self._Br_index4 = int(Br_group4[np.argmin(
            np.linalg.norm(Br_relative1[:, :2], axis=1))])

        Br_relative2 = self._atoms.positions[
            self._Br_index1] - self._atoms.positions[Br_group2]
        self._Br_index2 = int(Br_group2[np.argmin(
            np.linalg.norm(Br_relative2[:, :2], axis=1))])

        Br_relative3 = self._atoms.positions[
            self._Br_index2] - self._atoms.positions[Br_group3]
        self._Br_index3 = int(Br_group3[np.argmin(
            np.linalg.norm(Br_relative3[:, :2], axis=1))])
def test_bulk_operators():
    h2 = Atoms('H2', positions=[[0, 0, 0], [0, 0, 0.75]])
    blocks = [('H', 4), ('H2O', 3), (h2, 2)]  # the building blocks
    volume = 40. * sum([x[1] for x in blocks])  # cell volume in angstrom^3
    splits = {(2,): 1, (1,): 1}  # cell splitting scheme

    stoichiometry = []
    for block, count in blocks:
        if type(block) == str:
            stoichiometry += list(Atoms(block).numbers) * count
        else:
            stoichiometry += list(block.numbers) * count

    atom_numbers = list(set(stoichiometry))
    blmin = closest_distances_generator(atom_numbers=atom_numbers,
                                        ratio_of_covalent_radii=1.3)

    cellbounds = CellBounds(bounds={'phi': [30, 150], 'chi': [30, 150],
                                    'psi': [30, 150], 'a': [3, 50],
                                    'b': [3, 50], 'c': [3, 50]})

    sg = StartGenerator(blocks, blmin, volume, cellbounds=cellbounds,
                        splits=splits)

    # Generate 2 candidates
    a1 = sg.get_new_candidate()
    a1.info['confid'] = 1
    a2 = sg.get_new_candidate()
    a2.info['confid'] = 2

    # Define and test genetic operators
    pairing = CutAndSplicePairing(blmin, p1=1., p2=0., minfrac=0.15,
                                  cellbounds=cellbounds, use_tags=True)

    a3, desc = pairing.get_new_individual([a1, a2])
    cell = a3.get_cell()
    assert cellbounds.is_within_bounds(cell)
    assert not atoms_too_close(a3, blmin, use_tags=True)

    n_top = len(a1)
    strainmut = StrainMutation(blmin, stddev=0.7, cellbounds=cellbounds,
                               use_tags=True)
    softmut = SoftMutation(blmin, bounds=[2., 5.], used_modes_file=None,
                           use_tags=True)
    rotmut = RotationalMutation(blmin, fraction=0.3, min_angle=0.5 * np.pi)
    rattlemut = RattleMutation(blmin, n_top, rattle_prop=0.3, rattle_strength=0.5,
                               use_tags=True, test_dist_to_slab=False)
    rattlerotmut = RattleRotationalMutation(rattlemut, rotmut)
    permut = PermutationMutation(n_top, probability=0.33, test_dist_to_slab=False,
                                 use_tags=True, blmin=blmin)
    combmut = CombinationMutation(rattlemut, rotmut, verbose=True)
    mutations = [strainmut, softmut, rotmut,
                 rattlemut, rattlerotmut, permut, combmut]

    for i, mut in enumerate(mutations):
        a = [a1, a2][i % 2]
        a3 = None
        while a3 is None:
            a3, desc = mut.get_new_individual([a])

        cell = a3.get_cell()
        assert cellbounds.is_within_bounds(cell)
        assert np.all(a3.numbers == a.numbers)
        assert not atoms_too_close(a3, blmin, use_tags=True)

    modes_file = 'modes.txt'
    softmut_with = SoftMutation(blmin, bounds=[2., 5.], use_tags=True,
                                used_modes_file=modes_file)
    no_muts = 3
    for _ in range(no_muts):
        softmut_with.get_new_individual([a1])
    softmut_with.read_used_modes(modes_file)
    assert len(list(softmut_with.used_modes.values())[0]) == no_muts
    os.remove(modes_file)

    comparator = OFPComparator(recalculate=True)
    gold = bulk('Au') * (2, 2, 2)
    assert comparator.looks_like(gold, gold)

    # This move should not exceed the default threshold
    gc = gold.copy()
    gc[0].x += .1
    assert comparator.looks_like(gold, gc)

    # An additional step will exceed the threshold
    gc[0].x += .2
    assert not comparator.looks_like(gold, gc)