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

584 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-12-10 11:04 +0000

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

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

3 

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

5Kitchin. The path of the directory containing the pseudopotential 

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

7by the environmental flag $VASP_PP_PATH. 

8 

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

10to a python script looking something like:: 

11 

12 import os 

13 exitcode = os.system('vasp') 

14 

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

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

17 

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

19""" 

20 

21import os 

22import shutil 

23import warnings 

24from os.path import isfile, islink, join 

25from typing import List, Sequence, Tuple 

26 

27import numpy as np 

28 

29import ase 

30from ase.calculators.calculator import kpts2ndarray 

31from ase.calculators.vasp.setups import get_default_setups 

32from ase.config import cfg 

33from ase.io.vasp_parsers.incar_writer import write_incar 

34 

35FLOAT_FORMAT = '5.6f' 

36EXP_FORMAT = '5.2e' 

37 

38 

39def check_ichain(ichain, ediffg, iopt): 

40 ichain_dct = {} 

41 if ichain > 0: 

42 ichain_dct['ibrion'] = 1 

43 ichain_dct['potim'] = 0.0 

44 if iopt is None: 

45 warnings.warn( 

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

47 ichain_dct['iopt'] = 1 

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

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

50 return ichain_dct 

51 

52 

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

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

55 magmom_dct = {} 

56 if magmom_input is not None: 

57 if not len(magmom_input) == len(atoms): 

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

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

60 len(atoms), len(magmom_input)) 

61 raise ValueError(msg) 

62 

63 # Check if user remembered to specify ispin 

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

65 if not ispin: 

66 spinpol = True 

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

68 # matter 

69 magmom_dct['ispin'] = 2 

70 magmom = np.array(magmom_input) 

71 magmom = magmom[sorting] 

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

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

74 # but we could still be doing a spinpol calculation 

75 if not ispin: 

76 magmom_dct['ispin'] = 2 

77 # Write out initial magnetic moments 

78 magmom = atoms.get_initial_magnetic_moments()[sorting] 

79 # unpack magmom array if three components specified 

80 if magmom.ndim > 1: 

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

82 else: 

83 return spinpol, {} 

84 # Compactify the magmom list to symbol order 

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

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

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

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

89 else: 

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

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

92 for mom in lst]) 

93 magmom_dct['magmom'] = line 

94 return spinpol, magmom_dct 

95 

96 

97def set_ldau(ldau_param, luj_params, symbol_count): 

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

99 ldau_dct = {} 

100 if ldau_param is None: 

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

102 llist = [] 

103 ulist = [] 

104 jlist = [] 

105 for symbol in symbol_count: 

106 # default: No +U 

107 luj = luj_params.get( 

108 symbol[0], 

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

110 ) 

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

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

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

114 ldau_dct['ldaul'] = llist 

115 ldau_dct['ldauu'] = ulist 

116 ldau_dct['ldauj'] = jlist 

117 return ldau_dct 

118 

119 

120def test_nelect_charge_compitability(nelect, charge, nelect_from_ppp): 

121 # We need to determine the nelect resulting from a given 

122 # charge in any case if it's != 0, but if nelect is 

123 # additionally given explicitly, then we need to determine it 

124 # even for net charge of 0 to check for conflicts 

125 if charge is not None and charge != 0: 

126 nelect_from_charge = nelect_from_ppp - charge 

127 if nelect and nelect != nelect_from_charge: 

128 raise ValueError('incompatible input parameters: ' 

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

130 '(neutral nelect is ' 

131 f'{nelect_from_ppp})') 

132 print(nelect_from_charge) 

133 return nelect_from_charge 

134 else: 

135 return nelect 

136 

137 

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

139 """ 

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

141 

142 Parameters 

143 ---------- 

144 setup : [str, dict] 

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

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

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

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

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

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

151 available. The default is 'minimal 

152 

153 Returns 

154 ------- 

155 setups : dict 

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

157 as values. 

158 special_setups : list 

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

