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
« 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
9class SingleCrystal(BaseParticle):
10 """
11 A `SingleCrystal` object is a Wulff construction of a single
12 crystalline particle, i.e., a standard Wulff construction.
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`.
38 Example
39 -------
40 The following example illustrates some possible uses of a
41 `SingleCrystal` object::
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
52 """
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)
79 @property
80 def atoms(self) -> Atoms:
81 """
82 Returns an ASE Atoms object
83 """
84 return self._get_atoms()
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.
99 Parameters
100 ----------
101 center_shift
102 Shift of center in Cartesian coordinates.
103 """
104 return self._get_atoms(center_shift=center_shift)