Skip to content
ExpSineTest.md

ExpSineTest

Test component that connects an exponentially damped sine wave to an integrator for validation.

This component instantiates an ExpSine signal generator with configurable parameters and connects its output to an Integrator block to test the integration of a damped sinusoidal signal. The ExpSine generates a signal according to:

y=offset+amplitudeedamping(tstart_time)sin(frequency(tstart_time)+phase)

Usage

ExpSineTest()

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.amplitudeesignal.damping(signal.start_time+t)sin(signal.phase+6.2832signal.frequency(signal.start_time+t)),signal.offset)

Source

dyad
# Test component that connects an exponentially damped sine wave to an integrator for validation.
#
# This component instantiates an ExpSine signal generator with configurable parameters and connects
# its output to an Integrator block to test the integration of a damped sinusoidal signal. The ExpSine
# generates a signal according to:
#
# ```math
# y = offset + amplitude \cdot e^{-damping \cdot (t-start\_time)} \cdot \sin(frequency \cdot (t-start\_time) + phase)
# ```
test component ExpSineTest
  # Integrator block that accumulates the input signal
  integrator = Integrator()
  # Exponentially damped sine wave generator with specified parameters
  signal = ExpSine(amplitude=1, damping=0.5, frequency=2, start_time=0.5, offset=0.5, phase=3.14)
relations
  # Connects the exponentially damped sine output to the integrator input
  connect(signal.y, integrator.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 7,
        "atol": {"signal.y": 0.001, "integrator.x": 0.001},
        "expect": {
          "initial": {"signal.y": 0.5},
          "signals": ["signal.y", "integrator.x"],
          "final": {"signal.y": 0.50006, "integrator.x": 3.41826}
        }
      }
    }
  }
}
end
Flattened Source
dyad
# Test component that connects an exponentially damped sine wave to an integrator for validation.
#
# This component instantiates an ExpSine signal generator with configurable parameters and connects
# its output to an Integrator block to test the integration of a damped sinusoidal signal. The ExpSine
# generates a signal according to:
#
# ```math
# y = offset + amplitude \cdot e^{-damping \cdot (t-start\_time)} \cdot \sin(frequency \cdot (t-start\_time) + phase)
# ```
test component ExpSineTest
  # Integrator block that accumulates the input signal
  integrator = Integrator()
  # Exponentially damped sine wave generator with specified parameters
  signal = ExpSine(amplitude=1, damping=0.5, frequency=2, start_time=0.5, offset=0.5, phase=3.14)
relations
  # Connects the exponentially damped sine output to the integrator input
  connect(signal.y, integrator.u)
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 7,
        "atol": {"signal.y": 0.001, "integrator.x": 0.001},
        "expect": {
          "initial": {"signal.y": 0.5},
          "signals": ["signal.y", "integrator.x"],
          "final": {"signal.y": 0.50006, "integrator.x": 3.41826}
        }
      }
    }
  }
}
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 = ExpSineTest()
u0_case1 = []
prob_case1 = ODEProblem(model_case1, u0_case1, (0, 7))
sol_case1 = solve(prob_case1)
retcode: Success
Interpolation: 3rd order Hermite
t: 30-element Vector{Float64}:
 0.0
 9.999999999999999e-5
 0.0010999999999999998
 0.011099999999999997
 0.11109999999999996
 0.38454929438966845
 0.607288600111156
 0.7057957872145424
 0.8618031037063139
 0.9999891212569498

 3.7013822366936813
 3.991338044134852
 4.295707204082095
 4.633069320228226
 5.012073599779496
 5.354083478672929
 5.922443943630637
 6.412574619721399
 7.0
u: 30-element Vector{Vector{Float64}}:
 [0.0]
 [4.999999999999998e-5]
 [0.0005499999999999998]
 [0.005549999999999997]
 [0.05554999999999997]
 [0.19227464719483417]
 [0.23637515358134645]
 [0.20663228333237232]
 [0.3303088525611885]
 [0.4749259033120527]

 [1.7510939933674825]
 [1.9223745251990512]
 [2.050692436219378]
 [2.2291396776918213]
 [2.4268837081626273]
 [2.5875329592386884]
 [2.8796747340609663]
 [3.1241351945198956]
 [3.4182640461981553]
julia
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.signal.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "ExpSineTest_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]], [0.50006], 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, "ExpSineTest_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]], [3.41826], label="Final Condition for `integrator.x`")

plt