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"""This module defines an ASE interface to ABINIT. 

2 

3http://www.abinit.org/ 

4""" 

5 

6import re 

7 

8import ase.io.abinit as io 

9from ase.calculators.calculator import FileIOCalculator 

10from subprocess import check_output 

11 

12 

13def get_abinit_version(command): 

14 txt = check_output([command, '--version']).decode('ascii') 

15 # This allows trailing stuff like betas, rc and so 

16 m = re.match(r'\s*(\d\.\d\.\d)', txt) 

17 if m is None: 

18 raise RuntimeError('Cannot recognize abinit version. ' 

19 'Start of output: {}' 

20 .format(txt[:40])) 

21 return m.group(1) 

22 

23 

24class Abinit(FileIOCalculator): 

25 """Class for doing ABINIT calculations. 

26 

27 The default parameters are very close to those that the ABINIT 

28 Fortran code would use. These are the exceptions:: 

29 

30 calc = Abinit(label='abinit', xc='LDA', ecut=400, toldfe=1e-5) 

31 """ 

32 

33 implemented_properties = ['energy', 'forces', 'stress', 'magmom'] 

34 ignored_changes = {'pbc'} # In abinit, pbc is always effectively True. 

35 command = 'abinit < PREFIX.files > PREFIX.log' 

36 discard_results_on_any_change = True 

37 

38 default_parameters = dict( 

39 xc='LDA', 

40 smearing=None, 

41 kpts=None, 

42 raw=None, 

43 pps='fhi') 

44 

45 def __init__(self, restart=None, 

46 ignore_bad_restart_file=FileIOCalculator._deprecated, 

47 label='abinit', atoms=None, pp_paths=None, 

48 v8_legacy_format=None, 

49 **kwargs): 

50 """Construct ABINIT-calculator object. 

51 

52 Parameters 

53 ========== 

54 label: str 

55 Prefix to use for filenames (label.in, label.txt, ...). 

56 Default is 'abinit'. 

57 

58 Examples 

59 ======== 

60 Use default values: 

61 

62 >>> h = Atoms('H', calculator=Abinit(ecut=200, toldfe=0.001)) 

63 >>> h.center(vacuum=3.0) 

64 >>> e = h.get_potential_energy() 

65 

66 """ 

67 

68 self.v8_legacy_format = v8_legacy_format 

69 self.pp_paths = pp_paths 

70 

71 FileIOCalculator.__init__(self, restart, ignore_bad_restart_file, 

72 label, atoms, **kwargs) 

73 

74 def write_input(self, atoms, properties, system_changes): 

75 """Write input parameters to files-file.""" 

76 io.write_all_inputs( 

77 atoms, properties, parameters=self.parameters, 

78 pp_paths=self.pp_paths, 

79 label=self.label, v8_legacy_format=self.v8_legacy_format) 

80 

81 def read(self, label): 

82 """Read results from ABINIT's text-output file.""" 

83 # XXX I think we should redo the concept of 'restarting'. 

84 # It makes sense to load a previous calculation as 

85 # 

86 # * static, calculator-independent results 

87 # * an actual calculator capable of calculating 

88 # 

89 # Either of which is simpler than our current mechanism which 

90 # implies both at the same time. Moreover, we don't need 

91 # something like calc.read(label). 

92 # 

93 # What we need for these two purposes is 

94 # 

95 # * calc = MyCalculator.read(basefile) 

96 # (or maybe it should return Atoms with calc attached) 

97 # * results = read_results(basefile, format='abinit') 

98 # 

99 # where basefile determines the file tree. 

100 FileIOCalculator.read(self, label) 

101 self.atoms, self.parameters = io.read_ase_and_abinit_inputs(self.label) 

102 self.results = io.read_results(self.label, self._output_filename()) 

103 

104 def _output_filename(self): 

105 if self.v8_legacy_format: 

106 ext = '.txt' 

107 else: 

108 ext = '.abo' 

109 return self.label + ext 

110 

111 def read_results(self): 

112 self.results = io.read_results(self.label, self._output_filename()) 

113 

114 def get_number_of_iterations(self): 

115 return self.results['niter'] 

116 

117 def get_electronic_temperature(self): 

118 return self.results['width'] 

119 

120 def get_number_of_electrons(self): 

121 return self.results['nelect'] 

122 

123 def get_number_of_bands(self): 

124 return self.results['nbands'] 

125 

126 def get_k_point_weights(self): 

127 return self.results['kpoint_weights'] 

128 

129 def get_bz_k_points(self): 

130 raise NotImplementedError 

131 

132 def get_ibz_k_points(self): 

133 return self.results['ibz_kpoints'] 

134 

135 def get_spin_polarized(self): 

136 return self.results['eigenvalues'].shape[0] == 2 

137 

138 def get_number_of_spins(self): 

139 return len(self.results['eigenvalues']) 

140 

141 def get_fermi_level(self): 

142 return self.results['fermilevel'] 

143 

144 def get_eigenvalues(self, kpt=0, spin=0): 

145 return self.results['eigenvalues'][spin, kpt] 

146 

147 def get_occupations(self, kpt=0, spin=0): 

148 raise NotImplementedError