Skip to content

Commit 4889931

Browse files
Add spin-weighted spherical harmonics (#103)
* add spin-weighted spherical harmonics * update freebsd image * add horner and clenshaw routines don't export
1 parent 84be69f commit 4889931

8 files changed

+249
-19
lines changed

.cirrus.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
freebsd_instance:
2-
image: freebsd-12-0-release-amd64
2+
image: freebsd-12-1-release-amd64
33
task:
44
name: FreeBSD
55
env:

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "FastTransforms"
22
uuid = "057dd010-8810-581a-b7be-e3fc3b93f78c"
3-
version = "0.8.2"
3+
version = "0.9.0"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
@@ -22,7 +22,7 @@ BinaryProvider = "0.5.8"
2222
DSP = "0.6"
2323
FFTW = "1"
2424
FastGaussQuadrature = "0.4"
25-
FastTransforms_jll = "0.2.13"
25+
FastTransforms_jll = "0.3.0"
2626
Reexport = "0.2"
2727
SpecialFunctions = "0.8, 0.9, 0.10"
2828
ToeplitzMatrices = "0.6"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ julia> using FastTransforms, LinearAlgebra
1919

2020
## Fast orthogonal polynomial transforms
2121

22-
The 26 orthogonal polynomial transforms are listed in `FastTransforms.kind2string.(0:25)`. Univariate transforms may be planned with the standard normalization or with orthonormalization. For multivariate transforms, the standard normalization may be too severe for floating-point computations, so it is omitted. Here are two examples:
22+
The 29 orthogonal polynomial transforms are listed in `FastTransforms.kind2string.(0:28)`. Univariate transforms may be planned with the standard normalization or with orthonormalization. For multivariate transforms, the standard normalization may be too severe for floating-point computations, so it is omitted. Here are two examples:
2323

2424
### The Chebyshev--Legendre transform
2525

examples/spinweighted.jl

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#############
2+
# This example plays with analysis of:
3+
#
4+
# f(r) = e^{i k⋅r},
5+
#
6+
# for some k ∈ ℝ³ and where r ∈ 𝕊², using spin-0 spherical harmonics.
7+
#
8+
# It applies ð, the spin-raising operator,
9+
# both on the spin-0 coefficients as well as the original function,
10+
# followed by a spin-1 analysis to compare coefficients.
11+
#
12+
# See also sphere.jl
13+
# For the storage pattern of the arrays, please consult the documentation.
14+
#############
15+
16+
using FastTransforms, LinearAlgebra
17+
18+
# The colatitudinal grid (mod π):
19+
N = 10
20+
θ = (0.5:N-0.5)/N
21+
22+
# The longitudinal grid (mod π):
23+
M = 2*N-1
24+
φ = (0:M-1)*2/M
25+
26+
k = [2/7, 3/7, 6/7]
27+
r = (θ,φ) -> [sinpi(θ)*cospi(φ), sinpi(θ)*sinpi(φ), cospi(θ)]
28+
29+
# On the tensor product grid, our function samples are:
30+
31+
F = [exp(im*(kr(θ,φ))) for θ in θ, φ in φ]
32+
33+
P = plan_spinsph2fourier(F, 0)
34+
PA = plan_spinsph_analysis(F, 0)
35+
36+
# Its spin-0 spherical harmonic coefficients are:
37+
38+
U⁰ = P\(PA*F)
39+
40+
norm(U⁰) sqrt(4π)
41+
42+
# Spin can be incremented by applying ð, either on the spin-0 coefficients:
43+
44+
U¹c = zero(U⁰)
45+
for n in 1:N-1
46+
U¹c[n, 1] = sqrt(n*(n+1))*U⁰[n+1, 1]
47+
end
48+
for m in 1:M÷2
49+
for n in 0:N-1
50+
U¹c[n+1, 2m] = -sqrt((n+m)*(n+m+1))*U⁰[n+1, 2m]
51+
U¹c[n+1, 2m+1] = sqrt((n+m)*(n+m+1))*U⁰[n+1, 2m+1]
52+
end
53+
end
54+
55+
# or on the original function through analysis with spin-1 spherical harmonics:
56+
57+
F = [-(k[1]*(im*cospi(θ)*cospi(φ) + sinpi(φ)) + k[2]*(im*cospi(θ)*sinpi(φ)-cospi(φ)) - im*k[3]*sinpi(θ))*exp(im*(kr(θ,φ))) for θ in θ, φ in φ]
58+
59+
P = plan_spinsph2fourier(F, 1)
60+
PA = plan_spinsph_analysis(F, 1)
61+
62+
U¹s = P\(PA*F)
63+
64+
norm(U¹c) norm(U¹s) sqrt(8π/3*(kk))

src/FastTransforms.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ export plan_leg2cheb, plan_cheb2leg, plan_ultra2ultra, plan_jac2jac,
4444
plan_sphv2fourier, plan_sphv_synthesis, plan_sphv_analysis,
4545
plan_disk2cxf, plan_disk_synthesis, plan_disk_analysis,
4646
plan_tri2cheb, plan_tri_synthesis, plan_tri_analysis,
47-
plan_tet2cheb, plan_tet_synthesis, plan_tet_analysis
47+
plan_tet2cheb, plan_tet_synthesis, plan_tet_analysis,
48+
plan_spinsph2fourier, plan_spinsph_synthesis, plan_spinsph_analysis
4849

4950
include("libfasttransforms.jl")
5051

@@ -87,7 +88,8 @@ export sphones, sphzeros, sphrand, sphrandn, sphevaluate,
8788
sphvones, sphvzeros, sphvrand, sphvrandn,
8889
diskones, diskzeros, diskrand, diskrandn,
8990
triones, trizeros, trirand, trirandn, trievaluate,
90-
tetones, tetzeros, tetrand, tetrandn
91+
tetones, tetzeros, tetrand, tetrandn,
92+
spinsphones, spinsphzeros, spinsphrand, spinsphrandn
9193

9294
lgamma(x) = logabsgamma(x)[1]
9395

src/libfasttransforms.jl

Lines changed: 104 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,38 @@ end
4343

4444
set_num_threads(n::Integer) = ccall((:ft_set_num_threads, libfasttransforms), Cvoid, (Cint, ), n)
4545

46+
function horner!(c::Vector{Float64}, x::Vector{Float64}, f::Vector{Float64})
47+
@assert length(x) == length(f)
48+
ccall((:ft_horner, libfasttransforms), Cvoid, (Cint, Ptr{Float64}, Cint, Cint, Ptr{Float64}, Ptr{Float64}), length(c), c, 1, length(x), x, f)
49+
end
50+
51+
function horner!(c::Vector{Float32}, x::Vector{Float32}, f::Vector{Float32})
52+
@assert length(x) == length(f)
53+
ccall((:ft_hornerf, libfasttransforms), Cvoid, (Cint, Ptr{Float32}, Cint, Cint, Ptr{Float32}, Ptr{Float32}), length(c), c, 1, length(x), x, f)
54+
end
55+
56+
function clenshaw!(c::Vector{Float64}, x::Vector{Float64}, f::Vector{Float64})
57+
@assert length(x) == length(f)
58+
ccall((:ft_clenshaw, libfasttransforms), Cvoid, (Cint, Ptr{Float64}, Cint, Cint, Ptr{Float64}, Ptr{Float64}), length(c), c, 1, length(x), x, f)
59+
end
60+
61+
function clenshaw!(c::Vector{Float32}, x::Vector{Float32}, f::Vector{Float32})
62+
@assert length(x) == length(f)
63+
ccall((:ft_clenshawf, libfasttransforms), Cvoid, (Cint, Ptr{Float32}, Cint, Cint, Ptr{Float32}, Ptr{Float32}), length(c), c, 1, length(x), x, f)
64+
end
65+
66+
function clenshaw!(c::Vector{Float64}, A::Vector{Float64}, B::Vector{Float64}, C::Vector{Float64}, x::Vector{Float64}, phi0::Vector{Float64}, f::Vector{Float64})
67+
@assert length(c) == length(A) == length(B) == length(C)-1
68+
@assert length(x) == length(phi0) == length(f)
69+
ccall((:ft_orthogonal_polynomial_clenshaw, libfasttransforms), Cvoid, (Cint, Ptr{Float64}, Cint, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}, Cint, Ptr{Float64}, Ptr{Float64}, Ptr{Float64}), length(c), c, 1, A, B, C, length(x), x, phi0, f)
70+
end
71+
72+
function clenshaw!(c::Vector{Float32}, A::Vector{Float32}, B::Vector{Float32}, C::Vector{Float32}, x::Vector{Float32}, phi0::Vector{Float32}, f::Vector{Float32})
73+
@assert length(c) == length(A) == length(B) == length(C)-1
74+
@assert length(x) == length(phi0) == length(f)
75+
ccall((:ft_orthogonal_polynomial_clenshawf, libfasttransforms), Cvoid, (Cint, Ptr{Float32}, Cint, Ptr{Float32}, Ptr{Float32}, Ptr{Float32}, Cint, Ptr{Float32}, Ptr{Float32}, Ptr{Float32}), length(c), c, 1, A, B, C, length(x), x, phi0, f)
76+
end
77+
4678
const LEG2CHEB = 0
4779
const CHEB2LEG = 1
4880
const ULTRA2ULTRA = 2
@@ -59,16 +91,20 @@ const SPHEREV = 12
5991
const DISK = 13
6092
const TRIANGLE = 14
6193
const TETRAHEDRON = 15
62-
const SPHERESYNTHESIS = 16
63-
const SPHEREANALYSIS = 17
64-
const SPHEREVSYNTHESIS = 18
65-
const SPHEREVANALYSIS = 19
66-
const DISKSYNTHESIS = 20
67-
const DISKANALYSIS = 21
68-
const TRIANGLESYNTHESIS = 22
69-
const TRIANGLEANALYSIS = 23
70-
const TETRAHEDRONSYNTHESIS = 24
71-
const TETRAHEDRONANALYSIS = 25
94+
const SPINSPHERE = 16
95+
const SPHERESYNTHESIS = 17
96+
const SPHEREANALYSIS = 18
97+
const SPHEREVSYNTHESIS = 19
98+
const SPHEREVANALYSIS = 20
99+
const DISKSYNTHESIS = 21
100+
const DISKANALYSIS = 22
101+
const TRIANGLESYNTHESIS = 23
102+
const TRIANGLEANALYSIS = 24
103+
const TETRAHEDRONSYNTHESIS = 25
104+
const TETRAHEDRONANALYSIS = 26
105+
const SPINSPHERESYNTHESIS = 27
106+
const SPINSPHEREANALYSIS = 28
107+
72108

