r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1from collections import OrderedDict

2from typing import List

4import numpy as np

6from ase import Atoms

7from icet import ClusterSpace

8from icet.core.sublattices import Sublattices

9from mchammer.calculators.base_calculator import BaseCalculator

12class TargetVectorCalculator(BaseCalculator):

13 """

14 A TargetVectorCalculator enables evaluation of the similarity

15 between a structure and a target cluster vector. Such a comparison

16 can be carried out in many ways, and this implementation follows the

17 measure proposed by van de Walle *et al.* in Calphad **42**, 13

18 (2013) [WalTiwJon13]_. Specifically, the objective function

19 :math:Q is calculated as

21 .. math::

22 Q = - \\omega L + \\sum_{\\alpha}

23 \\left| \\Gamma_{\\alpha} - \\Gamma^{\\text{target}}_{\\alpha}

24 \\right|.

26 Here, :math:\\Gamma_{\\alpha} are components in the cluster vector

27 and :math:\\Gamma^\\text{target}_{\\alpha} the corresponding

28 target values. The factor :math:\\omega is the radius of the

29 largest pair cluster such that all clusters with the same or smaller

30 radii have :math:\\Gamma_{\\alpha} -

31 \\Gamma^\\text{target}_{\\alpha} = 0.

33 Parameters

34 ----------

35 structure

36 structure for which to set up calculator

37 cluster_space

38 cluster space from which to build calculator

39 target_vector

40 vector to which any vector will be compared

41 weights

42 weighting of each component in cluster vector

43 comparison, by default 1.0 for all components

44 optimality_weight

45 factor :math:L, a high value of which effectively

46 favors a complete series of optimal cluster correlations

47 for the smallest pairs (see above)

48 optimality_tol

49 tolerance for determining whether a perfect match

50 has been achieved (used in conjunction with :math:L)

51 name

52 human-readable identifier for this calculator

53 """

55 def __init__(self, structure: Atoms, cluster_space: ClusterSpace,

56 target_vector: List[float],

57 weights: List[float] = None,

58 optimality_weight: float = 1.0,

59 optimality_tol: float = 1e-5,

60 name: str = 'Target vector calculator') -> None:

61 super().__init__(name=name)

63 if len(target_vector) != len(cluster_space): 63 ↛ 64line 63 didn't jump to line 64, because the condition on line 63 was never true

64 raise ValueError('Cluster space and target vector '

65 'must have the same length')

66 self.cluster_space = cluster_space

67 self.target_vector = target_vector

69 if weights is None:

70 weights = np.array([1.0] * len(cluster_space))

71 else:

72 if len(weights) != len(cluster_space):

73 raise ValueError('Cluster space and weights '

74 'must have the same length')

75 self.weights = np.array(weights)

77 if optimality_weight is not None:

78 self.optimality_weight = optimality_weight

79 self.optimality_tol = optimality_tol

80 self.orbit_data = self.cluster_space.orbit_data

81 else:

82 self.optimality_weight = None

83 self.optimality_tol = None

84 self.orbit_data = None

86 self._cluster_space = cluster_space

87 self._structure = structure

88 self._sublattices = self._cluster_space.get_sublattices(structure)

90 def calculate_total(self, occupations: List[int]) -> float:

91 """

92 Calculates and returns the similarity value :math:Q

93 of the current configuration.

95 Parameters

96 ----------

97 occupations

98 the entire occupation vector (i.e. list of atomic species)

99 """

100 self._structure.set_atomic_numbers(occupations)

101 cv = self.cluster_space.get_cluster_vector(self._structure)

102 return compare_cluster_vectors(cv, self.target_vector,

103 self.orbit_data,

104 weights=self.weights,

105 optimality_weight=self.optimality_weight,

106 tol=self.optimality_tol)

108 def calculate_change(self):

109 raise NotImplementedError

111 @property

112 def sublattices(self) -> Sublattices:

113 """Sublattices of the calculators structure."""

114 return self._sublattices

117def compare_cluster_vectors(cv_1: np.ndarray, cv_2: np.ndarray,

118 orbit_data: List[OrderedDict],

119 weights: List[float] = None,

120 optimality_weight: float = 1.0,

121 tol: float = 1e-5) -> float:

122 """

123 Calculate a quantity that measures similarity between two cluster

124 vecors.

126 Parameters

127 ----------

128 cv_1

129 cluster vector 1

130 cv_2

131 cluster vector 2

132 orbit_data

133 orbit data as obtained by ClusterSpace.orbit_data

134 weights

135 Weight assigned to each cluster vector element

136 optimality_weight

137 quantity :math:L in [WalTiwJon13]_

138 (see :class:mchammer.calculators.TargetVectorCalculator)

139 tol

140 numerical tolerance for determining whether two elements are

141 exactly equal

142 """

143 if weights is None:

144 weights = np.ones(len(cv_1))

145 diff = abs(cv_1 - cv_2)

146 score = np.dot(diff, weights)

147 if optimality_weight:

149 for orbit_index, d in enumerate(diff):

150 orbit = orbit_data[orbit_index]

151 if orbit['order'] != 2:

152 continue

153 if d < tol: