Skip to content
LIBRARY
Logical.Tests.LogicGates.md

Logical.Tests.LogicGates

Validation test for logic gate blocks: And, Or, Xor, Nand, Nor.

Uses a Ramp source with height=4, duration=4: ramp(t) = offset + t. Two GreaterThreshold blocks convert ramp to Boolean by comparing against thresholds at -100 (always true) or 100 (always false).

Four test cases cover the full truth table by overriding thresholds:

  • TT (both true): bool1.threshold=-100, bool2.threshold=-100

  • TF (true,false): bool1.threshold=-100, bool2.threshold=100

  • FT (false,true): bool1.threshold=100, bool2.threshold=-100

  • FF (both false): bool1.threshold=100, bool2.threshold=100

Usage

BlockComponents.Logical.Tests.LogicGates()

Behavior

julia
using BlockComponents #hide
using ModelingToolkit #hide
@named sys = BlockComponents.Logical.Tests.LogicGates() #hide
let eqs = full_equations(sys); Base.length(eqs) > 25 ? nothing : eqs end #hide
<< @example-block not executed in draft mode >>

Source

dyad
"""
Validation test for logic gate blocks: And, Or, Xor, Nand, Nor.

Uses a Ramp source with height=4, duration=4: ramp(t) = offset + t.
Two GreaterThreshold blocks convert ramp to Boolean by comparing against
thresholds at -100 (always true) or 100 (always false).

Four test cases cover the full truth table by overriding thresholds:
- TT (both true):  bool1.threshold=-100, bool2.threshold=-100
- TF (true,false): bool1.threshold=-100, bool2.threshold=100
- FT (false,true): bool1.threshold=100,  bool2.threshold=-100
- FF (both false): bool1.threshold=100,  bool2.threshold=100
"""
test component LogicGates
  "Ramp: ramp(t) = offset + t for t in [0, 4]"
  ramp = BlockComponents.Sources.Ramp(height = 4, duration = 4, offset = 0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 20, "y1": 230, "x2": 120, "y2": 330, "rot": 0}
      },
      "tags": []
    }
  }
  "Boolean input 1: threshold=-100 means always true by default"
  bool1 = BlockComponents.Logical.GreaterThreshold(threshold = -100.0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 161, "y1": 230, "x2": 261, "y2": 330, "rot": 0}
      },
      "tags": []
    }
  }
  "Boolean input 2: threshold=-100 means always true by default"
  bool2 = BlockComponents.Logical.GreaterThreshold(threshold = -100.0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 161, "y1": 406, "x2": 261, "y2": 506, "rot": 0}
      },
      "tags": []
    }
  }
  "Logic gates under test"
  and1 = BlockComponents.Logical.And() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 380, "x2": 411, "y2": 480, "rot": 0}
      },
      "tags": []
    }
  }
  or1 = BlockComponents.Logical.Or() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 500, "x2": 411, "y2": 600, "rot": 0}
      },
      "tags": []
    }
  }
  xor1 = BlockComponents.Logical.Xor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 320, "y1": 20, "x2": 420, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  nand1 = BlockComponents.Logical.Nand() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 140, "x2": 411, "y2": 240, "rot": 0}
      },
      "tags": []
    }
  }
  nor1 = BlockComponents.Logical.Nor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 260, "x2": 411, "y2": 360, "rot": 0}
      },
      "tags": []
    }
  }
