Pseudopotential Selection in VASP#
Choosing the right pseudopotential (POTCAR) is critical for accurate VASP calculations. This tutorial covers:
Types of VASP pseudopotentials and naming conventions
When to use each variant
How to specify custom setups in the calculator
ENMAX/ENCUT considerations
POTCAR Variants#
VASP uses PAW (Projector Augmented Wave) pseudopotentials. For each element, multiple versions are available:
Suffix |
Meaning |
Description |
|---|---|---|
(none) |
Standard |
Default, computationally efficient |
|
p-valence |
Includes semi-core p states |
|
Semi-core valence |
Includes more core states |
|
d-electrons |
Includes d states for main group |
|
Hard |
Higher cutoff, more accurate |
|
Soft |
Lower cutoff, faster |
|
GW-ready |
For GW calculations |
Example 1: Transition Metals (Fe)#
For 3d transition metals, the standard POTCAR freezes 3s3p electrons. This can cause errors in:
Magnetic properties
Oxide compounds
High-pressure calculations
Recommendation: Use _pv for transition metal oxides and magnetic systems.
from ase.build import bulk
from vasp import Vasp
# Create BCC Fe
fe = bulk('Fe', 'bcc', a=2.87)
fe.set_initial_magnetic_moments([2.5])
# Standard Fe POTCAR (8 valence electrons: 3d6 4s2)
# Freezes 3s and 3p core electrons
calc_standard = Vasp(
label='results/fe_standard',
atoms=fe.copy(),
xc='PBE',
encut=400,
kpts=(12, 12, 12),
ispin=2,
# No setups = use default Fe POTCAR
)
print("Standard Fe: 8 valence electrons (3d6 4s2)")
print("ENCUT = 400 eV is sufficient")
Standard Fe: 8 valence electrons (3d6 4s2)
ENCUT = 400 eV is sufficient
# Fe_pv POTCAR (14 valence electrons: 3p6 3d6 4s2)
# Includes 3p semi-core states
calc_pv = Vasp(
label='results/fe_pv',
atoms=fe.copy(),
xc='PBE',
encut=450, # Higher cutoff needed for _pv
kpts=(12, 12, 12),
ispin=2,
setups={'Fe': 'pv'}, # Use Fe_pv POTCAR
)
print("Fe_pv: 14 valence electrons (3p6 3d6 4s2)")
print("ENCUT = 450 eV recommended")
print("More accurate for oxides and magnetic systems")
Fe_pv: 14 valence electrons (3p6 3d6 4s2)
ENCUT = 450 eV recommended
More accurate for oxides and magnetic systems
Example 2: Perovskite Oxides (SrTiO₃)#
For perovskites (ABO₃), recommended setups:
A-site (Sr, Ba, Ca): Use
_svor_pvB-site (Ti, Zr, Fe): Use
_pvO: Standard is usually fine
from ase import Atoms
# Create cubic SrTiO3
a = 3.905 # Lattice constant in Å
srtio3 = Atoms(
'SrTiO3',
positions=[
(0.0, 0.0, 0.0), # Sr at corner
(a/2, a/2, a/2), # Ti at body center
(a/2, a/2, 0.0), # O at face centers
(a/2, 0.0, a/2),
(0.0, a/2, a/2),
],
cell=[a, a, a],
pbc=True,
)
print(f"SrTiO3 unit cell: {len(srtio3)} atoms")
print(f"Lattice constant: {a} Å")
SrTiO3 unit cell: 5 atoms
Lattice constant: 3.905 Å
# Recommended setups for perovskites
setups = {
'Sr': 'sv', # Include 4s4p semi-core (10 valence e-)
'Ti': 'pv', # Include 3p semi-core (10 valence e-)
'O': '', # Standard O is fine (6 valence e-)
}
calc = Vasp(
label='results/srtio3',
atoms=srtio3,
xc='PBE',
encut=520, # Higher cutoff for _sv/_pv
kpts=(6, 6, 6),
setups=setups,
)
print("Setups:")
for elem, setup in setups.items():
variant = f"_{setup}" if setup else " (standard)"
print(f" {elem}: {elem}{variant}")
Setups:
Sr: Sr_sv
Ti: Ti_pv
O: O (standard)
Example 3: Battery Materials (LiFePO₄)#
For Li-ion battery cathodes:
Li: Use
_sv(CRITICAL - treats 1s as valence)Transition metals: Use
_pvP, O: Standard is fine
Why Li_sv is important#
POTCAR |
Valence e⁻ |
Core |
Notes |
|---|---|---|---|
Li |
1 |
1s² |
May underestimate Li binding |
Li_sv |
3 |
none |
Accurate for intercalation voltages |
# Battery material setups
battery_setups = {
'Li': 'sv', # CRITICAL: Include 1s electrons (3 valence e-)
'Fe': 'pv', # Include 3p semi-core (14 valence e-)
'P': '', # Standard is fine (5 valence e-)
'O': '', # Standard is fine (6 valence e-)
}
print("Recommended setups for LiFePO4:")
for elem, setup in battery_setups.items():
variant = f"_{setup}" if setup else " (standard)"
print(f" {elem}: {elem}{variant}")
print("\nNote: Li_sv requires ENCUT ≥ 650 eV due to high ENMAX (499 eV)")
Recommended setups for LiFePO4:
Li: Li_sv
Fe: Fe_pv
P: P (standard)
O: O (standard)
Note: Li_sv requires ENCUT ≥ 650 eV due to high ENMAX (499 eV)
ENCUT Recommendations#
Each POTCAR has an ENMAX value (recommended minimum plane-wave cutoff).
Rule of thumb: ENCUT ≥ 1.3 × max(ENMAX)
Typical ENMAX values (eV)#
Element |
Standard |
_pv |
_sv |
Notes |
|---|---|---|---|---|
Li |
140 |
- |
499 |
Use _sv for batteries |
Na |
102 |
265 |
646 |
Use _pv minimum |
K |
117 |
117 |
249 |
Standard already has 3s3p |
Ca |
267 |
267 |
267 |
All variants similar |
Ti |
178 |
222 |
275 |
Use _pv for oxides |
Fe |
268 |
293 |
391 |
Use _pv for oxides |
O |
400 |
- |
- |
Standard is fine |
Sr |
- |
- |
229 |
Use _sv for perovskites |
# ENCUT calculation helper
def recommend_encut(elements_enmax: dict, factor: float = 1.3) -> int:
"""Calculate recommended ENCUT from element ENMAX values."""
max_enmax = max(elements_enmax.values())
encut = int(factor * max_enmax / 10) * 10 # Round to nearest 10
return encut
# Example: Fe2O3 with Fe_pv
fe2o3_enmax = {'Fe_pv': 293, 'O': 400}
print(f"Fe2O3 (Fe_pv): max ENMAX = {max(fe2o3_enmax.values())} eV")
print(f"Recommended ENCUT = {recommend_encut(fe2o3_enmax)} eV")
print()
# Example: LiFePO4 with Li_sv, Fe_pv
lifepo4_enmax = {'Li_sv': 499, 'Fe_pv': 293, 'P': 255, 'O': 400}
print(f"LiFePO4 (Li_sv, Fe_pv): max ENMAX = {max(lifepo4_enmax.values())} eV")
print(f"Recommended ENCUT = {recommend_encut(lifepo4_enmax)} eV")
Fe2O3 (Fe_pv): max ENMAX = 400 eV
Recommended ENCUT = 520 eV
LiFePO4 (Li_sv, Fe_pv): max ENMAX = 499 eV
Recommended ENCUT = 640 eV
Material-Specific Recommendations#
Perovskite Oxides (ABO₃)#
perovskite_setups = {
# A-site
'Sr': 'sv', 'Ba': 'sv', 'Ca': 'pv', 'La': '', 'Pb': 'd',
# B-site
'Ti': 'pv', 'Zr': 'sv', 'Fe': 'pv', 'Mn': 'pv', 'Nb': 'pv',
# Oxygen
'O': '',
}
print("Perovskite oxide setups:")
print(" A-site: Sr_sv, Ba_sv, Ca_pv, La (std), Pb_d")
print(" B-site: Ti_pv, Zr_sv, Fe_pv, Mn_pv, Nb_pv")
print(" O: standard")
print(" ENCUT: 520 eV")
Perovskite oxide setups:
A-site: Sr_sv, Ba_sv, Ca_pv, La (std), Pb_d
B-site: Ti_pv, Zr_sv, Fe_pv, Mn_pv, Nb_pv
O: standard
ENCUT: 520 eV
Battery Cathode Materials#
battery_setups = {
# Alkali
'Li': 'sv', 'Na': 'pv',
# Transition metals
'Fe': 'pv', 'Mn': 'pv', 'Co': '', 'Ni': '',
# Anions
'O': '', 'P': '', 'S': '',
}
print("Battery cathode setups:")
print(" Alkali: Li_sv (critical!), Na_pv")
print(" TM: Fe_pv, Mn_pv, Co (std), Ni (std)")
print(" Anions: O, P, S (all standard)")
print(" ENCUT: 520 eV (650 eV with Li_sv)")
Battery cathode setups:
Alkali: Li_sv (critical!), Na_pv
TM: Fe_pv, Mn_pv, Co (std), Ni (std)
Anions: O, P, S (all standard)
ENCUT: 520 eV (650 eV with Li_sv)
Semiconductors#
# Standard potentials usually sufficient for semiconductors
semiconductor_setups = {
'Si': '', # Standard
'Ge': 'd', # Include d for better band structure
'Ga': 'd', # Include d
'As': '', # Standard
'N': '', # Standard
}
print("Semiconductor setups:")
print(" Group IV: Si (std), Ge_d")
print(" III-V: Ga_d, As (std), N (std)")
print(" ENCUT: 400-520 eV")
Semiconductor setups:
Group IV: Si (std), Ge_d
III-V: Ga_d, As (std), N (std)
ENCUT: 400-520 eV
Summary: Quick Reference#
When to use _pv#
3d transition metals in oxides
Magnetic systems
High-pressure calculations
When to use _sv#
Alkali metals (Li, Na, K) in batteries
Alkaline earth metals (Ca, Sr, Ba) in perovskites
When highest accuracy is needed
General guidelines#
Check VASP wiki for specific recommendations
Test convergence with ENCUT for your system
Compare variants for critical properties
Document your choices for reproducibility
# Complete example with all parameters
from ase import Atoms
from ase.build import bulk
from vasp import Vasp
# Example: Fe2O3 (hematite) - create manually since ASE doesn't have corundum
# Using a simplified rhombohedral cell
a = 5.035 # Lattice parameter in Å
c = 13.747
# Create Fe2O3 with hexagonal setting (simplified 2 formula units)
fe2o3 = Atoms(
symbols=['Fe', 'Fe', 'Fe', 'Fe', 'O', 'O', 'O', 'O', 'O', 'O'],
scaled_positions=[
(0.0, 0.0, 0.355), # Fe
(0.0, 0.0, 0.145), # Fe
(0.0, 0.0, 0.645), # Fe
(0.0, 0.0, 0.855), # Fe
(0.306, 0.0, 0.25), # O
(0.0, 0.306, 0.25), # O
(0.694, 0.694, 0.25), # O
(0.694, 0.0, 0.75), # O
(0.0, 0.694, 0.75), # O
(0.306, 0.306, 0.75), # O
],
cell=[(a, 0, 0),
(-a/2, a*0.866, 0),
(0, 0, c)],
pbc=True,
)
calc = Vasp(
label='results/fe2o3',
atoms=fe2o3,
xc='PBE',
setups={
'Fe': 'pv', # Include 3p semi-core
'O': '', # Standard oxygen
},
encut=520, # 1.3 × max(ENMAX)
kpts=(4, 4, 2),
ispin=2, # Spin-polarized for Fe
lorbit=11, # Project onto atoms
)
print("Fe2O3 (hematite) calculation configured with:")
print(f" Atoms: {len(fe2o3)} ({fe2o3.get_chemical_formula()})")
print(f" setups = {calc.parameters.get('setups', {})}")
print(f" encut = {calc.parameters.get('encut')} eV")
Fe2O3 (hematite) calculation configured with:
Atoms: 10 (Fe4O6)
setups = {'Fe': 'pv', 'O': ''}
encut = 520 eV