Coverage for /builds/ase/ase/ase/calculators/vasp/create_input.py: 70.60%

619 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-08-02 00:12 +0000

1# fmt: off 

2 

3# Copyright (C) 2008 CSC - Scientific Computing Ltd. 

4"""This module defines an ASE interface to VASP. 

5 

6Developed on the basis of modules by Jussi Enkovaara and John 

7Kitchin. The path of the directory containing the pseudopotential 

8directories (potpaw,potpaw_GGA, potpaw_PBE, ...) should be set 

9by the environmental flag $VASP_PP_PATH. 

10 

11The user should also set the environmental flag $VASP_SCRIPT pointing 

12to a python script looking something like:: 

13 

14 import os 

15 exitcode = os.system('vasp') 

16 

17Alternatively, user can set the environmental flag $VASP_COMMAND pointing 

18to the command use the launch vasp e.g. 'vasp' or 'mpirun -n 16 vasp' 

19 

20http://cms.mpi.univie.ac.at/vasp/ 

21""" 

22 

23import os 

24import shutil 

25import warnings 

26from os.path import isfile, islink, join 

27from typing import List, Sequence, TextIO, Tuple, Union 

28 

29import numpy as np 

30 

31import ase 

32from ase import Atoms 

33from ase.calculators.calculator import kpts2ndarray 

34from ase.calculators.vasp.setups import get_default_setups 

35from ase.config import cfg 

36from ase.io.vasp_parsers.incar_writer import write_incar 

37 

38FLOAT_FORMAT = '5.6f' 

39EXP_FORMAT = '5.2e' 

40 

41 

42def check_ichain(ichain, ediffg, iopt): 

43 ichain_dct = {} 

44 if ichain > 0: 

45 ichain_dct['ibrion'] = 3 

46 ichain_dct['potim'] = 0.0 

47 if iopt is None: 

48 warnings.warn( 

49 'WARNING: optimization is set to LFBGS (IOPT = 1)') 

50 ichain_dct['iopt'] = 1 

51 if ediffg is None or float(ediffg > 0.0): 

52 raise RuntimeError('Please set EDIFFG < 0') 

53 return ichain_dct 

54 

55 

56def set_magmom(ispin, spinpol, atoms, magmom_input, sorting): 

57 """Helps to set the magmom tag in the INCAR file with correct formatting""" 

58 magmom_dct = {} 

59 if magmom_input is not None: 

60 if len(magmom_input) != len(atoms): 

61 msg = ('Expected length of magmom tag to be' 

62 ' {}, i.e. 1 value per atom, but got {}').format( 

63 len(atoms), len(magmom_input)) 

64 raise ValueError(msg) 

65 

66 # Check if user remembered to specify ispin 

67 # note: we do not overwrite ispin if ispin=1 

68 if not ispin: 

69 spinpol = True 

70 # note that ispin is an int key, but for the INCAR it does not 

71 # matter 

72 magmom_dct['ispin'] = 2 

73 magmom = np.array(magmom_input) 

74 magmom = magmom[sorting] 

75 elif (spinpol and atoms.get_initial_magnetic_moments().any()): 

76 # We don't want to write magmoms if they are all 0. 

77 # but we could still be doing a spinpol calculation 

78 if not ispin: 

79 magmom_dct['ispin'] = 2 

80 # Write out initial magnetic moments 

81 magmom = atoms.get_initial_magnetic_moments()[sorting] 

82 # unpack magmom array if three components specified 

83 if magmom.ndim > 1: 

84 magmom = [item for sublist in magmom for item in sublist] 

85 else: 

86 return spinpol, {} 

87 # Compactify the magmom list to symbol order 

88 lst = [[1, magmom[0]]] 

89 for n in range(1, len(magmom)): 

90 if magmom[n] == magmom[n - 1]: 

91 lst[-1][0] += 1 

92 else: 

93 lst.append([1, magmom[n]]) 

94 line = ' '.join(['{:d}*{:.4f}'.format(mom[0], mom[1]) 

95 for mom in lst]) 

96 magmom_dct['magmom'] = line 

97 return spinpol, magmom_dct 

98 

99 

100def set_ldau(ldau_param, luj_params, symbol_count): 

101 """Helps to set the ldau tag in the INCAR file with correct formatting""" 

102 ldau_dct = {} 

103 if ldau_param is None: 

104 ldau_dct['ldau'] = '.TRUE.' 

105 llist = [] 

106 ulist = [] 

107 jlist = [] 

108 for symbol in symbol_count: 

109 # default: No +U 

110 luj = luj_params.get( 

111 symbol[0], 

112 {'L': -1, 'U': 0.0, 'J': 0.0} 

113 ) 

114 llist.append(int(luj['L'])) 

115 ulist.append(f'{luj["U"]:{".3f"}}') 

116 jlist.append(f'{luj["J"]:{".3f"}}') 

117 ldau_dct['ldaul'] = llist 

118 ldau_dct['ldauu'] = ulist 

119 ldau_dct['ldauj'] = jlist 

120 return ldau_dct 

121 

122 

123def _calc_nelect_from_charge( 

124 nelect: Union[float, None], 

125 charge: Union[float, None], 

126 nelect_from_ppp: float, 

127) -> Union[float, None]: 

128 """Determine nelect resulting from a given charge if charge != 0.0. 

129 

130 If nelect is additionally given explicitly, then we need to determine it 

131 even for net charge of 0 to check for conflicts. 

132 

133 """ 

134 if charge is not None and charge != 0.0: 

135 nelect_from_charge = nelect_from_ppp - charge 

136 if nelect and nelect != nelect_from_charge: 

137 raise ValueError( 

138 'incompatible input parameters: ' 

139 f'nelect={nelect}, but charge={charge} ' 

140 f'(neutral nelect is {nelect_from_ppp})' 

141 ) 

142 return nelect_from_charge 

143 return nelect # NELECT explicitly given in INCAR (`None` if not given) 

144 

145 

146def get_pp_setup(setup) -> Tuple[dict, Sequence[int]]: 

147 """ 

148 Get the pseudopotential mapping based on the "setpus" input. 

149 

150 Parameters 

151 ---------- 

152 setup : [str, dict] 

153 The setup to use for the calculation. This can be a string 

154 shortcut, or a dict of atom identities and suffixes. 

155 In the dict version it is also possible to select a base setup 

156 e.g.: {'base': 'minimal', 'Ca': '_sv', 2: 'O_s'} 

157 If the key is an integer, this means an atom index. 

158 For the string version, 'minimal', 'recommended' and 'GW' are 

159 available. The default is 'minimal 

160 

161 Returns 

162 ------- 

163 setups : dict 

164 The setup dictionary, with atom indices as keys and suffixes 

165 as values. 

166 special_setups : list 

167 A list of atom indices that have a special setup. 

168 """ 

169 special_setups = [] 

170 

171 # Avoid mutating the module dictionary, so we use a copy instead 

172 # Note, it is a nested dict, so a regular copy is not enough 

173 setups_defaults = get_default_setups() 

174 

175 # Default to minimal basis 

176 if setup is None: 

177 setup = {'base': 'minimal'} 

178 

179 # String shortcuts are initialised to dict form 

180 elif isinstance(setup, str): 

181 if setup.lower() in setups_defaults.keys(): 

182 setup = {'base': setup} 

183 

184 # Dict form is then queried to add defaults from setups.py. 

185 if 'base' in setup: 

186 setups = setups_defaults[setup['base'].lower()] 

187 else: 

188 setups = {} 

189 

190 # Override defaults with user-defined setups 

191 if setup is not None: 

192 setups.update(setup) 

193 

194 for m in setups: 

195 try: 

196 special_setups.append(int(m)) 

197 except ValueError: 

198 pass 

199 return setups, special_setups 

200 

201 

202def format_kpoints(kpts, atoms, reciprocal=False, gamma=False): 

203 tokens = [] 

204 append = tokens.append 

205 

206 append('KPOINTS created by Atomic Simulation Environment\n') 

207 

208 if isinstance(kpts, dict): 

209 kpts = kpts2ndarray(kpts, atoms=atoms) 

210 reciprocal = True 

211 

212 shape = np.array(kpts).shape 

213 

214 # Wrap scalar in list if necessary 

215 if shape == (): 

216 kpts = [kpts] 

217 shape = (1, ) 

218 

219 if len(shape) == 1: 

220 append('0\n') 

221 if shape == (1, ): 

222 append('Auto\n') 

223 elif gamma: 

224 append('Gamma\n') 

225 else: 

226 append('Monkhorst-Pack\n') 

227 append(' '.join(f'{kpt:d}' for kpt in kpts)) 

228 append('\n0 0 0\n') 

229 elif len(shape) == 2: 

230 append('%i \n' % (len(kpts))) 

231 if reciprocal: 

232 append('Reciprocal\n') 

233 else: 

234 append('Cartesian\n') 

235 for n in range(len(kpts)): 

236 [append('%f ' % kpt) for kpt in kpts[n]] 

237 if shape[1] == 4: 

238 append('\n') 

239 elif shape[1] == 3: 

240 append('1.0 \n') 

241 return ''.join(tokens) 

242 

243 

244# Parameters that can be set in INCAR. The values which are None 

245# are not written and default parameters of VASP are used for them. 

246 