relations
  # Boolean signal generation from ramp
  connect(ramp.y, bool1.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(ramp.y, bool2.u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 140, "y": 456}], "E": 2}],
      "junctions": [{"x": 140, "y": 280}],
      "renderStyle": "standard"
    }
  }
  # All gates: bool1 → u1, bool2 → u2
  connect(bool1.y, and1.u1) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [], "E": -2},
        {"S": -2, "M": [], "E": 2}
      ],
      "junctions": [{"x": 291, "y": 280}, {"x": 291, "y": 400}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, and1.u2) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bool1.y, or1.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 291, "y": 280}, {"x": 291, "y": 520}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, or1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 281, "y": 576}], "E": 2}],
      "junctions": [{"x": 281, "y": 456}],
      "renderStyle": "standard"
    }
  }
  connect(bool1.y, xor1.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 291, "y": 280}, {"x": 291, "y": 40}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, xor1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 281, "y": 456}, {"x": 281, "y": 96}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bool1.y, nand1.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 291, "y": 280}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 291, "y": 160}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, nand1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 281, "y": 456}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 281, "y": 216}],
      "renderStyle": "standard"
    }
  }
  connect(bool1.y, nor1.u1) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bool2.y, nor1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 281, "y": 456}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 281, "y": 336}],
      "renderStyle": "standard"
    }
  }
metadata {
  "Dyad": {
    "icons": {"default": "dyad://BlockComponents/Example.svg"},
    "tests": {
      "TT": {
        "stop": 1,
        "params": {"bool1.threshold": -100, "bool2.threshold": -100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      },
      "TF": {
        "stop": 1,
        "params": {"bool1.threshold": -100, "bool2.threshold": 100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      },
      "FT": {
        "stop": 1,
        "params": {"bool1.threshold": 100, "bool2.threshold": -100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      },
      "FF": {
        "stop": 1,
        "params": {"bool1.threshold": 100, "bool2.threshold": 100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      }
    }
  }
}
end
Flattened Source
dyad
"""
Validation test for logic gate blocks: And, Or, Xor, Nand, Nor.

Uses a Ramp source with height=4, duration=4: ramp(t) = offset + t.
Two GreaterThreshold blocks convert ramp to Boolean by comparing against
thresholds at -100 (always true) or 100 (always false).

Four test cases cover the full truth table by overriding thresholds:
- TT (both true):  bool1.threshold=-100, bool2.threshold=-100
- TF (true,false): bool1.threshold=-100, bool2.threshold=100
- FT (false,true): bool1.threshold=100,  bool2.threshold=-100
- FF (both false): bool1.threshold=100,  bool2.threshold=100
"""
test component LogicGates
  "Ramp: ramp(t) = offset + t for t in [0, 4]"
  ramp = BlockComponents.Sources.Ramp(height = 4, duration = 4, offset = 0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 20, "y1": 230, "x2": 120, "y2": 330, "rot": 0}
      },
      "tags": []
    }
  }
  "Boolean input 1: threshold=-100 means always true by default"
  bool1 = BlockComponents.Logical.GreaterThreshold(threshold = -100.0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 161, "y1": 230, "x2": 261, "y2": 330, "rot": 0}
      },
      "tags": []
    }
  }
  "Boolean input 2: threshold=-100 means always true by default"
  bool2 = BlockComponents.Logical.GreaterThreshold(threshold = -100.0) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 161, "y1": 406, "x2": 261, "y2": 506, "rot": 0}
      },
      "tags": []
    }
  }
  "Logic gates under test"
  and1 = BlockComponents.Logical.And() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 380, "x2": 411, "y2": 480, "rot": 0}
      },
      "tags": []
    }
  }
  or1 = BlockComponents.Logical.Or() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 500, "x2": 411, "y2": 600, "rot": 0}
      },
      "tags": []
    }
  }
  xor1 = BlockComponents.Logical.Xor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 320, "y1": 20, "x2": 420, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  nand1 = BlockComponents.Logical.Nand() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 140, "x2": 411, "y2": 240, "rot": 0}
      },
      "tags": []
    }
  }
  nor1 = BlockComponents.Logical.Nor() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 311, "y1": 260, "x2": 411, "y2": 360, "rot": 0}
      },
      "tags": []
    }
  }
