Skip to content

Commit

Permalink
l and m ranges in LM and ML
Browse files Browse the repository at this point in the history
  • Loading branch information
jishnub committed Jul 31, 2020
1 parent 7e1b9d2 commit bb7c79e
Show file tree
Hide file tree
Showing 9 changed files with 1,164 additions and 3,544 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
Manifest.toml
*.jl.*.cov
*.jl.cov
docs/build
2 changes: 1 addition & 1 deletion Project.toml
@@ -1,6 +1,6 @@
name = "SphericalHarmonicModes"
uuid = "0e9554e2-b38b-11e9-16d7-9d9abfec665a"
version = "0.3.4"
version = "0.4.0"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
68 changes: 20 additions & 48 deletions README.md
Expand Up @@ -9,7 +9,7 @@ This package provides a few iterators that are relevant in the context of spheri
The iterators implemented currently are:

1. `LM` and `ML`: Two iterators to loop over spherical harmonic modes denoted by `(l,m)`, where `l` is the angular degree and `m` is the azimuthal order.
2. `L₂L₁Δ`: An iterator to loop over pairs of spherical harmonic degrees `l₁` and `l₂`, where `|l₁-Δl| <= l₂ <= l₁+Δl`. The iterator generates pairs of `(l₂,l₁)` for a specified range of `l₁` and all `Δl` that satisfy `0 ⩽ Δl ⩽ Δl_max` for a specified `Δl_max`. Optionally a bound on `l₂` may be specified.
2. `L2L1Triangle`: An iterator to loop over pairs of spherical harmonic degrees `l2` and `l1` that satisfy the triangle condition `|l1-Δl| <= l2 <= l1+Δl`. The iterator generates pairs of `(l2,l1)` for a specified range of `l1` and all `Δl` that satisfy `0 ⩽ Δl ⩽ Δl_max` for a specified `Δl_max`. Optionally a bound on `l2` may be specified.

## Getting Started

Expand All @@ -29,7 +29,7 @@ There are two different orderings possible to iterate over spherical harmonic mo
Both the iterators are created using the general syntax `itr(l_min,l_max,m_min,m_max)` where `itr` may be `LM` or `ML`. To create an iterator with `m` increasing faster than `l`:

```julia
julia> itr = ML(0,1,-1,1)
julia> itr = ML(0:1, -1:1)
Spherical harmonic modes with m increasing faster than l
(l_min = 0, l_max = 1, m_min = -1, m_max = 1)

Expand All @@ -44,7 +44,7 @@ julia> collect(itr)
To create an iterator with `l` increasing faster than `m`:

```julia
julia> itr = LM(0,1,-1,1)
julia> itr = LM(0:1, -1:1)
Spherical harmonic modes with l increasing faster than m
(l_min = 0, l_max = 1, m_min = -1, m_max = 1)

Expand All @@ -59,33 +59,25 @@ julia> collect(itr)
Special constructors to include all `m`'s are available for convenience.

```julia
julia> LM(2) # only one l, and all valid m for that l
Spherical harmonic modes with l increasing faster than m
(l_min = 2, l_max = 2, m_min = -2, m_max = 2)

julia> LM(2,4) # a range in l, and all valid m for each l
julia> LM(2:4) # a range in l, and all valid m for each l
Spherical harmonic modes with l increasing faster than m
(l_min = 2, l_max = 4, m_min = -4, m_max = 4)

julia> LM(2:4) == LM(2,4) # may specify the range as a UnitRange
true
```

You may also choose a range of `m`'s.
```julia
julia> LM(2:4,0:2) # a range in l, and all valid m in range for each l
julia> LM(2:4, 0:2) # a range in l, and all valid m in range for each l
Spherical harmonic modes with l increasing faster than m
(l_min = 2, l_max = 4, m_min = 0, m_max = 2)
```

### Creating an (l₂,l₁) iterator
### Creating an (l2,l1) iterator

This iterator may be created as `L₂L₁Δ(l₁_min,l₁_max,Δl_max,l₂_min,l₂_max)`, for example
This iterator may be created as `L2L1Triangle(l1_min,l1_max,Δl_max,l2_min,l2_max)`, for example

```julia
julia> itr = L₂L₁Δ(1,3,2,2,4)
Spherical harmonic modes (l₂,l₁) where |l₁-Δl| l₂ l₁+Δl for 0 Δl Δl_max, l₁_min l₁ l₁_max, and l₂_min l₂ l₂_max
(2 l₂ 4 and 1 l₁ 3, with Δl_max = 2)
julia> itr = L2L1Triangle(1,3,2,2,4)
Spherical harmonic modes (l2,l1) that satisfy l1 - 2 l2 l1 + 2, with 2 l2 4 and 1 l1 3

julia> collect(itr)
8-element Array{Tuple{Int64,Int64},1}:
Expand All @@ -99,47 +91,27 @@ julia> collect(itr)
(4, 3)
```

The ranges of `l₁` and `l₂` will be clipped to the maximal valid subset dictated by `Δl_max`. Several convenience constructors are available, such as

