# Common Analysis Data

`comdata.h`/`comdata.cpp` define `CommonData`, a single struct carrying the small set of
values that every analysis core, every device's `setup()`/`eval()`/`load()`, and `Circuit`
itself need to agree on for one solve: homotopy conductances, the bypass-control flags, the
current analysis identification, and the per-unknown/per-residual tolerance tables used for
convergence and scaling. It is passed by reference almost everywhere in the solve path (see
[Analysis Core Base Class](core.md), device setup in `devbase.h`/`devbuiltin.h`, and
`Circuit::setup()`/`evalAndLoad()` in [Circuit Representation and Construction](circuit.md))
instead of being threaded through as several separate parameters.

## Lifetime and ownership

A `Circuit` owns exactly one `CommonData commons` member, constructed once and reused across
every analysis run on that circuit. `CommonData` is non-copyable and non-movable (all four
special member functions are deleted) - it is meant to be mutated in place through its
`reset()`/`fromOptions()`/tolerance methods, not duplicated or handed off.

- **`CommonData()`** calls `reset()`.
- **`reset()`** restores the homotopy and bypass fields to their neutral defaults: `gmin=0`,
  `gshunt=0`, `gdev=0`, `sourcescalefactor=1` (i.e. no extra conductance, no scale-back of
  independent sources), `analysis_name`/`analysis_type` cleared, `allowContinueStateBypass=false`,
  `iteration=0`, `requestForcedBypass=false`. It does **not** touch the tolerance arrays or
  `natures` - those are reset separately via `resetTolerances()`.
- **`fromOptions(options)`** calls `reset()` and then seeds `gmin`/`gshunt` from
  [`SimulatorOptions`](options.md), the values a homotopy algorithm perturbs away from as it runs.

## Homotopy and bypass fields

- **`sourcescalefactor`**, **`gmin`**, **`gdev`**, **`gshunt`** - the knobs homotopy algorithms
  (gmin-stepping, source-stepping) turn between operating-point attempts. `gmin` is the
  conductance devices are expected to add in parallel to nonlinear branches; `gdev` is an
  additional homotopy-only gmin computed and passed in by the simulator that most models do not
  read (homotopy code is written to modify `gmin` itself instead); `gshunt` is a conductance from
  every potential node to ground.
- **`iteration`** - the current Newton-Raphson iteration counter, set by the analysis core driving
  the solve.
- **`analysis_name`**/**`analysis_type`** - identify which analysis is currently loading the
  circuit; devices can branch on these (e.g. to disable noise sources outside a noise analysis).
- **`allowContinueStateBypass`**/**`requestForcedBypass`** - bypass-control flags consulted by
  device `load()`. `allowContinueStateBypass` is set by the owning analysis (true for all but the
  first point of the innermost sweep when `nr_contbypass` is enabled and continuation is in
  effect); `requestForcedBypass` is set per-iteration by the analysis core to force every
  bypassable device to reuse its converged state regardless of how much the inputs moved.

## Nature tolerance tables

`CommonData` also carries the static (input-independent) part of the per-unknown and
per-residual absolute-tolerance tables used for convergence testing and residual scaling. Each
table has one entry per unknown, indices `0..n` inclusive where `n` is
`unknownCountExcludingGround` and index `0` is the ground/reference unknown (see
[per-unknown array indexing conventions in Circuit](circuit.md)):

- `unknown_abstol`/`unknown_idt_abstol` and their `NatureId`/`NatureIndex` companions
  (`unknown_natureId`/`unknown_natureIndex`, `unknown_idt_natureId`/`unknown_idt_natureIndex`) -
  tolerance and nature bookkeeping for the unknown itself and for its time-integral (used for
  charge/flux-type unknowns).
- `residual_abstol`/`residual_idt_abstol` and their `NatureId`/`NatureIndex` companions - the
  matching tables for the KCL/KVL residual at that unknown.
- `natures` - a [`NaturesSubset`](natures.md), the set of natures actually in use by the circuit;
  it maps each `NatureId` to a dense `NatureIndex` used to index per-nature limit tables
  elsewhere.

### Populating and combining tolerances

- **`resetTolerances(n)`** resizes all eight arrays to `n+1` entries and initializes every entry
  to `NatureTolerance(NatureRegistry::noNature, +inf)` - "no nature claimed yet, tolerance not yet
  constraining."
- **`updateTolerances(i, u, idt_u, r, idt_r, force)`** is the tightening primitive: for each of the
  four tolerance slots at unknown `i`, it overwrites the stored value only if `force` is true or
  the new `abstol` is smaller (tighter) than what is already stored. Devices call this once per
  nature-contributing terminal/branch, so the table naturally converges to the tightest tolerance
  requested by any device touching that unknown.
- **`setTolerances(i, ...)`** is `updateTolerances(..., force=true)` - an unconditional overwrite,
  used when a caller knows it holds the authoritative value (e.g. `AnnotatedSolution` bookkeeping
  or explicit reinitialization).
- **`defaultTolerances(i, ...)`** is the opposite of forcing: it fills in a slot only if that slot
  is still at `NatureRegistry::noNature` (i.e. nothing has claimed it yet), used to backstop
  unknowns that no device explicitly constrained.
- **`scaleTolerances(scl)`** multiplies all four `*_abstol` arrays by `scl` in place, in-place
  rescaling used when tolerances need to move with a unit or global scale change.
- **`getTolerances(i)`** packages the four `NatureTolerance` values for unknown `i` back into a
  `std::tuple`, the read side matching `setTolerances`'s write side.
- **`enumerateNatures(s)`** re-derives every `*_natureIndex` array from its `*_natureId`
  counterpart via `natures.natureIndex(id)`, after all tolerances have been registered and
  `natures` is complete. It always returns `true` (`Status& s` is accepted for interface
  consistency with other setup steps but is unused).

## Fit in the simulator

`CommonData` is constructed once per `Circuit` and threaded by reference through the whole
setup/eval/load path: `Circuit::setup()` and `Circuit::evalAndLoad()` take it, every
`AnalysisCore` subclass receives it at construction and keeps a reference member, and every device
`setup()`/`setStaticTolerances()`/`eval()`/`load()` override takes it as a parameter (see
`devbase.h`, `devbuiltin.h`, `osdiinstance.h`). Analysis cores mutate `iteration`,
`analysis_name`/`analysis_type`, and the bypass flags as they drive Newton-Raphson; devices read
`gmin`/`gdev`/`gshunt` while loading and call `updateTolerances()`/`defaultTolerances()` during
`setStaticTolerances()` to register their contribution to each unknown's convergence tolerance.
