# DC Transfer Function Analysis

`andcxf.h`/`coredcxf.h` (with `lib/andcxf.cpp`/`lib/coredcxf.cpp`) implement the DC small-signal transfer function analysis: at a fixed DC operating point it computes, for one or more independent sources in turn, the small-signal transfer function from that source's magnitude to a chosen output, and the small-signal input impedance/admittance seen at the source's terminals. It is the per-source counterpart of DC incremental analysis (see [DC Incremental Analysis](andcinc.md)), which instead excites all sources together.

## Class and Data Structures

`DCXF` is the typedef `SmallSignal<DCXFCore, DCXFData>` ([Small-Signal Analysis Template](ansmsig.md)), pairing an `OperatingPointCore` ([Operating Point Analysis](anop.md)) with the `DCXFCore`. `DCXFData` (`andcxf.h`) supplies the `DataMixin` slot's storage:

- `sourceIndex` - map from source instance `Id` to a dense index, built incrementally as `tf`/`zin`/`yin` save directives are resolved (shared by `addAllTfZin()`/`addTf()`/`addZin()`/`addYin()`, see [Analysis Core Base Class](core.md)).
- `sources` - the resolved `Instance*` for each index (`nullptr` if the named instance does not exist or is not a source).
- `incrementalSolution` - scratch incremental-solution vector, reused for each source in turn.
- `tf`, `yin`, `zin` - one entry per source: transfer function, input admittance, input impedance.

`DCXFCore` (`coredcxf.h`) is the concrete `AnalysisCore`. `DCXFParameters` embeds `OperatingPointParameters opParams` and adds `out`, the output node or node pair.

`SmallSignal<DCXFCore, DCXFData>` is specialized in `andcxf.cpp` for its constructor, `resolveSave()`, and `dump()`.

## Core Algorithm

Same governing equation as the rest of this section (comment block in `coredcxf.h`):

```
            d
   f(x(t)) + ---- q(x(t)) = 0
            dt
```

DC transfer function analysis assumes `t=0`, solves the operating point `f(x0) = 0` via `opCore_` (producing the factored resistive Jacobian `Jr`), then for **each** independent source `i` listed in `sources` solves

```
   Jr dx = du_i
```

where `du_i` is the unity excitation of source `i` alone (`inst->scaledUnityExcitation()` added/subtracted at the source's excitation equations, from `inst->sourceExcitation()`) - equivalent to setting that source's `mag` to 1 and every other source's `mag` to 0. `Jr` is already factored by the op core, so each source only costs one triangular solve. From the resulting `dx`:

- **Transfer function** `tf[i] = dx[up] - dx[un]`, the incremental response at the output node pair `(up, un)` given by the `out` parameter (resolved once via `getDiffNodePair()`, [Analysis Core Base Class](core.md)) per unit source magnitude.
- **Input impedance/admittance**, read at the source's response unknowns (`inst->sourceResponse()`) and scaled by `inst->responseScalingFactor()` (accounts for parallel instances/`$mfactor`) divided by `inst->scaledUnityExcitation()`. For a voltage source the natural response is current, giving `yin` directly (`zin = 1/yin`, or `1e20` if `yin` is exactly zero); for a current source the natural response is voltage, giving `zin` directly (`yin = 1/zin` likewise guarded against division by zero).

See [Operating Point Analysis](anop.md) for how nodesets seed the op solve.

## Parameters

`DCXFParameters` (`coredcxf.h`), registered for introspection in `coredcxf.cpp`:

| Parameter | Type | Description |
|---|---|---|
| `out` | Value (string or 2-element string vector) | Output node, or output node pair for a differential output. |
| `write` | Int | Write the transfer-function results to a file (default 1). |
| `writeop` | Int | Exposes `opParams.write`: write the operating-point results to a separate `<name>.op` file (default 0). |
| `nodeset` | Value | Exposes `opParams.nodeset`: stored-solution slot name to read, or a list of nodesets for the op solve. |
| `store` | String | Exposes `opParams.store`: stored-solution slot name to write after the op solve. |

## Recognized Save Directives

Resolved in `SmallSignal<DCXFCore, DCXFData>::resolveSave()` (`andcxf.cpp`), using the `AnalysisCore` transfer-function helpers ([Analysis Core Base Class](core.md)). Anything not below falls through to `resolveOpSave()` (shared operating-point saves, written to the separate `.op` output file).

| Save directive | Arguments | Description |
|---|---|---|
| `default` | none | `tf` and `zin` for every independent source in the circuit (`addAllTfZin()`); the fallback when no save directive produces any descriptor. |
| `tf` | one source instance name | Transfer function from that source to `out`. |
| `zin` | one source instance name | Input impedance felt at that source's terminals. |
| `yin` | one source instance name | Input admittance felt at that source's terminals. |

| OP save directive (via `resolveOpSave()`) | Arguments | Description |
|---|---|---|
| `opdefault` | none | All circuit unknowns, operating-point values. |
| `opfull` | none | Every non-ground node, operating-point values. |
| `v` | one node name | Operating-point voltage at the given node. |
| `i` | one instance name | Operating-point branch current of the given instance. |
| `p` | instance name, outvar name | One instance output variable's operating-point value. |

An instance named by `tf`/`zin`/`yin` (or picked up by `default`) that is not found, or that is found but is not a source, is an error under strict resolution.

## Related Documentation

- [Small-Signal Analysis Template](ansmsig.md) - the `SmallSignal<CoreClass, DataMixin>` template this analysis instantiates.
- [Operating Point Analysis](anop.md) - the dependency core providing the DC bias point and nodeset mechanism.
- [Analysis Core Base Class](core.md) - `AnalysisCore`, the `tf`/`zin`/`yin` save-directive helpers, and the core pipeline.
- [DC Incremental Analysis](andcinc.md) - the all-sources-at-once counterpart of this analysis.
- [AC Small-Signal Transfer Function Analysis](anacxf.md) - the frequency-swept counterpart of this analysis.
