Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/Documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Documentation

on:
push:
branches:
- main # update to match your development branch (master, main, dev, trunk, ...)
tags: '*'
pull_request:

jobs:
build:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: julia-actions/cache@v2
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: '1.12'
- uses: julia-actions/julia-buildpkg@v1
- name: Install dependencies
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # If authenticating with GitHub Actions token
run: julia --color=yes --project=docs/ docs/make.jl
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Manifest.toml
docs/build
3 changes: 3 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
TabularFunctions = "7add9882-6fce-4afb-882d-af036a41bc9c"
40 changes: 40 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Documenter
using TabularFunctions

DocMeta.setdocmeta!(TabularFunctions, :DocTestSetup, :(using TabularFunctions); recursive=true)
# meshes_ext = Base.get_extension(Exodus, :ExodusMeshesExt)
# unitful_ext = Base.get_extension(Exodus, :ExodusUnitfulExt)
makedocs(;
# modules=[Exodus, meshes_ext, unitful_ext],
modules=[TabularFunctions],
authors="Craig M. Hamel <[email protected]> and contributors",
repo="https://github.com/cthonios/TabularFunctions.jl/blob/{commit}{path}#{line}",
sitename="TabularFunctions.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
canonical="https://cthonios.github.io/TabularFunctions.jl/stable",
edit_link="main",
assets=String[],
size_threshold=nothing
),
pages=[
# "Exodus" => "index.md",
# "Installation" => "installation.md",
# "Opening Files" => "opening_files.md",
# "Reading Data" => "reading_data.md",
# "Writing Data" => "writing_data.md",
# "Use With MPI" => "use_with_mpi.md",
# "Exodus Methods" => "methods.md",
# "Exodus Types" => "types.md",
# "ExodusMeshesExt" => "meshes_ext.md",
# "ExodusUnitfulExt" => "unitful_ext.md",
# "Glossary" => "glossary.md"
# "README" => "../README.md"
"TabularFunctions" => "index.md"
],
)

deploydocs(;
repo="github.com/cthonios/TabularFunctions.jl",
devbranch="main"
)
145 changes: 145 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# TabularFunctions.jl

## Description
This is a small package to help define julia functions via
either tabular data, e.g. (x, y) pairs, or tables of functions
to aid in simply writing piecewise analytic functions.

## Installation
Currently ```TabularFunctions.jl``` has not been registered. To install, one
can do the following in the package manager
```julia
pkg> add https://github.com/Cthonios/TabularFunctions.jl/
```

## Future installation instructions
From the package manager simply type
```julia
pkg> add TabularFunctions
```

Or from the REPL
```julia
julia> using Pkg
julia> Pkg.add("TabularFunctions")
```

# Examples

## PiecewiseAnalyticFunction
Suppose we like to define a piecewise analytic function such that
$$
f(x) =
\begin{cases}
x, & \text{if } x < 1 \\
x^2, & \text{if } x \ge 1
\end{cases}
$$

then we can use the maco ```@piecewise_analytic``` to define the above function as follows

```jldoctest analytic
using TabularFunctions
func = @piecewise_analytic begin
0.0, x -> x
1.0, x -> x^2
end;
nothing
# output

```

and this can be used like a regular julia function as follows
```jldoctest analytic
x = 0.5
y = func(x)

# output
0.5
```

```jldoctest analytic
x = 1.5
y = func(x)

# output
2.25
```

Note that closures are not necessary in the macro definition. The following is also valid syntax for the ```@piecewise_analytic``` macro
```jldoctest; output=false
using TabularFunctions
func = @piecewise_analytic begin
0.0, sin
1.0, cos
end
nothing

# output

```

## PiecewiseLinearFunction
If instead you need to define a function simply from sparse tabular data, you can use the ```@piecewise_linear``` macro. This creates a simple function that will exactly reproduce values at the supplied points and linearly interpolate when provided with values between those points. If the provided input lies outside the bounds, the lower or upper bound is returned respectively. An example of a triangle wave is shown below

```jldoctest linear
using TabularFunctions
func = @piecewise_linear begin
0.0, 0.0
0.5, 1.0
1.0, 0.0
end
nothing

# output

```

