Example 16: Delay Differential Equation (DDE) PK model

Script: examples/16_dde_model.py

Demonstrates:

  • DDESubroutine (ADVAN16) for delay-dependent elimination kinetics

  • The _AHISTORY history function injected into pk_params

  • Comparing DDE output with a standard ODE reference (TAU = 0)

  • Plotting the separation between delayed and non-delayed systems

Background

Standard PK ODEs compute rates from the current state A(t). Delay differential equations allow the rate to depend on the state at a past time A(t − τ):

dA/dt = −(CL/V) · A(t − τ)

This arises in:

  • Transit absorption — drug traverses n transit compartments before reaching the sampling site

  • Receptor feedback — occupancy at time t drives elimination at t + τ

  • Cell-cycle models — cells require τ hours to mature before dividing

Key code

from openpkpd.pk.ode.dde import DDESubroutine

def dde_des(t, A, pk_params, theta, eta):
    hist = pk_params.get("_AHISTORY")   # injected by DDESubroutine
    tau  = pk_params.get("TAU", 0.0)
    ke   = pk_params["CL"] / pk_params["V"]

    if hist is not None and tau > 0:
        A_lag = hist(max(t - tau, 0.0))  # A at time t − tau
        return [-ke * A_lag[0]]
    return [-ke * A[0]]  # degenerate to ODE when tau = 0

solver = DDESubroutine(n_compartments=1)
sol = solver.solve(
    pk_params={"CL": 2.0, "V": 10.0, "TAU": 0.5},
    dose_events=dose_events,
    obs_times=obs_times,
    des_callable=dde_des,
)
# sol.ipred — concentration array at obs_times

Output

============================================================
Example 16: Delay Differential Equation (DDE) PK model
============================================================
    Time    ODE (no delay)    DDE (tau=0.5h)    Analytical
------------------------------------------------------------
    0.10            9.8020           10.0000        9.8020
    1.31            7.6948           10.0000        7.6948
    2.52            6.0407           10.0000        6.0407
    3.73            4.7421           10.0000        4.7421
    4.94            3.7227           10.0000        3.7227
    6.15            2.9224           10.0000        2.9224
    7.36            2.2942           10.0000        2.2942
    8.57            1.8010           10.0000        1.8010
    9.78            1.4138           10.0000        1.4138
   10.99            1.1099           10.0000        1.1099

Max ODE vs analytical error: 2.63e-06  (should be < 1e-4)
Max DDE vs ODE difference:  9.09e+00  (should be > 0 with tau=0.5)

DDE model with tau=0.5 h produces delayed elimination — as expected.

Figure saved to docs/_static/examples/16_dde_model.png

Figures

DDE vs ODE

Running

python examples/16_dde_model.py

See also

  • Advanced PK Features — DDE architecture and API reference

  • examples/08_ode_transit_absorption.py — Transit compartment approximation