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