• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

materialsproject / pymatgen / 4075885785

pending completion
4075885785

push

github

Shyue Ping Ong
Merge branch 'master' of github.com:materialsproject/pymatgen

96 of 96 new or added lines in 27 files covered. (100.0%)

81013 of 102710 relevant lines covered (78.88%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.0
/pymatgen/analysis/tests/test_wulff.py
1
from __future__ import annotations
1✔
2

3
import json
1✔
4
import os
1✔
5
import unittest
1✔
6

7
from pytest import approx
1✔
8

9
from pymatgen.analysis.wulff import WulffShape
1✔
10
from pymatgen.core.lattice import Lattice
1✔
11
from pymatgen.core.structure import Structure
1✔
12
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
1✔
13
from pymatgen.util.coord import in_coord_list
1✔
14
from pymatgen.util.testing import PymatgenTest
1✔
15

16
__author__ = "Zihan Xu, Richard Tran, Balachandran Radhakrishnan"
1✔
17
__copyright__ = "Copyright 2013, The Materials Virtual Lab"
1✔
18
__version__ = "0.1"
1✔
19
__maintainer__ = "Zihan Xu"
1✔
20
__email__ = "zix009@eng.ucsd.edu"
1✔
21
__date__ = "May 05 2016"
1✔
22

23

24
class WulffShapeTest(PymatgenTest):
1✔
25
    def setUp(self):
1✔
26
        module_dir = os.path.dirname(os.path.abspath(__file__))
1✔
27
        with open(os.path.join(module_dir, "surface_samples.json")) as data_file:
1✔
28
            surface_properties = json.load(data_file)
1✔
29

30
        surface_energies, miller_indices = {}, {}
1✔
31
        for mpid in surface_properties:
1✔
32
            e_surf_list, miller_list = [], []
1✔
33
            for surface in surface_properties[mpid]["surfaces"]:
1✔
34
                e_surf_list.append(surface["surface_energy"])
1✔
35
                miller_list.append(surface["miller_index"])
1✔
36
            surface_energies[mpid] = e_surf_list
1✔
37
            miller_indices[mpid] = miller_list
1✔
38

39
        # In the case of a high anisotropy material
40
        # Nb: mp-8636
41
        latt_Nb = Lattice.cubic(2.992)
1✔
42
        # In the case of an fcc material
43
        # Ir: mp-101
44
        latt_Ir = Lattice.cubic(3.8312)
1✔
45
        # In the case of a hcp material
46
        # Ti: mp-72
47
        latt_Ti = Lattice.hexagonal(4.6000, 2.8200)
1✔
48
        self.ucell_Nb = Structure(
1✔
49
            latt_Nb,
50
            ["Nb", "Nb", "Nb", "Nb"],
51
            [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]],
52
        )
53
        self.wulff_Nb = WulffShape(latt_Nb, miller_indices["mp-8636"], surface_energies["mp-8636"])
1✔
54

55
        self.ucell_Ir = Structure(
1✔
56
            latt_Nb,
57
            ["Ir", "Ir", "Ir", "Ir"],
58
            [[0, 0, 0], [0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]],
59
        )
60
        self.wulff_Ir = WulffShape(latt_Ir, miller_indices["mp-101"], surface_energies["mp-101"])
1✔
61

62
        self.ucell_Ti = Structure(
1✔
63
            latt_Ti,
64
            ["Ti", "Ti", "Ti"],
65
            [[0, 0, 0], [0.333333, 0.666667, 0.5], [0.666667, 0.333333, 0.5]],
66
        )
67
        self.wulff_Ti = WulffShape(latt_Ti, miller_indices["mp-72"], surface_energies["mp-72"])
1✔
68
        self.cube = WulffShape(Lattice.cubic(1), [(1, 0, 0)], [1])
1✔
69
        self.hex_prism = WulffShape(Lattice.hexagonal(2.63, 5.21), [(0, 0, 1), (1, 0, 0)], [0.35, 0.53])
1✔
70

71
        self.surface_properties = surface_properties
1✔
72

73
    @unittest.skipIf("DISPLAY" not in os.environ, "Need display")
1✔
74
    def test_get_plot(self):
1✔
75
        # Basic test, not really a unittest.
76
        self.wulff_Ti.get_plot()
×
77
        self.wulff_Nb.get_plot()
×
78
        self.wulff_Ir.get_plot()
×
79

80
    @unittest.skipIf("DISPLAY" not in os.environ, "Need display")
1✔
81
    def test_get_plotly(self):
1✔
82
        # Basic test, not really a unittest.
83
        self.wulff_Ti.get_plotly()
×
84
        self.wulff_Nb.get_plotly()
×
85
        self.wulff_Ir.get_plotly()
×
86

87
    def symm_check(self, ucell, wulff_vertices):
