Skip to content

Commit 2c91190

Browse files
authored
Merge pull request #726 from yang-ruoxi/absorption
Absorption
2 parents ff72eab + 1403c69 commit 2c91190

File tree

3 files changed

+299
-0
lines changed

3 files changed

+299
-0
lines changed

atomate/vasp/drones.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,11 @@ def generate_doc(self, dir_name, vasprun_files, outcar_files):
419419
for k in ["optical_absorption_coeff", "dielectric"]:
420420
d["output"][k] = d_calc_final["output"][k]
421421

422+
# store optical data, overwrites the LOPTICS data
423+
if d["input"]["incar"].get("ALGO") == 'CHI':
424+
for k in ["optical_absorption_coeff", "dielectric"]:
425+
d["output"][k] = d_calc_final["output"][k]
426+
422427
d["state"] = (
423428
"successful" if d_calc["has_vasp_completed"] else "unsuccessful"
424429
)
@@ -582,6 +587,14 @@ def process_vasprun(self, dir_name, taskname, filename):
582587
)
583588
d["output"]["optical_absorption_coeff"] = vrun.optical_absorption_coeff
584589

590+
# parse output from response function
591+
if vrun.incar.get("ALGO") == 'CHI':
592+
dielectric = vrun.dielectric
593+
d["output"]["dielectric"] = dict(
594+
energy=dielectric[0], real=dielectric[1], imag=dielectric[2]
595+
)
596+
d["output"]["optical_absorption_coeff"] = vrun.optical_absorption_coeff
597+
585598
return d
586599

587600
def process_bandstructure(self, vrun):
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import os
2+
from importlib import import_module
3+
4+
import numpy as np
5+
6+
from monty.serialization import dumpfn
7+
from fireworks import FiretaskBase, explicit_serialize
8+
from fireworks.utilities.dict_mods import apply_mod
9+
from pymatgen.core.structure import Structure
10+
from pymatgen.io.vasp import Incar, Poscar, Potcar, PotcarSingle, Kpoints
11+
from pymatgen.io.vasp.sets import MPAbsorptionSet
12+
from pymatgen.io.vasp.outputs import Vasprun
13+
from atomate.utils.utils import env_chk, load_class
14+
15+
@explicit_serialize
16+
class WriteVaspAbsorptionFromPrev(FiretaskBase):
17+
"""
18+
Writes input files for an LOPTICS absorption run. Assumes that output files (WAVECAR) from an
19+
scf job can be accessed.
20+
Optional params:
21+
"prev_calc_dir",
22+
"mode", either "IPA" or "RPA"
23+
"reciprocal_density",
24+
"other_params",
25+
"potcar_spec"
26+
27+
"""
28+
optional_params = [
29+
"prev_calc_dir",
30+
"structure",
31+
"mode",
32+
"copy_wavecar",
33+
"nbands",
34+
"nbands_factor",
35+
"reciprocal_density",
36+
"nkred",
37+
"ncores",
38+
"nedos",
39+
"potcar_spec",
40+
"other_params"
41+
]
42+
43+
def run_task(self, fw_spec):
44+
vis = MPAbsorptionSet.from_prev_calc(
45+
prev_calc_dir=self.get("prev_calc_dir", "."),
46+
mode=self.get("mode", "IPA"),
47+
copy_wavecar=self.get("copy_wavecar", True),
48+
nbands=self.get("nbands", None),
49+
nbands_factor=self.get("nbands_factor", 2),
50+
reciprocal_density=self.get("reciprocal_density", 200),
51+
nkred=self.get("nkred", None),
52+
nedos=self.get("nedos", 2001),
53+
**self.get("other_params", {})
54+
)
55+
potcar_spec = self.get("potcar_spec", False)
56+
vis.write_input(".", potcar_spec=potcar_spec)

