File: test_slab_operators.py

package info (click to toggle)
python-ase 3.26.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,484 kB
  • sloc: python: 148,112; xml: 2,728; makefile: 110; javascript: 47
file content (104 lines) | stat: -rw-r--r-- 2,931 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# fmt: off
import numpy as np
import pytest

from ase.build import fcc111
from ase.ga.slab_operators import (
    CutSpliceSlabCrossover,
    NeighborhoodElementMutation,
    RandomCompositionMutation,
    RandomElementMutation,
    RandomSlabPermutation,
)


@pytest.fixture()
def cu_slab():
    a = 1
    size = (2, 4, 3)
    p1 = fcc111('Cu', size, orthogonal=True, a=a)
    p1.info['confid'] = 1
    return p1


def test_cut_splice(seed, cu_slab):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    ratio = .4
    op = CutSpliceSlabCrossover(min_ratio=ratio, rng=rng)
    p1 = cu_slab
    natoms = len(p1)

    p2 = cu_slab.copy()
    p2.symbols = ['Au'] * natoms

    p2.info['confid'] = 2
    child, desc = op.get_new_individual([p1, p2])
    assert desc == 'CutSpliceSlabCrossover: Parents 1 2'

    # Check the ratio of elements
    syms = child.get_chemical_symbols()
    new_ratio = syms.count('Au') / natoms
    assert new_ratio > ratio and new_ratio < 1 - ratio

    op = CutSpliceSlabCrossover(element_pools=['Cu', 'Au'],
                                allowed_compositions=[(12, 12)], rng=rng)
    child = op.operate(p1, p2)
    assert child.get_chemical_symbols().count('Au') == 12


def test_random_composition_mutation(seed, cu_slab):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    p1 = cu_slab
    p1.symbols[3] = 'Au'
    op = RandomCompositionMutation(element_pools=['Cu', 'Au'],
                                   allowed_compositions=[(12, 12), (18, 6)],
                                   rng=rng)
    child, _ = op.get_new_individual([p1])
    no_Au = (child.symbols == 'Au').sum()
    assert no_Au in [6, 12]

    op = RandomCompositionMutation(element_pools=['Cu', 'Au'], rng=rng)
    child2 = op.operate(child)
    # Make sure we have gotten a new stoichiometry
    assert (child2.symbols == 'Au').sum() != no_Au


def test_random_element_mutation(seed, cu_slab):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    op = RandomElementMutation(element_pools=[['Cu', 'Au']], rng=rng)

    child, _desc = op.get_new_individual([cu_slab.copy()])

    assert (child.symbols == 'Au').sum() == 24


def test_neighborhood_element_mutation(seed, cu_slab):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    op = NeighborhoodElementMutation(element_pools=[['Cu', 'Ni', 'Au']],
                                     rng=rng)

    child, _desc = op.get_new_individual([cu_slab])

    assert (child.symbols == 'Ni').sum() == 24


def test_random_permutation(seed, cu_slab):
    # set up the random number generator
    rng = np.random.RandomState(seed)

    p1 = cu_slab
    p1.symbols[:8] = 'Au'

    op = RandomSlabPermutation(rng=rng)
    child, _desc = op.get_new_individual([p1])

    assert (child.symbols == 'Au').sum() == 8
    assert sum(p1.numbers == child.numbers) == 22