relations
  # Boolean signal generation from ramp
  connect(ramp.y, bool1.u) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(ramp.y, bool2.u) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 140, "y": 456}], "E": 2}],
      "junctions": [{"x": 140, "y": 280}],
      "renderStyle": "standard"
    }
  }
  # All gates: bool1 → u1, bool2 → u2
  connect(bool1.y, and1.u1) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [], "E": -2},
        {"S": -2, "M": [], "E": 2}
      ],
      "junctions": [{"x": 291, "y": 280}, {"x": 291, "y": 400}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, and1.u2) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bool1.y, or1.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 291, "y": 280}, {"x": 291, "y": 520}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, or1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 281, "y": 576}], "E": 2}],
      "junctions": [{"x": 281, "y": 456}],
      "renderStyle": "standard"
    }
  }
  connect(bool1.y, xor1.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 291, "y": 280}, {"x": 291, "y": 40}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, xor1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 281, "y": 456}, {"x": 281, "y": 96}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(bool1.y, nand1.u1) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 291, "y": 280}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 291, "y": 160}],
      "renderStyle": "standard"
    }
  }
  connect(bool2.y, nand1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 281, "y": 456}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 281, "y": 216}],
      "renderStyle": "standard"
    }
  }
  connect(bool1.y, nor1.u1) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bool2.y, nor1.u2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 281, "y": 456}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 281, "y": 336}],
      "renderStyle": "standard"
    }
  }
