コード例 #1
0
def prepare_ga(dbfile='godb.db', N=20):
    ''' This method creates a database with the desired number
    of randomly generated structures.
    '''
    blocks = [('Si', 7)]  # the building blocks
    l = [list(Atoms(block).numbers) * count for block, count in blocks]
    stoichiometry = [int(item) for sublist in l for item in sublist]
    atom_numbers = list(set(stoichiometry))

    # This dictionary will be used to check that the shortest
    # Si-Si distances are above a certain threshold 
    # (here 1.5 Angstrom):
    blmin = {(14, 14): 1.5}

    # This defines the cubic simulation cell:
    slab = Atoms('', positions=np.zeros((0, 3)), cell=[16] * 3)

    # This defines the smaller box in which the 
    # initial coordinates are allowed to vary
    density = 0.12  # in atoms per cubic Angstrom
    aspect_ratios = np.array([1.0, 1.0, 1.0])
    v = len(stoichiometry) / density
    l = np.cbrt(v / np.product(aspect_ratios))
    cell = np.identity(3) * aspect_ratios * l
    p0 = 0.5 * (np.diag(slab.get_cell() - cell))
    box = [p0, cell]

    # Seed the random number generators using the system time,
    # to ensure that no two runs produce the same results:
    np.random.seed()
    seed()

    # Generate the random structures and add them to the database:
    sg = StartGenerator(slab=slab, atom_numbers=stoichiometry,
                        closest_allowed_distances=blmin,
                        box_to_place_in=box)

    da = PrepareDB(db_file_name=dbfile,
                   simulation_cell=slab,
                   stoichiometry=stoichiometry)

    for i in range(N):
        a = sg.get_new_candidate()
        da.add_unrelaxed_candidate(a)

    return
コード例 #2
0
def prepare_ga(dbfile='godb.db', N=20):
    """
    This method creates a database with the desired number
    of randomly generated structures.
    """ 
    Z = atomic_numbers['Si']
    atom_numbers = [Z] * 7

    # This dictionary will be used to check that the shortest
    # Si-Si distances are above a certain threshold 
    # (here 1.5 Angstrom):
    blmin = {(Z, Z): 1.5}  

    # This defines the cubic simulation cell. In case there
    big_cell = np.identity(3) * 16.
    slab = Atoms('', cell=big_cell)

    # This defines the smaller box in which the initial
    # coordinates are allowed to be generated
    density = 0.1  # in atoms per cubic Angstrom
    L = np.cbrt(len(atom_numbers) / density)
    small_cell = np.identity(3) * L
    p0 = 0.5 * np.diag(big_cell - small_cell)
    box = [p0, small_cell]

    # Seed the random number generators using the system time,
    # to ensure that no two runs produce the same results:
    np.random.seed()
    seed()

    # Generate the random structures and add them to the database:
    sg = StartGenerator(slab=slab, atom_numbers=atom_numbers,
                        closest_allowed_distances=blmin,
                        box_to_place_in=box)

    da = PrepareDB(db_file_name=dbfile,
                   simulation_cell=slab,
                   stoichiometry=atom_numbers)

    for i in range(N):
        a = sg.get_new_candidate()
        da.add_unrelaxed_candidate(a)

    return
コード例 #3
0
# (and not intramolecularly):
Z = atomic_numbers['N']
blmin = closest_distances_generator(atom_numbers=[Z],
                                    ratio_of_covalent_radii=1.3)

# The bounds for the randomly generated unit cells:
cellbounds = CellBounds(bounds={'phi': [30, 150], 'chi': [30, 150],
                                'psi': [30, 150], 'a': [3, 50],
                                'b': [3, 50], 'c': [3, 50]})

# The familiar 'slab' object, here only providing
# the PBC as there are no atoms or cell vectors
# that need to be applied.
slab = Atoms('', pbc=True)

# create the starting population
sg = StartGenerator(slab, blocks, blmin, box_volume=box_volume,
                    cellbounds=cellbounds, splits=splits,
                    number_of_variable_cell_vectors=3,
                    test_too_far=False)

