It is still not clear to me, perhaps a simple example of this sphere use case?
I don’t promise this is right, but it looks like the simplest things you can do are these:
julia> torus = CyclicArray(
[1 2 3; 4 5 6; 7 8 9],
hcat(
reshape([1 1 2 0; 1 1 1 0],1,1,2,4),
reshape([1 2 2 0; 1 2 1 0],1,1,2,4)
))
3×3 CyclicArray{Int64, 2}:
1 2 3
4 5 6
7 8 9
julia> [torus[i,j] for i in -2:6, j in -2:6]
9×9 Matrix{Int64}:
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
julia> klein = CyclicArray(
[1 2 3; 4 5 6; 7 8 9],
hcat(
reshape([1 1 2 0; 1 1 1 0], 1,1,2,4),
reshape([1 2 2 1; 1 2 1 1], 1,1,2,4)
))
3×3 CyclicArray{Int64, 2}:
1 2 3
4 5 6
7 8 9
julia> [klein[i,j] for i in -2:6, j in -2:6]
9×9 Matrix{Int64}:
3 2 1 3 2 1 3 2 1
6 5 4 6 5 4 6 5 4
9 8 7 9 8 7 9 8 7
1 2 3 1 2 3 1 2 3
4 5 6 4 5 6 4 5 6
7 8 9 7 8 9 7 8 9
3 2 1 3 2 1 3 2 1
6 5 4 6 5 4 6 5 4
9 8 7 9 8 7 9 8 7
The idea is similar to the xgcm python package:
Just a note, CyclicArrays
define a container with an abstract type. Which may lead to some performance issues. A way around this would be mimic CircularArrays
and define an extra type parameter struct CyclicArray{T,N,A}
…
This may not be important for some application cases, but defining Base.sum(ca::CyclicArray) = Base.sum(ca.data)
should have some inference trouble in @code_warntype
.
Here is a quick example to play with:
x0=permutedims(reshape((1:1:96)',(4,4,6,1)),(3,4,2,1))
x1=CyclicArray(x0,“cubed”)
This example includes 6 faces interconnected in this order:
5
1 2 3 4. # → x direction
6
julia> x1[1,1,1,0]==x1[4,1,1,4]
true
julia> x1[3,1,1,0]==x1[2,1,1,4]
true
The package is still under development. The named grid topology is still not documented but it is active.
for searching purposes, there is now a registered Package that does this:
https://github.com/Vexatos/CircularArrays.jl
Note that with this type of approach (as in CircularArrays.jl and CyclicArrays.jl), you pay a computational price for every getindex
operations (for a mod
in CircularArrays and a much more expensive calculation in CyclicArrays).
In many circumstances, you don’t need to access the array at arbitrary indices, but only at indices in the interior and just outside the boundary, and in such cases you can get both greater efficiency and greater flexibility (in topology etcetera) by using ghost cells.
If you only need one-dimensional arrays, you can use CircularList.jl. It looks to have a really nice interface, where you can have a head pointing to a certain point in the list. (And the developer is great!)