247float_keys = [ 

248 'aexx', # Fraction of exact/DFT exchange 

249 'aggac', # Fraction of gradient correction to correlation 

250 'aggax', # Fraction of gradient correction to exchange 

251 'aldac', # Fraction of LDA correlation energy 

252 'amin', # 

253 'amix', # 

254 'amix_mag', # 

255 'bmix', # tags for mixing 

256 'bmix_mag', # 

257 'cshift', # Complex shift for dielectric tensor calculation (LOPTICS) 

258 'deper', # relative stopping criterion for optimization of eigenvalue 

259 'ebreak', # absolute stopping criterion for optimization of eigenvalues 

260 # (EDIFF/N-BANDS/4) 

261 'efield', # applied electrostatic field 

262 'emax', # energy-range for DOSCAR file 

263 'emin', # 

264 'enaug', # Density cutoff 

265 'encut', # Planewave cutoff 

266 'encutgw', # energy cutoff for response function 

267 'encutfock', # FFT grid in the HF related routines 

268 'hfscreen', # attribute to change from PBE0 to HSE 

269 'kspacing', # determines the number of k-points if the KPOINTS 

270 # file is not present. KSPACING is the smallest 

271 # allowed spacing between k-points in units of 

272 # $\AA$^{-1}$. 

273 'potim', # time-step for ion-motion (fs) 

274 'nelect', # total number of electrons 

275 'param1', # Exchange parameter 

276 'param2', # Exchange parameter 

277 'pomass', # mass of ions in am 

278 'pstress', # add this stress to the stress tensor, and energy E = V * 

279 # pstress 

280 'sigma', # broadening in eV 

281 'smass', # Nose mass-parameter (am) 

282 'spring', # spring constant for NEB 

283 'time', # special control tag 

284 'weimin', # maximum weight for a band to be considered empty 

285 'zab_vdw', # vdW-DF parameter 

286 'zval', # ionic valence 

287 # The next keywords pertain to the VTST add-ons from Graeme Henkelman's 

288 # group at UT Austin 

289 'jacobian', # Weight of lattice to atomic motion 

290 'ddr', # (DdR) dimer separation 

291 'drotmax', # (DRotMax) number of rotation steps per translation step 

292 'dfnmin', # (DFNMin) rotational force below which dimer is not rotated 

293 'dfnmax', # (DFNMax) rotational force below which dimer rotation stops 

294 'sltol', # convergence ratio for minimum eigenvalue 

295 'sdr', # finite difference for setting up Lanczos matrix and step 

296 # size when translating 

297 'maxmove', # Max step for translation for IOPT > 0 

298 'invcurv', # Initial curvature for LBFGS (IOPT = 1) 

299 'timestep', # Dynamical timestep for IOPT = 3 and IOPT = 7 

300 'sdalpha', # Ratio between force and step size for IOPT = 4 

301 # The next keywords pertain to IOPT = 7 (i.e. FIRE) 

302 'ftimemax', # Max time step 

303 'ftimedec', # Factor to dec. dt 

304 'ftimeinc', # Factor to inc. dt 

305 'falpha', # Parameter for velocity damping 

306 'falphadec', # Factor to dec. alpha 

307 'clz', # electron count for core level shift 

308 'vdw_radius', # Cutoff radius for Grimme's DFT-D2 and DFT-D3 and 

309 # Tkatchenko and Scheffler's DFT-TS dispersion corrections 

310 'vdw_scaling', # Global scaling parameter for Grimme's DFT-D2 dispersion 

311 # correction 

312 'vdw_d', # Global damping parameter for Grimme's DFT-D2 and Tkatchenko 

313 # and Scheffler's DFT-TS dispersion corrections 

314 'vdw_cnradius', # Cutoff radius for calculating coordination number in 

315 # Grimme's DFT-D3 dispersion correction 

316 'vdw_s6', # Damping parameter for Grimme's DFT-D2 and DFT-D3 and 

317 # Tkatchenko and Scheffler's DFT-TS dispersion corrections 

318 'vdw_s8', # Damping parameter for Grimme's DFT-D3 dispersion correction 

319 'vdw_sr', # Scaling parameter for Grimme's DFT-D2 and DFT-D3 and 

320 # Tkatchenko and Scheffler's DFT-TS dispersion correction 

321 'vdw_a1', # Damping parameter for Grimme's DFT-D3 dispersion correction 

322 'vdw_a2', # Damping parameter for Grimme's DFT-D3 dispersion correction 

323 'eb_k', # solvent permitivity in Vaspsol 

324 'tau', # surface tension parameter in Vaspsol 

325 'langevin_gamma_l', # Friction for lattice degrees of freedom 

326 'pmass', # Mass for latice degrees of freedom 

327 'bparam', # B parameter for nonlocal VV10 vdW functional 

328 'cparam', # C parameter for nonlocal VV10 vdW functional 

329 'aldax', # Fraction of LDA exchange (for hybrid calculations) 

330 'tebeg', # 

331 'teend', # temperature during run 

332 'andersen_prob', # Probability of collision in Andersen thermostat 

333 'apaco', # Distance cutoff for pair correlation function calc. 

334 'auger_ecblo', # Undocumented parameter for Auger calculations 

335 'auger_edens', # Density of electrons in conduction band 

336 'auger_hdens', # Density of holes in valence band 

337 'auger_efermi', # Fixed Fermi level for Auger calculations 

338 'auger_evbhi', # Upper bound for valence band maximum 

339 'auger_ewidth', # Half-width of energy window function 

340 'auger_occ_fac_eeh', # Undocumented parameter for Auger calculations 

341 'auger_occ_fac_ehh', # Undocumented parameter for Auger calculations 

342 'auger_temp', # Temperature for Auger calculation 

343 'dq', # Finite difference displacement magnitude (NMR) 

344 'avgap', # Average gap (Model GW) 

345 'ch_sigma', # Broadening of the core electron absorption spectrum 

346 'bpotim', # Undocumented Bond-Boost parameter (GH patches) 

347 'qrr', # Undocumented Bond-Boost parameter (GH patches) 

348 'prr', # Undocumented Bond-Boost parameter (GH patches) 

349 'rcut', # Undocumented Bond-Boost parameter (GH patches) 

350 'dvmax', # Undocumented Bond-Boost parameter (GH patches) 

351 'bfgsinvcurv', # Initial curvature for BFGS (GH patches) 

352 'damping', # Damping parameter for LBFGS (GH patches) 

353 'efirst', # Energy of first NEB image (GH patches) 

354 'elast', # Energy of final NEB image (GH patches) 

355 'fmagval', # Force magnitude convergence criterion (GH patches) 

356 'cmbj', # Modified Becke-Johnson MetaGGA c-parameter 

357 'cmbja', # Modified Becke-Johnson MetaGGA alpha-parameter 

358 'cmbjb', # Modified Becke-Johnson MetaGGA beta-parameter 

359 'sigma_nc_k', # Width of ion gaussians (VASPsol) 

360 'sigma_k', # Width of dielectric cavidty (VASPsol) 

361 'nc_k', # Cavity turn-on density (VASPsol) 

362 'lambda_d_k', # Debye screening length (VASPsol) 

363 'ediffsol', # Tolerance for solvation convergence (VASPsol) 

364 'soltemp', # Solvent temperature for isol 2 in Vaspsol++ 

365 'a_k', # Smoothing length for FFT for isol 2 in Vaspsol++ 

366 'r_cav', # Offset for solute surface area for isol 2 in Vaspsol++ 

367 'epsilon_inf', # Bulk optical dielectric for isol 2 in Vaspsol++ 

368 'n_mol', # Solvent density for isol 2 in Vaspsol++ 

369 'p_mol', # Solvent dipole moment for isol 2 in Vaspsol++ 

370 'r_solv', # Solvent radius for isol 2 in Vaspsol++ 

371 'r_diel', # Dielectric radius for isol 2 in Vaspsol++ 

372 'r_b', # Bound charge smearing length for isol 2 in Vaspsol++ 

373 'c_molar', # Electrolyte concentration for isol 2 in Vaspsol++ 

374 'zion', # Electrolyte ion valency for isol 2 in Vaspsol++ 

375 'd_ion', # Packing diameter of electrolyte ions for isol 2 in Vaspsol++ 

376 'r_ion', # Ionic radius of electrolyte ions for isol 2 in Vaspsol++ 

377 'efermi_ref', # Potential vs vacuum for isol 2 in Vaspsol++ 

378 'capacitance_init', # Initial guess for isol 2 in Vaspsol++ 

379 'deg_threshold', # Degeneracy threshold 

380 'omegamin', # Minimum frequency for dense freq. grid 

381 'omegamax', # Maximum frequency for dense freq. grid 

382 'rtime', # Undocumented parameter 

383 'wplasma', # Undocumented parameter 

384 'wplasmai', # Undocumented parameter 

385 'dfield', # Undocumented parameter 

386 'omegatl', # Maximum frequency for coarse freq. grid 

387 'encutgwsoft', # Soft energy cutoff for response kernel 

388 'encutlf', # Undocumented parameter 

389 'scissor', # Scissor correction for GW/BSE calcs 

390 'dimer_dist', # Distance between dimer images 

391 'step_size', # Step size for finite difference in dimer calculation 

392 'step_max', # Maximum step size for dimer calculation 

393 'minrot', # Minimum rotation allowed in dimer calculation 

394 'dummy_mass', # Mass of dummy atom(s?) 

395 'shaketol', # Tolerance for SHAKE algorithm 

396 'shaketolsoft', # Soft tolerance for SHAKE algorithm 

397 'shakesca', # Scaling of each step taken in SHAKE algorithm 

398 'hills_stride', # Undocumented metadynamics parameter 

399 'hills_h', # Height (in eV) of gaussian bias for metadynamics 

400 'hills_w', # Width of gaussian bias for metadynamics 

401 'hills_k', # Force constant coupling dummy&real for metadynamics 

402 'hills_m', # Mass of dummy particle for use in metadynamics 

403 'hills_temperature', # Temp. of dummy particle for metadynamics 

404 'hills_andersen_prob', # Probability of thermostat coll. for metadynamics 

405 'hills_sqq', # Nose-hoover particle mass for metadynamics 

406 'dvvdelta0', # Undocumented parameter 

407 'dvvvnorm0', # Undocumented parameter 

408 'dvvminpotim', # Undocumented parameter 

409 'dvvmaxpotim', # Undocumented parameter 

410 'enchg', # Undocumented charge fitting parameter 

411 'tau0', # Undocumented charge fitting parameter 

412 'encut4o', # Cutoff energy for 4-center integrals (HF) 

413 'param3', # Undocumented HF parameter 

414 'model_eps0', # Undocumented HF parameter 

415 'model_alpha', # Undocumented HF parameter 

416 'qmaxfockae', # Undocumented HF parameter 

417 'hfscreenc', # Range-separated screening length for correlations 

418 'hfrcut', # Cutoff radius for HF potential kernel 

419 'encutae', # Undocumented parameter for all-electron density calc. 

420 'encutsubrotscf', # Undocumented subspace rotation SCF parameter 

421 'enini', # Cutoff energy for wavefunctions (?) 

422 'wc', # Undocumented mixing parameter 

423 'enmax', # Cutoff energy for wavefunctions (?) 

424 'scalee', # Undocumented parameter 

425 'eref', # Reference energy 

426 'epsilon', # Dielectric constant of bulk charged cells 

427 'rcmix', # Mixing parameter for core density in rel. core calcs. 

428 'esemicore', # Energetic lower bound for states considered "semicore" 

429 'external_pressure', # Pressure for NPT calcs., equivalent to PSTRESS 

430 'lj_radius', # Undocumented classical vdW parameter 

431 'lj_epsilon', # Undocumented classical vdW parameter 

432 'lj_sigma', # Undocumented classical vdW parameter 

433 'mbd_beta', # TS MBD vdW correction damping parameter 

434 'scsrad', # Cutoff radius for dipole-dipole interaction tensor in SCS 

435 'hitoler', # Iterative Hirschfeld partitioning tolerance 

436 'lambda', # "Spring constant" for magmom constraint calcs. 

437 'kproj_threshold', # Threshold for k-point projection scheme 

438 'maxpwamp', # Undocumented HF parameter 

439 'vcutoff', # Undocumented parameter 

440 'mdtemp', # Temperature for AIMD 

441 'mdgamma', # Undocumented AIMD parameter 

442 'mdalpha', # Undocumented AIMD parameter 

443 'ofield_kappa', # Bias potential strength for interface pinning method 

444 'ofield_q6_near', # Steinhardt-Nelson Q6 parameters for interface pinning 

445 'ofield_q6_far', # Steinhardt-Nelson Q6 parameters for interface pinning 

446 'ofield_a', # Target order parameter for interface pinning method 

447 'pthreshold', # Don't print timings for routines faster than this value 

448 'qltol', # Eigenvalue tolerance for Lanczos iteration (instanton) 

449 'qdr', # Step size for building Lanczos matrix & CG (instanton) 

450 'qmaxmove', # Max step size (instanton) 

451 'qdt', # Timestep for quickmin minimization (instanton) 

452 'qtpz', # Temperature (instanton) 

453 'qftol', # Tolerance (instanton) 

454 'nupdown', # fix spin moment to specified value 

455] 

456 

457exp_keys = [ 

458 'ediff', # stopping-criterion for electronic upd. 

459 'ediffg', # stopping-criterion for ionic upd. 

460 'symprec', # precession in symmetry routines 

461 # The next keywords pertain to the VTST add-ons from Graeme Henkelman's 

462 # group at UT Austin 

463 'fdstep', # Finite diference step for IOPT = 1 or 2 

464] 

465 

466string_keys = [ 

467 'algo', # algorithm: Normal (Davidson) | Fast | Very_Fast (RMM-DIIS) 

468 'gga', # xc-type: PW PB LM or 91 (LDA if not set) 

469 'metagga', # 

470 'prec', # Precission of calculation (Low, Normal, Accurate) 

471 'system', # name of System 

472 'precfock', # FFT grid in the HF related routines 

473 'radeq', # Which type of radial equations to use for rel. core calcs. 

474 'localized_basis', # Basis to use in CRPA 

475 'proutine', # Select profiling routine 

476 'efermi', # Sets the FERMI level in VASP 6.4.0+ 

477] 

478 