metadata {
  "Dyad": {
    "icons": {"default": "dyad://BlockComponents/Example.svg"},
    "tests": {
      "TT": {
        "stop": 1,
        "params": {"bool1.threshold": -100, "bool2.threshold": -100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      },
      "TF": {
        "stop": 1,
        "params": {"bool1.threshold": -100, "bool2.threshold": 100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      },
      "FT": {
        "stop": 1,
        "params": {"bool1.threshold": 100, "bool2.threshold": -100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      },
      "FF": {
        "stop": 1,
        "params": {"bool1.threshold": 100, "bool2.threshold": 100},
        "expect": {
          "signals": ["bool1.y", "bool2.y", "and1.y", "or1.y", "xor1.y", "nand1.y", "nor1.y"]
        }
      }
    }
  }
}
end


Test 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 TT

julia
@named model_TT = BlockComponents.Logical.Tests.LogicGates(bool1.threshold=-100, bool2.threshold=-100)
model_TT = toggle_namespacing(model_TT, false)

model_TT = toggle_namespacing(model_TT, true)
result_TT = TransientAnalysis(; model = model_TT, alg = ODEAlg.Auto(), start = 0e+0, stop = 1e+0, abstol=1e-6, reltol=1e-6)
sol_TT = rebuild_sol(result_TT)
<< @setup-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.bool1.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.bool1.y], width=2, label="Actual value of bool1.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of bool1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.bool2.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.bool2.y], width=2, label="Actual value of bool2.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of bool2.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.and1.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.and1.y], width=2, label="Actual value of and1.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of and1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.or1.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.or1.y], width=2, label="Actual value of or1.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of or1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.xor1.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig4.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.xor1.y], width=2, label="Actual value of xor1.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of xor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.nand1.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig5.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.nand1.y], width=2, label="Actual value of nand1.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of nand1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TT = DataFrame(:t => sol_TT[:t], :actual => sol_TT[model_TT.nor1.y])
dfr_TT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TT_sig6.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TT, idxs=[model_TT.nor1.y], width=2, label="Actual value of nor1.y")
if !isnothing(dfr_TT)
  scatter!(plt, dfr_TT.t, dfr_TT.expected, mc=:red, ms=3, label="Expected value of nor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>

Test Case TF

julia
@named model_TF = BlockComponents.Logical.Tests.LogicGates(bool1.threshold=-100, bool2.threshold=100)
model_TF = toggle_namespacing(model_TF, false)

model_TF = toggle_namespacing(model_TF, true)
result_TF = TransientAnalysis(; model = model_TF, alg = ODEAlg.Auto(), start = 0e+0, stop = 1e+0, abstol=1e-6, reltol=1e-6)
sol_TF = rebuild_sol(result_TF)
<< @setup-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.bool1.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.bool1.y], width=2, label="Actual value of bool1.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of bool1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.bool2.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.bool2.y], width=2, label="Actual value of bool2.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of bool2.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.and1.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.and1.y], width=2, label="Actual value of and1.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of and1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.or1.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.or1.y], width=2, label="Actual value of or1.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of or1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.xor1.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig4.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.xor1.y], width=2, label="Actual value of xor1.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of xor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.nand1.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig5.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.nand1.y], width=2, label="Actual value of nand1.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of nand1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_TF = DataFrame(:t => sol_TF[:t], :actual => sol_TF[model_TF.nor1.y])
dfr_TF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_TF_sig6.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_TF, idxs=[model_TF.nor1.y], width=2, label="Actual value of nor1.y")
if !isnothing(dfr_TF)
  scatter!(plt, dfr_TF.t, dfr_TF.expected, mc=:red, ms=3, label="Expected value of nor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>

Test Case FT

julia
@named model_FT = BlockComponents.Logical.Tests.LogicGates(bool1.threshold=100, bool2.threshold=-100)
model_FT = toggle_namespacing(model_FT, false)

model_FT = toggle_namespacing(model_FT, true)
result_FT = TransientAnalysis(; model = model_FT, alg = ODEAlg.Auto(), start = 0e+0, stop = 1e+0, abstol=1e-6, reltol=1e-6)
sol_FT = rebuild_sol(result_FT)
<< @setup-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.bool1.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.bool1.y], width=2, label="Actual value of bool1.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of bool1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.bool2.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.bool2.y], width=2, label="Actual value of bool2.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of bool2.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.and1.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.and1.y], width=2, label="Actual value of and1.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of and1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.or1.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.or1.y], width=2, label="Actual value of or1.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of or1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.xor1.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig4.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.xor1.y], width=2, label="Actual value of xor1.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of xor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.nand1.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig5.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.nand1.y], width=2, label="Actual value of nand1.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of nand1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FT = DataFrame(:t => sol_FT[:t], :actual => sol_FT[model_FT.nor1.y])
dfr_FT = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FT_sig6.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FT, idxs=[model_FT.nor1.y], width=2, label="Actual value of nor1.y")
if !isnothing(dfr_FT)
  scatter!(plt, dfr_FT.t, dfr_FT.expected, mc=:red, ms=3, label="Expected value of nor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>

Test Case FF

julia
@named model_FF = BlockComponents.Logical.Tests.LogicGates(bool1.threshold=100, bool2.threshold=100)
model_FF = toggle_namespacing(model_FF, false)

model_FF = toggle_namespacing(model_FF, true)
result_FF = TransientAnalysis(; model = model_FF, alg = ODEAlg.Auto(), start = 0e+0, stop = 1e+0, abstol=1e-6, reltol=1e-6)
sol_FF = rebuild_sol(result_FF)
<< @setup-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.bool1.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.bool1.y], width=2, label="Actual value of bool1.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of bool1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.bool2.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.bool2.y], width=2, label="Actual value of bool2.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of bool2.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.and1.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig2.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.and1.y], width=2, label="Actual value of and1.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of and1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.or1.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig3.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.or1.y], width=2, label="Actual value of or1.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of or1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.xor1.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig4.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.xor1.y], width=2, label="Actual value of xor1.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of xor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.nand1.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig5.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.nand1.y], width=2, label="Actual value of nand1.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of nand1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>
julia
df_FF = DataFrame(:t => sol_FF[:t], :actual => sol_FF[model_FF.nor1.y])
dfr_FF = try CSV.read(joinpath(snapshotsdir, "BlockComponents.Logical.Tests.LogicGates_FF_sig6.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_FF, idxs=[model_FF.nor1.y], width=2, label="Actual value of nor1.y")
if !isnothing(dfr_FF)
  scatter!(plt, dfr_FF.t, dfr_FF.expected, mc=:red, ms=3, label="Expected value of nor1.y")
end
<< @setup-block not executed in draft mode >>
julia
plt
<< @example-block not executed in draft mode >>