Skip to content

Commit 2aa9d7d

Browse files
committed
add docs and tests for constant torque
1 parent 50da17d commit 2aa9d7d

File tree

4 files changed

+75
-37
lines changed

4 files changed

+75
-37
lines changed

src/Mechanical/Rotational/Rotational.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ include("utils.jl")
1515
export Fixed, Inertia, Spring, Damper, IdealGear, RotationalFriction
1616
include("components.jl")
1717

18-
export Torque, Speed
18+
export Torque, ConstantTorque, Speed
1919
include("sources.jl")
2020

2121
export AngleSensor, SpeedSensor, TorqueSensor, RelSpeedSensor

src/Mechanical/Rotational/sources.jl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Input signal acting as external torque on a flange
1616
1717
# States:
1818
19-
- `phi_support(t)`: [`rad`] Absolute angle of support flange"
19+
- `phi_support(t)`: [`rad`] Absolute angle of support flange
2020
2121
# Connectors:
2222
@@ -35,6 +35,24 @@ function Torque(; name, use_support = false)
3535
return extend(ODESystem(eqs, t, [], []; name = name, systems = [tau]), partial_element)
3636
end
3737

38+
"""
39+
ConstantTorque(; name, tau_constant, use_support = false)
40+
41+
Constant torque source
42+
43+
# State variables:
44+
45+
- `phi_support(t)`: [`rad`] Absolute angle of support flange, only available if `use_support = true`
46+
- `tau`: Accelerating torque acting at flange (= -flange.tau)
47+
- `w`: Angular velocity of flange with respect to support (= der(phi))
48+
49+
# Connectors:
50+
- `flange` [Flange](@ref)
51+
52+
# Arguments:
53+
- `tau_constant`: The constant torque applied by the source
54+
- `use_support`: Whether or not an internal support flange is added, defaults to false.
55+
"""
3856
function ConstantTorque(; name, tau_constant, use_support = false)
3957
@named partial_element = PartialTorque(; use_support)
4058
@unpack flange, phi = partial_element

src/Mechanical/Rotational/utils.jl

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,26 @@ Base.@doc """
1818
extend(ODESystem(Equation[], t, [], [], name = name), flange)
1919
end
2020

21-
Base.@doc """
22-
InternalSupport(;name, tau)
23-
24-
1-dim. rotational flange of a shaft.
25-
26-
- `tau`: External support torque (must be computed via torque balance in model where InternalSupport is used; = flange.tau)
27-
28-
# States:
29-
- `phi(t)`: [`rad`] Absolute rotation angle of flange
30-
- `tau(t)`: [`N.m`] Cut torque in the flange
31-
""" Flange
32-
33-
@connector function InternalSupport(; name, tau)
34-
@named flange = Flange()
35-
@variables phi(t)=0 [description = "Rotation angle of support $name"]
36-
# tau(t), [connect = Flow, description = "Cut torque in support $name"],)
37-
equations = [flange.tau ~ tau
38-
flange.phi ~ phi]
39-
ODESystem(equations, t, [phi], [], name = name, systems = [flange]) # NOTE: tau not included since it belongs elsewhere
40-
end
21+
# Base.@doc """
22+
# InternalSupport(;name, tau)
23+
24+
# 1-dim. rotational flange of a shaft.
25+
26+
# - `tau`: External support torque (must be computed via torque balance in model where InternalSupport is used; = flange.tau)
27+
28+
# # States:
29+
# - `phi(t)`: [`rad`] Absolute rotation angle of flange
30+
# - `tau(t)`: [`N.m`] Cut torque in the flange
31+
# """ Flange
32+
33+
# @connector function InternalSupport(; name, tau)
34+
# @named flange = Flange()
35+
# @variables phi(t)=0 [description = "Rotation angle of support $name"]
36+
# # tau(t), [connect = Flow, description = "Cut torque in support $name"],)
37+
# equations = [flange.tau ~ tau
38+
# flange.phi ~ phi]
39+
# ODESystem(equations, t, [phi], [], name = name, systems = [flange]) # NOTE: tau not included since it belongs elsewhere
40+
# end
4141

