valyte 0.1.9__py3-none-any.whl → 0.1.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- valyte/band.py +135 -177
- valyte/band_plot.py +25 -66
- valyte/cli.py +66 -81
- valyte/dos_plot.py +137 -306
- valyte/ipr.py +186 -0
- valyte/kpoints.py +26 -54
- valyte/potcar.py +29 -54
- valyte/supercell.py +5 -22
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/METADATA +60 -1
- valyte-0.1.11.dist-info/RECORD +19 -0
- valyte-0.1.9.dist-info/RECORD +0 -18
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/WHEEL +0 -0
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/entry_points.txt +0 -0
- {valyte-0.1.9.dist-info → valyte-0.1.11.dist-info}/top_level.txt +0 -0
valyte/ipr.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Inverse participation ratio (IPR) from VASP PROCAR."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
import numpy as np
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def read_procar(filename="PROCAR"):
|
|
9
|
+
"""Read PROCAR and extract atomic total projections."""
|
|
10
|
+
if not os.path.exists(filename):
|
|
11
|
+
raise FileNotFoundError(f"{filename} not found")
|
|
12
|
+
|
|
13
|
+
with open(filename, "r") as f:
|
|
14
|
+
lines = f.readlines()
|
|
15
|
+
|
|
16
|
+
header_line = next((l for l in lines if "k-points" in l), None)
|
|
17
|
+
if header_line is None:
|
|
18
|
+
raise ValueError("Could not find PROCAR header with k-points/bands/ions")
|
|
19
|
+
|
|
20
|
+
numbers = [int(x) for x in re.findall(r"\d+", header_line)]
|
|
21
|
+
if len(numbers) < 3:
|
|
22
|
+
raise ValueError("PROCAR header does not contain k-points, bands, and ions")
|
|
23
|
+
|
|
24
|
+
nkpts, nbands, natoms = numbers[0], numbers[1], numbers[2]
|
|
25
|
+
|
|
26
|
+
proj = [[[] for _ in range(nbands)] for _ in range(nkpts)]
|
|
27
|
+
energies = [[0.0 for _ in range(nbands)] for _ in range(nkpts)]
|
|
28
|
+
|
|
29
|
+
ik = -1
|
|
30
|
+
ib = -1
|
|
31
|
+
|
|
32
|
+
for raw in lines:
|
|
33
|
+
line = raw.strip()
|
|
34
|
+
if not line:
|
|
35
|
+
continue
|
|
36
|
+
|
|
37
|
+
if line.startswith("k-point"):
|
|
38
|
+
ik += 1
|
|
39
|
+
ib = -1
|
|
40
|
+
continue
|
|
41
|
+
|
|
42
|
+
if line.startswith("band"):
|
|
43
|
+
ib += 1
|
|
44
|
+
parts = line.split()
|
|
45
|
+
if len(parts) > 4:
|
|
46
|
+
energies[ik][ib] = float(parts[4])
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
if line[0].isdigit() and ik >= 0 and ib >= 0:
|
|
50
|
+
parts = line.split()
|
|
51
|
+
proj[ik][ib].append(float(parts[-1]))
|
|
52
|
+
|
|
53
|
+
return proj, energies, nkpts, nbands, natoms
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def compute_ipr_atomic(projections):
|
|
57
|
+
"""Compute atomic IPR from atomic projections."""
|
|
58
|
+
projections = np.array(projections)
|
|
59
|
+
tot = projections.sum()
|
|
60
|
+
if tot < 1e-12:
|
|
61
|
+
return 0.0
|
|
62
|
+
weights = projections / tot
|
|
63
|
+
return np.sum(weights ** 2)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def analyze_bands(proj, energies, nkpts, band_indices, verbose=True):
|
|
67
|
+
"""Compute k-averaged atomic IPR for selected bands."""
|
|
68
|
+
results = []
|
|
69
|
+
|
|
70
|
+
for iband in band_indices:
|
|
71
|
+
ipr_k = []
|
|
72
|
+
e_k = []
|
|
73
|
+
|
|
74
|
+
if verbose:
|
|
75
|
+
print(f"\nBand {iband}")
|
|
76
|
+
|
|
77
|
+
for ik in range(nkpts):
|
|
78
|
+
ipr = compute_ipr_atomic(proj[ik][iband - 1])
|
|
79
|
+
ipr_k.append(ipr)
|
|
80
|
+
e_k.append(energies[ik][iband - 1])
|
|
81
|
+
|
|
82
|
+
if verbose:
|
|
83
|
+
neff = (1 / ipr) if ipr > 0 else 0.0
|
|
84
|
+
print(
|
|
85
|
+
f" k-point {ik + 1:3d} "
|
|
86
|
+
f"E = {energies[ik][iband - 1]:8.4f} eV "
|
|
87
|
+
f"IPR = {ipr:8.4f} "
|
|
88
|
+
f"N_eff = {neff:8.2f}"
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
avg_ipr = float(np.mean(ipr_k)) if ipr_k else 0.0
|
|
92
|
+
avg_e = float(np.mean(e_k)) if e_k else 0.0
|
|
93
|
+
neff = (1 / avg_ipr) if avg_ipr > 0 else 0.0
|
|
94
|
+
|
|
95
|
+
if verbose:
|
|
96
|
+
print(" ------------------------------")
|
|
97
|
+
print(f" Avg IPR = {avg_ipr:.4f}")
|
|
98
|
+
print(f" N_eff = {neff:.2f}")
|
|
99
|
+
|
|
100
|
+
results.append((iband, avg_e, avg_ipr, neff))
|
|
101
|
+
|
|
102
|
+
return results
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def save_results(results, filename="ipr_procar.dat"):
|
|
106
|
+
"""Save IPR results to a file."""
|
|
107
|
+
with open(filename, "w") as f:
|
|
108
|
+
f.write("# Band Energy(eV) IPR N_eff\n")
|
|
109
|
+
for band, e, ipr, neff in results:
|
|
110
|
+
f.write(f"{band:5d} {e:10.6f} {ipr:8.4f} {neff:8.2f}\n")
|
|
111
|
+
|
|
112
|
+
print(f"\nResults written to {filename}")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _parse_band_indices(text):
|
|
116
|
+
tokens = re.split(r"[\s,]+", text.strip())
|
|
117
|
+
indices = []
|
|
118
|
+
seen = set()
|
|
119
|
+
|
|
120
|
+
for token in tokens:
|
|
121
|
+
if not token:
|
|
122
|
+
continue
|
|
123
|
+
if "-" in token:
|
|
124
|
+
parts = token.split("-")
|
|
125
|
+
if len(parts) != 2:
|
|
126
|
+
continue
|
|
127
|
+
try:
|
|
128
|
+
start = int(parts[0])
|
|
129
|
+
end = int(parts[1])
|
|
130
|
+
except ValueError:
|
|
131
|
+
continue
|
|
132
|
+
if start > end:
|
|
133
|
+
start, end = end, start
|
|
134
|
+
for i in range(start, end + 1):
|
|
135
|
+
if i not in seen:
|
|
136
|
+
indices.append(i)
|
|
137
|
+
seen.add(i)
|
|
138
|
+
else:
|
|
139
|
+
try:
|
|
140
|
+
i = int(token)
|
|
141
|
+
except ValueError:
|
|
142
|
+
continue
|
|
143
|
+
if i not in seen:
|
|
144
|
+
indices.append(i)
|
|
145
|
+
seen.add(i)
|
|
146
|
+
|
|
147
|
+
return indices
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def run_ipr_interactive():
|
|
151
|
+
"""Interactive IPR workflow."""
|
|
152
|
+
procar_file = "PROCAR"
|
|
153
|
+
|
|
154
|
+
try:
|
|
155
|
+
proj, energies, nkpts, nbands, natoms = read_procar(procar_file)
|
|
156
|
+
except Exception as e:
|
|
157
|
+
print(f"Error: {e}")
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
print("PROCAR info")
|
|
161
|
+
print(f" k-points : {nkpts}")
|
|
162
|
+
print(f" bands : {nbands}")
|
|
163
|
+
print(f" atoms : {natoms}")
|
|
164
|
+
|
|
165
|
+
band_text = input("Band indices (e.g., 5 6 7 or 5-7): ").strip()
|
|
166
|
+
if not band_text:
|
|
167
|
+
print("No band indices provided.")
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
band_indices = _parse_band_indices(band_text)
|
|
171
|
+
if not band_indices:
|
|
172
|
+
print("No valid band indices found.")
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
filtered = [b for b in band_indices if 1 <= b <= nbands]
|
|
176
|
+
if not filtered:
|
|
177
|
+
print(f"No bands in range 1..{nbands}.")
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
if len(filtered) != len(band_indices):
|
|
181
|
+
print("Warning: some bands were out of range and were skipped.")
|
|
182
|
+
|
|
183
|
+
show_details = input("Show per-k-point values? [y/N]: ").strip().lower() == "y"
|
|
184
|
+
|
|
185
|
+
results = analyze_bands(proj, energies, nkpts, filtered, verbose=show_details)
|
|
186
|
+
save_results(results, "ipr_procar.dat")
|
valyte/kpoints.py
CHANGED
|
@@ -1,108 +1,80 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Interactive K-Point Generation Module
|
|
3
|
-
=====================================
|
|
4
|
-
|
|
5
|
-
Handles interactive generation of KPOINTS files based on user input and structure.
|
|
6
|
-
"""
|
|
1
|
+
"""Interactive KPOINTS generation."""
|
|
7
2
|
|
|
8
3
|
import os
|
|
9
|
-
import sys
|
|
10
4
|
import numpy as np
|
|
11
5
|
from pymatgen.core import Structure
|
|
12
6
|
from pymatgen.io.vasp.inputs import Kpoints
|
|
13
7
|
from valyte.potcar import generate_potcar
|
|
14
8
|
|
|
9
|
+
|
|
15
10
|
def generate_kpoints_interactive():
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
print("\n🔮 Valyte K-Point Generator")
|
|
20
|
-
|
|
21
|
-
# Check for POSCAR
|
|
11
|
+
"""Interactively generate a KPOINTS file based on POSCAR and user input."""
|
|
12
|
+
print("\nValyte K-Point Generator")
|
|
13
|
+
|
|
22
14
|
poscar_path = "POSCAR"
|
|
23
15
|
if not os.path.exists(poscar_path):
|
|
24
|
-
|
|
25
|
-
files = [f for f in os.listdir('.') if f.startswith('POSCAR')]
|
|
16
|
+
files = [f for f in os.listdir(".") if f.startswith("POSCAR")]
|
|
26
17
|
if files:
|
|
27
18
|
poscar_path = files[0]
|
|
28
|
-
print(f"
|
|
19
|
+
print(f"Found structure: {poscar_path}")
|
|
29
20
|
else:
|
|
30
|
-
print("
|
|
21
|
+
print("Error: POSCAR file not found in current directory.")
|
|
31
22
|
return
|
|
32
23
|
|
|
33
24
|
try:
|
|
34
25
|
structure = Structure.from_file(poscar_path)
|
|
35
26
|
except Exception as e:
|
|
36
|
-
print(f"
|
|
27
|
+
print(f"Error reading structure: {e}")
|
|
37
28
|
return
|
|
38
29
|
|
|
39
|
-
# Scheme Selection
|
|
40
30
|
print("\nSelect K-Mesh Scheme:")
|
|
41
31
|
print(" 1. Monkhorst-Pack")
|
|
42
32
|
print(" 2. Gamma (Default)")
|
|
43
|
-
|
|
33
|
+
|
|
44
34
|
choice = input(" > ").strip()
|
|
45
|
-
|
|
46
|
-
if choice == '1':
|
|
47
|
-
scheme = 'MP'
|
|
48
|
-
else:
|
|
49
|
-
scheme = 'Gamma'
|
|
35
|
+
scheme = "MP" if choice == "1" else "Gamma"
|
|
50
36
|
|
|
51
|
-
# K-Spacing Input
|
|
52
37
|
print("\nEnter K-Spacing (units of 2π/Å):")
|
|
53
|
-
print("
|
|
54
|
-
|
|
38
|
+
print(" Typical values: 0.03 - 0.04")
|
|
39
|
+
|
|
55
40
|
try:
|
|
56
41
|
kspacing_str = input(" > ").strip()
|
|
57
|
-
if
|
|
58
|
-
kspacing = 0.04 # Default
|
|
59
|
-
else:
|
|
60
|
-
kspacing = float(kspacing_str)
|
|
42
|
+
kspacing = float(kspacing_str) if kspacing_str else 0.04
|
|
61
43
|
except ValueError:
|
|
62
|
-
print("
|
|
44
|
+
print("Error: invalid number.")
|
|
63
45
|
return
|
|
64
46
|
|
|
65
47
|
if kspacing <= 0:
|
|
66
|
-
print("
|
|
48
|
+
print("Using Gamma-only grid (1 1 1)")
|
|
67
49
|
kpts = Kpoints.gamma_automatic((1, 1, 1))
|
|
68
50
|
grid = (1, 1, 1)
|
|
69
51
|
else:
|
|
70
|
-
# Calculate grid based on spacing
|
|
71
|
-
# Formula: N = |b| / (spacing * 2*pi)
|
|
72
|
-
# pymatgen reciprocal lattice lengths include the 2*pi factor.
|
|
73
|
-
|
|
74
52
|
recip_lattice = structure.lattice.reciprocal_lattice
|
|
75
53
|
b_lengths = recip_lattice.abc
|
|
76
|
-
|
|
77
|
-
#
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
# Create Kpoints object
|
|
83
|
-
if scheme == 'MP':
|
|
54
|
+
|
|
55
|
+
# KSPACING-style estimate: N = |b| / kspacing
|
|
56
|
+
grid = [max(1, int(l / kspacing + 0.5)) for l in b_lengths]
|
|
57
|
+
|
|
58
|
+
if scheme == "MP":
|
|
84
59
|
kpts = Kpoints.monkhorst_automatic(grid)
|
|
85
60
|
else:
|
|
86
61
|
kpts = Kpoints.gamma_automatic(grid)
|
|
87
62
|
|
|
88
|
-
|
|
89
|
-
print("\n📊 Summary")
|
|
63
|
+
print("\nSummary")
|
|
90
64
|
print(f" Structure: {structure.formula}")
|
|
91
65
|
print(f" Lattice: a={structure.lattice.a:.2f}, b={structure.lattice.b:.2f}, c={structure.lattice.c:.2f} Å")
|
|
92
66
|
print(f" K-Mesh: {grid[0]} x {grid[1]} x {grid[2]} ({scheme})")
|
|
93
67
|
|
|
94
|
-
# Write KPOINTS
|
|
95
68
|
output_file = "KPOINTS"
|
|
96
69
|
kpts.write_file(output_file)
|
|
97
|
-
print(f"\
|
|
70
|
+
print(f"\nGenerated {output_file}.")
|
|
98
71
|
|
|
99
|
-
# --- POTCAR Generation (if missing) ---
|
|
100
72
|
potcar_file = "POTCAR"
|
|
101
73
|
if not os.path.exists(potcar_file):
|
|
102
74
|
try:
|
|
103
|
-
print(
|
|
75
|
+
print("\nPOTCAR not found. Generating default POTCAR (PBE)...")
|
|
104
76
|
generate_potcar(poscar_path=poscar_path, functional="PBE", output=potcar_file)
|
|
105
77
|
except Exception as e:
|
|
106
|
-
print(f"
|
|
78
|
+
print(f"Warning: could not generate POTCAR: {e}")
|
|
107
79
|
else:
|
|
108
|
-
print(
|
|
80
|
+
print("POTCAR already exists; skipping generation.")
|
valyte/potcar.py
CHANGED
|
@@ -1,61 +1,36 @@
|
|
|
1
1
|
import os
|
|
2
|
-
import sys
|
|
3
2
|
from pymatgen.core import Structure
|
|
4
|
-
from pymatgen.io.vasp.
|
|
3
|
+
from pymatgen.io.vasp.inputs import Potcar
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _ordered_symbols(structure):
|
|
7
|
+
symbols = []
|
|
8
|
+
seen = set()
|
|
9
|
+
for site in structure:
|
|
10
|
+
sym = site.specie.symbol if hasattr(site.specie, "symbol") else str(site.specie)
|
|
11
|
+
if sym not in seen:
|
|
12
|
+
symbols.append(sym)
|
|
13
|
+
seen.add(sym)
|
|
14
|
+
return symbols
|
|
15
|
+
|
|
5
16
|
|
|
6
17
|
def generate_potcar(poscar_path="POSCAR", functional="PBE", output="POTCAR"):
|
|
7
|
-
"""
|
|
8
|
-
Generates a POTCAR file based on the species in the POSCAR using Pymatgen configuration.
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
poscar_path (str): Path to input POSCAR file.
|
|
12
|
-
functional (str): Functional to use (e.g., "PBE", "PBE_52", "PBE_54", "LDA").
|
|
13
|
-
Defaults to "PBE" which usually maps to the configured default (often PBE_54).
|
|
14
|
-
output (str): Output filename.
|
|
15
|
-
"""
|
|
18
|
+
"""Generate a POTCAR based on species in a POSCAR."""
|
|
16
19
|
if not os.path.exists(poscar_path):
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
raise FileNotFoundError(f"Input file '{poscar_path}' not found.")
|
|
21
|
+
|
|
22
|
+
structure = Structure.from_file(poscar_path)
|
|
23
|
+
species = _ordered_symbols(structure)
|
|
24
|
+
|
|
25
|
+
print(f"Reading structure from {poscar_path}...")
|
|
26
|
+
print(f"Detected species: {species}")
|
|
19
27
|
|
|
20
28
|
try:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# Pymatgen's Potcar.from_file is for reading.
|
|
30
|
-
# We want to CREATE.
|
|
31
|
-
# Potcar(symbols, functional)
|
|
32
|
-
|
|
33
|
-
# Let's verify which method is best.
|
|
34
|
-
# structure.species gives list of all sites.
|
|
35
|
-
# We need unique species in order of appearance in POSCAR (usually).
|
|
36
|
-
# Wrapper: pymatgen.io.vasp.sets often handles this (e.g. MPRelaxSet),
|
|
37
|
-
# but that generates INCAR/KPOINTS too.
|
|
38
|
-
# Let's stick to just Potcar.
|
|
39
|
-
|
|
40
|
-
print(f"Reading structure from {poscar_path}...")
|
|
41
|
-
print(f"Detected species: {species}")
|
|
42
|
-
|
|
43
|
-
# Use simple Potcar construction.
|
|
44
|
-
# Note: functional argument in pymatgen Potcar init is 'functional'.
|
|
45
|
-
# Assuming Pymatgen is configured correctly, this should work.
|
|
46
|
-
|
|
47
|
-
try:
|
|
48
|
-
# Try explicit functional mapping if user provides "PBE" but config uses "PBE_54" etc
|
|
49
|
-
potcar = Potcar(species, functional=functional)
|
|
50
|
-
except OSError:
|
|
51
|
-
# Fallback or specific error msg about PMG setup
|
|
52
|
-
print(f"⚠️ Could not find POTCARs for functional '{functional}'.")
|
|
53
|
-
print(" Please ensure PMG_VASP_PSP_DIR is set in ~/.pmgrc.yaml")
|
|
54
|
-
raise
|
|
55
|
-
|
|
56
|
-
potcar.write_file(output)
|
|
57
|
-
|
|
58
|
-
print(f"✅ Generated {output} using functional '{functional}'")
|
|
59
|
-
|
|
60
|
-
except Exception as e:
|
|
61
|
-
print(f"❌ Error generating POTCAR: {e}")
|
|
29
|
+
potcar = Potcar(species, functional=functional)
|
|
30
|
+
except OSError as e:
|
|
31
|
+
print(f"Could not find POTCARs for functional '{functional}'.")
|
|
32
|
+
print("Ensure PMG_VASP_PSP_DIR is set in ~/.pmgrc.yaml")
|
|
33
|
+
raise e
|
|
34
|
+
|
|
35
|
+
potcar.write_file(output)
|
|
36
|
+
print(f"Generated {output} using functional '{functional}'")
|
valyte/supercell.py
CHANGED
|
@@ -1,35 +1,18 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Supercell generation module for Valyte.
|
|
3
|
-
"""
|
|
1
|
+
"""Supercell generation."""
|
|
4
2
|
|
|
5
3
|
import os
|
|
6
4
|
from pymatgen.core import Structure
|
|
7
5
|
|
|
8
6
|
|
|
9
7
|
def create_supercell(poscar_path="POSCAR", nx=1, ny=1, nz=1, output="POSCAR_supercell"):
|
|
10
|
-
"""
|
|
11
|
-
Creates a supercell from a POSCAR file.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
poscar_path (str): Path to input POSCAR file.
|
|
15
|
-
nx (int): Supercell size in x direction.
|
|
16
|
-
ny (int): Supercell size in y direction.
|
|
17
|
-
nz (int): Supercell size in z direction.
|
|
18
|
-
output (str): Output filename for the supercell POSCAR.
|
|
19
|
-
"""
|
|
20
|
-
|
|
8
|
+
"""Create a supercell from a POSCAR file."""
|
|
21
9
|
if not os.path.exists(poscar_path):
|
|
22
10
|
raise FileNotFoundError(f"{poscar_path} not found")
|
|
23
|
-
|
|
24
|
-
# Read structure
|
|
11
|
+
|
|
25
12
|
structure = Structure.from_file(poscar_path)
|
|
26
|
-
|
|
27
|
-
# Create supercell
|
|
28
13
|
supercell = structure.copy()
|
|
29
14
|
supercell.make_supercell([nx, ny, nz])
|
|
30
|
-
|
|
31
|
-
# Write output
|
|
32
15
|
supercell.to(filename=output, fmt="poscar")
|
|
33
|
-
|
|
16
|
+
|
|
34
17
|
supercell_atoms = len(supercell)
|
|
35
|
-
print(f"
|
|
18
|
+
print(f"Supercell created: {output} ({supercell_atoms} atoms)")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: valyte
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.11
|
|
4
4
|
Summary: A comprehensive CLI tool for VASP pre-processing (Supercells, K-points) and post-processing (DOS, Band Structure plotting)
|
|
5
5
|
Home-page: https://github.com/nikyadav002/Valyte-Project
|
|
6
6
|
Author: Nikhil
|
|
@@ -42,6 +42,7 @@ Requires-Dist: seekpath
|
|
|
42
42
|
- VBM alignment to 0 eV.
|
|
43
43
|
- Color-coded bands (Purple for VB, Teal for CB).
|
|
44
44
|
- High-symmetry path labels from KPOINTS.
|
|
45
|
+
- **IPR Analysis**: Compute Inverse Participation Ratio from PROCAR to analyze wavefunction localization.
|
|
45
46
|
- **Publication Quality**: Clean aesthetics, custom fonts (Arial, Helvetica, Times New Roman), high DPI output.
|
|
46
47
|
|
|
47
48
|
## Installation
|
|
@@ -152,6 +153,38 @@ This command will prompt you for:
|
|
|
152
153
|
|
|
153
154
|
It automatically calculates the optimal grid based on your `POSCAR` structure.
|
|
154
155
|
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### 🧪 Generate POTCAR
|
|
159
|
+
|
|
160
|
+
Generate a `POTCAR` file based on the species in your `POSCAR`.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
valyte potcar [options]
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Options:**
|
|
167
|
+
- `-i`, `--input`: Input POSCAR file (default: `POSCAR`).
|
|
168
|
+
- `-o`, `--output`: Output filename (default: `POTCAR`).
|
|
169
|
+
- `--functional`: Functional to use (default: `PBE`). Options include `PBE`, `PBE_52`, `PBE_54`, `LDA`, etc.
|
|
170
|
+
|
|
171
|
+
**Example:**
|
|
172
|
+
```bash
|
|
173
|
+
# Generate POTCAR using default PBE functional
|
|
174
|
+
valyte potcar
|
|
175
|
+
|
|
176
|
+
# Use a specific functional
|
|
177
|
+
valyte potcar --functional PBE_54
|
|
178
|
+
|
|
179
|
+
# Specify input and output files
|
|
180
|
+
valyte potcar -i POSCAR_relaxed -o POTCAR_new
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
> [!IMPORTANT]
|
|
184
|
+
> **Pymatgen Configuration Required**: This command requires Pymatgen to be configured with your VASP pseudopotential directory. Set `PMG_VASP_PSP_DIR` in your `~/.pmgrc.yaml` file. See the [Pymatgen documentation](https://pymatgen.org/installation.html#potcar-setup) for setup instructions.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
155
188
|
#### 2. Plot Band Structure
|
|
156
189
|
|
|
157
190
|
Plot the electronic band structure from `vasprun.xml`.
|
|
@@ -216,4 +249,30 @@ valyte dos -e Fe "Fe(d)"
|
|
|
216
249
|
valyte dos ./vasp_data --xlim -5 5 -o my_dos.png
|
|
217
250
|
```
|
|
218
251
|
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### 📐 Compute IPR (Inverse Participation Ratio)
|
|
255
|
+
|
|
256
|
+
Compute the Inverse Participation Ratio (IPR) from VASP `PROCAR` to analyze wavefunction localization.
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
valyte ipr
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
This interactive command will:
|
|
263
|
+
1. Read the `PROCAR` file from the current directory.
|
|
264
|
+
2. Display the number of k-points, bands, and atoms.
|
|
265
|
+
3. Prompt you for **band indices** to analyze (e.g., `5 6 7` or `5-7`).
|
|
266
|
+
4. Optionally show per-k-point IPR values.
|
|
267
|
+
5. Save results to `ipr_procar.dat`.
|
|
268
|
+
|
|
269
|
+
**Output Columns:**
|
|
270
|
+
- **Band**: Band index.
|
|
271
|
+
- **Energy**: Average energy (eV) across k-points.
|
|
272
|
+
- **IPR**: Inverse Participation Ratio (higher = more localized).
|
|
273
|
+
- **N_eff**: Effective number of atoms (1/IPR).
|
|
274
|
+
|
|
275
|
+
> [!TIP]
|
|
276
|
+
> Use IPR to identify localized defect states. A state localized on a single atom has IPR ≈ 1.0 and N_eff ≈ 1. Delocalized band states have small IPR and large N_eff.
|
|
277
|
+
|
|
219
278
|
</details>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
valyte/Logo.png,sha256=HSZQsjsCj4y_8zeXE1kR1W7deb-6gXheEnmcLcSKUxw,4327936
|
|
2
|
+
valyte/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
valyte/band.py,sha256=ckwLeIvU1goyxRYusWl-yqdZRZDmYBVOF3fhwGzEEAg,8738
|
|
4
|
+
valyte/band_plot.py,sha256=XTx6zFrLaTo_GYYvANulMl_0eFSQCyRqJCPfYJffXdg,2869
|
|
5
|
+
valyte/cli.py,sha256=xmGEOOfOQOsOzJ_dhzMDOSfuimL_1X--nlmBiQ_WG9Q,8816
|
|
6
|
+
valyte/dos_plot.py,sha256=iMjvSevX61PqmOOye7uNirj2bh9uFdlgZZXfCK1oGWo,10771
|
|
7
|
+
valyte/ipr.py,sha256=cT6G10Zt__TRSx-Vt7HiCPRVC8uTz5JNWzQN-2J7df0,5316
|
|
8
|
+
valyte/kpoints.py,sha256=Qh80UmEwt3OssPoEwN8PaVc9E7KG_W-vR0_kP7IzoZ0,2632
|
|
9
|
+
valyte/potcar.py,sha256=7JRo1Tkz1M6kqVYKbAYkkPVlt1gqeqjMKkpFWWzXdTk,1160
|
|
10
|
+
valyte/supercell.py,sha256=5qeeeJN81LAGdzdgEtYIMy8-g4T4xKRm_cxbsVuVBQA,595
|
|
11
|
+
valyte/valyte_band.png,sha256=1Bh-x7qvl1j4D9HGGbQK8OlMUrTU1mhU_kMILUsNiD8,246677
|
|
12
|
+
valyte/valyte_dos.png,sha256=ViE4CycCSqFi_ZtUhA7oGI1nTyt0mHoYI6yg5-Et35k,182523
|
|
13
|
+
valyte/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
valyte/data/bradcrack.json,sha256=Jpaf7giqp99BAhFdLv9pRFsx_m-ooQaQpOrPDusuZX4,22614
|
|
15
|
+
valyte-0.1.11.dist-info/METADATA,sha256=PpUiK7lOajinqNTEtpNrzYjS0-5ARSk07hTDv-bLL2s,8160
|
|
16
|
+
valyte-0.1.11.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
17
|
+
valyte-0.1.11.dist-info/entry_points.txt,sha256=Ny3Z5rh3Ia7lEKoMDDZOm4_jS-Zde3qFHv8f1GLUdxk,43
|
|
18
|
+
valyte-0.1.11.dist-info/top_level.txt,sha256=72-UqyU15JSWDjtBQf6cY0_UBqz0EU2FoVeXjd1JZ5M,7
|
|
19
|
+
valyte-0.1.11.dist-info/RECORD,,
|
valyte-0.1.9.dist-info/RECORD
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
valyte/Logo.png,sha256=HSZQsjsCj4y_8zeXE1kR1W7deb-6gXheEnmcLcSKUxw,4327936
|
|
2
|
-
valyte/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
valyte/band.py,sha256=RrzNQOzUlIXThVNJx_ONgpudJNAykjVwWgVNyl96h9w,12130
|
|
4
|
-
valyte/band_plot.py,sha256=2jP6fEh8qDYHXxDAs4S69xDcxrzWbYcjOAWiGHwjyF4,4766
|
|
5
|
-
valyte/cli.py,sha256=GzJ7ql6CJwfg52-rdJrGHaEO_BOy50QZNldXoMuJEpw,9886
|
|
6
|
-
valyte/dos_plot.py,sha256=PWlUSlF887-s2SXuHEjMiGLdo4_5419SVwVn1xTYvQQ,18972
|
|
7
|
-
valyte/kpoints.py,sha256=PxXsR7DugXUgWFcJfXigkfk6NY4Lu6bMivefGUIbCkY,3571
|
|
8
|
-
valyte/potcar.py,sha256=wd-QQNhbxfuQCZOTxCfcxQmCWJOoi3qgnIfK8H6fFxQ,2606
|
|
9
|
-
valyte/supercell.py,sha256=w6Ik_krXoshgliJDiyjoIZXuifzN0ydi6VSmpzutm9Y,996
|
|
10
|
-
valyte/valyte_band.png,sha256=1Bh-x7qvl1j4D9HGGbQK8OlMUrTU1mhU_kMILUsNiD8,246677
|
|
11
|
-
valyte/valyte_dos.png,sha256=ViE4CycCSqFi_ZtUhA7oGI1nTyt0mHoYI6yg5-Et35k,182523
|
|
12
|
-
valyte/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
valyte/data/bradcrack.json,sha256=Jpaf7giqp99BAhFdLv9pRFsx_m-ooQaQpOrPDusuZX4,22614
|
|
14
|
-
valyte-0.1.9.dist-info/METADATA,sha256=fONHYXiNPujBFABQT_XSdPGF8U_5yuGD5h1vKewVm7M,6272
|
|
15
|
-
valyte-0.1.9.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
16
|
-
valyte-0.1.9.dist-info/entry_points.txt,sha256=Ny3Z5rh3Ia7lEKoMDDZOm4_jS-Zde3qFHv8f1GLUdxk,43
|
|
17
|
-
valyte-0.1.9.dist-info/top_level.txt,sha256=72-UqyU15JSWDjtBQf6cY0_UBqz0EU2FoVeXjd1JZ5M,7
|
|
18
|
-
valyte-0.1.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|