Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2This module provides the ClusterCounts class. 

3""" 

4 

5from collections import OrderedDict 

6from typing import Union 

7 

8import numpy as np 

9 

10from ase import Atoms 

11from _icet import ClusterCounts as _ClusterCounts 

12from _icet import Cluster 

13from icet.core.orbit_list import OrbitList 

14from icet.core.structure import Structure 

15from .local_orbit_list_generator import LocalOrbitListGenerator 

16 

17 

18class ClusterCounts(_ClusterCounts): 

19 """ 

20 Provides an interface for inspecting cluster counts. 

21 

22 Parameters 

23 ---------- 

24 orbit_list : icet.OrbitList 

25 orbit list for a primitive structure 

26 structure : ase.Atoms 

27 supercell of the structure that `orbit_list` is based on 

28 fractional_position_tolerance : float 

29 tolerance for positions in fractional coordinates 

30 

31 Attributes 

32 ---------- 

33 cluster_counts : OrderedDict 

34 keys are representative clusters (icet Cluster objects) for all 

35 distinct orbits in the orbit list, values are dicts where the key is 

36 the chemical symbols of the species in a cluster, and the value is 

37 the number of counts of such clusters, e.g., 

38 {('Au', 'Ag'): 3, ('Au', 'Au'): 5}. 

39 """ 

40 

41 def __init__(self, 

42 orbit_list: OrbitList, 

43 structure: Atoms, 

44 fractional_position_tolerance: float): 

45 self._orbit_list = orbit_list 

46 self._structure = Structure.from_atoms(structure) 

47 # call (base) C++ constructor 

48 _ClusterCounts.__init__(self) 

49 self.cluster_counts = self._count_clusters( 

50 fractional_position_tolerance=fractional_position_tolerance) 

51 

52 def _count_clusters(self, 

53 fractional_position_tolerance: float, 

54 keep_order_intact: bool = False, 

55 permute_sites: bool = True): 

56 """ 

57 Counts all clusters in a structure by finding their local orbit list. 

58 

59 Parameters 

60 ---------- 

61 fractional_position_tolerance 

62 tolerance for positions in fractional coordinates 

63 keep_order_intact : bool 

64 if true the order in the cluster will be sorted 

65 permute_sites : bool 

66 if true will permute the sites so they are in the 

67 symmetrically equivalent order as the representative sites 

68 """ 

69 

70 local_orbit_list_generator = LocalOrbitListGenerator( 

71 orbit_list=self._orbit_list, 

72 structure=self._structure, 

73 fractional_position_tolerance=fractional_position_tolerance) 

74 

75 for i in range( 

76 local_orbit_list_generator.get_number_of_unique_offsets()): 

77 self.count_orbit_list( 

78 self._structure, 

79 local_orbit_list_generator.generate_local_orbit_list(i), 

80 keep_order_intact, permute_sites) 

81 

82 sorted_cluster_counts = \ 

83 OrderedDict(sorted(self.get_cluster_counts().items())) 

84 return sorted_cluster_counts 

85 

86 def __str__(self): 

87 """ 

88 String representation of ClusterCounts object that provides an 

89 overview of the clusters (cluster, chemical symbol, and count). 

90 """ 

91 tuplets = {1: 'Singlet', 2: 'Pair', 3: 'Triplet', 

92 4: 'Quadruplet', 5: 'Pentuplet'} 

93 width = 60 

94 s = ['{s:=^{n}}'.format(s=' Cluster Counts ', n=width)] 

95 

96 first = True 

97 for cluster, counts in self.cluster_counts.items(): 

98 if not first: 

99 s += [''] 

100 else: 

101 first = False 

102 

103 # Add a description of the orbit to the string 

104 tuplet_type = tuplets.get(cluster.order, 

105 '{}-tuplet'.format(cluster.order)) 

106 s += ['{}: {} {} {:.4f}' 

107 .format(tuplet_type, cluster.sites, 

108 [np.round(i, 5) for i in cluster.distances], cluster.radius)] 

109 

110 # Print the actual counts together with the species they refer to 

111 for chemical_symbols, count in counts.items(): 

112 t = ['{:3} '.format(el) for el in chemical_symbols] 

113 s += ['{} {}'.format(''.join(t), count)] 

114 s += [''.center(width, '=')] 

115 return '\n'.join(s) 

116 

117 def __getitem__(self, key: Union[int, Cluster]): 

118 """ 

119 Returns cluster count (Cluster object and dict with counts) for a 

120 ClusterCounts object. 

121 

122 Parameters 

123 ---------- 

124 key 

125 if int, return the key-th counts; 

126 if Cluster, return the counts belonging to that cluster 

127 """ 

128 if isinstance(key, int): 

129 return list(self.cluster_counts.values())[key] 

130 elif isinstance(key, Cluster): 130 ↛ exitline 130 didn't return from function '__getitem__', because the condition on line 130 was never false

131 return self.cluster_counts[key]