# Initialize the database
da = PrepareDB(db_file_name='gadb.db', simulation_cell=slab,
               stoichiometry=[Z] * 16)

# Generate the new structures
# and add them to the database
for i in range(N):
    a = sg.get_new_candidate()
    da.add_unrelaxed_candidate(a)
コード例 #4
0
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.

# Define the composition of the atoms to optimize
atom_numbers = 2 * [47] + 2 * [79]

# define the closest distance two atoms of a given species can be to each other
unique_atom_types = get_all_atom_types(slab, atom_numbers)
blmin = closest_distances_generator(atom_numbers=unique_atom_types,
                                    ratio_of_covalent_radii=0.7)

# create the starting population
sg = StartGenerator(slab,
                    atom_numbers,
                    blmin,
                    box_to_place_in=[p0, [v1, v2, v3]])

# generate the starting population
population_size = 20
starting_population = [sg.get_new_candidate() for i in range(population_size)]

# from ase.visualize import view   # uncomment these lines
# view(starting_population)        # to see the starting population

# create the database to store information in
d = PrepareDB(db_file_name=db_file,
              simulation_cell=slab,
              stoichiometry=atom_numbers)

for a in starting_population:
コード例 #5
0
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.

# Define the composition of the atoms to optimize
atom_numbers = 2 * [47] + 2 * [79]

# define the closest distance two atoms of a given species can be to each other
unique_atom_types = get_all_atom_types(slab, atom_numbers)
cd = closest_distances_generator(atom_numbers=unique_atom_types,
                                 ratio_of_covalent_radii=0.7)

# create the starting population
sg = StartGenerator(slab=slab,
                    atom_numbers=atom_numbers,
                    closest_allowed_distances=cd,
                    box_to_place_in=[p0, [v1, v2, v3]])

# generate the starting population
population_size = 5
starting_population = [sg.get_new_candidate() for i in xrange(population_size)]

# from ase.visualize import view   # uncomment these lines
# view(starting_population)        # to see the starting population

# create the database to store information in
d = PrepareDB(db_file_name=db_file,
              simulation_cell=slab,
              stoichiometry=atom_numbers,)
              # population_size=population_size)
コード例 #6
0
def test_film_operators(seed):
    from ase.ga.startgenerator import StartGenerator
    from ase.ga.cutandsplicepairing import CutAndSplicePairing
    from ase.ga.standardmutations import StrainMutation
    from ase.ga.utilities import (closest_distances_generator, atoms_too_close,
                                  CellBounds)
    import numpy as np
    from ase import Atoms
    from ase.build import molecule

    # set up the random number generator
    rng = np.random.RandomState(seed)

    slab = Atoms('', cell=(0, 0, 15), pbc=[True, True, False])

    cation, anion = 'Mg', molecule('OH')
    d_oh = anion.get_distance(0, 1)
    blocks = [(cation, 4), (anion, 8)]
    n_top = 4 + 8 * len(anion)

    use_tags = True
    num_vcv = 2
    box_volume = 8. * n_top

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

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

    box_to_place_in = [[None, None, 3.], [None, None, [0., 0., 5.]]]

    sg = StartGenerator(slab,
                        blocks,
                        blmin,
                        box_volume=box_volume,
                        splits={(2, 1): 1},
                        box_to_place_in=box_to_place_in,
                        number_of_variable_cell_vectors=num_vcv,
                        cellbounds=cellbounds,
                        test_too_far=True,
                        test_dist_to_slab=False,
                        rng=rng)

    parents = []
    for i in range(2):
        a = None
        while a is None:
            a = sg.get_new_candidate()

        a.info['confid'] = i
        parents.append(a)

        assert len(a) == n_top
        assert len(np.unique(a.get_tags())) == 4 + 8
        assert np.allclose(a.get_pbc(), slab.get_pbc())

        p = a.get_positions()
        assert np.min(p[:, 2]) > 3. - 0.5 * d_oh
        assert np.max(p[:, 2]) < 3. + 5. + 0.5 * d_oh
        assert not atoms_too_close(a, blmin, use_tags=use_tags)

        c = a.get_cell()
        assert np.allclose(c[2], slab.get_cell()[2])
        assert cellbounds.is_within_bounds(c)

        v = a.get_volume() * 5. / 15.
        assert abs(v - box_volume) < 1e-5

    # Test cut-and-splice pairing and strain mutation
    pairing = CutAndSplicePairing(slab,
                                  n_top,
                                  blmin,
                                  number_of_variable_cell_vectors=num_vcv,
                                  p1=1.,
                                  p2=0.,
                                  minfrac=0.15,
                                  cellbounds=cellbounds,
                                  use_tags=use_tags,
                                  rng=rng)

    strainmut = StrainMutation(blmin,
                               cellbounds=cellbounds,
                               number_of_variable_cell_vectors=num_vcv,
                               use_tags=use_tags,
                               rng=rng)
    strainmut.update_scaling_volume(parents)

    for operator in [pairing, strainmut]:
        child = None
        while child is None:
            child, desc = operator.get_new_individual(parents)

        assert not atoms_too_close(child, blmin, use_tags=use_tags)
        cell = child.get_cell()
        assert cellbounds.is_within_bounds(cell)
        assert np.allclose(cell[2], slab.get_cell()[2])
