Skip to content

Commit 5011335

Browse files
committed
Merge remote-tracking branch 'origin/master' into fix_ode_jumps
2 parents f690295 + 5cfb1b6 commit 5011335

File tree

7 files changed

+41
-31
lines changed

7 files changed

+41
-31
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelingToolkit"
22
uuid = "961ee093-0014-501f-94e3-6117800e7a78"
33
authors = ["Yingbo Ma <[email protected]>", "Chris Rackauckas <[email protected]> and contributors"]
4-
version = "9.68.0"
4+
version = "9.68.1"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
2929
[compat]
3030
BenchmarkTools = "1.3"
3131
BifurcationKit = "0.4"
32-
DataInterpolations = "6.5"
32+
DataInterpolations = "6.5, 8"
3333
Distributions = "0.25"
3434
Documenter = "1"
3535
DynamicQuantities = "^0.11.2, 0.12, 1"

docs/src/comparison.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
- Modelica is an object-oriented single dispatch language. ModelingToolkit.jl,
2424
built on Julia, uses multiple dispatch extensively to simplify code.
2525
- Many Modelica compilers supply a GUI. ModelingToolkit.jl does not.
26-
- Modelica can be used to simulate ODE and DAE systems. ModelingToolkit.jl
27-
has a much more expansive set of system types, including nonlinear systems,
28-
SDEs, PDEs, and more.
26+
- Modelica is designed for simulating ODE and DAE systems (which can include nonlinear dynamics).
27+
In contrast, ModelingToolkit.jl supports a much broader range of system types, including SDEs,
28+
PDEs, time-independent nonlinear systems (e.g. various forms of optimization problems) and more.
2929

3030
## Comparison Against Simulink
3131

docs/src/tutorials/change_independent_variable.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ Ordinary differential equations describe the rate of change of some dependent va
44
For the modeler it is often most natural to write down the equations with a particular independent variable, say time $t$.
55
However, in many cases there are good reasons for changing the independent variable:
66

7-
1. One may want $y(x)$ as a function of $x$ instead of $(x(t), y(t))$ as a function of $t$
8-
2. Some differential equations vary more nicely (e.g. less stiff) with respect to one independent variable than another.
9-
3. It can reduce the number of equations that must be solved (e.g. $y(x)$ is one equation, while $(x(t), y(t))$ are two).
7+
1. One may want $y(x)$ as a function of $x$ instead of $(x(t), y(t))$ as a function of $t$
8+
9+
2. Some differential equations vary more nicely (e.g. less stiff) with respect to one independent variable than another.
10+
3. It can reduce the number of equations that must be solved (e.g. $y(x)$ is one equation, while $(x(t), y(t))$ are two).
1011

1112
To manually change the independent variable of an ODE, one must rewrite all equations in terms of a new variable and transform differentials with the chain rule.
1213
This is mechanical and error-prone.
@@ -34,9 +35,9 @@ It expresses the position $(x(t), y(t))$ as a function of time $t$.
3435
But suppose we want to determine whether the projectile hits a target 10 meters away.
3536
There are at least three ways of answering this:
3637

37-
- Solve the ODE for $(x(t), y(t))$ and use a callback to terminate when $x$ reaches 10 meters, and evaluate $y$ at the final time.
38-
- Solve the ODE for $(x(t), y(t))$ and use root finding to find the time when $x$ reaches 10 meters, and evaluate $y$ at that time.
39-
- Solve the ODE for $y(x)$ and evaluate it at 10 meters.
38+
- Solve the ODE for $(x(t), y(t))$ and use a callback to terminate when $x$ reaches 10 meters, and evaluate $y$ at the final time.
39+
- Solve the ODE for $(x(t), y(t))$ and use root finding to find the time when $x$ reaches 10 meters, and evaluate $y$ at that time.
40+
- Solve the ODE for $y(x)$ and evaluate it at 10 meters.
4041

4142
We will demonstrate the last method by changing the independent variable from $t$ to $x$.
4243
This transformation is well-defined for any non-zero horizontal velocity $v$, so $x$ and $t$ are one-to-one.
@@ -55,7 +56,7 @@ M2s # display this # hide
5556

