Skip to main content

Component

Trait Component 

Source
pub trait Component: Debug {
Show 60 methods // Required methods fn clone_box(&self) -> Box<dyn Component>; fn as_any(&self) -> &dyn Any; fn as_any_mut(&mut self) -> &mut dyn Any; fn dyn_eq(&self, other: &dyn Component) -> bool; fn type_tag(&self) -> &'static str; fn is_passive(&self) -> bool; fn pin_config(&self) -> PinConfig; fn graph_role(&self) -> GraphRole; fn stamp_mna( &self, comp_id: &str, n1: Option<usize>, n2: Option<usize>, mna: &mut MnaSystem, sample_rate: f64, ) -> StampResult; fn footprint_ref(&self) -> (&'static str, &'static str); // Provided methods fn solver_hint(&self) -> Option<SolverMethod> { ... } fn ports(&self) -> Vec<(&'static str, &'static str)> { ... } fn nonideal_fx(&self, _sample_rate: f64) -> Vec<NonIdealFx> { ... } fn output_impedance(&self) -> OutputImpedance { ... } fn signal_terminals(&self) -> SignalTerminals { ... } fn port_semantic(&self, _pin_a: &str, _pin_b: &str) -> PortSemantic { ... } fn is_nonlinear(&self) -> bool { ... } fn is_active_ic(&self) -> bool { ... } fn is_control_only(&self) -> bool { ... } fn is_variable(&self) -> bool { ... } fn modulation_pins(&self) -> &'static [&'static str] { ... } fn edges(&self) -> Vec<ComponentEdge> { ... } fn signal_adjacencies(&self) -> Vec<(&'static str, &'static str)> { ... } fn pin_direction(&self, _pin: &str) -> PinDirection { ... } fn resolve_edges( &self, _neighbors: &ResolveContext, ) -> Option<Vec<ComponentEdge>> { ... } fn mna_vsource_count(&self) -> usize { ... } fn mna_internal_node_count(&self) -> usize { ... } fn stamp_mna_multi( &self, comp_id: &str, ctx: &mut StampContext<'_>, mna: &mut MnaSystem, ) -> StampResult { ... } fn make_leaf(&self, _comp_id: &str, _sample_rate: f64) -> Option<DynNode> { ... } fn resistance(&self) -> Option<f64> { ... } fn capacitance(&self) -> Option<f64> { ... } fn inductance(&self) -> Option<f64> { ... } fn validate_values(&self, _comp_id: &str) -> Vec<(Severity, String)> { ... } fn terminal_requirements(&self) -> Vec<(&'static str, Vec<NeighborReq>)> { ... } fn classify_nonlinear( &self, _comp_id: &str, _node_a: usize, _node_b: usize, _gnd_node: usize, _node_names: &HashMap<String, usize>, ) -> Option<(NonlinearKind, Vec<usize>)> { ... } fn controls(&self) -> Vec<ControlParam> { ... } fn modulation_sink(&self, _pin: &str) -> Option<ModulationSink> { ... } fn is_modulation_source(&self) -> bool { ... } fn is_bjt(&self) -> bool { ... } fn is_jfet(&self) -> bool { ... } fn is_mosfet(&self) -> bool { ... } fn is_tube(&self) -> bool { ... } fn is_transformer(&self) -> bool { ... } fn is_pot(&self) -> bool { ... } fn is_diode_family(&self) -> bool { ... } fn is_trigger(&self) -> bool { ... } fn feedback_input_is_barrier(&self) -> bool { ... } fn k_method_spec(&self) -> Option<KMethodSpec> { ... } fn k_method_candidacy(&self) -> (bool, usize, &'static str) { ... } fn is_simple_passive(&self) -> bool { ... } fn is_gain_device(&self) -> bool { ... } fn model_name(&self) -> Option<&str> { ... } fn op_amp_type(&self) -> Option<OpAmpType> { ... } fn pot_taper(&self) -> Option<PotTaper> { ... } fn diode_type(&self) -> Option<DiodeType> { ... } fn transformer_config(&self) -> Option<&TransformerConfig> { ... } fn apply_bias( &self, _bias_voltages: &HashMap<String, f64>, _supply_voltage: f64, ) -> BiasResult { ... } fn symbol_name(&self) -> &'static str { ... } fn layout_class(&self) -> &'static str { ... } fn display_value(&self) -> Option<String> { ... }
}
Expand description