コード例 #7
0
def test_cutandsplicepairing(seed):
    from ase.ga.startgenerator import StartGenerator
    from ase.ga.utilities import closest_distances_generator, atoms_too_close
    from ase.ga.cutandsplicepairing import CutAndSplicePairing
    import numpy as np
    from ase.build import fcc111
    from ase.constraints import FixAtoms

    # set up the random number generator
    rng = np.random.RandomState(seed)

    # first create two random starting candidates
    slab = fcc111('Au', size=(4, 4, 2), vacuum=10.0, orthogonal=True)
    slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.))

    pos = slab.get_positions()
    cell = slab.get_cell()
    p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
    v1 = cell[0, :] * 0.8
    v2 = cell[1, :] * 0.8
    v3 = cell[2, :]
    v3[2] = 3.

    blmin = closest_distances_generator(atom_numbers=[47, 79],
                                        ratio_of_covalent_radii=0.7)

    atom_numbers = 2 * [47] + 2 * [79]

    sg = StartGenerator(slab=slab,
                        blocks=atom_numbers,
                        blmin=blmin,
                        box_to_place_in=[p0, [v1, v2, v3]],
                        rng=rng)

    c1 = sg.get_new_candidate()
    c1.info['confid'] = 1
    c2 = sg.get_new_candidate()
    c2.info['confid'] = 2

    n_top = len(atom_numbers)

    pairing = CutAndSplicePairing(slab, n_top, blmin, rng=rng)

    c3, desc = pairing.get_new_individual([c1, c2])

    # verify that the stoichiometry is preserved
    assert np.all(c3.numbers == c1.numbers)
    top1 = c1[-n_top:]
    top2 = c2[-n_top:]
    top3 = c3[-n_top:]

    # verify that the positions in the new candidate come from c1 or c2
    n1 = -1 * np.ones((n_top, ))
    n2 = -1 * np.ones((n_top, ))
    for i in range(n_top):
        for j in range(n_top):
            if np.allclose(top1.positions[j, :], top3.positions[i, :], 1e-12):
                n1[i] = j
                break
            elif np.allclose(top2.positions[j, :], top3.positions[i, :],
                             1e-12):
                n2[i] = j
                break
        assert (n1[i] > -1 and n2[i] == -1) or (n1[i] == -1 and n2[i] > -1)

    # verify that c3 includes atoms from both c1 and c2
    assert len(n1[n1 > -1]) > 0 and len(n2[n2 > -1]) > 0

    # verify no atoms too close
    assert not atoms_too_close(top3, blmin)
コード例 #8
0
p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.

