Skip to content
LimiterTest.md

LimiterTest

Test harness for the Limiter component that constrains signals to specified bounds.

This test component creates a signal chain that feeds a high-amplitude sine wave through an integrator and then into a limiter with bounds at -3 and 3. The limiter constrains the integrated sine wave output to stay within the specified bounds, demonstrating how signal limiting works in practice. The test includes verification of expected output values.

Usage

LimiterTest()

Behavior

sine.y(t)=integrator.u(t)integrator.y(t)=limiter.u(t)limiter.y(t)=clamp(limiter.u(t),limiter.y_min,limiter.y_max)dintegrator.x(t)dt=integrator.kintegrator.u(t)integrator.y(t)=integrator.x(t)sine.y(t)=ifelse(sine.start_time<t,sine.offset+sine.amplitudesin(sine.phase+6.2832sine.frequency(sine.start_time+t)),sine.offset)

Source

dyad
# Test harness for the Limiter component that constrains signals to specified bounds.
#
# This test component creates a signal chain that feeds a high-amplitude sine wave through
# an integrator and then into a limiter with bounds at -3 and 3. The limiter constrains the
# integrated sine wave output to stay within the specified bounds, demonstrating how signal
# limiting works in practice. The test includes verification of expected output values.
test component LimiterTest
  # Limiter block that constraints signals between -3 and 3
  limiter = Limiter(y_max=3, y_min=-3)
  # Integrator block that accumulates the input signal
  integrator = Integrator()
  # Sine wave generator with large amplitude to drive the system
  sine = Sine(amplitude=4*π, frequency=1)
relations
  # Connect sine output to integrator input
  connect(sine.y, integrator.u)
  # Connect integrator output to limiter input
  connect(integrator.y, limiter.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 1,
        "expect": {"signals": ["limiter.y"], "final": {"limiter.y": 0.000086636306}}
      }
    }
  }
}
end
Flattened Source
dyad
# Test harness for the Limiter component that constrains signals to specified bounds.
#
# This test component creates a signal chain that feeds a high-amplitude sine wave through
# an integrator and then into a limiter with bounds at -3 and 3. The limiter constrains the
# integrated sine wave output to stay within the specified bounds, demonstrating how signal
# limiting works in practice. The test includes verification of expected output values.
test component LimiterTest
  # Limiter block that constraints signals between -3 and 3
  limiter = Limiter(y_max=3, y_min=-3)
  # Integrator block that accumulates the input signal
  integrator = Integrator()
  # Sine wave generator with large amplitude to drive the system
  sine = Sine(amplitude=4*π, frequency=1)
relations
  # Connect sine output to integrator input
  connect(sine.y, integrator.u)
  # Connect integrator output to limiter input
  connect(integrator.y, limiter.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 1,
        "expect": {"signals": ["limiter.y"], "final": {"limiter.y": 0.000086636306}}
      }
    }
  }
}
end


Test Cases

This is setup code, that must be run before each test case.

julia
using BlockComponents
using ModelingToolkit, OrdinaryDiffEqDefault
using Plots
using CSV, DataFrames

snapshotsdir = joinpath(dirname(dirname(pathof(BlockComponents))), "test", "snapshots")
"/home/actions-runner-10/.julia/packages/BlockComponents/77kIK/test/snapshots"

Test Case case1

julia
@mtkbuild model_case1 = LimiterTest()
u0_case1 = []
prob_case1 = ODEProblem(model_case1, u0_case1, (0, 1))
sol_case1 = solve(prob_case1)
retcode: Success
Interpolation: 3rd order Hermite
t: 13-element Vector{Float64}:
 0.0
 9.999999999999999e-5
 0.0010999999999999998
 0.011099999999999997
 0.045169799191467096
 0.1030303755070893
 0.17821776306357956
 0.27557223476943316
 0.396005612483368
 0.5458723853815644
 0.795673797180243
 0.9598499450451993
 1.0
u: 13-element Vector{Vector{Float64}}:
 [0.0]
 [3.947841630556954e-7]
 [4.776869514604149e-5]
 [0.004862164501008518]
 [0.08000902115477489]
 [0.4046412851209853]
 [1.128230452376531]
 [2.3199691101821154]
 [3.588023524690188]
 [3.917502143198791]
 [1.4339793400208956]
 [0.06339011701843185]
 [8.663630642755591e-5]
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.limiter.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "LimiterTest_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.limiter.y], width=2, label="Actual value of limiter.y")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of limiter.y")
end
scatter!(plt, [df_case1.t[end]], [0.000086636306], label="Final Condition for `limiter.y`")

plt