Skip to content

One-Compartment IV Bolus

Single-compartment pharmacokinetic model with instantaneous IV bolus or zero-order infusion administration.


Function Signature

neopkpd.simulate_pk_iv_bolus(
    cl: float,
    v: float,
    doses: list[dict],
    t0: float,
    t1: float,
    saveat: list[float],
    alg: str = "Tsit5",
    reltol: float = 1e-10,
    abstol: float = 1e-12,
    maxiters: int = 10**7,
    alag: float | None = None,
    bioavailability: float | None = None,
) -> dict

Parameters

Parameter Type Description
cl float Clearance (volume/time, e.g., L/h)
v float Volume of distribution (L)
doses list[dict] Dose events (see below)
t0 float Simulation start time
t1 float Simulation end time
saveat list[float] Time points for output
alg str ODE solver algorithm (default: "Tsit5")
reltol float Relative tolerance (default: 1e-10)
abstol float Absolute tolerance (default: 1e-12)
maxiters int Maximum solver iterations
alag float Absorption lag time (optional)
bioavailability float Fraction absorbed, 0-1 (optional)

Dose Event Format

doses = [
    {"time": 0.0, "amount": 100.0},                    # IV bolus
    {"time": 8.0, "amount": 100.0, "duration": 1.0},   # 1-hour infusion
]

Returns

{
    "t": [0.0, 1.0, 2.0, ...],           # Time points
    "states": {
        "A": [100.0, 90.5, ...]          # Amount in compartment
    },
    "observations": {
        "conc": [10.0, 9.05, ...]        # Concentration (A/V)
    },
    "metadata": {...}
}

Model Equations

\[\frac{dA}{dt} = -k \cdot A\]
\[C = \frac{A}{V}\]
\[k = \frac{CL}{V}\]

For infusion (duration > 0): $\(\frac{dA}{dt} = R_0 - k \cdot A\)$

where \(R_0 = \text{amount} / \text{duration}\)


Basic Examples

Single IV Bolus

import neopkpd

result = neopkpd.simulate_pk_iv_bolus(
    cl=10.0,      # 10 L/h clearance
    v=50.0,       # 50 L volume
    doses=[{"time": 0.0, "amount": 500.0}],
    t0=0.0,
    t1=24.0,
    saveat=[0, 1, 2, 4, 6, 8, 12, 24]
)

# Access results
print(f"C0 = {result['observations']['conc'][0]:.1f} mg/L")  # 10.0 mg/L
print(f"Half-life = {0.693 * 50 / 10:.1f} h")                # 3.47 h

IV Infusion

# 500 mg over 2 hours
result = neopkpd.simulate_pk_iv_bolus(
    cl=10.0,
    v=50.0,
    doses=[{"time": 0.0, "amount": 500.0, "duration": 2.0}],
    t0=0.0,
    t1=24.0,
    saveat=[i * 0.5 for i in range(49)]
)

# Peak occurs at end of infusion
conc = result['observations']['conc']
t = result['t']
cmax_idx = max(range(len(conc)), key=lambda i: conc[i])
print(f"Cmax = {conc[cmax_idx]:.2f} mg/L at t = {t[cmax_idx]} h")

Multiple Dosing

Repeated IV Boluses

# 500 mg every 8 hours for 5 doses
doses = [{"time": i * 8.0, "amount": 500.0} for i in range(5)]

result = neopkpd.simulate_pk_iv_bolus(
    cl=10.0,
    v=50.0,
    doses=doses,
    t0=0.0,
    t1=48.0,
    saveat=[i * 0.5 for i in range(97)]
)

# Find Cmax and Cmin in last dosing interval
conc = result['observations']['conc']
t = result['t']

# Last interval: 32-40 h
last_start = next(i for i, x in enumerate(t) if x >= 32)
last_end = next(i for i, x in enumerate(t) if x >= 40)

cmax = max(conc[last_start:last_end])
cmin = min(conc[last_start:last_end])

print(f"Steady-state Cmax: {cmax:.2f} mg/L")
print(f"Steady-state Cmin: {cmin:.2f} mg/L")

Continuous Infusion

# Continuous infusion: 20 mg/h for 24 hours
result = neopkpd.simulate_pk_iv_bolus(
    cl=10.0,
    v=50.0,
    doses=[{"time": 0.0, "amount": 480.0, "duration": 24.0}],
    t0=0.0,
    t1=48.0,
    saveat=[i * 0.5 for i in range(97)]
)

# Steady-state concentration
css = 480.0 / 24.0 / 10.0  # Rate / CL = 2 mg/L
print(f"Theoretical Css: {css:.1f} mg/L")
print(f"Simulated C at 24h: {result['observations']['conc'][48]:.2f} mg/L")

Loading Dose Strategy

# Loading dose followed by maintenance infusion
cl = 10.0
v = 50.0
target_css = 5.0  # mg/L

# Loading dose to immediately reach target
loading_dose = target_css * v  # 250 mg

# Maintenance rate to sustain target
maint_rate = target_css * cl  # 50 mg/h

doses = [
    {"time": 0.0, "amount": loading_dose},                     # Loading bolus
    {"time": 0.0, "amount": maint_rate * 24, "duration": 24.0} # 24h infusion
]

result = neopkpd.simulate_pk_iv_bolus(
    cl=cl, v=v,
    doses=doses,
    t0=0.0, t1=24.0,
    saveat=[i * 0.25 for i in range(97)]
)

# Concentration should stay near 5 mg/L throughout
print(f"C at 0h: {result['observations']['conc'][0]:.2f} mg/L")
print(f"C at 12h: {result['observations']['conc'][48]:.2f} mg/L")
print(f"C at 24h: {result['observations']['conc'][-1]:.2f} mg/L")

Visualization

import neopkpd
from neopkpd.viz import plot_pk_profile

result = neopkpd.simulate_pk_iv_bolus(
    cl=10.0, v=50.0,
    doses=[{"time": 0.0, "amount": 500.0}],
    t0=0.0, t1=24.0,
    saveat=[i * 0.25 for i in range(97)]
)

# Plot concentration-time profile
fig = plot_pk_profile(
    result['t'],
    result['observations']['conc'],
    title="One-Compartment IV Bolus",
    xlabel="Time (h)",
    ylabel="Concentration (mg/L)"
)

Derived Parameters

From Simulation Results

import numpy as np

result = neopkpd.simulate_pk_iv_bolus(
    cl=10.0, v=50.0,
    doses=[{"time": 0.0, "amount": 500.0}],
    t0=0.0, t1=48.0,
    saveat=[i * 0.1 for i in range(481)]
)

conc = np.array(result['observations']['conc'])
t = np.array(result['t'])

# AUC (trapezoidal rule)
auc = np.trapz(conc, t)
print(f"AUC: {auc:.1f} mg*h/L")
print(f"Theoretical AUC (Dose/CL): {500/10:.1f} mg*h/L")

# Half-life from log-linear regression
log_conc = np.log(conc[conc > 0])
t_valid = t[conc > 0]
slope = np.polyfit(t_valid, log_conc, 1)[0]
half_life = -0.693 / slope
print(f"Half-life: {half_life:.2f} h")

Equations Summary

Quantity Formula
Elimination rate constant \(k = CL/V\)
Half-life \(t_{1/2} = 0.693/k\)
C(t) after bolus \(C_0 \cdot e^{-kt}\)
Css (infusion) \(R_0/CL\)
AUC (single dose) \(Dose/CL\)

See Also