# define the closest distance between two atoms of a given species
cd = closest_distances_generator(atom_numbers=[47, 79],
                                 ratio_of_covalent_radii=0.7)

# Define the composition of the atoms to optimize
atom_numbers = 2 * [47] + 2 * [79]

# create the starting population
sg = StartGenerator(slab=slab,
                    atom_numbers=atom_numbers,
                    closest_allowed_distances=cd,
                    box_to_place_in=[p0, [v1, v2, v3]])

# generate the starting population
starting_population = [sg.get_new_candidate() for i in range(20)]

d = PrepareDB(db_file_name=db_file,
              simulation_cell=slab,
              stoichiometry=atom_numbers)

for a in starting_population:
    d.add_unrelaxed_candidate(a)

# and now for the actual test
dc = DataConnection(db_file)
コード例 #9
0
def test_mutations(seed):
    from ase.ga.startgenerator import StartGenerator
    from ase.ga.utilities import closest_distances_generator
    from ase.ga.standardmutations import RattleMutation, PermutationMutation
    import numpy as np
    from ase.build import fcc111
    from ase.constraints import FixAtoms

    # set up the random number generator
    rng = np.random.RandomState(seed)

    # first create two random starting candidates
    slab = fcc111('Au', size=(4, 4, 2), vacuum=10.0, orthogonal=True)
    slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.))

    pos = slab.get_positions()
    cell = slab.get_cell()
    p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
    v1 = cell[0, :] * 0.8
    v2 = cell[1, :] * 0.8
    v3 = cell[2, :]
    v3[2] = 3.

    blmin = closest_distances_generator(atom_numbers=[47, 79],
                                        ratio_of_covalent_radii=0.7)

    atom_numbers = 2 * [47] + 2 * [79]
    n_top = len(atom_numbers)
    sg = StartGenerator(slab=slab,
                        blocks=atom_numbers,
                        blmin=blmin,
                        box_to_place_in=[p0, [v1, v2, v3]],
                        rng=rng)

    c1 = sg.get_new_candidate()
    c1.info['confid'] = 1

    # first verify that the rattle mutation works
    rmut = RattleMutation(blmin, n_top, rattle_strength=0.8, rattle_prop=0.4,
                          rng=rng)

    c2, desc = rmut.get_new_individual([c1])

    assert np.all(c1.numbers == c2.numbers)

    top1 = c1[-n_top:]
    top2 = c2[-n_top:]
    slab2 = c2[0:(len(c1) - n_top)]

    assert len(slab) == len(slab2)
    assert np.all(slab.get_positions() == slab2.get_positions())

    dp = np.sum((top2.get_positions() - top1.get_positions())**2, axis=1)**0.5

    # check that all displacements are smaller than the rattle strength we
    # cannot check if 40 % of the structures have been rattled since it is
    # probabilistic and because the probability will be lower if two atoms
    # get too close
    for p in dp:
        assert p < 0.8 * 3**0.5

    # now we check the permutation mutation

    mmut = PermutationMutation(n_top, probability=0.5, rng=rng)

    c3, desc = mmut.get_new_individual([c1])
    assert np.all(c1.numbers == c3.numbers)

    top1 = c1[-n_top:]
    top2 = c3[-n_top:]
    slab2 = c3[0:(len(c1) - n_top)]

    assert len(slab) == len(slab2)
    assert np.all(slab.get_positions() == slab2.get_positions())
    dp = np.sum((top2.get_positions() - top1.get_positions())**2, axis=1)**0.5

    # verify that two positions have been changed
    assert len(dp[dp > 0]) == 2
コード例 #10
0
ファイル: cutandsplicepairing.py プロジェクト: jboes/ase
slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.0))

pos = slab.get_positions()
cell = slab.get_cell()
p0 = np.array([0.0, 0.0, max(pos[:, 2]) + 2.0])
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.0

cd = closest_distances_generator(atom_numbers=[47, 79], ratio_of_covalent_radii=0.7)

atom_numbers = 2 * [47] + 2 * [79]

