Skip to content

Commit c465005

Browse files
committed
add absorption
1 parent 813ab08 commit c465005

File tree

3 files changed

+286
-0
lines changed

3 files changed

+286
-0
lines changed

atomate/vasp/drones.py

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

424+
# store optical data, overwrites the LOPTICS data
425+
if d["input"]["incar"].get("ALGO") == 'CHI':
426+
for k in ["optical_absorption_coeff", "dielectric"]:
427+
d["output"][k] = d_calc_final["output"][k]
428+
424429
d["state"] = (
425430
"successful" if d_calc["has_vasp_completed"] else "unsuccessful"
426431
)
@@ -586,6 +591,14 @@ def process_vasprun(self, dir_name, taskname, filename):
586591
)
587592
d["output"]["optical_absorption_coeff"] = vrun.optical_absorption_coeff
588593

594+
# parse output from response function
595+
if vrun.incar.get("ALGO") == 'CHI':
596+
dielectric = vrun.dielectric
597+
d["output"]["dielectric"] = dict(
598+
energy=dielectric[0], real=dielectric[1], imag=dielectric[2]
599+
)
600+
d["output"]["optical_absorption_coeff"] = vrun.optical_absorption_coeff
601+
589602
return d
590603

591604
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)
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
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={},
43+
**kwargs,
44+
):
45+
"""
46+
FW that calculates frequency dpendent dielectric function within
47+
indenpendent-particle-approxiamtion. A previous ground state calculation
48+
with 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 another calculation with 'ALGO = EXACT, LOPTICS = True'
51+
with variable NBANDS will be performed (MODE = "IPA"). This calculation
52+
can save the 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 polarization FireWork.
59+
static_name (str): Name for the SCF run to be used in PassCalcLoc
60+
if copy_vasp_outputs != True.
61+
mode: 'STATIC', 'IPA', or 'RPA'. Default is 'IPA'
62+
vasp_cmd (str): Command to run vasp.
63+
vasp_input_set (str): string name for the VASP input set (e.g.,
64+
"MPAbsorptionSet").
65+
vasp_input_set_params (dict): Dict of vasp_input_set_kwargs.
66+
db_file (str): Path to file specifying db credentials.
67+
parents (Firework): Parents of this particular Firework. FW or list
68+
of FWS.
69+
vasp_cmd (str): Command to run vasp.
70+
prev_calc_loc (bool or str): If true (default), copies outputs from previous calc. If
71+
a str value, retrieves a previous calculation output by name. If False/None, will create
72+
new SCAN calculation using the provided structure.
73+
prev_calc_dir (str): Path to a previous calculation to copy from
74+
db_file (str): Path to file specifying db credentials.
75+
parents (Firework): Parents of this particular Firework. FW or list of FWs.
76+
vasptodb_kwargs (dict): kwargs to pass to VaspToDb
77+
**kwargs: Other kwargs that are passed to Firework.__init__.
78+
79+
"""
80+
t = []
81+
82+
vasp_input_set_params = vasp_input_set_params or {}
83+
vasptodb_kwargs = vasptodb_kwargs or {}
84+
if "additional_fields" not in vasptodb_kwargs:
85+
vasptodb_kwargs["additional_fields"] = {}
86+
vasptodb_kwargs["additional_fields"]["task_label"] = name
87+
88+
fw_name = "{}-{}-{}".format(
89+
structure.composition.reduced_formula if structure else "unknown", name, mode
90+
)
91+
92+
has_previous_calc = False
93+
94+
# define what wavecars to copy from the previous run
95+
if mode == "STATIC":
96+
wavecars = []
97+
elif mode == "IPA":
98+
wavecars = ["WAVECAR"]
99+
elif mode == "RPA":
100+
wavecars = ["WAVECAR", "WAVEDER"]
101+
else:
102+
raise Exception("Mode has to be from 'STATIC', 'IPA' or 'RPA'. ")
103+
104+
# "IPA" or "RPA" run
105+
if mode == "IPA" or mode == "RPA":
106+
if prev_calc_dir:
107+
# Copy the WAVECAR from previous calc directory
108+
t.append(CopyVaspOutputs(
109+
calc_dir=prev_calc_dir,
110+
contcar_to_poscar=True,
111+
additional_files=wavecars)
112+
)
113+
114+
t.append(
115+
WriteVaspAbsorptionFromPrev(
116+
prev_calc_dir=".",
117+
structure=structure, # The structure will only be useful for the FW name
118+
mode=mode,
119+
copy_wavecar=True,
120+
nbands=None,
121+
nbands_factor=nbands_factor,
122+
reciprocal_density=reciprocal_density,
123+
nkred=nkred,
124+
nedos=nedos,
125+
**vasp_input_set_params
126+
)
127+
)
128+
129+
elif parents:
130+
# Copy the WAVECAR from previous calc location
131+
t.append(
132+
CopyVaspOutputs(
133+
calc_loc=True,
134+
contcar_to_poscar=True,
135+
additional_files=wavecars
136+
)
137+
)
138+
139+
t.append(
140+
WriteVaspAbsorptionFromPrev(
141+
prev_calc_dir=".",
142+
structure=structure, # The structure will only be useful for the FW name
143+
mode=mode,
144+
copy_wavecar=True,
145+
nbands=None,
146+
nbands_factor=nbands_factor,
147+
reciprocal_density=reciprocal_density,
148+
nkred=nkred,
149+
nedos=nedos,
150+
**vasp_input_set_params
151+
)
152+
)
153+
154+
else:
155+
raise ValueError("Must specify previous calculation for {}".format(mode))
156+
157+
# when mode = "static"
158+
elif mode == "STATIC":
159+
if prev_calc_dir:
160+
# Copy only the CONTCAR from previous calc directory
161+
t.append(CopyVaspOutputs(
162+
calc_dir=prev_calc_dir,
163+
contcar_to_poscar=True,
164+
additional_files=wavecars)
165+
)
166+
167+
t.append(WriteVaspStaticFromPrev(user_incar_settings={"LWAVE": "TRUE"}))
168+
169+
elif parents:
170+
# Copy only the CONTCAR from previous calc
171+
t.append(
172+
CopyVaspOutputs(
173+
calc_loc=True,
174+
contcar_to_poscar=True,
175+
additional_files=wavecars
176+
)
177+
)
178+
179+
t.append(WriteVaspStaticFromPrev(user_incar_settings={"LWAVE": "TRUE"}))
180+
181+
elif structure:
182+
vasp_input_set = MPStaticSet(
183+
structure, user_incar_settings={"LWAVE": "TRUE"}
184+
)
185+
t.append(
186+
WriteVaspFromIOSet(structure=structure, vasp_input_set=vasp_input_set)
187+
)
188+
189+
else:
190+
raise ValueError("Must specify structure or previous calculation for Static calculation")
191+
192+
else:
193+
raise ValueEroor("Must specify mode from 'STATIC', 'IPA', or 'RPA'")
194+
195+
# use the 'default' custodian handler group
196+
handler_group = "default"
197+
198+
# Run VASP
199+
t.append(
200+
RunVaspCustodian(
201+
vasp_cmd=vasp_cmd,
202+
auto_npar=">>auto_npar<<",
203+
handler_group=handler_group,
204+
gzip_output=False,
205+
)
206+
)
207+
t.append(PassCalcLocs(name=name))
208+
# Parse
209+
t.append(VaspToDb(db_file=db_file,
210+
additional_fields={
211+
"task_label": structure.composition.reduced_formula + " " + name + " " + mode}))
212+
# zip the output (don't rely on custodian to do it)
213+
t.append(GzipDir())
214+
215+
super().__init__(t, parents=parents, name=fw_name, **kwargs)
216+
217+

0 commit comments

Comments
 (0)