/
list_psp.jl
78 lines (69 loc) · 3.06 KB
/
list_psp.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
import IterTools
"""
list_psp(element; functional, family, core, datadir_psp)
List the pseudopotential files known to DFTK. Allows various ways
to restrict the displayed files.
# Examples
```julia-repl
julia> list_psp(family="hgh")
```
will list all HGH-type pseudopotentials and
```julia-repl
julia> list_psp(family="hgh", functional="lda")
```
will only list those for LDA (also known as Pade in this context)
and
```julia-repl
julia> list_psp(:O, core=:semicore)
```
will list all oxygen semicore pseudopotentials known to DFTK.
"""
function list_psp(element=nothing; family=nothing, functional=nothing, core=nothing,
datadir_psp=datadir_psp())
# Normalize input keys
isnothing(element) || (element = Symbol(PeriodicTable.elements[element].symbol))
isnothing(functional) || (functional = lowercase(functional))
isnothing(family) || (family = lowercase(family))
# Path separator character
pathsep = Sys.iswindows() ? '\\' : '/'
psplist = []
for (root, _, files) in walkdir(datadir_psp)
root = relpath(root, datadir_psp)
for file in files
base, ext = splitext(file)
ext == ".sh" && continue # Ignore scripts
count(isequal('-'), base) == 1 || continue # Need exactly one '-' in filename
count(isequal(pathsep), root) == 1 || continue # family/functional
f_family, f_functional = split(root, pathsep)
f_element, f_nvalence = split(base, '-')
f_nvalence[1] == 'q' || continue # Need 'q' before valence number
f_element = Symbol(uppercase(f_element[1]) * f_element[2:end])
haskey(PeriodicTable.elements, Symbol(f_element)) || continue
f_identifier = joinpath(root, file)
Sys.iswindows() && (f_identifier = replace(f_identifier, "\\" => "/"))
push!(psplist, (identifier=f_identifier, family=f_family,
functional=f_functional, element=f_element,
n_elec_valence=parse(Int, f_nvalence[2:end]),
path=joinpath(datadir_psp, root, file)))
end
end
# Annotate "core" property (:other, :semicore, :fullcore)
per_elem = IterTools.groupby(psp -> (psp.family, psp.functional, psp.element), psplist)
psp_per_element = map(per_elem) do elgroup
@assert length(elgroup) > 0
if length(elgroup) == 1
cores = [(core=:fullcore, )]
else
cores = append!(fill((core=:other, ), length(elgroup) - 2),
[(core=:fullcore, ), (core=:semicore, )])
end
merge.(sort(elgroup, by=psp -> psp.n_elec_valence), cores)
end
filter(collect(Iterators.flatten(psp_per_element))) do psp
!isnothing(element) && psp.element != element && return false
!isnothing(functional) && psp.functional != functional && return false
!isnothing(family) && psp.family != family && return false
!isnothing(core) && psp.core != core && return false
true
end
end