Skip to content

Commit 463f98f

Browse files
authored
Merge pull request #389 from emarazzi/phonons_atomate2
New factories for phonons workflow in atomate2
2 parents 88f1334 + e089040 commit 463f98f

2 files changed

Lines changed: 115 additions & 3 deletions

File tree

abipy/abio/factories.py

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,44 @@ def nscf_from_gsinput(gs_input, kppa=None, nband=None, accuracy="normal",
12431243

12441244
return nscf_input
12451245

1246+
def wfq_nscf_from_gsinput(gs_input, qpt, kppa=None, nband=None, accuracy="high",
1247+
shift_mode="Monkhorst-Pack") -> AbinitInput:
1248+
"""
1249+
Return an |AbinitInput| object to perform a NSCF calculation on a K+Q grid from a GS SCF input.
1250+
1251+
Args:
1252+
gs_input: the |AbinitInput| that was used to calculated the charge density.
1253+
qpt: q-point used to shift the k grid.
1254+
kppa: defines the kpt sampling used for the NSCF run. If None the kpoint sampling and
1255+
shifts will be the same as in the SCF input.
1256+
nband: the number of bands to be used for the calculation. If None it will be
1257+
automatically generated.
1258+
accuracy: accuracy of the calculation.
1259+
shift_mode: the mode to be used for the shifts. Options are "Gamma", "Monkhorst-Pack",
1260+
"Symmetric", "OneSymmetric". See ShiftMode object for more details. Only used if kppa
1261+
is not None.
1262+
1263+
Return: |AbinitInput|
1264+
"""
1265+
# create a copy to avoid messing with the previous input
1266+
wfq_input = gs_input.deepcopy()
1267+
wfq_input.pop_irdvars()
1268+
1269+
if kppa is not None:
1270+
shift_mode = ShiftMode.from_object(shift_mode)
1271+
shifts = _get_shifts(shift_mode, gs_input.structure)
1272+
dos_ksampling = aobj.KSampling.automatic_density(wfq_input.structure, kppa, chksymbreak=0, shifts=shifts)
1273+
wfq_input.set_vars(dos_ksampling.to_abivars())
1274+
1275+
if nband is None:
1276+
nband = _find_nscf_nband_from_gsinput(gs_input)
1277+
1278+
wfq_input.set_vars(qpt=qpt, nband=nband, iscf=-2, nqpt=1, kptopt=3)
1279+
wfq_input.set_vars(_stopping_criterion("nscf", accuracy))
1280+
1281+
return wfq_input
1282+
1283+
12461284

12471285
def dos_from_gsinput(gs_input, kppa=None, nband=None, accuracy="normal", dos_method="tetra",
12481286
projection="l", shift_mode="Monkhorst-Pack") -> AbinitInput:
@@ -1352,10 +1390,9 @@ def hybrid_scf_input(gs_input: AbinitInput,
13521390

13531391
def scf_for_phonons(structure, pseudos, kppa=None, ecut=None, pawecutdg=None, nband=None, accuracy="normal",
13541392
spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None,
1355-
shift_mode="Symmetric") -> AbinitInput:
1393+
shift_mode="Symmetric", nbdbuf=4) -> AbinitInput:
13561394

13571395
# add the band for nbdbuf, if needed
1358-
nbdbuf = 4
13591396
if nband is not None:
13601397
nband += nbdbuf
13611398

@@ -1364,7 +1401,7 @@ def scf_for_phonons(structure, pseudos, kppa=None, ecut=None, pawecutdg=None, nb
13641401
scf_algorithm=scf_algorithm, shift_mode=shift_mode)
13651402

13661403
# with no bands set and no smearing the minimum number of bands plus some nbdbuf
1367-
if nband is None and smearing is None:
1404+
if nband is None and (smearing is None or smearing == "nosmearing"):
13681405
nval = structure.num_valence_electrons(pseudos)
13691406
nval -= abiinput['charge']
13701407
nband = int(round(nval / 2) + nbdbuf)
@@ -1453,6 +1490,32 @@ def dtepert_from_gsinput(gs_input, dte_pert, manager=None) -> AbinitInput:
14531490
return dte_inp
14541491

14551492

1493+
1494+
def phononpert_from_gsinput(gs_input, phonon_pert, phonon_tol=None, manager=None) -> AbinitInput:
1495+
"""
1496+
Returns an |AbinitInput| to perform a phonon perturbation calculation for a specific perturbation based on a ground state |AbinitInput|.
1497+
1498+
Args:
1499+
gs_input: an |AbinitInput| representing a ground state calculation, likely the SCF performed to get the WFK.
1500+
phonon_pert: dict with the Abinit variables defining the perturbation
1501+
Example: {'idir': 1, 'ipert': 1, 'qpt': [0.0, 0.0, 0.0]},
1502+
phonon_tol: dict with a single ABINIT tolerance variable (e.g. ``{'tolvrs': 1.0e-10}``)
1503+
used to control the convergence of the DFPT calculation.
1504+
If ``None``, a default of ``{'tolvrs': 1.0e-10}`` is used.
1505+
manager: |TaskManager| of the task. If None, the manager is initialized from the config file.
1506+
"""
1507+
gs_input = gs_input.deepcopy()
1508+
gs_input.pop_irdvars()
1509+
gs_input.pop_vars(['autoparal', 'npfft'])
1510+
1511+
if phonon_tol is None:
1512+
phonon_tol = {"tolvrs": 1.0e-10}
1513+
1514+
phonon_inp = gs_input.make_phpert_input(perturbation=phonon_pert, tolerance=phonon_tol, manager=manager)
1515+
1516+
return phonon_inp
1517+
1518+
14561519
def dte_from_gsinput(gs_input, use_phonons=True, ph_tol=None, ddk_tol=None, dde_tol=None,
14571520
skip_dte_permutations=False, manager=None) -> MultiDataset:
14581521
"""

abipy/abio/inputs.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,6 +2329,55 @@ def make_dtepert_input(self, perturbation, ixc=None, manager=None) -> AbinitInpu
23292329

23302330
return inp
23312331

2332+
2333+
def make_phpert_input(self, perturbation, tolerance=None, prtwf=-1, manager=None) -> AbinitInput:
2334+
"""
2335+
Return |AbinitInput| for a Phonon calculation for a given perturbation.
2336+
This functions should be called with an input that represents a GS run.
2337+
2338+
Args:
2339+
perturbation: dict with the Abinit variables defining the irreducible perturbation.
2340+
Example: {'idir': 1, 'ipert': 4, 'qpt': [0.0, 0.0, 0.0]}.
2341+
tolerance: Dict with a single ABINIT tolerance variable (e.g. ``{'tolvrs': 1.0e-10}``)
2342+
used to control the convergence of the DFPT calculation. If ``None``, a
2343+
default of ``{'tolvrs': 1.0e-10}`` is used.
2344+
prtwf: Value passed to the ABINIT variable ``prtwf`` to control the printing
2345+
of wavefunctions for the phonon calculation. Defaults to ``-1`` (ABINIT default).
2346+
manager: |TaskManager| of the task. If None, the manager is initialized from
2347+
the config file.
2348+
"""
2349+
if tolerance is None: tolerance = {"tolvrs": 1.0e-10}
2350+
2351+
if len(tolerance) != 1 or any(k not in _TOLVARS for k in tolerance):
2352+
raise self.Error(f"Invalid {tolerance=}")
2353+
inp = self.deepcopy()
2354+
inp.pop_irdvars()
2355+
2356+
scf_kptopt = self.get("kptopt", 1)
2357+
kptopt = 3
2358+
if np.allclose(perturbation["qpt"], 0) and scf_kptopt in (1, 2):
2359+
kptopt = 2
2360+
2361+
rfdir = 3 * [0]
2362+
rfdir[perturbation["idir"] - 1] = 1
2363+
2364+
inp.set_vars(
2365+
rfphon=1, # Will consider phonon-type perturbation
2366+
nqpt=1, # One wavevector is to be considered
2367+
qpt=perturbation["qpt"], # q-wavevector.
2368+
rfatpol=[perturbation["ipert"], perturbation["ipert"]],
2369+
rfdir=rfdir,
2370+
kptopt=kptopt,
2371+
comment="Input file for PH calculation with DFPT.",
2372+
prtwf=prtwf,
2373+
)
2374+
2375+
inp.pop_tolerances()
2376+
inp.set_vars(tolerance)
2377+
2378+
return inp
2379+
2380+
23322381
def make_dte_inputs(self, phonon_pert=False, skip_permutations=False, ixc=None, manager=None) -> MultiDataset:
23332382
"""
23342383
Return |MultiDataset| inputs for DTE calculation.

0 commit comments

Comments
 (0)