```julia
julia> itr = L₂L₁Δ(1,2,2) # all valid l₂
Spherical harmonic modes (l₂,l₁) where |l₁-Δl| l₂ l₁+Δl for 0 Δl Δl_max, l₁_min l₁ l₁_max, and l₂_min l₂ l₂_max
(0 l₂ 4 and 1 l₁ 2, with Δl_max = 2)

julia> L₂L₁Δ(1:2,2) == L₂L₁Δ(1,2,2) # the range in l₁ may be specified as a UnitRange
true

julia> itr = L₂L₁Δ(1:2,2,2) # all valid l₂ that lie above the lower cutoff
Spherical harmonic modes (l₂,l₁) where |l₁-Δl| l₂ l₁+Δl for 0 Δl Δl_max, l₁_min l₁ l₁_max, and l₂_min l₂ l₂_max
(2 l₂ 4 and 1 l₁ 2, with Δl_max = 2)

julia> itr = L₂L₁Δ(1:2,2,2,2) # all valid l₂ in range
Spherical harmonic modes (l₂,l₁) where |l₁-Δl| l₂ l₁+Δl for 0 Δl Δl_max, l₁_min l₁ l₁_max, and l₂_min l₂ l₂_max
(2 l₂ 2 and 1 l₁ 2, with Δl_max = 2)

julia> L₂L₁Δ(1:2,2,2:2) == L₂L₁Δ(1:2,2,2,2) # the range in l₂ may be specified as a UnitRange
true
```
The ranges of `l1` and `l2` will be clipped to the maximal valid subset dictated by `Δl_max`.

### Using the iterators

The length of an iterator can be computed in `O(1)` time.

```julia
julia> @btime length(m) setup=(m=LM(0:rand(1:1000000)))
20.160 ns (0 allocations: 0 bytes)
3.197 ns (0 allocations: 0 bytes)
```

It is easy to check whether a mode is present in the iterator. This can also be checked in `O(1)` time.

```julia
julia> @btime el in m setup=(m=LM(0:rand(1:1000000)); el=(rand(1:100),rand(1:100)))
2.676 ns (0 allocations: 0 bytes)
7.307 ns (0 allocations: 0 bytes)
```

The index at which a mode is present can be checked using `modeindex`. For example
```julia
julia> itr = ML(0,2,-1,2);
julia> itr = ML(0:2,-1:2);

julia> collect(itr)
8-element Array{Tuple{Int64,Int64},1}:
Expand All @@ -162,17 +134,17 @@ julia> modeindex(itr,(2,2))
This is also evaluated in `O(1)` time.

```julia
julia> itr = ML(0,20000);
julia> itr = ML(0:20000);

julia> @btime modeindex($itr,el) setup=(el=(rand(1000:20000),rand(1:1000)))
17.488 ns (0 allocations: 0 bytes)
6.386 ns (0 allocations: 0 bytes)

julia> itr = LM(0,20000);
julia> itr = LM(0:20000);

julia> @btime modeindex($itr,el) setup=(el=(rand(1000:20000),rand(1:1000)))
18.084 ns (0 allocations: 0 bytes)
9.595 ns (0 allocations: 0 bytes)

julia> itr = L₂L₁Δ(1:100,100);
julia> itr = L2L1Triangle(1:100, 100);

julia> @btime modeindex($itr,el) setup=(el=(rand(1:100),rand(1:100)))
15.411 ns (0 allocations: 0 bytes)
Expand All @@ -181,15 +153,15 @@ julia> @btime modeindex($itr,el) setup=(el=(rand(1:100),rand(1:100)))
Indexing is not supported at the moment, but the last element can be obtained easily.

```julia
julia> itr = ML(0,2,-1,2);
julia> itr = ML(0:2,-1:2);

julia> collect(itr)[end]
(2, 2)

julia> last(itr)
(2, 2)

julia> itr = ML(0,20000);
julia> itr = ML(0:20000);

julia> @btime last(m) setup=(m=ML(0:rand(1:20000)))
3.734 ns (0 allocations: 0 bytes)
Expand Down
5 changes: 5 additions & 0 deletions docs/Project.toml
@@ -0,0 +1,5 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

[compat]
Documenter = "0.25"
23 changes: 23 additions & 0 deletions docs/make.jl
@@ -0,0 +1,23 @@
using Documenter
using SphericalHarmonicModes

DocMeta.setdocmeta!(SphericalHarmonicModes, :DocTestSetup, :(using SphericalHarmonicModes); recursive=true)

makedocs(;
modules=[SphericalHarmonicModes],
authors="Jishnu Bhattacharya",
repo="https://github.com/jishnub/SphericalHarmonicModes.jl/blob/{commit}{path}#L{line}",
sitename="SphericalHarmonicModes.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
canonical="https://jishnub.github.io/SphericalHarmonicModes.jl",
assets=String[],
),
pages=[
"Reference" => "index.md",
],
)

deploydocs(;
repo="github.com/jishnub/SphericalHarmonicModes.jl",
)
9 changes: 9 additions & 0 deletions docs/src/index.md
@@ -0,0 +1,9 @@
```@meta
CurrentModule = SphericalHarmonicModes
```

# SphericalHarmonicModes.jl

```@autodocs
Modules = [SphericalHarmonicModes]
```

0 comments on commit bb7c79e

Please sign in to comment.