Coverage for wulffpack/single_crystal.py: 100%

21 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-02 08:51 +0000

1from typing import Tuple, List 

2from ase import Atoms 

3import numpy as np 

4from .core import BaseParticle 

5from .core.geometry import get_symmetries, get_standardized_structure 

6from .core.form import setup_forms 

7 

8 

9class SingleCrystal(BaseParticle): 

10 """ 

11 A `SingleCrystal` object is a Wulff construction of a single 

12 crystalline particle, i.e., a standard Wulff construction. 

13 

14 Parameters 

15 ---------- 

16 surface_energies 

17 A dictionary with surface energies, where keys are 

18 Miller indices and values surface energies (per area) 

19 in a unit of choice, such as J/m^2. 

20 primitive_structure 

21 primitive cell to implicitly define the point group as 

22 well as the atomic structure used if an atomic structure 

23 is requested. By default, an Au FCC structure is used. 

24 natoms 

25 Together with `primitive_structure`, this parameter 

26 defines the volume of the particle. If an atomic structure 

27 is requested, the number of atoms will as closely as possible 

28 match this value. 

29 symprec 

30 Numerical tolerance for symmetry analysis, forwarded to spglib. 

31 tol 

32 Numerical tolerance parameter. 

33 symmetry_operations 

34 This parameter allows one to pass an explicit list of allowed 

35 symmetry operations. By default (``None``) the allowed symmetry 

36 operations are obtained from :attr:`primitive_structure`. 

37 

38 Example 

39 ------- 

40 The following example illustrates some possible uses of a 

41 `SingleCrystal` object:: 

42 

43 >>> from wulffpack import SingleCrystal 

44 >>> from ase.build import bulk 

45 >>> from ase.io import write 

46 >>> surface_energies = {(1, 1, 0): 1.0, (1, 0, 0): 1.08} 

47 >>> prim = bulk('W', a=3.16, crystalstructure='bcc') 

48 >>> particle = SingleCrystal(surface_energies, prim) 

49 >>> particle.view() 

50 >>> write('single_crystal.xyz', particle.atoms) # Writes atomic structure to file 

51 

52 """ 

53 

54 def __init__( 

55 self, 

56 surface_energies: dict, 

57 primitive_structure: Atoms = None, 

58 natoms: int = 1000, 

59 symprec: float = 1e-5, 

60 tol: float = 1e-5, 

61 symmetry_operations: List[np.ndarray] = None, 

62 ): 

63 standardized_structure = get_standardized_structure(primitive_structure, symprec=symprec) 

64 if symmetry_operations is None: 

65 symmetries = get_symmetries(standardized_structure, symprec=symprec) 

66 else: 

67 if len(symmetry_operations) == 0: 

68 raise ValueError('You need to provide at least one symmetry operation.') 

69 symmetries = symmetry_operations 

70 forms = setup_forms(surface_energies, 

71 standardized_structure.cell.T, 

72 symmetries, 

73 symmetries) 

74 super().__init__(forms=forms, 

75 standardized_structure=standardized_structure, 

76 natoms=natoms, 

77 tol=tol) 

78 

79 @property 

80 def atoms(self) -> Atoms: 

81 """ 

82 Returns an ASE Atoms object 

83 """ 

84 return self._get_atoms() 

85 

86 def get_shifted_atoms( 

87 self, 

88 center_shift: Tuple[float, float, float] = None, 

89 ) -> Atoms: 

90 """ 

91 Returns an ASE Atoms object where the center has been shifted 

92 from with respect to the standardized cells. This can, for 

93 example, allow creation of atomistic representations in which 

94 the center of the nanoparticle does not coincide with an atom. 

95 Thereby the space of possible atomistic representations increases 

96 and may make the returned number of atoms closer to the requested 

97 number. 

98 

99 Parameters 

100 ---------- 

101 center_shift 

102 Shift of center in Cartesian coordinates. 

103 """ 

104 return self._get_atoms(center_shift=center_shift)