The single source of truth for circuit component behavior.

Every circuit element in PedalKernel — resistors, capacitors, op-amps, BJTs, vacuum tubes, diodes, potentiometers, transformers, BBD delay lines — implements this trait. The compilation pipeline queries these methods to determine topology, solver strategy, stage boundaries, and runtime behavior without ever pattern-matching on concrete component types.

§Trait Object Support

Component is used as Box<dyn Component> throughout the pipeline. It requires Debug for trait-object formatting and provides clone_box, as_any, and dyn_eq for trait-object Clone, downcasting, and PartialEq support.

§Method Groups

The trait methods are organized into functional groups:

§Identity

  • type_tag — human-readable name (e.g., "resistor", "NPN transistor")

§Ports

  • ports — terminal pairs carrying current. A resistor has 1 port (a, b); a BJT has 2 ports (base-emitter, collector-emitter).

§Signal Flow

  • signal_terminals — directionality for feedback analysis. Amplifiers declare input/output pins; passive components are bidirectional. The compiler uses Tarjan’s SCC algorithm on the directed signal graph to detect feedback loops.
  • output_impedance — determines stage split points. OutputImpedance::VoltageSource (op-amps in feedback) allows safe splitting; OutputImpedance::Finite (passives, BJT collectors) prevents it. Based on Harold Black’s negative feedback theorem (1934).

§Non-Idealities

  • nonideal_fx — declares physical imperfections as NonIdealFx variants. Values come from SPICE models and datasheets. The stage builder applies these as composable post-processing filters after the ideal WDF/MNA solver.

§Classification

§Graph Building

§MNA Stamping

§WDF Leaf Creation

  • make_leaf — create a runtime WDF leaf node (DynNode). Resistors, capacitors, and inductors return leaf nodes; nonlinear and virtual components return None.

§Pin Interface

  • pin_config — valid pin names and aliases
  • pin_direction — inferred direction for layout (Input, Output, Up, Down)

§Controls

  • controls — declares runtime-adjustable parameters (ControlParam). Pots declare PotPosition; LFOs declare LfoRate and LfoDepth.
  • modulation_sink — how this component receives LFO/envelope control signals, including bias voltage and modulation range.

§Validation

  • validate_values — design rule checks for suspicious or invalid component values (e.g., a 1-ohm resistor, a 1-farad capacitor).

§Implementing a New Component

To add a new component type to PedalKernel:

  1. Create a struct in super::components (e.g., MyDevice { model: String })
  2. Implement Component with at minimum:
    • type_tag() — return a human-readable name
    • is_passive() — true for R/C/L, false for active devices
    • pin_config() — declare valid pin names
    • graph_role() — how it enters the circuit graph
    • edges() — declare edge kinds (Linear, Nonlinear, etc.)
    • stamp_mna() — stamp into MNA matrices (for R-node solving)
    • footprint_ref() — KiCad symbol reference
  3. For nonlinear devices, also implement classify_nonlinear() and set is_nonlinear() -> true
  4. For active devices with feedback, implement output_impedance() and signal_terminals()
  5. Add the DSL parser variant in crate::dsl

No changes are needed in the graph builder, SPQR decomposer, stage builder, or any other pipeline module.

Required Methods§

Source

fn clone_box(&self) -> Box<dyn Component>

Clone into a boxed trait object.

Source

fn as_any(&self) -> &dyn Any

Downcast to Any for type-erased equality checks and downcasting.

Source

fn as_any_mut(&mut self) -> &mut dyn Any

Downcast to Any mutably for in-place mutation (e.g., tolerance tweaks).

Source

