LIBRARY
Math.Tests.Log10
Computes the base-10 logarithm of constant and time-varying inputs.
Connects a constant source with value 100 to a Log10 block and verifies that log10(100) = 2. A second Log10 block is driven by a sine wave (offset 5.5, amplitude 4.5) that stays strictly positive (1..10) as required by the logarithm domain while varying over time.
Usage
BlockComponents.Math.Tests.Log10()
Behavior
julia
using BlockComponents #hide
using ModelingToolkit #hide
@named sys = BlockComponents.Math.Tests.Log10() #hide
let eqs = full_equations(sys); Base.length(eqs) > 25 ? nothing : eqs end #hide<< @example-block not executed in draft mode >>Source
dyad
"""
Computes the base-10 logarithm of constant and time-varying inputs.
Connects a constant source with value 100 to a Log10 block and verifies that
log10(100) = 2. A second Log10 block is driven by a sine wave (offset 5.5,
amplitude 4.5) that stays strictly positive (1..10) as required by the
logarithm domain while varying over time.
"""
test component Log10
"Constant source providing the input value"
c1 = BlockComponents.Sources.Constant(k = 100) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 20, "y1": 20, "x2": 120, "y2": 120, "rot": 0}
},
"tags": []
}
}
"Sine source kept strictly positive for the log domain"
sine = BlockComponents.Sources.Sine(amplitude = 4.5, frequency = 1, offset = 5.5) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 20, "y1": 140, "x2": 120, "y2": 240, "rot": 0}
},
"tags": []
}
}
"Log10 block under test"
log10_block = BlockComponents.Math.Log10() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 160, "y1": 20, "x2": 260, "y2": 120, "rot": 0}
},
"tags": []
}
}
"Second Log10 block driven by the sine source"
log10_block_2 = BlockComponents.Math.Log10() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 160, "y1": 140, "x2": 260, "y2": 240, "rot": 0}
},
"tags": []
}
}
relations
connect(c1.y, log10_block.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(sine.y, log10_block_2.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {
"Dyad": {
"icons": {"default": "dyad://BlockComponents/Example.svg"},
"tests": {
"case1": {
"stop": 1,
"expect": {"signals": ["log10_block.y", "log10_block_2.y", "sine.y"]}
}
}
}
}
endFlattened Source
dyad
"""
Computes the base-10 logarithm of constant and time-varying inputs.
Connects a constant source with value 100 to a Log10 block and verifies that
log10(100) = 2. A second Log10 block is driven by a sine wave (offset 5.5,
amplitude 4.5) that stays strictly positive (1..10) as required by the
logarithm domain while varying over time.
"""
test component Log10
"Constant source providing the input value"
c1 = BlockComponents.Sources.Constant(k = 100) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 20, "y1": 20, "x2": 120, "y2": 120, "rot": 0}
},
"tags": []
}
}
"Sine source kept strictly positive for the log domain"
sine = BlockComponents.Sources.Sine(amplitude = 4.5, frequency = 1, offset = 5.5) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 20, "y1": 140, "x2": 120, "y2": 240, "rot": 0}
},
"tags": []
}
}
"Log10 block under test"
log10_block = BlockComponents.Math.Log10() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 160, "y1": 20, "x2": 260, "y2": 120, "rot": 0}
},
"tags": []
}
}
"Second Log10 block driven by the sine source"
log10_block_2 = BlockComponents.Math.Log10() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 160, "y1": 140, "x2": 260, "y2": 240, "rot": 0}
},
"tags": []
}
}
relations
connect(c1.y, log10_block.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(sine.y, log10_block_2.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {
"Dyad": {
"icons": {"default": "dyad://BlockComponents/Example.svg"},
"tests": {
"case1": {
"stop": 1,
"expect": {"signals": ["log10_block.y", "log10_block_2.y", "sine.y"]}
}
}
}
}
endTest Cases
julia
using BlockComponents
using DyadInterface: TransientAnalysis, rebuild_sol, ODEAlg
using ModelingToolkit: toggle_namespacing, get_initial_conditions, @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 = BlockComponents.Math.Tests.Log10()
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.log10_block.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Math.Tests.Log10_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.log10_block.y], width=2, label="Actual value of log10_block.y")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of log10_block.y")
end<< @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.log10_block_2.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Math.Tests.Log10_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.log10_block_2.y], width=2, label="Actual value of log10_block_2.y")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of log10_block_2.y")
end<< @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.sine.y])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Math.Tests.Log10_case1_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.sine.y], width=2, label="Actual value of sine.y")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of sine.y")
end<< @setup-block not executed in draft mode >>julia
plt<< @example-block not executed in draft mode >>