Skip to content

Commit 772a0fc

Browse files
committed
modified: .gitignore
modified: Project.toml DiffEqBase, RecursiveArrayTools, Unitfu only modified: README.md Short explanation modified: src/MechGlueDiffEqBase.jl Drop experiments, norm only. deleted: test/Manifest.toml deleted: test/Project.toml modified: test/runtests.jl Include 1..3 new file: test/test_1.jl First version new file: test/test_2.jl First version new file: test/test_3.jl First version
1 parent cade4f2 commit 772a0fc

File tree

10 files changed

+224
-1535
lines changed

10 files changed

+224
-1535
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
/Manifest.toml
2+
/.vscode

Project.toml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
name = "MechGlueDiffEqBase"
22
uuid = "2532746b-52b5-4539-9431-8bb183ab067f"
33
authors = ["hustf <[email protected]> and contributors"]
4-
version = "0.1.31"
4+
version = "0.1.32"
55

66
[deps]
77
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
8-
MechGluePlots = "03a24088-0a82-4850-846f-2cad5d056ae1"
9-
MechanicalUnits = "e6be9192-89dc-11e9-36e6-5dbcb28f419e"
10-
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
11-
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
8+
RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd"
129
Unitfu = "5ee08b94-2369-4f4a-b8c7-99333ba35fb0"
1310

1411
[compat]
1512
julia = "1"
1613

1714
[extras]
1815
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
16+
MechanicalUnits = "e6be9192-89dc-11e9-36e6-5dbcb28f419e"
1917

