Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ jobs:
matrix:
version:
- '1.2'
- '1.6'
- '~1.7.0-0'
- 'nightly'
- '1.7'
- '1'
os:
- ubuntu-latest
- macOS-latest
Expand Down Expand Up @@ -49,7 +48,7 @@ jobs:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: '1.6'
version: '1.8'
- run: |
julia --project=docs -e '
using Pkg
Expand All @@ -66,14 +65,14 @@ jobs:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: '1.6'
version: '1.8'
- run: |
julia --project=docs -e '
using Pkg
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()'
- run: |
julia --project=docs -e '
julia --project=docs --color=yes -e '
using Documenter: DocMeta, doctest
using AtomicLevels
DocMeta.setdocmeta!(AtomicLevels, :DocTestSetup, :(using AtomicLevels); recursive=true)
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "AtomicLevels"
uuid = "10933b4c-d60f-11e8-1fc6-bd9035a249a1"
authors = ["Stefanos Carlström <stefanos.carlstrom@gmail.com>"]
version = "0.1.8"
version = "0.2"

[deps]
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ AtomicLevels = "10933b4c-d60f-11e8-1fc6-bd9035a249a1"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "0.25"
Documenter = "0.27"
5 changes: 4 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@ makedocs(
doctest = false
)

deploydocs(repo = "github.com/JuliaAtoms/AtomicLevels.jl.git")
deploydocs(;
repo = "github.com/JuliaAtoms/AtomicLevels.jl.git",
push_preview = true,
)
3 changes: 2 additions & 1 deletion docs/src/csfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ In the multi-electron case, the states that you multiply together are the atomic

