TheAlgorithms/Python · error · ValueError

Impossible bulk modulus

Error message

Impossible bulk modulus

What it means

Raised by physics/speed_of_sound.py:speed_of_sound_in_a_fluid when bulk_modulus <= 0 while density > 0. The bulk modulus measures a fluid's resistance to compression and is strictly positive for any physical medium; a non-positive value would make sqrt(bulk_modulus/density) zero or imaginary. This is the second guard, so you only see it once density has passed its check.

Source

Thrown at physics/speed_of_sound.py:40

def speed_of_sound_in_a_fluid(density: float, bulk_modulus: float) -> float:
    """
    Calculates the speed of sound in a fluid from its density and bulk modulus

    Examples:
    Example 1 --> Water 20°C: bulk_modulus= 2.15MPa, density=998kg/m³
    Example 2 --> Mercury 20°C: bulk_modulus= 28.5MPa, density=13600kg/m³

    >>> speed_of_sound_in_a_fluid(bulk_modulus=2.15e9, density=998)
    1467.7563207952705
    >>> speed_of_sound_in_a_fluid(bulk_modulus=28.5e9, density=13600)
    1447.614670861731
    """

    if density <= 0:
        raise ValueError("Impossible fluid density")
    if bulk_modulus <= 0:
        raise ValueError("Impossible bulk modulus")

    return (bulk_modulus / density) ** 0.5


if __name__ == "__main__":
    import doctest

    doctest.testmod()

View on GitHub (pinned to f5988cc097)

Solutions

  1. Pass bulk_modulus in pascals (Pa); water at 20C is 2.15e9, mercury 28.5e9 - the docstring's 'MPa' labels are misleading, the code expects Pa.
  2. If your source gives compressibility k, convert with bulk_modulus = 1/abs(k) before calling.
  3. Validate bulk_modulus > 0 together with density > 0 before the call.
  4. Catch ValueError at the call site if zero bulk modulus is a legitimate 'no data' marker in your pipeline.

Example fix

# before (docstring examples label units as MPa but pass Pa)
speed_of_sound_in_a_fluid(bulk_modulus=2.15, density=998)  # works but wrong physics
speed_of_sound_in_a_fluid(bulk_modulus=0, density=998)    # raises

# after
speed_of_sound_in_a_fluid(bulk_modulus=2.15e9, density=998)
Defensive patterns

Strategy: validation

Validate before calling

if bulk_modulus <= 0 or density <= 0:
    raise ValueError('need density > 0 kg/m^3 and bulk_modulus > 0 Pa')
c = speed_of_sound_in_a_fluid(bulk_modulus=bulk_modulus, density=density)

Type guard

def is_valid_bulk_modulus(b: float) -> bool:
    return isinstance(b, (int, float)) and b > 0

Try / catch

try:
    speed_of_sound_in_a_fluid(b, d)
except ValueError as e:
    if 'bulk modulus' in str(e):
        ...

Prevention

When it happens

Trigger: Calling speed_of_sound_in_a_fluid(bulk_modulus=0, density=998), or with a negative bulk_modulus and any positive density, e.g. speed_of_sound_in_a_fluid(bulk_modulus=-2.15e9, density=998).

Common situations: Confusing MPa and Pa magnitudes (the docstring examples say 2.15MPa but the code expects 2.15e9 Pa); a missing config key defaulting to 0; sign error when converting a negative compressibility (k = -1/V * dV/dP is negative by convention) to bulk modulus (B = -V dP/dV is positive); using tabulated values for a substance at a state where no data exists.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/06db3fa84ee730ec. Report an issue: GitHub.