# Stored Solutions

`ansolution.h`/`ansolution.cpp` define `AnnotatedSolution`, a snapshot of a circuit's solution vector together with just enough metadata to reapply it later - possibly to a circuit whose unknown numbering has since changed. It is the vehicle behind named solution storage/reuse across analyses (continuation between sweep points, restoring an operating point, seeding a periodic steady-state or harmonic-balance guess).

## Storage layout

An `AnnotatedSolution` bundles:

- **`typeTag_`** (`Id`) - identifies what kind of solution this is (which analysis produced it, what the aux data means); set/interpreted by the owning analysis, not by `AnnotatedSolution` itself.
- **`values_`** - a `std::variant<std::monostate, Vector<double>, Vector<Complex>>` (see [Analysis Support Classes](ansupport.md) for `Vector<T>`). Real solutions (DC operating point, transient, PSS time-domain) use the real alternative, one component per unknown; harmonic-balance solutions use the complex alternative, holding the per-node spectrum instead. `values()`/`cxValues()` unwrap the active alternative (via `std::get`, so calling the wrong accessor throws `std::bad_variant_access`); `setValues()`/`setCxValues()` install one or the other.
- **`names_`** - one `Id` per stored unknown, used to cross-match a stored solution against a circuit's *current* unknown numbering, which can differ from the numbering in effect when the solution was captured (elaboration order is not guaranteed stable across circuit changes). `setNames(circuit)` populates this by walking every unknown 0..`circuit.unknownCount()` inclusive - **including index 0, the ground/reference unknown** - and recording `circuit.reprNode(i)->name()` (see [Nodes](node.md)). The comment in `ansolution.cpp` is explicit that this inclusion is load-bearing: `OperatingPointCore::runSolver()` checks a stored solution's consistency by comparing its length against `unknownCount()+1`, so dropping ground from `names_` would require updating that consistency check (and the code that copies a stored solution back into the live solution vector) in lockstep.
- **`realVec_`** - an auxiliary real vector whose meaning depends on `typeTag_`: for an operating-point solution it holds device state values; for harmonic balance it holds timepoints.
- **`spurs_`** - a `Spurs` object (frequency-domain spectrum/mixing descriptor, `spurs.h`), relevant to harmonic-balance solutions only. `setSpurs()` takes a copy.
- **`auxReal_`** - a single auxiliary scalar; for a periodic steady-state solution this is the period, with a value `<=0` meaning no period was captured.

`clear()` resets all of the above to their default/empty state in one call.

## Move-only, no default copy

`AnnotatedSolution`'s copy constructor and copy assignment are deleted; only move construction/assignment are available. A solution is meant to be built once and then either moved into storage or left in place - not duplicated implicitly.

## Where solutions live

`AnnotatedSolution` instances are not self-storing; a circuit's own `solutionRepository` (an `Id`-keyed map, `circuit.h`) owns them, populated through `Circuit::newStoredSolution(name)`/looked up through `Circuit::storedSolution(name)`. Analysis cores also keep one directly as their own working solution (see `AnalysisCore::solution` in `core.h`). Downstream, forces/continuation setup (`OpNRSolver::setForces()`, `HBNRSolver::setForces()`) reads a stored `AnnotatedSolution` back into the live solve, matching entries by `names_` rather than assuming positional correspondence.