sg = StartGenerator(
    slab=slab, atom_numbers=atom_numbers, closest_allowed_distances=cd, box_to_place_in=[p0, [v1, v2, v3]]
)

c1 = sg.get_new_candidate()
c1.info["confid"] = 1
c2 = sg.get_new_candidate()
c2.info["confid"] = 2

n_top = len(atom_numbers)

pairing = CutAndSplicePairing(slab, n_top, cd)

c3, desc = pairing.get_new_individual([c1, c2])

# verify that the stoichiometry is preserved
assert np.all(c3.numbers == c1.numbers)
コード例 #11
0
# controls the level of translational symmetry (within the unit
# cell) of the randomly generated structures. Here a 1:1 ratio
# of splitting factors 2 and 1 is used:
splits = {(2,): 1, (1,): 1}
# There will hence be a 50% probability that a candidate
# is constructed by repeating an randomly generated Ag12
# structure along a randomly chosen axis. In the other 50%
# of cases, no cell cell splitting will be applied.

# The 'slab' object in the GA serves as a template
# in the creation of new structures, which inherit
# the slab's atomic positions (if any), cell vectors
# (if specified), and periodic boundary conditions.
# Here only the last property is relevant:
slab = Atoms('', pbc=True)

# Initialize the random structure generator
sg = StartGenerator(slab, blocks, blmin, box_volume=volume,
                    number_of_variable_cell_vectors=3,
                    cellbounds=cellbounds, splits=splits)

# Create the database
da = PrepareDB(db_file_name='gadb.db',
               stoichiometry=[Z] * 24)

# Generate N random structures
# and add them to the database
for i in range(N):
    a = sg.get_new_candidate()
    da.add_unrelaxed_candidate(a)
コード例 #12
0
pos = slab.get_positions()
cell = slab.get_cell()
p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
v1 = cell[0, :] * 0.8
v2 = cell[1, :] * 0.8
v3 = cell[2, :]
v3[2] = 3.

cd = closest_distances_generator(atom_numbers=[47, 79],
                                 ratio_of_covalent_radii=0.7)

atom_numbers = 2 * [47] + 2 * [79]

sg = StartGenerator(slab=slab,
                    atom_numbers=atom_numbers,
                    closest_allowed_distances=cd,
                    box_to_place_in=[p0, [v1, v2, v3]])

c1 = sg.get_new_candidate()
c1.info['confid'] = 1
c2 = sg.get_new_candidate()
c2.info['confid'] = 2

n_top = len(atom_numbers)

pairing = CutAndSplicePairing(slab, n_top, cd)

c3, desc = pairing.get_new_individual([c1, c2])

