|
| 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