Conversation
|
I would throw a warning, on top of returning 0. Since we are looking at |
So I've been looking a bit into this,
my idea was to make a function |
This comment was marked as resolved.
This comment was marked as resolved.
|
Actually, the and |
|
Yes, I'd it is not necessary then. We could include this info in the docstrings though. |
Added usage notes for GPUArray interpolation.
|
There is no need for @loop when you don't shift This works fine on the GPU. Testing the out-of range stuff is fine for scalars. Since This one is a little funny since x[1] is shifted to [0,2.5] in the i direction which is within the domain. the j direction is shifted to [-0.5,3] which is out, so the final interpolant is [value,0]. Is that what we want to happen? |
|
@weymouth, neat approach with Not sure it's what we want indeed. The correct way is to check whether the initial point passed is inside the domain, and not if a shifted point is, something like this I suppose function _interp(x::SVector{D,T}, arr::AbstractArray{T,D}) where {D,T}
# Index below the interpolation coordinate and the difference
x = x .+ 1.5f0; i = floor.(Int,x); y = x.-i
# CartesianIndices around x
I = CartesianIndex(i...); R = I:I+oneunit(I)
# Linearly weighted sum over arr[R] (in serial)
s = zero(T)
@fastmath @inbounds @simd for J in R
weight = prod(@. ifelse(J.I==I.I,1-y,y))
s += arr[J]*weight
end
return s
end
using EllipsisNotation
function interp(x::SVector{D,T}, varr::AbstractArray{T}) where {D,T}
!(all(0 .≤ x) && all(x .≤ size(varr)[1:D].-2)) && return zero(x)
# Shift to align with each staggered grid component and interpolate
@inline shift(i) = SVector{D,T}(ifelse(i==j,0.5,0.) for j in 1:D)
return SVector{D,T}(_interp(x+shift(i),@view(varr[..,i])) for i in 1:D)
end
function interp(x::SVector{D,T}, arr::AbstractArray{T,D}) where {D,T}
!(all(0 .≤ x) && all(x .≤ size(arr).-2)) ? zero(T) : _interp(x, arr)
endwhich returns this for your test case 8-element CuArray{Float32, 1, CUDA.DeviceMemory}:
0.0
0.5563227
0.2339635
0.617647
0.47089913
0.6314482
0.01321663
0.0
8-element CuArray{SVector{2, Float32}, 1, CUDA.DeviceMemory}:
[0.0, 0.0]
[0.37724477, 0.3874247]
[0.639042, 0.6405743]
[0.49747413, 0.90232533]
[0.37469953, 0.6171435]
[0.430172, 0.49962258]
[0.6113318, 0.65551376]
[0.0, 0.0]which is probably better. |
I've noticed that
interpcan be called with locations that are outside the computational mesh. This is an issue since it sometimes returns rubbish.I am not too sure what the best approach here, a manual check like I implemented, or removing the
@inboundsfrom the interpolation loopMy version has the benefit of working regardless of the value of
xand simply returnszero(T).Additionally, this is a challenge to test since
@inbondsis removed by@test, and the code never reaches the point of testing the condition, simply throwing anOutOfBoundError.