479int_keys = [ 

480 'ialgo', # algorithm: use only 8 (CG) or 48 (RMM-DIIS) 

481 'ibrion', # ionic relaxation: 0-MD 1-quasi-New 2-CG 

482 'icharg', # charge: 0-WAVECAR 1-CHGCAR 2-atom 10-const 

483 'idipol', # monopol/dipol and quadropole corrections 

484 'images', # number of images for NEB calculation 

485 'imix', # specifies density mixing 

486 'iniwav', # initial electr wf. : 0-lowe 1-rand 

487 'isif', # calculate stress and what to relax 

488 'ismear', # part. occupancies: -5 Blochl -4-tet -1-fermi 0-gaus >0 MP 

489 'ispin', # spin-polarized calculation 

490 'istart', # startjob: 0-new 1-cont 2-samecut 

491 'isym', # symmetry: 0-nonsym 1-usesym 2-usePAWsym 

492 'iwavpr', # prediction of wf.: 0-non 1-charg 2-wave 3-comb 

493 'kpar', # k-point parallelization paramater 

494 'ldauprint', # 0-silent, 1-occ. matrix written to OUTCAR, 2-1+pot. matrix 

495 # written 

496 'ldautype', # L(S)DA+U: 1-Liechtenstein 2-Dudarev 4-Liechtenstein(LDAU) 

497 'lmaxmix', # 

498 'lorbit', # create PROOUT 

499 'maxmix', # 

500 'ngx', # FFT mesh for wavefunctions, x 

501 'ngxf', # FFT mesh for charges x 

502 'ngy', # FFT mesh for wavefunctions, y 

503 'ngyf', # FFT mesh for charges y 

504 'ngz', # FFT mesh for wavefunctions, z 

505 'ngzf', # FFT mesh for charges z 

506 'nbands', # Number of bands 

507 'nblk', # blocking for some BLAS calls (Sec. 6.5) 

508 'nbmod', # specifies mode for partial charge calculation 

509 'nelm', # nr. of electronic steps (default 60) 

510 'nelmdl', # nr. of initial electronic steps 

511 'nelmgw', # nr. of self-consistency cycles for GW 

512 'nelmin', 

513 'nfree', # number of steps per DOF when calculting Hessian using 

514 # finite differences 

515 'nkred', # define sub grid of q-points for HF with 

516 # nkredx=nkredy=nkredz 

517 'nkredx', # define sub grid of q-points in x direction for HF 

518 'nkredy', # define sub grid of q-points in y direction for HF 

519 'nkredz', # define sub grid of q-points in z direction for HF 

520 'nomega', # number of frequency points 

521 'nomegar', # number of frequency points on real axis 

522 'npar', # parallelization over bands 

523 'nsim', # evaluate NSIM bands simultaneously if using RMM-DIIS 

524 'nsw', # number of steps for ionic upd. 

525 'nwrite', # verbosity write-flag (how much is written) 

526 'vdwgr', # extra keyword for Andris program 

527 'vdwrn', # extra keyword for Andris program 

528 'voskown', # use Vosko, Wilk, Nusair interpolation 

529 # The next keywords pertain to the VTST add-ons from Graeme Henkelman's 

530 # group at UT Austin 

531 'ichain', # Flag for controlling which method is being used (0=NEB, 

532 # 1=DynMat, 2=Dimer, 3=Lanczos) if ichain > 3, then both 

533 # IBRION and POTIM are automatically set in the INCAR file 

534 'iopt', # Controls which optimizer to use. for iopt > 0, ibrion = 3 

535 # and potim = 0.0 

536 'snl', # Maximum dimentionality of the Lanczos matrix 

537 'lbfgsmem', # Steps saved for inverse Hessian for IOPT = 1 (LBFGS) 

538 'fnmin', # Max iter. before adjusting dt and alpha for IOPT = 7 (FIRE) 

539 'icorelevel', # core level shifts 

540 'clnt', # species index 

541 'cln', # main quantum number of excited core electron 

542 'cll', # l quantum number of excited core electron 

543 'ivdw', # Choose which dispersion correction method to use 

544 'nbandsgw', # Number of bands for GW 

545 'nbandso', # Number of occupied bands for electron-hole treatment 

546 'nbandsv', # Number of virtual bands for electron-hole treatment 

547 'ncore', # Number of cores per band, equal to number of cores divided 

548 # by npar 

549 'mdalgo', # Determines which MD method of Tomas Bucko to use 

550 'nedos', # Number of grid points in DOS 

551 'turbo', # Ewald, 0 = Normal, 1 = PME 

552 'omegapar', # Number of groups for response function calc. 

553 # (Possibly Depricated) Number of groups in real time for 

554 # response function calc. 

555 'taupar', 

556 'ntaupar', # Number of groups in real time for response function calc. 

557 'antires', # How to treat antiresonant part of response function 

558 'magatom', # Index of atom at which to place magnetic field (NMR) 

559 'jatom', # Index of atom at which magnetic moment is evaluated (NMR) 

560 'ichibare', # chi_bare stencil size (NMR) 

561 'nbas', # Undocumented Bond-Boost parameter (GH patches) 

562 'rmds', # Undocumented Bond-Boost parameter (GH patches) 

563 'ilbfgsmem', # Number of histories to store for LBFGS (GH patches) 

564 'vcaimages', # Undocumented parameter (GH patches) 

565 'ntemper', # Undocumented subspace diagonalization param. (GH patches) 

566 'ncshmem', # Share memory between this many cores on each process 

567 'lmaxtau', # Undocumented MetaGGA parameter (prob. max ang.mom. for tau) 

568 'kinter', # Additional finer grid (?) 

569 'ibse', # Type of BSE calculation 

570 'nbseeig', # Number of BSE wfns to write 

571 'naturalo', # Use NATURALO (?) 

572 'nbandsexact', # Undocumented parameter 

573 'nbandsgwlow', # Number of bands for which shifts are calculated 

574 'nbandslf', # Number of bands included in local field effect calc. 

575 'omegagrid', # Undocumented parameter 

576 'telescope', # Undocumented parameter 

577 'maxmem', # Amount of memory to allocate per core in MB 

578 'nelmhf', # Number of iterations for HF part (GW) 

579 'dim', # Undocumented parameter 

580 'nkredlf', # Reduce k-points for local field effects 

581 'nkredlfx', # Reduce k-points for local field effects in X 

582 'nkredlfy', # Reduce k-points for local field effects in Y 

583 'nkredlfz', # Reduce k-points for local field effects in Z 

584 'lmaxmp2', # Undocumented parameter 

585 'switch', # Undocumented dimer parameter 

586 'findiff', # Use forward (1) or central (2) finite difference for dimer 

587 'engine', # Undocumented dimer parameter 

588 'restartcg', # Undocumented dimer parameter 

589 'thermostat', # Deprecated parameter for selecting MD method (use MDALGO) 

590 'scaling', # After how many steps velocities should be rescaled 

591 'shakemaxiter', # Maximum # of iterations in SHAKE algorithm 

592 'equi_regime', # Number of steps to equilibrate for 

593 'hills_bin', # Update metadynamics bias after this many steps 

594 'hills_maxstride', # Undocumented metadynamics parameter 

595 'dvvehistory', # Undocumented parameter 

596 'ipead', # Undocumented parameter 

597 'ngaus', # Undocumented charge fitting parameter 

598 'exxoep', # Undocumented HF parameter 

599 'fourorbit', # Undocumented HF parameter 

600 'model_gw', # Undocumented HF parameter 

601 'hflmax', # Maximum L quantum number for HF calculation 

602 'lmaxfock', # Maximum L quantum number for HF calc. (same as above) 

603 'lmaxfockae', # Undocumented HF parameter 

604 'nmaxfockae', # Undocumented HF parameter 

605 'nblock_fock', # Undocumented HF parameter 

606 'idiot', # Determines which warnings/errors to print 

607 'nrmm', # Number of RMM-DIIS iterations 

608 'mremove', # Undocumented mixing parameter 

609 'inimix', # Undocumented mixing parameter 

610 'mixpre', # Undocumented mixing parameter 

611 'nelmall', # Undocumented parameter 

612 'nblock', # How frequently to write data 

613 'kblock', # How frequently to write data 

614 'npaco', # Undocumented pair correlation function parameter 

615 'lmaxpaw', # Max L quantum number for on-site charge expansion 

616 'irestart', # Undocumented parameter 

617 'nreboot', # Undocumented parameter 

618 'nmin', # Undocumented parameter 

619 'nlspline', # Undocumented parameter 

620 'ispecial', # "Select undocumented and unsupported special features" 

621 'rcrep', # Number of steps between printing relaxed core info 

622 'rcndl', # Wait this many steps before updating core density 

623 'rcstrd', # Relax core density after this many SCF steps 

624 'vdw_idampf', # Select type of damping function for TS vdW 

625 'i_constrained_m', # Select type of magmom. constraint to use 

626 'igpar', # "G parallel" direction for Berry phase calculation 

627 'nppstr', # Number of kpts in "igpar' direction for Berry phase calc. 

628 'nbands_out', # Undocumented QP parameter 

629 'kpts_out', # Undocumented QP parameter 

630 'isp_out', # Undocumented QP parameter 

631 'nomega_out', # Undocumented QP parameter 

632 'maxiter_ft', # Max iterations for sloppy Remez algorithm 

633 'nmaxalt', # Max sample points for alternant in Remez algorithms 

634 'itmaxlsq', # Max iterations in LSQ search algorithm 

635 'ndatalsq', # Number of sample points for LSQ search algorithm 

636 'ncore_in_image1', # Undocumented parameter 

637 'kimages', # Undocumented parameter 

638 'ncores_per_band', # Undocumented parameter 

639 'maxlie', # Max iterations in CRPA diagonalization routine 

640 'ncrpalow', # Undocumented CRPA parameter 

641 'ncrpahigh', # Undocumented CRPA parameter 

642 'nwlow', # Undocumented parameter 

643 'nwhigh', # Undocumented parameter 

644 'nkopt', # Number of k-points to include in Optics calculation 

645 'nkoffopt', # K-point "counter offset" for Optics 

646 'nbvalopt', # Number of valence bands to write in OPTICS file 

647 'nbconopt', # Number of conduction bands to write in OPTICS file 

648 'ch_nedos', # Number dielectric function calculation grid points for XAS 

649 'plevel', # No timings for routines with "level" higher than this 

650 'qnl', # Lanczos matrix size (instanton) 

651 'isol', # vaspsol++ flag 1 linear, 2 nonlinear 

652] 

653 

