Skip to main content
Particle Simulator supports two distinct simulation modes: kinematic mode (massless) and dynamic mode (mass-based). Each mode uses different physics calculations and is suited for different use cases.

Kinematic Mode (Massless)

Kinematic mode is a position-based simulation where particles follow predefined trajectories without considering forces or mass. This mode is ideal for particles that move along mathematical paths.

Characteristics

  • Particles have the isMassless flag set to true
  • Position is calculated directly from trajectory formulas
  • No force calculations or mass considerations
  • Gravity affects trajectory but not through force/mass equations
  • Simpler and more predictable motion

Position Calculation

In kinematic mode, the position at time t is calculated using:
const nx = p.p0_fis[0] + evaluarFormula(p.fx, nt, live.pos[0], live.pos[1], live.pos[2]) + p.v0_fis[0] * nt;
const ny = p.p0_fis[1] + evaluarFormula(p.fy, nt, live.pos[0], live.pos[1], live.pos[2]) + p.v0_fis[1] * nt;
const nz = p.p0_fis[2] + evaluarFormula(p.fz, nt, live.pos[0], live.pos[1], live.pos[2]) + p.v0_fis[2] * nt - 0.5 * g_val * Math.pow(nt, 2);
The position is determined by:
  • Initial position (p0_fis)
  • Trajectory formula (fx, fy, fz) evaluated at time t
  • Initial velocity (v0_fis) multiplied by time
  • Gravity (only in z-direction): -0.5 * g * t²
In kinematic mode, the fx, fy, fz fields represent displacement functions, not forces.

When to Use Kinematic Mode

Use kinematic mode when you want to:
  • Create particles that follow exact mathematical trajectories
  • Simulate projectile motion with simple parabolic paths
  • Have complete control over the particle’s path
  • Avoid complex force interactions
  • Create predictable, repeatable motion

PData Structure for Kinematic Mode

const kinematicParticle: PData = {
  id: 1,
  p0_fis: [0, 0, 10],        // Initial position (x, y, z)
  v0_fis: [5, 0, 0],         // Initial velocity
  a0_fis: [0, 0, 0],         // Not used in kinematic mode
  fx: "0",                   // Displacement formula in x
  fy: "0",                   // Displacement formula in y
  fz: "0",                   // Displacement formula in z
  curr_fis: [0, 0, 10],      // Current position
  curr_vel: [5, 0, 0],       // Current velocity
  t: 0,                      // Current time
  trail_three: [],           // Trail for visualization
  enSuelo: false,
  color: "#00ff88",
  mass: 1,                   // Not used in kinematic mode
  isMassless: true,          // KEY: Set to true for kinematic mode
  forces: [],                // Not used in kinematic mode
  events: []
};
Even though kinematic particles don’t use forces, you can still set initial velocity (v0_fis) to create linear motion combined with your trajectory formulas.

Dynamic Mode (Mass-Based)

Dynamic mode is a force-based simulation using Newtonian physics. Particles have mass and respond to forces according to Newton’s laws of motion. This mode uses the Velocity Verlet integration algorithm for accurate physics simulation.

Characteristics

  • Particles have the isMassless flag set to false
  • Motion is determined by forces and mass (F = ma)
  • Uses Velocity Verlet integration for stability
  • Supports multiple simultaneous forces
  • Realistic physics including friction and collisions
  • Can handle complex force interactions

Velocity Verlet Integration

The Velocity Verlet algorithm provides more accurate and stable numerical integration than basic Euler methods. It calculates position and velocity in three steps:

Step 1: Update Position

// r(t+dt) = r(t) + v(t)*dt + 0.5*a(t)*dt²
posFinal = [
  live.pos[0] + live.vel[0] * dT + 0.5 * accOld[0] * dT * dT,
  live.pos[1] + live.vel[1] * dT + 0.5 * accOld[1] * dT * dT,
  live.pos[2] + live.vel[2] * dT + 0.5 * accOld[2] * dT * dT,
];

Step 2: Calculate New Acceleration

