-
Notifications
You must be signed in to change notification settings - Fork 2
/
da.jl
83 lines (66 loc) · 1.92 KB
/
da.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
module DA
export etkf, ensrf, gaspari_cohn
using Statistics
using LinearAlgebra
using Distributions
function gaspari_cohn(r)
if 0 <= r < 1
G = 1 - 5/3*r^2 + 5/8*r^3 + 1/2*r^4 - 1/4*r^5
elseif 1 <= r < 2
G = 4 - 5*r + 5/3*r^2 + 5/8*r^3 - 1/2*r^4 + 1/12*r^5 - 2/(3*r)
elseif r >= 2
G = 0
end
return G
end
function gaspari_cohn_localization(c, D; cyclic=false)
localization = zeros(D, D)
for i=1:D
for j=1:i
if cyclic
r = min(mod(i - j, 0:D), mod(j - i, 0:D))/c
else
r = abs(i - j)
end
localization[i, j] = DA.gaspari_cohn(r)
end
end
return Symmetric(localization, :L)
end
"""
Ensemble transform Kalman filter (ETKF)
"""
function etkf(; E::AbstractMatrix{float_type}, R::Symmetric{float_type},
R_inv::Symmetric{float_type},
inflation::float_type=1.0, H::AbstractMatrix,
y::AbstractVector{float_type}) where {float_type<:AbstractFloat}
D, m = size(E)
x_m = mean(E, dims=2)
X = (E .- x_m)/sqrt(m - 1)
X = sqrt(inflation)*X
y_m = H*x_m
Y = (H*E .- y_m)/sqrt(m - 1)
Ω = inv(Symmetric(I + Y'*R_inv*Y))
w = Ω*Y'*R_inv*(y - y_m)
E = x_m .+ X*(w .+ sqrt(m - 1)*sqrt(Ω))
return E
end
function ensrf(; E::AbstractMatrix{float_type}, R::Symmetric{float_type},
R_inv::Symmetric{float_type},
inflation::float_type=1.0, H::AbstractMatrix,
y::AbstractVector{float_type},
localization=nothing) where {float_type<:AbstractFloat}
D, m = size(E)
x_m = mean(E, dims=2)
A = E .- x_m
if localization === nothing
P = inflation*A*A'/(m - 1)
else
P = inflation*localization.*(A*A')/(m - 1)
end
K = P*H'*inv(H*P*H' + R)
x_m .+= K*(y - H*x_m)
E = x_m .+ real((I + P*H'*R_inv*H)^(-1/2))*A
return E
end
end