654bool_keys = [ 

655 'addgrid', # finer grid for augmentation charge density 

656 'kgamma', # The generated kpoint grid (from KSPACING) is either 

657 # centred at the $\Gamma$ 

658 # point (e.g. includes the $\Gamma$ point) 

659 # (KGAMMA=.TRUE.) 

660 'laechg', # write AECCAR0/AECCAR1/AECCAR2 

661 'lasph', # non-spherical contributions to XC energy (and pot for 

662 # VASP.5.X) 

663 'lasync', # overlap communcation with calculations 

664 'lcharg', # 

665 'lcorr', # Harris-correction to forces 

666 'ldau', # L(S)DA+U 

667 'ldiag', # algorithm: perform sub space rotation 

668 'ldipol', # potential correction mode 

669 'lelf', # create ELFCAR 

670 'lepsilon', # enables to calculate and to print the BEC tensors 

671 'lhfcalc', # switch to turn on Hartree Fock calculations 

672 'loptics', # calculate the frequency dependent dielectric matrix 

673 'lpard', # evaluate partial (band and/or k-point) decomposed charge 

674 # density 

675 'lplane', # parallelisation over the FFT grid 

676 'lscalapack', # switch off scaLAPACK 

677 'lscalu', # switch of LU decomposition 

678 'lsepb', # write out partial charge of each band separately? 

679 'lsepk', # write out partial charge of each k-point separately? 

680 'lthomas', # 

681 'luse_vdw', # Invoke vdW-DF implementation by Klimes et. al 

682 'lvdw', # Invoke DFT-D2 method of Grimme 

683 'lvhar', # write Hartree potential to LOCPOT (vasp 5.x) 

684 'lvtot', # create WAVECAR/CHGCAR/LOCPOT 

685 'lwave', # 

686 # The next keywords pertain to the VTST add-ons from Graeme Henkelman's 

687 # group at UT Austin 

688 'lclimb', # Turn on CI-NEB 

689 'ltangentold', # Old central difference tangent 

690 'ldneb', # Turn on modified double nudging 

691 'lnebcell', # Turn on SS-NEB 

692 'lglobal', # Optmize NEB globally for LBFGS (IOPT = 1) 

693 'llineopt', # Use force based line minimizer for translation (IOPT = 1) 

694 'lbeefens', # Switch on print of BEE energy contributions in OUTCAR 

695 'lbeefbas', # Switch off print of all BEEs in OUTCAR 

696 'lcalcpol', # macroscopic polarization (vasp5.2). 'lcalceps' 

697 'lcalceps', # Macroscopic dielectric properties and Born effective charge 

698 # tensors (vasp 5.2) 

699 'lvdw', # Turns on dispersion correction 

700 'lvdw_ewald', # Turns on Ewald summation for Grimme's DFT-D2 and 

701 # Tkatchenko and Scheffler's DFT-TS dispersion correction 

702 'lspectral', # Use the spectral method to calculate independent particle 

703 # polarizability 

704 'lrpa', # Include local field effects on the Hartree level only 

705 'lwannier90', # Switches on the interface between VASP and WANNIER90 

706 'lsorbit', # Enable spin-orbit coupling 

707 'lsol', # turn on solvation for Vaspsol 

708 'lnldiel', # turn on nonlinear dielectric in Vaspsol++ 

709 'lnlion', # turn on nonlinear ionic in Vaspsol++ 

710 'lsol_scf', # turn on solvation in SCF cycle in Vaspsol++ 

711 'lautoscale', # automatically calculate inverse curvature for VTST LBFGS 

712 'interactive', # Enables interactive calculation for VaspInteractive 

713 'lauger', # Perform Auger calculation (Auger) 

714 'lauger_eeh', # Calculate EEH processes (Auger) 

715 'lauger_ehh', # Calculate EHH processes (Auger) 

716 'lauger_collect', # Collect wfns before looping over k-points (Auger) 

717 'lauger_dhdk', # Auto-determine E. window width from E. derivs. (Auger) 

718 'lauger_jit', # Distribute wavefunctions for k1-k4 (Auger) 

719 'orbitalmag', # Enable orbital magnetization (NMR) 

720 'lchimag', # Use linear response for shielding tensor (NMR) 

721 'lwrtcur', # Write response of current to mag. field to file (NMR) 

722 'lnmr_sym_red', # Reduce symmetry for finite difference (NMR) 

723 'lzora', # Use ZORA approximation in linear-response NMR (NMR) 

724 'lbone', # Use B-component in AE one-center terms for LR NMR (NMR) 

725 'lmagbloch', # Use Bloch summations to obtain orbital magnetization (NMR) 

726 'lgauge', # Use gauge transformation for zero moment terms (NMR) 

727 'lbfconst', # Use constant B-field with sawtooth vector potential (NMR) 

728 'nucind', # Use nuclear independent calculation (NMR) 

729 'lnicsall', # Use all grid points for 'nucind' calculation (NMR) 

730 'llraug', # Use two-center corrections for induced B-field (NMR) 

731 'lbbm', # Undocumented Bond-Boost parameter (GH patches) 

732 'lnoncollinear', # Do non-collinear spin polarized calculation 

733 'bfgsdfp', # Undocumented BFGS parameter (GH patches) 

734 'linemin', # Use line minimization (GH patches) 

735 'ldneborg', # Undocumented NEB parameter (GH patches) 

736 'dseed', # Undocumented dimer parameter (GH patches) 

737 'linteract', # Undocumented parameter (GH patches) 

738 'lmpmd', # Undocumented parameter (GH patches) 

739 'ltwodim', # Makes stress tensor two-dimensional (GH patches) 

740 'fmagflag', # Use force magnitude as convergence criterion (GH patches) 

741 'ltemper', # Use subspace diagonalization (?) (GH patches) 

742 'qmflag', # Undocumented FIRE parameter (GH patches) 

743 'lmixtau', # Undocumented MetaGGA parameter 

744 'ljdftx', # Undocumented VASPsol parameter (VASPsol) 

745 'lrhob', # Write the bound charge density (VASPsol) 

746 'lrhoion', # Write the ionic charge density (VASPsol) 

747 'lnabla', # Undocumented parameter 

748 'linterfast', # Interpolate in K using linear response routines 

749 'lvel', # Undocumented parameter 

750 'lrpaforce', # Calculate RPA forces 

751 'lhartree', # Use IP approx. in BSE (testing only) 

752 'ladder', # Use ladder diagrams 

753 'lfxc', # Use approximate ladder diagrams 

754 'lrsrpa', # Undocumented parameter 

755 'lsingles', # Calculate HF singles 

756 'lfermigw', # Iterate Fermi level 

757 'ltcte', # Undocumented parameter 

758 'ltete', # Undocumented parameter 

759 'ltriplet', # Undocumented parameter 

760 'lfxceps', # Undocumented parameter 

761 'lfxheg', # Undocumented parameter 

762 'l2order', # Undocumented parameter 

763 'lmp2lt', # Undocumented parameter 

764 'lgwlf', # Undocumented parameter 

765 'lusew', # Undocumented parameter 

766 'selfenergy', # Undocumented parameter 

767 'oddonlygw', # Avoid gamma point in response function calc. 

768 'evenonlygw', # Avoid even points in response function calc. 

769 'lspectralgw', # More accurate self-energy calculation 

770 'ch_lspec', # Calculate matrix elements btw. core and conduction states 

771 'fletcher_reeves', # Undocumented dimer parameter 

772 'lidm_selective', # Undocumented dimer parameter 

773 'lblueout', # Write output of blue-moon algorithm 

774 'hills_variable_w', # Enable variable-width metadynamics bias 

775 'dvvminus', # Undocumented parameter 

776 'lpead', # Calculate cell-periodic orbital derivs. using finite diff. 

777 'skip_edotp', # Skip updating elec. polarization during scf 

778 'skip_scf', # Skip calculation w/ local field effects 

779 'lchgfit', # Turn on charge fitting 

780 'lgausrc', # Undocumented charge fitting parameter 

781 'lstockholder', # Enable ISA charge fitting (?) 

782 'lsymgrad', # Restore symmetry of gradient (HF) 

783 'lhfone', # Calculate one-center terms (HF) 

784 'lrscor', # Include long-range correlation (HF) 

785 'lrhfcalc', # Include long-range HF (HF) 

786 'lmodelhf', # Model HF calculation (HF) 

787 'shiftred', # Undocumented HF parameter 

788 'hfkident', # Undocumented HF parameter 

789 'oddonly', # Undocumented HF parameter 

790 'evenonly', # Undocumented HF parameter 

791 'lfockaedft', # Undocumented HF parameter 

792 'lsubrot', # Enable subspace rotation diagonalization 

793 'mixfirst', # Mix before diagonalization 

794 'lvcader', # Calculate derivs. w.r.t. VCA parameters 

795 'lcompat', # Enable "full compatibility" 

796 'lmusic', # "Joke" parameter 

797 'ldownsample', # Downsample WAVECAR to fewer k-points 

798 'lscaaware', # Disable ScaLAPACK for some things but not all 

799 'lorbitalreal', # Undocumented parameter 

800 'lmetagga', # Undocumented parameter 

801 'lspiral', # Undocumented parameter 

802 'lzeroz', # Undocumented parameter 

803 'lmono', # Enable "monopole" corrections 

804 'lrelcore', # Perform relaxed core calculation 

805 'lmimicfc', # Mimic frozen-core calcs. for relaxed core calcs. 

806 'lmatchrw', # Match PS partial waves at RWIGS? (otherwise PAW cutoff) 

807 'ladaptelin', # Linearize core state energies to avoid divergences 

808 'lonlysemicore', # Only linearize semi-core state energies 

809 'gga_compat', # Enable backwards-compatible symmetrization of GGA derivs. 

810 'lrelvol', # Undocumented classical vdW parameter 

811 'lj_only', # Undocumented classical vdW parameter 

812 'lvdwscs', # Include self-consistent screening in TS vdW correction 

813 'lcfdm', # Use coupled fluctuating dipoles model for TS vdW 

814 'lvdw_sametype', # Include interactions between atoms of the same type 

815 'lrescaler0', # Rescale damping parameters in SCS vdW correction 

816 'lscsgrad', # Calculate gradients for TS+SCS vdW correction energies 

817 'lvdwexpansion', # Write 2-6 body contribs. to MBD vdW correction energy 

818 'lvdw_relvolone', # Undocumented classical vdW parameter 

819 'lberry', # Enable Berry-phase calculation 

820 'lpade_fit', # Undocumented QP parameter 

821 'lkproj', # Enable projection onto k-points 

822 'l_wr_moments', # Undocumented parameter 

823 'l_wr_density', # Undocumented parameter 

824 'lkotani', # Undocumented parameter 

825 'ldyson', # Undocumented parameter 

826 'laddherm', # Undocumented parameter 

827 'lcrpaplot', # Plot bands used in CRPA response func. calc. 

828 'lplotdis', # Plot disentangled bands in CRPA response func. calc. 

829 'ldisentangle', # Disentangle bands in CRPA 

830 'lweighted', # "Weighted" CRPA approach 

831 'luseorth_lcaos', # Use orthogonalized LCAOs in CRPA 

832 'lfrpa', # Use full RPA in CRPA 

833 'lregularize', # Regularize projectors in CRPA 

834 'ldrude', # Include Drude term in CRPA 

835 'ldmatrix', # Undocumented parameter 

836 'lefg', # Calculate electric field gradient at atomic nuclei 

837 'lhyperfine', # Enable Hyperfine calculation 

838 'lwannier', # Enable Wannier interface 

839 'localize', # Undocumented Wannier parameter 

840 'lintpol_wpot', # Interpolate WPOT for Wannier 

841 'lintpol_orb', # Interpolate orbitals for Wannier 

842 'lintpol_kpath', # Interpolate bandstructure on given kpath for Wannier 

843 'lintpol_kpath_orb', # Interpolate orbitals on given kpath for Wannier 

844 'lread_eigenvalues', # Use Eigenvalues from EIGENVALUES.INT file 

845 'lintpol_velocity', # Interpolate electron velocity for Wannier 

846 'lintpol_conductivity', # Interpolate conductivity for Wannier 

847 'lwannierinterpol', # Undocumented Wannier parameter 

848 'wanproj', # Undocumented Wannier parameter 

849 'lorbmom', # Undocumented LDA+U parameter 

850 'lwannier90_run', # Undocumented WANNIER90 parameter 

851 'lwrite_wanproj', # Write UWAN files for WANNIER90 

852 'lwrite_unk', # Write UNK files for WANNIER90 

853 'lwrite_mmn_amn', # Write MMN and AMN files for WANNIER90 

854 'lread_amn', # Read AMN files instead of recomputing (WANNIER90) 

855 'lrhfatm', # Undocumented HF parameter 

856 'lvpot', # Calculate unscreened potential 

857 'lwpot', # Calculate screened potential 

858 'lwswq', # Undocumented parameter 

859 'pflat', # Only print "flat" timings to OUTCAR 

860 'qifcg', # Use CG instead of quickmin (instanton) 

861 'qdo_ins', # Find instanton 

862 'qdo_pre', # Calculate prefactor (instanton) 

863 # The next keyword pertains to the periodic NBO code of JR Schmidt's group 

864 # at UW-Madison (https://github.com/jrschmidt2/periodic-NBO) 

865 'lnbo', # Enable NBO analysis 

866] 

867 

868list_int_keys = [ 

869 'iband', # bands to calculate partial charge for 

870 'kpuse', # k-point to calculate partial charge for 

871 'ldaul', # DFT+U parameters, overruled by dict key 'ldau_luj' 

872 'random_seed', # List of ints used to seed RNG for advanced MD routines 

873 # (Bucko) 

874 'auger_bmin_eeh', # 4 ints | Various undocumented parameters for Auger 

875 'auger_bmax_eeh', # 4 ints | calculations 

876 'auger_bmin_ehh', # 4 ints | 

877 'auger_bmax_ehh', # 4 ints | 

878 'balist', # nbas ints | Undocumented Bond-Boost parameter (GH patches) 

879 'kpoint_bse', # 4 ints | Undocumented parameter 

880 'nsubsys', # <=3 ints | Last atom # for each of up to 3 thermostats 

881 'vdw_refstate', # ntyp ints | Undocumented classical vdW parameter 

882 'vdw_mbd_size', # 3 ints | Supercell size for TS MBD vdW correction 

883 'nbands_index', # nbands_out ints | Undocumented QP parameter 

884 'kpts_index', # kpts_out ints | Undocumented QP parameter 

885 'isp_index', # isp_out ints | Undocumented QP parameter 

886 'nomega_index', # nomega_out ints | Undocumented QP parameter 

887 'ntarget_states', # nbands ints | Undocumented CRPA parameter 

888 'wanproj_i', # nions ints | Undocumented Wannier parameter 

889 'wanproj_l', # ? ints | Undocumented Wannier parameter 

890] 

891 

892list_bool_keys = [ 

893 'lattice_constraints', # 3 bools | Undocumented advanced MD parameter 

894 'lrctype', # ntyp bools | Enable relaxed-core calc. for these atoms 

895 'lvdw_onecell', # 3 bools | Enable periodicity in A, B, C vector for vdW 

896] 

897 

