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 os 

9import ase.io.abinit as io 

10from ase.calculators.genericfileio import (CalculatorTemplate, 

11 GenericFileIOCalculator) 

12from subprocess import check_output, check_call 

13from pathlib import Path 

14 

15 

16def get_abinit_version(command): 

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

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

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

20 if m is None: 

21 raise RuntimeError('Cannot recognize abinit version. ' 

22 'Start of output: {}' 

23 .format(txt[:40])) 

24 return m.group(1) 

25 

26 

27class AbinitProfile: 

28 def __init__(self, argv): 

29 self.argv = argv 

30 

31 def version(self): 

32 return check_output(self.argv + ['--version']) 

33 

34 def run(self, directory, inputfile, outputfile): 

35 with open(outputfile, 'w') as fd: 

36 check_call(self.argv + [str(inputfile)], stdout=fd, 

37 env=os.environ, 

38 cwd=directory) 

39 

40 

41class AbinitTemplate(CalculatorTemplate): 

42 _label = 'abinit' # Controls naming of files within calculation directory 

43 

44 def __init__(self): 

45 super().__init__( 

46 name='abinit', 

47 implemented_properties=['energy', 'free_energy', 

48 'forces', 'stress', 'magmom']) 

49 

50 self.input_file = f'{self._label}.in' 

51 self.output_file = f'{self._label}.log' 

52 

53 def execute(self, directory, profile) -> None: 

54 profile.run(directory, self.input_file, self.output_file) 

55 

56 def write_input(self, directory, atoms, parameters, properties): 

57 directory = Path(directory) 

58 parameters = dict(parameters) 

59 pp_paths = parameters.pop('pp_paths', None) 

60 assert pp_paths is not None 

61 

62 kw = dict( 

63 xc='LDA', 

64 smearing=None, 

65 kpts=None, 

66 raw=None, 

67 pps='fhi') 

68 kw.update(parameters) 

69 

70 io.prepare_abinit_input( 

71 directory=directory, 

72 atoms=atoms, properties=properties, parameters=kw, 

73 pp_paths=pp_paths) 

74 

75 def read_results(self, directory): 

76 return io.read_abinit_outputs(directory, self._label) 

77 

78 

79class Abinit(GenericFileIOCalculator): 

80 """Class for doing ABINIT calculations. 

81 

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

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

84 

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

86 """ 

87 

88 def __init__(self, *, profile=None, directory='.', **kwargs): 

89 """Construct ABINIT-calculator object. 

90 

91 Parameters 

92 ========== 

93 label: str 

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

95 Default is 'abinit'. 

96 

97 Examples 

98 ======== 

99 Use default values: 

100 

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

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

103 >>> e = h.get_potential_energy() 

104 

105 """ 

106 

107 if profile is None: 

108 profile = AbinitProfile(['abinit']) 

109 

110 super().__init__(template=AbinitTemplate(), 

111 profile=profile, 

112 directory=directory, 

113 parameters=kwargs)