%matplotlib inline
from aiida import load_profile
from aiida.orm import load_node, ArrayData, Dict
from aiida.engine import CalcJob
from aiida_kkr.calculations import KkrCalculation, KkrimpCalculation
from aiida_kkr.workflows import kkr_imp_sub_wc, kkr_imp_wc, combine_imps_wc
from aiida_kkr.workflows._combine_imps import parse_Jij
from aiida_kkr.tools.parse_dos import parse_dosfiles
from aiida_kkr.workflows.kkr_imp_dos import parse_impdosfiles
from masci_tools.io.common_functions import get_Ry2eV
import io
import re
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.ticker as ticker
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
# connect to aiida db
profile = load_profile()
Version of workflow: 0.7.2
def plot_dos_from_calc(calc, iatom, ispin=None, sum_atoms=False, average_atoms=False, orbital='total', xfactor=1, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False):
# get number of atoms
if calc.process_class == KkrCalculation or calc.process_class == KkrimpCalculation:
natom = calc.outputs.output_parameters.get_attribute('number_of_atoms_in_unit_cell')
else:
print('ERROR : node input must be a KkrCalculation or KkrimpCalculation node')
# get number of spins
nspin = calc.outputs.output_parameters.get_attribute('nspin')
# get number of atoms
natoms = calc.outputs.output_parameters.get_attribute('number_of_atoms_in_unit_cell')
if not lmdos:
orbital_map = {
'total': 0,'s': 1,'p': 2,'d': 3,'f': 4,'ns': -1
}
else:
orbital_map = {
's': 0,
'p1': 1, 'p2': 2, 'p3': 3,
'd1': 4,'d2': 5,'d3': 6,'d4': 7,'d5': 8,\
'f1': 9,'f2': 10,'f3': 11,'f4': 12,'f5': 13,'f6': 14,'f7': 15
}
if orbital in orbital_map:
iorb = orbital_map[orbital]
else:
if not lmdos:
print('ERROR: chose between total / s / p / d / f / ns')
else:
print('ERROR: Invalid orbital for lmdos')
# get dos_data node from the calc retrieved folder
if calc.process_class == KkrCalculation:
dos_host_dict = parse_dosfiles(calc.outputs.retrieved)
if calc.process_class == KkrimpCalculation:
try:
host_calc = calc.inputs.host_Greenfunction_folder.get_incoming(node_class=KkrCalculation).first().node
parent_calc = host_calc.inputs.parent_folder.get_incoming(node_class=KkrCalculation).first().node
ef = parent_calc.outputs.output_parameters.get_attribute('fermi_energy')
except:
#get fermi energy from parent impurity calculation
if 'parent_calc_folder' in calc.inputs:
host_folder = calc.inputs.parent_calc_folder
parent_calc = host_folder.get_incoming(node_class=CalcJob).all()[-1].node
out_potential_content = parent_calc.outputs.retrieved.get_object_content("out_potential")
else:
potential = calc.get_incoming(node_class=kkr_imp_sub_wc).first().node.inputs.host_imp_startpot
out_potential_content = potential.get_content()
out_potential_content = out_potential_content.split('\n')
ef = float(out_potential_content[3].split()[1])
dos_host_dict = parse_impdosfiles(calc.outputs.retrieved, natom, nspin, ef, lmdos)
dos_data = dos_host_dict['dos_data']
x_data = dos_data.get_x()[1][0]
y_data = dos_data.get_y()[iorb][1]
y_data_atoms = []
if nspin==1:
y_data_atom = np.zeros(len(x_data))
else:
y_data_atom = np.array([np.zeros(len(x_data)), np.zeros(len(x_data))])
plots = []
if type(iatom) == int:
iatom = [iatom]
elif iatom == 'all':
iatom = range(1,natoms+1,1)
elif iatom == 'vac':
vac_atoms = []
core_states = imp_calc.outputs.output_parameters.get_attribute('charge_core_states_per_atom')
for i, core_state in enumerate(core_states):
if core_state == 0:
vac_atoms.append(i+1)
iatom = vac_atoms
for atom in iatom:
if nspin ==1:
y_data_atom = y_data[atom-1]
elif nspin ==2:
y_data_atom = (y_data[(atom-1)*2], y_data[(atom-1)*2+1])
if ispin == 1:
y_data_atom = y_data_atom[0]
elif ispin == 2:
y_data_atom = y_data_atom[1]
elif ispin == None:
y_data_atom = y_data_atom[0] + y_data_atom[1]
else:
print('ERROR : Spin value should be 1 or 2')
if _abs == True:
y_data_atom=abs(y_data_atom)
y_data_atoms.append(y_data_atom)
if not return_data:
if not sum_atoms:
plot, = plt.plot(x_data*xfactor, y_data_atom*yfactor+yoffset)
plots.append(plot)
if sum_atoms:
y_data_sum = np.sum(y_data_atoms, axis=0)
if average_atoms:
plot, = plt.plot(x_data*xfactor, y_data_sum*yfactor/len(iatom)+yoffset)
else:
plot, = plt.plot(x_data*xfactor, y_data_sum*yfactor+yoffset)
if return_data:
return dos_host_dict, x_data*xfactor, y_data_atoms
else:
if len(iatom) == 1 or sum_atoms:
return plot
else:
return plots
def plot_ldos_iatom(DOS_calc, iatom, xfactor=1000, xlim=[-3,3], at_type=None, legend_show=False):
calc = DOS_calc.get_outgoing(node_class=kkr_imp_sub_wc).first().node.get_outgoing(node_class=KkrimpCalculation).first().node
# Plot and store the plot objects
plot1 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='total', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
plot2 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='s', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
plot3 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='p', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
plot4 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
plot5 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='f', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
plot6 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='ns', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
# Set colors for the plots
plot1.set_color('black')
plot1.set_linewidth(3)
ls = '-'
lw = 2
title_size = 24
label_size = 20
legend_size = 19
legend_loc = 2
plot2.set_color(f'C{0}')
plot2.set_linestyle(ls)
plot2.set_linewidth(lw)
plot3.set_color(f'C{1}')
plot3.set_linestyle(ls)
plot3.set_linewidth(lw)
plot4.set_color(f'C{2}')
plot4.set_linestyle(ls)
plot4.set_linewidth(lw)
plot5.set_color(f'C{3}')
plot5.set_linestyle(ls)
plot5.set_linewidth(lw)
plot6.set_color(f'C{4}')
plot6.set_linestyle(ls)
plot6.set_linewidth(lw)
plt.xlim(xlim)
plt.ylabel('DOS (1/eV)', fontsize=label_size)
plt.xlabel('Energy (meV)', fontsize=label_size)
plt.yticks(fontsize=label_size)
plt.xticks(fontsize=label_size)
if iatom ==1:
if legend_show:
plt.legend(labels=['Total', 's', 'p', 'd', 'f', 'ns'], fontsize=legend_size, loc=legend_loc)
plt.title('Gd', fontsize=title_size)
else:
if legend_show:
plt.legend(labels=['Total', 's', 'p', 'd', 'f', 'ns'], fontsize=legend_size, loc=legend_loc)
if at_type is None:
if iatom ==8:
plt.title('Nb1', fontsize=title_size)
if iatom ==9:
plt.title('Nb2', fontsize=title_size)
if iatom ==14:
plt.title('Nb3', fontsize=title_size)
else:
plt.title(f'{at_type}', fontsize=title_size)
def plot_d_dos_iatom(DOS_calc, iatom, xfactor=1000, xlim=[-3, 3], at_type=None, legend_show=False):
calc = DOS_calc.get_outgoing(node_class=kkr_imp_sub_wc).first().node.get_outgoing(node_class=KkrimpCalculation).first().node
# Plot and store the plot objects
plot1 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='total', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
# plot2 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d', xfactor=1000, yfactor=1, _abs=False, yoffset=0., lmdos=False, return_data=False)
plot3 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d1', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=True, return_data=False)
plot4 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d2', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=True, return_data=False)
plot5 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d3', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=True, return_data=False)
plot6 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d4', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=True, return_data=False)
plot7 = plot_dos_from_calc(calc, iatom, ispin=None, orbital='d5', xfactor=xfactor, yfactor=1, _abs=False, yoffset=0., lmdos=True, return_data=False)
# Set colors for the plots
plot1.set_color('black')
plot1.set_linewidth(3)
# plot2.set_color(f'C{0}')
ls = '-'
lw = '2'
title_size = 24
label_size = 20
legend_size = 19
legend_loc = 2
plot3.set_color(f'C{0}')
plot3.set_linestyle(ls)
plot3.set_linewidth(lw)
plot4.set_color(f'C{1}')
plot4.set_linestyle(ls)
plot4.set_linewidth(lw)
plot5.set_color(f'C{2}')
plot5.set_linestyle(ls)
plot5.set_linewidth(lw)
plot6.set_color(f'C{3}')
plot6.set_linestyle(ls)
plot6.set_linewidth(lw)
plot7.set_color(f'C{4}')
plot7.set_linestyle(ls)
plot7.set_linewidth(lw)
plt.xlim(xlim)
plt.ylabel('DOS (1/eV)', fontsize=label_size)
plt.xlabel('Energy (meV)', fontsize=label_size)
plt.yticks(fontsize=label_size)
plt.xticks(fontsize=label_size)
if iatom==1:
if legend_show==True:
plt.legend(labels=['Total', '$d_{x^2-y^2}$', '$d_{xz}$', '$d_{z^2}$', '$d_{yz}$', '$d_{xy}$'], fontsize=legend_size, loc=legend_loc)
plt.title('Gd', fontsize=title_size)
else:
if legend_show==True:
plt.legend(labels=['Total', '$d_{x^2-y^2}$', '$d_{xz}$', '$d_{z^2}$', '$d_{yz}$', '$d_{xy}$'], fontsize=legend_size, loc=legend_loc)
if at_type is None:
if iatom==8:
plt.title('Nb1', fontsize=title_size)
if iatom==9:
plt.title('Nb2', fontsize=title_size)
if iatom==14:
plt.title('Nb3', fontsize=title_size)
else:
plt.title(f'{at_type}', fontsize=title_size)
def plot_gap_edges(gap=1.91, lim=3, color='black', alpha=0.4):
plt.axvspan(-lim, -gap, facecolor=color, alpha=alpha/8)
plt.axvspan(gap, lim, facecolor=color, alpha=alpha/8)
plt.axvline(-gap, color=color, linestyle='--', alpha=alpha)
plt.axvline(gap, color=color, linestyle='--', alpha=alpha)
def get_peak_energy(calc, iatom, iorb, lmdos=True):
if type(iorb) is not list:
iorb = [iorb]
iatom = iatom-1
if lmdos:
x_data = calc.outputs.dos_data_lm.get_x()[1][0]
y_data = calc.outputs.dos_data_lm.get_y()
else:
x_data = calc.outputs.dos_data.get_x()[1][0]
y_data = calc.outputs.dos_data.get_y()
x_peak = []
y_peak = []
for orb in iorb:
y_data_orb = y_data[orb][1]
y_data_orb_atom = y_data_orb[2*iatom] + y_data_orb[2*iatom+1]
y_max_orb_atom = np.max(y_data_orb_atom)
y_peak.append(y_max_orb_atom)
for i, val in enumerate(y_data_orb_atom):
if val == y_max_orb_atom:
x_peak.append(x_data[i]*1000)
return x_peak, y_peak
# Function to download the content of a remote file into memory
def get_remote_file_data(remote_data, relpath):
"""Retrieve the content of a remote file as an in-memory array."""
# Create a temporary file in-memory
with io.BytesIO() as temp_file:
with open('/tmp/temp_remote_file', 'wb') as temp_path:
remote_data.getfile(relpath, temp_path.name)
# Read and return the file data as a numpy array
with open(temp_path.name, 'r') as f:
return np.loadtxt(f)
# Function to store JIJ data into arrays
def get_J_all_energies(calc, pattern, reload_data=False, test=False):
remote_data = calc.outputs.remote_folder
# Get Gd atom indices
Gd_atoms = [int(k.split('=')[1]) + 1 for k, v in calc.inputs.settings_LDAU.items() if 'iatom' in k]
# print('Gd atoms:', Gd_atoms)
# Initialize data storage variables
J_tot_all, J_all = [], []
D_tot_all, D_all = [], []
Dx_tot_all, Dx_all = [], []
Dy_tot_all, Dy_all = [], []
Dz_tot_all, Dz_all = [], []
J_tot = D_tot = Dx_tot = Dy_tot = Dz_tot = 0
# Load data from node extra if exists and reload_data is False, otherwise read from files
if 'uuid_saved_Jij_data' in remote_data.extras and not reload_data:
print('Loading data from node extra')
data_node = load_node(remote_data.extras['uuid_saved_Jij_data'])
data_all = data_node.get_array('data')
else:
print('Loading data from files and storing in node extra')
# List all files in the remote directory
try:
all_files = remote_data.listdir()
except IOError as e:
print(f"Error while listing directory: {e}")
return
# Filter files matching the given pattern
Jij_files = sorted([f for f in all_files if re.match(pattern, f)])
if not Jij_files:
print("No files matching the pattern found.")
return
# Limit files for testing if `test` is set to True
if test:
Jij_files = Jij_files[:2]
data_all = [get_remote_file_data(remote_data, filename) for filename in Jij_files]
data_all = np.array(data_all)
# Save data to a new ArrayData node
data_node = ArrayData()
data_node.set_array('data', data_all)
data_node.store()
remote_data.set_extra('uuid_saved_Jij_data', data_node.uuid)
# Process each file and compute J and D values
for i in range(len(data_all)):
data = data_all[i]
for line in data:
if line[0] == Gd_atoms[0] and line[1] == Gd_atoms[1]:
J_matrix = line[4:].reshape(3, 3) * 1000 * get_Ry2eV() * -1 # Convert to meV and adjust sign
J = np.trace(J_matrix) / 3 # Average diagonal for isotropic J
Dx, Dy, Dz = J_matrix[1, 2], J_matrix[2, 0], J_matrix[0, 1]
D = np.sqrt(Dx**2 + Dy**2 + Dz**2)
# Accumulate values
J_tot += J
D_tot += D
Dx_tot += Dx
Dy_tot += Dy
Dz_tot += Dz
# Append values to arrays
J_all.append(J)
D_all.append(D)
Dx_all.append(Dx)
Dy_all.append(Dy)
Dz_all.append(Dz)
J_tot_all.append(J_tot)
D_tot_all.append(D_tot)
Dx_tot_all.append(Dx_tot)
Dy_tot_all.append(Dy_tot)
Dz_tot_all.append(Dz_tot)
# Print values for verification
# print(f'J = {J}, J_tot = {J_tot}')
# print(f'D = {D}, D_tot = {D_tot}')
break
return J_all, J_tot_all, D_all, D_tot_all, Dx_tot_all, Dy_tot_all, Dz_tot_all
# Function to plot DOS
def plot_dos(ax, DOS_calc, d_ef=0, ylabel_left=True, ylabel_right=True, no_ytick_labels_left=False, no_ytick_labels_right=False):
x_data = DOS_calc.outputs.dos_data_lm.get_x()[1][0]
y_data_all_i, c_all_i = [], []
for i, color in zip(range(4, 9), range(5)):
y_label = DOS_calc.outputs.dos_data_lm.get_y()[i][0]
y_data = DOS_calc.outputs.dos_data_lm.get_y()[i][1][0] + DOS_calc.outputs.dos_data_lm.get_y()[i][1][1] # Sum the two channels
y_data_all_i.append(y_data)
# Calculate cumulative charge
c_all = np.cumsum((x_data[::-1][1:] - x_data[::-1][:-1]) * y_data[::-1][:-1])
c_all_shifted = c_all - c_all[len(c_all) // 2] # Shift to have c=0 at ef
c_all_i.append(c_all_shifted)
#Total DOS
y_data_i_sum = np.sum(y_data_all_i, axis=0)
ax.plot(x_data, y_data_i_sum, label='d tot', color='black', linewidth=linewidth)
# Total cumulative charge
ax2 = plt.twinx(ax)
twin_axes.append(ax2) # Store the twin axis
c_all_i_sum = np.sum(c_all_i, axis=0)
c_all_i_sum = c_all_i_sum + d_ef # Shift to have c=c(ef) at ef
ax2.plot(x_data[::-1][:-1], c_all_i_sum, label='Total charge', color=f'C{3}', linestyle='-', linewidth=linewidth)
# ax2.tick_params(axis='y', colors=darker_C3)
if ylabel_left:
ax.set_ylabel(r'DOS (1/eV)', fontsize=label_fontsize)
ax.yaxis.set_label_coords(label_x_coord, 0.5) # Set fixed x-position for alignment
if no_ytick_labels_left:
ax.set_yticklabels([])
if ylabel_right:
ax2.set_ylabel(r'$\rho_d$ (e)', color=darker_C3, fontsize=label_fontsize)
ax2.yaxis.set_label_coords(1-label_x_coord, 0.5) # Set fixed x-position for alignment
if no_ytick_labels_right:
ax2.set_yticklabels([])
#ax.legend(labels=['$d_{x^2-y^2}$', '$d_{xz}$', '$d_{z^2}$', '$d_{yz}$', '$d_{xy}$', '$d_{tot}$', r'$\Delta\rho_{d}$'], loc=2, prop={'size': legend_size})
ax.axvline(0, color=f'black', linestyle='--', linewidth=linewidt_vline, alpha=alpha_vline)
# ax.axhline(0, color='black', linewidth=linewidt_hline, alpha=alpha_hline)
ax.set_xlim([-1, 1])
ax.set_ylim([0, 2.5])
ax2.set_ylim([0, 2.5])
# Function to plot J_tot and D_tot
def plot_j_tot(ax, J_tot, D_tot, J_offset, D_offset, label_y_right=False,
no_ytick_labels_left=False, no_ytick_labels_right=False):
x = np.linspace(-2, 2, 192)
J_shifted = np.array(J_tot) - (J_tot[95] + J_tot[96]) / 2 + J_offset
ax.plot(x, J_shifted, color='C0', linewidth=linewidth)
ax.axhline(0, color='C0', linewidth=linewidt_hline, alpha=alpha_hline)
ax.axvline(0, color='black', linestyle='--', linewidth=linewidt_vline, alpha=alpha_vline)
ax.set_ylim([-20, 40])
if no_ytick_labels_left:
ax.set_yticklabels([])
ax2 = ax.twinx()
twin_axes.append(ax2)
D_shifted = np.array(D_tot) - (D_tot[95] + D_tot[96]) / 2 + D_offset
ax2.plot(x, D_shifted, color='C1', linewidth=linewidth)
if label_y_right:
ax2.set_ylabel('D (meV)', color='C1', fontsize=label_fontsize)
ax2.axhline(0, color='C1', linewidth=linewidt_hline, alpha=alpha_hline)
ax2.set_ylim([-3.5, 1])
if no_ytick_labels_right:
ax2.set_yticklabels([])
def get_ldec_charges(calc):
# Access the 'retrieved' folder
retrieved_folder = calc.outputs.retrieved
# Open and read 'out_log.000.txt'
with retrieved_folder.open("out_log.000.txt", "r") as file:
lines = file.readlines()
# Find the last occurrence of 'l-dec'
last_occurrence_index = None
for i, line in enumerate(lines):
if 'l-dec' in line:
last_occurrence_index = i
# Initialize dictionary to store orbital information
orbital_data = {}
# If 'l-dec' was found, get the 12 lines following the last occurrence
if last_occurrence_index is not None:
selected_lines = lines[last_occurrence_index + 1:last_occurrence_index + 13]
# Define a regex pattern to capture orbital information with '=' sign
pattern = re.compile(r"(\w+)\s*=\s*([\d\.]+)\s+([\d\.]+)\s+([\d\.]+)")
for line in selected_lines:
# Check if the line matches the pattern with '='
match = pattern.search(line)
if match:
orbital = match.group(1)
spin_dn = float(match.group(2))
spin_up = float(match.group(3))
m_spin = float(match.group(4))
# Store the data in the dictionary
orbital_data[orbital] = {
'spin_dn': spin_dn,
'spin_up': spin_up,
}
elif len(line.strip().split()) == 4: # Handle 'ns' and 'TOT' lines
parts = line.strip().split()
orbital = parts[0]
spin_dn = float(parts[1])
spin_up = float(parts[2])
m_spin = float(parts[3])
# Store the data in the dictionary
orbital_data[orbital] = {
'spin_dn': spin_dn,
'spin_up': spin_up,
}
return orbital_data
else:
print("No 'l-dec' found in the file.")
return None
def get_J_and_D(calc):
impurity1_output_node = impurity2_output_node = Dimer_short_wf.inputs.impurity1_output_node
retrieved = calc.outputs.retrieved
impurity_info = calc.inputs.impurity_info
calc_JiJ_data = parse_Jij(retrieved, impurity_info, impurity1_output_node, impurity2_output_node)['Jijdata'].get_array('JijData')
J = calc_JiJ_data[0][3]
D = calc_JiJ_data[0][4]
return J, D
# SCF clac
Dimer_short_wf = load_node('ccd90de3-5e20-4129-a5d3-bc326e8ce1c0')
Dimer_long_wf = load_node('bec9e4ae-28ce-42b3-b473-7974691ba9ef')
# JIJ calc
Dimer_short_Jij_ef = load_node('c5219333-9d05-4b01-a9fe-658441f63828')
Dimer_long_Jij_ef = load_node('1eb745d8-bc1d-4256-b3b5-e5341ea27d94')
Dimer_short_Jij = load_node('ea3073e4-b574-496d-a347-92beb1a2275c')
Dimer_long_Jij = load_node('ba3c538e-0a4f-4cd0-a2ed-20821de71c4a')
# Normal state DOS
Dimer_short_DOS = load_node('f92edd22-23ea-4668-b561-1acb05c9ee94')
Dimer_long_DOS = load_node('2bcad826-54d0-41ca-914d-bd3a66f8cf46')
# BdG lmDOS
Single_Gd_BdG_lmDOS = load_node('47e694bd-7f41-41b3-9d13-de71cd31ebe6')
Dimer_short_BdG_lmDOS = load_node('ee5234a7-f761-46be-a2ff-4def32fdcc7a')
Dimer_long_BdG_lmDOS = load_node('f99f916e-9cbd-4164-9e90-9360cdb7f27f')
# !verdi archive create --compress 9 -N ccd90de3-5e20-4129-a5d3-bc326e8ce1c0 bec9e4ae-28ce-42b3-b473-7974691ba9ef c5219333-9d05-4b01-a9fe-658441f63828 1eb745d8-bc1d-4256-b3b5-e5341ea27d94 ea3073e4-b574-496d-a347-92beb1a2275c ba3c538e-0a4f-4cd0-a2ed-20821de71c4a f92edd22-23ea-4668-b561-1acb05c9ee94 2bcad826-54d0-41ca-914d-bd3a66f8cf46 47e694bd-7f41-41b3-9d13-de71cd31ebe6 ee5234a7-f761-46be-a2ff-4def32fdcc7a f99f916e-9cbd-4164-9e90-9360cdb7f27f e062f1c8-ca25-41fa-9c19-d843173eba00 1998492c-bf32-42c4-a67a-decd748e57f6 -f export_kkr.aiida
# Experiment data
Nb_host_single = np.loadtxt('data/deconvoluted/Nb_single_deconvoluted.txt').T # Nb substrate single atom
Nb_host_dimer = np.loadtxt('data/deconvoluted/Nb_dimers_deconvoluted.txt').T # Nb substrate dimers
Gd_single = np.loadtxt('data/deconvoluted/Gd_single_deconvoluted.txt').T # Gd single
Gd_dimer_short = np.loadtxt('data/deconvoluted/Gd_dimer_short_deconvoluted.txt').T # 001 dimer
Gd_dimer_long = np.loadtxt('data/deconvoluted/Gd_dimer_long_deconvoluted.txt').T # 1-10 dimer
Gd_data_all = [Gd_single, Gd_dimer_long, Gd_dimer_short]
DOS_calcs = [Single_Gd_BdG_lmDOS, Dimer_long_BdG_lmDOS, Dimer_short_BdG_lmDOS]
label_fontsize = 24
fig, axes = plt.subplots(len(DOS_calcs), 2, figsize=(12, 3*len(DOS_calcs))) # Adjust the figsize if needed
system=['single\nGd', 'long\ndimer', 'short\ndimer']
linewidth_set = 4
for i, (Gd_data, DOS_calc) in enumerate(zip(Gd_data_all, DOS_calcs)):
linewidth = linewidth_set
if i == 0:
Nb_host = Nb_host_single
else:
Nb_host = Nb_host_dimer
axes[i,0].plot(Nb_host[0]*1000, Nb_host[1]/Nb_host[1][107], linestyle='--', color='black', linewidth=linewidth)
axes[i,0].plot(Gd_data[0]*1000, Gd_data[1]/Gd_data[1][107], linewidth=linewidth, color=f'C{i}')
axes[i,0].set_xlim([-4, 4])
axes[i,0].set_ylabel('dI/dU (norm.)', fontsize = label_fontsize)
axes[i,0].tick_params(axis='both', which='major', labelsize=label_fontsize)
data_max = max(Gd_data[1])
# if i==0:
# text_y = 1
# else:
# text_y = 2
text_y = 0.75*data_max
axes[i,0].text(0, text_y, system[i], fontsize=label_fontsize-1, color=f'C{i}', horizontalalignment='center')
# if axes[i,0] == axes[0,0]:
# axes[i,0].legend(['Host Nb'], fontsize=label_fontsize, loc=2)
axes[i,0].set_ylim([0, 1.05*data_max])
if axes[i,0] is not axes[-1,0]:
axes[i,0].set_xticklabels([])
host_calc = DOS_calc.inputs.gf_dos_remote.get_incoming(node_class=KkrCalculation).first().node
imp_calc = DOS_calc.get_outgoing(node_class=kkr_imp_sub_wc).first().node.get_outgoing(node_class=KkrimpCalculation).first().node
# Create a temporary figure to capture the Line2D plots
temp_fig, temp_ax = plt.subplots()
# Plot total DOS and vacuum DOS on the temporary figure
plot_dos_from_calc(host_calc,iatom='all',sum_atoms=True,average_atoms=True,ispin=1,orbital='total',xfactor=1000,_abs=False,yfactor=1,yoffset=0.,lmdos=False,return_data=False)
plot_dos_from_calc(imp_calc,iatom='all',sum_atoms=True,average_atoms=True,ispin=None,orbital='total',xfactor=1000,_abs=False,yfactor=1,yoffset=0.,lmdos=False,return_data=False)
plot_dos_from_calc(imp_calc,iatom=1,sum_atoms=True,average_atoms=True,ispin=None,orbital='total',xfactor=1000,_abs=False,yfactor=1,yoffset=0.,lmdos=False,return_data=False)
# Extract data from the Line2D objects and re-plot on the target subplot
for j, line in enumerate(temp_ax.get_lines()):
linewidth = linewidth_set
if j==0:
linestyle='--'
color='black'
else:
linestyle='-'
color=f'C{i}'
if j==2:
linestyle=':'
linewidth=3
x_data = line.get_xdata()
y_data = line.get_ydata()
# Normalise
y_data_norm_fac = sum(y_data[0:38])/38
y_data = y_data/y_data_norm_fac
axes[i,1].plot(x_data, y_data, label=line.get_label(), linewidth=linewidth, linestyle=linestyle, color=color)
axes[i,1].tick_params(axis='both', which='major', labelsize=label_fontsize)
axes[i,1].yaxis.set_major_locator(ticker.MultipleLocator(2))
axes[i,1].set_xlim([-4,4])
axes[i,1].set_ylabel('DOS (norm.)', fontsize=label_fontsize)
if axes[i,1] is not axes[-1,1]:
axes[i,1].set_xticklabels([])
# Close the temporary figure
plt.close(temp_fig)
# Adjust layout to prevent overlap
plt.tight_layout()
axes[-1,0].set_xlabel('Bias (mV)', fontsize = label_fontsize)
axes[-1,1].set_xlabel('Energy (meV)', fontsize=label_fontsize)
plt.subplots_adjust(hspace=0.12, wspace=0.3)
# plt.savefig('Fig2_new.pdf', bbox_inches='tight')
# plt.savefig('Fig2_new.svg', bbox_inches='tight')
plt.show()
# get non-integrated J and D values
file_pattern = r'test_jijmatrix_eres_ie_int.*\.dat'
J_all_Dimer_short, J_tot_all_Dimer_short, D_all_Dimer_short, D_tot_all_Dimer_short, Dx_tot_all_Dimer_short, Dy_tot_all_Dimer_short, Dz_tot_all_Dimer_short = get_J_all_energies(Dimer_short_Jij, file_pattern)
J_all_Dimer_long, J_tot_all_Dimer_long, D_all_Dimer_long, D_tot_all_Dimer_long, Dx_tot_all_Dimer_long, Dy_tot_all_Dimer_long, Dz_tot_all_Dimer_long = get_J_all_energies(Dimer_long_Jij, file_pattern)
# J and D values at ef
J_ef_short, D_ef_short = get_J_and_D(Dimer_short_Jij_ef)
J_ef_long, D_ef_long = get_J_and_D(Dimer_short_Jij_ef)
# Get d orbital occupation at ef
charges_dimer_short = get_ldec_charges(Dimer_short_Jij_ef)
charges_dimer_long = get_ldec_charges(Dimer_long_Jij_ef)
d_ef_dimer_short = charges_dimer_short['d']['spin_dn'] + charges_dimer_short['d']['spin_up']
d_ef_dimer_long = charges_dimer_long['d']['spin_dn'] + charges_dimer_long['d']['spin_up']
# Plotting variables
label_fontsize = 20
ticks_fontsize = 20
linewidth = 3
alpha_vline, linewidt_vline = 0.4, 1.25
alpha_hline, linewidt_hline = 0.6, 1.25
label_x_coord = -0.16 # Define fixed x-coordinate for aligned y-labels
legend_size = 17
# Define custom darker colors
darker_C0 = (0.2, 0.4, 0.6) # Darker shade for 'C0'
darker_C1 = (0.9, 0.35, 0) # Darker shade for 'C1'
darker_C3 = (0.8, 0, 0)
# Set up figure and subplots
fig, axs = plt.subplots(2, 2, figsize=(12, 10), sharex=True, gridspec_kw={'height_ratios': [2, 2]})
# Store twin axes for setting tick label sizes
twin_axes = []
# Plotting for DOS Dimer_short and DOS Dimer_long
plot_dos(axs[1, 0], Dimer_short_DOS, d_ef = d_ef_dimer_short, ylabel_right=False, no_ytick_labels_right=True)
axs[1, 0].set_xlabel('Energy (eV)', fontsize=label_fontsize)
plot_dos(axs[1, 1], Dimer_long_DOS, d_ef = d_ef_dimer_long, ylabel_left=False, no_ytick_labels_left=True)
axs[1, 1].set_xlabel('Energy (eV)', fontsize=label_fontsize)
# Plot J_tot_all_Dimer_short and J_tot_all_Dimer_long with distinct offsets
plot_j_tot(axs[0, 0], J_tot_all_Dimer_short, D_tot_all_Dimer_short, J_offset=J_ef_short, D_offset=D_ef_short, no_ytick_labels_right=True)
axs[0, 0].set_ylabel('J (meV)', color=darker_C0, fontsize=label_fontsize)
axs[0, 0].yaxis.set_label_coords(label_x_coord, 0.5) # Align y-labels for J_tot plots
plot_j_tot(axs[0, 1], J_tot_all_Dimer_long, D_tot_all_Dimer_long, J_offset=J_ef_long, D_offset=D_ef_long, label_y_right=True, no_ytick_labels_left=True)
# Annotations
axs[0, 0].text(-0.14, 1.1, 'a', weight='bold', transform=axs[0, 0].transAxes, fontsize=label_fontsize, va='top', ha='right')
axs[0, 1].text(-0.04, 1.1, 'b', weight='bold', transform=axs[0, 1].transAxes, fontsize=label_fontsize, va='top', ha='right')
axs[1, 0].text(-0.14, 1.1, 'c', weight='bold', transform=axs[1, 0].transAxes, fontsize=label_fontsize, va='top', ha='right')
axs[1, 1].text(-0.04, 1.1, 'd', weight='bold', transform=axs[1, 1].transAxes, fontsize=label_fontsize, va='top', ha='right')
# Set tick label size for all subplots, including twin y-axes
for ax in axs.flat:
ax.tick_params(axis='both', which='major', labelsize=ticks_fontsize)
for ax2 in twin_axes:
ax2.tick_params(axis='y', which='major', labelsize=ticks_fontsize)
# Reduce space between plots
plt.subplots_adjust(hspace=0.2, wspace=0.15)
# plt.savefig(f'J_Dimers.pdf', bbox_inches='tight')
# plt.savefig(f'J_Dimers.png', bbox_inches='tight')
plt.show()
Loading data from node extra Loading data from node extra
/opt/aiida-core/aiida/orm/querybuilder.py:1369: AiidaEntryPointWarning: Process type 'aiida_kkr.workflows._combine_imps.combine_imps_wc' does not correspond to a registered entry. This risks queries to fail once the location of the process class changes. Add an entry point for 'aiida_kkr.workflows._combine_imps.combine_imps_wc' to remove this warning. warnings.warn( /opt/aiida-core/aiida/orm/querybuilder.py:1369: AiidaEntryPointWarning: Process type 'aiida_kkr.workflows._combine_imps.combine_imps_wc' does not correspond to a registered entry. This risks queries to fail once the location of the process class changes. Add an entry point for 'aiida_kkr.workflows._combine_imps.combine_imps_wc' to remove this warning. warnings.warn( /opt/aiida-core/aiida/orm/querybuilder.py:1369: AiidaEntryPointWarning: Process type 'aiida_kkr.workflows._combine_imps.combine_imps_wc' does not correspond to a registered entry. This risks queries to fail once the location of the process class changes. Add an entry point for 'aiida_kkr.workflows._combine_imps.combine_imps_wc' to remove this warning. warnings.warn( /opt/aiida-core/aiida/orm/querybuilder.py:1369: AiidaEntryPointWarning: Process type 'aiida_kkr.workflows._combine_imps.combine_imps_wc' does not correspond to a registered entry. This risks queries to fail once the location of the process class changes. Add an entry point for 'aiida_kkr.workflows._combine_imps.combine_imps_wc' to remove this warning. warnings.warn(
# Create a figure with 3 subplots (2 rows, 3 columns)
fig, axes = plt.subplots(2, 3, figsize=(18, 10)) # Adjust the figsize if needed
# Define subplot labels
subplot_labels = ['a', 'b', 'c', 'd', 'e', 'f']
for l in [0, 1]:
# Iterate over atoms and subplot axes
for i, iatom in enumerate([1, 8, 14]):
at_type = None
if iatom == 1:
legend_show = True
else:
legend_show = False
if iatom == 1:
at_type = 'Gd'
elif iatom == 8:
at_type = 'Nb1'
elif iatom == 14:
at_type = 'Nb2'
# Compute the row and column index for the 2D axes array
row = l # l is either 0 or 1, representing the row
col = i # i is 0, 1, or 2, representing the column
# Set the current axis to the corresponding subplot
plt.sca(axes[row, col])
if l == 0:
plot_ldos_iatom(Single_Gd_BdG_lmDOS, iatom, at_type=at_type, legend_show=legend_show)
elif l == 1:
plot_d_dos_iatom(Single_Gd_BdG_lmDOS, iatom, at_type=at_type, legend_show=legend_show)
plot_gap_edges()
# Set y-axis limit for the current subplot
plt.ylim([0, 5])
# Set y-axis label only for the first subplot in each row
if col == 0:
pass # You can add a y-axis label here if desired
else:
axes[row, col].set_ylabel('') # Remove y-axis label for other subplots
# Add subplot label (a), (b), (c), etc.
axes[row, col].text(0.04, 1.12, subplot_labels[l * 3 + i],
transform=axes[row, col].transAxes,
fontsize=24, weight='bold', va='top', ha='right')
# Adjust layout to avoid overlap
plt.tight_layout()
# plt.savefig('Gd_single_atom_DOS_combined.pdf', bbox_inches='tight')
# Create a figure with 3 subplots (2 rows, 3 columns)
fig, axes = plt.subplots(2, 4, figsize=(24, 10)) # Adjust the figsize if needed
# Define subplot labels
subplot_labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
for l in [0, 1]:
# Iterate over atoms and subplot axes
for i, iatom in enumerate([1, 8, 9, 14]):
at_type = None
if iatom == 1:
legend_show = True
else:
legend_show = False
if iatom == 1:
at_type='Gd'
legend_show=True
elif iatom == 8:
at_type='Nb1'
elif iatom == 9:
at_type='Nb2'
elif iatom == 14:
at_type='Nb3'
# Compute the row and column index for the 2D axes array
row = l # l is either 0 or 1, representing the row
col = i # i is 0, 1, or 2, representing the column
# Set the current axis to the corresponding subplot
plt.sca(axes[row, col])
if l == 0:
plot_ldos_iatom(Dimer_short_BdG_lmDOS, iatom, at_type=at_type, legend_show=legend_show)
elif l == 1:
plot_d_dos_iatom(Dimer_short_BdG_lmDOS, iatom, at_type=at_type, legend_show=legend_show)
plot_gap_edges()
# Set y-axis limit for the current subplot
plt.ylim([0, 7])
# Set y-axis label only for the first subplot in each row
if col == 0:
pass # You can add a y-axis label here if desired
else:
axes[row, col].set_ylabel('') # Remove y-axis label for other subplots
# Add subplot label (a), (b), (c), etc.
axes[row, col].text(0.04, 1.12, subplot_labels[l * 4 + i],
transform=axes[row, col].transAxes,
fontsize=24, weight='bold', va='top', ha='right')
# Adjust layout to avoid overlap
plt.tight_layout()
# plt.savefig('Gd_dimer_short_DOS_combined.pdf', bbox_inches='tight')
# Create a figure with 3 subplots (2 rows, 3 columns)
fig, axes = plt.subplots(2, 4, figsize=(24, 10)) # Adjust the figsize if needed
# Define subplot labels
subplot_labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
for l in [0, 1]:
# Iterate over atoms and subplot axes
for i, iatom in enumerate([1, 14, 15, 8]):
at_type = None
if iatom == 1:
legend_show = True
else:
legend_show = False
if iatom == 1:
at_type='Gd'
legend_show=True
elif iatom == 14:
at_type='Nb1'
elif iatom == 15:
at_type='Nb2'
elif iatom == 8:
at_type='Nb3'
# Compute the row and column index for the 2D axes array
row = l # l is either 0 or 1, representing the row
col = i # i is 0, 1, or 2, representing the column
# Set the current axis to the corresponding subplot
plt.sca(axes[row, col])
if l == 0:
plot_ldos_iatom(Dimer_long_BdG_lmDOS, iatom, at_type=at_type, legend_show=legend_show)
elif l == 1:
plot_d_dos_iatom(Dimer_long_BdG_lmDOS, iatom, at_type=at_type, legend_show=legend_show)
plot_gap_edges()
# Set y-axis limit for the current subplot
plt.ylim([0, 5])
# Set y-axis label only for the first subplot in each row
if col == 0:
pass # You can add a y-axis label here if desired
else:
axes[row, col].set_ylabel('') # Remove y-axis label for other subplots
# Add subplot label (a), (b), (c), etc.
axes[row, col].text(0.04, 1.12, subplot_labels[l * 4 + i],
transform=axes[row, col].transAxes,
fontsize=24, weight='bold', va='top', ha='right')
# Adjust layout to avoid overlap
plt.tight_layout()
# plt.savefig('Gd_dimer_long_DOS_combined.pdf', bbox_inches='tight')