898list_float_keys = [ 

899 'dipol', # center of cell for dipol 

900 'eint', # energy range to calculate partial charge for 

901 'ferwe', # Fixed band occupation (spin-paired) 

902 'ferdo', # Fixed band occupation (spin-plarized) 

903 'magmom', # initial magnetic moments 

904 'ropt', # number of grid points for non-local proj in real space 

905 'rwigs', # Wigner-Seitz radii 

906 'ldauu', # ldau parameters, has potential to redundant w.r.t. dict 

907 'ldauj', # key 'ldau_luj', but 'ldau_luj' can't be read direct from 

908 # the INCAR (since it needs to know information about atomic 

909 # species. In case of conflict 'ldau_luj' gets written out 

910 # when a calculation is set up 

911 'vdw_c6', # List of floats of C6 parameters (J nm^6 mol^-1) for each 

912 # species (DFT-D2 and DFT-TS) 

913 'vdw_c6au', # List of floats of C6 parameters (a.u.) for each species 

914 # (DFT-TS) 

915 'vdw_r0', # List of floats of R0 parameters (angstroms) for each 

916 # species (DFT-D2 and DFT-TS) 

917 'vdw_r0au', # List of floats of R0 parameters (a.u.) for each species 

918 # (DFT-TS) 

919 'vdw_alpha', # List of floats of free-atomic polarizabilities for each 

920 # species (DFT-TS) 

921 'langevin_gamma', # List of floats for langevin friction coefficients 

922 'auger_emin_eeh', # 4 floats | Various undocumented parameters for Auger 

923 'auger_emax_eeh', # 4 floats | calculations 

924 'auger_emin_ehh', # 4 floats | 

925 'auger_emax_ehh', # 4 floats | 

926 'avecconst', # 3 floats | magnitude of magnetic moment (NMR) 

927 'magdipol', # 3 floats | magnitude of magnetic dipole (NMR) 

928 'bconst', # 3 floats | magnitude of constant magnetic field (NMR) 

929 'magpos', # 3 floats | position for magnetic moment w/ 'nucind' (NMR) 

930 'bext', # 3 floats | Undocumented (probably external magnetic field) 

931 'core_c', # ntyp floats | pseudo-core charge magnitude (VASPsol) 

932 'sigma_rc_k', # ntyp floats | width of pseudo-core gaussians (VASPsol) 

933 'darwinr', # ntypd (?) floats | Undocumented parameter 

934 'darwinv', # ntypd (?) floats | Undocumented parameter 

935 'dummy_k', # ? floats | Force const. connecting dummy atoms to sys. 

936 'dummy_r0', # ? floats | Minimum dist., ang., etc. for dummy atom DOFs 

937 'dummy_positions', # 3 floats | Position of dummy atom(s?) 

938 'psubsys', # <=3 floats | Coll. prob. for each of up to 3 thermostats 

939 'tsubsys', # <=3 floats | Temp. for each of up to 3 thermostats 

940 'increm', # ? floats | Undocumented advanced MD parameter 

941 'value_min', # ? floats | Undocumented advanced MD parameter 

942 'value_max', # ? floats | Undocumented advanced MD parameter 

943 'hills_position', # ? floats | Dummy particle(s) pos. for metadynamics 

944 'hills_velocity', # ? floats | Dummy particle(s) vel. for metadynamics 

945 'spring_k', # ? floats | Spring constant for harmonic constraints 

946 'spring_r0', # ? floats | Spring minima for harmonic constraints 

947 'spring_v0', # ? floats | Initial velocity of harmonic constraints 

948 'hills_wall_lower', # ? floats | Undocumented metadynamics parameter 

949 'hills_wall_upper', # ? floats | Undocumented metadynamics parameter 

950 'efield_pead', # 3 floats | homogeneous electric field for PEAD calc. 

951 'zct', # ? floats | Undocumented charge fitting parameter 

952 'rgaus', # ? floats | Undocumented charge fitting parameter 

953 'hfalpha', # 10 floats | Undocumented HF parameter 

954 'mcalpha', # 10 floats | Undocumented HF parameter 

955 'saxis', # 3 floats | Coordinate for collinear spin calculations 

956 'vca', # ? floats | Atom weight for VCA calculations 

957 'stm', # 7 floats | "range for STM data" 

958 'qspiral', # 3 floats | Undocumented parameter 

959 'external_stress', # 6 floats | Target stress (adds w/ external_pressure) 

960 'm_constr', # 3*nions floats | Local magmom assigned to each spin DOF 

961 'quad_efg', # ntyp floats | Nuclear quadrupole moments 

962 'ngyromag', # ntyp floats | Nuclear gyromagnetic ratios 

963 'rcrhocut', # ntyp floats | Core density cutoff rad. for HF relcore calc 

964 'ofield_k', # 3 floats | Undocumented parameter 

965 'paripot', # ? floats | Undocumented parameter 

966 'smearings', # ? floats | ismear,sigma smearing params to loop over 

967 'wanproj_e', # 2 floats | Undocumented Wannier parameter 

968] 

969 

970special_keys = [ 

971 'lreal', # non-local projectors in real space 

972] 

973 

974dict_keys = [ 

975 'ldau_luj', # dictionary with L(S)DA+U parameters, e.g. {'Fe':{'L':2, 

976 # 'U':4.0, 'J':0.9}, ...} 

977] 

978 

979keys: List[str] = [ 

980 # 'NBLOCK' and KBLOCK inner block; outer block 

981 # 'NPACO' and APACO distance and nr. of slots for P.C. 

982 # 'WEIMIN, EBREAK, DEPER special control tags 

983] 

984 

985 

986class GenerateVaspInput: 

987 # Parameters corresponding to 'xc' settings. This may be modified 

988 # by the user in-between loading calculators.vasp submodule and 

989 # instantiating the calculator object with calculators.vasp.Vasp() 

990 xc_defaults = { 

991 'lda': { 

992 'pp': 'LDA' 

993 }, 

994 # GGAs 

995 'blyp': { # https://www.vasp.at/forum/viewtopic.php?p=17234 

996 'pp': 'PBE', 

997 'gga': 'B5', 

998 'aldax': 1.00, 

999 'aggax': 1.00, 

1000 'aggac': 1.00, 

1001 'aldac': 0.00 

1002 }, 

1003 'pw91': { 

1004 'pp': 'PW91', 

1005 'gga': '91' 

1006 }, 

1007 'pbe': { 

1008 'pp': 'PBE', 

1009 'gga': 'PE' 

1010 }, 

1011 'pbesol': { 

1012 'gga': 'PS' 

1013 }, 

1014 'revpbe': { 

1015 'gga': 'RE' 

1016 }, 

1017 'rpbe': { 

1018 'gga': 'RP' 

1019 }, 

1020 'am05': { 

1021 'gga': 'AM' 

1022 }, 

1023 # Meta-GGAs 

1024 'tpss': { 

1025 'metagga': 'TPSS' 

1026 }, 

1027 'revtpss': { 

1028 'metagga': 'RTPSS' 

1029 }, 

1030 'm06l': { 

1031 'metagga': 'M06L' 

1032 }, 

1033 'ms0': { 

1034 'metagga': 'MS0' 

1035 }, 

1036 'ms1': { 

1037 'metagga': 'MS1' 

1038 }, 

1039 'ms2': { 

1040 'metagga': 'MS2' 

1041 }, 

1042 'scan': { 

1043 'metagga': 'SCAN' 

1044 }, 

1045 'rscan': { 

1046 'metagga': 'RSCAN' 

1047 }, 

1048 'r2scan': { 

1049 'metagga': 'R2SCAN' 

1050 }, 

1051 'scan-rvv10': { 

1052 'metagga': 'SCAN', 

1053 'luse_vdw': True, 

1054 'bparam': 15.7 

1055 }, 

1056 'mbj': { 

1057 # Modified Becke-Johnson 

1058 'metagga': 'MBJ', 

1059 }, 

1060 'tb09': { 

1061 # Alias for MBJ 

1062 'metagga': 'MBJ', 

1063 }, 

1064 # vdW-DFs 

1065 'vdw-df': { 

1066 'gga': 'RE', 

1067 'luse_vdw': True, 

1068 'aggac': 0. 

1069 }, 

1070 'vdw-df-cx': { 

1071 'gga': 'CX', 

1072 'luse_vdw': True, 

1073 'aggac': 0. 

1074 }, 

1075 'vdw-df-cx0p': { 

1076 'gga': 'CX', 

1077 'luse_vdw': True, 

1078 'aggac': 0., 

1079 'lhfcalc': True, 

1080 'aexx': 0.2, 

1081 'aggax': 0.8 

1082 }, 

1083 'optpbe-vdw': { 

1084 'gga': 'OR', 

1085 'luse_vdw': True, 

1086 'aggac': 0.0 

1087 }, 

1088 'optb88-vdw': { 

1089 'gga': 'BO', 

1090 'luse_vdw': True, 

1091 'aggac': 0.0, 

1092 'param1': 1.1 / 6.0, 

1093 'param2': 0.22 

1094 }, 

1095 'optb86b-vdw': { 

1096 'gga': 'MK', 

1097 'luse_vdw': True, 

1098 'aggac': 0.0, 

1099 'param1': 0.1234, 

1100 'param2': 1.0 

1101 }, 

1102 'vdw-df2': { 

1103 'gga': 'ML', 

1104 'luse_vdw': True, 

1105 'aggac': 0.0, 

1106 'zab_vdw': -1.8867 

1107 }, 

1108 'rev-vdw-df2': { 

1109 'gga': 'MK', 

1110 'luse_vdw': True, 

1111 'param1': 0.1234, 

1112 'param2': 0.711357, 

1113 'zab_vdw': -1.8867, 

1114 'aggac': 0.0 

1115 }, 

1116 'beef-vdw': { 

1117 'gga': 'BF', 

1118 'luse_vdw': True, 

1119 'zab_vdw': -1.8867 

1120 }, 

1121 # Hartree-Fock and hybrids 

1122 'hf': { 

1123 'lhfcalc': True, 

1124 'aexx': 1.0, 

1125 'aldac': 0.0, 

1126 'aggac': 0.0 

1127 }, 

1128 'b3lyp': { 

1129 'gga': 'B3', 

1130 'lhfcalc': True, 

1131 'aexx': 0.2, 

1132 'aggax': 0.72, 

1133 'aggac': 0.81, 

1134 'aldac': 0.19 

1135 }, 

1136 'pbe0': { 

1137 'gga': 'PE', 

1138 'lhfcalc': True 

1139 }, 

1140 'hse03': { 

1141 'gga': 'PE', 

1142 'lhfcalc': True, 

1143 'hfscreen': 0.3 

1144 }, 

1145 'hse06': { 

1146 'gga': 'PE', 

1147 'lhfcalc': True, 

1148 'hfscreen': 0.2 

1149 }, 

1150 'hsesol': { 

1151 'gga': 'PS', 

1152 'lhfcalc': True, 

1153 'hfscreen': 0.2 

1154 }, 

1155 # MN-VFM functionals 

1156 'sogga': { 

1157 'gga': 'SA' 

1158 }, 

1159 'sogga11': { 

1160 'gga': 'S1' 

1161 }, 

1162 'sogga11-x': { 

1163 'gga': 'SX', 

1164 'lhfcalc': True, 

1165 'aexx': 0.401 

1166 }, 

1167 'n12': { 

1168 'gga': 'N2' 

1169 }, 

1170 'n12-sx': { 

1171 'gga': 'NX', 

1172 'lhfcalc': True, 

1173 'lhfscreen': 0.2 

1174 }, 

1175 'mn12l': { 

1176 'metagga': 'MN12L' 

1177 }, 

1178 'gam': { 

1179 'gga': 'GA' 

1180 }, 

1181 'mn15l': { 

1182 'metagga': 'MN15L' 

1183 }, 

1184 'hle17': { 

1185 'metagga': 'HLE17' 

1186 }, 

1187 'revm06l': { 

1188 'metagga': 'revM06L' 

1189 }, 

1190 'm06sx': { 

1191 'metagga': 'M06SX', 

1192 'lhfcalc': True, 

1193 'hfscreen': 0.189, 

1194 'aexx': 0.335 

1195 } 

1196 } 

1197 

1198 # environment variable for PP paths 

1199 VASP_PP_PATH = 'VASP_PP_PATH' 

1200 

1201 def __init__(self, restart=None): 

1202 self.float_params = {} 

1203 self.exp_params = {} 

1204 self.string_params = {} 

1205 self.int_params = {} 

1206 self.bool_params = {} 

1207 self.list_bool_params = {} 

1208 self.list_int_params = {} 

1209 self.list_float_params = {} 

1210 self.special_params = {} 

1211 self.dict_params = {} 

1212 self.atoms = None 

1213 for key in float_keys: 

1214 self.float_params[key] = None 

1215 for key in exp_keys: 

1216 self.exp_params[key] = None 

1217 for key in string_keys: 

1218 self.string_params[key] = None 

1219 for key in int_keys: 

1220 self.int_params[key] = None 

1221 for key in bool_keys: 

1222 self.bool_params[key] = None 

1223 for key in list_bool_keys: 

