forked from JuliaMolSim/DFTK.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plotting.jl
91 lines (79 loc) · 3.13 KB
/
plotting.jl
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
# This is needed to flag that the plots-dependent code has been loaded
const PLOTS_LOADED = true
function ScfPlotTrace(plt=Plots.plot(yaxis=:log); kwargs...)
energies = nothing
function callback(info)
if info.stage == :finalize
minenergy = minimum(energies[max(1, end-5):end])
error = abs.(energies .- minenergy)
error[error .== 0] .= NaN
extra = ifelse(:mark in keys(kwargs), (), (mark=:x, ))
Plots.plot!(plt, error; extra..., kwargs...)
display(plt)
elseif info.n_iter == 1
energies = [info.energies.total]
else
push!(energies, info.energies.total)
end
info
end
end
function plot_band_data(band_data; εF=nothing,
klabels=Dict{String, Vector{Float64}}(), unit=u"hartree", kwargs...)
eshift = isnothing(εF) ? 0.0 : εF
data = prepare_band_data(band_data, klabels=klabels)
# Constant to convert from AU to the desired unit
to_unit = ustrip(auconvert(unit, 1.0))
markerargs = ()
if !(:markersize in keys(kwargs)) && !(:markershape in keys(kwargs))
if length(krange_spin(band_data.basis, 1)) < 70
markerargs = (markersize=2, markershape=:circle)
end
end
# For each branch, plot all bands, spins and errors
p = Plots.plot(xlabel="wave vector")
for branch in data.branches
for σ in 1:data.n_spin, iband = 1:data.n_bands
yerror = nothing
if hasproperty(branch, :λerror)
yerror = branch.λerror[:, iband, σ] .* to_unit
end
energies = (branch.λ[:, iband, σ] .- eshift) .* to_unit
color = (:blue, :red)[σ]
Plots.plot!(p, branch.kdistances, energies; color, label="",
yerror, markerargs..., kwargs...)
end
end
# X-range: 0 to last kdistance value
Plots.xlims!(p, (0, data.branches[end].kdistances[end]))
Plots.xticks!(p, data.ticks.distances, data.ticks.labels)
ylims = [-0.147, 0.147]
!isnothing(εF) && is_metal(band_data, εF) && (ylims = [-0.367, 0.367])
ylims = round.(ylims .* to_unit, sigdigits=2)
if isnothing(εF)
Plots.ylabel!(p, "eigenvalues ($(string(unit)))")
else
Plots.ylabel!(p, "eigenvalues - ε_f ($(string(unit)))")
Plots.ylims!(p, ylims...)
end
p
end
function plot_dos(basis, eigenvalues; εF=nothing, kwargs...)
n_spin = basis.model.n_spin_components
εs = range(minimum(minimum(eigenvalues)) - .5,
maximum(maximum(eigenvalues)) + .5, length=1000)
p = Plots.plot(;kwargs...)
spinlabels = spin_components(basis.model)
colors = [:blue, :red]
Dεs = compute_dos.(εs, Ref(basis), Ref(eigenvalues))
for σ in 1:n_spin
D = [Dσ[σ] for Dσ in Dεs]
label = n_spin > 1 ? "DOS $(spinlabels[σ]) spin" : "DOS"
Plots.plot!(p, εs, D, label=label, color=colors[σ])
end
if !isnothing(εF)
Plots.vline!(p, [εF], label="εF", color=:green, lw=1.5)
end
p
end
plot_dos(scfres; kwargs...) = plot_dos(scfres.basis, scfres.eigenvalues; εF=scfres.εF, kwargs...)