# verify that the stoichiometry is preserved
assert np.all(c3.numbers == c1.numbers)
コード例 #13
0
def test_basic_example_main_run(seed, testdir):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    # create the surface
    slab = fcc111('Au', size=(4, 4, 1), vacuum=10.0, orthogonal=True)
    slab.set_constraint(FixAtoms(mask=len(slab) * [True]))

    # define the volume in which the adsorbed cluster is optimized
    # the volume is defined by a corner position (p0)
    # and three spanning vectors (v1, v2, v3)
    pos = slab.get_positions()
    cell = slab.get_cell()
    p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
    v1 = cell[0, :] * 0.8
    v2 = cell[1, :] * 0.8
    v3 = cell[2, :]
    v3[2] = 3.

    # Define the composition of the atoms to optimize
    atom_numbers = 2 * [47] + 2 * [79]

    # define the closest distance two atoms of a given species can be to each other
    unique_atom_types = get_all_atom_types(slab, atom_numbers)
    blmin = closest_distances_generator(atom_numbers=unique_atom_types,
                                        ratio_of_covalent_radii=0.7)

    # create the starting population
    sg = StartGenerator(slab=slab,
                        blocks=atom_numbers,
                        blmin=blmin,
                        box_to_place_in=[p0, [v1, v2, v3]],
                        rng=rng)

    # generate the starting population
    population_size = 5
    starting_population = [sg.get_new_candidate() for i in range(population_size)]

    # from ase.visualize import view   # uncomment these lines
    # view(starting_population)        # to see the starting population

    # create the database to store information in
    d = PrepareDB(db_file_name=db_file,
                  simulation_cell=slab,
                  stoichiometry=atom_numbers)

    for a in starting_population:
        d.add_unrelaxed_candidate(a)

    # XXXXXXXXXX This should be the beginning of a new test,
    # but we are using some resources from the precious part.
    # Maybe refactor those things as (module-level?) fixtures.

    # Change the following three parameters to suit your needs
    population_size = 5
    mutation_probability = 0.3
    n_to_test = 5

    # Initialize the different components of the GA
    da = DataConnection('gadb.db')
    atom_numbers_to_optimize = da.get_atom_numbers_to_optimize()
    n_to_optimize = len(atom_numbers_to_optimize)
    slab = da.get_slab()
    all_atom_types = get_all_atom_types(slab, atom_numbers_to_optimize)
    blmin = closest_distances_generator(all_atom_types,
                                        ratio_of_covalent_radii=0.7)

    comp = InteratomicDistanceComparator(n_top=n_to_optimize,
                                         pair_cor_cum_diff=0.015,
                                         pair_cor_max=0.7,
                                         dE=0.02,
                                         mic=False)

    pairing = CutAndSplicePairing(slab, n_to_optimize, blmin, rng=rng)
    mutations = OperationSelector([1., 1., 1.],
                            [MirrorMutation(blmin, n_to_optimize, rng=rng),
                             RattleMutation(blmin, n_to_optimize, rng=rng),
                             PermutationMutation(n_to_optimize, rng=rng)],
                             rng=rng)

    # Relax all unrelaxed structures (e.g. the starting population)
    while da.get_number_of_unrelaxed_candidates() > 0:
        a = da.get_an_unrelaxed_candidate()
        a.calc = EMT()
        print('Relaxing starting candidate {0}'.format(a.info['confid']))
        dyn = BFGS(a, trajectory=None, logfile=None)
        dyn.run(fmax=0.05, steps=100)
        set_raw_score(a, -a.get_potential_energy())
        da.add_relaxed_step(a)

    # create the population
    population = Population(data_connection=da,
                            population_size=population_size,
                            comparator=comp,
                            rng=rng)

    # test n_to_test new candidates
    for i in range(n_to_test):
        print('Now starting configuration number {0}'.format(i))
        a1, a2 = population.get_two_candidates()
        a3, desc = pairing.get_new_individual([a1, a2])
        if a3 is None:
            continue
        da.add_unrelaxed_candidate(a3, description=desc)

        # Check if we want to do a mutation
        if rng.rand() < mutation_probability:
            a3_mut, desc = mutations.get_new_individual([a3])
            if a3_mut is not None:
                da.add_unrelaxed_step(a3_mut, desc)
                a3 = a3_mut

        # Relax the new candidate
        a3.calc = EMT()
        dyn = BFGS(a3, trajectory=None, logfile=None)
        dyn.run(fmax=0.05, steps=100)
        set_raw_score(a3, -a3.get_potential_energy())
        da.add_relaxed_step(a3)
        population.update()

    write('all_candidates.traj', da.get_all_relaxed_candidates())