1224 self.list_bool_params[key] = None 

1225 for key in list_int_keys: 

1226 self.list_int_params[key] = None 

1227 for key in list_float_keys: 

1228 self.list_float_params[key] = None 

1229 for key in special_keys: 

1230 self.special_params[key] = None 

1231 for key in dict_keys: 

1232 self.dict_params[key] = None 

1233 

1234 # Initialize internal dictionary of input parameters which are 

1235 # not regular VASP keys 

1236 self.input_params = { 

1237 'xc': None, # Exchange-correlation recipe (e.g. 'B3LYP') 

1238 'pp': None, # Pseudopotential file (e.g. 'PW91') 

1239 'setups': None, # Special setups (e.g pv, sv, ...) 

1240 'txt': '-', # Where to send information 

1241 'kpts': (1, 1, 1), # k-points 

1242 # Option to use gamma-sampling instead of Monkhorst-Pack: 

1243 'gamma': False, 

1244 # number of points between points in band structures: 

1245 'kpts_nintersections': None, 

1246 # Option to write explicit k-points in units 

1247 # of reciprocal lattice vectors: 

1248 'reciprocal': False, 

1249 # Switch to disable writing constraints to POSCAR 

1250 'ignore_constraints': False, 

1251 # Net charge for the whole system; determines nelect if not 0 

1252 'charge': None, 

1253 # Deprecated older parameter which works just like "charge" but 

1254 # with the sign flipped 

1255 'net_charge': None, 

1256 # Custom key-value pairs, written to INCAR with *no* type checking 

1257 'custom': {}, 

1258 } 

1259 # warning message for pw91 

1260 self.pw91_warning_msg =\ 

1261 "The PW91 (potpaw_GGA) pseudopotential set is " \ 

1262 "from 2006 and not recommended for use.\nWe will " \ 

1263 "remove support for it in a future release, " \ 

1264 "and use the current PBE (potpaw_PBE) set instead.\n" \ 

1265 "Note that this still allows for PW91 calculations, " \ 

1266 "since VASP recalculates the exchange-correlation\n" \ 

1267 "energy inside the PAW sphere and corrects the atomic " \ 

1268 "energies given by the POTCAR file." 

1269 

1270 def set_xc_params(self, xc): 

1271 """Set parameters corresponding to XC functional""" 

1272 xc = xc.lower() 

1273 if xc is None: 

1274 pass 

1275 elif xc not in self.xc_defaults: 

1276 xc_allowed = ', '.join(self.xc_defaults.keys()) 

1277 raise ValueError('{} is not supported for xc! Supported xc values' 

1278 'are: {}'.format(xc, xc_allowed)) 

1279 else: 

1280 # print future warning in case pw91 is selected: 

1281 if xc == 'pw91': 

1282 warnings.warn( 

1283 self.pw91_warning_msg, FutureWarning 

1284 ) 

1285 # XC defaults to PBE pseudopotentials 

1286 if 'pp' not in self.xc_defaults[xc]: 

1287 self.set(pp='PBE') 

1288 self.set(**self.xc_defaults[xc]) 

1289 

1290 def set(self, **kwargs): 

1291 

1292 if (('ldauu' in kwargs) and ('ldaul' in kwargs) and ('ldauj' in kwargs) 

1293 and ('ldau_luj' in kwargs)): 

1294 raise NotImplementedError( 

1295 'You can either specify ldaul, ldauu, and ldauj OR ' 

1296 'ldau_luj. ldau_luj is not a VASP keyword. It is a ' 

1297 'dictionary that specifies L, U and J for each ' 

1298 'chemical species in the atoms object. ' 

1299 'For example for a water molecule:' 

1300 '''ldau_luj={'H':{'L':2, 'U':4.0, 'J':0.9}, 

1301 'O':{'L':2, 'U':4.0, 'J':0.9}}''') 

1302 

1303 if 'xc' in kwargs: 

1304 self.set_xc_params(kwargs['xc']) 

1305 for key, value in kwargs.items(): 

1306 if key in self.float_params: 

1307 self.float_params[key] = value 

1308 elif key in self.exp_params: 

1309 self.exp_params[key] = value 

1310 elif key in self.string_params: 

1311 self.string_params[key] = value 

1312 elif key in self.int_params: 

1313 self.int_params[key] = value 

1314 elif key in self.bool_params: 

1315 self.bool_params[key] = value 

1316 elif key in self.list_bool_params: 

1317 self.list_bool_params[key] = value 

1318 elif key in self.list_int_params: 

1319 self.list_int_params[key] = value 

1320 elif key in self.list_float_params: 

1321 self.list_float_params[key] = value 

1322 elif key in self.special_params: 

1323 self.special_params[key] = value 

1324 elif key in self.dict_params: 

1325 self.dict_params[key] = value 

1326 elif key in self.input_params: 

1327 self.input_params[key] = value 

1328 elif isinstance(value, str): 

1329 self.string_params[key] = value 

1330 # `bool` is a subclass of `int` and should be checked earlier. 

1331 # https://docs.python.org/3/c-api/bool.html 

1332 elif isinstance(value, bool): 

1333 self.bool_params[key] = value 

1334 elif isinstance(value, int): 

1335 self.int_params[key] = value 

1336 elif isinstance(value, float): 

1337 self.float_params[key] = value 

1338 elif isinstance(value, list): 

1339 if len(value) == 0: 

1340 msg = f'empty list is given for {key}' 

1341 raise ValueError(msg) 

1342 if isinstance(value[0], bool): 

1343 self.list_bool_params[key] = value 

1344 elif isinstance(value[0], int): 

1345 self.list_int_params[key] = value 

1346 elif isinstance(value[0], float): 

1347 self.list_float_params[key] = value 

1348 else: 

1349 msg = f'cannot handle type of value for {key} = {value!r}' 

1350 raise TypeError(msg) 

1351 else: 

1352 msg = f'cannot handle type of value for {key} = {value!r}' 

1353 raise TypeError(msg) 

1354 

1355 def check_xc(self): 

1356 """Make sure the calculator has functional & pseudopotentials set up 

1357 

1358 If no XC combination, GGA functional or POTCAR type is specified, 

1359 default to PW91. Otherwise, try to guess the desired pseudopotentials. 

1360 """ 

1361 

1362 p = self.input_params 

1363 

1364 # There is no way to correctly guess the desired 

1365 # set of pseudopotentials without 'pp' being set. 

1366 # Usually, 'pp' will be set by 'xc'. 

1367 if 'pp' not in p or p['pp'] is None: 

1368 if self.string_params['gga'] is None: 

1369 p.update({'pp': 'lda'}) 

1370 elif self.string_params['gga'] == '91': 

1371 p.update({'pp': 'pw91'}) 

1372 warnings.warn( 

1373 self.pw91_warning_msg, FutureWarning 

1374 ) 

1375 

1376 elif self.string_params['gga'] == 'PE': 

1377 p.update({'pp': 'pbe'}) 

1378 else: 

1379 raise NotImplementedError( 

1380 "Unable to guess the desired set of pseudopotential" 

1381 "(POTCAR) files. Please do one of the following: \n" 

1382 "1. Use the 'xc' parameter to define your XC functional." 

1383 "These 'recipes' determine the pseudopotential file as " 

1384 "well as setting the INCAR parameters.\n" 

1385 "2. Use the 'gga' settings None (default), 'PE' or '91'; " 

1386 "these correspond to LDA, PBE and PW91 respectively.\n" 

1387 "3. Set the POTCAR explicitly with the 'pp' flag. The " 

1388 "value should be the name of a folder on the VASP_PP_PATH" 

1389 ", and the aliases 'LDA', 'PBE' and 'PW91' are also" 

1390 "accepted.\n") 

1391 

1392 if (p['xc'] is not None and p['xc'].lower() == 'lda' 

1393 and p['pp'].lower() != 'lda'): 

1394 warnings.warn("XC is set to LDA, but PP is set to " 

1395 "{0}. \nThis calculation is using the {0} " 

1396 "POTCAR set. \n Please check that this is " 

1397 "really what you intended!" 

1398 "\n".format(p['pp'].upper())) 

1399 

1400 def _make_sort( 

1401 self, atoms: ase.Atoms, special_setups: Sequence[int] = () 

1402 ) -> Tuple[List[int], List[int]]: 

1403 symbols, _ = count_symbols(atoms, exclude=special_setups) 

1404 

1405 # Create sorting list 

1406 srt = [] # type: List[int] 

1407 srt.extend(special_setups) 

1408 

1409 for symbol in symbols: 

1410 for m, atom in enumerate(atoms): 

1411 if m in special_setups: 

1412 continue 

1413 if atom.symbol == symbol: 

1414 srt.append(m) 

1415 # Create the resorting list 

1416 resrt = list(range(len(srt))) 

1417 for n in range(len(resrt)): 

1418 resrt[srt[n]] = n 

1419 return srt, resrt 

1420 

1421 def _set_spinpol(self, atoms): 

1422 if self.int_params['ispin'] is None: 

1423 self.spinpol = atoms.get_initial_magnetic_moments().any() 

1424 else: 

1425 # VASP runs non-spin-polarized calculations when `ispin=1`, 

1426 # regardless if `magmom` is specified or not. 

1427 self.spinpol = (self.int_params['ispin'] == 2) 

1428 

1429 def _build_pp_list(self, 

1430 atoms, 

1431 setups=None, 

1432 special_setups: Sequence[int] = ()): 

1433 """Build the pseudopotential lists""" 

1434 

1435 p = self.input_params 

1436 

1437 if setups is None: 

1438 setups, special_setups = get_pp_setup(p['setups']) 

1439 

1440 symbols, _ = count_symbols(atoms, exclude=special_setups) 

1441 

1442 # Potpaw folders may be identified by an alias or full name 

1443 for pp_alias, pp_folder in (('lda', 'potpaw'), ('pw91', 'potpaw_GGA'), 

1444 ('pbe', 'potpaw_PBE')): 

1445 if p['pp'].lower() == pp_alias: 

1446 break 

1447 else: 

1448 pp_folder = p['pp'] 

1449 

1450 if self.VASP_PP_PATH in cfg: 

1451 pppaths = cfg[self.VASP_PP_PATH].split(':') 

1452 else: 

1453 pppaths = [] 

1454 ppp_list = [] 

1455 # Setting the pseudopotentials, first special setups and 

1456 # then according to symbols 

1457 for m in special_setups: 

1458 if m in setups: 

1459 special_setup_index = m 

1460 elif str(m) in setups: 

1461 special_setup_index = str(m) # type: ignore[assignment] 

1462 else: 

1463 raise Exception("Having trouble with special setup index {}." 

1464 " Please use an int.".format(m)) 

1465 potcar = join(pp_folder, setups[special_setup_index], 'POTCAR') 

1466 for path in pppaths: 

1467 filename = join(path, potcar) 

1468 

1469 if isfile(filename) or islink(filename): 

1470 ppp_list.append(filename) 

1471 break 

1472 elif isfile(filename + '.Z') or islink(filename + '.Z'): 

1473 ppp_list.append(filename + '.Z') 

1474 break 

1475 else: 

1476 symbol = atoms.symbols[m] 

1477 msg = """Looking for {}. 

1478 No pseudopotential for symbol{} with setup {} """.format( 

1479 potcar, symbol, setups[special_setup_index]) 

1480 raise RuntimeError(msg) 

1481 

1482 for symbol in symbols: 

1483 try: 

1484 potcar = join(pp_folder, symbol + setups[symbol], 'POTCAR') 

1485 except (TypeError, KeyError): 

1486 potcar = join(pp_folder, symbol, 'POTCAR') 

1487 for path in pppaths: 

1488 filename = join(path, potcar) 

1489 

1490 if isfile(filename) or islink(filename): 

1491 ppp_list.append(filename) 

1492 break 

1493 elif isfile(filename + '.Z') or islink(filename + '.Z'): 

1494 ppp_list.append(filename + '.Z') 

1495 break 

1496 else: 

1497 msg = ("""Looking for PP for {} 

1498 The pseudopotentials are expected to be in: 

1499 LDA: $VASP_PP_PATH/potpaw/ 

1500 PBE: $VASP_PP_PATH/potpaw_PBE/ 

1501 PW91: $VASP_PP_PATH/potpaw_GGA/ 

1502 

1503 No pseudopotential for {}!""".format(potcar, symbol)) 

1504 raise RuntimeError(msg) 

1505 return ppp_list 

1506 

1507 def initialize(self, atoms: Atoms) -> None: 

