Coverage for /builds/kinetik161/ase/ase/cluster/cluster.py: 41.18%
51 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-12-10 11:04 +0000
1import math
3import numpy as np
5from ase import Atoms
6from ase.cluster.base import ClusterBase
9class Cluster(Atoms, ClusterBase):
10 symmetry = None
11 surfaces = None
12 lattice_basis = None
13 resiproc_basis = None
14 atomic_basis = None
16 def copy(self):
17 cluster = Atoms.copy(self)
18 cluster.symmetry = self.symmetry
19 cluster.surfaces = self.surfaces.copy()
20 cluster.lattice_basis = self.lattice_basis.copy()
21 cluster.atomic_basis = self.atomic_basis.copy()
22 cluster.resiproc_basis = self.resiproc_basis.copy()
23 return cluster
25 def get_surfaces(self):
26 """Returns the miller indexs of the stored surfaces of the cluster."""
27 if self.surfaces is not None:
28 return self.surfaces.copy()
29 else:
30 return None
32 def get_layers(self):
33 """Return number of atomic layers in stored surfaces directions."""
35 layers = []
37 for s in self.surfaces:
38 n = self.miller_to_direction(s)
39 c = self.get_positions().mean(axis=0)
40 r = np.dot(self.get_positions() - c, n).max()
41 d = self.get_layer_distance(s, 2)
42 l_ = 2 * np.round(r / d).astype(int)
44 ls = np.arange(l_ - 1, l_ + 2)
45 ds = np.array([self.get_layer_distance(s, i) for i in ls])
47 mask = (np.abs(ds - r) < 1e-10)
49 layers.append(ls[mask][0])
51 return np.array(layers, int)
53 def get_diameter(self, method='volume'):
54 """Returns an estimate of the cluster diameter based on two different
55 methods.
57 Parameters
58 ----------
59 method : {'volume', 'shape'}
60 'volume' (default) returns the diameter of a sphere with the same
61 volume as the atoms. 'shape' returns the averaged diameter
62 calculated from the directions given by the defined surfaces.
63 """
65 if method == 'shape':
66 cen = self.get_positions().mean(axis=0)
67 pos = self.get_positions() - cen
68 d = 0.0
69 for s in self.surfaces:
70 n = self.miller_to_direction(s)
71 r = np.dot(pos, n)
72 d += r.max() - r.min()
73 return d / len(self.surfaces)
74 elif method == 'volume':
75 V_cell = np.abs(np.linalg.det(self.lattice_basis))
76 N_cell = len(self.atomic_basis)
77 N = len(self)
78 return 2.0 * (3.0 * N * V_cell /
79 (4.0 * math.pi * N_cell)) ** (1.0 / 3.0)
80 else:
81 return 0.0