160 """ 

161 special_setups = [] 

162 

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

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

165 setups_defaults = get_default_setups() 

166 

167 # Default to minimal basis 

168 if setup is None: 

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

170 

171 # String shortcuts are initialised to dict form 

172 elif isinstance(setup, str): 

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

174 setup = {'base': setup} 

175 

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

177 if 'base' in setup: 

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

179 else: 

180 setups = {} 

181 

182 # Override defaults with user-defined setups 

183 if setup is not None: 

184 setups.update(setup) 

185 

186 for m in setups: 

187 try: 

188 special_setups.append(int(m)) 

189 except ValueError: 

190 pass 

191 return setups, special_setups 

192 

193 

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

195 tokens = [] 

196 append = tokens.append 

197 

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

199 

200 if isinstance(kpts, dict): 

201 kpts = kpts2ndarray(kpts, atoms=atoms) 

202 reciprocal = True 

203 

204 shape = np.array(kpts).shape 

205 

206 # Wrap scalar in list if necessary 

207 if shape == (): 

208 kpts = [kpts] 

209 shape = (1, ) 

210 

211 if len(shape) == 1: 

212 append('0\n') 

213 if shape == (1, ): 

214 append('Auto\n') 

215 elif gamma: 

216 append('Gamma\n') 

217 else: 

218 append('Monkhorst-Pack\n') 

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

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

221 elif len(shape) == 2: 

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

223 if reciprocal: 

224 append('Reciprocal\n') 

225 else: 

226 append('Cartesian\n') 

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

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

229 if shape[1] == 4: 

230 append('\n') 

231 elif shape[1] == 3: 

232 append('1.0 \n') 

233 return ''.join(tokens) 

234 

235 

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

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

238 

239float_keys = [ 

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

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

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

243 'aldac', # Fraction of LDA correlation energy 

244 'amin', # 

245 'amix', # 

246 'amix_mag', # 

247 'bmix', # tags for mixing 

248 'bmix_mag', # 

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

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

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

252 # (EDIFF/N-BANDS/4) 

253 'efield', # applied electrostatic field 

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

255 'emin', # 

256 'enaug', # Density cutoff 

257 'encut', # Planewave cutoff 

258 'encutgw', # energy cutoff for response function 

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

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

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

262 # file is not present. KSPACING is the smallest 

263 # allowed spacing between k-points in units of 

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

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

266 'nelect', # total number of electrons 

267 'param1', # Exchange parameter 

268 'param2', # Exchange parameter 

269 'pomass', # mass of ions in am 

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

271 # pstress 

272 'sigma', # broadening in eV 

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

274 'spring', # spring constant for NEB 

275 'time', # special control tag 

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

277 'zab_vdw', # vdW-DF parameter 

278 'zval', # ionic valence 

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

280 # group at UT Austin 

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

282 'ddr', # (DdR) dimer separation 

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

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

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

286 'sltol', # convergence ratio for minimum eigenvalue 

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

288 # size when translating 

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

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

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

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

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

294 'ftimemax', # Max time step 

295 'ftimedec', # Factor to dec. dt 

296 'ftimeinc', # Factor to inc. dt 

297 'falpha', # Parameter for velocity damping 

298 'falphadec', # Factor to dec. alpha 

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

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

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

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

303 # correction 

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

305 # and Scheffler's DFT-TS dispersion corrections 

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

307 # Grimme's DFT-D3 dispersion correction 

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

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

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

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

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

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

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

315 'eb_k', # solvent permitivity in Vaspsol 

316 'tau', # surface tension parameter in Vaspsol 

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

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

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

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

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

322 'tebeg', # 

323 'teend', # temperature during run 

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

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

326 'auger_ecblo', # Undocumented parameter for Auger calculations 

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

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

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

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

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

332 'auger_occ_fac_eeh', # Undocumented parameter for Auger calculations 

333 'auger_occ_fac_ehh', # Undocumented parameter for Auger calculations 

334 'auger_temp', # Temperature for Auger calculation 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

356 'deg_threshold', # Degeneracy threshold 

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

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

359 'rtime', # Undocumented parameter 

360 'wplasma', # Undocumented parameter 

361 'wplasmai', # Undocumented parameter 

362 'dfield', # Undocumented parameter 

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

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

365 'encutlf', # Undocumented parameter 

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

367 'dimer_dist', # Distance between dimer images 

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

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

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

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

372 'shaketol', # Tolerance for SHAKE algorithm 

373 'shaketolsoft', # Soft tolerance for SHAKE algorithm 

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

375 'hills_stride', # Undocumented metadynamics parameter 

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

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

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

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

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

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

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

383 'dvvdelta0', # Undocumented parameter 

384 'dvvvnorm0', # Undocumented parameter 

385 'dvvminpotim', # Undocumented parameter 

386 'dvvmaxpotim', # Undocumented parameter 

387 'enchg', # Undocumented charge fitting parameter 

388 'tau0', # Undocumented charge fitting parameter 

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

390 'param3', # Undocumented HF parameter 

391 'model_eps0', # Undocumented HF parameter 

392 'model_alpha', # Undocumented HF parameter 

393 'qmaxfockae', # Undocumented HF parameter 

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

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

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

397 'encutsubrotscf', # Undocumented subspace rotation SCF parameter 

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

399 'wc', # Undocumented mixing parameter 

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

401 'scalee', # Undocumented parameter 

402 'eref', # Reference energy 

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

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

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

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

407 'lj_radius', # Undocumented classical vdW parameter 

408 'lj_epsilon', # Undocumented classical vdW parameter 

409 'lj_sigma', # Undocumented classical vdW parameter 

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

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

412 'hitoler', # Iterative Hirschfeld partitioning tolerance 

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

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

415 'maxpwamp', # Undocumented HF parameter 

416 'vcutoff', # Undocumented parameter 

417 'mdtemp', # Temperature for AIMD 

418 'mdgamma', # Undocumented AIMD parameter 

419 'mdalpha', # Undocumented AIMD parameter 

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

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

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

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

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

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

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

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

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

429 'qtpz', # Temperature (instanton) 

430 'qftol', # Tolerance (instanton) 

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

432] 

433 

434exp_keys = [ 

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

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

437 'symprec', # precession in symmetry routines 

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

439 # group at UT Austin 

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

441] 

442 

443string_keys = [ 

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

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

446 'metagga', # 

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

448 'system', # name of System 

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

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

451 'localized_basis', # Basis to use in CRPA 

452 'proutine', # Select profiling routine 

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

454] 

455 

456int_keys = [ 

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

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

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

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

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

462 'imix', # specifies density mixing 

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

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

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

466 'ispin', # spin-polarized calculation 

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

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

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

470 'kpar', # k-point parallelization paramater 

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

472 # written 

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

474 'lmaxmix', # 

475 'lorbit', # create PROOUT 

476 'maxmix', # 

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

478 'ngxf', # FFT mesh for charges x 

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

480 'ngyf', # FFT mesh for charges y 

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

482 'ngzf', # FFT mesh for charges z 

483 'nbands', # Number of bands 

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

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

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

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

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

489 'nelmin', 

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

491 # finite differences 

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

493 # nkredx=nkredy=nkredz 

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

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

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

497 'nomega', # number of frequency points 

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

499 'npar', # parallelization over bands 

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

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

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

503 'vdwgr', # extra keyword for Andris program 

504 'vdwrn', # extra keyword for Andris program 

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

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

507 # group at UT Austin 

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

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

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

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

512 # and potim = 0.0 

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

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

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

516 'icorelevel', # core level shifts 

517 'clnt', # species index 

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

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

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

521 'nbandsgw', # Number of bands for GW 

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

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

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

525 # by npar 

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

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

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

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

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

531 # response function calc. 

532 'taupar', 

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

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

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

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

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

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

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

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

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

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

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

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

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

546 'ibse', # Type of BSE calculation 

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

548 'naturalo', # Use NATURALO (?) 

549 'nbandsexact', # Undocumented parameter 

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

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

552 'omegagrid', # Undocumented parameter 

553 'telescope', # Undocumented parameter 

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

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

556 'dim', # Undocumented parameter 

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

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

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

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

561 'lmaxmp2', # Undocumented parameter 

562 'switch', # Undocumented dimer parameter 

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

564 'engine', # Undocumented dimer parameter 

565 'restartcg', # Undocumented dimer parameter 

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

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

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

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

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

571 'hills_maxstride', # Undocumented metadynamics parameter 

572 'dvvehistory', # Undocumented parameter 

573 'ipead', # Undocumented parameter 

574 'ngaus', # Undocumented charge fitting parameter 

575 'exxoep', # Undocumented HF parameter 

576 'fourorbit', # Undocumented HF parameter 

577 'model_gw', # Undocumented HF parameter 

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

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

580 'lmaxfockae', # Undocumented HF parameter 

581 'nmaxfockae', # Undocumented HF parameter 

582 'nblock_fock', # Undocumented HF parameter 

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

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

585 'mremove', # Undocumented mixing parameter 

586 'inimix', # Undocumented mixing parameter 

587 'mixpre', # Undocumented mixing parameter 

588 'nelmall', # Undocumented parameter 

589 'nblock', # How frequently to write data 

590 'kblock', # How frequently to write data 

591 'npaco', # Undocumented pair correlation function parameter 

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

593 'irestart', # Undocumented parameter 

594 'nreboot', # Undocumented parameter 

595 'nmin', # Undocumented parameter 

596 'nlspline', # Undocumented parameter 

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

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

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

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

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

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

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

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

605 'nbands_out', # Undocumented QP parameter 

606 'kpts_out', # Undocumented QP parameter 

607 'isp_out', # Undocumented QP parameter 

608 'nomega_out', # Undocumented QP parameter 

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

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

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

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

613 'ncore_in_image1', # Undocumented parameter 

614 'kimages', # Undocumented parameter 

615 'ncores_per_band', # Undocumented parameter 

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

617 'ncrpalow', # Undocumented CRPA parameter 

618 'ncrpahigh', # Undocumented CRPA parameter 

619 'nwlow', # Undocumented parameter 

620 'nwhigh', # Undocumented parameter 

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

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

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

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

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

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

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

628] 

629 

630bool_keys = [ 

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

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

633 # centred at the $\Gamma$ 

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

635 # (KGAMMA=.TRUE.) 

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

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

638 # VASP.5.X) 

639 'lasync', # overlap communcation with calculations 

640 'lcharg', # 

641 'lcorr', # Harris-correction to forces 

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

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

644 'ldipol', # potential correction mode 

645 'lelf', # create ELFCAR 

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

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

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

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

650 # density 

651 'lplane', # parallelisation over the FFT grid 

652 'lscalapack', # switch off scaLAPACK 

653 'lscalu', # switch of LU decomposition 

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

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

656 'lthomas', # 

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

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

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

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

661 'lwave', # 

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

663 # group at UT Austin 

664 'lclimb', # Turn on CI-NEB 

665 'ltangentold', # Old central difference tangent 

666 'ldneb', # Turn on modified double nudging 

667 'lnebcell', # Turn on SS-NEB 

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

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

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

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

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

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

674 # tensors (vasp 5.2) 

675 'lvdw', # Turns on dispersion correction 

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

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

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

679 # polarizability 

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

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

682 'lsorbit', # Enable spin-orbit coupling 

683 'lsol', # turn on solvation for Vaspsol 

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

685 'interactive', # Enables interactive calculation for VaspInteractive 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

716 'lmixtau', # Undocumented MetaGGA parameter 

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

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

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

720 'lnabla', # Undocumented parameter 

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

722 'lvel', # Undocumented parameter 

723 'lrpaforce', # Calculate RPA forces 

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

725 'ladder', # Use ladder diagrams 

726 'lfxc', # Use approximate ladder diagrams 

727 'lrsrpa', # Undocumented parameter 

728 'lsingles', # Calculate HF singles 

729 'lfermigw', # Iterate Fermi level 

730 'ltcte', # Undocumented parameter 

731 'ltete', # Undocumented parameter 

732 'ltriplet', # Undocumented parameter 

733 'lfxceps', # Undocumented parameter 

734 'lfxheg', # Undocumented parameter 

735 'l2order', # Undocumented parameter 

736 'lmp2lt', # Undocumented parameter 

737 'lgwlf', # Undocumented parameter 

738 'lusew', # Undocumented parameter 

739 'selfenergy', # Undocumented parameter 

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

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

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

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

744 'fletcher_reeves', # Undocumented dimer parameter 

745 'lidm_selective', # Undocumented dimer parameter 

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

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

748 'dvvminus', # Undocumented parameter 

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

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

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

752 'lchgfit', # Turn on charge fitting 

753 'lgausrc', # Undocumented charge fitting parameter 

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

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

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

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

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

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

760 'shiftred', # Undocumented HF parameter 

761 'hfkident', # Undocumented HF parameter 

762 'oddonly', # Undocumented HF parameter 

763 'evenonly', # Undocumented HF parameter 

764 'lfockaedft', # Undocumented HF parameter 

765 'lsubrot', # Enable subspace rotation diagonalization 

766 'mixfirst', # Mix before diagonalization 

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

768 'lcompat', # Enable "full compatibility" 

769 'lmusic', # "Joke" parameter 

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

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

772 'lorbitalreal', # Undocumented parameter 

773 'lmetagga', # Undocumented parameter 

774 'lspiral', # Undocumented parameter 

775 'lzeroz', # Undocumented parameter 

776 'lmono', # Enable "monopole" corrections 

777 'lrelcore', # Perform relaxed core calculation 

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

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

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

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

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

783 'lrelvol', # Undocumented classical vdW parameter 

784 'lj_only', # Undocumented classical vdW parameter 

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

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

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

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

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

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

791 'lvdw_relvolone', # Undocumented classical vdW parameter 

792 'lberry', # Enable Berry-phase calculation 

793 'lpade_fit', # Undocumented QP parameter 

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

795 'l_wr_moments', # Undocumented parameter 

796 'l_wr_density', # Undocumented parameter 

797 'lkotani', # Undocumented parameter 

798 'ldyson', # Undocumented parameter 

799 'laddherm', # Undocumented parameter 

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

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

802 'ldisentangle', # Disentangle bands in CRPA 

803 'lweighted', # "Weighted" CRPA approach 

804 'luseorth_lcaos', # Use orthogonalized LCAOs in CRPA 

805 'lfrpa', # Use full RPA in CRPA 

806 'lregularize', # Regularize projectors in CRPA 

807 'ldrude', # Include Drude term in CRPA 

808 'ldmatrix', # Undocumented parameter 

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

810 'lhyperfine', # Enable Hyperfine calculation 

811 'lwannier', # Enable Wannier interface 

812 'localize', # Undocumented Wannier parameter 

813 'lintpol_wpot', # Interpolate WPOT for Wannier 

814 'lintpol_orb', # Interpolate orbitals for Wannier 

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

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

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

818 'lintpol_velocity', # Interpolate electron velocity for Wannier 

819 'lintpol_conductivity', # Interpolate conductivity for Wannier 

820 'lwannierinterpol', # Undocumented Wannier parameter 

821 'wanproj', # Undocumented Wannier parameter 

822 'lorbmom', # Undocumented LDA+U parameter 

823 'lwannier90_run', # Undocumented WANNIER90 parameter 

824 'lwrite_wanproj', # Write UWAN files for WANNIER90 

825 'lwrite_unk', # Write UNK files for WANNIER90 

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

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

828 'lrhfatm', # Undocumented HF parameter 

829 'lvpot', # Calculate unscreened potential 

830 'lwpot', # Calculate screened potential 

831 'lwswq', # Undocumented parameter 

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

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

834 'qdo_ins', # Find instanton 

835 'qdo_pre', # Calculate prefactor (instanton) 

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

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

838 'lnbo', # Enable NBO analysis 

839] 

840 

841list_int_keys = [ 

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

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

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

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

846 # (Bucko) 

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

848 'auger_bmax_eeh', # 4 ints | calculations 

849 'auger_bmin_ehh', # 4 ints | 

850 'auger_bmax_ehh', # 4 ints | 

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

852 'kpoint_bse', # 4 ints | Undocumented parameter 

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

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

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

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

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

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

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

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

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

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

863] 

864 

865list_bool_keys = [ 

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

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

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

869] 

870 

871list_float_keys = [ 

872 'dipol', # center of cell for dipol 

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

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

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

876 'magmom', # initial magnetic moments 

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

878 'rwigs', # Wigner-Seitz radii 

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

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

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

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

883 # when a calculation is set up 

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

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

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

887 # (DFT-TS) 

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

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

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

891 # (DFT-TS) 

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

893 # species (DFT-TS) 

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

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

896 'auger_emax_eeh', # 4 floats | calculations 

897 'auger_emin_ehh', # 4 floats | 

898 'auger_emax_ehh', # 4 floats | 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

931 'qspiral', # 3 floats | Undocumented parameter 

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

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

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

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

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

937 'ofield_k', # 3 floats | Undocumented parameter 

938 'paripot', # ? floats | Undocumented parameter 

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

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

941] 

942 

943special_keys = [ 

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

945] 

946 

947dict_keys = [ 

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

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

950] 

951 

952keys: List[str] = [ 

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

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

955 # 'WEIMIN, EBREAK, DEPER special control tags 

956] 

957 

958 

959class GenerateVaspInput: 

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

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

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

963 xc_defaults = { 

964 'lda': { 

965 'pp': 'LDA' 

966 }, 

967 # GGAs 

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

969 'pp': 'PBE', 

970 'gga': 'B5', 

971 'aldax': 1.00, 

972 'aggax': 1.00, 

973 'aggac': 1.00, 

974 'aldac': 0.00 

975 }, 

976 'pw91': { 

977 'pp': 'PW91', 

978 'gga': '91' 

979 }, 

980 'pbe': { 

981 'pp': 'PBE', 

982 'gga': 'PE' 

983 }, 

984 'pbesol': { 

985 'gga': 'PS' 

986 }, 

987 'revpbe': { 

988 'gga': 'RE' 

989 }, 

990 'rpbe': { 

991 'gga': 'RP' 

992 }, 

993 'am05': { 

994 'gga': 'AM' 

995 }, 

996 # Meta-GGAs 

997 'tpss': { 

998 'metagga': 'TPSS' 

999 }, 

1000 'revtpss': { 

1001 'metagga': 'RTPSS' 

1002 }, 

1003 'm06l': { 

1004 'metagga': 'M06L' 

1005 }, 

1006 'ms0': { 

1007 'metagga': 'MS0' 

1008 }, 

1009 'ms1': { 

1010 'metagga': 'MS1' 

1011 }, 

1012 'ms2': { 

1013 'metagga': 'MS2' 

1014 }, 

1015 'scan': { 

1016 'metagga': 'SCAN' 

1017 }, 

1018 'rscan': { 

1019 'metagga': 'RSCAN' 

1020 }, 

1021 'r2scan': { 

1022 'metagga': 'R2SCAN' 

1023 }, 

1024 'scan-rvv10': { 

1025 'metagga': 'SCAN', 

1026 'luse_vdw': True, 

1027 'bparam': 15.7 

1028 }, 

1029 'mbj': { 

1030 # Modified Becke-Johnson 

1031 'metagga': 'MBJ', 

1032 }, 

1033 'tb09': { 

1034 # Alias for MBJ 

1035 'metagga': 'MBJ', 

1036 }, 

1037 # vdW-DFs 

1038 'vdw-df': { 

1039 'gga': 'RE', 

1040 'luse_vdw': True, 

1041 'aggac': 0. 

1042 }, 

1043 'vdw-df-cx': { 

1044 'gga': 'CX', 

1045 'luse_vdw': True, 

1046 'aggac': 0. 

1047 }, 

1048 'vdw-df-cx0p': { 

1049 'gga': 'CX', 

1050 'luse_vdw': True, 

1051 'aggac': 0., 

1052 'lhfcalc': True, 

1053 'aexx': 0.2, 

1054 'aggax': 0.8 

1055 }, 

1056 'optpbe-vdw': { 

1057 'gga': 'OR', 

1058 'luse_vdw': True, 

1059 'aggac': 0.0 

1060 }, 

1061 'optb88-vdw': { 

1062 'gga': 'BO', 

1063 'luse_vdw': True, 

1064 'aggac': 0.0, 

1065 'param1': 1.1 / 6.0, 

1066 'param2': 0.22 

1067 }, 

1068 'optb86b-vdw': { 

1069 'gga': 'MK', 

1070 'luse_vdw': True, 

1071 'aggac': 0.0, 

1072 'param1': 0.1234, 

1073 'param2': 1.0 

1074 }, 

1075 'vdw-df2': { 

1076 'gga': 'ML', 

1077 'luse_vdw': True, 

1078 'aggac': 0.0, 

1079 'zab_vdw': -1.8867 

1080 }, 

1081 'rev-vdw-df2': { 

1082 'gga': 'MK', 

1083 'luse_vdw': True, 

1084 'param1': 0.1234, 

1085 'param2': 0.711357, 

1086 'zab_vdw': -1.8867, 

1087 'aggac': 0.0 

1088 }, 

1089 'beef-vdw': { 

1090 'gga': 'BF', 

1091 'luse_vdw': True, 

1092 'zab_vdw': -1.8867 

1093 }, 

1094 # Hartree-Fock and hybrids 

1095 'hf': { 

1096 'lhfcalc': True, 

1097 'aexx': 1.0, 

1098 'aldac': 0.0, 

1099 'aggac': 0.0 

1100 }, 

1101 'b3lyp': { 

1102 'gga': 'B3', 

1103 'lhfcalc': True, 

1104 'aexx': 0.2, 

1105 'aggax': 0.72, 

1106 'aggac': 0.81, 

1107 'aldac': 0.19 

1108 }, 

1109 'pbe0': { 

1110 'gga': 'PE', 

1111 'lhfcalc': True 

1112 }, 

1113 'hse03': { 

1114 'gga': 'PE', 

1115 'lhfcalc': True, 

1116 'hfscreen': 0.3 

1117 }, 

1118 'hse06': { 

1119 'gga': 'PE', 

1120 'lhfcalc': True, 

1121 'hfscreen': 0.2 

1122 }, 

1123 'hsesol': { 

1124 'gga': 'PS', 

1125 'lhfcalc': True, 

1126 'hfscreen': 0.2 

1127 }, 

1128 # MN-VFM functionals 

1129 'sogga': { 

1130 'gga': 'SA' 

1131 }, 

1132 'sogga11': { 

1133 'gga': 'S1' 

1134 }, 

1135 'sogga11-x': { 

1136 'gga': 'SX', 

1137 'lhfcalc': True, 

1138 'aexx': 0.401 

1139 }, 

1140 'n12': { 

1141 'gga': 'N2' 

1142 }, 

1143 'n12-sx': { 

1144 'gga': 'NX', 

1145 'lhfcalc': True, 

1146 'lhfscreen': 0.2 

1147 }, 

1148 'mn12l': { 

1149 'metagga': 'MN12L' 

1150 }, 

1151 'gam': { 

1152 'gga': 'GA' 

1153 }, 

1154 'mn15l': { 

1155 'metagga': 'MN15L' 

1156 }, 

1157 'hle17': { 

1158 'metagga': 'HLE17' 

1159 }, 

1160 'revm06l': { 

1161 'metagga': 'revM06L' 

1162 }, 

1163 'm06sx': { 

1164 'metagga': 'M06SX', 

1165 'lhfcalc': True, 

1166 'hfscreen': 0.189, 

1167 'aexx': 0.335 

1168 } 

1169 } 

1170 

1171 # environment variable for PP paths 

1172 VASP_PP_PATH = 'VASP_PP_PATH' 

1173 

1174 def __init__(self, restart=None): 

1175 self.float_params = {} 

1176 self.exp_params = {} 

1177 self.string_params = {} 

1178 self.int_params = {} 

1179 self.bool_params = {} 

1180 self.list_bool_params = {} 

1181 self.list_int_params = {} 

1182 self.list_float_params = {} 

1183 self.special_params = {} 

1184 self.dict_params = {} 

1185 self.atoms = None 

1186 for key in float_keys: 

1187 self.float_params[key] = None 

1188 for key in exp_keys: 

1189 self.exp_params[key] = None 

1190 for key in string_keys: 

1191 self.string_params[key] = None 

1192 for key in int_keys: 

1193 self.int_params[key] = None 

1194 for key in bool_keys: 

1195 self.bool_params[key] = None 

1196 for key in list_bool_keys: 

1197 self.list_bool_params[key] = None 

1198 for key in list_int_keys: 

1199 self.list_int_params[key] = None 

1200 for key in list_float_keys: 

1201 self.list_float_params[key] = None 

1202 for key in special_keys: 

1203 self.special_params[key] = None 

1204 for key in dict_keys: 

1205 self.dict_params[key] = None 

1206 

1207 # Initialize internal dictionary of input parameters which are 

1208 # not regular VASP keys 

1209 self.input_params = { 

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

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

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

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

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

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

1216 'gamma': False, 

1217 # number of points between points in band structures: 

1218 'kpts_nintersections': None, 

1219 # Option to write explicit k-points in units 

1220 # of reciprocal lattice vectors: 

1221 'reciprocal': False, 

1222 # Switch to disable writing constraints to POSCAR 

1223 'ignore_constraints': False, 

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

1225 'charge': None, 

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

1227 # with the sign flipped 

1228 'net_charge': None, 

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

1230 'custom': {}, 

1231 } 

1232 # warning message for pw91 

1233 self.pw91_warning_msg =\ 

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

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

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

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

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

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

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

1241 "energies given by the POTCAR file." 

1242 

1243 def set_xc_params(self, xc): 

1244 """Set parameters corresponding to XC functional""" 

1245 xc = xc.lower() 

1246 if xc is None: 

1247 pass 

1248 elif xc not in self.xc_defaults: 

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

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

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

1252 else: 

1253 # print future warning in case pw91 is selected: 

1254 if xc == 'pw91': 

1255 warnings.warn( 

1256 self.pw91_warning_msg, FutureWarning 

1257 ) 

1258 # XC defaults to PBE pseudopotentials 

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

1260 self.set(pp='PBE') 

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

1262 

1263 def set(self, **kwargs): 

1264 

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

1266 and ('ldau_luj' in kwargs)): 

1267 raise NotImplementedError( 

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

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

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

1271 'chemical species in the atoms object. ' 

1272 'For example for a water molecule:' 

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

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

1275 

1276 if 'xc' in kwargs: 

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

1278 for key in kwargs: 

1279 if key in self.float_params: 

1280 self.float_params[key] = kwargs[key] 

1281 elif key in self.exp_params: 

1282 self.exp_params[key] = kwargs[key] 

1283 elif key in self.string_params: 

1284 self.string_params[key] = kwargs[key] 

1285 elif key in self.int_params: 

1286 self.int_params[key] = kwargs[key] 

1287 elif key in self.bool_params: 

1288 self.bool_params[key] = kwargs[key] 

1289 elif key in self.list_bool_params: 

1290 self.list_bool_params[key] = kwargs[key] 

1291 elif key in self.list_int_params: 

1292 self.list_int_params[key] = kwargs[key] 

1293 elif key in self.list_float_params: 

1294 self.list_float_params[key] = kwargs[key] 

1295 elif key in self.special_params: 

1296 self.special_params[key] = kwargs[key] 

1297 elif key in self.dict_params: 

1298 self.dict_params[key] = kwargs[key] 

1299 elif key in self.input_params: 

1300 self.input_params[key] = kwargs[key] 

1301 else: 

1302 raise TypeError('Parameter not defined: ' + key) 

1303 

1304 def check_xc(self): 

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

1306 

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

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

1309 """ 

