diff --git a/docs/src/basics/MTKModel_Connector.md b/docs/src/basics/MTKModel_Connector.md index b562c5323c..b264210ae3 100644 --- a/docs/src/basics/MTKModel_Connector.md +++ b/docs/src/basics/MTKModel_Connector.md @@ -30,6 +30,8 @@ equations. - `@parameters`: for specifying the symbolic parameters - `@structural_parameters`: for specifying non-symbolic parameters - `@variables`: for specifying the states + - `@continuous_events`: for specifying a list of continuous events + - `@discrete_events`: for specifying a list of discrete events Let's explore these in more detail with the following example: @@ -162,6 +164,59 @@ getdefault(model_c4.model_a.k_array[2]) - List all the equations here +#### `@continuous_events` begin block + + - Defining continuous events as described [here](https://docs.sciml.ai/ModelingToolkit/stable/basics/Events/#Continuous-Events). + - If this block is not defined in the model, no continuous events will be added. + +```@example mtkmodel-example +using ModelingToolkit + +@mtkmodel M begin + @parameters begin + k + end + @variables begin + x(t) + y(t) + end + @equations begin + x ~ k * D(x) + D(y) ~ -k + end + @continuous_events begin + [x ~ 1.5] => [x ~ 5, y ~ 5] + [t ~ 4] => [x ~ 10] + end +end +``` + +#### `@discrete_events` begin block + + - Defining discrete events as described [here](https://docs.sciml.ai/ModelingToolkit/stable/basics/Events/#Discrete-events-support). + - If this block is not defined in the model, no discrete events will be added. + +```@example mtkmodel-example +using ModelingToolkit + +@mtkmodel M begin + @parameters begin + k + end + @variables begin + x(t) + y(t) + end + @equations begin + x ~ k * D(x) + D(y) ~ -k + end + @discrete_events begin + (t == 1.5) => [x ~ x + 5, y ~ 5] + end +end +``` + #### A begin block - Any other Julia operations can be included with dedicated begin blocks. @@ -351,4 +406,4 @@ Using ternary operator or if-elseif-else statement, conditional initial guesses p = flag ? 1 : 2 end end -``` +``` \ No newline at end of file diff --git a/src/systems/model_parsing.jl b/src/systems/model_parsing.jl index a139fb8e04..60144b0915 100644 --- a/src/systems/model_parsing.jl +++ b/src/systems/model_parsing.jl @@ -92,7 +92,6 @@ function _model_macro(mod, name, expr, isconnector) gui_metadata = isassigned(icon) > 0 ? GUIMetadata(GlobalRef(mod, name), icon[]) : GUIMetadata(GlobalRef(mod, name)) - sys = :($ODESystem($Equation[equations...], $iv, variables, parameters; name, systems, gui_metadata = $gui_metadata)) @@ -105,12 +104,15 @@ function _model_macro(mod, name, expr, isconnector) isconnector && push!(exprs.args, :($Setfield.@set!(var"#___sys___".connector_type=$connector_type(var"#___sys___")))) - !(c_evts==[]) && push!(exprs.args, - :($Setfield.@set!(var"#___sys___".continuous_events=$SymbolicContinuousCallback.([$(c_evts...)])))) - - !(d_evts==[]) && push!(exprs.args, - :($Setfield.@set!(var"#___sys___".discrete_events=$SymbolicDiscreteCallback.([$(d_evts...)])))) + !(c_evts == []) && push!(exprs.args, + :($Setfield.@set!(var"#___sys___".continuous_events=$SymbolicContinuousCallback.([ + $(c_evts...), + ])))) + !(d_evts == []) && push!(exprs.args, + :($Setfield.@set!(var"#___sys___".discrete_events=$SymbolicDiscreteCallback.([ + $(d_evts...), + ])))) f = :($(Symbol(:__, name, :__))(; name, $(kwargs...)) = $exprs) :($name = $Model($f, $dict, $isconnector)) @@ -636,6 +638,7 @@ function parse_discrete_events!(d_evts, dict, body) dict[:discrete_events] = [] Base.remove_linenums!(body) for arg in body.args + push!(d_evts, arg) push!(dict[:discrete_events], readable_code.(d_evts)...) end end diff --git a/test/model_parsing.jl b/test/model_parsing.jl index f94d7483fd..b99a8975bf 100644 --- a/test/model_parsing.jl +++ b/test/model_parsing.jl @@ -326,6 +326,36 @@ end @test A.structure[:components] == [[:cc, :C]] end +@testset "Event handeling in MTKModel" begin + @mtkmodel M begin + @variables begin + x(t) + y(t) + z(t) + end + @equations begin + x ~ -D(x) + D(y) ~ 0 + D(z) ~ 0 + end + @continuous_events begin + [x ~ 1.5] => [x ~ 5, y ~ 1] + end + @discrete_events begin + (t == 1.5) => [x ~ x + 5, z ~ 2] + end + end + + @mtkbuild model = M() + u0 = [model.x => 10, model.y => 0, model.z => 0] + + prob = ODEProblem(model, u0, (0, 5.0)) + sol = solve(prob, tstops = [1.5]) + + @test isequal(sol[model.y][end], 1.0) + @test isequal(sol[model.z][end], 2.0) +end + # Ensure that modules consisting MTKModels with component arrays and icons of # `Expr` type and `unit` metadata can be precompiled. module PrecompilationTest @@ -538,4 +568,4 @@ end @test Equation[ternary_true.ternary_parameter_true ~ 0] == equations(ternary_true) @test Equation[ternary_false.ternary_parameter_false ~ 0] == equations(ternary_false) -end +end \ No newline at end of file