fn dyn_eq(&self, other: &dyn Component) -> bool

Dynamic equality: returns true if other is the same concrete type and compares equal.

Source

fn type_tag(&self) -> &'static str

Human-readable type name (e.g. “resistor”, “NPN transistor”).

Source

fn is_passive(&self) -> bool

Whether this component is passive (collectible by BFS for stage building).

Source

fn pin_config(&self) -> PinConfig

Valid pins and aliases for this component type.

Source

fn graph_role(&self) -> GraphRole

How this component participates in circuit graph construction.

Source

fn stamp_mna( &self, comp_id: &str, n1: Option<usize>, n2: Option<usize>, mna: &mut MnaSystem, sample_rate: f64, ) -> StampResult

Stamp into MNA system. Returns what was produced.

comp_id is the component’s string identifier (needed for DynNode::Pot). n1/n2 are MNA node indices (None = ground). Transformers return Skip — they need coupled-edge context from the caller.

Source

fn footprint_ref(&self) -> (&'static str, &'static str)

KiCad symbol library reference and designator prefix.

Provided Methods§

Source

fn solver_hint(&self) -> Option<SolverMethod>

Return the preferred nonlinear solver method for this component.

Returns None to accept the global default (Newton-Raphson). Returns Some(SolverMethod::WrightOmega) to request the explicit closed-form Wright Omega solver (diodes only).

The build pass uses this to choose between DiodePairRoot/DiodeRoot (NR) and ExplicitDiodePairRoot/ExplicitDiodeRoot (WO).

Source

fn ports(&self) -> Vec<(&'static str, &'static str)>

Terminal pairs carrying current through this component.

Each port = one graph edge. A resistor has 1 port (a, b). A BJT has 2 ports (base-emitter, collector-emitter). A pot has 2 ports (a-wiper, wiper-b). An op-amp has 1 port (neg-out, pos is voltage-sense).

Source

fn nonideal_fx(&self, _sample_rate: f64) -> Vec<NonIdealFx>

Non-ideal behaviors for this component (GBW, slew, rails, thermal, etc.).

Each component declares what non-idealities it has. Values come from the SPICE model / datasheet lookup. The stage builder attaches them as post-processing. No pattern matching on component type.

Default: empty vec (ideal component).

Source

fn output_impedance(&self) -> OutputImpedance

Output impedance at this component’s output pin.

VoltageSource means the output node voltage is determined entirely by the component (via feedback), independent of downstream load. The compiler can safely split the circuit at these nodes.

Finite (default) means splitting here would change impedances and break the transfer function.

Source

fn signal_terminals(&self) -> SignalTerminals

Signal flow classification for this component’s pins.

Drives feedback analysis: amplifier input→output defines the feedback cycle direction. Passive components have no directionality.

Source

fn port_semantic(&self, _pin_a: &str, _pin_b: &str) -> PortSemantic

Classify the electrical behavior of a port (pin pair) for optimization legality checks. The compiler uses this to determine which subgraphs can be safely lowered to IIR/BlackFeedback vs requiring full MNA/WDF.

Default derives from existing classification methods. Override for multi-port devices where different pin pairs have different semantics (e.g., BJT: B-E is Nonlinear, C-E is Nonlinear).

Source

fn is_nonlinear(&self) -> bool

Whether this component is a nonlinear element (needs NR solver).

Source

fn is_active_ic(&self) -> bool

Whether this component is an active IC (counted toward num_active).

Source

fn is_control_only(&self) -> bool

Whether this component is a control-only element (no circuit pins).

Source

fn is_variable(&self) -> bool

Whether this component’s edge impedance changes at runtime. Stages containing variable edges need scattering matrix recomputation.

Source

fn modulation_pins(&self) -> &'static [&'static str]

Extra pins that are valid as modulation targets but may not be in pin_config.

Source

fn edges(&self) -> Vec<ComponentEdge>

Declare this component’s circuit edges with their electrical classification.

Returns empty for Virtual/ActiveIc components (no WDF topology participation). The planner uses these edges to group components into stages by EdgeKind.

