Skip to content

Commit 3c268e5

Browse files
committed
lots of changes that has been sitting locally for a month now
1 parent 2613b49 commit 3c268e5

File tree

1 file changed

+78
-16
lines changed

1 file changed

+78
-16
lines changed

src/numericalnim/rbf.nim

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,25 @@ type
2727
template km(point: Tensor[float], index: int, delta: float): int =
2828
int(ceil(point[0, index] / delta))
2929

30-
iterator neighbours*[T](grid: RbfGrid[T], k: int): int =
30+
iterator neighbours*[T](grid: RbfGrid[T], k: int, searchLevels: int = 1): int =
3131
# TODO: Create product iterator that doesn't need to allocate 3^gridDim seqs
32-
for dir in product(@[@[-1, 0, 1]].cycle(grid.gridDim)):
32+
let directions = @[toSeq(-searchLevels .. searchLevels)].cycle(grid.gridDim)
33+
for dir in product(directions):
3334
block loopBody:
3435
var kNeigh = k
3536
for i, x in dir:
3637
let step = grid.gridSize ^ (grid.gridDim - i - 1)
37-
if (k div step) mod grid.gridSize == 0 and x == -1:
38+
for level in 1 .. searchLevels:
39+
if (k div step) mod grid.gridSize == level - 1 and x <= -level:
40+
break loopBody
41+
elif (k div step) mod grid.gridSize == grid.gridSize - level and x >= level:
42+
break loopBody
43+
#[ if ((k div step) mod grid.gridSize == 0 and x == -1) or ((k div step) mod grid.gridSize == 1 and x == -2):
3844
break loopBody
3945
elif (k div step) mod grid.gridSize == grid.gridSize - 1 and x == 1:
4046
break loopBody
41-
else:
42-
kNeigh += x * step
47+
else: ]#
48+
kNeigh += x * step
4349
if kNeigh >= 0 and kNeigh < grid.gridSize ^ grid.gridDim:
4450
yield kNeigh
4551

@@ -67,11 +73,23 @@ template dist2(p1, p2: Tensor[float]): float =
6773
proc findAllWithin*[T](grid: RbfGrid[T], x: Tensor[float], rho: float): seq[int] =
6874
assert x.shape.len == 2 and x.shape[0] == 1
6975
let index = grid.findIndex(x)
70-
for k in grid.neighbours(index):
76+
let searchLevels = (rho / grid.gridDelta).ceil.int
77+
for k in grid.neighbours(index, searchLevels):
7178
for i in grid.indices[k]:
7279
if dist2(x, grid.points[i, _]) <= rho*rho:
7380
result.add i
7481

82+
proc findAllBetween*[T](grid: RbfGrid[T], x: Tensor[float], rho1, rho2: float): seq[int] =
83+
assert x.shape.len == 2 and x.shape[0] == 1
84+
assert rho2 > rho1
85+
let index = grid.findIndex(x)
86+
let searchLevels = (rho2 / grid.gridDelta).ceil.int
87+
for k in grid.neighbours(index, searchLevels):
88+
for i in grid.indices[k]:
89+
let d = dist2(x, grid.points[i, _])
90+
if rho1*rho1 <= d and d <= rho2*rho2:
91+
result.add i
92+
7593
proc newRbfGrid*[T](points: Tensor[float], values: Tensor[T], gridSize: int = 0): RbfGrid[T] =
7694
let nPoints = points.shape[0]
7795
let nDims = points.shape[1]
@@ -108,7 +126,10 @@ template compactRbfFuncScalar*(r: float, epsilon: float): float =
108126

109127
proc compactRbfFunc*(r: Tensor[float], epsilon: float): Tensor[float] =
110128
result = map_inline(r):
111-
(1 - x/epsilon) ^ 4 * (4*x/epsilon + 1) * float(x < epsilon)
129+
let xeps = x / epsilon
130+
let temp = (1 - xeps)
131+
let temp2 = temp * temp
132+
temp2*temp2 * (4*xeps + 1) * float(xeps < 1)
112133

