Mercurial > repos > public > sbplib_julia
diff diffOp.jl @ 134:79699dda29be
Merge in cell_based_test
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Thu, 21 Feb 2019 16:27:28 +0100 |
parents | 1aaeb46ba5f4 |
children | bb1cc9c7877c c6aaf061c0a9 |
line wrap: on
line diff
--- a/diffOp.jl Fri Jan 25 15:20:40 2019 +0100 +++ b/diffOp.jl Thu Feb 21 16:27:28 2019 +0100 @@ -1,6 +1,7 @@ abstract type DiffOp end -function apply!(D::DiffOp, u::AbstractVector, v::AbstractVector) +# TBD: The "error("not implemented")" thing seems to be hiding good error information. How to fix that? Different way of saying that these should be implemented? +function apply(D::DiffOp, v::AbstractVector, i::Int) error("not implemented") end @@ -32,50 +33,98 @@ error("not implemented") end -# Differential operator for a*d^2/dx^2 -struct Laplace{Dim,T<:Real,N,M,K} <: DiffOp +abstract type DiffOpCartesian{Dim} <: DiffOp end + +# DiffOp must have a grid of dimension Dim!!! +function apply!(D::DiffOpCartesian{Dim}, u::AbstractArray{T,Dim}, v::AbstractArray{T,Dim}) where {T,Dim} + for I ∈ eachindex(D.grid) + u[I] = apply(D, v, I) + end + + return nothing +end + +function apply_region!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}) where T + apply_region!(D, u, v, Lower, Lower) + apply_region!(D, u, v, Lower, Interior) + apply_region!(D, u, v, Lower, Upper) + apply_region!(D, u, v, Interior, Lower) + apply_region!(D, u, v, Interior, Interior) + apply_region!(D, u, v, Interior, Upper) + apply_region!(D, u, v, Upper, Lower) + apply_region!(D, u, v, Upper, Interior) + apply_region!(D, u, v, Upper, Upper) + return nothing +end + +# Maybe this should be split according to b3fbef345810 after all?! Seems like it makes performance more predictable +function apply_region!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}, r1::Type{<:Region}, r2::Type{<:Region}) where T + for I ∈ regionindices(D.grid.size, closureSize(D.op), (r1,r2)) + @inbounds indextuple = (Index{r1}(I[1]), Index{r2}(I[2])) + @inbounds u[I] = apply(D, v, indextuple) + end + return nothing +end + +function apply_tiled!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}) where T + apply_region_tiled!(D, u, v, Lower, Lower) + apply_region_tiled!(D, u, v, Lower, Interior) + apply_region_tiled!(D, u, v, Lower, Upper) + apply_region_tiled!(D, u, v, Interior, Lower) + apply_region_tiled!(D, u, v, Interior, Interior) + apply_region_tiled!(D, u, v, Interior, Upper) + apply_region_tiled!(D, u, v, Upper, Lower) + apply_region_tiled!(D, u, v, Upper, Interior) + apply_region_tiled!(D, u, v, Upper, Upper) + return nothing +end + +using TiledIteration +function apply_region_tiled!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}, r1::Type{<:Region}, r2::Type{<:Region}) where T + ri = regionindices(D.grid.size, closureSize(D.op), (r1,r2)) + for tileaxs ∈ TileIterator(axes(ri), padded_tilesize(T, (5,5), 2)) # TBD: Is this the right way, the right size? + for j ∈ tileaxs[2], i ∈ tileaxs[1] + I = ri[i,j] + u[i,j] = apply(D, v, (Index{r1}(I[1]), Index{r2}(I[2]))) + end + end + return nothing +end + +function apply(D::DiffOp, v::AbstractVector)::AbstractVector + u = zeros(eltype(v), size(v)) + apply!(D,v,u) + return u +end + +struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim} grid::Grid.EquidistantGrid{Dim,T} a::T op::D2{Float64,N,M,K} end -# u = L*v -function apply!(L::Laplace{1}, u::AbstractVector, v::AbstractVector) - h = Grid.spacings(L.grid)[1] - apply!(L.op, u, v, h) - u .= L.a * u - return nothing +function apply(L::Laplace{Dim}, v::AbstractArray{T,Dim} where T, I::CartesianIndex{Dim}) where Dim + error("not implemented") end # u = L*v -function apply!(L::Laplace{2}, u::AbstractVector, v::AbstractVector) - u .= 0*u - h = Grid.spacings(L.grid) - - li = LinearIndices(L.grid.numberOfPointsPerDim) - n_x, n_y = L.grid.numberOfPointsPerDim - - - # For each x - temp = zeros(eltype(u), n_y) - for i ∈ 1:n_x - - v_i = view(v, li[i,:]) - apply!(L.op, temp, v_i, h[2]) +function apply(L::Laplace{1}, v::AbstractVector, i::Int) + uᵢ = L.a * apply(L.op, L.grid.spacing[1], v, i) + return uᵢ +end - u[li[i,:]] += temp - end +@inline function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, I::Tuple{Index{R1}, Index{R2}}) where {R1, R2} + # 2nd x-derivative + @inbounds vx = view(v, :, Int(I[2])) + @inbounds uᵢ = L.a*apply(L.op, L.grid.inverse_spacing[1], vx , I[1]) + # 2nd y-derivative + @inbounds vy = view(v, Int(I[1]), :) + @inbounds uᵢ += L.a*apply(L.op, L.grid.inverse_spacing[2], vy, I[2]) + return uᵢ +end - # For each y - temp = zeros(eltype(u), n_x) - for i ∈ 1:n_y - v_i = view(v, li[:,i]) - apply!(L.op, temp, v_i, h[1]) - - u[li[:,i]] += temp - end - - u .= L.a*u - - return nothing +# Slow but maybe convenient? +function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, i::CartesianIndex{2}) + I = Index{Unknown}.(Tuple(i)) + apply(L, v, I) end