コード例 #14
0
def test_chain_operators(seed):
    from ase.ga.startgenerator import StartGenerator
    from ase.ga.cutandsplicepairing import CutAndSplicePairing
    from ase.ga.standardmutations import StrainMutation
    from ase.ga.utilities import (closest_distances_generator, atoms_too_close,
                                  CellBounds)
    import numpy as np
    from ase import Atoms

    # set up the random number generator
    rng = np.random.RandomState(seed)

    slab = Atoms('', cell=(0, 16, 16), pbc=[True, False, False])
    blocks = ['C'] * 8
    n_top = 8

    use_tags = False
    num_vcv = 1
    box_volume = 8. * n_top

    blmin = closest_distances_generator(atom_numbers=[6],
                                        ratio_of_covalent_radii=0.6)

    cellbounds = CellBounds(
        bounds={
            'phi': [0.1 * 180., 0.9 * 180.],
            'chi': [0.1 * 180., 0.9 * 180.],
            'psi': [0.1 * 180., 0.9 * 180.],
            'a': [1, 6]
        })

    box_to_place_in = [[None, 6., 6.], [None, [0., 4., 0.], [0., 0., 4.]]]

    sg = StartGenerator(slab,
                        blocks,
                        blmin,
                        box_volume=box_volume,
                        splits=None,
                        box_to_place_in=box_to_place_in,
                        number_of_variable_cell_vectors=num_vcv,
                        cellbounds=cellbounds,
                        test_too_far=True,
                        test_dist_to_slab=False,
                        rng=rng)

    parents = []
    for i in range(2):
        a = None
        while a is None:
            a = sg.get_new_candidate()

        a.info['confid'] = i
        parents.append(a)

        assert len(a) == n_top
        assert len(np.unique(a.get_tags())) == 8
        assert np.allclose(a.get_pbc(), slab.get_pbc())

        p = a.get_positions()
        assert np.min(p[:, 1:]) > 6.
        assert np.max(p[:, 1:]) < 6. + 4.
        assert not atoms_too_close(a, blmin, use_tags=use_tags)

        c = a.get_cell()
        assert np.allclose(c[1:], slab.get_cell()[1:])
        assert cellbounds.is_within_bounds(c)

        v = a.get_volume() * (4. / 16.)**2
        assert abs(v - box_volume) < 1e-5

    # Test cut-and-splice pairing and strain mutation
    pairing = CutAndSplicePairing(slab,
                                  n_top,
                                  blmin,
                                  number_of_variable_cell_vectors=num_vcv,
                                  p1=1.,
                                  p2=0.,
                                  minfrac=0.15,
                                  cellbounds=cellbounds,
                                  use_tags=use_tags,
                                  rng=rng)

    strainmut = StrainMutation(blmin,
                               cellbounds=cellbounds,
                               number_of_variable_cell_vectors=num_vcv,
                               use_tags=use_tags,
                               rng=rng)
    strainmut.update_scaling_volume(parents)

    for operator in [pairing, strainmut]:
        child = None
        while child is None:
            child, desc = operator.get_new_individual(parents)

        assert not atoms_too_close(child, blmin, use_tags=use_tags)
        cell = child.get_cell()
        assert cellbounds.is_within_bounds(cell)
        assert np.allclose(cell[1:], slab.get_cell()[1:])
コード例 #15
0
    c = slab.get_cell()
    v1 = np.array((c[0][0], 0., 0.))
    v2 = np.array((0., c[1][1], 0.))
    v3 = np.array((0., 0., 6.))
    p0 = np.array((0., 0., 8.))
    box = [p0, [v1, v2, v3]]
    stoichiometry = 5 * [22] + 10 * [8]

    print 'slab', buildFeature(slab, 6, [8, 22])

    dmin = closest_distances_generator(atom_numbers=[22, 8],
                                       ratio_of_covalent_radii=0.6)

    sg = StartGenerator(
        slab=slab,  # Generator to generate initial structures
        atom_numbers=stoichiometry,
        closest_allowed_distances=dmin,
        box_to_place_in=box)

    calc = MorsePotential()
    test = sg.get_new_candidate()
    test.set_calculator(calc)
    test.info['confid'] = 1
    view(test)
    cd = ClusterDistanceMutation(slab,
                                 len(stoichiometry),
                                 dmin,
                                 5,
                                 1,
                                 verbose=True)
