How to Simulate Acoustic Levitation in Matter.js
This article explains how to simulate acoustic levitation in the Matter.js 2D physics engine by modeling acoustic radiation forces and standing wave nodes. By calculating Gor'kov-inspired restoring forces and applying them iteratively to disc bodies via the engine's update cycle, you can trap, stabilize, and suspend small particles between simulated ultrasonic transducers against gravity.
Fundamentals of the Acoustic Model
Acoustic levitation relies on standing acoustic waves formed between an emitter and a reflector (or opposing emitters). In a 1D vertical standing wave, the acoustic radiation force \(F_{\text{rad}}\) acting on small particles can be approximated as a sinusoidal force function:
\[F_{\text{rad}} = -F_{\text{max}} \sin(2 k y)\]
Where:
- \(k = \frac{2\pi}{\lambda}\) is the wave number, with \(\lambda\) representing the wavelength.
- \(y\) is the vertical position relative to an emitter.
- \(F_{\text{max}}\) is the maximum trapping force determined by sound pressure and particle volume.
Stable pressure nodes occur at intervals of \(\frac{\lambda}{2}\). Particles denser than the medium are pushed away from antinodes and become trapped at these nodal points.
Setting Up Matter.js
To set up the simulation, initialize the standard Matter.js modules and construct the world. Gravity can be left at its default downward value (\(g = 1\)) to demonstrate the acoustic force counteracting gravity, or reduced for easier calibration.
const { Engine, Render, Runner, Bodies, Composite, Events, Body, Vector } = Matter;
const engine = Engine.create();
const world = engine.world;
// Standard downward gravity
engine.gravity.y = 1;
const render = Render.create({
element: document.body,
engine: engine,
options: {
width: 800,
height: 600,
wireframes: false
}
});
Render.run(render);
const runner = Runner.create();
Runner.run(runner, engine);Creating the Acoustic Field Parameters
Define the wavelength and field strength. The wavelength sets the spacing between the levitation nodes, while the maximum force determines the trap's stiffness.
const WAVELENGTH = 80; // Distance in pixels
const K = (2 * Math.PI) / WAVELENGTH;
const F_MAX = 0.005; // Peak acoustic force
const LATERAL_STIFFNESS = 0.0001; // Restores particles to the center axis
const FIELD_CENTER_X = 400;Spawning Disc Bodies
Create small disc bodies using Bodies.circle. Assign a
low friction and an appropriate mass so that the calculated force can
overcome gravity.
const discs = [];
const discRadius = 8;
for (let i = 0; i < 5; i++) {
const disc = Bodies.circle(FIELD_CENTER_X + (Math.random() - 0.5) * 20, 100 + i * 40, discRadius, {
frictionAir: 0.05, // High air resistance aids stabilization
restitution: 0.2,
render: { fillStyle: '#4CAF50' }
});
discs.push(disc);
Composite.add(world, disc);
}Applying Acoustic Forces
Use the beforeUpdate event to apply forces before every
physics step. The applied force contains two components:
- Vertical Force (\(F_y\)): The primary standing-wave force counteracting gravity and pulling particles to nodes.
- Horizontal Force (\(F_x\)): A lateral confining force that simulates the acoustic beam's focal waist, preventing particles from slipping out sideways.
Events.on(engine, 'beforeUpdate', () => {
discs.forEach(disc => {
const y = disc.position.y;
const x = disc.position.x;
// Vertical standing wave force: oscillates between nodes
const fy = -F_MAX * Math.sin(2 * K * y);
// Horizontal confining force toward the beam center
const fx = -LATERAL_STIFFNESS * (x - FIELD_CENTER_X);
// Apply force directly to the body center of mass
Body.applyForce(disc, disc.position, { x: fx, y: fy });
});
});Tuning for Stability
Simulating acoustic levitation requires balancing three factors:
- Air Resistance (
frictionAir): In real acoustic levitation, viscous air damping removes kinetic energy. Without sufficientfrictionAir(around0.03to0.08), discs will oscillate indefinitely around the nodes and eventually escape. - Wave Amplitude (
F_MAX): If \(F_{\text{max}} < m \cdot g\), the acoustic force will not overcome gravity, and particles will fall. Set \(F_{\text{max}}\) high enough to create a net upward force beneath each node. - Wavelength Scaling: Ensure particle radii remain significantly smaller than \(\frac{\lambda}{4}\) (the distance between a node and an antinode) to preserve the physical assumption of the Gor'kov potential.