5657
The derivatives are now with respect to the new independent variable $x$, which can be accessed with `M2.x`.
5758

58-
!!! warn
59+
!!! info
5960

6061
At this point `x`, `M1.x`, `M1s.x`, `M2.x`, `M2s.x` are *three* different variables.
6162
Meanwhile `y`, `M1.y`, `M1s.y`, `M2.y` and `M2s.y` are *four* different variables.
@@ -66,7 +67,7 @@ It is straightforward to evolve the ODE for 10 meters and plot the resulting tra
6667

6768
```@example changeivar
6869
using OrdinaryDiffEq, Plots
69-
prob = ODEProblem(M2s, [M2s.y => 0.0], [0.0, 10.0], [v => 8.0]) # throw 10 meters with x-velocity 8 m/s
70+
prob = ODEProblem(M2s, [M2s.y => 0.0], [0.0, 10.0], [v => 8.0]) # throw 10 meters
7071
sol = solve(prob, Tsit5())
7172
plot(sol; idxs = M2.y) # must index by M2.y = y(x); not M1.y = y(t)!
7273
```

src/systems/jumps/jumpsystem.jl

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,14 @@ const JumpType = Union{VariableRateJump, ConstantRateJump, MassActionJump}
44
# call reset_aggregated_jumps!(integrator).
55
# assumes iip
66
function _reset_aggregator!(expr, integrator)
7-
if expr isa Symbol
8-
error("Error, encountered a symbol. This should not happen.")
7+
@assert Meta.isexpr(expr, :function)
8+
body = expr.args[end]
9+
body = quote
10+
$body
11+
$reset_aggregated_jumps!($integrator)
912
end
10-
if expr isa LineNumberNode
11-
return
12-
end
13-
14-
if (expr.head == :function)
15-
_reset_aggregator!(expr.args[end], integrator)
16-
else
17-
if expr.args[end] == :nothing
18-
expr.args[end] = :(reset_aggregated_jumps!($integrator))
19-
push!(expr.args, :nothing)
20-
else
21-
_reset_aggregator!(expr.args[end], integrator)
22-
end
23-
end
24-
25-
nothing
13+
expr.args[end] = body
14+
return nothing
2615
end
2716

2817
"""

src/systems/parameter_buffer.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,9 @@ end
444444

445445
function validate_parameter_type(ic::IndexCache, stype, sz, sym, index, val)
446446
(; portion) = index
447+
if stype <: FnType
448+
stype = fntype_to_function_type(stype)
449+
end
447450
# Nonnumeric parameters have to match the type
448451
if portion === NONNUMERIC_PORTION
449452
val isa stype && return nothing

test/initial_values.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using ModelingToolkit
22
using ModelingToolkit: t_nounits as t, D_nounits as D, get_u0
33
using OrdinaryDiffEq
4+
using DataInterpolations
45
using SymbolicIndexingInterface: getu
56

67
@variables x(t)[1:3]=[1.0, 2.0, 3.0] y(t) z(t)[1:2]
@@ -219,3 +220,19 @@ end
219220
@test_throws ["a(t)", "c(t)"] ODEProblem(
220221
sys, [e => 2, a => b, b => a + 1, c => d, d => c + 1], (0, 1))
221222
end
223+
224+
@testset "Issue#3490: `remake` works with callable parameters" begin
225+
ts = collect(0.0:0.1:10.0)
226+
spline = LinearInterpolation(ts .^ 2, ts)
227+
Tspline = typeof(spline)
228+
@variables x(t)
229+
@parameters (interp::Tspline)(..)
230+
231+
@mtkbuild sys = ODESystem(D(x) ~ interp(t), t)
232+
233+
prob = ODEProblem(sys, [x => 0.0], (0.0, 1.0), [interp => spline])
234+
spline2 = LinearInterpolation(ts .^ 2, ts .^ 2)
235+
p_new = [interp => spline2]
236+
prob2 = remake(prob; p = p_new)
237+
@test prob2.ps[interp] == spline2
238+
end

0 commit comments

Comments
 (0)