コード例 #16
0
def test_database_logic(seed, testdir):
    from ase.ga.data import PrepareDB
    from ase.ga.data import DataConnection
    from ase.ga.startgenerator import StartGenerator
    from ase.ga.utilities import closest_distances_generator
    from ase.ga import set_raw_score
    import numpy as np
    from ase.build import fcc111
    from ase.constraints import FixAtoms

    # set up the random number generator
    rng = np.random.RandomState(seed)

    slab = fcc111('Au', size=(4, 4, 2), vacuum=10.0, orthogonal=True)
    slab.set_constraint(FixAtoms(mask=slab.positions[:, 2] <= 10.))

    # define the volume in which the adsorbed cluster is optimized
    # the volume is defined by a corner position (p0)
    # and three spanning vectors (v1, v2, v3)
    pos = slab.get_positions()
    cell = slab.get_cell()
    p0 = np.array([0., 0., max(pos[:, 2]) + 2.])
    v1 = cell[0, :] * 0.8
    v2 = cell[1, :] * 0.8
    v3 = cell[2, :]
    v3[2] = 3.

    # define the closest distance between two atoms of a given species
    blmin = closest_distances_generator(atom_numbers=[47, 79],
                                        ratio_of_covalent_radii=0.7)

    # Define the composition of the atoms to optimize
    atom_numbers = 2 * [47] + 2 * [79]

    # create the starting population
    sg = StartGenerator(slab=slab,
                        blocks=atom_numbers,
                        blmin=blmin,
                        box_to_place_in=[p0, [v1, v2, v3]],
                        rng=rng)

    # generate the starting population
    starting_population = [sg.get_new_candidate() for i in range(20)]

    d = PrepareDB(db_file_name=db_file,
                  simulation_cell=slab,
                  stoichiometry=atom_numbers)

    for a in starting_population:
        d.add_unrelaxed_candidate(a)

    # and now for the actual test
    dc = DataConnection(db_file)

    dc.get_slab()
    dc.get_atom_numbers_to_optimize()

    assert dc.get_number_of_unrelaxed_candidates() == 20

    a1 = dc.get_an_unrelaxed_candidate()
    dc.mark_as_queued(a1)

    assert dc.get_number_of_unrelaxed_candidates() == 19
    assert len(dc.get_all_candidates_in_queue()) == 1

    set_raw_score(a1, 0.0)
    dc.add_relaxed_step(a1)

    assert dc.get_number_of_unrelaxed_candidates() == 19
    assert len(dc.get_all_candidates_in_queue()) == 0

    assert len(dc.get_all_relaxed_candidates()) == 1

    a2 = dc.get_an_unrelaxed_candidate()
    dc.mark_as_queued(a2)
    confid = a2.info['confid']
    assert dc.get_all_candidates_in_queue()[0] == confid

    dc.remove_from_queue(confid)
    assert len(dc.get_all_candidates_in_queue()) == 0
コード例 #17
0
def test_bulk_operators(seed):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    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]})

    slab = Atoms('', pbc=True)
    sg = StartGenerator(slab, blocks, blmin, box_volume=volume,
                        number_of_variable_cell_vectors=3,
                        cellbounds=cellbounds, splits=splits, rng=rng)

    # 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
    n_top = len(a1)
    pairing = CutAndSplicePairing(slab, n_top, blmin, p1=1., p2=0., minfrac=0.15,
                                  number_of_variable_cell_vectors=3,
                                  cellbounds=cellbounds, use_tags=True, rng=rng)

    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,
                               number_of_variable_cell_vectors=3,
                               use_tags=True, rng=rng)
    softmut = SoftMutation(blmin, bounds=[2., 5.], used_modes_file=None,
                           use_tags=True)  # no rng
    rotmut = RotationalMutation(blmin, fraction=0.3, min_angle=0.5 * np.pi,
                                rng=rng)
    rattlemut = RattleMutation(blmin, n_top, rattle_prop=0.3, rattle_strength=0.5,
                               use_tags=True, test_dist_to_slab=False, rng=rng)
    rattlerotmut = RattleRotationalMutation(rattlemut, rotmut)  # no rng
    permut = PermutationMutation(n_top, probability=0.33, test_dist_to_slab=False,
                                 use_tags=True, blmin=blmin, rng=rng)
    combmut = CombinationMutation(rattlemut, rotmut, verbose=True)  # no rng
    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 rng
    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)