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 argv = self.argv + [str(inputfile)] 

36 with open(directory / outputfile, 'wb') as fd: 

37 check_call(argv, stdout=fd, env=os.environ, cwd=directory) 

38 

39 def socketio_argv_unix(self, socket): 

40 # XXX clean up the passing of the inputfile 

41 inputfile = AbinitTemplate().input_file 

42 return [*self.argv, inputfile, '--ipi', f'{socket}:UNIX'] 

43 

44 

45class AbinitTemplate(CalculatorTemplate): 

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

47 

48 def __init__(self): 

49 super().__init__( 

50 name='abinit', 

51 implemented_properties=['energy', 'free_energy', 

52 'forces', 'stress', 'magmom']) 

53 

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

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

56 

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

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

59 

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

61 directory = Path(directory) 

62 parameters = dict(parameters) 

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

64 assert pp_paths is not None 

65 

66 kw = dict( 

67 xc='LDA', 

68 smearing=None, 

69 kpts=None, 

70 raw=None, 

71 pps='fhi') 

72 kw.update(parameters) 

73 

74 io.prepare_abinit_input( 

75 directory=directory, 

76 atoms=atoms, properties=properties, parameters=kw, 

77 pp_paths=pp_paths) 

78 

79 def read_results(self, directory): 

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

81 

82 

83class Abinit(GenericFileIOCalculator): 

84 """Class for doing ABINIT calculations. 

85 

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

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

88 

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

90 """ 

91 

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

93 """Construct ABINIT-calculator object. 

94 

95 Parameters 

96 ========== 

97 label: str 

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

99 Default is 'abinit'. 

100 

101 Examples 

102 ======== 

103 Use default values: 

104 

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

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

107 >>> e = h.get_potential_energy() 

108 

109 """ 

110 

111 if profile is None: 

112 profile = AbinitProfile(['abinit']) 

113 

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

115 profile=profile, 

116 directory=directory, 

117 parameters=kwargs)