2018
[targets]
2119
test = ["Test"]

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
11
# MechGlueDiffEqBase
2+
Glue code for making [DiffEqBase](https://github.com/SciML/DiffEqBase.jl) work with units.
3+
4+
It also includes glue code for [RecursiveArrayTools](https://github.com/SciML/RecursiveArrayTools.jl), which enables type-stable solution of equations with mixed units.
5+
6+
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:
7+
8+
err_scaled = **error** / (**abstol** + norm(u) * **reltol**)
9+
10+
where **bold** indicates unitful objects.
11+
12+
The functions are adaptions of corresponding code from [DiffEqBase](https://github.com/SciML/DiffEqBase.jl/blob/6bb8830711e729ef513f2b1beb95853e4a691375/src/init.jl).
13+
14+
15+

src/MechGlueDiffEqBase.jl

Lines changed: 21 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,37 @@
11
module MechGlueDiffEqBase
2-
import Unitfu: AbstractQuantity, Quantity, ustrip
3-
import DiffEqBase: value, ODE_DEFAULT_NORM, UNITLESS_ABS2
2+
import Unitfu: AbstractQuantity, Quantity, ustrip, norm
3+
import DiffEqBase: value, ODE_DEFAULT_NORM, UNITLESS_ABS2, zero
4+
import DiffEqBase: calculate_residuals, @muladd
5+
using RecursiveArrayTools
46
export value, ODE_DEFAULT_NORM, UNITLESS_ABS2, Unitfu, AbstractQuantity, Quantity
7+
export norm, ArrayPartition
58

6-
7-
import RecipesBase
8-
import RecipesBase.@recipe
9-
import SciMLBase
10-
import SciMLBase: AbstractTimeseriesSolution, RecipesBase
11-
import SciMLBase: AbstractDiscreteProblem, AbstractRODESolution, SensitivityInterpolation
12-
import SciMLBase: getsyms, interpret_vars, cleansyms
13-
import SciMLBase: diffeq_to_arrays, issymbollike, getindepsym_defaultt
14-
import SciMLBase: DEFAULT_PLOT_FUNC
15-
16-
9+
# This is identical to what DiffEqBase defines for Unitful
1710
function value(x::Type{AbstractQuantity{T,D,U}}) where {T,D,U}
1811
T
1912
end
20-
function value(x::AbstractQuantity)
21-
x.val
22-
end
13+
# This is different from what DiffEqBase defines for Unitful
14+
value(::Type{<:AbstractQuantity{T,D,U}}) where {T,D,U<:Core.TypeofBottom} = Base.undef_ref_str
15+
value(x::Q) where {Q<:AbstractQuantity} = ustrip(x)
16+
17+
18+
# This is identical to what DiffEqBase defines for Unitful
2319
@inline function ODE_DEFAULT_NORM(u::AbstractArray{<:AbstractQuantity,N},t) where {N}
20+
# Support adaptive errors should be errorless for exponentiation
2421
sqrt(sum(x->ODE_DEFAULT_NORM(x[1],x[2]),zip((value(x) for x in u),Iterators.repeated(t))) / length(u))
2522
end
23+
# This is identical to what DiffEqBase defines for Unitful
2624
@inline function ODE_DEFAULT_NORM(u::Array{<:AbstractQuantity,N},t) where {N}
2725
sqrt(sum(x->ODE_DEFAULT_NORM(x[1],x[2]),zip((value(x) for x in u),Iterators.repeated(t))) / length(u))
2826
end
29-
@inline function ODE_DEFAULT_NORM(u::AbstractQuantity,t)
30-
abs(value(u))
27+
28+
# This is identical to what DiffEqBase defines for Unitful
29+
30+
@inline function ODE_DEFAULT_NORM(u::AbstractQuantity, t)
31+
abs(ustrip(u))
3132
end
33+
# This is slightly different from what DiffEqBase defines for Unitful
3234
@inline function UNITLESS_ABS2(x::AbstractQuantity)
33-
real(abs2(x)/oneunit(x)*oneunit(x))
35+
real(abs2(x) / (oneunit(x)^2))
3436
end
35-
36-
# This recipe is copied from SciMLBase, and only the signature is adopted
37-
# for use with unitful solutions. It can perhaps be deleted now, and the link to RecipesBase be deleted.
38-
@recipe function f(sol::AbstractTimeseriesSolution{T, N, A};
39-
plot_analytic=false,
40-
denseplot = (sol.dense ||
41-
typeof(sol.prob) <: AbstractDiscreteProblem) &&
42-
!(typeof(sol) <: AbstractRODESolution) &&
43-
!(hasfield(typeof(sol),:interp) &&
44-
typeof(sol.interp) <: SensitivityInterpolation),
45-
plotdensity = min(Int(1e5),sol.tslocation==0 ?
46-
(typeof(sol.prob) <: AbstractDiscreteProblem ?
47-
max(1000,100*length(sol)) :
48-
max(1000,10*length(sol))) :
49-
1000*sol.tslocation),
50-
tspan = nothing, axis_safety = 0.1,
51-
vars=nothing) where {T<:Quantity, N, A<:Array{<:Quantity}}
52-
syms = getsyms(sol)
53-
int_vars = interpret_vars(vars,sol,syms)
54-
strs = cleansyms(syms)
55-
56-
tscale = get(plotattributes, :xscale, :identity)
57-
plot_vecs,labels = diffeq_to_arrays(sol,plot_analytic,denseplot,
58-
plotdensity,tspan,axis_safety,
59-
vars,int_vars,tscale,strs)
60-
61-
tdir = sign(sol.t[end]-sol.t[1])
62-
xflip --> tdir < 0
63-
seriestype --> :path
64-
65-
# Special case labels when vars = (:x,:y,:z) or (:x) or [:x,:y] ...
66-
if typeof(vars) <: Tuple && (issymbollike(vars[1]) && issymbollike(vars[2]))
67-
xguide --> issymbollike(int_vars[1][2]) ? Symbol(int_vars[1][2]) : strs[int_vars[1][2]]
68-
yguide --> issymbollike(int_vars[1][3]) ? Symbol(int_vars[1][3]) : strs[int_vars[1][3]]
69-
if length(vars) > 2
70-
zguide --> issymbollike(int_vars[1][4]) ? Symbol(int_vars[1][4]) : strs[int_vars[1][4]]
71-
end
72-
end
73-
74-
if (!any(issymbollike,getindex.(int_vars,1)) && getindex.(int_vars,1) == zeros(length(int_vars))) ||
75-
(!any(issymbollike,getindex.(int_vars,2)) && getindex.(int_vars,2) == zeros(length(int_vars))) ||
76-
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,1)) || all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,2))
77-
xguide --> "$(getindepsym_defaultt(sol))"
78-
end
79-
if length(int_vars[1]) >= 3 && ((!any(issymbollike,getindex.(int_vars,3)) && getindex.(int_vars,3) == zeros(length(int_vars))) ||
80-
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,3)))
81-
yguide --> "$(getindepsym_defaultt(sol))"
82-
end
83-
if length(int_vars[1]) >= 4 && ((!any(issymbollike,getindex.(int_vars,4)) && getindex.(int_vars,4) == zeros(length(int_vars))) ||
84-
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,4)))
85-
zguide --> "$(getindepsym_defaultt(sol))"
86-
end
87-
88-
if (!any(issymbollike,getindex.(int_vars,2)) && getindex.(int_vars,2) == zeros(length(int_vars))) ||
89-
all(t->Symbol(t)==getindepsym_defaultt(sol),getindex.(int_vars,2))
90-
if tspan === nothing
91-
if tdir > 0
92-
xlims --> (sol.t[1],sol.t[end])
93-
else
94-
xlims --> (sol.t[end],sol.t[1])
95-
end
96-
else
97-
xlims --> (tspan[1],tspan[end])
98-
end
99-
else
100-
mins = minimum(sol[int_vars[1][2],:])
101-
maxs = maximum(sol[int_vars[1][2],:])
102-
for iv in int_vars
103-
mins = min(mins,minimum(sol[iv[2],:]))
104-
maxs = max(maxs,maximum(sol[iv[2],:]))
105-
end
106-
xlims --> ((1-sign(mins)*axis_safety)*mins,(1+sign(maxs)*axis_safety)*maxs)
107-
end
108-
109-
# Analytical solutions do not save enough information to have a good idea
110-
# of the axis ahead of time
111-
# Only set axis for animations
112-
if sol.tslocation != 0 && !(typeof(sol) <: AbstractAnalyticalSolution)
113-
if all(getindex.(int_vars,1) .== DEFAULT_PLOT_FUNC)
114-
mins = minimum(sol[int_vars[1][3],:])
115-
maxs = maximum(sol[int_vars[1][3],:])
116-
for iv in int_vars
117-
mins = min(mins,minimum(sol[iv[3],:]))
118-
maxs = max(maxs,maximum(sol[iv[3],:]))
119-
end
120-
ylims --> ((1-sign(mins)*axis_safety)*mins,(1+sign(maxs)*axis_safety)*maxs)
121-
122-
if length(int_vars[1]) >= 4
123-
mins = minimum(sol[int_vars[1][4],:])
124-
maxs = maximum(sol[int_vars[1][4],:])
125-
for iv in int_vars
126-
mins = min(mins,minimum(sol[iv[4],:]))
127-
maxs = max(mins,maximum(sol[iv[4],:]))
128-
end
129-
zlims --> ((1-sign(mins)*axis_safety)*mins,(1+sign(maxs)*axis_safety)*maxs)
130-
end
131-
end
132-
end
133-
134-
label --> reshape(labels,1,length(labels))
135-
println("----------------------------------MechGlueDiffEqBase")
136-
(plot_vecs...,)
137-
end
138-
13937
end

0 commit comments

Comments
 (0)