Skip to content

Commit 102100d

Browse files
Merge pull request #358 from shobhitvoleti/main
Adding Power, Modulo, UnaryMinus, Floor and Ceil blocks
2 parents 5a2bfbd + 7ec57c4 commit 102100d

File tree

4 files changed

+209
-1
lines changed

4 files changed

+209
-1
lines changed

docs/src/API/blocks.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ Add
3636
Add3
3737
Product
3838
Division
39+
UnaryMinus
40+
Power
41+
Modulo
42+
Floor
43+
Ceil
3944
StaticNonLinearity
4045
Abs
4146
Sign

src/Blocks/Blocks.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ using ModelingToolkit: getdefault, t_nounits as t, D_nounits as D
1010
export RealInput, RealInputArray, RealOutput, RealOutputArray, SISO
1111
include("utils.jl")
1212

13-
export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division
13+
export Gain, Sum, MatrixGain, Feedback, Add, Add3, Product, Division, Power, Modulo, UnaryMinus, Floor, Ceil
1414
export Abs, Sign, Sqrt, Sin, Cos, Tan, Asin, Acos, Atan, Atan2, Sinh, Cosh, Tanh, Exp
1515
export Log, Log10
1616
include("math.jl")

src/Blocks/math.jl

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,112 @@ Output first input divided by second input.
208208
end
209209
end
210210

