Skip to content

Continuum percolation

Overlapping disks at uniform positions in a square, whose clusters percolate near a filling of 1.13.

  • Name: continuum_percolation
  • Field: physics/statistical_mechanics
  • Formalism: static solution
  • References: Satz 2022; Mertens and Moore 2012

Factory

@register_model(
    field='physics/statistical_mechanics',
    tags=('percolation', 'disorder', 'clusters', 'static'),
    references=('Satz 2022', 'Mertens and Moore 2012'),
)
def continuum_percolation(
    filling: float = 1.1,
    *,
    side: float = 60.0,
    radius: float = 1.0,
    random_state: int | np.random.Generator | None = 0,
) -> System:
    """Return overlapping disks at uniform positions in a square, whose clusters percolate near a filling of 1.13.

    The number of disks is `filling side^2 / (pi radius^2)`. The clusters of touching disks are read by
    `ClusterAnalysis(radius=radius)`, and an `Experiment` sweeps `filling` and `random_state` for the spanning
    probability (Satz 2022 ch. 3).

    Args:
        filling:
            The filling factor, the total area of the disks over the area of the square.

        side:
            The side of the square.

        radius:
            The radius of a disk.

        random_state:
            The seed or generator of the positions.

    Returns:
        system:
            The model, with the positions `disks.x`.

    Examples:
        >>> from skcomplex.models.physics.statistical_mechanics import continuum_percolation
        >>> continuum_percolation(1.0, side=10.0).elements[0].size
        32
    """
    size = round(filling * side**2 / (np.pi * radius**2))
    positions = np.random.default_rng(random_state).uniform(0.0, side, (size, 2))
    visual = VisualSpec('points', {'position': 'x', 'radius': radius, 'states': ()})
    disks = GroupElement('disks', element=DiskElement, size=size, values={'x': positions}, visual=visual)
    return System(elements=[disks], space=ContinuousSpace(extent=[side, side]), time=StaticTime())

Components

class DiskElement(Element):
    """Disk of the plane at a position that no law moves.

    Args:
        label:
            The label of the disk or the group.

        x:
            The position of its centre.

    Examples:
        >>> from skcomplex.models.physics.statistical_mechanics import DiskElement
        >>> DiskElement('disk', x=(1.0, 2.0)).x
        (1.0, 2.0)
    """

    def __init__(
        self,
        label: str,
        x: Annotated[npt.ArrayLike, StateSpec(vector=True, role='position')] = 0.0,
    ) -> None:
        super().__init__(label)
        self.x = x