Skip to content

Commit

Permalink
modified: Project.toml 0.2.3
Browse files Browse the repository at this point in the history
modified:   README.md      Update
modified:   src/MechGlueDiffEqBase.jl similar, zero, precompile
modified:   test/test_4.jl    Test zero and similar inferrable
  • Loading branch information
hustf committed May 11, 2021
1 parent b26f560 commit fc2125f
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MechGlueDiffEqBase"
uuid = "2532746b-52b5-4539-9431-8bb183ab067f"
authors = ["hustf <[email protected]> and contributors"]
version = "0.2.2"
version = "0.2.3"

[deps]
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
Expand Down
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
# MechGlueDiffEqBase
Glue code for making [DiffEqBase](https://github.com/SciML/DiffEqBase.jl) work with units.

This defines how to calculate the vector norm when the vector is given in units compatible with [Unitfu.jl](https://github.com/hustf/Unitfu.jl), from registy [M8](https://github.com/hustf/M8). The differential equation algorithms expects the norm to be unitless, as can be seen in e.g. step size estimators:
This defines

It also used to include glue code for [RecursiveArrayTools](https://github.com/SciML/RecursiveArrayTools.jl), which enables type-stable solution of equations with mixed units. This may not be needed after a change to Unitfu.jl v1.7.7, but the depencency is kept until further upstream testing.
* how to calculate the vector norm 'ODE_DEFAULT_NORM' when the vector is given in units compatible with [Unitfu.jl](https://github.com/hustf/Unitfu.jl), from registy [M8](https://github.com/hustf/M8). The differential equation algorithms expects the norm to be unitless, as can be seen in e.g. step size estimators.

* type-stable and inferrable 'zero', 'value', 'UNITLESS_ABS2', 'similar'

These functions preserve types for mixed-unit vectors. E.g. [1.0kg, 2.0N, 3.0m/s, 4.0m/s].

This package also uses and reexports 'ArrayPartition' from [RecursiveArrayTools](https://github.com/SciML/RecursiveArrayTools.jl), which enables type-stable solution of equations with mixed units. It pre-compiles it with use of mixed unit vectors.


Note: The way error tolerances are defined is initially confusing, but good to know:

err_scaled = **error** / (**abstol** + norm(u) * **reltol**)

where **bold** indicates unitful objects.

The functions are adaptions of corresponding code from [DiffEqBase](https://github.com/SciML/DiffEqBase.jl/blob/6bb8830711e729ef513f2b1beb95853e4a691375/src/init.jl).
Some functions are adaptions of corresponding code from [DiffEqBase](https://github.com/SciML/DiffEqBase.jl/blob/6bb8830711e729ef513f2b1beb95853e4a691375/src/init.jl).
83 changes: 80 additions & 3 deletions src/MechGlueDiffEqBase.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
module MechGlueDiffEqBase
import Unitfu: AbstractQuantity, Quantity, ustrip, norm, unit
import DiffEqBase: value, ODE_DEFAULT_NORM, UNITLESS_ABS2, zero
import Base: similar
import Unitfu: AbstractQuantity, Quantity, ustrip, norm, unit, zero
import Unitfu: Dimensions, FreeUnits
import DiffEqBase: value, ODE_DEFAULT_NORM, UNITLESS_ABS2
import DiffEqBase: calculate_residuals, @muladd
using RecursiveArrayTools
export value, ODE_DEFAULT_NORM, UNITLESS_ABS2, Unitfu, AbstractQuantity, Quantity
export norm , ArrayPartition # Probably no longer necessary with changes in Unitfu 1.7.7. We could perhaps drop this depencency.
export norm , ArrayPartition, similar, zero

# This is identical to what DiffEqBase defines for Unitful
function value(x::Type{AbstractQuantity{T,D,U}}) where {T,D,U}
Expand Down Expand Up @@ -45,4 +47,79 @@ end
abs2(xul)::T
end

# Vectors with compatible units, treat as normal
zero(x::Vector{Quantity{T, D, U}}) where {T,D,U} = fill!(similar(x), zero(Quantity{T, D, U}))
# Vectors with incompatible units, special inferreable treatment
function zero(x::Vector{Q}) where {Q<:AbstractQuantity{T, D, U} where {D,U}} where T
x0 = copy(x)
for i in eachindex(x0)
x = x0[i]
x0[i] = 0 * x * sign(x)
end
x0
end

# Vectors with compatible units, treat as normal
similar(x::Vector{Quantity{T, D, U}}) where {T,D,U} = Vector{Quantity{T, D, U}}(undef, size(x,1))
#similar(a::Array{T,1}) where {T} = Vector{T}(undef, size(a,1))
# Vectors with incompatible units, special inferreable treatment
# VERY similar is still similar and (very slightly) different
similar(x::Vector{Q}) where {Q<:AbstractQuantity{T, D, U} where {D,U}} where T = copy(x)




# KISS pre-compillation to reduce loading times
# This is simply a boiled-down obfuscated test_4.jl
import Unitfu: m, s, kg, N,
let
r0ul = [1131.340, -2282.343, 6672.423]
r0ul = [1131.340, -2282.343, 6672.423]
v0ul = [-5.64305, 4.30333, 2.42879]
rv0ul = ArrayPartition(r0ul,v0ul)
ODE_DEFAULT_NORM(rv0ul, 0.0)
r0 = [1131.340, -2282.343, 6672.423]kg
v0 = [-5.64305, 4.30333, 2.42879]kg/s
rv0 = ArrayPartition(r0, v0)
ODE_DEFAULT_NORM(rv0, 0.0s)
r0 = [1.0kg, 2.0N, 3.0m/s, 4.0m/s]
v0 = [1.0kg/s, 2.0N/s, 3.0m/s^2, 4m/s^2]
rv0 = ArrayPartition(r0, v0)
r0ul = [1131.340, -2282.343, 6672.423]
v0ul = [-5.64305, 4.30333, 2.42879]
rv0ul = ArrayPartition(r0ul, v0ul)
r0 = [1131.340, -2282.343, 6672.423]kg
r1 = [1kg, 2.0m]
zero(r0)
zero(r1)
rv0 = ArrayPartition(r0)
zero(rv0)
rv1 = ArrayPartition(r1)
zero(rv1)
r0 = [1.0kg, -2kg, 3m/s, 4m/s]
zero(r0)
rv0 = ArrayPartition(r0)
zer = zero(rv0)
zer == [0.0kg, 0.0kg, 0.0m/s, 0.0m/s]
r0 = [1131.340, -2282.343, 6672.423]kg
simi = similar(r0)
rv0 = ArrayPartition(r0)
sima = similar(rv0)
r0 = [1.0kg, -2kg, 3m/s, 4m/s]
similar(r0)
rv0 = ArrayPartition(r0)
sima = similar(rv0)
r0ul = [1131.340, -2282.343, 6672.423]
v0ul = [-5.64305, 4.30333, 2.42879]
rv0ul = ArrayPartition(r0ul,v0ul)
UNITLESS_ABS2(rv0ul)
r0 = [1.0kg, 2.0N, 3.0m/s, 4.0m/s]
v0 = [1.0kg/s, 2.0N/s, 3.0m/s^2, 4m/s^2]
rv0 = ArrayPartition(r0, v0)
UNITLESS_ABS2(1.0kg)
UNITLESS_ABS2(r0)
UNITLESS_ABS2(rv0)
nothing
end

end
33 changes: 26 additions & 7 deletions test/test_4.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Check type stability of ODE_DEFAULT_NORM with mixed units and with ArrayPartition
using Test
using MechGlueDiffEqBase
import MechGlueDiffEqBase: zero_collection
using MechanicalUnits: @import_expand, dimension, NoDims,
import MechanicalUnits: g, g⁻¹
@import_expand(km, N, s, m, km, kg, °, inch)
Expand Down Expand Up @@ -46,18 +45,38 @@ end
@test @inferred(zero(rv1)) == [0.0, 0.0]km
@test typeof(zero(rv0)) == typeof(rv0)
end
@testset "(Inferrable) zero ArrayPartition mixed units" begin
r0 = [1.0km, 2km, 3m/s, 4m/s]
v0 = [1.0km/s, 2.0km/s, 3.0m/s², 4m/s²]
# Not inferrable, but inferred return type is now AbstractVector{var"#s831"} where var"#s831", not Any
@test zero(r0) == [0.0km, 0.0km, 0.0m/s, 0.0m/s]
# ArrayPartition fixes that
@testset "Inferrable zero vector and ArrayPartition mixed units" begin
r0 = [1.0km, -2km, 3m/s, 4m/s]
@test @inferred(zero(r0)) == [0.0km, 0.0km, 0.0m/s, 0.0m/s]
rv0 = @inferred ArrayPartition(r0)
zer = @inferred zero(rv0)
@test zer == [0.0km, 0.0km, 0.0m/s, 0.0m/s]
@test typeof(zer) === typeof(rv0)
end

@testset "Inferrable similar vector and ArrayPartition compatible units" begin
r0 = [1131.340, -2282.343, 6672.423]km
simi = @inferred(similar(r0))
@test all(typeof.(r0) == typeof.(simi))
@test simi !== r0
rv0 = @inferred ArrayPartition(r0)
sima = @inferred similar(rv0)
@test all(typeof.(rv0) == typeof.(sima))
@test sima !== rv0
end


@testset "Inferrable similar vector and ArrayPartition mixed units" begin
r0 = [1.0km, -2km, 3m/s, 4m/s]
simi = @inferred(similar(r0))
@test all(typeof.(r0) == typeof.(simi))
@test simi !== r0
rv0 = @inferred ArrayPartition(r0)
sima = @inferred similar(rv0)
@test all(typeof.(rv0) == typeof.(sima))
@test sima !== rv0
end

@testset "Inferrable UNITLESS_ABS2 Unitless ArrayPartition" begin
r0ul = [1131.340, -2282.343, 6672.423]
v0ul = [-5.64305, 4.30333, 2.42879]
Expand Down

0 comments on commit fc2125f

Please sign in to comment.