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

BlockComponents.ExpSineTest()

Behavior

julia
using BlockComponents #hide
using ModelingToolkit #hide
@named sys = BlockComponents.ExpSineTest() #hide
full_equations(sys) #hide
<< @example-block not executed in draft mode >>

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() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 150, "y1": 20, "x2": 250, "y2": 120, "rot": 0}
      }
    }
  }
  "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 = pi / 4) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 20, "y1": 20, "x2": 120, "y2": 120, "rot": 0}
      }
    }
  }
relations
  "Connects the exponentially damped sine output to the integrator input"
  connect(signal.y, integrator.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {
  "Dyad": {
    "icons": {"default": "dyad://BlockComponents/Example.svg"},
    "tests": {
      "case1": {
        "stop": 7,
        "atol": {"signal.y": 0.001, "integrator.x": 0.001},
        "expect": {
          "initial": {"signal.y": 1.207},
          "signals": ["signal.y", "integrator.x"],
          "final": {"signal.y": 0.527, "integrator.x": 3.91}
        }
      }
    }
  }
}
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() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 150, "y1": 20, "x2": 250, "y2": 120, "rot": 0}
      }
    }
  }
  "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 = pi / 4) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 20, "y1": 20, "x2": 120, "y2": 120, "rot": 0}
      }
    }
  }
relations
  "Connects the exponentially damped sine output to the integrator input"
  connect(signal.y, integrator.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {
  "Dyad": {
    "icons": {"default": "dyad://BlockComponents/Example.svg"},
    "tests": {
      "case1": {
        "stop": 7,
        "atol": {"signal.y": 0.001, "integrator.x": 0.001},
        "expect": {
          "initial": {"signal.y": 1.207},
          "signals": ["signal.y", "integrator.x"],
          "final": {"signal.y": 0.527, "integrator.x": 3.91}
        }
      }
    }
  }
}
end


Test Cases

julia
using BlockComponents
using DyadInterface: TransientAnalysis, rebuild_sol
using ModelingToolkit: toggle_namespacing, get_defaults, @named
using CSV, DataFrames, Plots

snapshotsdir = joinpath(dirname(dirname(pathof(BlockComponents))), "test", "snapshots")
<< @setup-block not executed in draft mode >>

Test Case case1

julia
@named model_case1 = ExpSineTest()
model_case1 = toggle_namespacing(model_case1, false)

model_case1 = toggle_namespacing(model_case1, true)
result_case1 = TransientAnalysis(; model = model_case1, alg = "auto", start = 0e+0, stop = 7e+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.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]], [1.207], label="Initial Condition for `signal.y`")
scatter!(plt, [df_case1.t[end]], [0.527], label="Final Condition for `signal.y`")
<< @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.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.91], label="Final Condition for `integrator.x`")
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>