1310 

1311 p = self.input_params 

1312 

1313 # There is no way to correctly guess the desired 

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

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

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

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

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

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

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

1321 warnings.warn( 

1322 self.pw91_warning_msg, FutureWarning 

1323 ) 

1324 

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

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

1327 else: 

1328 raise NotImplementedError( 

1329 "Unable to guess the desired set of pseudopotential" 

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

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

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

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

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

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

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

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

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

1339 "accepted.\n") 

1340 

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

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

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

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

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

1346 "really what you intended!" 

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

1348 

1349 def _make_sort( 

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

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

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

1353 

1354 # Create sorting list 

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

1356 srt.extend(special_setups) 

1357 

1358 for symbol in symbols: 

1359 for m, atom in enumerate(atoms): 

1360 if m in special_setups: 

1361 continue 

1362 if atom.symbol == symbol: 

1363 srt.append(m) 

1364 # Create the resorting list 

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

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

1367 resrt[srt[n]] = n 

1368 return srt, resrt 

1369 

1370 def _set_spinpol(self, atoms): 

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

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

1373 else: 

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

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

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

1377 

1378 def _build_pp_list(self, 

1379 atoms, 

1380 setups=None, 

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

1382 """Build the pseudopotential lists""" 

1383 

1384 p = self.input_params 

1385 

1386 if setups is None: 

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

1388 

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

1390 

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

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

1393 ('pbe', 'potpaw_PBE')): 

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

1395 break 

1396 else: 

1397 pp_folder = p['pp'] 

1398 

1399 if self.VASP_PP_PATH in cfg: 

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

1401 else: 

1402 pppaths = [] 

1403 ppp_list = [] 

1404 # Setting the pseudopotentials, first special setups and 

1405 # then according to symbols 

1406 for m in special_setups: 

1407 if m in setups: 

1408 special_setup_index = m 

1409 elif str(m) in setups: 

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

1411 else: 

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

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

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

1415 for path in pppaths: 

1416 filename = join(path, potcar) 

1417 

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

1419 ppp_list.append(filename) 

1420 break 

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

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

1423 break 

1424 else: 

1425 symbol = atoms.symbols[m] 

1426 msg = """Looking for {}. 

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

1428 potcar, symbol, setups[special_setup_index]) 

1429 raise RuntimeError(msg) 

1430 

1431 for symbol in symbols: 

1432 try: 

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

1434 except (TypeError, KeyError): 

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

1436 for path in pppaths: 

1437 filename = join(path, potcar) 

1438 

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

1440 ppp_list.append(filename) 

1441 break 

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

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

1444 break 

1445 else: 

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

1447 The pseudopotentials are expected to be in: 

1448 LDA: $VASP_PP_PATH/potpaw/ 

1449 PBE: $VASP_PP_PATH/potpaw_PBE/ 

1450 PW91: $VASP_PP_PATH/potpaw_GGA/ 

1451 

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

1453 raise RuntimeError(msg) 

1454 return ppp_list 

1455 

1456 def initialize(self, atoms): 

1457 """Initialize a VASP calculation 

1458 

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

1460 User should specify the PATH 

1461 to the pseudopotentials in VASP_PP_PATH environment variable 

1462 

1463 The pseudopotentials are expected to be in: 

1464 LDA: $VASP_PP_PATH/potpaw/ 

1465 PBE: $VASP_PP_PATH/potpaw_PBE/ 

1466 PW91: $VASP_PP_PATH/potpaw_GGA/ 

1467 

1468 if your pseudopotentials are somewhere else, or named 

1469 differently you may make symlinks at the paths above that 

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

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

1472 """ 

1473 

1474 self.check_xc() 

1475 self.atoms = atoms 

1476 self.all_symbols = atoms.get_chemical_symbols() 

1477 self.natoms = len(atoms) 

1478 

1479 self._set_spinpol(atoms) 

1480 

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

1482 

1483 # Determine the number of atoms of each atomic species 

1484 # sorted after atomic species 

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

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

1487 special_setups=special_setups) 

1488 

1489 self.atoms_sorted = atoms[self.sort] 

1490 

1491 # Check if the necessary POTCAR files exists and 

1492 # create a list of their paths. 

1493 atomtypes = atoms.get_chemical_symbols() 

1494 self.symbol_count = [] 

1495 for m in special_setups: 

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

1497 for m in symbols: 

1498 self.symbol_count.append([m, symbolcount[m]]) 

1499 

1500 # create pseudopotential list 

1501 self.ppp_list = self._build_pp_list(atoms, 

1502 setups=setups, 

1503 special_setups=special_setups) 

1504 

1505 self.converged = None 

1506 self.setups_changed = None 

1507 

1508 def default_nelect_from_ppp(self): 

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

1510 

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

1512 """ 

1513 symbol_valences = [] 

1514 for filename in self.ppp_list: 

1515 with open_potcar(filename=filename) as ppp_file: 

1516 r = read_potcar_numbers_of_electrons(ppp_file) 

1517 symbol_valences.extend(r) 

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

1519 default_nelect = 0 

1520 for ((symbol1, count), 

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

1522 assert symbol1 == symbol2 

1523 default_nelect += count * valence 

1524 return default_nelect 

1525 

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

1527 from ase.io.vasp import write_vasp 

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

1529 self.atoms_sorted, 

1530 symbol_count=self.symbol_count, 

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

1532 self.write_incar(atoms, directory=directory) 

1533 self.write_potcar(directory=directory) 

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

1535 self.write_sort_file(directory=directory) 

1536 self.copy_vdw_kernel(directory=directory) 

1537 

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

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

1540 Set ASE_VASP_VDW environment variable to the vdw_kernel.bindat 

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

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

1543 

1544 vdw_env = 'ASE_VASP_VDW' 

1545 kernel = 'vdw_kernel.bindat' 

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

1547 

1548 # No need to copy the file again 

1549 if isfile(dst): 

1550 return 

1551 

1552 if self.bool_params['luse_vdw']: 

1553 src = None 

1554 if vdw_env in cfg: 

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

1556 

1557 if not src or not isfile(src): 

1558 warnings.warn( 

1559 ('vdW has been enabled, however no' 

1560 ' location for the {} file' 

1561 ' has been specified.' 

1562 ' Set {} environment variable to' 

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

1564 else: 

1565 shutil.copyfile(src, dst) 

1566 

1567 def clean(self): 

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

1569 

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

1571 method is called. 

1572 

1573 """ 

1574 files = [ 

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

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

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

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

1579 ] 

1580 for f in files: 

1581 try: 

1582 os.remove(f) 

1583 except OSError: 

1584 pass 

1585 

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

1587 """Writes the INCAR file.""" 

1588 incar_params = {} 

1589 incar_header = \ 

1590 'INCAR created by Atomic Simulation Environment' 

1591 # float params 

1592 float_dct = dict((key, f'{val:{FLOAT_FORMAT}}') for key, val 

1593 in self.float_params.items() 

1594 if val is not None) 

1595 

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

1597 'charge'] is not None: 

1598 nelect_val = test_nelect_charge_compitability( 

1599 self.float_params['nelect'], 

1600 self.input_params['charge'], 

1601 self.default_nelect_from_ppp()) 

1602 if nelect_val: 

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

1604 incar_params.update(float_dct) 

1605 

1606 # exp params 

1607 exp_dct = dict( 

1608 (key, f'{val:{EXP_FORMAT}}') for key, val in self.exp_params.items() 

1609 if val is not None) 

1610 incar_params.update(exp_dct) 

1611 

1612 # string_params 

1613 string_dct = dict((key, val) for key, val in self.string_params.items() 

1614 if val is not None) 

1615 incar_params.update(string_dct) 

1616 

1617 # int params 

1618 int_dct = dict((key, val) for key, val in self.int_params.items() 

1619 if val is not None) 

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

1621 ichain_dict = check_ichain( 

1622 ichain=int_dct['ichain'], 

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

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

1625 ) 

1626 int_dct.update(ichain_dict) 

1627 incar_params.update(int_dct) 

1628 

1629 # list_bool_params 

1630 bool_dct = dict((key, val) for key, val in self.list_bool_params.items() 

1631 if val is not None) 

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

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

1634 incar_params.update(bool_dct) 

1635 

1636 # list_int_params 

1637 int_dct = dict((key, val) for key, val in self.list_int_params.items() 

1638 if val is not None) 

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

1640 'ldau_luj'] is not None: 

1641 del int_dct['ldaul'] 

1642 incar_params.update(int_dct) 

1643 

1644 # list_float_params 

1645 float_dct = dict( 

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

1647 if val is not None) 

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

1649 'ldau_luj'] is not None: 

1650 del float_dct['ldauu'] 

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

1652 'ldau_luj'] is not None: 

1653 del float_dct['ldauj'] 

1654 incar_params.update(float_dct) 

1655 

1656 # bool params 

1657 bool_dct = dict( 

1658 (key, _to_vasp_bool(val)) for key, val in self.bool_params.items() 

1659 if val is not None) 

1660 incar_params.update(bool_dct) 

1661 

1662 # special params 

1663 special_dct = dict( 

1664 (key, val) for key, val in self.special_params.items() 

1665 if val is not None) 

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

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

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

1669 incar_params.update(special_dct) 

1670 

1671 # dict params 

1672 dict_dct = dict((key, val) for key, val in self.dict_params.items() 

1673 if val is not None) 

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

1675 ldau_dict = set_ldau( 

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

1677 luj_params=dict_dct['ldau_luj'], 

1678 symbol_count=self.symbol_count) 

1679 dict_dct.update(ldau_dict) 

1680 del dict_dct['ldau_luj'] 

1681 incar_params.update(dict_dct) 

1682 

1683 # set magmom based on input or initial atoms object 

1684 spinpol, magmom_dct = set_magmom( 

1685 atoms=atoms, 

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

1687 spinpol=self.spinpol, 

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

1689 sorting=self.sort, 

1690 ) 

1691 self.spinpol = spinpol 

1692 incar_params.update(magmom_dct) 

1693 

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

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

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

1697 # reliably and easily identify such non-standard entries 

1698 

1699 cust_dict = dict( 

1700 (key, str(val) + ' # <Custom ASE key>') for key, val in 

1701 self.input_params['custom'].items() 

1702 if val is not None) 

1703 incar_params.update(cust_dict) 

1704 

1705 write_incar(directory=directory, 

1706 parameters=incar_params, 

1707 header=incar_header) 

1708 

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

1710 """Writes the KPOINTS file.""" 

1711 

1712 if atoms is None: 

1713 atoms = self.atoms 

1714 

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

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

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

1718 return 

1719 else: 

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

1721 "Please use None or a positive number." 

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

1723 

1724 kpointstring = format_kpoints( 

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

1726 atoms=atoms, 

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

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

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

1730 kpoints.write(kpointstring) 

1731 

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

1733 """Writes the POTCAR file.""" 

1734 

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

1736 for filename in self.ppp_list: 

1737 with open_potcar(filename=filename) as ppp_file: 

1738 for line in ppp_file: 

1739 potfile.write(line) 

1740 

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

1742 """Writes a sortings file. 

1743 

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

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

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

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

1748 

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

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

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

1752 

1753 # The below functions are used to restart a calculation 

1754 

1755 def read_incar(self, filename): 

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

1757 

1758 Typically named INCAR.""" 

1759 

1760 self.spinpol = False 

1761 with open(filename) as fd: 

1762 lines = fd.readlines() 

1763 

1764 for line in lines: 

1765 try: 

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

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

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

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

1770 data = line.split() 

1771 # Skip empty and commented lines. 

1772 if len(data) == 0: 

1773 continue 

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

1775 continue 

1776 key = data[0].lower() 

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

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

1779 # Unconditionally add it, no type checking 

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

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

1782 # value should be '1 2 3' 

1783 

1784 # Split at first occurence of "=" 

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

1786 # First "#" denotes beginning of comment 

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

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

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

1790 elif key in float_keys: 

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

1792 elif key in exp_keys: 

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

1794 elif key in string_keys: 

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

1796 elif key in int_keys: 

1797 if key == 'ispin': 

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

1799 # out 

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

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

1802 self.spinpol = True 

1803 else: 

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

1805 elif key in bool_keys: 

1806 if 'true' in data[2].lower(): 

1807 self.bool_params[key] = True 

1808 elif 'false' in data[2].lower(): 

1809 self.bool_params[key] = False 

1810 

1811 elif key in list_bool_keys: 

1812 self.list_bool_params[key] = [ 

1813 _from_vasp_bool(x) 

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

1815 ] 

1816 

1817 elif key in list_int_keys: 

1818 self.list_int_params[key] = [ 

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

1820 ] 

1821 

1822 elif key in list_float_keys: 

1823 if key == 'magmom': 

1824 lst = [] 

1825 i = 2 

1826 while i < len(data): 

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

1828 break 

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

1830 b = lst.pop() 

1831 i += 1 

1832 for j in range(int(b)): 

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

1834 else: 

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

1836 i += 1 

1837 self.list_float_params['magmom'] = lst 

1838 lst = np.array(lst) 

1839 if self.atoms is not None: 

1840 self.atoms.set_initial_magnetic_moments( 

1841 lst[self.resort]) 

1842 else: 

1843 data = _args_without_comment(data) 

1844 self.list_float_params[key] = [ 

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

1846 ] 

1847 # elif key in list_keys: 

1848 # list = [] 

1849 # if key in ('dipol', 'eint', 'ferwe', 'ferdo', 

1850 # 'ropt', 'rwigs', 

1851 # 'ldauu', 'ldaul', 'ldauj', 'langevin_gamma'): 

1852 # for a in data[2:]: 

1853 # if a in ["!", "#"]: 

1854 # break 

1855 # list.append(float(a)) 

1856 # elif key in ('iband', 'kpuse', 'random_seed'): 

1857 # for a in data[2:]: 

1858 # if a in ["!", "#"]: 

1859 # break 

1860 # list.append(int(a)) 

1861 # self.list_params[key] = list 

1862 # if key == 'magmom': 

1863 # list = [] 

1864 # i = 2 

1865 # while i < len(data): 

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

1867 # break 

1868 # if data[i] == "*": 

1869 # b = list.pop() 

1870 # i += 1 

1871 # for j in range(int(b)): 

1872 # list.append(float(data[i])) 

1873 # else: 

1874 # list.append(float(data[i])) 

1875 # i += 1 

1876 # self.list_params['magmom'] = list 

1877 # list = np.array(list) 

1878 # if self.atoms is not None: 

1879 # self.atoms.set_initial_magnetic_moments( 

1880 # list[self.resort]) 

1881 elif key in special_keys: 

1882 if key == 'lreal': 

1883 if 'true' in data[2].lower(): 

1884 self.special_params[key] = True 

1885 elif 'false' in data[2].lower(): 

1886 self.special_params[key] = False 

1887 else: 

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

1889 except KeyError: 

1890 raise OSError('Keyword "%s" in INCAR is' 

1891 'not known by calculator.' % key) 

1892 except IndexError: 

1893 raise OSError(f'Value missing for keyword "{key}".') 

1894 

1895 def read_kpoints(self, filename): 

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

1897 # If we used VASP builtin kspacing, 

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

1899 # Don't update kpts array 

1900 return 

1901 

1902 with open(filename) as fd: 

1903 lines = fd.readlines() 

1904 

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

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

1907 if ktype == 'g': 

1908 self.set(gamma=True) 

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

1910 elif ktype == 'a': 

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

1912 elif ktype == 'm': 

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

1914 else: 

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

1916 self.set(reciprocal=False) 

1917 else: 

1918 self.set(reciprocal=True) 

1919 kpts = np.array( 

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

1921 self.set(kpts=kpts) 

1922 

1923 def read_potcar(self, filename): 

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

1925 """ 

1926 

1927 # Search for key 'LEXCH' in POTCAR 

1928 xc_flag = None 

1929 with open(filename) as fd: 

1930 for line in fd: 

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

1932 if key == 'LEXCH': 

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

1934 break 

1935 

1936 if xc_flag is None: 

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

1938 

1939 # Values of parameter LEXCH and corresponding XC-functional 

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

1941 

1942 if xc_flag not in xc_dict.keys(): 

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

1944 ' LEXCH=%s' % xc_flag) 

1945 

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

1947 

1948 def todict(self): 

1949 """Returns a dictionary of all parameters 

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

1951 dict_list = [ 

1952 'float_params', 'exp_params', 'string_params', 'int_params', 

1953 'bool_params', 'list_bool_params', 'list_int_params', 

1954 'list_float_params', 'special_params', 'dict_params', 

1955 'input_params' 

1956 ] 

1957 dct = {} 

1958 for item in dict_list: 

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

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

1961 return dct 

1962 

1963 

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

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

1966 

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

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

1969 

1970 """ 

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

1972 if comment_locs == []: 

1973 return data 

1974 else: 

1975 return data[:min(comment_locs)] 

1976 

1977 

1978def _from_vasp_bool(x): 

1979 """Cast vasp boolean to Python bool 

1980 

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

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

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

1984 

1985 """ 

1986 assert isinstance(x, str) 

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

1988 return True 

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

1990 return False 

1991 else: 

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

1993 

1994 

1995def _to_vasp_bool(x): 

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

1997 

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

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

2000 

2001 """ 

2002 if isinstance(x, str): 

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

2004 x = True 

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

2006 x = False 

2007 else: 

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

2009 assert isinstance(x, bool) 

2010 if x: 

2011 return '.TRUE.' 

2012 else: 

2013 return '.FALSE.' 

2014 

2015 

2016def open_potcar(filename): 

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

2018 """ 

2019 import gzip 

2020 if filename.endswith('R'): 

2021 return open(filename) 

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

2023 return gzip.open(filename) 

2024 else: 

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

2026 

2027 

2028def read_potcar_numbers_of_electrons(file_obj): 

2029 """ Read list of tuples (atomic symbol, number of valence electrons) 

2030 for each atomtype from a POTCAR file.""" 

2031 nelect = [] 

2032 lines = file_obj.readlines() 

2033 for n, line in enumerate(lines): 

2034 if 'TITEL' in line: 

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

2036 valence = float( 

2037 lines[n + 4].split(';')[1].split('=')[1].split()[0].strip()) 

2038 nelect.append((symbol, valence)) 

2039 return nelect 

2040 

2041 

2042def count_symbols(atoms, exclude=()): 

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

2044 

2045 Parameters: 

2046 atoms: Atoms object to be grouped 

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

2048 

2049 Returns: 

2050 Tuple of (symbols, symbolcount) 

2051 symbols: The unique symbols in the included list 

2052 symbolscount: Count of symbols in the included list 

2053 

2054 Example: 

2055 

2056 >>> from ase.build import bulk 

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

2058 >>> count_symbols(atoms) 

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

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

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

2062 """ 

2063 symbols = [] 

2064 symbolcount = {} 

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

2066 if m in exclude: 

2067 continue 

2068 if symbol not in symbols: 

2069 symbols.append(symbol) 

2070 symbolcount[symbol] = 1 

2071 else: 

2072 symbolcount[symbol] += 1 

2073 return symbols, symbolcount