7a_workflow_precompute_quantities.py — Precompute Phonon Quantities¶
This script covers the precomputation phase of the Disorder Linewidth pipeline (mirrors Notebooks 1-4). It must be run first; its HDF5 outputs are consumed by scripts 7b and 7c.
What it computes¶
Band structure — phonon dispersion of reference crystal graphite along a Γ-A-L-M-Γ-K-H path; saved as
dl_workflow/crystal_band_structure.png.Phonon mesh — frequencies and group velocities on a
[128, 128, 32]Γ-centred BZ mesh; saved todl_workflow/mesh_data.hdf5.Crystal VDOS and mean group speed — Lorentzian-broadened (half-width η = 0.6 cm⁻¹); saved to
dl_workflow/crystal_vdos_group_vel.hdf5.Disordered VDOS — Lorentzian-broadened from pre-computed frequencies in
2_irg_t2/irg_t2_frequencies.hdf5; saved todl_workflow/disordered_vdos.hdf5.Density-shifted crystal VDOS and speed — frequencies scaled by
(ρ_dis/ρ_crys)^(1/3)to align with the disordered system; saved todl_workflow/reduced_density_crystal_vdos_group_vel.hdf5.
Prerequisites: BNE + DL installation (see setup_dl.sh).
cd tutorials/disorder_linewidth
python 7a_workflow_precompute_quantities.py
1import os
2import sys
3
4import h5py
5import numpy as np
6import matplotlib
7import matplotlib.pyplot as plt
8import ase
9from ase.io import read
10
11from tqdm import tqdm
12
13
14from phonopy import Phonopy
15from phonopy import file_IO as phonopy_file_IO
16
17from phonopy.interface.calculator import read_crystal_structure
18from phonopy.phonon.band_structure import get_band_qpoints_and_path_connections
19
20
21from smooth_disorder.structural import obtain_density, THzToCm, THz, Angstrom
22from smooth_disorder.vis.interactive import *
23
24from smooth_disorder.disorder_linewidth import run_band_structure_manual
25from smooth_disorder.disorder_linewidth import run_phonon_mesh, save_mesh_data_to_files
26
27from smooth_disorder.disorder_linewidth import lorentzian_numpy, flatten_arrays_freq_only
28from smooth_disorder.disorder_linewidth import calculate_vdos_with_frequency
29from smooth_disorder.disorder_linewidth import save_vdos_data_to_files
30
31from smooth_disorder.disorder_linewidth import flatten_arrays
32from smooth_disorder.disorder_linewidth import calculate_vdos_and_average_speed_with_frequency
33from smooth_disorder.disorder_linewidth import save_vdos_speed_data_to_files
34
35
36
37CRYSTAL_POSCAR = "./1_graphite/POSCAR"
38CRYSTAL_FC2 = "./1_graphite/fc2.hdf5"
39SUPERCELL_MATRIX = np.diag([8, 8, 2])
40MESH = [128, 128, 32]
41GAMMA_CENTER = True
42
43WORK_DIR = "./dl_workflow"
44os.makedirs(WORK_DIR, exist_ok=True)
45
46MESH_SAVE = f"{WORK_DIR}/mesh_data"
47CRYSTAL_VEL_SAVE = f"{WORK_DIR}/crystal_vdos_group_vel"
48SHIFTED_SAVE = f"{WORK_DIR}/reduced_density_crystal_vdos_group_vel"
49
50
51DISORDERED_POSCAR = "./2_irg_t2/irg_t2_14009.vasp"
52DISORDERED_FREQUENCIES = "./2_irg_t2/irg_t2_frequencies.hdf5"
53DISORDERED_DIFFUSIVITY = "./2_irg_t2/diffusivity.hdf5"
54
55DISORDERED_VDOS_SAVE = f"{WORK_DIR}/disordered_vdos"
56
57# Lorentzian half-width η for VDOS broadening [cm⁻¹].
58# Controls spectral resolution — value used for graphite: 0.6 cm⁻¹.
59GAMMA_BROADENING = 0.6
60
61
62
63################################
64# BAND STRUCTURE VISUALIZATION #
65################################
66
67# Special BZ points for hexagonal graphite — fractional reciprocal-lattice coordinates
68atoms_ase = ase.io.read(CRYSTAL_POSCAR)
69print(f"Special points in the BZ")
70print(ase.dft.kpoints.get_special_points(atoms_ase.cell))
71
72# Preferred path chosen from the BZ
73path = [[[0, 0, 0], [0. , 0. , 0.5], [0.5, 0. , 0.5], [0.5, 0. , 0. ],
74 [0., 0., 0.], [0.33333333, 0.33333333, 0.], [0.33333333, 0.33333333, 0.5]]]
75labels = ["$\\Gamma$", "A", "L", "M", "$\\Gamma$", "K", "H"]
76
77print(f"Running the band structure calculation")
78frequencies, distances, qpoints = run_band_structure_manual(CRYSTAL_POSCAR, CRYSTAL_FC2, SUPERCELL_MATRIX, path, labels)
79
80num_paths = len(distances)
81num_modes = frequencies[0].shape[1]
82
83
84# visualization
85plt.figure(figsize=(16, 8))
86
87for path in range(num_paths):
88 for mode in range(num_modes):
89 plt.plot(distances[path], frequencies[path][:, mode]*THzToCm, color=Colors[3])
90
91y_min, y_max = 0, 1600
92plt.vlines(0.0, y_min, y_max, color="black", lw=1)
93plt.text(0.0-0.003, -50, labels[0])
94
95for path in range(num_paths):
96 plt.vlines(distances[path][-1], y_min, y_max, color="black", lw=1)
97 plt.text(distances[path][-1]-0.003, -50, labels[path+1])
98
99plt.ylabel("Frequencies [cm-1]")
100plt.xlabel("Brillouin zone special points")
101
102plt.xlim([-0.01, np.max(distances)+0.01])
103plt.xticks([])
104plt.savefig(f"{WORK_DIR}/crystal_band_structure.png", dpi=300)
105
106
107################################################################
108# OBTAIN FREQUENCIES AND GROUP VELOCITIES IN REFERENCE CRYSTAL #
109################################################################
110
111
112print(f"Obtaining the crystal group velocities...")
113mesh_dict = run_phonon_mesh(CRYSTAL_POSCAR, CRYSTAL_FC2, SUPERCELL_MATRIX, MESH, GAMMA_CENTER)
114
115save_mesh_data_to_files(MESH_SAVE,
116 mesh_dict['frequencies_cm'],
117 mesh_dict['weights'],
118 mesh_dict['qpoints'],
119 mesh_dict['group_velocities_ms'])
120
121with h5py.File(f"{MESH_SAVE}.hdf5", "r") as f:
122 frequencies_cm = np.asarray(f["frequencies_cm"]) # (N_qpts, N_bands) [cm⁻¹]
123 weights = np.asarray(f["weights"]) # (N_qpts,)
124 qpoints = np.asarray(f["qpoints"]) # (N_qpts, 3) fractional
125 group_velocities_ms = np.asarray(f["group_velocities_ms"]) # (N_qpts, N_bands, 3) [m/s]
126
127
128plt.figure(figsize=(16, 8))
129
130speed_2d = np.sqrt(
131 np.square(group_velocities_ms).sum(axis=2) / 3
132)
133
134plt.scatter(frequencies_cm, speed_2d, color=Colors[3], s=0.01)
135
136
137plt.xlabel("Frequency [cm^-1]")
138plt.ylabel("Group Velocity [m/s]")
139
140plt.title("Group Velocity of reference crystal")
141
142plt.savefig(f"{WORK_DIR}/crystal_group_velocities.png", dpi=300)
143
144
145#############################################
146# OBTAIN VDOS AND v(w) IN REFERENCE CRYSTAL #
147#############################################
148
149print(f"Obtaining the crystal VDOS")
150
151frequencies_flat, weights_flat, speed_flat, weights_sum = flatten_arrays(
152 frequencies_cm,
153 weights,
154 group_velocities_ms)
155
156vdos_crystal, speed_crystal, freq_crystal = calculate_vdos_and_average_speed_with_frequency(
157 frequencies_flat,
158 weights_flat,
159 speed_flat,
160 GAMMA_BROADENING,
161 CRYSTAL_POSCAR,
162 weights_sum
163)
164
165save_vdos_speed_data_to_files(CRYSTAL_VEL_SAVE, freq_crystal, vdos_crystal, speed_crystal)
166
167
168plt.figure(figsize=(16, 8))
169
170plt.plot(freq_crystal, vdos_crystal, color=Colors[3])
171
172plt.xlabel(r"Frequency [cm$^{-1}$]")
173plt.ylabel(r"VDOS [THz$^{-1}$ nm$^{-3}$]")
174
175plt.title("Vibrational Density of States of reference crystal")
176
177plt.savefig(f"{WORK_DIR}/crystal_vdos.png", dpi=300)
178
179
180
181plt.figure(figsize=(16, 8))
182
183speed_2d = np.sqrt(
184 np.square(group_velocities_ms).sum(axis=2) / 3
185)
186
187plt.scatter(frequencies_cm, speed_2d, color=Colors[0], s=0.01)
188
189# the average of the group velocities at a given frequency
190plt.plot(freq_crystal, speed_crystal, color=Colors[3])
191
192plt.xlabel("Frequency [cm^-1]")
193plt.ylabel("Group Velocity [m/s]")
194
195plt.title("Group Velocity of reference crystal")
196
197plt.savefig(f"{WORK_DIR}/crystal_group_velocities_vs_frequency.png", dpi=300)
198
199
200
201##############################################################
202# VISUALIZE FREQUENCIES AND DIFFUSIVITY IN DISORDERED SYSTEM #
203##############################################################
204
205
206with h5py.File(DISORDERED_FREQUENCIES, "r") as f:
207 print(f.keys())
208 frequencies = np.asarray(f['frequencies']) # these are already saved in cm^-1
209 weights = np.asarray(f['weights'])
210
211print(f"Obtaining VDOS of the disordered system")
212frequencies_flat, weights_flat, weights_sum = flatten_arrays_freq_only(frequencies, weights)
213
214vdos_disordered, freq_disordered = calculate_vdos_with_frequency(
215 frequencies_flat,
216 weights_flat,
217 GAMMA_BROADENING,
218 DISORDERED_POSCAR,
219 weights_sum
220)
221
222save_vdos_data_to_files(DISORDERED_VDOS_SAVE, freq_disordered, vdos_disordered)
223
224
225
226
227plt.figure(figsize=(16, 8))
228
229plt.plot(freq_disordered, vdos_disordered, color=Colors[0])
230
231plt.xlabel("Frequency [cm$^{-1}$]")
232plt.ylabel("VDOS [THz$^{-1}$ nm$^{-3}$]")
233
234plt.title("Vibrational Density of States of the disordered system")
235
236plt.xticks(np.arange(0, 1800, 100))
237
238plt.savefig(f"{WORK_DIR}/disordered_system_vdos.png", dpi=300)
239
240
241
242plt.figure(figsize=(16, 8))
243
244plt.plot(freq_crystal, vdos_crystal, color=Colors[3], label="reference crystal")
245plt.plot(freq_disordered, vdos_disordered, color=Colors[0], label='irradiated graphite')
246
247plt.xlabel("Frequency [cm^-1]")
248plt.ylabel("VDOS [THz^-1 nm^-3]")
249
250plt.title("Vibrational Densities of States of reference crystal and the disordered system")
251
252plt.xticks(np.arange(0, 2000, 100))
253
254plt.legend(loc='upper left')
255
256plt.savefig(f"{WORK_DIR}/crystal_vs_disordered_system_vdos.png", dpi=300)
257
258
259
260
261
262# read in the diffusivity
263with h5py.File(DISORDERED_DIFFUSIVITY, "r") as f:
264 print(f.keys())
265 diffusivity_plot = np.asarray(f["diffusivity"]) # in m^2/s
266 frequencies_plot_diff = np.asarray(f["frequencies_plot"]) # in cm^-1
267
268
269
270
271plt.figure(figsize=(16, 8))
272
273plt.plot(frequencies_plot_diff, diffusivity_plot*1e6, color=Colors[0])
274
275plt.xlabel("Frequency [cm$^{-1}$]")
276plt.ylabel("Diffusivity [mm$^2$/s]")
277
278plt.title("Diffusivity of modes in the disordered system")
279
280plt.xticks(np.arange(0, 1800, 100))
281
282plt.savefig(f"{WORK_DIR}/disordered_system_diffusivity.png", dpi=300)
283
284
285
286################################################################
287# INFLUENCE OF DENSITY ON FREQUENCY SHIFTS IN THE CRYSTAL VDOS #
288################################################################
289
290
291density_crystal = obtain_density(read(CRYSTAL_POSCAR))
292density_disordered = obtain_density(read(DISORDERED_POSCAR))
293
294density_factor = np.power(density_disordered/density_crystal, 1/3)
295print(f" ρ_crystal = {density_crystal:.4f} g/cm³")
296print(f" ρ_disordered = {density_disordered:.4f} g/cm³")
297print(f" Density factor = (ρ_dis/ρ_crys)^(1/3) = {density_factor:.4f}")
298
299
300
301# load the mesh data
302with h5py.File(f"{MESH_SAVE}.hdf5", "r") as f:
303 frequencies_cm = np.asarray(f["frequencies_cm"]) # (N_qpts, N_bands) [cm⁻¹]
304 weights = np.asarray(f["weights"]) # (N_qpts,)
305 qpoints = np.asarray(f["qpoints"]) # (N_qpts, 3) fractional
306 group_velocities_ms = np.asarray(f["group_velocities_ms"]) # (N_qpts, N_bands, 3) [m/s]
307
308
309print(f"Applying frequency shifts and recalculating crystal VDOS")
310
311# flatten the arrays for easier VDOS calculation
312frequencies_flat, weights_flat, speed_flat, weights_sum = flatten_arrays(
313 frequencies_cm,
314 weights,
315 group_velocities_ms)
316
317# we shift the frequencies by the multiplicative factor
318shifted_frequencies_flat = frequencies_flat * density_factor
319
320shifted_vdos_crystal, shifted_speed_crystal, shifted_freq_crystal = calculate_vdos_and_average_speed_with_frequency(
321 shifted_frequencies_flat,
322 weights_flat,
323 speed_flat,
324 GAMMA_BROADENING,
325 CRYSTAL_POSCAR,
326 weights_sum
327)
328
329save_vdos_speed_data_to_files(SHIFTED_SAVE, shifted_freq_crystal, shifted_vdos_crystal, shifted_speed_crystal)
330
331
332
333plt.figure(figsize=(16, 8))
334
335plt.plot(shifted_freq_crystal, shifted_vdos_crystal, color=Colors[3])
336
337plt.xlabel("Frequency [cm^-1]")
338plt.ylabel("VDOS [THz^-1 nm^-3]")
339
340plt.title("shifted Vibrational Density of States of the reference crystal")
341
342plt.savefig(f"{WORK_DIR}/crystal_shifted_vdos.png", dpi=300)
343
344
345plt.figure(figsize=(16, 8))
346
347plt.scatter(shifted_frequencies_flat, speed_flat, color=Colors[0], s=0.01)
348plt.plot(shifted_freq_crystal, shifted_speed_crystal, color=Colors[3])
349
350plt.xlabel("Frequency [cm^-1]")
351plt.ylabel("Group Velocity [m/s]")
352
353plt.title("Group Velocity of the reference crystal with shifted frequencies")
354
355plt.savefig(f"{WORK_DIR}/crystal_shifted_group_velocities.png", dpi=300)
356