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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

# coding: utf-8 

# Copyright (c) Pymatgen Development Team. 

# Distributed under the terms of the MIT License. 

 

from __future__ import division, unicode_literals 

 

""" 

This module implements a EnergyModel abstract class and some basic 

implementations. Basically, an EnergyModel is any model that returns an 

"energy" for any given structure. 

""" 

 

 

 

__author__ = "Shyue Ping Ong" 

__copyright__ = "Copyright 2012, The Materials Project" 

__version__ = "0.1" 

__maintainer__ = "Shyue Ping Ong" 

__email__ = "shyuep@gmail.com" 

__date__ = "11/19/13" 

 

import abc 

 

import six 

 

from monty.json import MSONable 

from pymatgen.analysis.ewald import EwaldSummation 

from pymatgen.symmetry.analyzer import SpacegroupAnalyzer 

 

 

class EnergyModel(six.with_metaclass(abc.ABCMeta, MSONable)): 

""" 

Abstract structure filter class. 

""" 

 

@abc.abstractmethod 

def get_energy(self, structure): 

""" 

Returns a boolean for any structure. Structures that return true are 

kept in the Transmuter object during filtering. 

""" 

return 

 

@classmethod 

def from_dict(cls, d): 

return cls(**d['init_args']) 

 

 

class EwaldElectrostaticModel(EnergyModel): 

""" 

Wrapper around EwaldSum to calculate the electrostatic energy. 

""" 

 

def __init__(self, real_space_cut=None, recip_space_cut=None, 

eta=None, acc_factor=8.0): 

""" 

Initializes the model. Args have the same definitions as in 

:class:`pymatgen.analysis.ewald.EwaldSummation`. 

 

Args: 

real_space_cut (float): Real space cutoff radius dictating how 

many terms are used in the real space sum. Defaults to None, 

which means determine automagically using the formula given 

in gulp 3.1 documentation. 

recip_space_cut (float): Reciprocal space cutoff radius. 

Defaults to None, which means determine automagically using 

the formula given in gulp 3.1 documentation. 

eta (float): Screening parameter. Defaults to None, which means 

determine automatically. 

acc_factor (float): No. of significant figures each sum is 

converged to. 

""" 

self.real_space_cut = real_space_cut 

self.recip_space_cut = recip_space_cut 

self.eta = eta 

self.acc_factor = acc_factor 

 

def get_energy(self, structure): 

e = EwaldSummation(structure, real_space_cut=self.real_space_cut, 

recip_space_cut=self.recip_space_cut, 

eta=self.eta, 

acc_factor=self.acc_factor) 

return e.total_energy 

 

def as_dict(self): 

return {"version": __version__, 

"@module": self.__class__.__module__, 

"@class": self.__class__.__name__, 

"init_args": {"real_space_cut": self.real_space_cut, 

"recip_space_cut": self.recip_space_cut, 

"eta": self.eta, 

"acc_factor": self.acc_factor}} 

 

 

class SymmetryModel(EnergyModel): 

""" 

Sets the energy to the -ve of the spacegroup number. Higher symmetry => 

lower "energy". 

 

Args have same meaning as in 

:class:`pymatgen.symmetry.finder.SpacegroupAnalyzer`. 

 

Args: 

symprec (float): Symmetry tolerance. Defaults to 0.1. 

angle_tolerance (float): Tolerance for angles. Defaults to 5 degrees. 

""" 

 

def __init__(self, symprec=0.1, angle_tolerance=5): 

self.symprec = symprec 

self.angle_tolerance = angle_tolerance 

 

def get_energy(self, structure): 

f = SpacegroupAnalyzer(structure, symprec=self.symprec, 

angle_tolerance=self.angle_tolerance) 

return -f.get_spacegroup_number() 

 

def as_dict(self): 

return {"version": __version__, 

"@module": self.__class__.__module__, 

"@class": self.__class__.__name__, 

"init_args": {"symprec": self.symprec, 

"angle_tolerance": self.angle_tolerance}} 

 

 

class IsingModel(EnergyModel): 

""" 

A very simple Ising model, with r^2 decay. 

 

Args: 

j (float): The interaction parameter. E = J * spin1 * spin2. 

radius (float): max_radius for the interaction. 

""" 

 

def __init__(self, j, max_radius): 

self.j = j 

self.max_radius = max_radius 

 

def get_energy(self, structure): 

all_nn = structure.get_all_neighbors(r=self.max_radius) 

energy = 0 

for i, nn in enumerate(all_nn): 

s1 = getattr(structure[i].specie, "spin", 0) 

for site, dist in nn: 

energy += self.j * s1 * getattr(site.specie, "spin", 

0) / (dist ** 2) 

return energy 

 

def as_dict(self): 

return {"version": __version__, 

"@module": self.__class__.__module__, 

"@class": self.__class__.__name__, 

"init_args": {"j": self.j, "max_radius": self.max_radius}} 

 

 

class NsitesModel(EnergyModel): 

""" 

Sets the energy to the number of sites. More sites => higher "energy". 

Used to rank structures from smallest number of sites to largest number 

of sites after enumeration. 

""" 

 

def get_energy(self, structure): 

return len(structure) 

 

def as_dict(self): 

return {"version": __version__, 

"@module": self.__class__.__module__, 

"@class": self.__class__.__name__, 

"init_args": {}}