2. Electrons are fermionic particles adhering to the [Pauli principle](https://en.wikipedia.org/wiki/Pauli_exclusion_principle).

This means that not all direct products of single-particle states are valid (the same single-particle state can not be repeated) or unique (anti-symmetry means that the order in the product does not matter). This, in turn, means that not all the coupled eigenstates predicted by the Clebsch-Gordan relation actually exist and you can not use the Clebsch–Gordan relation directly to determine their coefficients.
This means that not all direct products of single-particle states are valid (the same single-particle state can not be repeated) or unique (anti-symmetry means that the order in the product does not matter). This, in turn, means that not all the coupled eigenstates predicted by the ClebschGordan relation actually exist and you can not use the Clebsch–Gordan relation directly to determine their coefficients.

To work within those constraints, AtomicLevels specifies a _coupling scheme_. That is, the CSFs contain additional data that allows the states to be identified uniquely.

Expand Down Expand Up @@ -100,6 +100,7 @@ NonRelativisticCSF
RelativisticCSF
csfs
orbitals(::CSF)
term(::CSF)
```

## Index
Expand Down
1 change: 1 addition & 0 deletions docs/src/orbitals.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ generic orbitals can dispatch on that.
Orbital
RelativisticOrbital
AbstractOrbital
SpatialOrbital
```

The [`SpinOrbital`](@ref) type can be used to fully qualify all the quantum numbers (that
Expand Down
30 changes: 20 additions & 10 deletions docs/src/terms.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ intermediate_terms
### Disambiguating quantum numbers

The [`IntermediateTerm`](@ref) type does not specify how to interpret the disambiguating
quantum number(s) ``ν``, or even what the type of it should be. In AtomicLevels, we use two
quantum number(s) ``ν``, or even what the type of it should be. In AtomicLevels, we use four
different types, depending on the situation:

* **A simple `Integer`.** In this case, the quantum number ``\nu`` must be in the range
Expand All @@ -87,14 +87,24 @@ different types, depending on the situation:

AtomicLevels does not prescribe any further interpretation for the quantum number.
It can be used as a simple counter to distinguish the different terms, or the user can
define their own mapping from the set of integers to physical states.
define their own mapping from the set of integers to physical
states. See also [`TermEnumeration`](@ref) which can be used to wrap
this integer.

* **`Seniority`.** In this case the number is interpreted to be _Racah's seniority
number_. This gives the intermediate term a specific physical interpretation, but only
works for certain subshells. See the [`Seniority`](@ref) type for more information.

* **`SeniorityEnumeration`.** To further disambiguate those terms
which are degenerate for a given seniority ``\nu``, an additional,
ad-hoc, quantum number ``\alpha`` is added to the classification,
which simply enumerates the multiplet. See the
[`SeniorityEnumeration`](@ref) type for more information.

```@docs
Seniority
SeniorityEnumeration
TermEnumeration
```

## Term couplings
Expand Down Expand Up @@ -130,7 +140,7 @@ individual subshells:

```jldoctest intermediate_term_examples
julia> its = intermediate_terms(c"3p2 4s 5p2")
3-element Vector{Vector{IntermediateTerm{Term, Seniority}}}:
3-element Vector{Vector{IntermediateTerm{Term, SeniorityEnumeration}}}:
[₀¹S, ₂¹D, ₂³P]
[₁²S]
[₀¹S, ₂¹D, ₂³P]
Expand Down Expand Up @@ -222,7 +232,7 @@ each subshell of `3p² 4s 5p²`

```jldoctest intermediate_term_examples
julia> last.(its)
3-element Vector{IntermediateTerm{Term, Seniority}}:
3-element Vector{IntermediateTerm{Term, SeniorityEnumeration}}:
₂³P
₁²S
₂³P
Expand Down Expand Up @@ -268,12 +278,12 @@ schemes has the following [`CSF`](@ref)s:

```jldoctest levels_and_states
julia> csls = csfs(c"1s 2p")
2-element Vector{NonRelativisticCSF{Orbital{Int64}, Seniority}}:
2-element Vector{NonRelativisticCSF{Orbital{Int64}, SeniorityEnumeration}}:
1s(₁²S|²S) 2p(₁²Pᵒ|¹Pᵒ)-
1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-

julia> csjj = vcat(csfs(rc"1s 2p"), csfs(rc"1s 2p-"))
4-element Vector{RelativisticCSF{RelativisticOrbital{Int64}, Seniority}}:
4-element Vector{RelativisticCSF{RelativisticOrbital{Int64}, SeniorityEnumeration}}:
1s(₁1/2|1/2) 2p(₁3/2|1)-
1s(₁1/2|1/2) 2p(₁3/2|2)-
1s(₁1/2|1/2) 2p-(₁1/2|0)-
Expand All @@ -285,12 +295,12 @@ values of ``J``, i.e. ``0``, ``2\times 1``, and ``2``:

```jldoctest levels_and_states
julia> levels.(csls)
2-element Vector{Vector{Level{Orbital{Int64}, Term, Seniority}}}:
2-element Vector{Vector{Level{Orbital{Int64}, Term, SeniorityEnumeration}}}:
[|1s(₁²S|²S) 2p(₁²Pᵒ|¹Pᵒ)-, J = 1⟩]
[|1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-, J = 0⟩, |1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-, J = 1⟩, |1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-, J = 2⟩]

julia> levels.(csjj)
4-element Vector{Vector{Level{RelativisticOrbital{Int64}, HalfIntegers.Half{Int64}, Seniority}}}:
4-element Vector{Vector{Level{RelativisticOrbital{Int64}, HalfIntegers.Half{Int64}, SeniorityEnumeration}}}:
[|1s(₁1/2|1/2) 2p(₁3/2|1)-, J = 1⟩]
[|1s(₁1/2|1/2) 2p(₁3/2|2)-, J = 2⟩]
[|1s(₁1/2|1/2) 2p-(₁1/2|0)-, J = 0⟩]
Expand All @@ -311,7 +321,7 @@ schemes, sorting by ``M_J`` for clarity:

```jldoctest levels_and_states
julia> sort(reduce(vcat, reduce(vcat, states.(csls))), by=s->s.M_J)
12-element Vector{State{Orbital{Int64}, Term, Seniority}}:
12-element Vector{State{Orbital{Int64}, Term, SeniorityEnumeration}}:
|1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-, J = 2, M_J = -2⟩
|1s(₁²S|²S) 2p(₁²Pᵒ|¹Pᵒ)-, J = 1, M_J = -1⟩
|1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-, J = 1, M_J = -1⟩
Expand All @@ -326,7 +336,7 @@ julia> sort(reduce(vcat, reduce(vcat, states.(csls))), by=s->s.M_J)
|1s(₁²S|²S) 2p(₁²Pᵒ|³Pᵒ)-, J = 2, M_J = 2⟩

julia> sort(reduce(vcat, reduce(vcat, states.(csjj))), by=s->s.M_J)
12-element Vector{State{RelativisticOrbital{Int64}, HalfIntegers.Half{Int64}, Seniority}}:
12-element Vector{State{RelativisticOrbital{Int64}, HalfIntegers.Half{Int64}, SeniorityEnumeration}}:
|1s(₁1/2|1/2) 2p(₁3/2|2)-, J = 2, M_J = -2⟩
|1s(₁1/2|1/2) 2p(₁3/2|1)-, J = 1, M_J = -1⟩
|1s(₁1/2|1/2) 2p(₁3/2|2)-, J = 2, M_J = -1⟩
Expand Down
14 changes: 14 additions & 0 deletions src/common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,17 @@ function spectroscopic_label(ℓ)
ℓ >= 0 || throw(DomainError(ℓ, "Negative ℓ values not allowed"))
ℓ + 1 ≤ length(spectroscopic) ? spectroscopic[ℓ+1] : "[$(ℓ)]"
end

"""
@< a b [lt]

Helper macro that returns `true` if `a < b`, `false` if `a > b`, and
does nothing if `a == b`. The intended use-case is to simplify the
implementation of `isless` methods. Optionally accepts a custom
implementation of `lt`.
"""
macro <(a, b, lt=:(<))
islt = :($(esc(lt))($(esc(a)), $(esc(b))) && return true)
isgt = :($(esc(lt))($(esc(b)), $(esc(a))) && return false)
Expr(:block, islt, isgt, :(false))
end
16 changes: 8 additions & 8 deletions src/configurations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -935,9 +935,9 @@ non-relativistic orbital with `n` and `ℓ` quantum numbers, with given occupanc

# Examples

```jldoctest; filter = r"#s[0-9]+"
```jldoctest
julia> AtomicLevels.rconfigurations_from_orbital(3, 1, 2)
3-element Vector{Configuration{var"#s00"} where var"#s00"<:RelativisticOrbital}:
3-element Vector{Configuration{<:RelativisticOrbital}}:
3p-²
3p- 3p
3p²
Expand Down Expand Up @@ -977,9 +977,9 @@ non-relativistic version of the `orbital` with a given occupancy.

# Examples

```jldoctest; filter = r"#s[0-9]+"
```jldoctest
julia> AtomicLevels.rconfigurations_from_orbital(o"3p", 2)
3-element Vector{Configuration{var"#s00"} where var"#s00"<:RelativisticOrbital}:
3-element Vector{Configuration{<:RelativisticOrbital}}:
3p-²
3p- 3p
3p²
Expand Down Expand Up @@ -1035,9 +1035,9 @@ and `occupancy` are integers, and `ℓ` is in spectroscopic notation.

# Examples

```jldoctest; filter = r"#s[0-9]+"
```jldoctest
julia> rcs"3p2"
3-element Vector{Configuration{var"#s00"} where var"#s00"<:RelativisticOrbital}:
3-element Vector{Configuration{<:RelativisticOrbital}}:
3p-²
3p- 3p
3p²
Expand All @@ -1054,7 +1054,7 @@ end
Generate all possible configurations of spin-orbitals from `configuration`, i.e. all
permissible values for the quantum numbers `n`, `ℓ`, `mℓ`, `ms` for each electron. Example:

```jldoctest; filter = r"#s[0-9]+"
```jldoctest
julia> spin_configurations(c"1s2")
1-element Vector{SpinConfiguration{SpinOrbital{Orbital{Int64}, Tuple{Int64, HalfIntegers.Half{Int64}}}}}:
1s₀α 1s₀β
Expand All @@ -1064,7 +1064,7 @@ julia> spin_configurations(c"1s2"s)
1s₀α 1s₀β

julia> spin_configurations(c"1s ks")
4-element Vector{SpinConfiguration{SpinOrbital{var"#s00", Tuple{Int64, HalfIntegers.Half{Int64}}} where var"#s00"<:Orbital}}:
4-element Vector{SpinConfiguration{SpinOrbital{<:Orbital, Tuple{Int64, HalfIntegers.Half{Int64}}}}}:
1s₀α ks₀α
1s₀β ks₀α
1s₀α ks₀β
Expand Down
78 changes: 72 additions & 6 deletions src/csfs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ or non-relativistic orbitals.
* If it is a configuration of [`RelativisticOrbital`](@ref)s, both `subshell_terms` and
`terms` should both be a list of half-integer values.
"""
struct CSF{O<:AbstractOrbital, T<:Union{Term,HalfInteger}, S}
struct CSF{O<:SpatialOrbital, T<:Union{Term,HalfInteger}, S}
config::Configuration{<:O}
subshell_terms::Vector{IntermediateTerm{T,S}}
terms::Vector{T}
Expand Down Expand Up @@ -74,6 +74,9 @@ Base.isless(a::CSF, b::CSF) = last(a.terms) < last(b.terms)

num_electrons(csf::CSF) = num_electrons(csf.config)

isrelativistic(::NonRelativisticCSF) = false
isrelativistic(::RelativisticCSF) = true

"""
orbitals(csf::CSF{O}) -> Vector

Expand All @@ -93,6 +96,68 @@ julia> orbitals(csf)
"""
orbitals(csf::CSF) = orbitals(csf.config)

"""
term(csf::CSF)

Return the final term of `csf`.

```jldoctest
julia> c = first(csfs(c"1s 2p"))
1s(₁²S|²S) 2p(₁²Pᵒ|¹Pᵒ)-

julia> term(c)
¹Pᵒ

julia> c = first(csfs(rc"1s2 2p-2"))
1s² 2p-²
0 0
0 0+

julia> term(c)
0

julia> c = first(csfs(rc"1s2 2p-"))
1s² 2p-
0 1/2
0 1/2-

julia> term(c)
1/2
```
"""
term(csf::CSF) = last(csf.terms)

"""
parity(csf::CSF) -> Parity

Return the parity of `csf`.

```jldoctest
julia> c = first(csfs(c"1s 2p"))
1s(₁²S|²S) 2p(₁²Pᵒ|¹Pᵒ)-

julia> parity(c)
odd

julia> c = first(csfs(rc"1s2 2p-2"))
1s² 2p-²
0 0
0 0+

julia> parity(c)
even

julia> c = first(csfs(rc"1s2 2p-"))
1s² 2p-
0 1/2
0 1/2-

julia> parity(c)
odd
```
"""
parity(csf::CSF) = parity(csf.config)

"""
csfs(::Configuration) -> Vector{CSF}
csfs(::Vector{Configuration}) -> Vector{CSF}
Expand All @@ -102,15 +167,16 @@ configurations.
"""
function csfs end

function csfs(config::Configuration)
map(allchoices(intermediate_terms(peel(config)))) do subshell_terms
function csfs(config::Configuration, DQN::Type=SeniorityEnumeration)
map(allchoices(intermediate_terms(DQN, peel(config)))) do subshell_terms
map(intermediate_couplings(subshell_terms)) do coupled_terms
CSF(config, subshell_terms, coupled_terms[2:end])
end
end |> c -> vcat(c...) |> sort
end |> c -> reduce(vcat, c) |> sort
end

csfs(configs::Vector{Configuration{O}}) where O = vcat(map(csfs, configs)...)
csfs(configs::Vector{Configuration{O}}, DQN::Type=SeniorityEnumeration) where O =
reduce(vcat, map(Base.Fix2(csfs, DQN), configs))

Base.length(csf::CSF) = length(peel(csf.config))
Base.getindex(csf::CSF, i::Integer) =
Expand Down Expand Up @@ -184,4 +250,4 @@ function Base.show(io::IO, ::MIME"text/plain", csf::RelativisticCSF)
print(io, iseven(parity(csf.config)) ? "+" : "-")
end

export CSF, NonRelativisticCSF, RelativisticCSF, csfs
export CSF, NonRelativisticCSF, RelativisticCSF, csfs, term
Loading