LIBRARY
Sources.Tests.Torque2
Test for Torque2: two inertias driven by a torque acting between them, matching the MSL test topology.
SpeedSource (sine, f=1 Hz) → inertia_a (J=3) → Torque2 → inertia_b (J=3) ↑ sine (f=1 Hz)
inertia_b is free on its outer flange. With tau = sin(2πt), and the flow sign convention at the connection (connect sums flow to zero), inertia_b sees +tau:
J_b * a_b = +tau → a_b = sin(2πt)/3
w_b(t) = (1 - cos(2πt))/(6π)
At t=1.0: w_b = 0
phi_b(t) = t/(6π) - sin(2πt)/(12π²)
At t=1.0: phi_b ≈ 1/(6π) ≈ 0.05305
Usage
RotationalComponents.Sources.Tests.Torque2()
Behavior
julia
using RotationalComponents #hide
using ModelingToolkit #hide
@named sys = RotationalComponents.Sources.Tests.Torque2() #hide
full_equations(sys) #hide<< @example-block not executed in draft mode >>Source
dyad
"""
Test for Torque2: two inertias driven by a torque acting between them, matching the MSL test topology.
SpeedSource (sine, f=1 Hz) → inertia_a (J=3) → Torque2 → inertia_b (J=3)
↑
sine (f=1 Hz)
inertia_b is free on its outer flange. With tau = sin(2πt), and the flow sign
convention at the connection (connect sums flow to zero), inertia_b sees +tau:
- J_b * a_b = +tau → a_b = sin(2πt)/3
- w_b(t) = (1 - cos(2πt))/(6π)
- At t=1.0: w_b = 0
- phi_b(t) = t/(6π) - sin(2πt)/(12π²)
- At t=1.0: phi_b ≈ 1/(6π) ≈ 0.05305
"""
test component Torque2
"Fixed support for speed source"
fixed = RotationalComponents.Components.Fixed()
"Sine signal for speed reference (amplitude=1, f=1 Hz)"
speed_sine = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1)
"Speed source prescribing inertia_a velocity (Exact mode)"
speed = RotationalComponents.Sources.SpeedSource(ref_type = RotationalComponents.Sources.ReferenceType.Exact())
"First inertia (J=3), speed-driven side"
inertia_a = RotationalComponents.Components.Inertia(J = 3)
"Torque2 under test"
torque2 = RotationalComponents.Sources.Torque2()
"Sine signal for torque input (amplitude=1, f=1 Hz)"
torque_sine = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1)
"Second inertia (J=3), free side"
inertia_b = RotationalComponents.Components.Inertia(J = 3)
relations
initial inertia_a.phi = 0
initial inertia_b.phi = 0
initial inertia_b.w = 0
connect(speed_sine.y, speed.w_ref)
connect(speed.support, fixed.spline)
connect(speed.spline, inertia_a.spline_a)
connect(inertia_a.spline_b, torque2.spline_a)
connect(torque2.spline_b, inertia_b.spline_a)
connect(torque_sine.y, torque2.tau)
metadata {
"Dyad": {
"icons": {"default": "dyad://RotationalComponents/Example.svg"},
"tests": {
"case1": {
"stop": 1,
"atol": {"inertia_b.phi": 0.001, "inertia_b.w": 0.001, "inertia_a.w": 0.001},
"expect": {
"initial": {"inertia_a.phi": 0, "inertia_b.phi": 0, "inertia_b.w": 0},
"final": {"inertia_b.phi": 0.05305, "inertia_b.w": 0, "inertia_a.w": 0},
"signals": ["inertia_b.phi", "inertia_b.w", "inertia_a.w", "inertia_a.phi"]
}
}
}
}
}
endFlattened Source
dyad
"""
Test for Torque2: two inertias driven by a torque acting between them, matching the MSL test topology.
SpeedSource (sine, f=1 Hz) → inertia_a (J=3) → Torque2 → inertia_b (J=3)
↑
sine (f=1 Hz)
inertia_b is free on its outer flange. With tau = sin(2πt), and the flow sign
convention at the connection (connect sums flow to zero), inertia_b sees +tau:
- J_b * a_b = +tau → a_b = sin(2πt)/3
- w_b(t) = (1 - cos(2πt))/(6π)
- At t=1.0: w_b = 0
- phi_b(t) = t/(6π) - sin(2πt)/(12π²)
- At t=1.0: phi_b ≈ 1/(6π) ≈ 0.05305
"""
test component Torque2
"Fixed support for speed source"
fixed = RotationalComponents.Components.Fixed()
"Sine signal for speed reference (amplitude=1, f=1 Hz)"
speed_sine = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1)
"Speed source prescribing inertia_a velocity (Exact mode)"
speed = RotationalComponents.Sources.SpeedSource(ref_type = RotationalComponents.Sources.ReferenceType.Exact())
"First inertia (J=3), speed-driven side"
inertia_a = RotationalComponents.Components.Inertia(J = 3)
"Torque2 under test"
torque2 = RotationalComponents.Sources.Torque2()
"Sine signal for torque input (amplitude=1, f=1 Hz)"
torque_sine = BlockComponents.Sources.Sine(amplitude = 1, frequency = 1)
"Second inertia (J=3), free side"
inertia_b = RotationalComponents.Components.Inertia(J = 3)
relations
initial inertia_a.phi = 0
initial inertia_b.phi = 0
initial inertia_b.w = 0
connect(speed_sine.y, speed.w_ref)
connect(speed.support, fixed.spline)
connect(speed.spline, inertia_a.spline_a)
connect(inertia_a.spline_b, torque2.spline_a)
connect(torque2.spline_b, inertia_b.spline_a)
connect(torque_sine.y, torque2.tau)
metadata {
"Dyad": {
"icons": {"default": "dyad://RotationalComponents/Example.svg"},
"tests": {
"case1": {
"stop": 1,
"atol": {"inertia_b.phi": 0.001, "inertia_b.w": 0.001, "inertia_a.w": 0.001},
"expect": {
"initial": {"inertia_a.phi": 0, "inertia_b.phi": 0, "inertia_b.w": 0},
"final": {"inertia_b.phi": 0.05305, "inertia_b.w": 0, "inertia_a.w": 0},
"signals": ["inertia_b.phi", "inertia_b.w", "inertia_a.w", "inertia_a.phi"]
}
}
}
}
}
endTest Cases
julia
using RotationalComponents
using DyadInterface: TransientAnalysis, rebuild_sol, ODEAlg
using ModelingToolkit: toggle_namespacing, get_initial_conditions, @named
using CSV, DataFrames, Plots
snapshotsdir = joinpath(dirname(dirname(pathof(RotationalComponents))), "test", "snapshots")<< @setup-block not executed in draft mode >>Test Case case1
julia
@named model_case1 = RotationalComponents.Sources.Tests.Torque2()
model_case1 = toggle_namespacing(model_case1, false)
model_case1 = toggle_namespacing(model_case1, true)
result_case1 = TransientAnalysis(; model = model_case1, alg = ODEAlg.Auto(), start = 0e+0, stop = 1e+0, abstol=1e-6, reltol=1e-6)
sol_case1 = rebuild_sol(result_case1)<< @setup-block not executed in draft mode >>julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.inertia_b.phi])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "RotationalComponents.Sources.Tests.Torque2_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.inertia_b.phi], width=2, label="Actual value of inertia_b.phi")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of inertia_b.phi")
end
scatter!(plt, [df_case1.t[1]], [0], label="Initial Condition for `inertia_b.phi`")
scatter!(plt, [df_case1.t[end]], [0.05305], label="Final Condition for `inertia_b.phi`")<< @setup-block not executed in draft mode >>julia
plt<< @example-block not executed in draft mode >>julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.inertia_b.w])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "RotationalComponents.Sources.Tests.Torque2_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.inertia_b.w], width=2, label="Actual value of inertia_b.w")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of inertia_b.w")
end
scatter!(plt, [df_case1.t[1]], [0], label="Initial Condition for `inertia_b.w`")
scatter!(plt, [df_case1.t[end]], [0], label="Final Condition for `inertia_b.w`")<< @setup-block not executed in draft mode >>julia
plt<< @example-block not executed in draft mode >>julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.inertia_a.w])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "RotationalComponents.Sources.Tests.Torque2_case1_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.inertia_a.w], width=2, label="Actual value of inertia_a.w")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of inertia_a.w")
end
scatter!(plt, [df_case1.t[end]], [0], label="Final Condition for `inertia_a.w`")<< @setup-block not executed in draft mode >>julia
plt<< @example-block not executed in draft mode >>julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.inertia_a.phi])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "RotationalComponents.Sources.Tests.Torque2_case1_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.inertia_a.phi], width=2, label="Actual value of inertia_a.phi")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of inertia_a.phi")
end
scatter!(plt, [df_case1.t[1]], [0], label="Initial Condition for `inertia_a.phi`")<< @setup-block not executed in draft mode >>julia
plt<< @example-block not executed in draft mode >>Related
Examples
Experiments
Analyses
Tests