Skip to content

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
@abc.abstractmethod
def __call__(self, state: BubbleState) -> jax.Array:
    """Evaluate the property at *state*.

    Parameters
    ----------
    state : BubbleState
        Current bubble state.

    Returns
    -------
    jax.Array
        Scalar value of the property.
    """
    ...

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 (x: Array[1]) -> Array[1]. eqx.nn.MLP is the natural choice.

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 Property instance.

required

Returns:

Type Description
Property
Source code in jbubble/bubble/property.py
def as_property(val: ArrayLike | Property) -> Property:
    """Coerce a plain scalar or JAX array to a ``ConstantProperty``, or pass through.

    Parameters
    ----------
    val : float, jax.Array, or Property
        A plain scalar, a JAX array (possibly a tracer), or an existing
        ``Property`` instance.

    Returns
    -------
    Property
    """
    if isinstance(val, Property):
        return val
    return ConstantProperty(val=val)

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 state.R, state.R0, and state.P_gas0.

required

Returns:

Type Description
scalar

Gas pressure.

Source code in jbubble/bubble/gas.py
@abc.abstractmethod
def __call__(self, state: BubbleState) -> jax.Array:
    """Compute gas pressure p_gas(state).

    Parameters
    ----------
    state : BubbleState
        Current bubble state.  Uses ``state.R``, ``state.R0``,
        and ``state.P_gas0``.

    Returns
    -------
    scalar
        Gas pressure.
    """
    ...

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)

Laplace pressure contribution from surface tension.

Source code in jbubble/bubble/shell.py
def p_laplace(self, state: BubbleState) -> jax.Array:
    """Laplace pressure contribution from surface tension."""
    return 2.0 * self.sigma(state) / state.R

p_elastic(state) abstractmethod

Elastic contribution from the shell.

Source code in jbubble/bubble/shell.py
@abc.abstractmethod
def p_elastic(self, state: BubbleState) -> jax.Array:
    """Elastic contribution from the shell."""
    ...

p_viscous(state) abstractmethod

Viscous contribution from the shell.

Source code in jbubble/bubble/shell.py
@abc.abstractmethod
def p_viscous(self, state: BubbleState) -> jax.Array:
    """Viscous contribution from the shell."""
    ...

__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
def __call__(self, state: BubbleState) -> jax.Array:
    """Compute total shell pressure p_shell(state).

    Parameters
    ----------
    state : BubbleState
        Current bubble state.

    Returns
    -------
    scalar
        Total inward shell pressure.
    """
    return self.p_laplace(state) + self.p_elastic(state) + self.p_viscous(state)

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

Viscous contribution to the medium pressure.

Source code in jbubble/bubble/medium.py
@abc.abstractmethod
def p_viscous(self, state: BubbleState) -> jax.Array:
    """Viscous contribution to the medium pressure."""
    ...

p_elastic(state) abstractmethod

Elastic contribution to the medium pressure.

Source code in jbubble/bubble/medium.py
@abc.abstractmethod
def p_elastic(self, state: BubbleState) -> jax.Array:
    """Elastic contribution to the medium pressure."""
    ...

__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
def __call__(self, state: BubbleState) -> jax.Array:
    """Compute total medium pressure p_medium(state).

    Parameters
    ----------
    state : BubbleState
        Current bubble state.

    Returns
    -------
    scalar
        Total inward medium pressure (viscous + elastic).
    """
    return self.p_viscous(state) + self.p_elastic(state)

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)

Source code in jbubble/bubble/eom.py
def p_L(self, state: BubbleState) -> jax.Array:
    """Liquid-side boundary pressure.

    p_L = p_gas(state) - p_shell(state) - p_medium(state)
    """
    return self.gas(state) - self.shell(state) - self.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
def initial_state(self) -> BubbleState:
    """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.
    """
    R0 = jnp.asarray(self.R0)
    P_gas0 = (
        jnp.asarray(self.P_amb)
        + 2.0 * self.shell.sigma(BubbleState(R=R0, R0=R0)) / R0
    )
    return BubbleState(R=R0, R0=R0, P_gas0=P_gas0)

__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. R0 and P_gas0 derivatives are zero in the standard case.

Source code in jbubble/bubble/eom.py
@abc.abstractmethod
def __call__(
    self,
    t: Any,
    state: StateType,
    p_ac_fn: Callable,
) -> StateType:
    """Compute the ODE right-hand side  d(state)/dt.

    Parameters
    ----------
    t : scalar
        Current time.
    state : StateType
        Current bubble state (type matches the EoM's state parameter).
    p_ac_fn : callable  (t -> scalar)
        Driving acoustic pressure as a function of time.

    Returns
    -------
    StateType
        Time derivative of the state.  ``R0`` and ``P_gas0``
        derivatives are zero in the standard case.
    """
    ...

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].