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).
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].
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.
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.
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 system is::
A Rddot + B a_ddot = F (force balance)
C Rddot + D a_ddot = E (vessel inertia)
solved via Cramer's rule at each time step.
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_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].
initial_state()
¶
Initial state: equilibrium bubble and vessel radii, zero velocities.