# Independent Sources

`devvisrc.h`/`devvisrc.cpp` implement `BuiltinVSource`/`BuiltinISource` - the independent voltage and current sources - as instantiations of the [builtin device template framework](devbuiltin.md).

## Shared parameters, separate instance data

`DevSourceModelParams` is empty: independent sources have no model-level parameters. `DevSourceInstanceParams` is shared by both voltage and current sources and holds every waveform-type parameter in one struct - common fields (`mfactor`, `type`, `delay`, `tdphase`, `period`) plus the per-waveform-type fields for DC, pulse, sine, exponential, piecewise-linear (`wave`, plus breakpoint-detection tuning), and AM/FM, selected at runtime by the `type` parameter (an `Id` naming the waveform - `dc`, `pulse`, `sine`, ..., decoded into an `IndependentSourceType` enum). Small-signal `mag`/`phase` parameters are also part of this same struct, used only by AC/small-signal analyses.

`DevVSourceInstanceData` and `DevISourceInstanceData` are separate, however: a voltage source needs an extra branch-current unknown and equation (`uFlow`, plus the Jacobian pointers connecting it to the two terminal nodes) to represent the constraint `v(p,n) = waveform(t)`, which a current source - whose waveform value is injected directly as a node current - does not need. Both also cache waveform-evaluation state (`slopes`, `breakEnabled`, `nextBreakIndex`, `lastPointIndex`) for the piecewise-linear breakpoint machinery, so repeated evaluation during a transient run doesn't rescan the whole waveform each time.

## One shared waveform evaluator

`sourceCompute<InstanceParams, InstanceData>(params, data, time)` is a single template function, instantiated for both instance data types, that computes the waveform's value at a given time by switching on `typeCode` - the actual DC/sine/exponential/AM/FM/pulse/PWL math is identical regardless of whether the result will become a voltage or a current, since only how that value is wired into the circuit equations differs. That wiring is exactly what the [source API](devbase.md) (`sourceExcitation()`, `sourceResponse()`, `scaledUnityExcitation()`, `responseScalingFactor()`) is for: `BuiltinVSourceInstance` and `BuiltinISourceInstance` specialize it differently (a voltage source's excitation targets its own constraint equation; a current source's targets the two node equations it drives directly), while `evalCore()` for both calls the same `sourceCompute()` to get the value.

## What each device type specializes

Both devices specialize the full required `Core()` set from [the builtin framework](devbuiltin.md) (`setupCore`, `setStaticTolerancesCore`, `populateStructuresCore`, `bindCore`, `evalCore`, `loadCore`), plus `defineInternals()` (declaring their two terminals, and for the voltage source its internal branch-current node), `isSource()`/`isVoltageSource()`, `principalParameterIndex()`, `buildHierarchy()`/`deleteHierarchy()`, and the source/output-variable virtuals mentioned above. The full list of specialized methods is declared explicitly in the header - the pattern to follow when adding a new source-like device.
