braincell.quad.ind_exp_euler_step

braincell.quad.ind_exp_euler_step#

braincell.quad.ind_exp_euler_step(target, *args, excluded_paths=())[source]#

Advance each DiffEqState independently with exponential Euler.

This is the decoupled sibling of exp_euler_step(). Instead of building one global Jacobian over the full state vector, the routine iterates over every DiffEqState \(y^{(k)}\) in target and treats the others as frozen at their current values, fitting the local linearization

\[\frac{d y^{(k)}}{dt} \approx \lambda^{(k)} y^{(k)} + b^{(k)}\]

via brainstate.transform.vector_grad() and applying the component-wise exponential Euler update

\[y^{(k)}_{n+1} = y^{(k)}_n + \Delta t \, \varphi_1\!\left(\Delta t \, \lambda^{(k)}\right) f^{(k)}(t_n, y_n),\]

using brainunit.math.exprel() to evaluate \(\varphi_1(z) = (e^{z} - 1)/z\) accurately near \(z = 0\).

The trade-off compared with exp_euler_step():

  • exp_euler_step() is more accurate when states are tightly coupled, because it builds the full \(M \times M\) Jacobian and uses a true matrix exponential.

  • ind_exp_euler_step() is much cheaper for large state vectors and is the right choice when each variable is mostly self-coupled (the typical pattern for HH-style gating variables and ion concentrations) and especially when the voltage equation is being solved by a separate solver (see staggered_step()).

Parameters:
  • target (DiffEqModule) – The module whose DiffEqState leaves will be advanced.

  • *args – Extra positional arguments forwarded to target’s pre_integral(), compute_derivative(), and post_integral() hooks.

  • excluded_paths (tuple of tuple, optional) – Iterable of state paths to skip. Each entry is a tuple of attribute names identifying a DiffEqState inside target’s state graph. The classic use is excluded_paths=[('V',)] from staggered_step(), which leaves the membrane voltage untouched so the upstream cable solve is preserved.

Returns:

Differential states are updated in place; auxiliary (non-DiffEq) states are written from the trace captured during the first Jacobian evaluation.

Return type:

None

Raises:

See also

exp_euler_step

Coupled (full-Jacobian) exponential Euler.

staggered_step

Operator-splitting scheme that combines DHS for the voltage equation with this routine for everything else.

Notes

The current time and step size are read from the active brainstate.environ context.

Examples

>>> import brainstate
>>> import brainunit as u
>>> from braincell.quad import ind_exp_euler_step
>>> with brainstate.environ.context(t=0. * u.ms, dt=0.025 * u.ms):
...     ind_exp_euler_step(
...         my_cell, input_current,
...         excluded_paths=[('V',)],
...     )