1508 """Initialize a VASP calculation 

1509 

1510 Constructs the POTCAR file (does not actually write it). 

1511 User should specify the PATH 

1512 to the pseudopotentials in VASP_PP_PATH environment variable 

1513 

1514 The pseudopotentials are expected to be in: 

1515 LDA: $VASP_PP_PATH/potpaw/ 

1516 PBE: $VASP_PP_PATH/potpaw_PBE/ 

1517 PW91: $VASP_PP_PATH/potpaw_GGA/ 

1518 

1519 if your pseudopotentials are somewhere else, or named 

1520 differently you may make symlinks at the paths above that 

1521 point to the right place. Alternatively, you may pass the full 

1522 name of a folder on the VASP_PP_PATH to the 'pp' parameter. 

1523 """ 

1524 

1525 self.check_xc() 

1526 self.atoms = atoms 

1527 self.all_symbols = atoms.get_chemical_symbols() 

1528 self.natoms = len(atoms) 

1529 

1530 self._set_spinpol(atoms) 

1531 

1532 setups, special_setups = get_pp_setup(self.input_params['setups']) 

1533 

1534 # Determine the number of atoms of each atomic species 

1535 # sorted after atomic species 

1536 symbols, symbolcount = count_symbols(atoms, exclude=special_setups) 

1537 self.sort, self.resort = self._make_sort(atoms, 

1538 special_setups=special_setups) 

1539 

1540 self.atoms_sorted = atoms[self.sort] 

1541 

1542 # Check if the necessary POTCAR files exists and 

1543 # create a list of their paths. 

1544 atomtypes = atoms.get_chemical_symbols() 

1545 self.symbol_count: list[tuple[str, int]] = [] 

1546 for m in special_setups: 

1547 self.symbol_count.append((atomtypes[m], 1)) 

1548 for s in symbols: 

1549 self.symbol_count.append((s, symbolcount[s])) 

1550 

1551 # create pseudopotential list 

1552 self.ppp_list = self._build_pp_list( 

1553 atoms, 

1554 setups=setups, 

1555 special_setups=special_setups, 

1556 ) 

1557 

1558 self.converged = None 

1559 self.setups_changed = None 

1560 

1561 def default_nelect_from_ppp(self) -> float: 

1562 """ Get default number of electrons from ppp_list and symbol_count 

1563 

1564 "Default" here means that the resulting cell would be neutral. 

1565 """ 

1566 symbol_valences: list[tuple[str, float]] = [] 

1567 for filename in self.ppp_list: 

1568 with open_potcar(filename=filename) as ppp_file: 

1569 r = read_potcar_numbers_of_electrons(ppp_file) 

1570 symbol_valences.extend(r) 

1571 assert len(self.symbol_count) == len(symbol_valences) 

1572 default_nelect = 0.0 

1573 for ((symbol1, count), 

1574 (symbol2, valence)) in zip(self.symbol_count, symbol_valences): 

1575 assert symbol1 == symbol2 

1576 default_nelect += count * valence 

1577 return default_nelect 

1578 

1579 def write_input(self, atoms, directory='./'): 

1580 from ase.io.vasp import write_vasp 

1581 write_vasp(join(directory, 'POSCAR'), 

1582 self.atoms_sorted, 

1583 symbol_count=self.symbol_count, 

1584 ignore_constraints=self.input_params['ignore_constraints']) 

1585 self.write_incar(atoms, directory=directory) 

1586 self.write_potcar(directory=directory) 

1587 self.write_kpoints(atoms=atoms, directory=directory) 

1588 self.write_sort_file(directory=directory) 

1589 self.copy_vdw_kernel(directory=directory) 

1590 

1591 def copy_vdw_kernel(self, directory='./'): 

1592 """Method to copy the vdw_kernel.bindat file. 

1593 Set ASE_VASP_VDW environment variable to the vdw_kernel.bindat 

1594 folder location. Checks if LUSE_VDW is enabled, and if no location 

1595 for the vdW kernel is specified, a warning is issued.""" 

1596 

1597 vdw_env = 'ASE_VASP_VDW' 

1598 kernel = 'vdw_kernel.bindat' 

1599 dst = os.path.join(directory, kernel) 

1600 

1601 # No need to copy the file again 

1602 if isfile(dst): 

1603 return 

1604 

1605 if self.bool_params['luse_vdw']: 

1606 src = None 

1607 if vdw_env in cfg: 

1608 src = os.path.join(cfg[vdw_env], kernel) 

1609 

1610 if not src or not isfile(src): 

1611 warnings.warn( 

1612 ('vdW has been enabled, however no' 

1613 ' location for the {} file' 

1614 ' has been specified.' 

1615 ' Set {} environment variable to' 

1616 ' copy the vdW kernel.').format(kernel, vdw_env)) 

1617 else: 

1618 shutil.copyfile(src, dst) 

1619 

1620 def clean(self): 

1621 """Method which cleans up after a calculation. 

1622 

1623 The default files generated by Vasp will be deleted IF this 

1624 method is called. 

1625 

1626 """ 

1627 files = [ 

1628 'CHG', 'CHGCAR', 'POSCAR', 'INCAR', 'CONTCAR', 'DOSCAR', 

1629 'EIGENVAL', 'IBZKPT', 'KPOINTS', 'OSZICAR', 'OUTCAR', 'PCDAT', 

1630 'POTCAR', 'vasprun.xml', 'WAVECAR', 'XDATCAR', 'PROCAR', 

1631 'ase-sort.dat', 'LOCPOT', 'AECCAR0', 'AECCAR1', 'AECCAR2' 

1632 ] 

1633 for f in files: 

1634 try: 

1635 os.remove(f) 

1636 except OSError: 

1637 pass 

1638 

1639 def write_incar(self, atoms, directory='./', **kwargs): 

1640 """Writes the INCAR file.""" 

1641 incar_params = {} 

1642 

1643 # float params 

1644 float_dct = { 

1645 key: f'{val:{FLOAT_FORMAT}}' 

1646 for key, val in self.float_params.items() 

1647 if val is not None 

1648 } 

1649 

1650 if 'charge' in self.input_params and self.input_params[ 

1651 'charge'] is not None: 

1652 nelect_val = _calc_nelect_from_charge( 

1653 self.float_params['nelect'], 

1654 self.input_params['charge'], 

1655 self.default_nelect_from_ppp()) 

1656 if nelect_val: 

1657 float_dct['nelect'] = f'{nelect_val:{FLOAT_FORMAT}}' 

1658 incar_params.update(float_dct) 

1659 

1660 # exp params 

1661 exp_dct = { 

1662 key: f'{val:{EXP_FORMAT}}' 

1663 for key, val in self.exp_params.items() 

1664 if val is not None 

1665 } 

1666 incar_params.update(exp_dct) 

1667 

1668 # string_params 

1669 string_dct = { 

1670 key: val for key, val in self.string_params.items() if val is not 

1671 None 

1672 } 

1673 incar_params.update(string_dct) 

1674 

1675 # int params 

1676 int_dct = { 

1677 key: val for key, val in self.int_params.items() if val is not None 

1678 } 

1679 if 'ichain' in int_dct.keys(): 

1680 ichain_dict = check_ichain( 

1681 ichain=int_dct['ichain'], 

1682 ediffg=self.exp_params.get('ediffg', None), 

1683 iopt=int_dct.get('iopt', None), 

1684 ) 

1685 int_dct.update(ichain_dict) 

1686 incar_params.update(int_dct) 

1687 

1688 # list_bool_params 

1689 bool_dct = { 

1690 key: val 

1691 for key, val in self.list_bool_params.items() 

1692 if val is not None 

1693 } 

1694 for key, val in bool_dct.items(): 

1695 bool_dct[key] = [_to_vasp_bool(x) for x in val] 

1696 incar_params.update(bool_dct) 

1697 

1698 # list_int_params 

1699 int_dct = { 

1700 key: val 

1701 for key, val in self.list_int_params.items() 

1702 if val is not None 

1703 } 

1704 if 'ldaul' in int_dct.keys() and self.dict_params[ 

1705 'ldau_luj'] is not None: 

1706 del int_dct['ldaul'] 

1707 incar_params.update(int_dct) 

1708 

1709 # list_float_params 

1710 float_dct = { 

1711 key: val 

1712 for key, val in self.list_float_params.items() 

1713 if val is not None 

1714 } 

1715 if 'ldauu' in float_dct.keys() and self.dict_params[ 

1716 'ldau_luj'] is not None: 

1717 del float_dct['ldauu'] 

1718 if 'ldauj' in float_dct.keys() and self.dict_params[ 

1719 'ldau_luj'] is not None: 

1720 del float_dct['ldauj'] 

1721 incar_params.update(float_dct) 

1722 

1723 # bool params 

1724 bool_dct = { 

1725 key: _to_vasp_bool(val) 

1726 for key, val in self.bool_params.items() 

1727 if val is not None 

1728 } 

1729 incar_params.update(bool_dct) 

1730 

1731 # special params 

1732 special_dct = { 

1733 key: val for key, val in self.special_params.items() if val is not 

1734 None 

1735 } 

1736 if 'lreal' in special_dct.keys(): 

1737 if isinstance(special_dct['lreal'], bool): 

1738 special_dct['lreal'] = _to_vasp_bool(special_dct['lreal']) 

1739 incar_params.update(special_dct) 

1740 

1741 # dict params 

1742 dict_dct = { 

1743 key: val for key, val in self.dict_params.items() if val is not None 

1744 } 

1745 if 'ldau_luj' in dict_dct.keys(): 

1746 ldau_dict = set_ldau( 

1747 ldau_param=self.bool_params['ldau'], 

1748 luj_params=dict_dct['ldau_luj'], 

1749 symbol_count=self.symbol_count) 

1750 dict_dct.update(ldau_dict) 

1751 del dict_dct['ldau_luj'] 

1752 incar_params.update(dict_dct) 

1753 

1754 # set magmom based on input or initial atoms object 

1755 spinpol, magmom_dct = set_magmom( 

1756 atoms=atoms, 

1757 ispin=self.int_params['ispin'], 

1758 spinpol=self.spinpol, 

1759 magmom_input=float_dct.get('magmom', None), 

1760 sorting=self.sort, 

1761 ) 

1762 self.spinpol = spinpol 

1763 incar_params.update(magmom_dct) 

1764 

1765 # Custom key-value pairs, which receive no formatting 

1766 # Use the comment "# <Custom ASE key>" to denote such 

1767 # a custom key-value pair, as we cannot otherwise 

1768 # reliably and easily identify such non-standard entries 

1769 

1770 cust_dict = { 

1771 key: str(val) + ' # <Custom ASE key>' 

1772 for key, val in self.input_params['custom'].items() 

1773 if val is not None 

1774 } 

1775 incar_params.update(cust_dict) 

1776 

1777 write_incar(directory=directory, parameters=incar_params) 

1778 

1779 def write_kpoints(self, atoms=None, directory='./', **kwargs): 

1780 """Writes the KPOINTS file.""" 

1781 

1782 if atoms is None: 

1783 atoms = self.atoms 

1784 

1785 # Don't write anything if KSPACING is being used 

1786 if self.float_params['kspacing'] is not None: 

1787 if self.float_params['kspacing'] > 0: 

1788 return 

1789 else: 

1790 raise ValueError("KSPACING value {} is not allowable. " 

1791 "Please use None or a positive number." 

1792 "".format(self.float_params['kspacing'])) 

1793 if self.input_params['kpts'] is None: 

1794 return 

1795 

1796 kpointstring = format_kpoints( 

1797 kpts=self.input_params['kpts'], 

1798 atoms=atoms, 

1799 reciprocal=self.input_params['reciprocal'], 

1800 gamma=self.input_params['gamma']) 

1801 with open(join(directory, 'KPOINTS'), 'w') as kpoints: 

1802 kpoints.write(kpointstring) 

1803 

1804 def write_potcar(self, suffix="", directory='./'): 

1805 """Writes the POTCAR file.""" 

1806 

1807 with open(join(directory, 'POTCAR' + suffix), 'w') as potfile: 

1808 for filename in self.ppp_list: 

1809 with open_potcar(filename=filename) as ppp_file: 

1810 for line in ppp_file: 

1811 potfile.write(line) 

1812 

1813 def write_sort_file(self, directory='./'): 

1814 """Writes a sortings file. 

1815 

1816 This file contains information about how the atoms are sorted in 

1817 the first column and how they should be resorted in the second 

1818 column. It is used for restart purposes to get sorting right 

1819 when reading in an old calculation to ASE.""" 

