Two-phase zone exchange
Independent zones of a two-phase apparatus, each exchanging particles with the rest of the apparatus.
- Name:
two_phase_zone_exchange - Field:
physics/statistical_mechanics - Formalism: jump process
- References: Barsky 2020
Factory
@register_model(
field='physics/statistical_mechanics',
tags=('jump process', 'binomial', 'fluctuations', 'two-phase flow'),
references=('Barsky 2020',),
defaults={'until': 20.0, 'dt': 0.5},
)
def two_phase_zone_exchange(
n_zones: int = 100,
*,
Na: float = 100.0,
p: float = 0.1,
k: float = 1.0,
) -> System:
"""Return independent zones of a two-phase apparatus, each exchanging particles with the rest of the apparatus.
The zones start empty and their numbers of particles settle on the binomial distribution of mean `Na p` and
variance `Na p (1 - p)`.
Args:
n_zones:
The number of independent zones.
Na:
The number of particles in the apparatus and a zone.
p:
The volume fraction of a zone.
k:
The rate of exchange.
Returns:
system:
The model, with the numbers `zones.N`.
Examples:
>>> from skcomplex.models.physics.statistical_mechanics import two_phase_zone_exchange
>>> two_phase_zone_exchange(5).elements[0].check().prepare().size_
5
"""
return System(
elements=[GroupElement('zones', element=ZoneElement, size=n_zones, values={'Na': Na, 'p': p, 'k': k})],
)
Components
class ZoneElement(Element):
"""Small zone of a two-phase apparatus that exchanges particles with the rest of it.
Every one of the `Na` particles enters the zone at the rate `k p` and leaves it at the rate `k (1 - p)`, where
`p = dV / V` is the volume fraction of the zone, so the number in the zone is binomial with mean `Na p`.
Args:
label:
The label of the zone or the group.
visual:
How the element is drawn, or `None` for `default_visual_`.
N:
The initial number of particles in the zone.
Na:
The number of particles in the apparatus and the zone.
p:
The volume fraction of the zone.
k:
The rate of exchange.
Examples:
>>> from skcomplex.models.physics.statistical_mechanics import ZoneElement
>>> ZoneElement('zone').Na
100.0
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
N: Annotated[float, StateSpec(domain=NN)] = 0.0,
Na: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 100.0,
p: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.1,
k: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
) -> None:
super().__init__(label, visual=visual)
self.N = N
self.Na = Na
self.p = p
self.k = k
def _get_laws(self, s: SimpleNamespace) -> list[BaseLaw]:
"""Return the entries into and exits from the zone.
Args:
s:
The namespace of the symbols the laws can use.
Returns:
laws:
The laws of the component.
"""
return [
JumpLaw(s.k * s.p * (s.Na - s.N), {s.N: 1}),
JumpLaw(s.k * (1 - s.p) * s.N, {s.N: -1}),
]