Emergent Forces: Vortex Interaction

matter
forces
How hydrodynamic forces mimic particle interactions.
Author

Raúl Chiclano

Published

November 30, 2025

Objective

In the Dynamic Background Hypothesis, fundamental forces are not axiomatic but emergent properties of the vacuum hydrodynamics. Here, we test the interaction between two “particles” (topological defects) to see if they exhibit force-like behavior without external potentials.

Physical Setup

We initialize two vortices with the same topological charge (\(Q_1 = +1, Q_2 = +1\)) separated by a distance \(d\). In a standard vacuum, these would be static. However, in a superfluid background, the phase gradient (\(\nabla \theta\)) of one vortex creates a background flow velocity for the other.

According to the Magnus Effect, a vortex moving through a fluid flow experiences a force perpendicular to its velocity. For two co-rotating vortices, this results in a mutual orbital motion around their center of mass, mimicking an attractive/repulsive interaction depending on the frame of reference.

Methodology

  1. Product Ansatz: To create a valid wavefunction for multiple defects, we multiply the density profiles (creating two “holes”) and sum the phase fields: \[ \Psi_0 \propto \tanh\left(\frac{|\mathbf{r}-\mathbf{r}_1|}{\xi}\right) \cdot \tanh\left(\frac{|\mathbf{r}-\mathbf{r}_2|}{\xi}\right) \cdot e^{i(\theta_1 + \theta_2)} \]
  2. Imaginary Time Relaxation: We cool the system to find the exact ground state geometry for this topological configuration.
  3. Real Time Evolution: We let the system evolve under the GPE to observe the dynamics.
Code
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML

# --- 1. CONFIGURATION ---
N = 128
L = 30.0
dt = 0.005
dt_im = 0.005
g = 2.0
rho_0 = 1.0

x = np.linspace(-L/2, L/2, N)
y = np.linspace(-L/2, L/2, N)
X, Y = np.meshgrid(x, y)
dx = x[1] - x[0]

# Spectral Space
k = 2 * np.pi * np.fft.fftfreq(N, d=dx)
KX, KY = np.meshgrid(k, k)
K2 = KX**2 + KY**2

# Soft Trap Potential (Absorbing Boundaries)
R_grid = np.sqrt(X**2 + Y**2)
V_trap = 0.5 * (R_grid / (0.45*L))**10
V_trap[V_trap > 100] = 100

# --- 2. INITIAL CONDITION (TWO VORTICES) ---
d_sep = 3.0
x1, y1 = -d_sep, 0.0
x2, y2 = +d_sep, 0.0

# Vortex 1 Coords
X1, Y1 = X - x1, Y - y1
R1, Theta1 = np.sqrt(X1**2 + Y1**2), np.arctan2(Y1, X1)

# Vortex 2 Coords
X2, Y2 = X - x2, Y - y2
R2, Theta2 = np.sqrt(X2**2 + Y2**2), np.arctan2(Y2, X2)

# Healing length scale
xi = 1.0 / np.sqrt(g * rho_0)
xi_scale = 2.0 * xi

# Product Ansatz: Multiply densities, Sum phases
Psi = np.sqrt(rho_0) * np.tanh(R1/xi_scale) * np.tanh(R2/xi_scale) * np.exp(1j * (Theta1 + Theta2))

# Reference Phase for Relaxation (Topology Locking)
Theta_ref = np.angle(np.exp(1j * (Theta1 + Theta2)))

# --- 3. IMAGINARY TIME RELAXATION (COOLING) ---
U_kin_im = np.exp(-(K2 / 2.0) * dt_im)

# We relax for 100 steps to smooth the ansatz
for i in range(100):
    density = np.abs(Psi)**2
    Psi = Psi * np.exp(-(V_trap + g * density) * (dt_im / 2))
    Psi_k = np.fft.fft2(Psi)
    Psi_k *= U_kin_im
    Psi = np.fft.ifft2(Psi_k)
    density = np.abs(Psi)**2
    Psi = Psi * np.exp(-(V_trap + g * density) * (dt_im / 2))
    
    # Renormalize and enforce topology
    norm_factor = np.sqrt(rho_0) / np.max(np.abs(Psi))
    Psi *= norm_factor
    Psi = np.abs(Psi) * np.exp(1j * Theta_ref)

# --- 4. REAL TIME EVOLUTION ---
U_kin_real = np.exp(-1j * (K2 / 2.0) * dt)

def evolution_step_real(psi_in):
    # Split-Step Fourier Method
    psi_mod = psi_in * np.exp(-1j * (V_trap + g * np.abs(psi_in)**2) * (dt / 2))
    psi_k = np.fft.fft2(psi_mod)
    psi_k *= U_kin_real
    psi_mod = np.fft.ifft2(psi_k)
    psi_out = psi_mod * np.exp(-1j * (V_trap + g * np.abs(psi_mod)**2) * (dt / 2))
    return psi_out

# --- 5. VISUALIZATION ---
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
plt.close() # Prevent static output

im1 = ax1.imshow(np.abs(Psi)**2, extent=[-L/2, L/2, -L/2, L/2], cmap='inferno', vmin=0, vmax=1.2)
ax1.set_title("Density $|\\Psi|^2$")
ax1.set_xlabel("x")
ax1.set_ylabel("y")

im2 = ax2.imshow(np.angle(Psi), extent=[-L/2, L/2, -L/2, L/2], cmap='hsv', vmin=-np.pi, vmax=np.pi)
ax2.set_title("Phase $\\theta$")
ax2.set_xlabel("x")

def update(frame):
    global Psi
    # Evolve 5 steps per frame for speed
    for _ in range(5):
        Psi = evolution_step_real(Psi)
    im1.set_data(np.abs(Psi)**2)
    im2.set_data(np.angle(Psi))
    return im1, im2

# Generate Animation
ani = animation.FuncAnimation(fig, update, frames=80, interval=50, blit=True)

# Render as HTML5 Video (MP4)
display(HTML(ani.to_html5_video()))

Results

The simulation confirms that the two vortices are stable and exhibit a clear orbital motion around the center of the grid. This dynamic interaction emerges purely from the nonlinearity of the background field, without any explicit force terms in the Hamiltonian. This supports the hypothesis that fundamental forces can be reinterpreted as hydrodynamic interactions between topological defects.