1820 

1821 with open(join(directory, 'ase-sort.dat'), 'w') as fd: 

1822 for n in range(len(self.sort)): 

1823 fd.write('%5i %5i \n' % (self.sort[n], self.resort[n])) 

1824 

1825 # The below functions are used to restart a calculation 

1826 

1827 def read_incar(self, filename): 

1828 """Method that imports settings from INCAR file. 

1829 

1830 Typically named INCAR.""" 

1831 

1832 self.spinpol = False 

1833 with open(filename) as fd: 

1834 lines = fd.readlines() 

1835 

1836 for line in lines: 

1837 try: 

1838 # Make multiplication, comments, and parameters easier to spot 

1839 line = line.replace("*", " * ") 

1840 line = line.replace("=", " = ") 

1841 line = line.replace("#", "# ") 

1842 data = line.split() 

1843 # Skip empty and commented lines. 

1844 if len(data) == 0: 

1845 continue 

1846 elif data[0][0] in ['#', '!']: 

1847 continue 

1848 key = data[0].lower() 

1849 if '<Custom ASE key>' in line: 

1850 # This key was added with custom key-value pair formatting. 

1851 # Unconditionally add it, no type checking 

1852 # Get value between "=" and the comment, e.g. 

1853 # key = 1 2 3 # <Custom ASE key> 

1854 # value should be '1 2 3' 

1855 

1856 # Split at first occurence of "=" 

1857 value = line.split('=', 1)[1] 

1858 # First "#" denotes beginning of comment 

1859 # Add everything before comment as a string to custom dict 

1860 value = value.split('#', 1)[0].strip() 

1861 self.input_params['custom'][key] = value 

1862 elif key in float_keys: 

1863 self.float_params[key] = float(data[2]) 

1864 elif key in exp_keys: 

1865 self.exp_params[key] = float(data[2]) 

1866 elif key in string_keys: 

1867 self.string_params[key] = str(data[2]) 

1868 elif key in int_keys: 

1869 if key == 'ispin': 

1870 # JRK added. not sure why we would want to leave ispin 

1871 # out 

1872 self.int_params[key] = int(data[2]) 

1873 if int(data[2]) == 2: 

1874 self.spinpol = True 

1875 else: 

1876 self.int_params[key] = int(data[2]) 

1877 elif key in bool_keys: 

1878 val_char = data[2].lower().replace('.', '', 1) 

1879 if val_char.startswith('t'): 

1880 self.bool_params[key] = True 

1881 elif val_char.startswith('f'): 

1882 self.bool_params[key] = False 

1883 else: 

1884 raise ValueError(f'Invalid value "{data[2]}" for bool ' 

1885 f'key "{key}"') 

1886 

1887 elif key in list_bool_keys: 

1888 self.list_bool_params[key] = [ 

1889 _from_vasp_bool(x) 

1890 for x in _args_without_comment(data[2:]) 

1891 ] 

1892 

1893 elif key in list_int_keys: 

1894 self.list_int_params[key] = [ 

1895 int(x) for x in _args_without_comment(data[2:]) 

1896 ] 

1897 

1898 elif key in list_float_keys: 

1899 if key == 'magmom': 

1900 lst = [] 

1901 i = 2 

1902 while i < len(data): 

1903 if data[i] in ["#", "!"]: 

1904 break 

1905 if data[i] == "*": 

1906 b = lst.pop() 

1907 i += 1 

1908 for _ in range(int(b)): 

1909 lst.append(float(data[i])) 

1910 else: 

1911 lst.append(float(data[i])) 

1912 i += 1 

1913 self.list_float_params['magmom'] = lst 

1914 lst = np.array(lst) 

1915 if self.atoms is not None: 

1916 self.atoms.set_initial_magnetic_moments( 

1917 lst[self.resort]) 

1918 else: 

1919 data = _args_without_comment(data) 

1920 self.list_float_params[key] = [ 

1921 float(x) for x in data[2:] 

1922 ] 

1923 elif key in special_keys: 

1924 if key == 'lreal': 

1925 val_char = data[2].lower().replace('.', '', 1) 

1926 if val_char.startswith('t'): 

1927 self.bool_params[key] = True 

1928 elif val_char.startswith('f'): 

1929 self.bool_params[key] = False 

1930 else: 

1931 self.special_params[key] = data[2] 

1932 

1933 # non-registered keys 

1934 elif data[2].lower() in {'t', 'true', '.true.'}: 

1935 self.bool_params[key] = True 

1936 elif data[2].lower() in {'f', 'false', '.false.'}: 

1937 self.bool_params[key] = False 

1938 elif data[2].isdigit(): 

1939 self.int_params[key] = int(data[2]) 

1940 else: 

1941 try: 

1942 self.float_params[key] = float(data[2]) 

1943 except ValueError: 

1944 self.string_params[key] = data[2] 

1945 

1946 except KeyError as exc: 

1947 raise KeyError( 

1948 f'Keyword "{key}" in INCAR is not known by calculator.' 

1949 ) from exc 

1950 except IndexError as exc: 

1951 raise IndexError( 

1952 f'Value missing for keyword "{key}".' 

1953 ) from exc 

1954 

1955 def read_kpoints(self, filename): 

1956 """Read kpoints file, typically named KPOINTS.""" 

1957 # If we used VASP builtin kspacing, 

1958 if self.float_params['kspacing'] is not None: 

1959 # Don't update kpts array 

1960 return 

1961 

1962 with open(filename) as fd: 

1963 lines = fd.readlines() 

1964 

1965 ktype = lines[2].split()[0].lower()[0] 

1966 if ktype in ['g', 'm', 'a']: 

1967 if ktype == 'g': 

1968 self.set(gamma=True) 

1969 kpts = np.array([int(lines[3].split()[i]) for i in range(3)]) 

1970 elif ktype == 'a': 

1971 kpts = np.array([int(lines[3].split()[i]) for i in range(1)]) 

1972 elif ktype == 'm': 

1973 kpts = np.array([int(lines[3].split()[i]) for i in range(3)]) 

1974 else: 

1975 if ktype in ['c', 'k']: 

1976 self.set(reciprocal=False) 

1977 else: 

1978 self.set(reciprocal=True) 

1979 kpts = np.array( 

1980 [list(map(float, line.split())) for line in lines[3:]]) 

1981 self.set(kpts=kpts) 

1982 

1983 def read_potcar(self, filename): 

1984 """ Read the pseudopotential XC functional from POTCAR file. 

1985 """ 

1986 

1987 # Search for key 'LEXCH' in POTCAR 

1988 xc_flag = None 

1989 with open(filename) as fd: 

1990 for line in fd: 

1991 key = line.split()[0].upper() 

1992 if key == 'LEXCH': 

1993 xc_flag = line.split()[-1].upper() 

1994 break 

1995 

1996 if xc_flag is None: 

1997 raise ValueError('LEXCH flag not found in POTCAR file.') 

1998 

1999 # Values of parameter LEXCH and corresponding XC-functional 

2000 xc_dict = {'PE': 'PBE', '91': 'PW91', 'CA': 'LDA'} 

2001 

2002 if xc_flag not in xc_dict.keys(): 

2003 raise ValueError('Unknown xc-functional flag found in POTCAR,' 

2004 ' LEXCH=%s' % xc_flag) 

2005 

2006 self.input_params['pp'] = xc_dict[xc_flag] 

2007 

2008 def todict(self): 

2009 """Returns a dictionary of all parameters 

2010 that can be used to construct a new calculator object""" 

2011 dict_list = [ 

2012 'float_params', 'exp_params', 'string_params', 'int_params', 

2013 'bool_params', 'list_bool_params', 'list_int_params', 

2014 'list_float_params', 'special_params', 'dict_params', 

2015 'input_params' 

2016 ] 

2017 dct = {} 

2018 for item in dict_list: 

2019 dct.update(getattr(self, item)) 

2020 dct = {key: value for key, value in dct.items() if value is not None} 

2021 return dct 

2022 

2023 

2024def _args_without_comment(data, marks=['!', '#']): 

2025 """Check split arguments list for a comment, return data up to marker 

2026 

2027 INCAR reader splits list arguments on spaces and leaves comment markers as 

2028 individual items. This function returns only the data portion of the list. 

2029 

2030 """ 

2031 comment_locs = [data.index(mark) for mark in marks if mark in data] 

2032 if comment_locs == []: 

2033 return data 

2034 else: 

2035 return data[:min(comment_locs)] 

2036 

2037 

2038def _from_vasp_bool(x): 

2039 """Cast vasp boolean to Python bool 

2040 

2041 VASP files sometimes use T or F as shorthand for the preferred Boolean 

2042 notation .TRUE. or .FALSE. As capitalisation is pretty inconsistent in 

2043 practice, we allow all cases to be cast to a Python bool. 

2044 

2045 """ 

2046 assert isinstance(x, str) 

2047 if x.lower() == '.true.' or x.lower() == 't': 

2048 return True 

2049 elif x.lower() == '.false.' or x.lower() == 'f': 

2050 return False 

2051 else: 

2052 raise ValueError(f'Value "{x}" not recognized as bool') 

2053 

2054 

2055def _to_vasp_bool(x): 

2056 """Convert Python boolean to string for VASP input 

2057 

2058 In case the value was modified to a string already, appropriate strings 

2059 will also be accepted and cast to a standard .TRUE. / .FALSE. format. 

2060 

2061 """ 

2062 if isinstance(x, str): 

2063 if x.lower() in ('.true.', 't'): 

2064 x = True 

2065 elif x.lower() in ('.false.', 'f'): 

2066 x = False 

2067 else: 

2068 raise ValueError('"%s" not recognised as VASP Boolean') 

2069 assert isinstance(x, bool) 

2070 if x: 

2071 return '.TRUE.' 

2072 else: 

2073 return '.FALSE.' 

2074 

2075 

2076def open_potcar(filename): 

2077 """ Open POTCAR file with transparent decompression if it's an archive (.Z) 

2078 """ 

2079 import gzip 

2080 if filename.endswith('R'): 

2081 return open(filename) 

2082 elif filename.endswith('.Z'): 

2083 return gzip.open(filename) 

2084 else: 

2085 raise ValueError(f'Invalid POTCAR filename: "{filename}"') 

2086 

2087 

2088def read_potcar_numbers_of_electrons(fd: TextIO, /) -> list[tuple[str, float]]: 

2089 """Read number of valence electrons for each atomtype from a POTCAR file. 

2090 

2091 Returns 

2092 ------- 

2093 list[tuple[str, float]] 

2094 List of (atomic symbol, number of valence electrons). 

2095 

2096 """ 

2097 nelect: list[tuple[str, float]] = [] 

2098 lines = fd.readlines() 

2099 for n, line in enumerate(lines): 

2100 if 'TITEL' in line: 

2101 symbol = line.split('=')[1].split()[1].split('_')[0].strip() 

2102 linep4 = lines[n + 4] 

2103 zval = float(linep4.split(';')[1].split('=')[1].split()[0].strip()) 

2104 nelect.append((symbol, zval)) 

2105 return nelect 

2106 

2107 

2108def count_symbols(atoms: Atoms, exclude=()) -> tuple[list[str], dict[str, int]]: 

2109 """Count symbols in atoms object, excluding a set of indices 

2110 

2111 Parameters: 

2112 atoms: Atoms object to be grouped 

2113 exclude: List of indices to be excluded from the counting 

2114 

2115 Returns: 

2116 Tuple of (symbols, symbolcount) 

2117 symbols: The unique symbols in the included list 

2118 symbolscount: Count of symbols in the included list 

2119 

2120 Example: 

2121 

2122 >>> from ase.build import bulk 

2123 >>> atoms = bulk('NaCl', crystalstructure='rocksalt', a=4.1, cubic=True) 

2124 >>> count_symbols(atoms) 

2125 (['Na', 'Cl'], {'Na': 4, 'Cl': 4}) 

2126 >>> count_symbols(atoms, exclude=(1, 2, 3)) 

2127 (['Na', 'Cl'], {'Na': 3, 'Cl': 2}) 

2128 """ 

2129 symbols: list[str] = [] 

2130 symbolcount: dict[str, int] = {} 

2131 for m, symbol in enumerate(atoms.symbols): 

2132 if m in exclude: 

2133 continue 

2134 if symbol not in symbols: 

2135 symbols.append(symbol) 

2136 symbolcount[symbol] = 1 

2137 else: 

2138 symbolcount[symbol] += 1 

2139 return symbols, symbolcount