Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::junction::JunctionPair Struct Reference

One junction network: the exponential law over one or two antiparallel legs. More...

#include <junction.hpp>

Public Member Functions

double theta () const
 θ = n·V_T, the exponential's scale in volts.
double current (double v) const
 i(v).
double conductance (double v) const
 di/dv — the incremental conductance a Newton solve needs.
double antiderivative (double v) const
 ∫i(v)dv, in closed form — no numerical quadrature.
double conduction_estimate (double v_drive, double resistance) const
 A closed-form estimate of where a clipped node voltage will land, for use as a solver's warm start.
double knee_voltage (double target_current) const
 The junction voltage at which the network conducts target_current on its forward leg — the conduction knee, inverted from the same law.
double adaa_current (double v, double previous, double epsilon) const
 First-order antiderivative-antialiasing evaluation of the current between two consecutive junction voltages.
double adaa_conductance (double v, double previous, double epsilon) const
 d/dv of adaa_current — the Jacobian a Newton solve needs when its residual is built on the ADAA quotient rather than on current.

Public Attributes

double saturation_current = 1e-14
 Is, the reverse saturation current.
double ideality = 1.0
 n, the ideality factor. Sets the knee's SOFTNESS: higher is softer.
double leg_a = 1.0
 Reciprocal series-diode count of the forward leg.
double leg_b = 1.0
 Reciprocal series-diode count of the reverse leg.

Detailed Description

One junction network: the exponential law over one or two antiparallel legs.

A consuming module fills in (saturation_current, ideality) from its own declared device rows, and (leg_a, leg_b) from its own topology.

Member Function Documentation

◆ adaa_conductance()

double pulp::signal::junction::JunctionPair::adaa_conductance ( double v,
double previous,
double epsilon ) const
inline

d/dv of adaa_current — the Jacobian a Newton solve needs when its residual is built on the ADAA quotient rather than on current.

This exists because pairing the ADAA residual with conductance() is a silent catastrophe rather than a slow one. conductance is the slope of the PLAIN current; the quotient's slope is a different function, and feeding Newton a Jacobian that does not belong to its residual makes the step direction wrong rather than merely inaccurate. Measured, a diode clipper diverged geometrically at roughly 3300x per sample to 5.8e25 — full-scale noise, from a solver that never reported failure because every value stayed finite.

Differentiating (F1(v) − F1(p))/(v − p) gives [i(v)·(v − p) − (F1(v) − F1(p))] / (v − p)², and it stays strictly positive for the same reason conductance does: the quotient is the MEAN of i over [p, v], i is increasing, so i(v) is never below that mean. The bracketed solver's monotone-residual precondition therefore still holds — which is what makes the safeguard safe rather than merely present.

◆ adaa_current()

double pulp::signal::junction::JunctionPair::adaa_current ( double v,
double previous,
double epsilon ) const
inline

First-order antiderivative-antialiasing evaluation of the current between two consecutive junction voltages.

Falls back to direct evaluation when the two are too close for the difference quotient to carry precision — the standard ADAA guard. The epsilon lives with its one consumer here rather than being copied into every solver that wants antialiasing.

◆ antiderivative()

double pulp::signal::junction::JunctionPair::antiderivative ( double v) const
inline

∫i(v)dv, in closed form — no numerical quadrature.

Even, for the reason given in the file doc block.

◆ conductance()

double pulp::signal::junction::JunctionPair::conductance ( double v) const
inline

di/dv — the incremental conductance a Newton solve needs.

Strictly positive, which is what makes a residual built on it monotone.

◆ conduction_estimate()

double pulp::signal::junction::JunctionPair::conduction_estimate ( double v_drive,
double resistance ) const
inline

A closed-form estimate of where a clipped node voltage will land, for use as a solver's warm start.

This matters more than it looks. Newton on an exponential advances by roughly one thermal voltage per iteration when it starts deep in conduction — 26 mV at a time — so a cold start two volts away needs dozens of iterations against a typical RT cap of eight. Solving the conducting branch directly, with v ≪ v_drive, (v_drive − v)/R = Is·exp(a·v/θ) gives v ≈ (θ/a)·ln(v_drive/(R·Is)) — for a silicon diode at 2 V through 10 kΩ that is 0.613 V, the knee to three figures. From there Newton converges in two or three steps.

Below conduction, or with the relevant leg absent, the node follows the drive, which is the fallthrough.

◆ current()

double pulp::signal::junction::JunctionPair::current ( double v) const
inline

i(v).

The two legs' −1 terms cancel exactly, which is why this is a difference of exponentials rather than of expm1s.

◆ knee_voltage()

double pulp::signal::junction::JunctionPair::knee_voltage ( double target_current) const
inline

The junction voltage at which the network conducts target_current on its forward leg — the conduction knee, inverted from the same law.

This is how a bias point is derived rather than declared: a module states its operating current and the knee falls out, so the documented ~0.36 V germanium / ~0.69 V silicon figures are consequences of (Is, n) rather than separately maintained constants that can drift from them.

◆ theta()

double pulp::signal::junction::JunctionPair::theta ( ) const
inline

θ = n·V_T, the exponential's scale in volts.

Member Data Documentation

◆ ideality

double pulp::signal::junction::JunctionPair::ideality = 1.0

n, the ideality factor. Sets the knee's SOFTNESS: higher is softer.

◆ leg_a

double pulp::signal::junction::JunctionPair::leg_a = 1.0

Reciprocal series-diode count of the forward leg.

1 is a single diode, 1/2 is two in series (turns on at twice the voltage), 0 removes it.

◆ leg_b

double pulp::signal::junction::JunctionPair::leg_b = 1.0

Reciprocal series-diode count of the reverse leg.

0 makes the network a single junction — half-wave, even harmonics.

◆ saturation_current

double pulp::signal::junction::JunctionPair::saturation_current = 1e-14

Is, the reverse saturation current.

Units are whatever the consuming module works in — SI amps or calibration-relative — because every formula here is homogeneous in it.


The documentation for this struct was generated from the following file:
  • /home/runner/work/pulp/pulp/core/signal/include/pulp/signal/junction.hpp