SSN Component Implementation

The SSN base class hierarchy and what a new SSN component has to provide.

The method is derived under state-space nodal components and state-space nodal. This page covers only the code.

Base hierarchy

SSNComp holds the continuous matrices, the discrete pair, the equivalent admittance mW, the history vector mYHist and the state attribute x. Two branches specialise it by which quantity is the input:

  • VTypeSSNComp takes voltage in and gives current out, so it stamps as an admittance
  • ITypeSSNComp is the dual

Terminal-count layers sit on top: TwoTerminalVTypeSSNComp, TwoTerminalITypeSSNComp and FourTerminalVTypeSSNComp handle the mapping from terminal quantities to the model input, and the Variable layers add re-forming of the model between steps. Every EMT::Ph3 base sets PhaseType::ABC in its constructor, which the concrete components rely on.

What a component provides

A fixed-model component only calls SSNComp::setParameters(A, B, C, D) with its chosen state, input and output. EMT::Ph3::SSN::Inductor is the whole pattern:

Matrix aMatrix = Matrix::Zero(3, 3);   // x = i_abc
Matrix bMatrix = inductance.inverse(); // u = v_abc
Matrix cMatrix = Matrix::Identity(3, 3);
Matrix dMatrix = Matrix::Zero(3, 3);
SSNComp::setParameters(aMatrix, bMatrix, cMatrix, dMatrix);

The base does the rest: recomputeDiscreteModel calls Math::calculateStateSpaceTrapezoidalMatrices and sets mW = mC * mdB + mD, calculateHistoryVector returns mC * (mdA * x + mdB * u), and the post step updates the state from the old and new input.

A varying component additionally overrides updateStateSpaceModel (a no-op for linear components) and, for the variable bases, updateComponentParameters to report whether the model changed. Only when it reports a change is the system matrix refactorised.

Domain differences

The formulation differs by domain, and so does the code path. The theory is under SSN across domains.

A component supplies the same real (A, B, C, D) in either domain. EMT::SSNComp discretises them directly. DP::SSNComp does not: buildAugmentedA(omega) assembles the real-augmented 2n x 2n matrix with A on both diagonal blocks and +wI / -wI off-diagonal, buildAugmentedB places B on both diagonal blocks, and the result goes through the same Math::calculateStateSpaceTrapezoidalMatrices helper as EMT. The discrete blocks are then folded back into complex form as topLeft + j * bottomLeft, which is the inverse of the [[P, -Q], [Q, P]] representation. mW and the history vector are complex as a result.

recomputeDiscreteModel therefore takes omega in DP and takes no argument in EMT. A component that hardcodes a frequency here rather than using the value handed to mnaCompInitialize is wrong at any other system frequency.

Frame metadata

getLocalAbcStateBlocks returns nothing by default and should be overridden only for states that genuinely form physical abc triples. It is consumed by tooling that reasons about the state vector in the phase frame, and declaring a block that is not one produces wrong groupings rather than an error.

Initialization

calculateSteadyStateStateFromInput evaluates (jωI − A)⁻¹ B u, which requires the continuous model to be set first. Components with real control states cannot use the default initializeFromNodesAndTerminals on the mixed base; see DP Ph1 averaged VSI implementation for that case and for the requirement that the state matrix be handed over already carrier shifted.

The components

Fixed models: SSN_Full_Serial_RLC, SSN_Capacitor, SSN_Inductor, SSNTypeV2T, SSNTypeI2T. Varying models: SSN_Variable_Serial_RLC, PiecewiseLinearInductor, and the inverter models under power electronics. The Generic two- and four-terminal classes take the matrices from the caller instead of forming them, so they are the route to an SSN component without writing C++. Availability per domain is in model availability.