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
« prev ^ index » next coverage.py v7.5.3, created at 2025-08-02 00:12 +0000
1# fmt: off
3# Copyright (C) 2008 CSC - Scientific Computing Ltd.
4"""This module defines an ASE interface to VASP.
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.
11The user should also set the environmental flag $VASP_SCRIPT pointing
12to a python script looking something like::
14 import os
15 exitcode = os.system('vasp')
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'
20http://cms.mpi.univie.ac.at/vasp/
21"""
23import os
24import shutil
25import warnings
26from os.path import isfile, islink, join
27from typing import List, Sequence, TextIO, Tuple, Union
29import numpy as np
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
38FLOAT_FORMAT = '5.6f'
39EXP_FORMAT = '5.2e'
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
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)
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
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
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.
130 If nelect is additionally given explicitly, then we need to determine it
131 even for net charge of 0 to check for conflicts.
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)
146def get_pp_setup(setup) -> Tuple[dict, Sequence[int]]:
147 """
148 Get the pseudopotential mapping based on the "setpus" input.
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
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 = []
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()
175 # Default to minimal basis
176 if setup is None:
177 setup = {'base': 'minimal'}
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}
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 = {}
190 # Override defaults with user-defined setups
191 if setup is not None:
192 setups.update(setup)
194 for m in setups:
195 try:
196 special_setups.append(int(m))
197 except ValueError:
198 pass
199 return setups, special_setups
202def format_kpoints(kpts, atoms, reciprocal=False, gamma=False):
203 tokens = []
204 append = tokens.append
206 append('KPOINTS created by Atomic Simulation Environment\n')
208 if isinstance(kpts, dict):
209 kpts = kpts2ndarray(kpts, atoms=atoms)
210 reciprocal = True
212 shape = np.array(kpts).shape
214 # Wrap scalar in list if necessary
215 if shape == ():
216 kpts = [kpts]
217 shape = (1, )
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)
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.
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]
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]
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]
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]
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]
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]
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]
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]
970special_keys = [
971 'lreal', # non-local projectors in real space
972]
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]
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]
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 }
1198 # environment variable for PP paths
1199 VASP_PP_PATH = 'VASP_PP_PATH'
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
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."
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])
1290 def set(self, **kwargs):
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}}''')
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)
1355 def check_xc(self):
1356 """Make sure the calculator has functional & pseudopotentials set up
1358 If no XC combination, GGA functional or POTCAR type is specified,
1359 default to PW91. Otherwise, try to guess the desired pseudopotentials.
1360 """
1362 p = self.input_params
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 )
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")
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()))
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)
1405 # Create sorting list
1406 srt = [] # type: List[int]
1407 srt.extend(special_setups)
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
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)
1429 def _build_pp_list(self,
1430 atoms,
1431 setups=None,
1432 special_setups: Sequence[int] = ()):
1433 """Build the pseudopotential lists"""
1435 p = self.input_params
1437 if setups is None:
1438 setups, special_setups = get_pp_setup(p['setups'])
1440 symbols, _ = count_symbols(atoms, exclude=special_setups)
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']
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)
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)
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)
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/
1503 No pseudopotential for {}!""".format(potcar, symbol))
1504 raise RuntimeError(msg)
1505 return ppp_list
1507 def initialize(self, atoms: Atoms) -> None:
1508 """Initialize a VASP calculation
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
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/
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 """
1525 self.check_xc()
1526 self.atoms = atoms
1527 self.all_symbols = atoms.get_chemical_symbols()
1528 self.natoms = len(atoms)
1530 self._set_spinpol(atoms)
1532 setups, special_setups = get_pp_setup(self.input_params['setups'])
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)
1540 self.atoms_sorted = atoms[self.sort]
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]))
1551 # create pseudopotential list
1552 self.ppp_list = self._build_pp_list(
1553 atoms,
1554 setups=setups,
1555 special_setups=special_setups,
1556 )
1558 self.converged = None
1559 self.setups_changed = None
1561 def default_nelect_from_ppp(self) -> float:
1562 """ Get default number of electrons from ppp_list and symbol_count
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
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)
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."""
1597 vdw_env = 'ASE_VASP_VDW'
1598 kernel = 'vdw_kernel.bindat'
1599 dst = os.path.join(directory, kernel)
1601 # No need to copy the file again
1602 if isfile(dst):
1603 return
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)
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)
1620 def clean(self):
1621 """Method which cleans up after a calculation.
1623 The default files generated by Vasp will be deleted IF this
1624 method is called.
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
1639 def write_incar(self, atoms, directory='./', **kwargs):
1640 """Writes the INCAR file."""
1641 incar_params = {}
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 }
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
1777 write_incar(directory=directory, parameters=incar_params)
1779 def write_kpoints(self, atoms=None, directory='./', **kwargs):
1780 """Writes the KPOINTS file."""
1782 if atoms is None:
1783 atoms = self.atoms
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
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)
1804 def write_potcar(self, suffix="", directory='./'):
1805 """Writes the POTCAR file."""
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)
1813 def write_sort_file(self, directory='./'):
1814 """Writes a sortings file.
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."""
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]))
1825 # The below functions are used to restart a calculation
1827 def read_incar(self, filename):
1828 """Method that imports settings from INCAR file.
1830 Typically named INCAR."""
1832 self.spinpol = False
1833 with open(filename) as fd:
1834 lines = fd.readlines()
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'
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}"')
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 ]
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 ]
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]
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]
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
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
1962 with open(filename) as fd:
1963 lines = fd.readlines()
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)
1983 def read_potcar(self, filename):
1984 """ Read the pseudopotential XC functional from POTCAR file.
1985 """
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
1996 if xc_flag is None:
1997 raise ValueError('LEXCH flag not found in POTCAR file.')
1999 # Values of parameter LEXCH and corresponding XC-functional
2000 xc_dict = {'PE': 'PBE', '91': 'PW91', 'CA': 'LDA'}
2002 if xc_flag not in xc_dict.keys():
2003 raise ValueError('Unknown xc-functional flag found in POTCAR,'
2004 ' LEXCH=%s' % xc_flag)
2006 self.input_params['pp'] = xc_dict[xc_flag]
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
2024def _args_without_comment(data, marks=['!', '#']):
2025 """Check split arguments list for a comment, return data up to marker
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.
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)]
2038def _from_vasp_bool(x):
2039 """Cast vasp boolean to Python bool
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.
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')
2055def _to_vasp_bool(x):
2056 """Convert Python boolean to string for VASP input
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.
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.'
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}"')
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.
2091 Returns
2092 -------
2093 list[tuple[str, float]]
2094 List of (atomic symbol, number of valence electrons).
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
2108def count_symbols(atoms: Atoms, exclude=()) -> tuple[list[str], dict[str, int]]:
2109 """Count symbols in atoms object, excluding a set of indices
2111 Parameters:
2112 atoms: Atoms object to be grouped
2113 exclude: List of indices to be excluded from the counting
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
2120 Example:
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