Coverage for /builds/ase/ase/ase/calculators/abinit.py : 93.62%

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.
3http://www.abinit.org/
4"""
6import re
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
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)
27class AbinitProfile:
28 def __init__(self, argv):
29 self.argv = argv
31 def version(self):
32 return check_output(self.argv + ['--version'])
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)
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']
45class AbinitTemplate(CalculatorTemplate):
46 _label = 'abinit' # Controls naming of files within calculation directory
48 def __init__(self):
49 super().__init__(
50 name='abinit',
51 implemented_properties=['energy', 'free_energy',
52 'forces', 'stress', 'magmom'])
54 self.input_file = f'{self._label}.in'
55 self.output_file = f'{self._label}.log'
57 def execute(self, directory, profile) -> None:
58 profile.run(directory, self.input_file, self.output_file)
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
66 kw = dict(
67 xc='LDA',
68 smearing=None,
69 kpts=None,
70 raw=None,
71 pps='fhi')
72 kw.update(parameters)
74 io.prepare_abinit_input(
75 directory=directory,
76 atoms=atoms, properties=properties, parameters=kw,
77 pp_paths=pp_paths)
79 def read_results(self, directory):
80 return io.read_abinit_outputs(directory, self._label)
83class Abinit(GenericFileIOCalculator):
84 """Class for doing ABINIT calculations.
86 The default parameters are very close to those that the ABINIT
87 Fortran code would use. These are the exceptions::
89 calc = Abinit(label='abinit', xc='LDA', ecut=400, toldfe=1e-5)
90 """
92 def __init__(self, *, profile=None, directory='.', **kwargs):
93 """Construct ABINIT-calculator object.
95 Parameters
96 ==========
97 label: str
98 Prefix to use for filenames (label.in, label.txt, ...).
99 Default is 'abinit'.
101 Examples
102 ========
103 Use default values:
105 >>> h = Atoms('H', calculator=Abinit(ecut=200, toldfe=0.001))
106 >>> h.center(vacuum=3.0)
107 >>> e = h.get_potential_energy()
109 """
111 if profile is None:
112 profile = AbinitProfile(['abinit'])
114 super().__init__(template=AbinitTemplate(),
115 profile=profile,
116 directory=directory,
117 parameters=kwargs)