01/ Introduction to Vector Fields
A <strong>vector field</strong> is a mapping that associates a vector to every point in a coordinate space. Mathematically, in an $n$-dimensional Euclidean space, a vector field is represented as a function:
Vector fields are the core mathematical framework for modeling physical phenomena where quantities vary in both direction and magnitude across space. Examples include the velocity of fluid particles, electrostatic and gravitational forces, atmospheric wind currents, and the phase portraits of non-linear dynamical systems.
Visualizing these fields is a primary challenge in scientific computing. Rather than drawing static arrays of discrete arrows—which clutter regions of high intensity—we compute continuous <strong>streamlines</strong> (integral curves) that follow the field's tangents.
02/ Sandbox Mechanics & Features
Our implementation leverages <strong>Macroquad</strong> for fast rendering, <strong>Egui</strong> for immediate-mode GUI control, and <strong>Glam</strong> for vector operations. The engine includes:
- 7 Mathematical Presets: Incorporates classic fields (Vortex, Electric Dipole, Saddle) alongside noise-based flow models (Perlin Curl, Perlin Gradient, Trig Flow) and interactive N-Body orbital mechanics.
- <strong>Dual Physics Models:</strong> Supports <strong>Velocity Flow</strong> ($\mathbf{v} = \mathbf{F}(\mathbf{x})$) where particles trace fields directly, and <strong>Force Field</strong> ($\mathbf{a} = \mathbf{F}(\mathbf{x})/m$) enabling inertial motion, orbits, and slingshots.
- Dynamic Viewport Interactivity: Allows users to perturb field coordinates locally via attraction, repulsion, vortices, or by spawning, dragging, and deleting massive gravitational bodies.
- Tapered Alpha-Faded Particle Trails: Implements alpha-decay buffers mapping historical coordinates onto screen-space vectors for high-fidelity visualization.
03/ Hardware-Accelerated Sandbox (WASM)
The Rust simulation compiles directly to WebAssembly. Adjust particle settings, toggle color palettes, alter equations, and warp vectors in real-time. Click and drag on the viewport to interact.
Interactive Physics Engine
Hardware Accelerated WebAssembly Vector Field Engine
Live WebAssembly interactive render. Click inside canvas to interact.
04/ Theoretical Calculus & Vector Operators
Analyzing a vector field $\mathbf{F} = (P, Q, R)$ requires examining its local derivatives governed by two fundamental operators in vector calculus: <strong>Divergence</strong> and <strong>Curl</strong>.
Divergence ($\nabla \cdot \mathbf{F}$)
Divergence measures the net outward flux of a vector field per unit volume from an infinitesimal boundary around a point. It quantifies whether a point acts as a <strong>source</strong> ($\nabla \cdot \mathbf{F} > 0$) or a <strong>sink</strong> ($\nabla \cdot \mathbf{F} < 0$). In Cartesian coordinates:
Curl ($\nabla \times \mathbf{F}$)
Curl measures the rotation or vorticity of a vector field about a point. It yields a vector describing the axis and rate of rotation. In 3D:
In a two-dimensional vector field $\mathbf{F}(x, y) = (P, Q)$, the curl is simplified to a scalar component acting orthogonal to the coordinate plane:
05/ Governing Equations of Presets
1. Perlin Curl Noise (Divergence-Free)
To model fluid-like currents that do not clump into singular points, we compute the curl of a 2D scalar Fractal Brownian Motion field $\psi(x, y, t)$:
We approximate these partial derivatives numerically via central differences:
2. Electric Dipole
Calculates forces acting from a source at $\mathbf{p}_{\text{src}}$ and a sink at $\mathbf{p}_{\text{snk}}$:
Where $\delta$ represents a softening parameter to prevent singularities as the distance approaches zero.
3. Rotational Vortex (Solenoidal)
Represents pure rotational motion around a central axis. Because particles circle without moving outward, the divergence is zero:
4. Radial Sink (Convergent)
Models attraction toward a single sink point, representative of localized fluid drainage. Flow is irrotational (curl is zero):
06/ Dual Physics Models & Numerical Integration
Our simulation environment supports two fundamentally distinct physical models to translate vector values into coordinate displacements:
- <strong>Velocity Flow (First-order system):</strong> Particle velocity maps directly to the vector field ($\mathbf{v} = \mathbf{F}(\mathbf{x})$). The pathlines follow streamlines exactly:$$\frac{d\mathbf{x}}{dt} = \mathbf{F}(\mathbf{x})$$
- <strong>Force Field (Second-order system with Inertia):</strong> The vector field acts as an accelerating force ($\mathbf{a} = \mathbf{F}(\mathbf{x})/m$). Particles carry inertia, enabling orbits, chaotic loops, and slingshot physics:$$\frac{d^2\mathbf{x}}{dt^2} + \gamma \frac{d\mathbf{x}}{dt} = \mathbf{F}(\mathbf{x})$$
Numerical Integrators: Euler vs. Runge-Kutta 4 (RK4)
For stable orbits and high-vorticity zones, the sandbox implements a <strong>Runge-Kutta 4th Order (RK4)</strong> scheme:
07/ 2D Streamline Preview & Calculus HUD
Hover your cursor over the interactive canvas below to evaluate coordinates, vector magnitudes, divergence, and curl calculations calculated dynamically via central differences.
Field Controls
08/ Python Streamline Engine
Below is a Python script using NumPy and Matplotlib to calculate vector field streamlines and numerical Jacobian matrices:
import numpy as np
import matplotlib.pyplot as plt
def compute_jacobian(F, x, y, dx=1e-5):
"""
Computes the numerical Jacobian matrix of a 2D vector field F at (x, y)
using central differences.
"""
Fx_x, Fy_x = F(x + dx, y)
Fx_x_neg, Fy_x_neg = F(x - dx, y)
Fx_y, Fy_y = F(x, y + dx)
Fx_y_neg, Fy_y_neg = F(x, y - dx)
dFx_dx = (Fx_x - Fx_x_neg) / (2 * dx)
dFy_dx = (Fy_x - Fy_x_neg) / (2 * dx)
dFx_dy = (Fx_y - Fx_y_neg) / (2 * dx)
dFy_dy = (Fy_y - Fy_y_neg) / (2 * dx)
return np.array([
[dFx_dx, dFx_dy],
[dFy_dx, dFy_dy]
])
def vortex_field(x, y):
return np.array([-y, x])
x, y = np.meshgrid(np.linspace(-3, 3, 20), np.linspace(-3, 3, 20))
u, v = vortex_field(x, y)
plt.figure(figsize=(6, 6), facecolor='#09090b')
ax = plt.axes()
ax.set_facecolor('#09090b')
ax.streamplot(x, y, u, v, color='#38bdf8', linewidth=1, arrowsize=1.2)
ax.tick_params(colors='#71717a')
plt.title("Vector Field Streamlines", color='#fafafa')
plt.show()