Mercurial > repos > public > sbplib_julia
comparison DiffOps/src/DiffOps.jl @ 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 | diffOp.jl@bcd2029c590d |
| children | 3a93d8a799ce |
comparison
equal
deleted
inserted
replaced
| 210:2aa33d0eef90 | 211:1ad91e11b1f4 |
|---|---|
| 1 abstract type DiffOp end | |
| 2 | |
| 3 # 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? | |
| 4 function apply(D::DiffOp, v::AbstractVector, i::Int) | |
| 5 error("not implemented") | |
| 6 end | |
| 7 | |
| 8 function innerProduct(D::DiffOp, u::AbstractVector, v::AbstractVector)::Real | |
| 9 error("not implemented") | |
| 10 end | |
| 11 | |
| 12 function matrixRepresentation(D::DiffOp) | |
| 13 error("not implemented") | |
| 14 end | |
| 15 | |
| 16 abstract type DiffOpCartesian{Dim} <: DiffOp end | |
| 17 | |
| 18 # DiffOp must have a grid of dimension Dim!!! | |
| 19 function apply!(D::DiffOpCartesian{Dim}, u::AbstractArray{T,Dim}, v::AbstractArray{T,Dim}) where {T,Dim} | |
| 20 for I ∈ eachindex(D.grid) | |
| 21 u[I] = apply(D, v, I) | |
| 22 end | |
| 23 | |
| 24 return nothing | |
| 25 end | |
| 26 | |
| 27 function apply_region!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}) where T | |
| 28 apply_region!(D, u, v, Lower, Lower) | |
| 29 apply_region!(D, u, v, Lower, Interior) | |
| 30 apply_region!(D, u, v, Lower, Upper) | |
| 31 apply_region!(D, u, v, Interior, Lower) | |
| 32 apply_region!(D, u, v, Interior, Interior) | |
| 33 apply_region!(D, u, v, Interior, Upper) | |
| 34 apply_region!(D, u, v, Upper, Lower) | |
| 35 apply_region!(D, u, v, Upper, Interior) | |
| 36 apply_region!(D, u, v, Upper, Upper) | |
| 37 return nothing | |
| 38 end | |
| 39 | |
| 40 # Maybe this should be split according to b3fbef345810 after all?! Seems like it makes performance more predictable | |
| 41 function apply_region!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}, r1::Type{<:Region}, r2::Type{<:Region}) where T | |
| 42 for I ∈ regionindices(D.grid.size, closureSize(D.op), (r1,r2)) | |
| 43 @inbounds indextuple = (Index{r1}(I[1]), Index{r2}(I[2])) | |
| 44 @inbounds u[I] = apply(D, v, indextuple) | |
| 45 end | |
| 46 return nothing | |
| 47 end | |
| 48 | |
| 49 function apply_tiled!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}) where T | |
| 50 apply_region_tiled!(D, u, v, Lower, Lower) | |
| 51 apply_region_tiled!(D, u, v, Lower, Interior) | |
| 52 apply_region_tiled!(D, u, v, Lower, Upper) | |
| 53 apply_region_tiled!(D, u, v, Interior, Lower) | |
| 54 apply_region_tiled!(D, u, v, Interior, Interior) | |
| 55 apply_region_tiled!(D, u, v, Interior, Upper) | |
| 56 apply_region_tiled!(D, u, v, Upper, Lower) | |
| 57 apply_region_tiled!(D, u, v, Upper, Interior) | |
| 58 apply_region_tiled!(D, u, v, Upper, Upper) | |
| 59 return nothing | |
| 60 end | |
| 61 | |
| 62 using TiledIteration | |
| 63 function apply_region_tiled!(D::DiffOpCartesian{2}, u::AbstractArray{T,2}, v::AbstractArray{T,2}, r1::Type{<:Region}, r2::Type{<:Region}) where T | |
| 64 ri = regionindices(D.grid.size, closureSize(D.op), (r1,r2)) | |
| 65 # TODO: Pass Tilesize to function | |
| 66 for tileaxs ∈ TileIterator(axes(ri), padded_tilesize(T, (5,5), 2)) | |
| 67 for j ∈ tileaxs[2], i ∈ tileaxs[1] | |
| 68 I = ri[i,j] | |
| 69 u[I] = apply(D, v, (Index{r1}(I[1]), Index{r2}(I[2]))) | |
| 70 end | |
| 71 end | |
| 72 return nothing | |
| 73 end | |
| 74 | |
| 75 function apply(D::DiffOp, v::AbstractVector)::AbstractVector | |
| 76 u = zeros(eltype(v), size(v)) | |
| 77 apply!(D,v,u) | |
| 78 return u | |
| 79 end | |
| 80 | |
| 81 struct NormalDerivative{N,M,K} | |
| 82 op::D2{Float64,N,M,K} | |
| 83 grid::EquidistantGrid | |
| 84 bId::CartesianBoundary | |
| 85 end | |
| 86 | |
| 87 function apply_transpose(d::NormalDerivative, v::AbstractArray, I::Integer) | |
| 88 u = selectdim(v,3-dim(d.bId),I) | |
| 89 return apply_d(d.op, d.grid.inverse_spacing[dim(d.bId)], u, region(d.bId)) | |
| 90 end | |
| 91 | |
| 92 # Not correct abstraction level | |
| 93 # TODO: Not type stable D:< | |
| 94 function apply(d::NormalDerivative, v::AbstractArray, I::Tuple{Integer,Integer}) | |
| 95 i = I[dim(d.bId)] | |
| 96 j = I[3-dim(d.bId)] | |
| 97 N_i = d.grid.size[dim(d.bId)] | |
| 98 | |
| 99 r = getregion(i, closureSize(d.op), N_i) | |
| 100 | |
| 101 if r != region(d.bId) | |
| 102 return 0 | |
| 103 end | |
| 104 | |
| 105 if r == Lower | |
| 106 # Note, closures are indexed by offset. Fix this D:< | |
| 107 return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[i-1]*v[j] | |
| 108 elseif r == Upper | |
| 109 return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[N_i-j]*v[j] | |
| 110 end | |
| 111 end | |
| 112 | |
| 113 struct BoundaryValue{N,M,K} | |
| 114 op::D2{Float64,N,M,K} | |
| 115 grid::EquidistantGrid | |
| 116 bId::CartesianBoundary | |
| 117 end | |
| 118 | |
| 119 function apply(e::BoundaryValue, v::AbstractArray, I::Tuple{Integer,Integer}) | |
| 120 i = I[dim(e.bId)] | |
| 121 j = I[3-dim(e.bId)] | |
| 122 N_i = e.grid.size[dim(e.bId)] | |
| 123 | |
| 124 r = getregion(i, closureSize(e.op), N_i) | |
| 125 | |
| 126 if r != region(e.bId) | |
| 127 return 0 | |
| 128 end | |
| 129 | |
| 130 if r == Lower | |
| 131 # Note, closures are indexed by offset. Fix this D:< | |
| 132 return e.op.eClosure[i-1]*v[j] | |
| 133 elseif r == Upper | |
| 134 return e.op.eClosure[N_i-j]*v[j] | |
| 135 end | |
| 136 end | |
| 137 | |
| 138 function apply_transpose(e::BoundaryValue, v::AbstractArray, I::Integer) | |
| 139 u = selectdim(v,3-dim(e.bId),I) | |
| 140 return apply_e(e.op, u, region(e.bId)) | |
| 141 end | |
| 142 | |
| 143 struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim} | |
| 144 grid::EquidistantGrid{Dim,T} | |
| 145 a::T | |
| 146 op::D2{Float64,N,M,K} | |
| 147 e::BoundaryValue | |
| 148 d::NormalDerivative | |
| 149 end | |
| 150 | |
| 151 function apply(L::Laplace{Dim}, v::AbstractArray{T,Dim} where T, I::CartesianIndex{Dim}) where Dim | |
| 152 error("not implemented") | |
| 153 end | |
| 154 | |
| 155 # u = L*v | |
| 156 function apply(L::Laplace{1}, v::AbstractVector, i::Int) | |
| 157 uᵢ = L.a * apply(L.op, L.grid.spacing[1], v, i) | |
| 158 return uᵢ | |
| 159 end | |
| 160 | |
| 161 @inline function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, I::Tuple{Index{R1}, Index{R2}}) where {R1, R2} | |
| 162 # 2nd x-derivative | |
| 163 @inbounds vx = view(v, :, Int(I[2])) | |
| 164 @inbounds uᵢ = L.a*apply(L.op, L.grid.inverse_spacing[1], vx , I[1]) | |
| 165 # 2nd y-derivative | |
| 166 @inbounds vy = view(v, Int(I[1]), :) | |
| 167 @inbounds uᵢ += L.a*apply(L.op, L.grid.inverse_spacing[2], vy, I[2]) | |
| 168 return uᵢ | |
| 169 end | |
| 170 | |
| 171 # Slow but maybe convenient? | |
| 172 function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, i::CartesianIndex{2}) | |
| 173 I = Index{Unknown}.(Tuple(i)) | |
| 174 apply(L, v, I) | |
| 175 end | |
| 176 | |
| 177 struct BoundaryOperator | |
| 178 | |
| 179 end | |
| 180 | |
| 181 | |
| 182 """ | |
| 183 A BoundaryCondition should implement the method | |
| 184 sat(::DiffOp, v::AbstractArray, data::AbstractArray, ...) | |
| 185 """ | |
| 186 abstract type BoundaryCondition end | |
| 187 | |
| 188 struct Neumann{Bid<:BoundaryIdentifier} <: BoundaryCondition end | |
| 189 | |
| 190 function sat(L::Laplace{2,T}, bc::Neumann{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, I::CartesianIndex{2}) where {T,Bid} | |
| 191 e = BoundaryValue(L.op, L.grid, Bid()) | |
| 192 d = NormalDerivative(L.op, L.grid, Bid()) | |
| 193 Hᵧ = BoundaryQuadrature(L.op, L.grid, Bid()) | |
| 194 # TODO: Implement BoundaryQuadrature method | |
| 195 | |
| 196 return -L.Hi*e*Hᵧ*(d'*v - g) | |
| 197 # Need to handle d'*v - g so that it is an AbstractArray that TensorMappings can act on | |
| 198 end | |
| 199 | |
| 200 struct Dirichlet{Bid<:BoundaryIdentifier} <: BoundaryCondition | |
| 201 tau::Float64 | |
| 202 end | |
| 203 | |
| 204 function sat(L::Laplace{2,T}, bc::Dirichlet{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, i::CartesianIndex{2}) where {T,Bid} | |
| 205 e = BoundaryValue(L.op, L.grid, Bid()) | |
| 206 d = NormalDerivative(L.op, L.grid, Bid()) | |
| 207 Hᵧ = BoundaryQuadrature(L.op, L.grid, Bid()) | |
| 208 # TODO: Implement BoundaryQuadrature method | |
| 209 | |
| 210 return -L.Hi*(tau/h*e + d)*Hᵧ*(e'*v - g) | |
| 211 # Need to handle scalar multiplication and addition of TensorMapping | |
| 212 end | |
| 213 | |
| 214 # function apply(s::MyWaveEq{D}, v::AbstractArray{T,D}, i::CartesianIndex{D}) where D | |
| 215 # return apply(s.L, v, i) + | |
| 216 # sat(s.L, Dirichlet{CartesianBoundary{1,Lower}}(s.tau), v, s.g_w, i) + | |
| 217 # sat(s.L, Dirichlet{CartesianBoundary{1,Upper}}(s.tau), v, s.g_e, i) + | |
| 218 # sat(s.L, Dirichlet{CartesianBoundary{2,Lower}}(s.tau), v, s.g_s, i) + | |
| 219 # sat(s.L, Dirichlet{CartesianBoundary{2,Upper}}(s.tau), v, s.g_n, i) | |
| 220 # end |