Source

fn signal_adjacencies(&self) -> Vec<(&'static str, &'static str)>

Internal signal-path adjacencies: pin pairs that signal can traverse through.

Used by the validator to check in→out reachability. Default derives pairs from edges(); if edges is empty, fans out from first valid_pin to all others. Override for multi-terminal or complex components (BJTs, pots, transformers).

Source

fn pin_direction(&self, _pin: &str) -> PinDirection

Infer the signal direction for a given pin on this component.

Used by the layout engine to determine directed graph edges. Default: Bidirectional for all pins.

Source

fn resolve_edges( &self, _neighbors: &ResolveContext, ) -> Option<Vec<ComponentEdge>>

Context-dependent resolution: if this component’s behavior depends on how it’s wired, return a new edge list reflecting the resolved role.

Called after graph construction with neighbor connectivity info. Default: no resolution needed (return None to keep current edges).

Examples:

  • JFET gate → LFO/pot → resolve drain-source as Linear (variable resistor)
  • OTA Iabc → envelope → resolve as Vccs (linear mode)
Source

fn mna_vsource_count(&self) -> usize

Number of MNA voltage sources this component needs when stamped into an R-node. Default: 0. Op-amps return 1 (for the VCVS constraint).

Source

fn mna_internal_node_count(&self) -> usize

Number of internal MNA nodes this component needs. Default: 0. Op-amps return 1 (internal gain stage node for GBW pole).

Source

