Coverage for /builds/ase/ase/ase/calculators/espresso.py : 96.23%

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"""Quantum ESPRESSO Calculator
3Run pw.x jobs.
4"""
7import os
8from ase.calculators.genericfileio import (
9 GenericFileIOCalculator, CalculatorTemplate, read_stdout)
10from ase.io import read, write
13compatibility_msg = (
14 'Espresso calculator is being restructured. Please use e.g. '
15 'Espresso(profile=EspressoProfile(argv=[\'mpiexec\', \'pw.x\'])) '
16 'to customize command-line arguments.')
19# XXX We should find a way to display this warning.
20# warn_template = 'Property "%s" is None. Typically, this is because the ' \
21# 'required information has not been printed by Quantum ' \
22# 'Espresso at a "low" verbosity level (the default). ' \
23# 'Please try running Quantum Espresso with "high" verbosity.'
26class EspressoProfile:
27 def __init__(self, argv):
28 self.argv = tuple(argv)
30 @staticmethod
31 def parse_version(stdout):
32 import re
33 match = re.match(r'\s*Program PWSCF\s*v\.(\S+)', stdout, re.M)
34 assert match is not None
35 return match.group(1)
37 def version(self):
38 stdout = read_stdout(self.argv)
39 return self.parse_version(stdout)
41 def run(self, directory, inputfile, outputfile):
42 from subprocess import check_call
43 import os
44 argv = list(self.argv) + ['-in', str(inputfile)]
45 with open(directory / outputfile, 'wb') as fd:
46 check_call(argv, cwd=directory, stdout=fd, env=os.environ)
48 def socketio_argv_unix(self, socket):
49 template = EspressoTemplate()
50 # It makes sense to know the template for this kind of choices,
51 # but is there a better way?
52 return list(self.argv) + ['--ipi', f'{socket}:UNIX', '-in',
53 template.inputname]
56class EspressoTemplate(CalculatorTemplate):
57 def __init__(self):
58 super().__init__(
59 'espresso',
60 ['energy', 'free_energy', 'forces', 'stress', 'magmoms'])
61 self.inputname = 'espresso.pwi'
62 self.outputname = 'espresso.pwo'
64 def write_input(self, directory, atoms, parameters, properties):
65 dst = directory / self.inputname
66 write(dst, atoms, format='espresso-in', properties=properties,
67 **parameters)
69 def execute(self, directory, profile):
70 profile.run(directory,
71 self.inputname,
72 self.outputname)
74 def read_results(self, directory):
75 path = directory / self.outputname
76 atoms = read(path, format='espresso-out')
77 return dict(atoms.calc.properties())
80class Espresso(GenericFileIOCalculator):
81 def __init__(self, *, profile=None,
82 command=GenericFileIOCalculator._deprecated,
83 label=GenericFileIOCalculator._deprecated,
84 directory='.',
85 **kwargs):
86 """
87 All options for pw.x are copied verbatim to the input file, and put
88 into the correct section. Use ``input_data`` for parameters that are
89 already in a dict, all other ``kwargs`` are passed as parameters.
91 Accepts all the options for pw.x as given in the QE docs, plus some
92 additional options:
94 input_data: dict
95 A flat or nested dictionary with input parameters for pw.x
96 pseudopotentials: dict
97 A filename for each atomic species, e.g.
98 ``{'O': 'O.pbe-rrkjus.UPF', 'H': 'H.pbe-rrkjus.UPF'}``.
99 A dummy name will be used if none are given.
100 kspacing: float
101 Generate a grid of k-points with this as the minimum distance,
102 in A^-1 between them in reciprocal space. If set to None, kpts
103 will be used instead.
104 kpts: (int, int, int), dict, or BandPath
105 If kpts is a tuple (or list) of 3 integers, it is interpreted
106 as the dimensions of a Monkhorst-Pack grid.
107 If ``kpts`` is set to ``None``, only the Γ-point will be included
108 and QE will use routines optimized for Γ-point-only calculations.
109 Compared to Γ-point-only calculations without this optimization
110 (i.e. with ``kpts=(1, 1, 1)``), the memory and CPU requirements
111 are typically reduced by half.
112 If kpts is a dict, it will either be interpreted as a path
113 in the Brillouin zone (*) if it contains the 'path' keyword,
114 otherwise it is converted to a Monkhorst-Pack grid (**).
115 (*) see ase.dft.kpoints.bandpath
116 (**) see ase.calculators.calculator.kpts2sizeandoffsets
117 koffset: (int, int, int)
118 Offset of kpoints in each direction. Must be 0 (no offset) or
119 1 (half grid offset). Setting to True is equivalent to (1, 1, 1).
122 .. note::
123 Set ``tprnfor=True`` and ``tstress=True`` to calculate forces and
124 stresses.
126 .. note::
127 Band structure plots can be made as follows:
130 1. Perform a regular self-consistent calculation,
131 saving the wave functions at the end, as well as
132 getting the Fermi energy:
134 >>> input_data = {<your input data>}
135 >>> calc = Espresso(input_data=input_data, ...)
136 >>> atoms.calc = calc
137 >>> atoms.get_potential_energy()
138 >>> fermi_level = calc.get_fermi_level()
140 2. Perform a non-self-consistent 'band structure' run
141 after updating your input_data and kpts keywords:
143 >>> input_data['control'].update({'calculation':'bands',
144 >>> 'restart_mode':'restart',
145 >>> 'verbosity':'high'})
146 >>> calc.set(kpts={<your Brillouin zone path>},
147 >>> input_data=input_data)
148 >>> calc.calculate(atoms)
150 3. Make the plot using the BandStructure functionality,
151 after setting the Fermi level to that of the prior
152 self-consistent calculation:
154 >>> bs = calc.band_structure()
155 >>> bs.reference = fermi_energy
156 >>> bs.plot()
158 """
160 if command is not self._deprecated:
161 raise RuntimeError(compatibility_msg)
163 if label is not self._deprecated:
164 import warnings
165 warnings.warn('Ignoring label, please use directory instead',
166 FutureWarning)
168 if 'ASE_ESPRESSO_COMMAND' in os.environ and profile is None:
169 import warnings
170 warnings.warn(compatibility_msg, FutureWarning)
172 template = EspressoTemplate()
173 if profile is None:
174 profile = EspressoProfile(argv=['pw.x'])
175 super().__init__(profile=profile, template=template,
176 directory=directory,
177 parameters=kwargs)