```jldoctest linear
x = -1.0
y = func(x)
# output
0.0
```
```jldoctest linear
x = 0.0
y = func(x)
# output
0.0
```
```jldoctest linear
x = 0.25
y = func(x)
# output
0.5
```
```jldoctest linear
x = 0.5
y = func(x)
# output
1.0
```
```jldoctest linear
x = 0.75
y = func(x)
# output
0.5
```
```jldoctest linear
x = 1.0
y = func(x)
# output
0.0
```
```jldoctest linear
x = 2.0
y = func(x)
# output
0.0
```

# Reference
```@autodocs
Modules = [TabularFunctions]
Order = [:module, :type, :function, :macro]
```
64 changes: 62 additions & 2 deletions src/TabularFunctions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ using DocStringExtensions
using KernelAbstractions

# Error helpers
"""
$(TYPEDEF)
$(TYPEDFIELDS)
"""
struct XsNotMonotonicallyIncreasing <: Exception
end

Expand All @@ -22,24 +26,35 @@ function _monotonic_error()
end

# Abstract types
"""
$(TYPEDEF)
"""
abstract type AbstractTabularFunction{
V <: AbstractVector{<:Number}
} end


"""
$(TYPEDSIGNATURES)
"""
function KernelAbstractions.get_backend(f::AbstractTabularFunction)
return get_backend(f.x_vals)
end

"""
$(TYPEDEF)
$(TYPEDFIELDS)
"""
struct PiecewiseAnalyticFunction{
V <: AbstractVector{<:Number},
# Funcs <: NamedTuple
Funcs
} <: AbstractTabularFunction{V}
x_vals::V
funcs::Funcs
end

"""
$(TYPEDSIGNATURES)
"""
function PiecewiseAnalyticFunction(
xs::V, funcs::Funcs
) where {
Expand All @@ -60,6 +75,9 @@ function PiecewiseAnalyticFunction(
return PiecewiseAnalyticFunction(xs, funcs)
end

"""
$(TYPEDSIGNATURES)
"""
function Adapt.adapt_structure(to, func::PiecewiseAnalyticFunction)
return PiecewiseAnalyticFunction(
adapt(to, func.x_vals),
Expand All @@ -78,6 +96,9 @@ function _func(func::PiecewiseAnalyticFunction, x, ::CPU)
end
end

"""
$(TYPEDSIGNATURES)
"""
function (func::PiecewiseAnalyticFunction{V1, Funcs})(x::T) where {
T <: Number,
V1 <: AbstractVector{T},
Expand All @@ -87,6 +108,10 @@ function (func::PiecewiseAnalyticFunction{V1, Funcs})(x::T) where {
end

# Piecewise Linear
"""
$(TYPEDEF)
$(TYPEDFIELDS)
"""
struct PiecewiseLinearFunction{
V1 <: AbstractVector{<:Number},
V2 <: AbstractVector{<:Number}
Expand All @@ -113,6 +138,9 @@ struct PiecewiseLinearFunction{
end
end

"""
$(TYPEDSIGNATURES)
"""
function Adapt.adapt_structure(to, f::PiecewiseLinearFunction)
return PiecewiseLinearFunction(
adapt(to, f.x_vals),
Expand Down Expand Up @@ -154,6 +182,9 @@ function _func(func, x, ::Backend)
# kernel!(func, x, ndrange = length(func.x_vals) + 1)
end

"""
$(TYPEDSIGNATURES)
"""
function (func::PiecewiseLinearFunction{V1, V2})(x::T) where {
T <: Number,
V1 <: AbstractVector{T},
Expand All @@ -172,6 +203,23 @@ function _is_number_expr(ex)
return ex isa Number
end

"""
$(TYPEDSIGNATURES)
Example:
Define a function that switches between a linear and quadratic function
```jldoctest
func = @piecewise_analytic begin
0.0, x -> x
1.0, x -> x^2
end

func(0.)

# output
0.0

```
"""
macro piecewise_analytic(expr)
# Extract expressions inside the block
lines = expr isa Expr && expr.head == :block ? expr.args : [expr]
Expand Down Expand Up @@ -204,6 +252,18 @@ macro piecewise_analytic(expr)
# end
end

"""
$(TYPEDSIGNATURES)
Example:
Define a triangular wave of a single period
```julia
func = @piecewise_linear begin
0.0, 0.0
0.5, 1.0
1.0, 0.0
end
```
"""
macro piecewise_linear(expr)
# Get the expressions inside the block
pairs = expr isa Expr && expr.head == :block ? expr.args : [expr]
Expand Down