Skip to content

Commit

Permalink
Merge pull request #26 from kylebeggs/feature/virtual
Browse files Browse the repository at this point in the history
Feature/virtual
  • Loading branch information
kylebeggs authored Jul 17, 2024
2 parents 56a7811 + 4a96b39 commit 5ca0c01
Show file tree
Hide file tree
Showing 20 changed files with 280 additions and 104 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "RadialBasisFunctions"
uuid = "79ee0514-adf7-4479-8807-6f72ea8967e8"
authors = ["Kyle Beggs"]
version = "0.2.1"
version = "0.2.2"

[deps]
ChunkSplitters = "ae650224-84b6-46f8-82ea-d812ca08434e"
Expand Down
4 changes: 2 additions & 2 deletions docs/src/api.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Exported Functions
## Exported Functions

```@autodocs
Modules = [RadialBasisFunctions]
Private = false
Order = [:function, :type]
```

# Private
## Private

```@autodocs
Modules = [RadialBasisFunctions]
Expand Down
2 changes: 1 addition & 1 deletion docs/src/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ abs.(y_true .- y_new)
This package also provides an API for operators. There is support for several built-in operators along with support for user-defined operators. Currently, we have implementations for

- partial derivative (1st and 2nd order)
- gradient
- laplacian
- gradient

but we plan to add more in the future. Please make and issue or pull request for additional operators.

Expand Down
5 changes: 4 additions & 1 deletion src/RadialBasisFunctions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export find_neighbors, reorder_points!
include("linalg/stencil.jl")

include("operators/operators.jl")
export RadialBasisOperator
export RadialBasisOperator, update_weights!

include("operators/partial.jl")
export Partial, partial
Expand All @@ -37,6 +37,9 @@ export Gradient, gradient
include("operators/directional.jl")
export Directional, directional

include("operators/virtual.jl")
export ∂virtual

include("operators/monomial.jl")

include("operators/operator_combinations.jl")
Expand Down
29 changes: 19 additions & 10 deletions src/linalg/stencil.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
function _build_weights(ℒ, op; nchunks=Threads.nthreads())
data = op.data
basis = op.basis
dim = length(first(data)) # dimension of data

# build monomial basis and operator
mon = MonomialBasis(dim, basis.poly_deg)
ℒmon = (mon)
ℒrbf = (basis)

return _build_weights(op, ℒrbf, ℒmon, mon; nchunks=nchunks)
end

function _build_weights(op, ℒrbf, ℒmon, mon; nchunks=Threads.nthreads())
data = op.data
eval_points = op.eval_points
adjl = op.adjl
basis = op.basis

TD = eltype(first(data))
dim = length(first(data)) # dimension of data
nmon = binomial(dim + basis.poly_deg, basis.poly_deg)
k = length(first(adjl)) # number of data in influence/support domain
sizes = (k, nmon)

# build monomial basis and operator
mon = MonomialBasis(dim, basis.poly_deg)
ℒmon = (mon)
ℒrbf = (basis)

# allocate arrays to build sparse matrix
Na = length(adjl)
I = zeros(Int, k * Na)
Expand Down Expand Up @@ -45,12 +54,12 @@ function _build_stencil!(
b::Vector,
ℒrbf,
ℒmon,
data::AbstractVector{D},
eval_point::D,
data::AbstractVector{TD},
eval_point::TE,
basis::B,
mon::MonomialBasis,
k::Int,
) where {D<:AbstractArray,B<:AbstractRadialBasis}
) where {TD,TE,B<:AbstractRadialBasis}
_build_collocation_matrix!(A, data, basis, mon, k)
_build_rhs!(b, ℒrbf, ℒmon, data, eval_point, basis, k)
return (A \ b)[1:k]
Expand All @@ -75,8 +84,8 @@ function _build_collocation_matrix!(
end

function _build_rhs!(
b::AbstractVector, ℒrbf, ℒmon, data::AbstractVector{D}, eval_point::D, basis::B, k::K
) where {D<:AbstractArray,B<:AbstractRadialBasis,K<:Int}
b::AbstractVector, ℒrbf, ℒmon, data::AbstractVector{TD}, eval_point::TE, basis::B, k::K
) where {TD,TE,B<:AbstractRadialBasis,K<:Int}
# radial basis section
@inbounds for i in eachindex(data)
b[i] = ℒrbf(eval_point, data[i])
Expand Down
58 changes: 43 additions & 15 deletions src/operators/directional.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""
Directional <: VectorValuedOperator
Directional <: ScalarValuedOperator
Operator for the directional derivative, or the inner product of the gradient and a direction vector.
"""
struct Directional{L<:NTuple,T} <: VectorValuedOperator
struct Directional{L<:NTuple,T} <: ScalarValuedOperator
::L
v::T
end
Expand All @@ -18,14 +18,15 @@ function directional(
v::AbstractVector,
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, k),
) where {D<:AbstractArray,B<:AbstractRadialBasis,T<:Int}
f = ntuple(length(first(data))) do dim
return let dim = dim
x -> (x, 1, dim)
end
end
= Directional(f, v)
return RadialBasisOperator(ℒ, data, basis; k=k)
return RadialBasisOperator(ℒ, data, basis; k=k, adjl=adjl)
end

"""
Expand All @@ -34,41 +35,68 @@ end
Builds a `RadialBasisOperator` where the operator is the directional derivative, `Directional`.
"""
function directional(
data::AbstractVector{D},
eval_points::AbstractVector{D},
data::AbstractVector,
eval_points::AbstractVector,
v::AbstractVector,
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
) where {D<:AbstractArray,B<:AbstractRadialBasis,T<:Int}
adjl=find_neighbors(data, eval_points, k),
) where {B<:AbstractRadialBasis,T<:Int}
f = ntuple(length(first(data))) do dim
return let dim = dim
x -> (x, 1, dim)
end
end
= Directional(f, v)
return RadialBasisOperator(ℒ, data, eval_points, basis; k=k)
return RadialBasisOperator(ℒ, data, eval_points, basis; k=k, adjl=adjl)
end

function RadialBasisOperator(
::Directional,
data::AbstractVector{D},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, k),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
Na = length(adjl)
Nd = length(data)
weights = spzeros(eltype(D), Na, Nd)
return RadialBasisOperator(ℒ, weights, data, data, adjl, basis)
end

function RadialBasisOperator(
::Directional,
data::AbstractVector{TD},
eval_points::AbstractVector{TE},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, eval_points, k),
) where {TD,TE,T<:Int,B<:AbstractRadialBasis}
Na = length(adjl)
Nd = length(data)
weights = spzeros(eltype(TD), Na, Nd)
return RadialBasisOperator(ℒ, weights, data, eval_points, adjl, basis)
end

function _update_weights!(
op::RadialBasisOperator{<:Directional}, weights::NTuple{N,AbstractMatrix}
) where {N}
function update_weights!(op::RadialBasisOperator{<:Directional})
v = op..v
N = length(first(op.data))
@assert length(v) == N || length(v) == size(op)[1] "wrong size for v"
if length(v) == N
for (i, ℒ) in enumerate(op..ℒ)
weights[i] .= _build_weights(ℒ, op) * v[i]
op.weights .= mapreduce(+, enumerate(op..ℒ)) do (i, ℒ)
_build_weights(ℒ, op) * v[i]
end
else
vv = ntuple(i -> getindex.(v, i), N)
for (i, ℒ) in enumerate(op..ℒ)
weights[i] .= Diagonal(vv[i]) * _build_weights(ℒ, op)
op.weights .= mapreduce(+, enumerate(op..ℒ)) do (i, ℒ)
Diagonal(vv[i]) * _build_weights(ℒ, op)
end
end
validate_cache(op)
return nothing
end

Base.size(op::RadialBasisOperator{<:Directional}) = size(first(op.weights))
Base.size(op::RadialBasisOperator{<:Directional}) = size(op.weights)

# pretty printing
print_op(op::Directional) = "Directional Gradient (∇f⋅v)"
16 changes: 10 additions & 6 deletions src/operators/gradient.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@ end
Builds a `RadialBasisOperator` where the operator is the gradient, `Gradient`.
"""
function gradient(
data::AbstractVector{D}, basis::B=PHS(3; poly_deg=2); k::T=autoselect_k(data, basis)
data::AbstractVector{D},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, k),
) where {D<:AbstractArray,B<:AbstractRadialBasis,T<:Int}
f = ntuple(length(first(data))) do dim
return let dim = dim
x -> (x, 1, dim)
end
end
= Gradient(f)
return RadialBasisOperator(ℒ, data, basis; k=k)
return RadialBasisOperator(ℒ, data, basis; k=k, adjl=adjl)
end

"""
Expand All @@ -31,18 +34,19 @@ end
Builds a `RadialBasisOperator` where the operator is the gradient, `Gradient`. The resulting operator will only evaluate at `eval_points`.
"""
function gradient(
data::AbstractVector{D},
eval_points::AbstractVector{D},
data::AbstractVector,
eval_points::AbstractVector,
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
) where {D<:AbstractArray,B<:AbstractRadialBasis,T<:Int}
adjl=find_neighbors(data, eval_points, k),
) where {B<:AbstractRadialBasis,T<:Int}
f = ntuple(length(first(data))) do dim
return let dim = dim
x -> (x, 1, dim)
end
end
= Gradient(f)
return RadialBasisOperator(ℒ, data, eval_points, basis; k=k)
return RadialBasisOperator(ℒ, data, eval_points, basis; k=k, adjl=adjl)
end

Base.size(op::RadialBasisOperator{<:Gradient}) = size(first(op.weights))
Expand Down
16 changes: 10 additions & 6 deletions src/operators/laplacian.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ end

# convienience constructors
function laplacian(
data::AbstractVector{D}, basis::B=PHS(3; poly_deg=2); k::T=autoselect_k(data, basis)
data::AbstractVector{D},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, k),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
= Laplacian(∇²)
return RadialBasisOperator(ℒ, data, basis; k=k)
return RadialBasisOperator(ℒ, data, basis; k=k, adjl=adjl)
end

function laplacian(
data::AbstractVector{D},
eval_points::AbstractVector{D},
data::AbstractVector,
eval_points::AbstractVector,
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
adjl=find_neighbors(data, eval_points, k),
) where {T<:Int,B<:AbstractRadialBasis}
= Laplacian(∇²)
return RadialBasisOperator(ℒ, data, eval_points, basis; k=k)
return RadialBasisOperator(ℒ, data, eval_points, basis; k=k, adjl=adjl)
end

# pretty printing
Expand Down
2 changes: 1 addition & 1 deletion src/operators/operator_combinations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ for op in (:+, :-, :*, :/)
k2 = length(first((op2.adjl)))
k = k1 > k2 ? k1 : k2
= Base.$op(op1.ℒ, op2.ℒ)
return RadialBasisOperator(ℒ, op1.data, op1.basis; k=k)
return RadialBasisOperator(ℒ, op1.data, op1.basis; k=k, adjl=op1.adjl)
end
end

Expand Down
30 changes: 16 additions & 14 deletions src/operators/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ end

# convienience constructors
function RadialBasisOperator(
ℒ, data::AbstractVector{D}, basis::B=PHS(3; poly_deg=2); k::T=autoselect_k(data, basis)
ℒ,
data::AbstractVector{D},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, k),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
adjl = find_neighbors(data, k)
Na = length(adjl)
Nd = length(data)
weights = spzeros(eltype(D), Na, Nd)
Expand All @@ -35,15 +38,15 @@ end

function RadialBasisOperator(
ℒ,
data::AbstractVector{D},
eval_points::AbstractVector{D},
data::AbstractVector{TD},
eval_points::AbstractVector{TE},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
adjl = find_neighbors(data, eval_points, k)
adjl=find_neighbors(data, eval_points, k),
) where {TD,TE,T<:Int,B<:AbstractRadialBasis}
Na = length(adjl)
Nd = length(data)
weights = spzeros(eltype(D), Na, Nd)
weights = spzeros(eltype(TD), Na, Nd)
return RadialBasisOperator(ℒ, weights, data, eval_points, adjl, basis)
end

Expand All @@ -52,26 +55,25 @@ function RadialBasisOperator(
data::AbstractVector{D},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
adjl=find_neighbors(data, k),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
TD = eltype(D)
adjl = find_neighbors(data, k)
N = length(adjl)
weights = ntuple(_ -> _allocate_weights(TD, N, N, k), length(ℒ.ℒ))
return RadialBasisOperator(ℒ, weights, data, data, adjl, basis)
end

function RadialBasisOperator(
::VectorValuedOperator,
data::AbstractVector{D},
eval_points::AbstractVector{D},
data::AbstractVector{TD},
eval_points::AbstractVector{TE},
basis::B=PHS(3; poly_deg=2);
k::T=autoselect_k(data, basis),
) where {D<:AbstractArray,T<:Int,B<:AbstractRadialBasis}
TD = eltype(D)
adjl = find_neighbors(data, eval_points, k)
adjl=find_neighbors(data, eval_points, k),
) where {TD,TE,T<:Int,B<:AbstractRadialBasis}
Na = length(adjl)
Nd = length(data)
weights = ntuple(_ -> _allocate_weights(TD, Na, Nd, k), length(ℒ.ℒ))
weights = ntuple(_ -> _allocate_weights(eltype(TD), Na, Nd, k), length(ℒ.ℒ))
return RadialBasisOperator(ℒ, weights, data, eval_points, adjl, basis)
end

Expand Down
Loading

2 comments on commit 5ca0c01

@kylebeggs
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/111196

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.2.2 -m "<description of version>" 5ca0c01599f7bcc0f6bab5f1a9a51d15abf28266
git push origin v0.2.2

Please sign in to comment.