Skip to content
SineTest.md

SineTest

Test component that integrates a sine wave with specific parameters.

This component connects a configurable sine wave generator to an integrator and verifies correct numerical behavior through the test case in metadata. The sine wave has an amplitude of 1, frequency of 2 Hz, start time of 0.5s, offset of 0.5, and phase shift of 1.57 radians. The integrator accumulates the sine wave signal over time, and the test case verifies both signals meet expected values.

Usage

SineTest()

Behavior

signal.y(t)=integrator.u(t)dintegrator.x(t)dt=integrator.kintegrator.u(t)integrator.y(t)=integrator.x(t)signal.y(t)=ifelse(signal.start_time<t,signal.offset+signal.amplitudesin(signal.phase+6.2832signal.frequency(signal.start_time+t)),signal.offset)

Source

dyad
# Test component that integrates a sine wave with specific parameters.
#
# This component connects a configurable sine wave generator to an integrator and
# verifies correct numerical behavior through the test case in metadata. The sine
# wave has an amplitude of 1, frequency of 2 Hz, start time of 0.5s, offset of 0.5,
# and phase shift of 1.57 radians. The integrator accumulates the sine wave signal
# over time, and the test case verifies both signals meet expected values.
test component SineTest
  # Integrator that accumulates the sine wave input
  integrator = Integrator()
  # Sine wave generator with specific parameters for testing
  signal = Sine(amplitude=1, frequency=2, start_time=0.5, offset=0.5, phase=1.57)
relations
  # Connects the sine wave output to the integrator input
  connect(signal.y, integrator.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 5,
        "atol": {"signal.y": 0.001, "integrator.x": 0.001},
        "expect": {
          "initial": {"signal.y": 0.5},
          "signals": ["signal.y", "integrator.x"],
          "final": {"signal.y": 1.49999, "integrator.x": 2.54036}
        }
      }
    }
  }
}
end
Flattened Source
dyad
# Test component that integrates a sine wave with specific parameters.
#
# This component connects a configurable sine wave generator to an integrator and
# verifies correct numerical behavior through the test case in metadata. The sine
# wave has an amplitude of 1, frequency of 2 Hz, start time of 0.5s, offset of 0.5,
# and phase shift of 1.57 radians. The integrator accumulates the sine wave signal
# over time, and the test case verifies both signals meet expected values.
test component SineTest
  # Integrator that accumulates the sine wave input
  integrator = Integrator()
  # Sine wave generator with specific parameters for testing
  signal = Sine(amplitude=1, frequency=2, start_time=0.5, offset=0.5, phase=1.57)
relations
  # Connects the sine wave output to the integrator input
  connect(signal.y, integrator.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 5,
        "atol": {"signal.y": 0.001, "integrator.x": 0.001},
        "expect": {
          "initial": {"signal.y": 0.5},
          "signals": ["signal.y", "integrator.x"],
          "final": {"signal.y": 1.49999, "integrator.x": 2.54036}
        }
      }
    }
  }
}
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 = SineTest()
u0_case1 = []
prob_case1 = ODEProblem(model_case1, u0_case1, (0, 5))
sol_case1 = solve(prob_case1)
retcode: Success
Interpolation: 3rd order Hermite
t: 27-element Vector{Float64}:
 0.0
 9.999999999999999e-5
 0.0010999999999999998
 0.011099999999999997
 0.11109999999999996
 0.4322123992940966
 0.6997827070081394
 0.8187021820141794
 0.9903796302632835
 1.1510914852365013

 3.063583580538438
 3.285524826973897
 3.509682229288379
 3.746226182500011
 3.9942307347924
 4.251046205841142
 4.509554084964535
 4.76851660796056
 5.0
u: 27-element Vector{Vector{Float64}}:
 [0.0]
 [4.999999999999998e-5]
 [0.0005499999999999998]
 [0.005549999999999997]
 [0.05554999999999997]
 [0.21610619964704825]
 [0.43717229762302756]
 [0.38919350692083465]
 [0.5257869273810423]
 [0.6911608186582671]

 [1.6290844283343766]
 [1.6489185383138594]
 [1.8047629468803186]
 [1.917412830525422]
 [2.0315934917143887]
 [2.1650554128522965]
 [2.304505389637837]
 [2.406527078856014]
 [2.5403603171209603]
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.signal.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "SineTest_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.signal.y], width=2, label="Actual value of signal.y")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of signal.y")
end
scatter!(plt, [df_case1.t[1]], [0.5], label="Initial Condition for `signal.y`")
scatter!(plt, [df_case1.t[end]], [1.49999], label="Final Condition for `signal.y`")

plt

julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.integrator.x])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "SineTest_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.integrator.x], width=2, label="Actual value of integrator.x")
if !isnothing(dfr_case1)
  scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of integrator.x")
end
scatter!(plt, [df_case1.t[end]], [2.54036], label="Final Condition for `integrator.x`")

plt