// Sum all forces at the new position
const sumF = p.forces.reduce((acc, f) => {
  const fx = evaluarFormula(f.vec[0], nt, posFinal[0], posFinal[1], posFinal[2]);
  const fy = evaluarFormula(f.vec[1], nt, posFinal[0], posFinal[1], posFinal[2]);
  const fz = evaluarFormula(f.vec[2], nt, posFinal[0], posFinal[1], posFinal[2]);
  return [acc[0] + fx, acc[1] + fy, acc[2] + fz];
}, [0, 0, 0]);

const m = p.mass || 0.001;

// a(t+dt) = F(r(t+dt)) / m
accNew = [
  fuerzaResultanteX / m,
  fuerzaResultanteY / m,
  fuerzaResultanteZ / m - g_val,
];

Step 3: Update Velocity

// v(t+dt) = v(t) + 0.5*(a(t) + a(t+dt))*dt
velFinal = [
  live.vel[0] + 0.5 * (accOld[0] + accNew[0]) * dT,
  live.vel[1] + 0.5 * (accOld[1] + accNew[1]) * dT,
  live.vel[2] + 0.5 * (accOld[2] + accNew[2]) * dT,
];
Velocity Verlet is symplectic and time-reversible, making it ideal for physics simulations. It conserves energy better than simpler methods like Forward Euler.

When to Use Dynamic Mode

Use dynamic mode when you want to:
  • Simulate realistic physics with forces
  • Model interactions between multiple forces
  • Include friction, drag, and other resistive forces
  • Create complex emergent behavior
  • Simulate collisions and ground contact
  • Model systems where mass matters (different masses behave differently)

PData Structure for Dynamic Mode

const dynamicParticle: PData = {
  id: 2,
  p0_fis: [0, 0, 10],        // Initial position (x, y, z)
  v0_fis: [5, 0, 0],         // Initial velocity
  a0_fis: [0, 0, 0],         // Initial acceleration
  fx: "0",                   // Not used in dynamic mode
  fy: "0",                   // Not used in dynamic mode
  fz: "0",                   // Not used in dynamic mode
  curr_fis: [0, 0, 10],      // Current position
  curr_vel: [5, 0, 0],       // Current velocity
  t: 0,                      // Current time
  trail_three: [],           // Trail for visualization
  enSuelo: false,
  color: "#ff0088",
  mass: 2.5,                 // KEY: Mass affects acceleration (F=ma)
  isMassless: false,         // KEY: Set to false for dynamic mode
  forces: [                  // KEY: Forces drive the motion
    {
      id: 1,
      vec: ["-0.1*x", "0", "0"]  // Spring-like force
    }
  ],
  events: []
};

Comparison

Advantages:
  • Simpler to configure
  • Exact trajectory control
  • No force calculations needed
  • More predictable behavior
  • Lower computational cost
Disadvantages:
  • Cannot simulate force interactions
  • No realistic mass-based physics
  • Limited to predefined paths
  • No friction or collision response

Switching Between Modes

You can switch between modes by changing the isMassless flag:
// Convert from kinematic to dynamic
particle.isMassless = false;
particle.mass = 1.0;  // Set an appropriate mass
particle.forces = [   // Define forces
  { id: 1, vec: ["0", "0", "0"] }
];

// Convert from dynamic to kinematic
particle.isMassless = true;
particle.fx = "2*cos(t)";  // Define trajectory
particle.fy = "0";
particle.fz = "2*sin(t)";
When switching modes, make sure to properly configure the relevant fields (forces for dynamic mode, fx/fy/fz for kinematic mode) to avoid unexpected behavior.

Implementation Reference

The mode-specific physics calculations are implemented in PhysicsUpdate.tsx:110-287:
  • Kinematic mode: Lines 110-127
  • Dynamic mode (Velocity Verlet): Lines 128-287
  • Particles - Learn about particle properties and structure
  • Forces - Understanding the force system for dynamic mode
  • Visualization - How particles are rendered in both modes

Build docs developers (and LLMs) love