forked from SciML/ModelOrderReduction.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPOD.jl
More file actions
106 lines (93 loc) · 2.89 KB
/
POD.jl
File metadata and controls
106 lines (93 loc) · 2.89 KB
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using TSVD: tsvd
using RandomizedLinAlg: rsvd
function matricize(VoV::Vector{Vector{T}}) where {T}
return reduce(hcat, VoV)
end
function _svd(data::Vector{Vector{T}}; kwargs...) where {T}
mat_data = matricize(data)
return _svd(mat_data; kwargs...)
end
_svd(data; kwargs...) = svd(data; kwargs...)
function _tsvd(data::Vector{Vector{T}}, n::Int = 1; kwargs...) where {T}
mat_data = matricize(data)
return _tsvd(mat_data, n; kwargs...)
end
_tsvd(data, n::Int = 1; kwargs...) = tsvd(data, n; kwargs...)
function _rsvd(data::Vector{Vector{T}}, n::Int, p::Int) where {T}
mat_data = matricize(data)
return _rsvd(mat_data, n, p)
end
_rsvd(data, n::Int, p::Int) = rsvd(data, n, p)
mutable struct POD <: AbstractDRProblem
# specified
snapshots::Any
min_renergy::Any
min_nmodes::Int
max_nmodes::Int
# computed
nmodes::Int
rbasis::Any
renergy::Any
spectrum::Any
# constructors
function POD(
snaps;
min_renergy = 1.0,
min_nmodes::Int = 1,
max_nmodes::Int = length(snaps[1])
)
nmodes = min_nmodes
errorhandle(snaps, nmodes, min_renergy, min_nmodes, max_nmodes)
return new(snaps, min_renergy, min_nmodes, max_nmodes, nmodes, missing, 1.0, missing)
end
function POD(snaps, nmodes::Int)
errorhandle(snaps, nmodes, 0.0, nmodes, nmodes)
return new(snaps, 0.0, nmodes, nmodes, nmodes, missing, 1.0, missing)
end
end
function determine_truncation(s, min_nmodes, min_renergy, max_nmodes)
nmodes = min_nmodes
overall_energy = sum(s)
energy = sum(s[1:nmodes]) / overall_energy
while energy < min_renergy && nmodes < max_nmodes
nmodes += 1
energy += s[nmodes + 1] / overall_energy
end
return nmodes, energy
end
function reduce!(pod::POD, alg::SVD)
u, s, v = _svd(pod.snapshots; alg.kwargs...)
pod.nmodes,
pod.renergy = determine_truncation(
s, pod.min_nmodes, pod.max_nmodes,
pod.min_renergy
)
pod.rbasis = u[:, 1:(pod.nmodes)]
pod.spectrum = s
return nothing
end
function reduce!(pod::POD, alg::TSVD)
u, s, v = _tsvd(pod.snapshots, pod.nmodes; alg.kwargs...)
n_max = min(size(u, 1), size(v, 1))
pod.renergy = sum(s) / (sum(s) + (n_max - pod.nmodes) * s[end])
pod.rbasis = u
pod.spectrum = s
return nothing
end
function reduce!(pod::POD, alg::RSVD)
u, s, v = _rsvd(pod.snapshots, pod.nmodes, alg.p)
n_max = min(size(u, 1), size(v, 1))
pod.renergy = sum(s) / (sum(s) + (n_max - pod.nmodes) * s[end])
pod.rbasis = u
pod.spectrum = s
return nothing
end
function Base.show(io::IO, pod::POD)
print(io, "POD \n")
print(io, "Reduction Order = ", pod.nmodes, "\n")
print(
io, "Snapshot size = (", size(pod.snapshots, 1), ",", size(pod.snapshots[1], 2),
")\n"
)
return print(io, "Relative Energy = ", pod.renergy, "\n")
end