超导磁电效应
超导磁电效应
超导线性磁电效应,也叫超导Edelstein效应,描述的是超流驱动产生自旋磁化。超流可以用 Cooper pair 的有限动量 $\mathbf q$ 表示。对于小 $\mathbf q$,自旋磁化可以展开为
其中线性磁电效应定义为
若进一步用超流密度 $\mathbf J_s$ 表示,由于$J_{s,b}=\nu_s q_b$,也可以写成
考虑一般正常态 Bloch哈密顿量$H_{\mathbf k}$,它可以包含轨道、自旋、子格等内部自由度。超导配对矩阵记为$\hat\Delta_{\mathbf k}$,若超导序参量携带空间相位$\Delta(\mathbf r)=\Delta_0 e^{i\mathbf q\cdot \mathbf r}$,则 Cooper对的总动量为 $\mathbf q$。配对的两个电子动量可以写成
于是定义 Nambu 基底
在显式自旋基底下,可以写为
有限 $\mathbf q$ 的 BdG Hamiltonian 为
这里暂时假设 $\hat\Delta_{\mathbf k}$ 不显式依赖 $\mathbf q$。这个近似适用于弱超流,也就是 $\mathbf q$ 足够小的情况。
磁化的热力学定义
为了计算自旋磁化,引入一个辅助 Zeeman 场 $\mathbf h$。电子的 Zeeman 耦合为
其中 $s_a$ 是 Pauli 矩阵,真正的自旋算符是 $s_a/2$。在 Nambu 空间中,相应的广义自旋矩阵定义为
这里空穴块前面的负号来自粒子—-空穴结构。含辅助 Zeeman 场的格林函数写成
Gor’kov 格林函数为
辅助场 $\mathbf h$ 最后要取零。磁化由配分函数对 $\mathbf h$ 求导得到
由于 Nambu 表象中有一半的 double counting,配分函数中出现因子 $1/2$。对 $\mathrm{Tr}\log G^{-1}$ 求导,使用
得到
现在对$\mathcal H_{\rm BdG}(\mathbf k,\mathbf q)$在 $\mathbf q=0$ 附近展开,首先定义没有超流态的 BdG 哈密顿量
正常态速度矩阵定义为
由于电子块是 $H_{\mathbf k+\mathbf q/2}$,所以一阶展开为
空穴块是$-H^*_{-\mathbf k+\mathbf q/2}$,因此一阶展开为
所以 BdG Hamiltonian 的一阶展开可以写成
其中 Nambu 空间速度矩阵为
接下来对格林函数进行展开,定义没有超流态的格林函数
由方程$\eqref{eq:m1}$可得
因此
使用矩阵恒等式
得到
将其代入方程$\eqref{eq:m2}$得到
利用迹的循环不变性
因此
其中
而线性磁电张量为
这就是超导线性磁电效应的 Kubo-like格林函数形式。现在将上式改写成 BdG 能带表象,对零超流态 BdG哈密顿量对角化
这里 $n$ 是 BdG 能带指标。由于 BdG 哈密顿量具有粒子—-空穴对称性,能谱通常成对出现$E_{n\mathbf k}
\leftrightarrow
-E_{n,-\mathbf k}$,但是在下面的推导中,我们直接对所有 BdG 本征态求和,不需要额外区分正能和负能分支。
格林函数可以谱分解为
定义能带表象中的矩阵元
将格林函数的谱分解代入$\mathrm{Tr}
\left[
\eta_aG_0\hat v_bG_0
\right]$中得到
因此线性磁电张量系数为
下面对松原频率求和,定义
当 $n\neq m$ 时,用部分分式分解
结合标准松原频率求和公式
因此
于是
等价的可以表示为
由于 $\alpha_{ab}$ 是实物理量,通常可显式写成
当$E_{n\mathbf k}=E_{m\mathbf k}$时上式需要取极限,特别是$n=m$时
因此对角项为
注意 $f’(E)<0$。低温下,$f’(E)$ 只在 $E\approx 0$ 附近有明显贡献。因此,如果 BdG 谱完全打开能隙,那么这个对角项在 $T\to 0$ 时通常会被指数压低。
能带表象的表达式可以自然分成两部分
对角部分,即 $n=m$,为
这个部分反映 BdG 准粒子能带在有限 $\mathbf q$ 下的占据变化。它类似金属正常态响应中的费米面贡献。
非对角部分,即 $n\neq m$,为
这个部分来自不同 BdG 本征态之间的虚跃迁,类似带间极化率。也可以利用 $n,m$ 的对称性写成 $n<m$ 的形式
Rashba 超导
对于二维 Rashba 超导,正常态哈密顿量可写成
配对取常规的$s$波配对
速度矩阵为
由于 Rashba SOC 使自旋和动量锁定,超流沿 $x$ 方向时,主要诱导 $y$ 方向磁化
超流沿 $y$ 方向时,主要诱导 $x$ 方向磁化
在连续旋转对称的 Rashba 系统中
因此整体上有
由于
也就是
对称性约束
线性磁电效应
对称性上要求反演对称性破缺。因为$\mathbf{q}$是极矢量,在空间反演 $P$ 下变号
而磁化$\mathbf M$是轴矢量,在空间反演下不变
因此如果体系有反演对称性,那么$\mathbf M\propto \mathbf q$这一线性关系被禁止$(\alpha_{ab}=0)$。但是时间反演 $T$ 本身不禁止线性磁电效应,因为
所以$\mathbf M\propto\mathbf q$在时间反演下是允许的。所以Rashba 超导可以在保持时间反演对称性的情况下存在超导Edelstein效应。
程序代码
计算代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452#!/usr/bin/env julia
# ============================================================
# Square-lattice Rashba superconductor
# Superconducting Edelstein effect
#
# MPI parallel version.
#
# Output:
# data/rashba_lattice_edelstein_mpi.dat
#
# Tensor:
# delta M_a = alpha_ab q_b
#
# Main Rashba Edelstein component:
# alpha_yx : q_x -> M_y
# ============================================================
using MPI
using LinearAlgebra
using Printf
using Dates
BLAS.set_num_threads(1)
# ============================================================
# 0. MPI initialization
# ============================================================
MPI.Init()
const comm = MPI.COMM_WORLD
const rank = MPI.Comm_rank(comm)
const nprocs = MPI.Comm_size(comm)
# ============================================================
# 1. Parameters
# ============================================================
const t_hop = 1.0
const mu = -3.0
const Delta0 = 0.10
const temperature = 0.03
# k mesh
const Nk = 251
# Rashba SOC scan
const lambda_min = 0.0
const lambda_max = 0.60
const lambda_num = 61
# Constants, dimensionless units
const gs = 2.0
const muB = 1.0
# Degeneracy tolerance for K_nm
const degeneracy_eps = 1.0e-10
# Output
const data_dir = "data"
const output_file = joinpath(data_dir, "rashba_lattice_edelstein_mpi.dat")
# ============================================================
# 2. Pauli matrices
# ============================================================
const s0 = ComplexF64[
1.0 + 0im 0.0 + 0im
0.0 + 0im 1.0 + 0im
]
const sx = ComplexF64[
0.0 + 0im 1.0 + 0im
1.0 + 0im 0.0 + 0im
]
const sy = ComplexF64[
0.0 + 0im 0.0 - 1im
0.0 + 1im 0.0 + 0im
]
const sz = ComplexF64[
1.0 + 0im 0.0 + 0im
0.0 + 0im -1.0 + 0im
]
const zero2 = zeros(ComplexF64, 2, 2)
# ============================================================
# 3. Small matrix helpers
# ============================================================
function block2x2(A::Matrix{ComplexF64}, B::Matrix{ComplexF64},
C::Matrix{ComplexF64}, D::Matrix{ComplexF64})
M = zeros(ComplexF64, 4, 4)
begin
M[1:2, 1:2] .= A
M[1:2, 3:4] .= B
M[3:4, 1:2] .= C
M[3:4, 3:4] .= D
end
return M
end
# ============================================================
# 4. Normal-state Rashba lattice Hamiltonian
# ============================================================
function h_normal(kx::Float64, ky::Float64, lambda_R::Float64)
xi = -2.0 * t_hop * (cos(kx) + cos(ky)) - mu
H = xi .* s0 .+
lambda_R .* (sin(kx) .* sy .- sin(ky) .* sx)
return Matrix{ComplexF64}(H)
end
function dh_dk(kx::Float64, ky::Float64, lambda_R::Float64, direction::Symbol)
if direction == :x
V = 2.0 * t_hop * sin(kx) .* s0 .+
lambda_R * cos(kx) .* sy
elseif direction == :y
V = 2.0 * t_hop * sin(ky) .* s0 .-
lambda_R * cos(ky) .* sx
else
error("direction must be :x or :y")
end
return Matrix{ComplexF64}(V)
end
# ============================================================
# 5. BdG Hamiltonian and Nambu operators
# ============================================================
function bdg_hamiltonian(kx::Float64, ky::Float64, lambda_R::Float64)
Hk = h_normal(kx, ky, lambda_R)
Hmk = h_normal(-kx, -ky, lambda_R)
Delta = Delta0 .* (1im .* sy)
HBdG = block2x2(
Hk,
Matrix{ComplexF64}(Delta),
Matrix{ComplexF64}(Delta'),
-conj.(Hmk),
)
return HBdG
end
function nambu_velocity(kx::Float64, ky::Float64, lambda_R::Float64, direction::Symbol)
Ve = dh_dk(kx, ky, lambda_R, direction)
Vh = -conj.(dh_dk(-kx, -ky, lambda_R, direction))
Vbdg = block2x2(
Ve,
zero2,
zero2,
Vh,
)
return Vbdg
end
function nambu_spin(direction::Symbol)
s = if direction == :x
sx
elseif direction == :y
sy
elseif direction == :z
sz
else
error("spin direction must be :x, :y, or :z")
end
eta = block2x2(
Matrix{ComplexF64}(s),
zero2,
zero2,
-conj.(s),
)
return eta
end
const eta_ops = (
nambu_spin(:x),
nambu_spin(:y),
nambu_spin(:z),
)
# ============================================================
# 6. Fermi function and response kernel
# ============================================================
function fermi(E::Float64, beta::Float64)
x = clamp(beta * E, -700.0, 700.0)
return 1.0 / (exp(x) + 1.0)
end
function fermi_derivative(E::Float64, beta::Float64)
f = fermi(E, beta)
return -beta * f * (1.0 - f)
end
function response_kernel!(K::Matrix{Float64}, E::Vector{Float64}, beta::Float64)
nb = length(E)
for n in 1:nb
En = E[n]
fn = fermi(En, beta)
for m in 1:nb
Em = E[m]
fm = fermi(Em, beta)
denom = En - Em
if abs(denom) > degeneracy_eps
K[n, m] = (fn - fm) / denom
else
K[n, m] = fermi_derivative(0.5 * (En + Em), beta)
end
end
end
return nothing
end
# ============================================================
# 7. k mesh distribution over MPI ranks
# ============================================================
function linear_index_to_k(idx::Int)
# idx = 1, ..., Nk*Nk
ix = div(idx - 1, Nk) + 1
iy = mod(idx - 1, Nk) + 1
dk = 2.0 * pi / Nk
# midpoint mesh on [-pi, pi)
kx = -pi + (ix - 0.5) * dk
ky = -pi + (iy - 0.5) * dk
return kx, ky
end
function lambda_grid()
if lambda_num == 1
return [lambda_min]
end
return collect(range(lambda_min, lambda_max, length=lambda_num))
end
# ============================================================
# 8. Local calculation for one lambda_R
# ============================================================
function local_accumulate_for_lambda(lambda_R::Float64)
beta = 1.0 / temperature
# alpha accumulator: 3 spin components x 2 q directions
acc_total = zeros(Float64, 3, 2)
acc_intra = zeros(Float64, 3, 2)
acc_inter = zeros(Float64, 3, 2)
nb = 4
K = zeros(Float64, nb, nb)
total_k = Nk * Nk
# MPI distribution over k points
for idx in (rank + 1):nprocs:total_k
kx, ky = linear_index_to_k(idx)
HBdG = bdg_hamiltonian(kx, ky, lambda_R)
eig = eigen(Hermitian(HBdG))
E = Vector{Float64}(eig.values)
U = Matrix{ComplexF64}(eig.vectors)
response_kernel!(K, E, beta)
Udag = U'
eta_band = (
Udag * eta_ops[1] * U,
Udag * eta_ops[2] * U,
Udag * eta_ops[3] * U,
)
vx_op = nambu_velocity(kx, ky, lambda_R, :x)
vy_op = nambu_velocity(kx, ky, lambda_R, :y)
v_band = (
Udag * vx_op * U,
Udag * vy_op * U,
)
for ia in 1:3
eta_b = eta_band[ia]
for ib in 1:2
v_b = v_band[ib]
total_val = 0.0
intra_val = 0.0
inter_val = 0.0
for n in 1:nb
for m in 1:nb
# eta_nm * v_mn * K_nm
val = real(eta_b[n, m] * v_b[m, n]) * K[n, m]
total_val += val
if n == m
intra_val += val
else
inter_val += val
end
end
end
acc_total[ia, ib] += total_val
acc_intra[ia, ib] += intra_val
acc_inter[ia, ib] += inter_val
end
end
end
return acc_total, acc_intra, acc_inter
end
# ============================================================
# 9. MPI allreduce helper
# ============================================================
function allreduce_sum_matrix(local_mat::Matrix{Float64})
global_mat = similar(local_mat)
MPI.Allreduce!(local_mat, global_mat, +, comm)
return global_mat
end
# ============================================================
# 10. Main calculation
# ============================================================
function main()
lambdas = lambda_grid()
if rank == 0
mkpath(data_dir)
("============================================================\n")
("Rashba lattice superconducting Edelstein effect\n")
("Julia MPI calculation\n")
("============================================================\n")
("MPI processes = %d\n", nprocs)
("t = %.8f\n", t_hop)
("mu = %.8f\n", mu)
("Delta0 = %.8f\n", Delta0)
("T = %.8f\n", temperature)
("Nk = %d x %d\n", Nk, Nk)
("lambda_R range = [%.8f, %.8f], N = %d\n",
lambda_min, lambda_max, lambda_num)
("output = %s\n", output_file)
("============================================================\n")
flush(stdout)
open(output_file, "w") do io
println(io, "# Square-lattice Rashba superconductor")
println(io, "# H(k) = xi(k) s0 + lambda_R [sin(kx) sy - sin(ky) sx]")
println(io, "# xi(k) = -2t [cos(kx)+cos(ky)] - mu")
println(io, "# Delta = Delta0 i sy")
println(io, "# Response: delta M_a = alpha_ab q_b")
println(io, "# Units: a = hbar = kB = muB = 1")
println(io, "#")
(io, "# t = %.16e\n", t_hop)
(io, "# mu = %.16e\n", mu)
(io, "# Delta0 = %.16e\n", Delta0)
(io, "# temperature = %.16e\n", temperature)
(io, "# Nk = %d\n", Nk)
(io, "# nprocs = %d\n", nprocs)
println(io, "#")
println(io, "# columns:")
println(io, "# lambda_R alpha_xx alpha_xy alpha_yx alpha_yy alpha_zx alpha_zy alpha_yx_intra alpha_yx_inter")
end
end
MPI.Barrier(comm)
t0 = time()
for (iλ, λ) in enumerate(lambdas)
local_total, local_intra, local_inter = local_accumulate_for_lambda(λ)
global_total_raw = allreduce_sum_matrix(local_total)
global_intra_raw = allreduce_sum_matrix(local_intra)
global_inter_raw = allreduce_sum_matrix(local_inter)
# For BZ = [-pi, pi]^2,
# ∫BZ d^2k/(2π)^2 equals uniform average over k mesh.
#
# Formula:
# alpha_ab = (gs*muB/8) * average_k sum_nm Re[eta_nm v_mn] K_nm
prefactor = gs * muB / 8.0
norm = 1.0 / (Nk * Nk)
alpha_total = prefactor .* norm .* global_total_raw
alpha_intra = prefactor .* norm .* global_intra_raw
alpha_inter = prefactor .* norm .* global_inter_raw
if rank == 0
αxx = alpha_total[1, 1]
αxy = alpha_total[1, 2]
αyx = alpha_total[2, 1]
αyy = alpha_total[2, 2]
αzx = alpha_total[3, 1]
αzy = alpha_total[3, 2]
αyx_intra = alpha_intra[2, 1]
αyx_inter = alpha_inter[2, 1]
open(output_file, "a") do io
(io,
"%.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e %.16e\n",
λ, αxx, αxy, αyx, αyy, αzx, αzy, αyx_intra, αyx_inter
)
end
("[%4d/%4d] lambda_R = %.8f | alpha_yx = %+ .8e | intra = %+ .8e | inter = %+ .8e\n",
iλ, length(lambdas), λ, αyx, αyx_intra, αyx_inter)
flush(stdout)
end
end
MPI.Barrier(comm)
if rank == 0
elapsed = time() - t0
("============================================================\n")
("Finished. Elapsed time = %.2f s\n", elapsed)
("Data saved to: %s\n", output_file)
("============================================================\n")
end
end
main()
MPI.Finalize()绘图代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Plot superconducting Edelstein response from Julia MPI dat output.
Input:
data/rashba_lattice_edelstein_mpi.dat
Output:
figures/rashba_lattice_edelstein_alpha_tensor.png
figures/rashba_lattice_edelstein_alpha_tensor.pdf
figures/rashba_lattice_edelstein_alpha_yx_intra_inter.png
figures/rashba_lattice_edelstein_alpha_yx_intra_inter.pdf
"""
import os
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
# ============================================================
# 0. Settings
# ============================================================
DATA_FILE = "data/rashba_lattice_edelstein_mpi.dat"
FIG_DIR = "figures"
SAVE_PREFIX = "rashba_lattice_edelstein"
PLOT_ONLY_MAIN_COMPONENTS = False
# If True, show the figures interactively.
SHOW_FIG = True
# ============================================================
# 1. Plot style
# ============================================================
def setup_style():
plt.rcParams["font.family"] = "Times New Roman"
plt.rcParams["mathtext.fontset"] = "stix"
plt.rcParams["font.size"] = 18
plt.rcParams["axes.linewidth"] = 1.2
plt.rcParams["xtick.direction"] = "in"
plt.rcParams["ytick.direction"] = "in"
plt.rcParams["xtick.top"] = True
plt.rcParams["ytick.right"] = True
plt.rcParams["legend.frameon"] = False
def format_axes(ax):
"""
Common axis formatting:
1. Square plotting box.
2. At most 3 major tick labels on x and y axes.
"""
ax.set_box_aspect(1)
# nbins=2 usually gives at most 3 major ticks.
ax.xaxis.set_major_locator(MaxNLocator(nbins=2, min_n_ticks=2))
ax.yaxis.set_major_locator(MaxNLocator(nbins=2, min_n_ticks=2))
ax.tick_params(width=1.2, length=5)
# ============================================================
# 2. Load data
# ============================================================
def load_data(path):
if not os.path.exists(path):
raise FileNotFoundError(f"Cannot find data file: {path}")
data = np.loadtxt(path, comments="#")
lam = data[:, 0]
alpha_xx = data[:, 1]
alpha_xy = data[:, 2]
alpha_yx = data[:, 3]
alpha_yy = data[:, 4]
alpha_zx = data[:, 5]
alpha_zy = data[:, 6]
alpha_yx_intra = data[:, 7]
alpha_yx_inter = data[:, 8]
return {
"lambda": lam,
"alpha_xx": alpha_xx,
"alpha_xy": alpha_xy,
"alpha_yx": alpha_yx,
"alpha_yy": alpha_yy,
"alpha_zx": alpha_zx,
"alpha_zy": alpha_zy,
"alpha_yx_intra": alpha_yx_intra,
"alpha_yx_inter": alpha_yx_inter,
}
# ============================================================
# 3. Plot tensor components
# ============================================================
def plot_alpha_tensor(d):
lam = d["lambda"]
fig, ax = plt.subplots(figsize=(5.8, 5.8))
ax.plot(
lam,
d["alpha_yx"],
marker="o",
markersize=4,
linewidth=1.8,
label=r"$\alpha_{yx}$",
)
ax.plot(
lam,
d["alpha_xy"],
marker="s",
markersize=4,
linewidth=1.8,
linestyle="--",
label=r"$\alpha_{xy}$",
)
if not PLOT_ONLY_MAIN_COMPONENTS:
ax.plot(
lam,
d["alpha_xx"],
linewidth=1.3,
linestyle=":",
label=r"$\alpha_{xx}$",
)
ax.plot(
lam,
d["alpha_yy"],
linewidth=1.3,
linestyle="-.",
label=r"$\alpha_{yy}$",
)
ax.plot(
lam,
d["alpha_zx"],
linewidth=1.1,
linestyle=(0, (5, 2)),
label=r"$\alpha_{zx}$",
)
ax.plot(
lam,
d["alpha_zy"],
linewidth=1.1,
linestyle=(0, (3, 2, 1, 2)),
label=r"$\alpha_{zy}$",
)
ax.axhline(0.0, linewidth=1.0, color="black", alpha=0.5)
ax.set_xlabel(r"Rashba SOC $\lambda_R/t$")
ax.set_ylabel(r"Edelstein response $\alpha_{ab}$")
ax.set_xlim(lam.min(), lam.max())
format_axes(ax)
ax.legend(fontsize=12, loc="best")
fig.tight_layout()
png_path = os.path.join(FIG_DIR, f"{SAVE_PREFIX}_alpha_tensor.png")
pdf_path = os.path.join(FIG_DIR, f"{SAVE_PREFIX}_alpha_tensor.pdf")
fig.savefig(png_path, dpi=300, bbox_inches="tight", pad_inches=0.02)
fig.savefig(pdf_path, bbox_inches="tight", pad_inches=0.02)
print(f"Saved figure: {png_path}")
print(f"Saved figure: {pdf_path}")
return fig, ax
# ============================================================
# 4. Plot intra/inter decomposition
# ============================================================
def plot_alpha_yx_intra_inter(d):
lam = d["lambda"]
fig, ax = plt.subplots(figsize=(5.8, 5.8))
ax.plot(
lam,
d["alpha_yx"],
marker="o",
markersize=4,
linewidth=1.8,
label=r"total $\alpha_{yx}$",
)
ax.plot(
lam,
d["alpha_yx_intra"],
linewidth=1.8,
linestyle="--",
label=r"intra-band",
)
ax.plot(
lam,
d["alpha_yx_inter"],
linewidth=1.8,
linestyle="-.",
label=r"inter-band",
)
ax.axhline(0.0, linewidth=1.0, color="black", alpha=0.5)
ax.set_xlabel(r"Rashba SOC $\lambda_R/t$")
ax.set_ylabel(r"$\alpha_{yx}$")
ax.set_xlim(lam.min(), lam.max())
format_axes(ax)
ax.legend(fontsize=12, loc="best")
fig.tight_layout()
png_path = os.path.join(FIG_DIR, f"{SAVE_PREFIX}_alpha_yx_intra_inter.png")
pdf_path = os.path.join(FIG_DIR, f"{SAVE_PREFIX}_alpha_yx_intra_inter.pdf")
fig.savefig(png_path, dpi=300, bbox_inches="tight", pad_inches=0.02)
fig.savefig(pdf_path, bbox_inches="tight", pad_inches=0.02)
print(f"Saved figure: {png_path}")
print(f"Saved figure: {pdf_path}")
return fig, ax
# ============================================================
# 5. Main
# ============================================================
def main():
setup_style()
os.makedirs(FIG_DIR, exist_ok=True)
d = load_data(DATA_FILE)
print("=" * 80)
print("Loaded data")
print("=" * 80)
print(f"Data file = {DATA_FILE}")
print(f"Number of SOCs = {len(d['lambda'])}")
print(f"lambda range = [{d['lambda'].min():.6f}, {d['lambda'].max():.6f}]")
print("=" * 80)
plot_alpha_tensor(d)
plot_alpha_yx_intra_inter(d)
if SHOW_FIG:
plt.show()
else:
plt.close("all")
if __name__ == "__main__":
main()
参考文献
鉴于该网站分享的大都是学习笔记,作者水平有限,若发现有问题可以发邮件给我
- yxliphy@gmail.com
也非常欢迎喜欢分享的小伙伴投稿










