Skip to content

Mechanics

Mechanics realizations shared by the physics packages: reflections off walls.

ReflectionInteraction(label, *, target, guard, positions=('x',), velocities=('x_d1',), direction=0, restitution=1.0, region=None)

Bases: CrossingInteraction

Reflection of a moving point off a wall g(x) = 0, with a coefficient of restitution e.

When the guard g crosses zero, the velocity v of the point becomes v - (1 + e) (v . n) n / |n|**2, where n is the gradient of g with respect to the position. The normal velocity is reversed and scaled by e, and the tangential velocity is kept, so e = 1 is a specular, elastic reflection. The position and the velocity are given by the names of their states, scalar or vector, whose components pair up in order. A region restricts the wall to the part of the surface where it holds, and the point crosses the rest of the surface freely.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
target Annotated[str, RoleSpec()]

The path of the element that reflects.

required
guard Callable[[SimpleNamespace], object]

The function guard(namespace) of the wall, an expression of the position that is zero on the wall.

required
positions Sequence[str]

The names of the states that hold the position.

('x',)
velocities Sequence[str]

The names of the states that hold the velocity, the first derivatives of the position.

('x_d1',)
direction int

1 for crossings from negative to positive, -1 for the opposite, and 0 for both.

0
restitution Annotated[float, ParameterSpec(domain=closed(0, 1))]

The coefficient of restitution, the ratio of the normal speeds after and before the reflection.

1.0
region Callable[[SimpleNamespace], object] | None

The function region(namespace) of the condition that holds on the part of the surface that is a wall, or None for a wall on the whole surface.

None

Raises:

Type Description
ValidationError

The positions and the velocities have different numbers of names, or a function is not callable.

Examples:

>>> from skcomplex.core.elements import PointElement
>>> from skcomplex.core.spaces import ContinuousSpace
>>> from skcomplex.core.system import System
>>> from skcomplex.engine.runtime import Simulation
>>> from skcomplex.models.physics.common.mechanics import ReflectionInteraction
>>> wall = ReflectionInteraction('wall', target='ball', guard=lambda s: s.target.x[0] - 1, direction=1)
>>> ball = PointElement('ball', x=[0.0, 0.0], x_d1=[1.0, 1.0])
>>> system = System(elements=[ball], interactions=[wall], space=ContinuousSpace(n_dim=2))
>>> trajectory = Simulation(system, dt=0.5).check().prepare().run(until=2.0).trajectory_
>>> trajectory.values('ball.x')[-1].tolist()
[0.0, 2.0]
Source code in src/skcomplex/models/physics/common/mechanics/_reflection.py
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    guard: Callable[[SimpleNamespace], object],
    positions: Sequence[str] = ('x',),
    velocities: Sequence[str] = ('x_d1',),
    direction: int = 0,
    restitution: Annotated[float, ParameterSpec(domain=RealSet.closed(0, 1))] = 1.0,
    region: Callable[[SimpleNamespace], object] | None = None,
) -> None:
    super().__init__(label, target=target, guard=guard, direction=direction)
    self.positions = positions
    self.velocities = velocities
    self.restitution = restitution
    self.region = region