From 84e1c2c440e3ff69bcf98b73e6f3783d70bb1096 Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Tue, 21 Jan 2025 10:23:05 -0600 Subject: [PATCH 1/8] add modulo block to math.jl --- src/Blocks/math.jl | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index 7d453cd50..aedb56bf4 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -208,6 +208,28 @@ Output first input divided by second input. end end +""" + Modulo(; name) + +Output the remainder when the first input is divided by second input. + +# Connectors: + + - `input1` + - `input2` + - `output` +""" +@mtkmodel Modulo begin + @components begin + input1 = RealInput() + input2 = RealInput(guess = 1.0) # denominator can not be zero + output = RealOutput() + end + @equations begin + output.u ~ input1.u % input2.u + end +end + """ StaticNonLinearity(func; name) From bfa4872f0e52123b1a2a5d11b8c1d2908991b7a1 Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Tue, 21 Jan 2025 10:34:53 -0600 Subject: [PATCH 2/8] Add Power block to math.jl and update docs --- docs/src/API/blocks.md | 2 ++ src/Blocks/math.jl | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/docs/src/API/blocks.md b/docs/src/API/blocks.md index ac6cff905..ef6eae9de 100644 --- a/docs/src/API/blocks.md +++ b/docs/src/API/blocks.md @@ -36,6 +36,8 @@ Add Add3 Product Division +Power +Modulo StaticNonLinearity Abs Sign diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index aedb56bf4..fda7b2b47 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -208,6 +208,28 @@ Output first input divided by second input. end end +""" + Power(; name) + +Output the exponential with base as the first input and exponent as second input i.e u1^u2 + +# Connectors: + + - `input1` + - `input2` + - `output` +""" +@mtkmodel Power begin + @components begin + input1 = RealInput() + input2 = RealInput() # denominator can not be zero + output = RealOutput() + end + @equations begin + output.u ~ input1.u ^ input2.u + end +end + """ Modulo(; name) From 492ec4881fe5249c7a3da3eacf010aa061732559 Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Tue, 21 Jan 2025 11:02:38 -0600 Subject: [PATCH 3/8] add commented rounding functions --- src/Blocks/math.jl | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index fda7b2b47..baeb53db6 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -252,6 +252,87 @@ Output the remainder when the first input is divided by second input. end end +## Rounding functions add after the symbolic functions are registered +# """ +# Floor(; name) + +# Output the floor rounding of the input. + +# # Connectors: + +# - `input` +# - `output` +# """ +# @mtkmodel Floor begin +# @components begin +# input = RealInput() +# output = RealOutput() +# end +# @equations begin +# output.u ~ floor(input.u) +# end +# end + +# """ +# Ceil(; name) + +# Output the ceiling rounding of the input. + +# # Connectors: + +# - `input` +# - `output` +# """ +# @mtkmodel Ceil begin +# @components begin +# input = RealInput() +# output = RealOutput() +# end +# @equations begin +# output.u ~ ceil(input.u) +# end +# end + +# """ +# Round(; name) + +# Output the rounding to the nearest integer of the input. + +# # Connectors: + +# - `input` +# - `output` +# """ +# @mtkmodel Round begin +# @components begin +# input = RealInput() +# output = RealOutput() +# end +# @equations begin +# output.u ~ round(input.u) +# end +# end + +# """ +# Trunc(; name) + +# Output the truncation rounding of the input. + +# # Connectors: + +# - `input` +# - `output` +# """ +# @mtkmodel Trunc begin +# @components begin +# input = RealInput() +# output = RealOutput() +# end +# @equations begin +# output.u ~ trunc(input.u) +# end +# end + """ StaticNonLinearity(func; name) From b09f1e6a2f71ce41a9aedc79e3f8bdbf9e229cdd Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Tue, 21 Jan 2025 11:15:41 -0600 Subject: [PATCH 4/8] add unary minus to math.jl --- src/Blocks/math.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index baeb53db6..808092441 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -252,6 +252,26 @@ Output the remainder when the first input is divided by second input. end end +""" + UnaryMinus(; name) + +Output the product of -1 and the input. + +# Connectors: + + - `input` + - `output` +""" +@mtkmodel UnaryMinus begin + @components begin + input = RealInput() + output = RealOutput() + end + @equations begin + output.u ~ -(input.u) + end +end + ## Rounding functions add after the symbolic functions are registered # """ # Floor(; name) From 4a9ac36ffcb8f823ccf27cf3e5df8b7846f86849 Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Tue, 21 Jan 2025 11:16:05 -0600 Subject: [PATCH 5/8] add unaryminus to block.md --- docs/src/API/blocks.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/API/blocks.md b/docs/src/API/blocks.md index ef6eae9de..be65d7ad1 100644 --- a/docs/src/API/blocks.md +++ b/docs/src/API/blocks.md @@ -36,6 +36,7 @@ Add Add3 Product Division +UnaryMinus Power Modulo StaticNonLinearity From e037aecbe30c9583de36771965806ffa0dc81f3c Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Sun, 26 Jan 2025 21:00:38 -0600 Subject: [PATCH 6/8] add test for power block --- test/Blocks/math.jl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/Blocks/math.jl b/test/Blocks/math.jl index c29bba069..4d04a7ffe 100644 --- a/test/Blocks/math.jl +++ b/test/Blocks/math.jl @@ -157,6 +157,25 @@ end @test sol[prod.output.u] ≈ 2 * sin.(2 * pi * sol.t) end +@testset "Power" begin + @named c1 = Constant(; k = 2) + @named c2 = Constant(; k = 2) + @named pow = Power(;) + @named model = ODESystem( + [ + connect(c1.output, pow.input1), + connect(c2.output, pow.input2) + ], + t, + systems = [pow, c1, c2]) + sys = structural_simplify(model) + prob = ODEProblem(sys, [], (0.0, 1.0)) + sol = solve(prob, Rodas4()) + @test isequal(unbound_inputs(sys), []) + @test sol.retcode == Success + @test sol[pow.output.u] ≈ 4 +end + @testset "Division" begin @named c1 = Sine(; frequency = 1) @named c2 = Constant(; k = 2) From 9cb28d58b82723b9101b3a20a4575a664e9a7fa5 Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Sat, 8 Feb 2025 16:37:39 -0600 Subject: [PATCH 7/8] Add Power, Modulo, and UnaryMinus blocks; update math operations and tests --- src/Blocks/Blocks.jl | 2 +- src/Blocks/math.jl | 2 +- test/Blocks/math.jl | 48 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/Blocks/Blocks.jl b/src/Blocks/Blocks.jl index 447da8aea..3f728e43f 100644 --- a/src/Blocks/Blocks.jl +++ b/src/Blocks/Blocks.jl @@ -10,7 +10,7 @@ using ModelingToolkit: getdefault, t_nounits as t, D_nounits as D export RealInput, RealInputArray, RealOutput, RealOutputArray, SISO include("utils.jl") -export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division +export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division, Power, Modulo, UnaryMinus export Abs, Sign, Sqrt, Sin, Cos, Tan, Asin, Acos, Atan, Atan2, Sinh, Cosh, Tanh, Exp export Log, Log10 include("math.jl") diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index 808092441..ad6eaf2bf 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -248,7 +248,7 @@ Output the remainder when the first input is divided by second input. output = RealOutput() end @equations begin - output.u ~ input1.u % input2.u + output.u ~ mod(input1.u, input2.u) end end diff --git a/test/Blocks/math.jl b/test/Blocks/math.jl index 4d04a7ffe..9ec190466 100644 --- a/test/Blocks/math.jl +++ b/test/Blocks/math.jl @@ -158,22 +158,62 @@ end end @testset "Power" begin - @named c1 = Constant(; k = 2) + @named c1 = Sine(; frequency = 1) @named c2 = Constant(; k = 2) @named pow = Power(;) + @named int = Integrator(; k = 1) @named model = ODESystem( [ connect(c1.output, pow.input1), - connect(c2.output, pow.input2) + connect(c2.output, pow.input2), + connect(pow.output, int.input) + ], + t, + systems = [int, pow, c1, c2]) + sys = structural_simplify(model) + prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0)) + sol = solve(prob, Rodas4()) + @test isequal(unbound_inputs(sys), []) + @test sol.retcode == Success + @test sol[pow.output.u] ≈ sin.(2 * pi * sol.t) .^ 2 +end + +@testset "Modulo" begin + @named c1 = Ramp(height = 2, duration = 1, offset = 1, start_time = 0, smooth = false) + @named c2 = Constant(; k = 1) + @named modl = Modulo(;) + @named model = ODESystem( + [ + connect(c1.output, modl.input1), + connect(c2.output, modl.input2) ], t, - systems = [pow, c1, c2]) + systems = [modl, c1, c2]) sys = structural_simplify(model) prob = ODEProblem(sys, [], (0.0, 1.0)) sol = solve(prob, Rodas4()) @test isequal(unbound_inputs(sys), []) @test sol.retcode == Success - @test sol[pow.output.u] ≈ 4 + @test sol[modl.output.u] ≈ mod.(2 * sol.t,1) +end + +@testset "UnaryMinus" begin + @named c1 = Sine(; frequency = 1) + @named minu = UnaryMinus(;) + @named int = Integrator(; k = 1) + @named model = ODESystem( + [ + connect(c1.output, minu.input), + connect(minu.output, int.input) + ], + t, + systems = [int, minu, c1]) + sys = structural_simplify(model) + prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0)) + sol = solve(prob, Rodas4()) + @test isequal(unbound_inputs(sys), []) + @test sol.retcode == Success + @test sol[minu.output.u] ≈ - sin.(2 * pi * sol.t) end @testset "Division" begin From 7ec57c4245cd77e15488c3672997ad8c82e575d9 Mon Sep 17 00:00:00 2001 From: Rajeev Shobhit Voleti Date: Fri, 14 Feb 2025 16:30:32 -0600 Subject: [PATCH 8/8] add floor and ceiling blocks with tests --- docs/src/API/blocks.md | 2 + src/Blocks/Blocks.jl | 2 +- src/Blocks/math.jl | 119 ++++++++++++++--------------------------- test/Blocks/math.jl | 38 +++++++++++++ 4 files changed, 81 insertions(+), 80 deletions(-) diff --git a/docs/src/API/blocks.md b/docs/src/API/blocks.md index be65d7ad1..ebeb90c19 100644 --- a/docs/src/API/blocks.md +++ b/docs/src/API/blocks.md @@ -39,6 +39,8 @@ Division UnaryMinus Power Modulo +Floor +Ceil StaticNonLinearity Abs Sign diff --git a/src/Blocks/Blocks.jl b/src/Blocks/Blocks.jl index 3f728e43f..b4b18948c 100644 --- a/src/Blocks/Blocks.jl +++ b/src/Blocks/Blocks.jl @@ -10,7 +10,7 @@ using ModelingToolkit: getdefault, t_nounits as t, D_nounits as D export RealInput, RealInputArray, RealOutput, RealOutputArray, SISO include("utils.jl") -export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division, Power, Modulo, UnaryMinus +export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division, Power, Modulo, UnaryMinus, Floor, Ceil export Abs, Sign, Sqrt, Sin, Cos, Tan, Asin, Acos, Atan, Atan2, Sinh, Cosh, Tanh, Exp export Log, Log10 include("math.jl") diff --git a/src/Blocks/math.jl b/src/Blocks/math.jl index ad6eaf2bf..45e0c8203 100644 --- a/src/Blocks/math.jl +++ b/src/Blocks/math.jl @@ -273,85 +273,46 @@ Output the product of -1 and the input. end ## Rounding functions add after the symbolic functions are registered -# """ -# Floor(; name) - -# Output the floor rounding of the input. - -# # Connectors: - -# - `input` -# - `output` -# """ -# @mtkmodel Floor begin -# @components begin -# input = RealInput() -# output = RealOutput() -# end -# @equations begin -# output.u ~ floor(input.u) -# end -# end - -# """ -# Ceil(; name) - -# Output the ceiling rounding of the input. - -# # Connectors: - -# - `input` -# - `output` -# """ -# @mtkmodel Ceil begin -# @components begin -# input = RealInput() -# output = RealOutput() -# end -# @equations begin -# output.u ~ ceil(input.u) -# end -# end - -# """ -# Round(; name) - -# Output the rounding to the nearest integer of the input. - -# # Connectors: - -# - `input` -# - `output` -# """ -# @mtkmodel Round begin -# @components begin -# input = RealInput() -# output = RealOutput() -# end -# @equations begin -# output.u ~ round(input.u) -# end -# end - -# """ -# Trunc(; name) - -# Output the truncation rounding of the input. - -# # Connectors: - -# - `input` -# - `output` -# """ -# @mtkmodel Trunc begin -# @components begin -# input = RealInput() -# output = RealOutput() -# end -# @equations begin -# output.u ~ trunc(input.u) -# end -# end +""" + Floor(; name) + +Output the floor rounding of the input. + +# Connectors: + + - `input` + - `output` +""" +@mtkmodel Floor begin + @components begin + input = RealInput() + output = RealOutput() + end + @equations begin + output.u ~ floor(input.u) + end +end + +""" + Ceil(; name) + +Output the ceiling rounding of the input. + +# Connectors: + + - `input` + - `output` +""" +@mtkmodel Ceil begin + @components begin + input = RealInput() + output = RealOutput() + end + @equations begin + output.u ~ ceil(input.u) + end +end + """ StaticNonLinearity(func; name) diff --git a/test/Blocks/math.jl b/test/Blocks/math.jl index 9ec190466..5812ccf3d 100644 --- a/test/Blocks/math.jl +++ b/test/Blocks/math.jl @@ -216,6 +216,44 @@ end @test sol[minu.output.u] ≈ - sin.(2 * pi * sol.t) end +@testset "Floor" begin + @named c1 = Sine(; frequency = 1) + @named flr = Floor(;) + @named int = Integrator(; k = 1) + @named model = ODESystem( + [ + connect(c1.output, flr.input), + connect(flr.output, int.input) + ], + t, + systems = [int, flr, c1]) + sys = structural_simplify(model) + prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0)) + sol = solve(prob, Rodas4()) + @test isequal(unbound_inputs(sys), []) + @test sol.retcode == Success + @test sol[flr.output.u] ≈ floor.(sin.(2 * pi * sol.t)) +end + +@testset "Ceil" begin + @named c1 = Sine(; frequency = 1) + @named cel = Ceil(;) + @named int = Integrator(; k = 1) + @named model = ODESystem( + [ + connect(c1.output, cel.input), + connect(cel.output, int.input) + ], + t, + systems = [int, cel, c1]) + sys = structural_simplify(model) + prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0)) + sol = solve(prob, Rodas4()) + @test isequal(unbound_inputs(sys), []) + @test sol.retcode == Success + @test sol[cel.output.u] ≈ ceil.(sin.(2 * pi * sol.t)) +end + @testset "Division" begin @named c1 = Sine(; frequency = 1) @named c2 = Constant(; k = 2)