Skip to content

Commit 7a4e2a0

Browse files
authored
Add files via upload
1 parent 249a40f commit 7a4e2a0

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

gradient.jl

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# This file calculates the surface gradient of a scalar field.
2+
3+
function gradient!(U::Matrix{T}, ∇θU::Matrix{T}, ∇φU::Matrix{T}) where T
4+
@assert size(U) == size(∇θU) == size(∇φU)
5+
N, M = size(U)
6+
7+
# The first column is easy.
8+
@inbounds @simd for= 1:N-1
9+
∇θU[ℓ, 1] = -sqrt(T(ℓ*(ℓ+1)))*U[ℓ+1, 1]
10+
∇φU[ℓ, 1] = 0
11+
end
12+
∇θU[N, 1] = 0
13+
∇φU[N, 1] = 0
14+
15+
# Next, we differentiate with respect to φ, which preserves the order. It swaps sines and cosines in longitude, though.
16+
@inbounds for m = 1:M÷2
17+
@simd for= 1:N+1-m
18+
∇φU[ℓ, 2m] = -m*U[ℓ, 2m+1]
19+
∇φU[ℓ, 2m+1] = m*U[ℓ, 2m]
20+
end
21+
end
22+
23+
# Then, we differentiate with respect to θ, which preserves the order but divides by sin(θ).
24+
25+
@inbounds for m = 1:M÷2
26+
= 1
27+
bℓ = -(ℓ+m+1)*sqrt(T(ℓ*(ℓ+2m))/T((2+2m-1)*(2+2m+1)))
28+
∇θU[ℓ, 2m] = bℓ*U[ℓ+1, 2m]
29+
∇θU[ℓ, 2m+1] = bℓ*U[ℓ+1, 2m+1]
30+
@simd for= 2:N-m
31+
aℓ = (ℓ+m-2)*sqrt(T((ℓ-1)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
32+
bℓ = -(ℓ+m+1)*sqrt(T(ℓ*(ℓ+2m))/T((2+2m-1)*(2+2m+1)))
33+
∇θU[ℓ, 2m] = aℓ*U[ℓ-1, 2m] + bℓ*U[ℓ+1, 2m]
34+
∇θU[ℓ, 2m+1] = aℓ*U[ℓ-1, 2m+1] + bℓ*U[ℓ+1, 2m+1]
35+
end
36+
= N-m+1
37+
aℓ = (ℓ+m-2)*sqrt(T((ℓ-1)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
38+
∇θU[ℓ, 2m] = aℓ*U[ℓ-1, 2m]
39+
∇θU[ℓ, 2m+1] = aℓ*U[ℓ-1, 2m+1]
40+
end
41+
42+
# Finally, we divide by sin(θ), which can be done by decrementing the order P_ℓ^m ↘ P_ℓ^{m-1}.
43+
@inbounds for m = 1:M÷2
44+
= N+1-m
45+
aℓ = sqrt(T((ℓ+2m-2)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
46+
∇θU[ℓ, 2m] = ∇θU[ℓ, 2m]/aℓ
47+
∇θU[ℓ, 2m+1] = ∇θU[ℓ, 2m+1]/aℓ
48+
∇φU[ℓ, 2m] = ∇φU[ℓ, 2m]/aℓ
49+
∇φU[ℓ, 2m+1] = ∇φU[ℓ, 2m+1]/aℓ
50+
= N+1-m-1
51+
if> 0
52+
aℓ = sqrt(T((ℓ+2m-2)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
53+
∇θU[ℓ, 2m] = ∇θU[ℓ, 2m]/aℓ
54+
∇θU[ℓ, 2m+1] = ∇θU[ℓ, 2m+1]/aℓ
55+
∇φU[ℓ, 2m] = ∇φU[ℓ, 2m]/aℓ
56+
∇φU[ℓ, 2m+1] = ∇φU[ℓ, 2m+1]/aℓ
57+
end
58+
@simd for= N+1-m-2:-1:1
59+
aℓ = sqrt(T((ℓ+2m-2)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
60+
bℓ = -sqrt(T(ℓ*(ℓ+1))/T((2+2m-1)*(2+2m+1)))
61+
∇θU[ℓ, 2m] = (∇θU[ℓ, 2m] - bℓ*∇θU[ℓ+2, 2m])/aℓ
62+
∇θU[ℓ, 2m+1] = (∇θU[ℓ, 2m+1] - bℓ*∇θU[ℓ+2, 2m+1])/aℓ
63+
∇φU[ℓ, 2m] = (∇φU[ℓ, 2m] - bℓ*∇φU[ℓ+2, 2m])/aℓ
64+
∇φU[ℓ, 2m+1] = (∇φU[ℓ, 2m+1] - bℓ*∇φU[ℓ+2, 2m+1])/aℓ
65+
end
66+
end
67+
68+
∇θU
69+
end
70+
71+
function curl!(U::Matrix, U1::Matrix, U2::Matrix)
72+
gradient!(U, U2, U1)
73+
N, M = size(U)
74+
@inbounds for j = 1:M
75+
for i = 1:N
76+
U1[i,j] = -U1[i,j]
77+
end
78+
end
79+
U1
80+
end
81+
82+
83+
function partial_gradient!(U::Matrix{T}, ∇θU::Matrix{T}, ∇φU::Matrix{T}) where T
84+
@assert size(U) == size(∇θU) == size(∇φU)
85+
N, M = size(U)
86+
87+
# The first column is easy.
88+
@inbounds @simd for= 1:N-1
89+
∇θU[ℓ, 1] = -sqrt(T(ℓ*(ℓ+1)))*U[ℓ+1, 1]
90+
∇φU[ℓ, 1] = 0
91+
end
92+
∇θU[N, 1] = 0
93+
∇φU[N, 1] = 0
94+
95+
# Next, we differentiate with respect to φ, which preserves the order. It swaps sines and cosines in longitude, though.
96+
@inbounds for m = 1:M÷2
97+
@simd for= 1:N+1-m
98+
∇φU[ℓ, 2m] = -m*U[ℓ, 2m+1]
99+
∇φU[ℓ, 2m+1] = m*U[ℓ, 2m]
100+
end
101+
end
102+
103+
# Then, we differentiate with respect to θ, which preserves the order but divides by sin(θ).
104+
105+
@inbounds for m = 1:M÷2
106+
= 1
107+
bℓ = -(ℓ+m+1)*sqrt(T(ℓ*(ℓ+2m))/T((2+2m-1)*(2+2m+1)))
108+
∇θU[ℓ, 2m] = bℓ*U[ℓ+1, 2m]
109+
∇θU[ℓ, 2m+1] = bℓ*U[ℓ+1, 2m+1]
110+
@simd for= 2:N-m
111+
aℓ = (ℓ+m-2)*sqrt(T((ℓ-1)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
112+
bℓ = -(ℓ+m+1)*sqrt(T(ℓ*(ℓ+2m))/T((2+2m-1)*(2+2m+1)))
113+
∇θU[ℓ, 2m] = aℓ*U[ℓ-1, 2m] + bℓ*U[ℓ+1, 2m]
114+
∇θU[ℓ, 2m+1] = aℓ*U[ℓ-1, 2m+1] + bℓ*U[ℓ+1, 2m+1]
115+
end
116+
= N-m+1
117+
aℓ = (ℓ+m-2)*sqrt(T((ℓ-1)*(ℓ+2m-1))/T((2+2m-3)*(2+2m-1)))
118+
∇θU[ℓ, 2m] = aℓ*U[ℓ-1, 2m]
119+
∇θU[ℓ, 2m+1] = aℓ*U[ℓ-1, 2m+1]
120+
end
121+
122+
∇θU
123+
end

0 commit comments

Comments
 (0)