bubble¶
The jbubble.bubble subpackage contains all bubble physics components: state representation, the Property abstraction, and gas/shell/medium/EoM models.
State¶
jbubble.bubble.state.BubbleState
¶
Bases: Module
Standard bubble state.
Fields
R : jax.Array Bubble wall radius [m]. R_dot : jax.Array Bubble wall velocity [m/s]. R0 : jax.Array Equilibrium bubble radius [m]. Frozen (dR0/dt = 0) in the standard case; becomes a slow state variable for rectified diffusion etc. P_gas0 : jax.Array Equilibrium gas pressure [Pa]. Frozen in the standard case.
jbubble.bubble.state.ConfinedBubbleState
¶
Bases: BubbleState
State for a bubble confined in an elastic spherical vessel.
Extends BubbleState with the vessel wall radius and velocity.
Fields
a : jax.Array Vessel wall radius [m]. a_dot : jax.Array Vessel wall velocity [m/s].
Properties¶
The Property abstraction is the key extensibility mechanism in jbubble. Any physical parameter that could depend on the bubble state is represented as a Property — a callable state → scalar. Plain floats are automatically promoted via as_property.
jbubble.bubble.property.Property
¶
Bases: Module, ABC
Abstract base for state-dependent (or constant) bubble properties.
Any callable eqx.Module that maps a BubbleState to a scalar
array should inherit from this class. The concrete subclass
ConstantProperty handles the common case of a fixed value;
state-dependent models (e.g. MarmottantSurfaceTension) override
__call__ directly.
__call__(state)
abstractmethod
¶
Evaluate the property at state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
BubbleState
|
Current bubble state. |
required |
Returns:
| Type | Description |
|---|---|
Array
|
Scalar value of the property. |
Source code in jbubble/bubble/property.py
jbubble.bubble.property.ConstantProperty
¶
Bases: Property
A property that returns a constant value regardless of state.
Fields
val : float or jax.Array
The constant value. May be a JAX array (including a traced value
inside jax.grad / jax.jit) so that gradients flow through.
jbubble.bubble.property.NeuralProperty
¶
Bases: Property
A Property backed by an Equinox neural network.
The network receives a normalised 1-D input [R / R0] and must
return a 1-D output of shape (1,). The caller is responsible for
any output transform needed to satisfy physical constraints — for
example, wrapping the final layer output with jax.nn.softplus or
jnp.exp to enforce positivity for surface tension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
net
|
Module
|
Any callable Equinox module with signature |
required |
Example
import equinox as eqx import jax import jax.numpy as jnp key = jax.random.PRNGKey(0) mlp = eqx.nn.MLP(in_size=1, out_size=1, width_size=32, depth=3, ... final_activation=jax.nn.softplus, key=key) sigma = NeuralProperty(net=mlp)
jbubble.bubble.property.as_property(val)
¶
Coerce a plain scalar or JAX array to a ConstantProperty, or pass through.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
val
|
float, jax.Array, or Property
|
A plain scalar, a JAX array (possibly a tracer), or an existing
|
required |
Returns:
| Type | Description |
|---|---|
Property
|
|
Source code in jbubble/bubble/property.py
Gas models¶
jbubble.bubble.gas.GasModel
¶
Bases: Module, ABC
Internal gas pressure model.
Computes the outward gas pressure p_gas as a function of the
instantaneous state. The equilibrium configuration (R0,
P_gas0) is read directly from state, so gas models only
store their intrinsic physical parameters (e.g. the polytropic
exponent).
Examples: polytropic law, van der Waals corrected gas.
__call__(state)
abstractmethod
¶
Compute gas pressure p_gas(state).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
BubbleState
|
Current bubble state. Uses |
required |
Returns:
| Type | Description |
|---|---|
scalar
|
Gas pressure. |
Source code in jbubble/bubble/gas.py
jbubble.bubble.gas.PolytropicGas
¶
Bases: GasModel
Polytropic gas law.
p_gas(R) = P_gas0 (R0 / R)^(3 gamma)
Fields
gamma : float Polytropic exponent (1.0 = isothermal, 1.4 = adiabatic air).
jbubble.bubble.gas.VanDerWaalsGas
¶
Bases: GasModel
Hard-core corrected polytropic gas (van der Waals).
p_gas(R) = P_gas0 ((R0^3 - h^3) / (R^3 - h^3))^gamma
where h = h_frac * R0 is the van der Waals hard-core radius.
Fields
gamma : float Polytropic exponent. h_frac : float Hard-core radius as a fraction of R0 (dimensionless). A common value for lipid shells is 1/5.61 ≈ 0.178.
Shell models¶
jbubble.bubble.shell.ShellModel
¶
Bases: Module, ABC
Bubble shell / coating model.
Computes the total inward stress from the shell, including:
- Laplace pressure from surface tension: 2 sigma(R) / R
- Shell viscous dissipation (e.g. 4 kappa_s Rdot / R^2)
- Shell elastic restoring forces (for thick shells)
Every ShellModel holds a Property as its sigma field.
A plain float is accepted and auto-converted to a Property
in __post_init__.
p_laplace(state)
¶
p_elastic(state)
abstractmethod
¶
p_viscous(state)
abstractmethod
¶
__call__(state)
¶
Compute total shell pressure p_shell(state).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
BubbleState
|
Current bubble state. |
required |
Returns:
| Type | Description |
|---|---|
scalar
|
Total inward shell pressure. |
Source code in jbubble/bubble/shell.py
jbubble.bubble.shell.NoShell
¶
Bases: ShellModel
No shell coating — only Laplace pressure.
p_shell = 2 sigma(R) / R
Suitable for uncoated gas bubbles. Accepts a plain float for
sigma (e.g. 72e-3 for water).
Fields
sigma : float or Property Surface tension law.
jbubble.bubble.shell.LipidShell
¶
Bases: ShellModel
Thin lipid shell with surface viscosity.
p_shell = 2 sigma(R) / R + 4 kappa_s Rdot / R^2
This is the shell model used by Marmottant (2005) and most Gompertz-smoothed variants.
Note on elastic contributions
p_elastic returns zero for this model. The shell elasticity is
not absent — it is encoded entirely in the surface tension Property
sigma. When sigma is state-dependent (e.g.
MarmottantSurfaceTension, GompertzSurfaceTension), the
area-elasticity term χ((R/Rb)² − 1) enters through p_laplace =
2 σ(R) / R, not through a separate p_elastic term. This is
consistent with how the Marmottant model is written in the
literature: the elastic and ruptured regimes modify σ(R) rather than
adding an independent stress contribution.
Fields
sigma : float or Property Surface tension law. kappa_s : float or Property Shell surface-dilatational viscosity [N s/m].
jbubble.bubble.shell.ThickShell
¶
Bases: ShellModel
Church (1995) thick viscoelastic shell.
In addition to Laplace pressure, this model includes thick-shell elastic and viscous contributions::
p_elastic = (4/3) G_s (d_s / R0) (1 - (R0/R)^3)
p_shell_visc = 4 mu_s d_s Rdot / R^2
Total shell pressure::
p_shell = 2 sigma(R) / R + p_elastic + p_shell_visc
Fields
sigma : float or Property Surface tension law. d_s : float or Property Shell thickness [m]. G_s : float or Property Shell shear modulus [Pa]. May be state-dependent (e.g. strain- stiffening / strain-softening). mu_s : float or Property Shell viscosity [Pa s]. May be state-dependent (e.g. shear- thinning).
Surface tension Properties¶
These are Property subclasses that encode a state-dependent surface tension law. They are passed as the sigma argument to shell models.
jbubble.bubble.shell.MarmottantSurfaceTension
¶
Bases: Property
Piecewise Marmottant surface tension law.
Three regimes based on the ratio R / R_buckle::
R <= R_buckle : sigma = 0 (buckled)
R_buckle < R < R_rupture : sigma = chi ((R/R_b)^2 - 1) (elastic)
R >= R_rupture : sigma = sigma_rupture (ruptured)
where R_buckle = R_buckle_ratio * state.R0 and R_rupture is derived from continuity of sigma at the elastic-to-ruptured transition.
Note: sigma(R) has discontinuous first derivatives at the regime
boundaries. For applications requiring smooth gradients (e.g.
gradient-based optimisation), use GompertzSurfaceTension instead.
Fields
R_buckle_ratio : float Buckling radius as a fraction of R0 (dimensionless). chi : float or Property Shell elasticity [N/m]. sigma_rupture : float or Property Surface tension (post-rupture value) [N/m].
jbubble.bubble.shell.GompertzSurfaceTension
¶
Bases: Property
Smooth Gompertz surface tension law.
A differentiable Gompertz function approximates the piecewise Marmottant surface tension, enabling robust automatic differentiation::
sigma(R) = a exp(-b exp(c (1 - R / R_buckle)))
where R_buckle = R_buckle_ratio * state.R0.
The Gompertz parameters b and c are derived from chi and sigma_rupture such that sigma(R0) matches the elastic regime and sigma -> sigma_rupture as R -> infinity. R0 is read from the state so this model stays consistent when R0 evolves (e.g. rectified diffusion).
Steepness of the transition is set by c, which is scaled by the
dimensionless sharpness factor. The base c (sharpness = 1) matches
the Marmottant elastic slope at R0, which gives a poor global fit to
the piecewise curve. The default sharpness = 3.3 is the mean
least-squares optimum over the elastic regime across the typical
parameter range, giving a markedly tighter match to Marmottant.
Scaling c leaves both anchors fixed: b is re-solved so sigma(R0) is
unchanged, and sigma -> sigma_rupture as R -> infinity regardless.
Well-posedness constraint
The Gompertz fit requires that the initial surface tension at R0 lies strictly below the rupture threshold::
chi * ((1 / R_buckle_ratio)^2 - 1) < sigma_rupture
Construction raises ValueError if this is violated. A common
mistake is setting R_buckle_ratio too small (e.g. 0.9), which inflates
sigma(R0) above sigma_rupture. Values around 0.95–0.99 are typical.
Fields
R_buckle_ratio : float Buckling radius as a fraction of R0 (dimensionless). chi : float or Property Shell elasticity [N/m]. sigma_rupture : float or Property Asymptotic (ruptured) surface tension [N/m]. sharpness : float Dimensionless multiplier on the transition rate c. Default 3.3 (least-squares fit to Marmottant); 1.0 recovers the elastic-slope match at R0.
Medium models¶
jbubble.bubble.medium.MediumModel
¶
Bases: Module, ABC
Surrounding medium (fluid / tissue) model.
Computes the total inward viscous and elastic stresses exerted by the surrounding medium on the bubble wall. For a Newtonian liquid this is just 4 mu Rdot / R. Viscoelastic media (Kelvin-Voigt, Neo-Hookean, etc.) add elastic restoring forces.
Subclasses must implement separate methods for the viscous and elastic
contributions, which are then summed in the default __call__ to get
the total medium pressure p_medium(state).
A plain float is accepted for mu and auto-converted to a
Property in __post_init__.
Fields
mu : float or Property
Viscous scaling parameter. For Newtonian, Kelvin-Voigt, and
Neo-Hookean media this is the dynamic viscosity [Pa s]. For
PowerLawMedium it is the consistency index K [Pa·s^n],
which reduces to dynamic viscosity when n = 1.
p_viscous(state)
abstractmethod
¶
p_elastic(state)
abstractmethod
¶
__call__(state)
¶
Compute total medium pressure p_medium(state).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
BubbleState
|
Current bubble state. |
required |
Returns:
| Type | Description |
|---|---|
scalar
|
Total inward medium pressure (viscous + elastic). |
Source code in jbubble/bubble/medium.py
jbubble.bubble.medium.NewtonianMedium
¶
Bases: MediumModel
Newtonian liquid medium.
p_medium = 4 mu Rdot / R
Fields
mu : float or Property Dynamic viscosity [Pa s].
jbubble.bubble.medium.KelvinVoigtMedium
¶
Bases: MediumModel
Kelvin-Voigt viscoelastic medium.
p_medium = 4 mu Rdot / R + (4 G / 3) ((R / R0)^3 - 1)
Fields
mu : float or Property Dynamic viscosity [Pa s]. R0 : float Equilibrium bubble radius [m]. G : float or Property Shear modulus [Pa]. May be state-dependent (e.g. strain-stiffening).
jbubble.bubble.medium.NeoHookeanMedium
¶
Bases: MediumModel
Neo-Hookean finite-strain viscoelastic medium.
Correctly captures finite-strain behaviour at large oscillation amplitudes where the Kelvin-Voigt linear approximation breaks down.
The elastic pressure is derived by integrating the deviatoric stress difference (σ_θθ − σ_rr) through the surrounding incompressible neo-Hookean solid. With the substitution v = r₀/r the integral collapses exactly to 2G ∫(1 + v³) dv, giving::
p_elastic = G (5/2 − 2 (R0/R) − (1/2) (R0/R)^4)
Key behaviour:
- Zero at R = R0 (no elastic stress at equilibrium).
- Reduces to 4G(R − R0)/R0 for small strains (identical to KV).
- Saturates to 5G/2 as R → ∞ (physical: material density near bubble thins to zero so elastic pressure plateaus).
- Diverges to −∞ for R → 0 (strong restoring when compressed).
Total medium pressure::
p_medium = 4 mu Rdot / R + G (5/2 − 2 (R0/R) − (1/2) (R0/R)^4)
Fields
mu : float or Property Dynamic viscosity [Pa s]. A plain float is auto-converted. G : float or Property Shear modulus [Pa]. A plain float is auto-converted. May be state-dependent (e.g. strain-stiffening).
jbubble.bubble.medium.PowerLawMedium
¶
Bases: MediumModel
Power-law (generalised Newtonian) surrounding medium.
The effective viscosity depends on the shear rate at the bubble wall:
η_eff = mu · |2 Ṙ/R|^(n-1)
Integrating the resulting stress field over the incompressible flow surrounding the bubble (Ting 1975) gives the viscous pressure:
p_visc = (4 mu / n) · (2|Ṙ/R|)^(n-1) · Ṙ/R
The factor 1/n arises from the spatial variation of η with radius. For n = 1 this reduces exactly to the Newtonian result 4 mu Ṙ/R.
Special cases:
n < 1 shear-thinning (biological tissue, blood, polymer gels)
n = 1 Newtonian (recovers ``NewtonianMedium`` with viscosity mu)
n > 1 shear-thickening
Note: power-law fluids have unbounded viscosity at zero shear rate
when n < 1. A small floor eps on |2 Ṙ/R| prevents numerical
divergence near turnaround points without affecting dynamics.
Fields
mu : float or Property
Consistency index K [Pa·s^n]. Stored as mu (inherited field
name) but has dimensions [Pa·s^n], not [Pa·s]. Equals the
dynamic viscosity when n = 1.
n_exp : float or Property
Power-law exponent (dimensionless, positive).
eps : float
Floor applied to |2 Ṙ/R| [s⁻¹]. Default 1e-6.
Equations of motion¶
jbubble.bubble.eom.EquationOfMotion
¶
Bases: Module, ABC, Generic[StateType]
Macroscopic equation of motion for bubble dynamics.
Assembles a GasModel, ShellModel, and MediumModel into a
complete ODE right-hand side. Concrete subclasses encode different
EoM formulations (Rayleigh-Plesset, Keller-Miksis, ...) which differ
in how they relate p_L to the radial acceleration Rddot.
The type parameter StateType binds each EoM to the state it operates
on — standard EoMs use BubbleState, confined models use
ConfinedBubbleState. Passing the wrong state type is caught by
the type checker rather than failing at runtime deep inside a JAX
trace.
The liquid-side boundary pressure is computed by the concrete helper
p_L as::
p_L = gas(state) - shell(state) - medium(state)
Because p_L is a regular method on an Equinox module, JAX can
differentiate through it automatically. EoMs that require dp_L/dt
(e.g. Keller-Miksis) can use jax.grad(self.p_L) instead of
hand-coding analytical derivatives for every component combination.
The driving acoustic pressure is received as a callable p_ac_fn
so that EoMs needing dp_ac/dt can compute it via jax.grad.
R0 and P_gas0 (equilibrium configuration) are seeded into the
state by initial_state() and carried as frozen constants by the
ODE (zero time derivatives in the standard case).
Fields
gas : GasModel Internal gas pressure model. shell : ShellModel Shell / coating model. medium : MediumModel Surrounding medium model. R0 : float or jax.Array Equilibrium bubble radius [m]. P_amb : float or jax.Array Ambient (far-field) pressure [Pa]. rho_L : float or jax.Array Liquid density [kg/m^3].
p_L(state)
¶
Liquid-side boundary pressure.
p_L = p_gas(state) - p_shell(state) - p_medium(state)
initial_state()
¶
Default initial state: equilibrium radius, zero velocity.
Seeds R0 and P_gas0 (Laplace equilibrium) into the state.
Override for coupled systems with a larger state vector.
Source code in jbubble/bubble/eom.py
__call__(t, state, p_ac_fn)
abstractmethod
¶
Compute the ODE right-hand side d(state)/dt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
scalar
|
Current time. |
required |
state
|
StateType
|
Current bubble state (type matches the EoM's state parameter). |
required |
p_ac_fn
|
callable (t -> scalar)
|
Driving acoustic pressure as a function of time. |
required |
Returns:
| Type | Description |
|---|---|
StateType
|
Time derivative of the state. |
Source code in jbubble/bubble/eom.py
jbubble.bubble.eom.RayleighPlesset
¶
Bases: EquationOfMotion[BubbleState]
Rayleigh-Plesset equation of motion (incompressible liquid).
R Rddot + 3/2 Rdot^2 = (1/rho) (p_L - P_amb - p_ac)
The simplest bubble dynamics EoM, assuming an incompressible surrounding liquid. No additional fields beyond the base class.
jbubble.bubble.eom.ModifiedRayleighPlesset
¶
Bases: EquationOfMotion[BubbleState]
Modified Rayleigh-Plesset with gas radiation damping.
Adds a first-order compressibility correction to the gas pressure term only, as used by Marmottant et al. (2005)::
R Rddot + 3/2 Rdot^2
= (1/rho) (p_L + (R/c) dp_gas/dt - P_amb - p_ac)
where dp_gas/dt = (dp_gas/dR) Rdot is computed via autodiff.
Fields
c_L : float or jax.Array Speed of sound in the liquid [m/s].
jbubble.bubble.eom.KellerMiksis
¶
Bases: EquationOfMotion[BubbleState]
Keller-Miksis equation of motion (first-order compressibility).
Accounts for liquid compressibility up to first order in the Mach number M = Rdot / c_L::
(1-M) R Rddot + 3/2 (1 - M/3) Rdot^2
= (1/rho) (1+M) (p_L - P_amb - p_ac)
+ R / (rho c) (dp_L/dt - dp_ac/dt)
The time derivative dp_L/dt is computed automatically via JAX
autodiff (chain rule through p_L), so this EoM works with any
combination of gas, shell, and medium models without hand-coded
derivatives.
Fields
c_L : float or jax.Array Speed of sound in the liquid [m/s].
jbubble.bubble.eom.Gilmore
¶
Bases: EquationOfMotion[BubbleState]
Gilmore equation of motion (Kirkwood-Bethe hypothesis).
Improves on Keller-Miksis by treating liquid compressibility through the Tait equation of state rather than a linear approximation. The enthalpy H and local speed of sound C at the bubble wall are exact functions of the wall pressure, giving accurate results at high Mach numbers::
(1 - Ṙ/C) R R̈ + 3/2 (1 - Ṙ/(3C)) Ṙ²
= (1 + Ṙ/C) H + (R/C)(1 - Ṙ/C) Ḣ
where the enthalpy difference between bubble wall and far field is::
H = n/(n-1) · K · [(p_L+B)^((n-1)/n) − (p∞+B)^((n-1)/n)]
K = (P_amb+B)^(1/n) / ρ_L
and the local sound speed satisfies::
C² = n·K·(p∞+B)^((n-1)/n) + (n-1)·H
with p∞ = P_amb + p_ac.
Ḣ is expanded analytically via the chain rule: ∂H/∂p_L and ∂H/∂p∞
come from the Tait formula; dp_L/dt is obtained via
jax.grad(self.p_L) and dp_ac/dt via jax.grad(p_ac_fn).
The resulting coupling of R̈ through dp_L/dṘ is absorbed into the
denominator, following the same algebraic pattern as KellerMiksis.
Default Tait parameters correspond to water (Gilmore 1952): n = 7, B = 304.9 MPa.
References
Gilmore, F. R. (1952). The growth or collapse of a spherical bubble in a viscous compressible liquid. Hydrodynamics Laboratory Report 26-4, California Institute of Technology.
Fields
n_tait : float or jax.Array Tait exponent (dimensionless). Default 7.0. B_tait : float or jax.Array Tait pressure constant [Pa]. Default 304.9e6.
jbubble.bubble.eom.LeightonTube
¶
Bases: EquationOfMotion[BubbleState]
Leighton model for a bubble confined in a rigid-walled tube.
.. warning::
**Work in progress.** Like ``SphericalConfinement``, this model is
not yet validated. The geometry factor ``beta`` is also unverified
against the reference (see the ``TODO`` in ``__call__``): the code
currently uses ``beta = 2 alpha - 1`` while the documented form is
``beta = 2 alpha``. Use with caution.
Modifies the inertia terms of the standard Rayleigh-Plesset equation to account for the added mass effect of a rigid cylindrical tube::
R Rddot [1 + (R/Gamma) beta] + 3/2 Rdot^2 [1 + 4R/(3 Gamma) beta]
= (1/rho) (p_L_damped - P_amb - p_ac)
where beta = 2 alpha with
alpha = (zeta/Gamma)(1 + 8 Gamma / (3 pi zeta)) - 1 encodes
the tube geometry (Gamma = tube radius, zeta = half-length).
Fields
c_L : float or jax.Array Speed of sound in the liquid [m/s]. tube_radius : float or jax.Array Inner radius of the confining tube [m]. tube_length : float or jax.Array Length of the confining tube [m].
jbubble.bubble.eom.SphericalConfinement
¶
Bases: EquationOfMotion[ConfinedBubbleState]
Bubble confined inside a thin elastic spherical vessel.
.. warning::
**Work in progress.** The confinement models
(``SphericalConfinement`` and ``LeightonTube``) are not yet
validated against reference solutions and their physics is still
being checked. In particular, this model assumes a **Newtonian
lumen liquid**: only ``medium.mu`` is used, so the elastic and
non-Newtonian contributions of viscoelastic media
(``KelvinVoigtMedium``, ``NeoHookeanMedium``, ``PowerLawMedium``)
are **ignored** here. Surrounding-tissue elasticity is represented
by the vessel wall, not by the medium model. Use with caution.
Couples the bubble wall dynamics to the vessel wall motion, producing
a 4-DOF state (ConfinedBubbleState) where a is the vessel wall
radius.
The coupled 2x2 system is::
A Rddot + B a_ddot = E (liquid continuity)
C Rddot + D a_ddot = F (momentum / vessel inertia)
solved via Cramer's rule at each time step. Row 1 is the incompressible-lumen constraint d/dt(R^2 Rdot - a^2 adot) = 0; row 2 is the radial momentum balance carrying the vessel + tissue inertia D.
Fields
c_L : float or jax.Array Speed of sound in the liquid [m/s]. vessel_radius : float or jax.Array Equilibrium vessel wall radius [m]. vessel_rho : float or jax.Array Vessel wall density [kg/m^3]. vessel_E : float or jax.Array Vessel Young's modulus [Pa]. vessel_nu : float or jax.Array Vessel Poisson's ratio (dimensionless). vessel_d : float or jax.Array Vessel wall thickness [m]. tissue_rho : float or jax.Array Surrounding tissue density [kg/m^3]. tissue_d : float or jax.Array Surrounding tissue thickness [m].