113134
proc newRbf*[T](points: Tensor[float], values: Tensor[T], rbfFunc: RbfFunc = compactRbfFunc, epsilon: float = 1): RbfType[T] =
114135
assert points.shape[0] == values.shape[0]
@@ -150,7 +171,8 @@ proc newRbfPu*[T](points: Tensor[float], values: Tensor[T], gridSize: int = 0, r
150171

151172
proc eval*[T](rbf: RbfPUType[T], x: Tensor[float]): Tensor[T] =
152173
assert x.shape.len == 2
153-
assert (not ((x <=. rbf.limits.upper) and (x >=. rbf.limits.lower))).astype(int).sum() == 0, "Some of your points are outside the allowed limits"
174+
assert (not ((x <=. rbf.limits.upper) and (x >=. rbf.limits.lower))).astype(int).sum() == 0, "Some of your points are outside the allowed limits"
175+
154176
let nPoints = x.shape[0]
155177
let x = x.scalePoint(rbf.limits)
156178
result = newTensor[T](nPoints, rbf.nValues)
@@ -170,6 +192,32 @@ proc eval*[T](rbf: RbfPUType[T], x: Tensor[float]): Tensor[T] =
170192
else:
171193
result[row, _] = T(Nan) # allow to pass default value to newRbfPU?
172194

195+
proc evalAlt*[T](rbf: RbfPUType[T], x: Tensor[float]): Tensor[T] =
196+
assert x.shape.len == 2
197+
assert (not ((x <=. rbf.limits.upper) and (x >=. rbf.limits.lower))).astype(int).sum() == 0, "Some of your points are outside the allowed limits"
198+
199+
let nPoints = x.shape[0]
200+
let x = x.scalePoint(rbf.limits)
201+
result = newTensor[T](nPoints, rbf.nValues)
202+
var c = newTensor[float](nPoints, 1)
203+
var isSet = newTensor[bool](nPoints, 1)
204+
let nPatches = rbf.grid.points.shape[0]
205+
let pointGrid = newRbfGrid(x, x, rbf.grid.gridSize)
206+
for row in 0 ..< nPatches:
207+
let center = rbf.grid.points[row, _]
208+
let indices = pointGrid.findAllWithin(center, rbf.grid.gridDelta)
209+
if indices.len > 0:
210+
let vals = rbf.grid.values[row, 0].eval(x[indices, _])
211+
for i, index in indices:
212+
let r = sqrt(dist2(center, x[index, _]))
213+
let ci = compactRbfFuncScalar(r, rbf.grid.gridDelta)
214+
result[index, _] = result[index, _] + ci * vals[i, _]
215+
c[index] += ci
216+
isSet[index, 0] = true
217+
218+
result /.= c
219+
result[not isSet, _] = T(NaN)
220+
173221
when isMainModule:
174222
let x1 = @[@[0.01, 0.01, 0.01], @[1.0, 1.0, 0.0], @[1.0, 2.0, 4.0]].toTensor
175223
let x2 = @[@[0.0, 0.0, 1.0], @[1.0, 1.0, 2.0], @[1.0, 2.0, 3.0]].toTensor
@@ -179,18 +227,32 @@ when isMainModule:
179227

180228
import benchy
181229

182-
#let pos = randomTensor(5000, 3, 1.0)
183-
#let vals = randomTensor(5000, 1, 1.0)
184-
# timeIt "Rbf":
185-
# keep newRbf(pos, vals)
230+
var pos = randomTensor(100000, 3, 1.0)
231+
pos[0, _] = [[1.0, 1.0, 1.0]]
232+
pos[1, _] = [[0.0, 0.0, 0.0]]
233+
let vals = randomTensor(100000, 1, 1.0)
234+
let evalPos = randomTensor(100000, 3, 0.9)
235+
#let rb = newRbf(pos, vals)
236+
#let rbPU = newRbfPu(pos, vals)
237+
#timeIt "RbfPU eval":
238+
# keep rbPU.eval(evalPos)
239+
#timeIt "Rbf eval":
240+
# keep rb.eval(evalPos)
241+
186242
#let rbfPu = newRbfPu(x1, values, 3)
187243
#echo rbfPu.grid.values[1, 0]
188244
#echo rbfPu.eval(x1[[2, 1, 0], _])
189245

190246
#echo rbfPu.eval(sqrt x1)
191247
echo "----------------"
192-
#[ let xGrid = [[0.1, 0.1], [0.2, 0.3], [0.9, 0.9], [0.4, 0.4]].toTensor
248+
for y in countdown(4, 0):
249+
var row = ""
250+
for x in 0 .. 4:
251+
row &= $(x*5 + y) & "\t"
252+
echo row
253+
254+
let xGrid = [[0.1, 0.1], [0.2, 0.3], [0.9, 0.9], [0.4, 0.4]].toTensor
193255
let valuesGrid = @[0, 1, 9, 5].toTensor.reshape(4, 1)
194-
let grid = newRbfGrid(xGrid, valuesGrid, 2)
195-
echo grid
196-
echo grid.neighbours(3).toSeq ]#
256+
let grid = newRbfGrid(xGrid, valuesGrid, 5)
257+
#echo grid
258+
echo grid.neighbours(7, 1).toSeq

0 commit comments

Comments
 (0)