changeset 211:1ad91e11b1f4 package_refactor

Move DiffOps and Grids into packages
author Jonatan Werpers <jonatan@werpers.com>
date Wed, 26 Jun 2019 10:44:20 +0200
parents 2aa33d0eef90
children aa17d4d9d09e
files AbstractGrid.jl DiffOps/Project.toml DiffOps/src/DiffOps.jl EquidistantGrid.jl Grids/Project.toml Grids/src/AbstractGrid.jl Grids/src/EquidistantGrid.jl Grids/src/Grids.jl Manifest.toml Project.toml diffOp.jl sbp.jl
diffstat 12 files changed, 322 insertions(+), 293 deletions(-) [+]
line wrap: on
line diff
--- a/AbstractGrid.jl	Tue Jun 25 17:26:39 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-abstract type AbstractGrid end
-
-function dimension(grid::AbstractGrid)
-    error("Not implemented for abstact type AbstractGrid")
-end
-
-function points(grid::AbstractGrid)
-    error("Not implemented for abstact type AbstractGrid")
-end
-
-# Evaluate function f on the grid g
-function evalOn(g::AbstractGrid, f::Function)
-    F(x) = f(x...)
-    return F.(points(g))
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DiffOps/Project.toml	Wed Jun 26 10:44:20 2019 +0200
@@ -0,0 +1,4 @@
+name = "DiffOps"
+uuid = "39474f48-97ec-11e9-01fc-6ddcbe5918df"
+authors = ["Jonatan Werpers <jonatan.werpers@it.uu.se>"]
+version = "0.1.0"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DiffOps/src/DiffOps.jl	Wed Jun 26 10:44:20 2019 +0200
@@ -0,0 +1,220 @@
+abstract type DiffOp end
+
+# 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
+
+function innerProduct(D::DiffOp, u::AbstractVector, v::AbstractVector)::Real
+    error("not implemented")
+end
+
+function matrixRepresentation(D::DiffOp)
+    error("not implemented")
+end
+
+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))
+    # TODO: Pass Tilesize to function
+    for tileaxs ∈ TileIterator(axes(ri), padded_tilesize(T, (5,5), 2))
+        for j ∈ tileaxs[2], i ∈ tileaxs[1]
+            I = ri[i,j]
+            u[I] = 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 NormalDerivative{N,M,K}
+	op::D2{Float64,N,M,K}
+	grid::EquidistantGrid
+	bId::CartesianBoundary
+end
+
+function apply_transpose(d::NormalDerivative, v::AbstractArray, I::Integer)
+	u = selectdim(v,3-dim(d.bId),I)
+	return apply_d(d.op, d.grid.inverse_spacing[dim(d.bId)], u, region(d.bId))
+end
+
+# Not correct abstraction level
+# TODO: Not type stable D:<
+function apply(d::NormalDerivative, v::AbstractArray, I::Tuple{Integer,Integer})
+	i = I[dim(d.bId)]
+	j = I[3-dim(d.bId)]
+	N_i = d.grid.size[dim(d.bId)]
+
+	r = getregion(i, closureSize(d.op), N_i)
+
+	if r != region(d.bId)
+		return 0
+	end
+
+	if r == Lower
+		# Note, closures are indexed by offset. Fix this D:<
+		return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[i-1]*v[j]
+	elseif r == Upper
+		return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[N_i-j]*v[j]
+	end
+end
+
+struct BoundaryValue{N,M,K}
+	op::D2{Float64,N,M,K}
+	grid::EquidistantGrid
+	bId::CartesianBoundary
+end
+
+function apply(e::BoundaryValue, v::AbstractArray, I::Tuple{Integer,Integer})
+	i = I[dim(e.bId)]
+	j = I[3-dim(e.bId)]
+	N_i = e.grid.size[dim(e.bId)]
+
+	r = getregion(i, closureSize(e.op), N_i)
+
+	if r != region(e.bId)
+		return 0
+	end
+
+	if r == Lower
+		# Note, closures are indexed by offset. Fix this D:<
+		return e.op.eClosure[i-1]*v[j]
+	elseif r == Upper
+		return e.op.eClosure[N_i-j]*v[j]
+	end
+end
+
+function apply_transpose(e::BoundaryValue, v::AbstractArray, I::Integer)
+	u = selectdim(v,3-dim(e.bId),I)
+	return apply_e(e.op, u, region(e.bId))
+end
+
+struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim}
+    grid::EquidistantGrid{Dim,T}
+    a::T
+    op::D2{Float64,N,M,K}
+    e::BoundaryValue
+    d::NormalDerivative
+end
+
+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{1}, v::AbstractVector, i::Int)
+    uᵢ = L.a * apply(L.op, L.grid.spacing[1], v, i)
+    return uᵢ
+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
+
+# 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
+
+struct BoundaryOperator
+
+end
+
+
+"""
+A BoundaryCondition should implement the method
+    sat(::DiffOp, v::AbstractArray, data::AbstractArray, ...)
+"""
+abstract type BoundaryCondition end
+
+struct Neumann{Bid<:BoundaryIdentifier} <: BoundaryCondition end
+
+function sat(L::Laplace{2,T}, bc::Neumann{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, I::CartesianIndex{2}) where {T,Bid}
+    e = BoundaryValue(L.op, L.grid, Bid())
+    d = NormalDerivative(L.op, L.grid, Bid())
+    Hᵧ = BoundaryQuadrature(L.op, L.grid, Bid())
+    # TODO: Implement BoundaryQuadrature method
+
+    return -L.Hi*e*Hᵧ*(d'*v - g)
+    # Need to handle d'*v - g so that it is an AbstractArray that TensorMappings can act on
+end
+
+struct Dirichlet{Bid<:BoundaryIdentifier} <: BoundaryCondition
+    tau::Float64
+end
+
+function sat(L::Laplace{2,T}, bc::Dirichlet{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, i::CartesianIndex{2}) where {T,Bid}
+    e = BoundaryValue(L.op, L.grid, Bid())
+    d = NormalDerivative(L.op, L.grid, Bid())
+    Hᵧ = BoundaryQuadrature(L.op, L.grid, Bid())
+    # TODO: Implement BoundaryQuadrature method
+
+    return -L.Hi*(tau/h*e + d)*Hᵧ*(e'*v - g)
+    # Need to handle scalar multiplication and addition of TensorMapping
+end
+
+# function apply(s::MyWaveEq{D},  v::AbstractArray{T,D}, i::CartesianIndex{D}) where D
+# 	return apply(s.L, v, i) +
+# 		sat(s.L, Dirichlet{CartesianBoundary{1,Lower}}(s.tau),  v, s.g_w, i) +
+# 		sat(s.L, Dirichlet{CartesianBoundary{1,Upper}}(s.tau),  v, s.g_e, i) +
+# 		sat(s.L, Dirichlet{CartesianBoundary{2,Lower}}(s.tau),  v, s.g_s, i) +
+# 		sat(s.L, Dirichlet{CartesianBoundary{2,Upper}}(s.tau),  v, s.g_n, i)
+# end
--- a/EquidistantGrid.jl	Tue Jun 25 17:26:39 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-# EquidistantGrid is a grid with equidistant grid spacing per coordinat
-# direction. The domain is defined through the two points P1 = x̄₁, P2 = x̄₂
-# by the exterior product of the vectors obtained by projecting (x̄₂-x̄₁) onto
-# the coordinate directions. E.g for a 2D grid with x̄₁=(-1,0) and x̄₂=(1,2)
-# the domain is defined as (-1,1)x(0,2).
-
-struct EquidistantGrid{Dim,T<:Real} <: AbstractGrid
-    size::NTuple{Dim, Int} # First coordinate direction stored first
-    limit_lower::NTuple{Dim, T}
-    limit_upper::NTuple{Dim, T}
-    inverse_spacing::NTuple{Dim, T} # The reciprocal of the grid spacing
-
-    # General constructor
-    function EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) where Dim where T
-        @assert all(size.>0)
-        @assert all(limit_upper.-limit_lower .!= 0)
-        inverse_spacing = (size.-1)./abs.(limit_upper.-limit_lower)
-        return new{Dim,T}(size, limit_lower, limit_upper, inverse_spacing)
-    end
-end
-
-function Base.eachindex(grid::EquidistantGrid)
-    CartesianIndices(grid.size)
-end
-
-# Returns the number of dimensions of an EquidistantGrid.
-#
-# @Input: grid - an EquidistantGrid
-# @Return: dimension - The dimension of the grid
-function dimension(grid::EquidistantGrid)
-    return length(grid.size)
-end
-
-# Returns the spacing of the grid
-#
-function spacing(grid::EquidistantGrid)
-    return 1.0./grid.inverse_spacing
-end
-
-# Computes the points of an EquidistantGrid as an array of tuples with
-# the same dimension as the grid.
-#
-# @Input: grid - an EquidistantGrid
-# @Return: points - the points of the grid.
-function points(grid::EquidistantGrid)
-    # TODO: Make this return an abstract array?
-    indices = Tuple.(CartesianIndices(grid.size))
-    h = spacing(grid)
-    return broadcast(I -> grid.limit_lower .+ (I.-1).*h, indices)
-end
-
-function pointsalongdim(grid::EquidistantGrid, dim::Integer)
-    @assert dim<=dimension(grid)
-    @assert dim>0
-    points = collect(range(grid.limit_lower[dim],stop=grid.limit_upper[dim],length=grid.size[dim]))
-end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Grids/Project.toml	Wed Jun 26 10:44:20 2019 +0200
@@ -0,0 +1,4 @@
+name = "Grids"
+uuid = "960fdf28-97ed-11e9-2a74-bd90bf2fab5a"
+authors = ["Jonatan Werpers <jonatan.werpers@it.uu.se>"]
+version = "0.1.0"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Grids/src/AbstractGrid.jl	Wed Jun 26 10:44:20 2019 +0200
@@ -0,0 +1,15 @@
+abstract type AbstractGrid end
+
+function dimension(grid::AbstractGrid)
+    error("Not implemented for abstact type AbstractGrid")
+end
+
+function points(grid::AbstractGrid)
+    error("Not implemented for abstact type AbstractGrid")
+end
+
+# Evaluate function f on the grid g
+function evalOn(g::AbstractGrid, f::Function)
+    F(x) = f(x...)
+    return F.(points(g))
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Grids/src/EquidistantGrid.jl	Wed Jun 26 10:44:20 2019 +0200
@@ -0,0 +1,56 @@
+# EquidistantGrid is a grid with equidistant grid spacing per coordinat
+# direction. The domain is defined through the two points P1 = x̄₁, P2 = x̄₂
+# by the exterior product of the vectors obtained by projecting (x̄₂-x̄₁) onto
+# the coordinate directions. E.g for a 2D grid with x̄₁=(-1,0) and x̄₂=(1,2)
+# the domain is defined as (-1,1)x(0,2).
+
+struct EquidistantGrid{Dim,T<:Real} <: AbstractGrid
+    size::NTuple{Dim, Int} # First coordinate direction stored first
+    limit_lower::NTuple{Dim, T}
+    limit_upper::NTuple{Dim, T}
+    inverse_spacing::NTuple{Dim, T} # The reciprocal of the grid spacing
+
+    # General constructor
+    function EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) where Dim where T
+        @assert all(size.>0)
+        @assert all(limit_upper.-limit_lower .!= 0)
+        inverse_spacing = (size.-1)./abs.(limit_upper.-limit_lower)
+        return new{Dim,T}(size, limit_lower, limit_upper, inverse_spacing)
+    end
+end
+
+function Base.eachindex(grid::EquidistantGrid)
+    CartesianIndices(grid.size)
+end
+
+# Returns the number of dimensions of an EquidistantGrid.
+#
+# @Input: grid - an EquidistantGrid
+# @Return: dimension - The dimension of the grid
+function dimension(grid::EquidistantGrid)
+    return length(grid.size)
+end
+
+# Returns the spacing of the grid
+#
+function spacing(grid::EquidistantGrid)
+    return 1.0./grid.inverse_spacing
+end
+
+# Computes the points of an EquidistantGrid as an array of tuples with
+# the same dimension as the grid.
+#
+# @Input: grid - an EquidistantGrid
+# @Return: points - the points of the grid.
+function points(grid::EquidistantGrid)
+    # TODO: Make this return an abstract array?
+    indices = Tuple.(CartesianIndices(grid.size))
+    h = spacing(grid)
+    return broadcast(I -> grid.limit_lower .+ (I.-1).*h, indices)
+end
+
+function pointsalongdim(grid::EquidistantGrid, dim::Integer)
+    @assert dim<=dimension(grid)
+    @assert dim>0
+    points = collect(range(grid.limit_lower[dim],stop=grid.limit_upper[dim],length=grid.size[dim]))
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Grids/src/Grids.jl	Wed Jun 26 10:44:20 2019 +0200
@@ -0,0 +1,11 @@
+module Grids
+
+abstract type BoundaryIdentifier end
+struct CartesianBoundary{Dim, R<:Region} <: BoundaryIdentifier end
+dim(::CartesianBoundary{Dim, R}) where {Dim, R} = Dim
+region(::CartesianBoundary{Dim, R}) where {Dim, R} = R
+
+include("AbstractGrid.jl")
+include("EquidistantGrid.jl")
+
+end # module
--- a/Manifest.toml	Tue Jun 25 17:26:39 2019 +0200
+++ b/Manifest.toml	Wed Jun 26 10:44:20 2019 +0200
@@ -1,5 +1,15 @@
 # This file is machine-generated - editing it directly is not advised
 
+[[DiffOps]]
+path = "DiffOps"
+uuid = "39474f48-97ec-11e9-01fc-6ddcbe5918df"
+version = "0.1.0"
+
+[[Grids]]
+path = "Grids"
+uuid = "960fdf28-97ed-11e9-2a74-bd90bf2fab5a"
+version = "0.1.0"
+
 [[LazyTensors]]
 path = "LazyTensors"
 uuid = "62fbed2c-918d-11e9-279b-eb3a325b37d3"
--- a/Project.toml	Tue Jun 25 17:26:39 2019 +0200
+++ b/Project.toml	Wed Jun 26 10:44:20 2019 +0200
@@ -1,2 +1,4 @@
 [deps]
+DiffOps = "39474f48-97ec-11e9-01fc-6ddcbe5918df"
+Grids = "960fdf28-97ed-11e9-2a74-bd90bf2fab5a"
 LazyTensors = "62fbed2c-918d-11e9-279b-eb3a325b37d3"
--- a/diffOp.jl	Tue Jun 25 17:26:39 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,220 +0,0 @@
-abstract type DiffOp end
-
-# 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
-
-function innerProduct(D::DiffOp, u::AbstractVector, v::AbstractVector)::Real
-    error("not implemented")
-end
-
-function matrixRepresentation(D::DiffOp)
-    error("not implemented")
-end
-
-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))
-    # TODO: Pass Tilesize to function
-    for tileaxs ∈ TileIterator(axes(ri), padded_tilesize(T, (5,5), 2))
-        for j ∈ tileaxs[2], i ∈ tileaxs[1]
-            I = ri[i,j]
-            u[I] = 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 NormalDerivative{N,M,K}
-	op::D2{Float64,N,M,K}
-	grid::EquidistantGrid
-	bId::CartesianBoundary
-end
-
-function apply_transpose(d::NormalDerivative, v::AbstractArray, I::Integer)
-	u = selectdim(v,3-dim(d.bId),I)
-	return apply_d(d.op, d.grid.inverse_spacing[dim(d.bId)], u, region(d.bId))
-end
-
-# Not correct abstraction level
-# TODO: Not type stable D:<
-function apply(d::NormalDerivative, v::AbstractArray, I::Tuple{Integer,Integer})
-	i = I[dim(d.bId)]
-	j = I[3-dim(d.bId)]
-	N_i = d.grid.size[dim(d.bId)]
-
-	r = getregion(i, closureSize(d.op), N_i)
-
-	if r != region(d.bId)
-		return 0
-	end
-
-	if r == Lower
-		# Note, closures are indexed by offset. Fix this D:<
-		return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[i-1]*v[j]
-	elseif r == Upper
-		return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[N_i-j]*v[j]
-	end
-end
-
-struct BoundaryValue{N,M,K}
-	op::D2{Float64,N,M,K}
-	grid::EquidistantGrid
-	bId::CartesianBoundary
-end
-
-function apply(e::BoundaryValue, v::AbstractArray, I::Tuple{Integer,Integer})
-	i = I[dim(e.bId)]
-	j = I[3-dim(e.bId)]
-	N_i = e.grid.size[dim(e.bId)]
-
-	r = getregion(i, closureSize(e.op), N_i)
-
-	if r != region(e.bId)
-		return 0
-	end
-
-	if r == Lower
-		# Note, closures are indexed by offset. Fix this D:<
-		return e.op.eClosure[i-1]*v[j]
-	elseif r == Upper
-		return e.op.eClosure[N_i-j]*v[j]
-	end
-end
-
-function apply_transpose(e::BoundaryValue, v::AbstractArray, I::Integer)
-	u = selectdim(v,3-dim(e.bId),I)
-	return apply_e(e.op, u, region(e.bId))
-end
-
-struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim}
-    grid::EquidistantGrid{Dim,T}
-    a::T
-    op::D2{Float64,N,M,K}
-    e::BoundaryValue
-    d::NormalDerivative
-end
-
-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{1}, v::AbstractVector, i::Int)
-    uᵢ = L.a * apply(L.op, L.grid.spacing[1], v, i)
-    return uᵢ
-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
-
-# 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
-
-struct BoundaryOperator
-
-end
-
-
-"""
-A BoundaryCondition should implement the method
-    sat(::DiffOp, v::AbstractArray, data::AbstractArray, ...)
-"""
-abstract type BoundaryCondition end
-
-struct Neumann{Bid<:BoundaryIdentifier} <: BoundaryCondition end
-
-function sat(L::Laplace{2,T}, bc::Neumann{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, I::CartesianIndex{2}) where {T,Bid}
-    e = BoundaryValue(L.op, L.grid, Bid())
-    d = NormalDerivative(L.op, L.grid, Bid())
-    Hᵧ = BoundaryQuadrature(L.op, L.grid, Bid())
-    # TODO: Implement BoundaryQuadrature method
-
-    return -L.Hi*e*Hᵧ*(d'*v - g)
-    # Need to handle d'*v - g so that it is an AbstractArray that TensorMappings can act on
-end
-
-struct Dirichlet{Bid<:BoundaryIdentifier} <: BoundaryCondition
-    tau::Float64
-end
-
-function sat(L::Laplace{2,T}, bc::Dirichlet{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, i::CartesianIndex{2}) where {T,Bid}
-    e = BoundaryValue(L.op, L.grid, Bid())
-    d = NormalDerivative(L.op, L.grid, Bid())
-    Hᵧ = BoundaryQuadrature(L.op, L.grid, Bid())
-    # TODO: Implement BoundaryQuadrature method
-
-    return -L.Hi*(tau/h*e + d)*Hᵧ*(e'*v - g)
-    # Need to handle scalar multiplication and addition of TensorMapping
-end
-
-# function apply(s::MyWaveEq{D},  v::AbstractArray{T,D}, i::CartesianIndex{D}) where D
-# 	return apply(s.L, v, i) +
-# 		sat(s.L, Dirichlet{CartesianBoundary{1,Lower}}(s.tau),  v, s.g_w, i) +
-# 		sat(s.L, Dirichlet{CartesianBoundary{1,Upper}}(s.tau),  v, s.g_e, i) +
-# 		sat(s.L, Dirichlet{CartesianBoundary{2,Lower}}(s.tau),  v, s.g_s, i) +
-# 		sat(s.L, Dirichlet{CartesianBoundary{2,Upper}}(s.tau),  v, s.g_n, i)
-# end
--- a/sbp.jl	Tue Jun 25 17:26:39 2019 +0200
+++ b/sbp.jl	Wed Jun 26 10:44:20 2019 +0200
@@ -1,8 +1,6 @@
 module sbp
 include("index.jl")
-include("grid.jl")
 include("stencil.jl")
 include("sbpD2.jl")
-include("diffOp.jl")
 include("TimeStepper.jl")
 end  # module