73109
let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
74110
CHEB2LEG => "Chebyshev--Legendre",
@@ -86,6 +122,7 @@ let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
86122
DISK => "Zernike--Chebyshev×Fourier",
87123
TRIANGLE => "Proriol--Chebyshev²",
88124
TETRAHEDRON => "Proriol--Chebyshev³",
125+
SPINSPHERE => "Spin-weighted spherical harmonic--Fourier",
89126
SPHERESYNTHESIS => "FFTW Fourier synthesis on the sphere",
90127
SPHEREANALYSIS => "FFTW Fourier analysis on the sphere",
91128
SPHEREVSYNTHESIS => "FFTW Fourier synthesis on the sphere (vector field)",
@@ -95,7 +132,9 @@ let k2s = Dict(LEG2CHEB => "Legendre--Chebyshev",
95132
TRIANGLESYNTHESIS => "FFTW Chebyshev synthesis on the triangle",
96133
TRIANGLEANALYSIS => "FFTW Chebyshev analysis on the triangle",
97134
TETRAHEDRONSYNTHESIS => "FFTW Chebyshev synthesis on the tetrahedron",
98-
TETRAHEDRONANALYSIS => "FFTW Chebyshev analysis on the tetrahedron")
135+
TETRAHEDRONANALYSIS => "FFTW Chebyshev analysis on the tetrahedron",
136+
SPINSPHERESYNTHESIS => "FFTW Fourier synthesis on the sphere (spin-weighted)",
137+
SPINSPHEREANALYSIS => "FFTW Fourier analysis on the sphere (spin-weighted)")
99138
global kind2string
100139
kind2string(k::Integer) = k2s[Int(k)]
101140
end
@@ -132,6 +171,7 @@ show(io::IO, p::FTPlan{T, 2, SPHEREV}) where T = print(io, "FastTransforms ", ki
132171
show(io::IO, p::FTPlan{T, 2, DISK}) where T = print(io, "FastTransforms ", kind2string(DISK), " plan for $(p.n)×$(4p.n-3)-element array of ", T)
133172
show(io::IO, p::FTPlan{T, 2, TRIANGLE}) where T = print(io, "FastTransforms ", kind2string(TRIANGLE), " plan for $(p.n)×$(p.n)-element array of ", T)
134173
show(io::IO, p::FTPlan{T, 3, TETRAHEDRON}) where T = print(io, "FastTransforms ", kind2string(TETRAHEDRON), " plan for $(p.n)×$(p.n)×$(p.n)-element array of ", T)
174+
show(io::IO, p::FTPlan{T, 2, SPINSPHERE}) where T = print(io, "FastTransforms ", kind2string(SPINSPHERE), " plan for $(p.n)×$(2p.n-1)-element array of ", T)
135175
show(io::IO, p::FTPlan{T, 2, K}) where {T, K} = print(io, "FastTransforms plan for ", kind2string(K), " for $(p.n)×$(p.m)-element array of ", T)
136176
show(io::IO, p::FTPlan{T, 3, K}) where {T, K} = print(io, "FastTransforms plan for ", kind2string(K), " for $(p.n)×$(p.l)×$(p.m)-element array of ", T)
137177

@@ -141,7 +181,7 @@ function checksize(p::FTPlan{T}, x::Array{T}) where T
141181
end
142182
end
143183

144-
for K in (SPHERE, SPHEREV, DISK)
184+
for K in (SPHERE, SPHEREV, DISK, SPINSPHERE)
145185
@eval function checksize(p::FTPlan{T, 2, $K}, x::Matrix{T}) where T
146186
if p.n != size(x, 1)
147187
throw(DimensionMismatch("FTPlan has dimensions $(p.n) × $(p.n), x has leading dimension $(size(x, 1))"))
@@ -160,6 +200,7 @@ destroy_plan(p::FTPlan{Float64, 1}) = ccall((:ft_destroy_tb_eigen_FMM, libfasttr
160200
destroy_plan(p::FTPlan{BigFloat, 1}) = ccall((:ft_mpfr_destroy_plan, libfasttransforms), Cvoid, (Ptr{mpfr_t}, Cint), p, p.n)
161201
destroy_plan(p::FTPlan{Float64, 2}) = ccall((:ft_destroy_harmonic_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
162202
destroy_plan(p::FTPlan{Float64, 3}) = ccall((:ft_destroy_tetrahedral_harmonic_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
203+
destroy_plan(p::FTPlan{Complex{Float64}, 2, SPINSPHERE}) = ccall((:ft_destroy_spin_harmonic_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
163204
destroy_plan(p::FTPlan{Float64, 2, SPHERESYNTHESIS}) = ccall((:ft_destroy_sphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
164205
destroy_plan(p::FTPlan{Float64, 2, SPHEREANALYSIS}) = ccall((:ft_destroy_sphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
165206
destroy_plan(p::FTPlan{Float64, 2, SPHEREVSYNTHESIS}) = ccall((:ft_destroy_sphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
@@ -170,6 +211,8 @@ destroy_plan(p::FTPlan{Float64, 2, TRIANGLESYNTHESIS}) = ccall((:ft_destroy_tria
170211
destroy_plan(p::FTPlan{Float64, 2, TRIANGLEANALYSIS}) = ccall((:ft_destroy_triangle_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
171212
destroy_plan(p::FTPlan{Float64, 3, TETRAHEDRONSYNTHESIS}) = ccall((:ft_destroy_tetrahedron_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
172213
destroy_plan(p::FTPlan{Float64, 3, TETRAHEDRONANALYSIS}) = ccall((:ft_destroy_tetrahedron_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
214+
destroy_plan(p::FTPlan{Complex{Float64}, 2, SPINSPHERESYNTHESIS}) = ccall((:ft_destroy_spinsphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
215+
destroy_plan(p::FTPlan{Complex{Float64}, 2, SPINSPHEREANALYSIS}) = ccall((:ft_destroy_spinsphere_fftw_plan, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, ), p)
173216

174217
struct AdjointFTPlan{T, S}
175218
parent::S
@@ -233,6 +276,9 @@ for (f, plan_f) in ((:fourier2sph, :plan_sph2fourier), (:fourier2sphv, :plan_sph
233276
end
234277
end
235278

279+
plan_spinsph2fourier(x::AbstractArray{T}, y...; z...) where T = plan_spinsph2fourier(T, size(x, 1), y...; z...)
280+
spinsph2fourier(x::AbstractArray, y...; z...) = plan_spinsph2fourier(x, y...; z...)*x
281+
fourier2spinsph(x::AbstractArray, y...; z...) = plan_spinsph2fourier(x, y...; z...)\x
236282

237283
function plan_leg2cheb(::Type{Float32}, n::Integer; normleg::Bool=false, normcheb::Bool=false)
238284
plan = ccall((:ft_plan_legendre_to_chebyshevf, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Cint, Cint), normleg, normcheb, n)
@@ -427,6 +473,11 @@ function plan_tet2cheb(::Type{Float64}, n::Integer, α, β, γ, δ)
427473
return FTPlan{Float64, 3, TETRAHEDRON}(plan, n)
428474
end
429475

476+
function plan_spinsph2fourier(::Type{Complex{Float64}}, n::Integer, s::Integer)
477+
plan = ccall((:ft_plan_spinsph2fourier, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Cint), n, s)
478+
return FTPlan{Complex{Float64}, 2, SPINSPHERE}(plan, n)
479+
end
480+
430481
for (fJ, fC, fE, K) in ((:plan_sph_synthesis, :ft_plan_sph_synthesis, :ft_execute_sph_synthesis, SPHERESYNTHESIS),
431482
(:plan_sph_analysis, :ft_plan_sph_analysis, :ft_execute_sph_analysis, SPHEREANALYSIS),
432483
(:plan_sphv_synthesis, :ft_plan_sphv_synthesis, :ft_execute_sphv_synthesis, SPHEREVSYNTHESIS),
@@ -484,6 +535,35 @@ function lmul!(p::FTPlan{Float64, 3, TETRAHEDRONANALYSIS}, x::Array{Float64, 3})
484535
return x
485536
end
486537

538+
plan_spinsph_synthesis(x::Matrix{T}, s::Integer) where T = plan_spinsph_synthesis(T, size(x, 1), size(x, 2), s)
539+
540+
function plan_spinsph_synthesis(::Type{Complex{Float64}}, n::Integer, m::Integer, s::Integer)
541+
plan = ccall((:ft_plan_spinsph_synthesis, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Cint, Cint), n, m, s)
542+
return FTPlan{Complex{Float64}, 2, SPINSPHERESYNTHESIS}(plan, n, m)
543+
end
544+
545+
function lmul!(p::FTPlan{Complex{Float64}, 2, SPINSPHERESYNTHESIS}, x::Matrix{Complex{Float64}})
546+
if p.n != size(x, 1) || p.m != size(x, 2)
547+
throw(DimensionMismatch("FTPlan has dimensions $(p.n) × $(p.m), x has dimensions $(size(x, 1)) × $(size(x, 2))"))
548+
end
549+
ccall((:ft_execute_spinsph_synthesis, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint), p, x, size(x, 1), size(x, 2))
550+
return x
551+
end
552+
553+
plan_spinsph_analysis(x::Matrix{T}, s::Integer) where T = plan_spinsph_analysis(T, size(x, 1), size(x, 2), s)
554+
555+
function plan_spinsph_analysis(::Type{Complex{Float64}}, n::Integer, m::Integer, s::Integer)
556+
plan = ccall((:ft_plan_spinsph_analysis, libfasttransforms), Ptr{ft_plan_struct}, (Cint, Cint, Cint), n, m, s)
557+
return FTPlan{Complex{Float64}, 2, SPINSPHEREANALYSIS}(plan, n, m)
558+
end
559+
560+
function lmul!(p::FTPlan{Complex{Float64}, 2, SPINSPHEREANALYSIS}, x::Matrix{Complex{Float64}})
561+
if p.n != size(x, 1) || p.m != size(x, 2)
562+
throw(DimensionMismatch("FTPlan has dimensions $(p.n) × $(p.m), x has dimensions $(size(x, 1)) × $(size(x, 2))"))
563+
end
564+
ccall((:ft_execute_spinsph_analysis, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Float64}, Cint, Cint), p, x, size(x, 1), size(x, 2))
565+
return x
566+
end
487567

488568
*(p::FTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
489569
*(p::AdjointFTPlan{T}, x::Array{T}) where T = lmul!(p, deepcopy(x))
@@ -634,6 +714,18 @@ function ldiv!(p::FTPlan{Float64, 3, TETRAHEDRON}, x::Array{Float64, 3})
634714
return x
635715
end
636716

717+
function lmul!(p::FTPlan{Complex{Float64}, 2, SPINSPHERE}, x::Matrix{Complex{Float64}})
718+
checksize(p, x)
719+
ccall((:ft_execute_spinsph2fourier, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Complex{Float64}}, Cint, Cint), p, x, size(x, 1), size(x, 2))
720+
return x
721+
end
722+
723+
function ldiv!(p::FTPlan{Complex{Float64}, 2, SPINSPHERE}, x::Matrix{Complex{Float64}})
724+
checksize(p, x)
725+
ccall((:ft_execute_fourier2spinsph, libfasttransforms), Cvoid, (Ptr{ft_plan_struct}, Ptr{Complex{Float64}}, Cint, Cint), p, x, size(x, 1), size(x, 2))
726+
return x
727+
end
728+
637729
*(p::FTPlan{T}, x::Array{Complex{T}}) where T = lmul!(p, deepcopy(x))
638730
*(p::AdjointFTPlan{T}, x::Array{Complex{T}}) where T = lmul!(p, deepcopy(x))
639731
*(p::TransposeFTPlan{T}, x::Array{Complex{T}}) where T = lmul!(p, deepcopy(x))

src/specialfunctions.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,3 +605,50 @@ function tetones(::Type{T}, l::Int, m::Int, n::Int) where T
605605
end
606606

607607
tetzeros(::Type{T}, l::Int, m::Int, n::Int) where T = zeros(T, l, m, n)
608+
609+
function spinsphrand(::Type{T}, m::Int, n::Int, s::Int) where T
610+
A = zeros(T, m, n)
611+
as = abs(s)
612+
for i = 1:m-as
613+
A[i,1] = rand(T)
614+
end
615+
for j = 1:n÷2
616+
for i = 1:m-max(j, as)
617+
A[i,2j] = rand(T)
618+
A[i,2j+1] = rand(T)
619+
end
620+
end
621+
A
622+
end
623+
624+
function spinsphrandn(::Type{T}, m::Int, n::Int, s::Int) where T
625+
A = zeros(T, m, n)
626+
as = abs(s)
627+
for i = 1:m-as
628+
A[i,1] = randn(T)
629+
end
630+
for j = 1:n÷2
631+
for i = 1:m-max(j, as)
632+
A[i,2j] = randn(T)
633+
A[i,2j+1] = randn(T)
634+
end
635+
end
636+
A
637+
end
638+
639+
function spinsphones(::Type{T}, m::Int, n::Int, s::Int) where T
640+
A = zeros(T, m, n)
641+
as = abs(s)
642+
for i = 1:m-as
643+
A[i,1] = one(T)
644+
end
645+
for j = 1:n÷2
646+
for i = 1:m-max(j, as)
647+
A[i,2j] = one(T)
648+
A[i,2j+1] = one(T)
649+
end
650+
end
651+
A
652+
end
653+
654+
spinsphzeros(::Type{T}, m::Int, n::Int) where T = zeros(T, m, n)

0 commit comments

Comments
 (0)