1✔
88
        """
89
        # Checks if the point group of the Wulff shape matches
90
        # the point group of its conventional unit cell
91

92
        Args:
93
            ucell (str): Unit cell that the Wulff shape is based on.
94
            wulff_vertices (list): List of all vertices on the Wulff
95
                shape. Use wulff.wulff_pt_list to obtain the list
96
                (see wulff_generator.py).
97

98
        return (bool)
99
        """
100
        space_group_analyzer = SpacegroupAnalyzer(ucell)
×
101
        symm_ops = space_group_analyzer.get_point_group_operations(cartesian=True)
×
102
        for point in wulff_vertices:
×
103
            for op in symm_ops:
×
104
                symm_point = op.operate(point)
×
105
                if in_coord_list(wulff_vertices, symm_point):
×
106
                    continue
×
107
                else:
108
                    return False
×
109
        return True
×
110

111
    def consistency_tests(self):
1✔
112
        # For a set of given values, these tests will
113
        # ensure that the general result given by the
114
        # algorithm does not change as the code is edited
115

116
        # For fcc Ir, make sure the (111) direction
117
        # is the most dominant facet on the Wulff shape
118

119
        fractional_areas = self.wulff_Ir.area_fraction_dict
×
120
        miller_list = [hkl for hkl in fractional_areas]
×
121
        area_list = [fractional_areas[hkl] for hkl in fractional_areas]
×
122
        assert miller_list[area_list.index(max(area_list))] == (1, 1, 1)
×
123

124
        # Overall weighted surface energy of fcc Nb should be
125
        # equal to the energy of the (310) surface, ie. fcc Nb
126
        # is anisotropic, the (310) surface is so low in energy,
127
        # its the only facet that exists in the Wulff shape
128

129
        Nb_area_fraction_dict = self.wulff_Nb.area_fraction_dict
×
130
        for hkl in Nb_area_fraction_dict:
×
131
            if hkl == (3, 1, 0):
×
132
                assert Nb_area_fraction_dict[hkl] == 1
×
133
            else:
134
                assert Nb_area_fraction_dict[hkl] == 0
×
135

136
        assert self.wulff_Nb.miller_energy_dict[(3, 1, 0)] == self.wulff_Nb.weighted_surface_energy
×
137

138
    def symmetry_test(self):
1✔
139
        # Maintains that all wulff shapes have the same point
140
        # groups as the conventional unit cell they were
141
        # derived from. This test should pass for all subsequent
142
        # updates of the surface_properties collection
143

144
        check_symmetry_Nb = self.symm_check(self.ucell_Nb, self.wulff_Nb.wulff_pt_list)
×
145
        check_symmetry_Ir = self.symm_check(self.ucell_Ir, self.wulff_Ir.wulff_pt_list)
×
146
        check_symmetry_Ti = self.symm_check(self.ucell_Ti, self.wulff_Ti.wulff_pt_list)
×
147
        assert check_symmetry_Nb
×
148
        assert check_symmetry_Ir
×
149
        assert check_symmetry_Ti
×
150

151
    def test_get_azimuth_elev(self):
1✔
152
        # Test out the viewing of the Wulff shape from Miller indices.
153
        azim, elev = self.wulff_Ir._get_azimuth_elev((0, 0, 1))
1✔
154
        assert azim == 0
1✔
155
        assert elev == 90
1✔
156
        azim, elev = self.wulff_Ir._get_azimuth_elev((1, 1, 1))
1✔
157
        assert azim == approx(45)
1✔
158

159
    def test_properties(self):
1✔
160
        # Simple test to check if the values of some
161
        # properties are consistent with what we already have
162

163
        wulff_shapes = {
1✔
164
            "mp-8636": self.wulff_Nb,
165
            "mp-72": self.wulff_Ti,
166
            "mp-101": self.wulff_Ir,
167
        }
168
        for mp_id, wulff in wulff_shapes.items():
1✔
169
            properties = self.surface_properties[mp_id]
1✔
170
            assert round(wulff.weighted_surface_energy, 3) == round(properties["weighted_surface_energy"], 3)
1✔
171
            assert round(wulff.shape_factor, 3) == round(properties["shape_factor"], 3)
1✔
172
            assert round(wulff.anisotropy, 3) == round(properties["surface_anisotropy"], 3)
1✔
173

174
    def test_corner_and_edges(self):
1✔
175
        # Test if it is returning the correct number of corner and edges
176
        self.assertArrayEqual(self.cube.tot_corner_sites, 8)
1✔
177
        self.assertArrayEqual(self.cube.tot_edges, 12)
1✔
178
        self.assertArrayEqual(self.hex_prism.tot_corner_sites, 12)
1✔
179
        self.assertArrayEqual(self.hex_prism.tot_edges, 18)
1✔
180

181

182
if __name__ == "__main__":
1✔
183
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc