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

1import math 

2 

3import numpy as np 

4 

5from ase import Atoms 

6from ase.cluster.base import ClusterBase 

7 

8 

9class Cluster(Atoms, ClusterBase): 

10 symmetry = None 

11 surfaces = None 

12 lattice_basis = None 

13 resiproc_basis = None 

14 atomic_basis = None 

15 

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 

24 

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 

31 

32 def get_layers(self): 

33 """Return number of atomic layers in stored surfaces directions.""" 

34 

35 layers = [] 

36 

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) 

43 

44 ls = np.arange(l_ - 1, l_ + 2) 

45 ds = np.array([self.get_layer_distance(s, i) for i in ls]) 

46 

47 mask = (np.abs(ds - r) < 1e-10) 

48 

49 layers.append(ls[mask][0]) 

50 

51 return np.array(layers, int) 

52 

53 def get_diameter(self, method='volume'): 

54 """Returns an estimate of the cluster diameter based on two different 

55 methods. 

56 

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 """ 

64 

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