# web-page: Co_magnon_dispersion.png """Plot the magnon dispersion of Co(hcp)""" # General modules import numpy as np from matplotlib import rcParams import matplotlib.pyplot as plt # Script modules from gpaw import GPAW from gpaw.response.heisenberg import (calculate_fm_magnon_energies, calculate_single_site_magnon_energies) # ---------- Inputs ---------- # # Ground state gpw = 'Co.gpw' # High-symmetry points sp_p = [r'$\Gamma$', 'M', 'K', 'A'] spq_pc = [np.array(qc) for qc in [[0., 0., 0], [0.5, 0., 0.], [1 / 3., 1 / 3., 0.], [0., 0., 0.5]]] # Load MFT data q_qc = np.load('Co_q_qc.npy') rc_r = np.load('Co_rc_r.npy') Jsph1_qabr = np.load('Co_Jsph1_qabr.npy') Jsph2_qabr = np.load('Co_Jsph2_qabr.npy') Jmix_qp = np.load('Co_Jmix_qp.npy') # Define range of spherical radii to plot rmin = 1.0 rmax = 1.4 # Define a radius to plot the inequivalent spherical site model for rineq = 0.6 # Labels and limits mwlabel = r'$\hbar\omega$ [meV]' mwlim = (0., 800.) filename = 'Co_magnon_dispersion.png' # ---------- Script ---------- # # Extract the magnetization of the unit cell calc = GPAW(gpw, txt=None) muc = calc.get_magnetic_moment() # Convert relative q-points into distance along the bandpath in reciprocal # space. B_cv = 2.0 * np.pi * calc.atoms.cell.reciprocal() # Coordinate transform q_qv = q_qc @ B_cv # Transform into absolute reciprocal coordinates pathq_q = [0.] for q in range(1, len(q_qc)): pathq_q.append(pathq_q[-1] + np.linalg.norm(q_qv[q] - q_qv[q - 1])) pathq_q = np.array(pathq_q) # Define q-limits of plot qlim = ((pathq_q[0] - pathq_q[1]) / 2., (1.5 * pathq_q[-1] - 0.5 * pathq_q[-2])) # Calculate the magnon energies # We distribute the unit cell magnetization evenly between the sites mm_ar = muc / 2. * np.ones(Jsph1_qabr.shape[2:], dtype=float) Esph1_qnr = calculate_fm_magnon_energies(Jsph1_qabr, q_qc, mm_ar) * 1.e3 # meV Esph2_qnr = calculate_fm_magnon_energies(Jsph2_qabr, q_qc, mm_ar) * 1.e3 Emix_qp = calculate_single_site_magnon_energies(Jmix_qp, q_qc, muc) * 1.e3 # We separate the two magnon modes by sorting them Esph1_qnr = np.sort(Esph1_qnr, axis=1) Esph2_qnr = np.sort(Esph2_qnr, axis=1) # First, we plot the magnon dispersion calculated with equivalent spherical # sublattice site kernels colors = rcParams['axes.prop_cycle'].by_key()['color'] # We define the lower bound on the magnon energy as the minimum within the # chosen rc range, the "best estimate" as the median, and the upper bound # as the maximum value Evalid_qnr = Esph2_qnr[..., np.logical_and(rc_r >= rmin, rc_r <= rmax)] Emin_qn = np.min(Evalid_qnr, axis=2) E_qn = np.median(Evalid_qnr, axis=2) Emax_qn = np.max(Evalid_qnr, axis=2) # Plot one mode at a time for n in range(2): plt.fill_between(pathq_q, Emin_qn[:, n], Emax_qn[:, n], color=colors[0], alpha=0.4) plt.plot(pathq_q, Emin_qn[:, n], color='0.5') plt.plot(pathq_q, Emax_qn[:, n], color='0.5') if n == 0: label = 'eq. spheres' else: label = None plt.plot(pathq_q, E_qn[:, n], color=colors[0], label=label) # Secondly, we plot the dispersion with inequivalent spherical sites Eineq_qn = Esph1_qnr[..., np.where(np.abs(rc_r - rineq) < 1.e-8)[0][0]] plt.plot(pathq_q, Eineq_qn[:, 0], '-o', mec='k', color=colors[1], label='ineq. spheres') plt.plot(pathq_q, Eineq_qn[:, 1], '-o', mec='k', color=colors[1]) # Lastly plot the magnon dispersion with only a single site in the unit cell plt.plot(pathq_q, Emix_qp[:, 0], '-v', mec='k', color=colors[2], label='unit cell') plt.plot(pathq_q, Emix_qp[:, 1], '-^', mec='k', color=colors[3], label='cylinder') # Use high-symmetry points as tickmarks for the x-axis qticks = [] qticklabels = [] for sp, spq_c in zip(sp_p, spq_pc): for q, q_c in enumerate(q_qc): if np.allclose(q_c, spq_c): qticks.append(pathq_q[q]) qticklabels.append(sp) plt.xticks(qticks, qticklabels) # Plot also vertical lines for each special point for pq in qticks: plt.axvline(pq, color='0.5', linewidth=1, zorder=0) # Labels and limits plt.ylabel(mwlabel) plt.xlim(qlim) plt.ylim(mwlim) plt.legend(title='Site geometry') plt.savefig(filename, format=filename.split('.')[-1], bbox_inches='tight')