atomate/vasp/fireworks/absorption.py

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
from atomate.vasp.config import (
2+
VASP_CMD,
3+
DB_FILE,
4+
)
5+
from fireworks import Firework
6+
from pymatgen.io.vasp.sets import MPStaticSet, MPAbsorptionSet
7+
from atomate.common.firetasks.glue_tasks import (
8+
PassCalcLocs,
9+
CopyFiles,
10+
DeleteFiles,
11+
GzipDir,
12+
CreateFolder,
13+
PassCalcLocs
14+
)
15+
from atomate.vasp.firetasks import (
16+
CheckBandgap,
17+
CopyVaspOutputs,
18+
ModifyIncar,
19+
RunVaspCustodian,
20+
VaspToDb,
21+
)
22+
from atomate.vasp.firetasks.write_inputs import WriteVaspFromIOSet, WriteVaspStaticFromPrev
23+
from atomate.vasp.firetasks.absorption_tasks import WriteVaspAbsorptionFromPrev
24+
25+
26+
class AbsorptionFW(Firework):
27+
def __init__(
28+
self,
29+
structure,
30+
name="frequency dependent dielectrics",
31+
mode='STATIC',
32+
nbands=None,
33+
nbands_factor=2,
34+
reciprocal_density=200,
35+
nkred=None,
36+
nedos=2001,
37+
vasp_cmd=VASP_CMD,
38+
prev_calc_dir=None,
39+
db_file=DB_FILE,
40+
vasptodb_kwargs=None,
41+
parents=None,
42+
vasp_input_set_params=None,
43+
**kwargs,
44+
):
45+
"""
46+
FW that calculates frequency dependent dielectric function within
47+
indenpendent-particle-approxiamtion. A previous ground state calculation
48+
with the output WAVECAR is required by specifying mode = 'static'; in the case of no
49+
parent, a PBE functional ground state calculation will be performed and
50+
the WAVECAR will be saved. Then, perform another calculation with 'ALGO = EXACT, LOPTICS = True'
51+
with variable NBANDS by specifying MODE = "IPA". This calculation will save the
52+
WAVECAR and WAVEDER in case one wants to run RPA level absorption
53+
spectra. For RPA-DFT absorption spectrum, run another mode = 'RPA' calculation
54+
with the WAVECAR, WAVEDER saved from previous IPA calc.
55+
Args:
56+
structure (Structure): Input structure. For an interpolation, this
57+
is a dummy structure. See interpolate arg description.
58+
name (str): Name for the FireWork.
59+
mode: 'STATIC', 'IPA', or 'RPA'.
60+
nbands: number of bands to use, leave to None, and use nbands_factor instead
61+
nbands_factor: the multiplication of the number of bands
62+
reciprocal_density: k-point density
63+
nkred: reduced number of k-points, for RPA calculation use only, reduces the computing time
64+
nedos: energy mesh for DOS
65+
vasp_cmd (str): Command to run vasp.
66+
prev_calc_loc (bool or str): If true (default), copies outputs from previous calc. If
67+
a str value, retrieves a previous calculation output by name.
68+
vasp_input_set (str): string name for the VASP input set (e.g.,
69+
"MPAbsorptionSet").
70+
db_file (str): Path to file specifying db credentials.
71+
parents (Firework): Parents of this particular Firework. FW or list
72+
of FWS.
73+
vasp_input_set_params (dict): Dict of vasp_input_set_kwargs.
74+
prev_calc_dir (str): Path to a previous calculation to copy from
75+
vasptodb_kwargs (dict): kwargs to pass to VaspToDb
76+
**kwargs: Other kwargs that are passed to Firework.__init__.
77+
78+
"""
79+
t = []
80+
81+
vasp_input_set_params = vasp_input_set_params or {}
82+
vasptodb_kwargs = vasptodb_kwargs or {}
83+
if "additional_fields" not in vasptodb_kwargs:
84+
vasptodb_kwargs["additional_fields"] = {}
85+
vasptodb_kwargs["additional_fields"]["task_label"] = name
86+
87+
fw_name = "{}-{}-{}".format(
88+
structure.composition.reduced_formula if structure else "unknown", name, mode
89+
)
90+
91+
# define what wavecars to copy from the previous run
92+
if mode == "STATIC":
93+
wavecars = []
94+
elif mode == "IPA":
95+
wavecars = ["WAVECAR"]
96+
elif mode == "RPA":
97+
wavecars = ["WAVECAR", "WAVEDER"]
98+
else:
99+
raise Exception("Mode has to be from 'STATIC', 'IPA' or 'RPA'. ")
100+
101+
# "IPA" or "RPA" run
102+
if mode == "IPA" or mode == "RPA":
103+
if prev_calc_dir:
104+
# Copy the WAVECAR from previous calc directory
105+
t.append(CopyVaspOutputs(
106+
calc_dir=prev_calc_dir,
107+
contcar_to_poscar=True,
108+
additional_files=wavecars)
109+
)
110+
111+
t.append(
112+
WriteVaspAbsorptionFromPrev(
113+
prev_calc_dir=".",
114+
structure=structure, # The structure will only be useful for the FW name
115+
mode=mode,
116+
copy_wavecar=True,
117+
nbands=None,
118+
nbands_factor=nbands_factor,
119+
reciprocal_density=reciprocal_density,
120+
nkred=nkred,
121+
nedos=nedos,
122+
**vasp_input_set_params
123+
)
124+
)
125+
126+
elif parents:
127+
# Copy the WAVECAR from previous calc location
128+
t.append(
129+
CopyVaspOutputs(
130+
calc_loc=True,
131+
contcar_to_poscar=True,
132+
additional_files=wavecars
133+
)
134+
)
135+
136+
t.append(
137+
WriteVaspAbsorptionFromPrev(
138+
prev_calc_dir=".",
139+
structure=structure, # The structure will only be useful for the FW name
140+
mode=mode,
141+
copy_wavecar=True,
142+
nbands=None,
143+
nbands_factor=nbands_factor,
144+
reciprocal_density=reciprocal_density,
145+
nkred=nkred,
146+
nedos=nedos,
147+
**vasp_input_set_params
148+
)
149+
)
150+
151+
else:
152+
raise ValueError("Must specify previous calculation for {}".format(mode))
153+
154+
# when mode = "static"
155+
elif mode == "STATIC":
156+
static_incar={"LWAVE": True,
157+
"ENCUT": 500,
158+
"ISMEAR": 0,
159+
"SIGMA": 0.01,
160+
"LREAL": False,
161+
"GGA": "PE",
162+
"LELF": False,
163+
"LAECHG": False,
164+
"LASPH": False,
165+
"LVHAR": False,
166+
"LVTOT": False,
167+
"METAGGA": "None",
168+
"LMIXTAU": False}
169+
170+
if prev_calc_dir:
171+
# Copy only the CONTCAR from previous calc directory (often a relaxation run)
172+
t.append(
173+
CopyVaspOutputs(
174+
calc_dir=prev_calc_dir,
175+
contcar_to_poscar=True,
176+
additional_files=wavecars
177+
)
178+
)
179+
180+
t.append(
181+
WriteVaspStaticFromPrev(reciprocal_density=reciprocal_density,
182+
other_params={"user_incar_settings": static_incar})
183+
)
184+
185+
elif parents:
186+
# Copy only the CONTCAR from previous calc
187+
t.append(CopyVaspOutputs(calc_loc=True,
188+
additional_files=wavecars,
189+
contcar_to_poscar=True)
190+
)
191+
192+
t.append(
193+
WriteVaspStaticFromPrev(reciprocal_density=reciprocal_density,
194+
other_params={"user_incar_settings": static_incar})
195+
)
196+
197+
elif structure:
198+
static_input_set = MPStaticSet(structure=structure,
199+
reciprocal_density=reciprocal_density,
200+
user_incar_settings=static_incar)
201+
202+
t.append(WriteVaspFromIOSet(structure=structure, vasp_input_set=static_input_set)
203+
)
204+
205+
else:
206+
raise ValueError("Must specify structure or previous calculation for static calculation")
207+
208+
else:
209+
raise ValueError("Must specify a mode from 'STATIC', 'IPA', or 'RPA'")
210+
211+
# use the 'default' custodian handler group
212+
handler_group = "default"
213+
214+
# Run VASP
215+
t.append(
216+
RunVaspCustodian(
217+
vasp_cmd=vasp_cmd,
218+
auto_npar=">>auto_npar<<",
219+
handler_group=handler_group
220+
)
221+
)
222+
t.append(PassCalcLocs(name=name))
223+
# Parse
224+
t.append(VaspToDb(db_file=db_file,
225+
additional_fields={
226+
"task_label": structure.composition.reduced_formula + " " + name + " " + mode}))
227+
228+
super().__init__(t, parents=parents, name=fw_name, **kwargs)
229+
230+

0 commit comments

Comments
 (0)