fn stamp_mna_multi( &self, comp_id: &str, ctx: &mut StampContext<'_>, mna: &mut MnaSystem, ) -> StampResult

Stamp this component into an MNA system using multi-terminal pin resolution.

Default implementation resolves pins “a” and “b” and delegates to stamp_mna(). Multi-terminal components (op-amps) override this to resolve all their pins and stamp directly.

Source

fn make_leaf(&self, _comp_id: &str, _sample_rate: f64) -> Option<DynNode>

Create a WDF leaf node for this component. Returns None for non-leaf components (diodes, virtual elements, etc.).

Source

fn resistance(&self) -> Option<f64>

Source

fn capacitance(&self) -> Option<f64>

Source

fn inductance(&self) -> Option<f64>

Source

fn validate_values(&self, _comp_id: &str) -> Vec<(Severity, String)>

Check for suspicious or invalid component values.

Source

fn terminal_requirements(&self) -> Vec<(&'static str, Vec<NeighborReq>)>

Per-terminal neighbour requirements for active devices.

Returns (terminal_name, requirements) pairs declaring what each terminal needs from its connectivity to function as a circuit element. The completeness pass classifies each terminal’s actual neighbours (NeighborRole) and reports a compile error when a [Cardinality:: Required] role is missing.

Config tolerance: a NeighborRole::Load declared on more than one terminal of the same device (e.g. both plate and cathode of a triode) is satisfied if any of those terminals carries a Load. This lets a common-cathode stage (plate-load) AND a cathode-follower (cathode-load, plate straight to B+) both validate without a false positive.

Default: empty (passive / non-active components declare nothing and are never checked).

Source

fn classify_nonlinear( &self, _comp_id: &str, _node_a: usize, _node_b: usize, _gnd_node: usize, _node_names: &HashMap<String, usize>, ) -> Option<(NonlinearKind, Vec<usize>)>

Classify this component as a nonlinear element for the circuit solver.

Returns Some((kind, junction_nodes)) if this is a nonlinear element, where junction_nodes are the circuit nodes where passive elements connect. Returns None for passive, virtual, and active-IC components.

  • 1 junction node: diodes, JFETs, MOSFETs, zeners, OTAs
  • 2 junction nodes: BJTs (collector, emitter), triodes/pentodes (plate, cathode)
Source

fn controls(&self) -> Vec<ControlParam>

Declare controllable parameters for this component.

The compiler matches ControlDef.property against each param’s name to determine the control target without heuristic net scanning.

Source

fn modulation_sink(&self, _pin: &str) -> Option<ModulationSink>

If this component can be a modulation sink (LFO/envelope target), return the sink description for the given pin.

Called during LFO/envelope binding to determine bias and range.

Source

fn is_modulation_source(&self) -> bool

Source

fn is_bjt(&self) -> bool

Source

fn is_jfet(&self) -> bool

Source

fn is_mosfet(&self) -> bool

Source

fn is_tube(&self) -> bool

Source

fn is_transformer(&self) -> bool

Source

fn is_pot(&self) -> bool

Source

fn is_diode_family(&self) -> bool

Source

fn is_trigger(&self) -> bool

Source

fn feedback_input_is_barrier(&self) -> bool

Whether this element’s input node acts as a summing junction that should block BFS traversal in the signal flow graph.

Op-amp neg nodes are summing junctions: the input signal, feedback network, and interstage coupling all connect to the same node. Without blocking, BFS from a downstream element can traverse backward through this element’s feedback, across shared passives, and reach upstream elements — creating false cycle edges.

Returns true for op-amps (VCVS). Returns false for diodes, BJTs, tubes, etc. — their input nodes don’t create false coupling paths.

Source

fn k_method_spec(&self) -> Option<KMethodSpec>

K-method table shape declared by the component.

Requirements for candidacy:

  1. Memoryless: the NL is purely algebraic (no internal state/caps)
  2. Low port count: ≤3 dimensions for practical table sizes
  3. Monotonic: unique output for any input (no fold-back/hysteresis)

Axis dimensions:

  • 1D: incident wave only, e.g. diode/zener junction
  • 2D: incident wave + device control, e.g. BJT Vbe or triode Vgk
  • 3D: incident wave + two controls, e.g. pentode grids

Linear components return (false, 0, “linear”) — they don’t need NL tabulation. Variable components (pots, photocouplers) return false because their parameters change at runtime.

Source

fn k_method_candidacy(&self) -> (bool, usize, &'static str)

Compatibility wrapper for callers that still only need yes/no + dimensionality. New code should prefer Component::k_method_spec because it preserves the meaning of each table axis.

Source

fn is_simple_passive(&self) -> bool

Passive two-terminal element (R, C, L, etc.) — excludes transformers and pots.

Source

fn is_gain_device(&self) -> bool

Amplifying device: tube, BJT, JFET, MOSFET.

Source

fn model_name(&self) -> Option<&str>

Source

fn op_amp_type(&self) -> Option<OpAmpType>

Source

fn pot_taper(&self) -> Option<PotTaper>

Source

fn diode_type(&self) -> Option<DiodeType>

Source

fn transformer_config(&self) -> Option<&TransformerConfig>

Source

fn apply_bias( &self, _bias_voltages: &HashMap<String, f64>, _supply_voltage: f64, ) -> BiasResult

Apply DC bias from a static bias network detected at compile time.

bias_voltages maps pin names (e.g. “pos”, “neg”, “base”, “gate”) to their DC voltage computed from the circuit’s resistor divider. supply_voltage is the pedal’s supply rail voltage (e.g. 9.0V).

Each component type interprets bias differently:

  • Op-amp: sets positive/negative rail limits from bias point
  • BJT: sets quiescent Ic, Vce from collector/emitter voltages
  • Triode/Pentode: sets grid bias (Vgk) from grid DC voltage
  • JFET: sets Vgs from gate bias voltage

Returns BiasResult describing what was applied. Default: no-op (passive components don’t need bias).

Source

fn symbol_name(&self) -> &'static str

Symbol identifier for layout rendering (e.g., “resistor”, “triode”, “opamp”).

Source

fn layout_class(&self) -> &'static str

Layout class identifier for placement grouping (e.g., “resistor”, “npn”, “opamp”).

Source

fn display_value(&self) -> Option<String>

Human-readable display value for labels (e.g., “4.7kΩ”, “100nF”).

Trait Implementations§

Source§

impl Clone for Box<dyn Component>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl PartialEq for Box<dyn Component>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§