# Evaluation and Loading Setup

`elsetup.h` defines `DeviceRequests`, `EvalSetup`, and `LoadSetup` - the parameter blocks [`Device::eval()`/`load()`/`evalAndLoad()`](devbase.md) receive on every simulation step, controlling what a device instance should compute and where the results go. Both are plain structs with default member initializers (`{}`), not classes with invariants to maintain beyond what their own `initialize()` sets up.

## Mode flags, not device-type dispatch

`EvalSetup` carries a set of boolean mode flags (`staticAnalysis`, `dcAnalysis`, `acAnalysis`, `tranAnalysis`, `noiseAnalysis`, `nodesetEnabled`, `icEnabled`, ...) and per-quantity "should this be computed" flags (`evaluateResistiveJacobian`, `evaluateReactiveResidual`, `evaluateNoise`, `evaluateOutvars`, ...) rather than the analysis type being encoded in which method gets called. A device's `evalCore()` inspects these flags to decide what work is actually needed for the current step - the same evaluation code path serves every analysis type, doing only the subset of work each one requests.

## Opt-out destinations

Most of `LoadSetup`'s fields (and a few in `EvalSetup`, like `dummyStates`) are raw pointers documented as "skip if `nullptr`" - a destination a device writes its resistive residual, reactive residual, per-node maximum contribution, DC/AC small-signal residual, and so on into, only if the pointer is non-null. This is an opt-out data-collection pattern: an analysis that doesn't need, say, per-node maximum residual contributions simply leaves that pointer null, and every device's `loadCore()` skips the corresponding write for free, rather than every analysis needing its own variant of the loading code.

## Bounds that can only tighten

`boundStep`, `nextBreakPoint`, `discontinuity`, and `maxFreq` follow the same pattern: each starts at an extreme initial value (`clearBounds()` sets `boundStep`/`nextBreakPoint` to `+infinity`, `discontinuity` to `-1`, `maxFreq` to `0`), and `setBoundStep()`/`setBreakPoint()`/`setDiscontinuity()`/`setMaxFreq()` only ever move the stored value in the tightening direction (a smaller step bound, an earlier breakpoint, a lower nonnegative discontinuity index, a higher frequency) - never loosen it. Every instance evaluated during a step calls these unconditionally with whatever it wants to request; the tightest request across all instances wins, without any instance needing to know what any other instance asked for. This mirrors Verilog-A's own `$bound_step`/`$discontinuity`/`$limit` semantics, where any device in the circuit can constrain the next timestep.

## Diverting state writes: `dummyStates`

When `dummyStates` is set, `newStates` points into it instead of into the real `states` history (`VectorRepository<double>`, defined in `ansupport.h` - not documented separately here) - letting a caller run a trial/speculative evaluation (e.g. during Newton iteration before a step is accepted) without tainting the persisted state history that later steps depend on.

## Precomputed fast-access pointers

Both structs cache `oldStates`/`newStates` (and `EvalSetup` additionally `oldSolution`) as raw pointers, resolved once in `initialize()` from the `VectorRepository`/`dummyStates` fields above, explicitly commented "do not set manually" - since a device's `evalCore()`/`loadCore()` runs once per instance per step, resolving these lookups once per step (in `initialize()`) rather than once per instance avoids repeating the same repository indexing work for every device in the circuit.

## `DeviceRequests`

A small separate struct (`abort`/`finish`/`stop`) carrying back Verilog-A's `$stop`/`$finish`/abort-style requests from device evaluation to whatever drove it, reset via `clear()` before each round of evaluation.