4242
Base.@doc """
4343
Support(;name)

test/Mechanical/rotational.jl

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ D = Differential(t)
2525

2626
prob = ODEProblem(sys, Pair[], (0, 10.0))
2727
sol = solve(prob, Rodas4())
28-
@test sol.retcode == Success
28+
@test SciMLBase.successful_retcode(sol)
2929

3030
prob = ODAEProblem(sys, Pair[], (0, 10.0))
3131
sol = solve(prob, Rodas4())
32-
@test sol.retcode == Success
32+
@test SciMLBase.successful_retcode(sol)
3333

3434
prob = DAEProblem(sys, D.(states(sys)) .=> 0.0, Pair[], (0, 10.0))
3535
sol = solve(prob, DFBDF())
36-
@test sol.retcode == Success
36+
@test SciMLBase.successful_retcode(sol)
3737
@test all(sol[inertia1.w] .== 0)
3838
@test sol[inertia2.w][end]0 atol=1e-3 # all energy has dissipated
3939

@@ -48,7 +48,7 @@ end
4848
@named fixed = Fixed()
4949
@named torque = Torque(use_support = true)
5050
@named inertia1 = Inertia(J = 2, phi_start = pi / 2)
51-
@named spring = Spring(c = 1e4)
51+
@named spring = Rotational.Spring(c = 1e4)
5252
@named damper = Damper(d = 10)
5353
@named inertia2 = Inertia(J = 4)
5454
@named sine = Blocks.Sine(amplitude = amplitude, frequency = frequency)
@@ -73,17 +73,37 @@ end
7373
prob = DAEProblem(sys, D.(states(sys)) .=> 0.0,
7474
[D(D(inertia2.phi)) => 1.0; D.(states(model)) .=> 0.0], (0, 10.0))
7575
sol = solve(prob, DFBDF())
76-
@test sol.retcode == Success
76+
@test SciMLBase.successful_retcode(sol)
7777

7878
prob = ODAEProblem(sys, Pair[], (0, 1.0))
7979
sol = solve(prob, Rodas4())
80-
@test sol.retcode == Success
80+
@test SciMLBase.successful_retcode(sol)
8181

82-
@test_skip begin
83-
@test sol.retcode == Success
84-
@test all(isapprox.(sol[inertia1.w], -sol[inertia2.w] * 2, atol = 1)) # exact opposite oscillation with smaller amplitude J2 = 2*J1
85-
@test_broken all(sol[torque.flange.tau] .== -sol[sine.output.u]) # torque source is equal to negative sine
86-
end
82+
@test all(isapprox.(sol[inertia1.w], -sol[inertia2.w] * 2, atol = 1)) # exact opposite oscillation with smaller amplitude J2 = 2*J1
83+
@test all(sol[torque.flange.tau] .== -sol[sine.output.u]) # torque source is equal to negative sine
84+
85+
## Test with constant torque source
86+
@named torque = ConstantTorque(use_support = true, tau_constant = 1)
87+
connections = [connect(torque.support, fixed.flange)
88+
connect(torque.flange, inertia1.flange_a)
89+
connect(inertia1.flange_b, spring.flange_a, damper.flange_a)
90+
connect(spring.flange_b, damper.flange_b, inertia2.flange_a)]
91+
92+
@named model = ODESystem(connections, t,
93+
systems = [
94+
fixed,
95+
torque,
96+
inertia1,
97+
inertia2,
98+
spring,
99+
damper,
100+
])
101+
sys = structural_simplify(model)
102+
103+
prob = ODEProblem(sys, Pair[], (0, 10.0))
104+
sol = solve(prob, Rodas4())
105+
@test SciMLBase.successful_retcode(sol)
106+
@test sol(sol.t[end], idxs = inertia1.w)sol(sol.t[end], idxs = inertia2.w) rtol=0.1 # both inertias have same angular velocity after initial transient
87107
end
88108

89109
# see: https://doc.modelica.org/Modelica%204.0.0/Resources/helpWSM/Modelica/Modelica.Mechanics.Rotational.Examples.First.html
@@ -132,7 +152,7 @@ end
132152
sys = structural_simplify(model) #key 7 not found
133153
prob = ODAEProblem(sys, Pair[], (0, 1.0))
134154
sol = solve(prob, Rodas4())
135-
@test sol.retcode == Success
155+
@test SciMLBase.successful_retcode(sol)
136156
end
137157
# Plots.plot(sol; vars=[inertia2.w, inertia3.w])
138158
end
@@ -181,7 +201,7 @@ end
181201
prob = DAEProblem(sys, D.(states(sys)) .=> 0.0, Pair[], (0, 10.0))
182202

183203
sol = solve(prob, DFBDF())
184-
@test sol.retcode == Success
204+
@test SciMLBase.successful_retcode(sol)
185205
@test sol[angle_sensor.phi.u] == sol[inertia.flange_a.phi]
186206

187207
# p1 = Plots.plot(sol; vars=[inertia.flange_a.phi, source.phi], title="Angular Position", labels=["Inertia" "Source"], ylabel="Angle in rad")
@@ -218,7 +238,7 @@ end
218238

219239
prob = ODEProblem(sys, Pair[], (0, 10.0))
220240
sol = solve(prob, Rodas4())
221-
@test sol.retcode == Success
241+
@test SciMLBase.successful_retcode(sol)
222242
@test all(sol[inertia1.w] .== 0)
223243
@test all(sol[inertia1.w] .== sol[speed_sensor.w.u])
224244
@test sol[inertia2.w][end]0 atol=1e-3 # all energy has dissipated
@@ -227,7 +247,7 @@ end
227247

228248
prob = DAEProblem(sys, D.(states(sys)) .=> 0.0, Pair[], (0, 10.0))
229249
sol = solve(prob, DFBDF())
230-
@test sol.retcode == Success
250+
@test SciMLBase.successful_retcode(sol)
231251
@test all(sol[inertia1.w] .== 0)
232252
@test all(sol[inertia1.w] .== sol[speed_sensor.w.u])
233253
@test sol[inertia2.w][end]0 atol=1e-3 # all energy has dissipated

0 commit comments

Comments
 (0)