Skip to content

Commit 8d95bf2

Browse files
committed
modified: README.md Point out test_5
modified: src/MechGlueDiffEqBase.jl Two-param 'similar' modified: test/runtests.jl test_5.jl modified: test/test_2.jl spacing modified: test/test_3.jl Comment inferrability modified: test/test_4.jl Test two-param 'similar' new file: test/test_5.jl Inferrable mixed-units calc
1 parent fc2125f commit 8d95bf2

File tree

7 files changed

+100
-9
lines changed

7 files changed

+100
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ These functions preserve types for mixed-unit vectors. E.g. [1.0kg, 2.0N, 3.0m/s
1111

1212
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.
1313

14+
An example of inferrable, mixed units calculations with debugging is included in `test/test_5.jl`.
1415

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

src/MechGlueDiffEqBase.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,23 @@ end
6161

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

6968

69+
# Vectors with compatible units, treat as normal
70+
similar(x::Vector{Quantity{T, D, U}}, S::Type) where {T,D,U} = Vector{S}(undef, size(x,1))
71+
# Vectors with incompatible units, special inferreable treatment
72+
function similar(x::Vector{Q}, S::Type) where {Q<:AbstractQuantity{T, D, U} where {D, U}} where T
73+
x0 = Vector{S}(undef, size(x, 1))
74+
end
75+
7076

7177

7278
# KISS pre-compillation to reduce loading times
7379
# This is simply a boiled-down obfuscated test_4.jl
80+
7481
import Unitfu: m, s, kg, N,
7582
let
7683
r0ul = [1131.340, -2282.343, 6672.423]

test/runtests.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ using Test
22
include("test_1.jl")
33
include("test_2.jl")
44
include("test_3.jl")
5-
include("test_4.jl")
5+
include("test_4.jl")
6+
include("test_5.jl")

test/test_2.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ end
4646
sol = solve(prob,ExplicitRK())
4747
end
4848

49-
50-
51-
52-
53-
54-
5549
@testset "Without ArrayPartition - broken" begin
5650
# coordinate: u = [position, momentum]
5751
# parameters: p = [mass, force constanst]

test/test_3.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ end
7070

7171

7272

73-
@testset "ArrayPartition with mixed units" begin
73+
@testset "ArrayPartition with mixed units, not inferrable" begin
7474
α₀() = 30°
7575
x₀() = 0.0m
7676
y₀() = 0.0m
@@ -88,6 +88,8 @@ end
8888
Rx(vx, vy) = R(vx, vy) * cos(α(vx, vy))
8989
Ry(vx, vy) = R(vx, vy) * sin(α(vx, vy))
9090

91+
# An inferrable version of this is much faster
92+
# but this should work anyway.
9193
function f(du,u,p,t)
9294
x, y, vx,vy = u
9395
du[1] = dx = vx

test/test_4.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ using Test
33
using MechGlueDiffEqBase
44
using MechanicalUnits: @import_expand, dimension, NoDims,
55
import MechanicalUnits: g, g⁻¹
6+
import MechanicalUnits.Unitfu.numtype
67
@import_expand(km, N, s, m, km, kg, °, inch)
78
using DiffEqBase, OrdinaryDiffEq
89

@@ -63,6 +64,9 @@ end
6364
sima = @inferred similar(rv0)
6465
@test all(typeof.(rv0) == typeof.(sima))
6566
@test sima !== rv0
67+
# The expected behaviour (in some algorithms) is to drop the units here:
68+
simb = @inferred(similar(r0, Int64))
69+
@test all(typeof.(simb) .== Int64)
6670
end
6771

6872

@@ -75,6 +79,8 @@ end
7579
sima = @inferred similar(rv0)
7680
@test all(typeof.(rv0) == typeof.(sima))
7781
@test sima !== rv0
82+
simb = @inferred(similar(r0, Int64))
83+
@test all(typeof.(simb) .== Int64)
7884
end
7985

8086
@testset "Inferrable UNITLESS_ABS2 Unitless ArrayPartition" begin

test/test_5.jl

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Differential equations with mixed units using ArrayPartition and no specified algorithm
2+
using MechGlueDiffEqBase
3+
using MechanicalUnits: @import_expand, , g
4+
@import_expand(km, N, s, m, km, kg, °, inch)
5+
using OrdinaryDiffEq: ODEProblem
6+
using DifferentialEquations: solve, Tsit5
7+
using Logging: disable_logging, LogLevel, Debug, with_logger
8+
import Logging
9+
10+
using Test: @inferred
11+
12+
# Constants we don't think we'll change ever
13+
const x₀ = 0.0km
14+
const y₀ = 0.0km
15+
const ø = 15inch
16+
const ρ = 1.225kg/
17+
18+
# Calculated constants
19+
const Aₚᵣ = π/4 * ø^2
20+
# Constants that we define as functions, because we may
21+
# want to modify them later in the same scripting session.
22+
α₀() = 30°
23+
v₀() = 1050m/s
24+
25+
mₚ() = 495kg
26+
C_s() = 0.4
27+
x´₀() = v₀() * cos(α₀())
28+
y´₀() = v₀() * sin(α₀())
29+
30+
# Local tuple initial condition
31+
u₀ = ArrayPartition([x₀, y₀], [x´₀(), y´₀()])
32+
33+
# Functions
34+
v(vx, vy) = (vx^2 + vy^2)
35+
R(vx, vy) = 0.5ρC_s()Aₚᵣv(vx, vy)^2
36+
α(vx, vy) = atan(vy, vx)
37+
Rx(vx, vy) = R(vx, vy) * cos(α(vx, vy))
38+
Ry(vx, vy) = R(vx, vy) * sin(α(vx, vy))
39+
40+
41+
# Local tuple, i.e. the interesting degrees of freedom
42+
# and their derivatives
43+
function Γ!(u´, u, p, t)
44+
(x, y), (x´, y´) = packout(u)
45+
@debug "Γ" x y x´ y´ maxlog = 3
46+
# Calculate the acceleration for this step
47+
x´´ = -Rx(x´, y´) / mₚ()
48+
y´´ = -1g -Ry(x´, y´) / mₚ()
49+
@debug "Γ Acceleration" x´´|> g y´´|>g maxlog = 3
50+
packin!(u´, x´, y´, x´´, y´´)
51+
end
52+
53+
packout(u) = u.x[1], u.x[2]
54+
function packin!(u´, x´, y´, x´´, y´´)
55+
# We access the values through its field name, x (unrelated to the specific problem)
56+
.x[1][1] = x´; u´.x[1][2] =
57+
.x[2][1] = x´´; u´.x[2][2] = y´´
58+
return
59+
end
60+
61+
function solve_guarded(u₀; alg = Tsit5(), debug=false)
62+
# Test the functions
63+
@inferred packout(u₀)
64+
@inferred packout(0.01u₀/s)
65+
@inferred Γ!(u₀/s,u₀, nothing, nothing)
66+
!debug && disable_logging(Debug)
67+
prob = ODEProblem( Γ!,u₀,(0.0,60)s)
68+
sol = if debug
69+
with_logger(Logging.ConsoleLogger(stderr, Logging.Debug)) do
70+
solve(prob, Tsit5())
71+
end
72+
else
73+
solve(prob, Tsit5())
74+
end
75+
# Re-enable
76+
disable_logging(LogLevel(Debug-1))
77+
sol
78+
end
79+
@time sol = solve_guarded(u₀, debug=true);
80+
nothing

0 commit comments

Comments
 (0)