1
1
"""
2
2
Pre-plan an Inverse Padua Transform.
3
3
"""
4
- immutable IPaduaTransformPlan{DCTPLAN}
5
- cfsmat:: Matrix{Float64}
6
- tensorvals:: Matrix{Float64}
7
- padvals:: Vector{Float64}
8
- dctplan:: DCTPLAN
4
+ immutable IPaduaTransformPlan{IDCTPLAN,T}
5
+ cfsmat:: Matrix{T}
6
+ padvals:: Vector{T}
7
+ idctplan:: IDCTPLAN
9
8
end
10
9
11
- function plan_ipaduatransform (v:: AbstractVector )
10
+ function plan_ipaduatransform {T} (v:: AbstractVector{T} )
12
11
N= length (v)
13
12
n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
14
13
@assert N== div ((n+ 1 )* (n+ 2 ),2 )
15
- IPaduaTransformPlan (zeros (Float64, n+ 2 ,n+ 1 ),Array (Float64,n + 2 ,n + 1 ),
16
- Array (Float64,N), FFTW. plan_r2r (Array ( eltype (v), n+ 2 ,n+ 1 ),FFTW. REDFT00))
14
+ IPaduaTransformPlan (Array {T} ( n+ 2 ,n+ 1 ),Array {T} (N ),
15
+ FFTW. plan_r2r! (Array {T} ( n+ 2 ,n+ 1 ),FFTW. REDFT00))
17
16
end
18
17
19
18
"""
20
19
Inverse Padua Transform maps the 2D Chebyshev coefficients to the values of the interpolation polynomial at the Padua points.
21
20
"""
22
- function ipaduatransform (P:: IPaduaTransformPlan ,v:: AbstractVector )
21
+ function ipaduatransform {T} (P:: IPaduaTransformPlan ,v:: AbstractVector{T} )
23
22
cfsmat= trianglecfsmat (P,v)
24
- tensorvals = P . tensorvals
25
- cfsmat[:, 2 : end - 1 ] = scale! (cfsmat[ :,2 : end - 1 ] ,0.5 )
26
- cfsmat[ 2 : end - 1 ,:] = scale! (cfsmat[ 2 : end - 1 ,:] ,0.5 )
27
- tensorvals= P. dctplan * cfsmat
23
+ n,m = size (cfsmat)
24
+ scale! (view ( cfsmat, :,2 : m - 1 ) ,0.5 )
25
+ scale! (view ( cfsmat, 2 : n - 1 ,:) ,0.5 )
26
+ tensorvals= P. idctplan * cfsmat
28
27
paduavals= paduavec (P,tensorvals)
29
28
return paduavals
30
29
end
31
30
32
- function ipaduatransform (v:: AbstractVector )
33
- cfsmat= trianglecfsmat (v)
34
- n= size (cfsmat,2 )- 1
35
- tensorvals= Array (Float64,n+ 2 ,n+ 1 )
36
- cfsmat[:,2 : end - 1 ]= scale! (cfsmat[:,2 : end - 1 ],0.5 )
37
- cfsmat[2 : end - 1 ,:]= scale! (cfsmat[2 : end - 1 ,:],0.5 )
38
- tensorvals= FFTW. r2r (cfsmat,FFTW. REDFT00)
39
- paduavals= paduavec (tensorvals)
40
- return paduavals
41
- end
42
31
"""
43
32
Creates (n+2)x(n+1) Chebyshev coefficient matrix from triangle coefficients.
44
33
"""
45
34
function trianglecfsmat (P:: IPaduaTransformPlan ,cfs:: AbstractVector )
46
35
N= length (cfs)
47
36
n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
48
- cfsmat= P. cfsmat
49
- m= 1
50
- for d= 1 : n+ 1 , k= 1 : d
51
- j= d- k+ 1
52
- cfsmat[k,j]= cfs[m]
53
- if m== N
54
- return cfsmat
55
- else
56
- m+= 1
57
- end
58
- end
59
- return cfsmat
60
- end
61
-
62
- function trianglecfsmat (cfs:: AbstractVector )
63
- N= length (cfs)
64
- n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
65
- @assert N== div ((n+ 1 )* (n+ 2 ),2 )
66
- cfsmat= zeros (Float64,n+ 2 ,n+ 1 )
37
+ cfsmat= fill! (P. cfsmat,0 )
67
38
m= 1
68
- for d= 1 : n+ 1 , k= 1 : d
69
- j= d- k+ 1
70
- cfsmat[k,j]= cfs[m]
71
- if m== N
72
- return cfsmat
73
- else
74
- m+= 1
39
+ for d= 1 : n+ 1
40
+ @inbounds for k= 1 : d
41
+ j= d- k+ 1
42
+ cfsmat[k,j]= cfs[m]
43
+ if m== N
44
+ return cfsmat
45
+ else
46
+ m+= 1
47
+ end
75
48
end
76
49
end
77
50
return cfsmat
@@ -82,122 +55,71 @@ Vectorizes the function values at the Padua points.
82
55
"""
83
56
function paduavec (P:: IPaduaTransformPlan ,padmat:: Matrix )
84
57
n= size (padmat,2 )- 1
85
- padvals= P. padvals
86
- if iseven (n)> 0
87
- d= div (n+ 2 ,2 )
88
- m= 0
89
- for i= 1 : n+ 1
90
- padvals[m+ 1 : m+ d]= padmat[1 + mod (i,2 ): 2 : end - 1 + mod (i,2 ),i]
91
- m+= d
92
- end
93
- else
94
- padvals= padmat[1 : 2 : end - 1 ]
95
- end
96
- return padvals
97
- end
98
-
99
- function paduavec (padmat:: Matrix )
100
- n= size (padmat,2 )- 1
101
- N= div ((n+ 1 )* (n+ 2 ),2 )
102
- padvals= Array (Float64,N)
58
+ N= (n+ 1 )* (n+ 2 )
103
59
if iseven (n)> 0
104
60
d= div (n+ 2 ,2 )
105
61
m= 0
106
- for i= 1 : n+ 1
107
- padvals[m+ 1 : m+ d]= padmat[ 1 + mod (i,2 ): 2 : end - 1 + mod (i,2 ),i]
62
+ @inbounds for i= 1 : n+ 1
63
+ P . padvals[m+ 1 : m+ d]= view ( padmat, 1 + mod (i,2 ): 2 : n + 1 + mod (i,2 ),i)
108
64
m+= d
109
65
end
110
66
else
111
- padvals= padmat[ 1 : 2 : end - 1 ]
67
+ @inbounds P . padvals[:] = view ( padmat, 1 : 2 : N - 1 )
112
68
end
113
- return padvals
69
+ return P . padvals
114
70
end
115
71
116
72
"""
117
73
Pre-plan a Padua Transform.
118
74
"""
119
- immutable PaduaTransformPlan{IDCTPLAN}
120
- vals:: Matrix{Float64}
121
- tensorcfs:: Matrix{Float64}
122
- retvec:: Vector{Float64}
123
- idctplan:: IDCTPLAN
75
+ immutable PaduaTransformPlan{DCTPLAN,T}
76
+ vals:: Matrix{T}
77
+ retvec:: Vector{T}
78
+ dctplan:: DCTPLAN
124
79
end
125
80
126
- function plan_paduatransform (v:: AbstractVector )
81
+ function plan_paduatransform {T} (v:: AbstractVector{T} )
127
82
N= length (v)
128
83
n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
129
84
@assert N== div ((n+ 1 )* (n+ 2 ),2 )
130
- PaduaTransformPlan (zeros (Float64, n+ 2 ,n+ 1 ),Array (Float64,n + 2 ,n + 1 ),
131
- zeros (Float64,N), FFTW. plan_r2r (Array ( eltype (v), n+ 2 ,n+ 1 ),FFTW. REDFT00))
85
+ PaduaTransformPlan (Array {T} ( n+ 2 ,n+ 1 ),Array {T} (N ),
86
+ FFTW. plan_r2r! (Array {T} ( n+ 2 ,n+ 1 ),FFTW. REDFT00))
132
87
end
133
88
134
89
"""
135
90
Padua Transform maps from interpolant values at the Padua points to the 2D Chebyshev coefficients.
136
91
"""
137
- function paduatransform (P:: PaduaTransformPlan ,v:: AbstractVector )
92
+ function paduatransform {T} (P:: PaduaTransformPlan ,v:: AbstractVector{T} )
138
93
N= length (v)
139
94
n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
140
- tensorcfs= P. tensorcfs
141
95
vals= paduavalsmat (P,v)
142
- tensorcfs= P. idctplan* vals
143
- tensorcfs= scale! (tensorcfs,2. / (n* (n+ 1. )))
144
- tensorcfs[1 ,:]= scale! (tensorcfs[1 ,:],0.5 )
145
- tensorcfs[:,1 ]= scale! (tensorcfs[:,1 ],0.5 )
146
- tensorcfs[end ,:]= scale! (tensorcfs[end ,:],0.5 )
147
- tensorcfs[:,end ]= scale! (tensorcfs[:,end ],0.5 )
96
+ tensorcfs= P. dctplan* vals
97
+ m,l= size (tensorcfs)
98
+ scale! (tensorcfs,T (2 )/ (n* (n+ 1 )))
99
+ scale! (view (tensorcfs,1 ,:),0.5 )
100
+ scale! (view (tensorcfs,:,1 ),0.5 )
101
+ scale! (view (tensorcfs,m,:),0.5 )
102
+ scale! (view (tensorcfs,:,l),0.5 )
148
103
cfs= trianglecfsvec (P,tensorcfs)
149
104
return cfs
150
105
end
151
106
152
- function paduatransform (v:: AbstractVector )
153
- N= length (v)
154
- n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
155
- tensorcfs= Array (Float64,n+ 2 ,n+ 1 )
156
- vals= paduavalsmat (v)
157
- tensorcfs= FFTW. r2r (vals,FFTW. REDFT00)
158
- tensorcfs= scale! (tensorcfs,2. / (n* (n+ 1. )))
159
- tensorcfs[1 ,:]= scale! (tensorcfs[1 ,:],0.5 )
160
- tensorcfs[:,1 ]= scale! (tensorcfs[:,1 ],0.5 )
161
- tensorcfs[end ,:]= scale! (tensorcfs[end ,:],0.5 )
162
- tensorcfs[:,end ]= scale! (tensorcfs[:,end ],0.5 )
163
- cfsvec= trianglecfsvec (tensorcfs)
164
- return cfsvec
165
- end
166
-
167
107
"""
168
108
Creates (n+2)x(n+1) matrix of interpolant values on the tensor grid at the (n+1)(n+2)/2 Padua points.
169
109
"""
170
110
function paduavalsmat (P:: PaduaTransformPlan ,v:: AbstractVector )
171
111
N= length (v)
172
112
n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
173
- vals= P. vals
174
- if iseven (n)> 0
175
- d= div (n+ 2 ,2 )
176
- m= 0
177
- for i= 1 : n+ 1
178
- vals[1 + mod (i,2 ): 2 : end - 1 + mod (i,2 ),i]= v[m+ 1 : m+ d]
179
- m+= d
180
- end
181
- else
182
- vals[1 : 2 : end ]= v
183
- end
184
- return vals
185
- end
186
-
187
- function paduavalsmat (v:: AbstractVector )
188
- N= length (v)
189
- n= Int (cld (- 3 + sqrt (1 + 8 N),2 ))
190
- @assert N== div ((n+ 1 )* (n+ 2 ),2 )
191
- vals= zeros (Float64,n+ 2 ,n+ 1 )
113
+ vals= fill! (P. vals,0. )
192
114
if iseven (n)> 0
193
115
d= div (n+ 2 ,2 )
194
116
m= 0
195
- for i= 1 : n+ 1
196
- vals[1 + mod (i,2 ): 2 : end - 1 + mod (i,2 ),i]= v[ m+ 1 : m+ d]
117
+ @inbounds for i= 1 : n+ 1
118
+ vals[1 + mod (i,2 ): 2 : n + 1 + mod (i,2 ),i]= view (v, m+ 1 : m+ d)
197
119
m+= d
198
120
end
199
121
else
200
- vals[1 : 2 : end ]= v
122
+ @inbounds vals[1 : 2 : end ]= view (v,:)
201
123
end
202
124
return vals
203
125
end
@@ -207,67 +129,39 @@ Creates length (n+1)(n+2)/2 vector from matrix of triangle Chebyshev coefficient
207
129
"""
208
130
function trianglecfsvec (P:: PaduaTransformPlan ,cfs:: Matrix )
209
131
m= size (cfs,2 )
210
- ret= P. retvec
211
- l= 1
212
- for d= 1 : m,k= 1 : d
213
- j= d- k+ 1
214
- ret[l]= cfs[k,j]
215
- l+= 1
216
- end
217
- return ret
218
- end
219
-
220
- function trianglecfsvec (cfs:: Matrix )
221
- n,m= size (cfs)
222
- N= div (n* m,2 )
223
- ret= Array (Float64,N)
224
132
l= 1
225
- for d= 1 : m,k= 1 : d
226
- j= d- k+ 1
227
- ret[l]= cfs[k,j]
228
- l+= 1
133
+ for d= 1 : m
134
+ @inbounds for k= 1 : d
135
+ j= d- k+ 1
136
+ P. retvec[l]= cfs[k,j]
137
+ l+= 1
138
+ end
229
139
end
230
- return ret
140
+ return P . retvec
231
141
end
232
142
233
143
"""
234
144
Returns coordinates of the (n+1)(n+2)/2 Padua points.
235
145
"""
236
- function paduapoints ( n:: Integer )
146
+ function paduapoints {T} ( :: Type{T} , n:: Integer )
237
147
N= div ((n+ 1 )* (n+ 2 ),2 )
238
- MM= Array (Float64 ,N,2 )
148
+ MM= Array (T ,N,2 )
239
149
m= 0
240
150
delta= 0
241
151
NN= fld (n+ 2 ,2 )
242
- for k= n: - 1 : 0
152
+ @inbounds for k= n: - 1 : 0
243
153
if isodd (n)> 0
244
154
delta= mod (k,2 )
245
155
end
246
- for j= NN+ delta: - 1 : 1
156
+ @inbounds for j= NN+ delta: - 1 : 1
247
157
m+= 1
248
- MM[m,1 ]= sinpi (1. * k / n- 0.5 )
158
+ MM[m,1 ]= sinpi (T (k) / n- T ( 0.5 ) )
249
159
if isodd (n- k)> 0
250
- MM[m,2 ]= sinpi ((2 j- 1. ) / (n+ 1. ) - 0.5 )
160
+ MM[m,2 ]= sinpi ((2 j- one (T)) / (n+ 1 ) - T ( 0.5 ) )
251
161
else
252
- MM[m,2 ]= sinpi ((2 j- 2. )/ (n+ 1. ) - 0.5 )
162
+ MM[m,2 ]= sinpi (T (2 j- 2 )/ (n+ 1 ) - T ( 0.5 ) )
253
163
end
254
164
end
255
165
end
256
166
return MM
257
167
end
258
-
259
- """
260
- Interpolates a 2d function at a given point using 2d Chebyshev series.
261
- """
262
- function paduaeval (f:: Function ,x:: Float64 ,y:: Float64 ,m:: Integer )
263
- M= div ((m+ 1 )* (m+ 2 ),2 )
264
- pvals= Array (Float64,M)
265
- p= paduapoints (m)
266
- pvals= map (f,p[:,1 ],p[:,2 ])
267
- plan= plan_paduatransform (pvals)
268
- coeffs= paduatransform (plan,pvals)
269
- cfs_mat= trianglecfsmat (coeffs)
270
- cfs_mat= cfs_mat[1 : end - 1 ,:]
271
- f_x= sum ([cfs_mat[k,j]* cos ((j- 1 )* acos (x))* cos ((k- 1 )* acos (y)) for k= 1 : m+ 1 , j= 1 : m+ 1 ])
272
- return f_x
273
- end
0 commit comments