211+
"""
212+
Power(; name)
213+
214+
Output the exponential with base as the first input and exponent as second input i.e u1^u2
215+
216+
# Connectors:
217+
218+
- `input1`
219+
- `input2`
220+
- `output`
221+
"""
222+
@mtkmodel Power begin
223+
@components begin
224+
input1 = RealInput()
225+
input2 = RealInput() # denominator can not be zero
226+
output = RealOutput()
227+
end
228+
@equations begin
229+
output.u ~ input1.u ^ input2.u
230+
end
231+
end
232+
233+
"""
234+
Modulo(; name)
235+
236+
Output the remainder when the first input is divided by second input.
237+
238+
# Connectors:
239+
240+
- `input1`
241+
- `input2`
242+
- `output`
243+
"""
244+
@mtkmodel Modulo begin
245+
@components begin
246+
input1 = RealInput()
247+
input2 = RealInput(guess = 1.0) # denominator can not be zero
248+
output = RealOutput()
249+
end
250+
@equations begin
251+
output.u ~ mod(input1.u, input2.u)
252+
end
253+
end
254+
255+
"""
256+
UnaryMinus(; name)
257+
258+
Output the product of -1 and the input.
259+
260+
# Connectors:
261+
262+
- `input`
263+
- `output`
264+
"""
265+
@mtkmodel UnaryMinus begin
266+
@components begin
267+
input = RealInput()
268+
output = RealOutput()
269+
end
270+
@equations begin
271+
output.u ~ -(input.u)
272+
end
273+
end
274+
275+
## Rounding functions add after the symbolic functions are registered
276+
"""
277+
Floor(; name)
278+
279+
Output the floor rounding of the input.
280+
281+
# Connectors:
282+
283+
- `input`
284+
- `output`
285+
"""
286+
@mtkmodel Floor begin
287+
@components begin
288+
input = RealInput()
289+
output = RealOutput()
290+
end
291+
@equations begin
292+
output.u ~ floor(input.u)
293+
end
294+
end
295+
296+
"""
297+
Ceil(; name)
298+
299+
Output the ceiling rounding of the input.
300+
301+
# Connectors:
302+
303+
- `input`
304+
- `output`
305+
"""
306+
@mtkmodel Ceil begin
307+
@components begin
308+
input = RealInput()
309+
output = RealOutput()
310+
end
311+
@equations begin
312+
output.u ~ ceil(input.u)
313+
end
314+
end
315+
316+
211317
"""
212318
StaticNonLinearity(func; name)
213319

test/Blocks/math.jl

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,103 @@ end
157157
@test sol[prod.output.u] 2 * sin.(2 * pi * sol.t)
158158
end
159159

160+
@testset "Power" begin
161+
@named c1 = Sine(; frequency = 1)
162+
@named c2 = Constant(; k = 2)
163+
@named pow = Power(;)
164+
@named int = Integrator(; k = 1)
165+
@named model = ODESystem(
166+
[
167+
connect(c1.output, pow.input1),
168+
connect(c2.output, pow.input2),
169+
connect(pow.output, int.input)
170+
],
171+
t,
172+
systems = [int, pow, c1, c2])
173+
sys = structural_simplify(model)
174+
prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0))
175+
sol = solve(prob, Rodas4())
176+
@test isequal(unbound_inputs(sys), [])
177+
@test sol.retcode == Success
178+
@test sol[pow.output.u] sin.(2 * pi * sol.t) .^ 2
179+
end
180+
181+
@testset "Modulo" begin
182+
@named c1 = Ramp(height = 2, duration = 1, offset = 1, start_time = 0, smooth = false)
183+
@named c2 = Constant(; k = 1)
184+
@named modl = Modulo(;)
185+
@named model = ODESystem(
186+
[
187+
connect(c1.output, modl.input1),
188+
connect(c2.output, modl.input2)
189+
],
190+
t,
191+
systems = [modl, c1, c2])
192+
sys = structural_simplify(model)
193+
prob = ODEProblem(sys, [], (0.0, 1.0))
194+
sol = solve(prob, Rodas4())
195+
@test isequal(unbound_inputs(sys), [])
196+
@test sol.retcode == Success
197+
@test sol[modl.output.u] mod.(2 * sol.t,1)
198+
end
199+
200+
@testset "UnaryMinus" begin
201+
@named c1 = Sine(; frequency = 1)
202+
@named minu = UnaryMinus(;)
203+
@named int = Integrator(; k = 1)
204+
@named model = ODESystem(
205+
[
206+
connect(c1.output, minu.input),
207+
connect(minu.output, int.input)
208+
],
209+
t,
210+
systems = [int, minu, c1])
211+
sys = structural_simplify(model)
212+
prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0))
213+
sol = solve(prob, Rodas4())
214+
@test isequal(unbound_inputs(sys), [])
215+
@test sol.retcode == Success
216+
@test sol[minu.output.u] - sin.(2 * pi * sol.t)
217+
end
218+
219+
@testset "Floor" begin
220+
@named c1 = Sine(; frequency = 1)
221+
@named flr = Floor(;)
222+
@named int = Integrator(; k = 1)
223+
@named model = ODESystem(
224+
[
225+
connect(c1.output, flr.input),
226+
connect(flr.output, int.input)
227+
],
228+
t,
229+
systems = [int, flr, c1])
230+
sys = structural_simplify(model)
231+
prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0))
232+
sol = solve(prob, Rodas4())
233+
@test isequal(unbound_inputs(sys), [])
234+
@test sol.retcode == Success
235+
@test sol[flr.output.u] floor.(sin.(2 * pi * sol.t))
236+
end
237+
238+
@testset "Ceil" begin
239+
@named c1 = Sine(; frequency = 1)
240+
@named cel = Ceil(;)
241+
@named int = Integrator(; k = 1)
242+
@named model = ODESystem(
243+
[
244+
connect(c1.output, cel.input),
245+
connect(cel.output, int.input)
246+
],
247+
t,
248+
systems = [int, cel, c1])
249+
sys = structural_simplify(model)
250+
prob = ODEProblem(sys, Pair[int.x => 0.0], (0.0, 1.0))
251+
sol = solve(prob, Rodas4())
252+
@test isequal(unbound_inputs(sys), [])
253+
@test sol.retcode == Success
254+
@test sol[cel.output.u] ceil.(sin.(2 * pi * sol.t))
255+
end
256+
160257
@testset "Division" begin
161258
@named c1 = Sine(; frequency = 1)
162259
@named c2 = Constant(; k = 2)

0 commit comments

Comments
 (0)