4141function sparsegrid (D:: Integer , nodes1D:: Vector{Vector{Float64}} , weights1D:: Vector{Vector{Float64}} )
4242 order = length (nodes1D)
4343
44- # Final nodes and weights in D dimensions
45- nodes = Array {Float64} (undef, D, 0 )
46- weights = Array {Float64} (undef, 0 )
47-
48- mink = max (0 , order- D)
44+ mink = max (0 , order - D)
4945 maxk = order - 1
46+ all_alpha_lists = [listNdq (D, D + k) for k in mink: maxk]
47+
48+ number_of_nodes = map (x -> sum (prod .(x)), all_alpha_lists) |> sum
49+
50+ # Final nodes and weights in D dimensions
51+ nodes = Vector {Vector{Float64}} (undef, 0 )
52+ sizehint! (nodes, number_of_nodes)
5053
51- # Temporary nodes and weights for 1 dimension
52- N = Vector {Vector{Float64}} (undef, D)
53- W = similar (N)
54+ weights = Array {Float64} (undef, 0 )
55+ sizehint! (weights, number_of_nodes)
5456
55- for k in mink: maxk
56- alpha = listNdq (D, D+ k)
57- nalpha = size (alpha, 2 )
57+ for (alpha_idx, k) in enumerate (mink: maxk)
58+ this_alpha_list = all_alpha_lists[alpha_idx]
5859
59- for n in 1 : nalpha
60+ for alpha in this_alpha_list
6061 # The nodes and weights for this alpha mixture
61- for d in 1 : D
62- N[d] = nodes1D[ alpha[d,n] ]
63- W[d] = weights1D[ alpha[d,n] ]
64- end
62+ N = [nodes1D[index] for index in alpha]
63+ W = [weights1D[index] for index in alpha]
6564
6665 # Compute all the possible combinations of D-dimensional nodes
6766 combN = combvec (N)
6867
6968 # Compute the associated weights
7069 cw = combvec (W)
71- combW = (- 1 )^ (maxk- k) * binomial (D- 1 , D+ k - order) * prod (cw, dims = 1 )
70+ combW = (- 1 )^ (maxk - k) * binomial (D - 1 , D + k - order) * map (prod, cw )
7271
73- # Save nodes and weights
74- nodes = hcat (nodes, combN)
75- weights = vcat (weights, vec (combW))
72+ append! (nodes, combN)
73+ append! (weights, combW)
7674 end
7775 end
7876
79- # Remove redundant nodes
80- unodes, uweights = uniquenodes (nodes, weights)
81-
82- return unodes, uweights
77+ unique_nodes, combined_weights = uniquenodes (nodes, weights)
78+ return unique_nodes, combined_weights
8379end
8480
8581
86- # ------------------------------------------------------------
87- # To correctly reduce "overlapping" nodes the middle node in an
88- # uneven number must be exactly zero
89-
82+ """
83+ To correctly reduce "overlapping" nodes the middle node in an uneven number must be exactly zero
84+ """
9085function symmetrize! (nodes:: Vector{Float64} )
9186 N = length (nodes)
9287
9388 if isodd (N)
94- midpoint = div ( N - 1 , 2 )
95- nodes[ midpoint+ 1 ] = 0.0
89+ midpoint = div (N - 1 , 2 )
90+ nodes[midpoint + 1 ] = 0.0
9691 else
97- midpoint = div ( N, 2 )
92+ midpoint = div (N, 2 )
9893 end
9994
10095 for n in 1 : midpoint
101- nodes[n] = - nodes[N+ 1 - n]
96+ nodes[n] = - nodes[N + 1 - n]
10297 end
10398end
10499
@@ -118,11 +113,11 @@ The algorithm and the formula for computing the number of elements in this set i
118113"""
119114function listNdq (D:: Integer , q:: Integer )
120115 if q < D
121- error (" listNdq: q must be larger than D" )
116+ error (" q must be larger than D" )
122117 end
123118
124- M = binomial (q- 1 , D- 1 )
125- L = ones (Int, D, M)
119+ M = binomial (q - 1 , D - 1 )
120+ L = [ ones (Int, D) for _ in 1 : M]
126121
127122 k = ones (Int, D)
128123 maxk = q - D + 1
@@ -138,15 +133,15 @@ function listNdq(D::Integer, q::Integer)
138133 k[p] = 1
139134 p += 1
140135 else
141- for i in 1 : p- 1
136+ for i in 1 : p - 1
142137 khat[i] = khat[p] - k[p] + 1
143138 end
144139
145140 k[1 ] = khat[1 ]
146141 p = 1
147142
148143 count += 1
149- L[:, count] = k
144+ copy! (L[ count], k)
150145 end
151146 end
152147
@@ -155,70 +150,57 @@ end
155150
156151
157152"""
158- combvec( vecs::Array{Any} ) -> Matrix
153+ combvec(vecs)
159154
160155Counterpart of Matlab's combvec:
161156Creates all combinations of vectors in `vecs`, an array of vectors.
162157"""
163158function combvec (vecs:: Vector{Vector{T}} ) where T
164- # Construct all Cartesian combinations of elements in vec as tuples
165- P = Iterators. product (vecs... )
166-
167159 D = length (vecs)
168- N = length (P) :: Int64
169- y = Array {T} (undef, D,N)
160+ N = map (length, vecs) |> prod
161+ y = [ Vector {T} (undef, D) for _ in 1 : N]
170162
171- n = 0
172- for p in P
173- y[:, n+= 1 ] = [p... ]
163+ # Construct all Cartesian combinations of elements in vec as tuples
164+ P = Iterators. product (vecs... )
165+ for (n, p) in enumerate (P)
166+ y[n] = [p... ]
174167 end
175168
176169 return y
177170end
178171
179172
180- # ------------------------------------------------------------
181-
182- # Copy of Base._sortslices for dims = 2 that also returns the permutation indices
183- # Previously Base.Sort.sortcols
184- function sortcolsidx (A:: AbstractMatrix )
185- itspace = Base. compute_itspace (A, Val (2 ))
186- vecs = map (its-> view (A, its... ), itspace)
187- p = sortperm (vecs)
188-
189- return A[:,p], p
190- end
191-
192-
193173"""
194- uniquenodes(nodes::Matrix , weights::Vector )
174+ uniquenodes(nodes, weights)
195175
196- Find unique nodes and sum the weights of the identical nodes
176+ Find unique nodes and sum the weights of identical nodes
197177"""
198- function uniquenodes (nodes:: AbstractMatrix , weights:: AbstractVector )
178+ function uniquenodes (nodes, weights)
199179 # Sort nodes and weights according to nodes
200- sortnodes, P = sortcolsidx (nodes)
201- weights = weights[P]
180+ perm = sortperm (nodes)
181+ sorted_nodes = nodes[perm]
182+ perm_weights = weights[perm]
202183
203- D, N = size (nodes)
184+ unique_nodes = similar (nodes, 0 )
185+ N = length (nodes)
204186
205- keep = [1 ]
206- lastkeep = 1
187+ indices_to_keep = [1 ]
188+ sizehint! (indices_to_keep, N)
189+ last_index_to_keep = 1
207190
208191 for n in 2 : N
209- if sortnodes[:,n ] == sortnodes[:,n - 1 ]
210- weights[lastkeep ] += weights [n]
192+ if sorted_nodes[last_index_to_keep ] == sorted_nodes[n ]
193+ perm_weights[last_index_to_keep ] += perm_weights [n]
211194 else
212- lastkeep = n
213- push! (keep , n)
195+ last_index_to_keep = n
196+ push! (indices_to_keep , n)
214197 end
215198 end
216199
217- # Keep unique nodes
218- unodes = sortnodes[:, keep]
219- uweights = weights[keep]
200+ unique_nodes = sorted_nodes[indices_to_keep]
201+ collected_weights = perm_weights[indices_to_keep]
220202
221- return unodes, uweights
203+ return unique_nodes, collected_weights
222204end
223205
224206
@@ -231,11 +213,11 @@ end
231213 Compute tensor grid of `N` nodes and corresponding weights `W` for `D` dimensions.
232214"""
233215function tensorgrid (N:: Vector , W:: Vector , D:: Integer )
234- NN = repeat ( [N], outer= [D; 1 ] )
235- WW = repeat ( [W], outer= [D; 1 ] )
216+ NN = repeat ([N], outer= [D; 1 ])
217+ WW = repeat ([W], outer= [D; 1 ])
236218
237219 tensorN = combvec (NN[:])
238- tensorW = vec (prod ( combvec (WW[:]), 1 ))
220+ tensorW = vec (prod (combvec (WW[:]), 1 ))
239221
240222 return tensorN, tensorW
241223end
@@ -248,4 +230,3 @@ function tensorgrid(D::Integer, order::Integer, f::Function=gausshermite)
248230
249231 return tensorN, tensorW
250232end
251-
0 commit comments