mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
93 lines
3.3 KiB
Python
93 lines
3.3 KiB
Python
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
from matplotlib.animation import FuncAnimation
|
|
from IPython.display import HTML
|
|
|
|
# --- SETTINGS FOR THE SUPERFLUID UNIVERSE ---
|
|
# Increase N to see more complex vortex structures (filaments)
|
|
N_particles = 400
|
|
box_size = 10.0
|
|
dt = 0.04 # Simulation step (smoothness of motion)
|
|
steps = 400
|
|
|
|
# --- THE "HYPOTHESIS" PARAMETERS ---
|
|
# 1. ATTRACTION (Bjerknes Force / Gravity)
|
|
# This represents the low-pressure zones or cavitation collapse
|
|
k_attr = 100.0
|
|
soft_attr = 2.0 # "Blurring" of gravity at the center
|
|
|
|
# 2. REPULSION (Orbital Resonance / Electric Charge)
|
|
# IMPORTANT: Using Power 2 (1/r^2) to match Attraction power.
|
|
# This balance creates the "Matter as a Process" effect from the paper.
|
|
k_repel = 10.0
|
|
soft_repel = 0.1 # Repulsion is "sharper" than attraction to create a core
|
|
|
|
# 3. ENVIRONMENT
|
|
R_max = 22.0 # Reach of interaction (defines filament length)
|
|
damping = 0.98 # Higher value = less friction (more "Superfluid")
|
|
thermal_noise = 10.0 # Initial "Heat" to trigger the vortex formation
|
|
|
|
# --- INITIALIZATION ---
|
|
# Starting with random positions and initial thermal movement
|
|
pos = np.random.rand(N_particles, 2) * box_size
|
|
vel = (np.random.rand(N_particles, 2) - 0.5) * thermal_noise
|
|
|
|
fig, ax = plt.subplots(figsize=(8, 8), facecolor='#000000')
|
|
ax.set_xlim(0, box_size)
|
|
ax.set_ylim(0, box_size)
|
|
ax.set_title("Vortex Matter Evolution (Equal Force Powers 1/r²)", color='white', fontsize=12)
|
|
ax.set_axis_off()
|
|
|
|
# Blue glow for the vortex cores
|
|
scatter = ax.scatter(pos[:, 0], pos[:, 1], s=25, c='#00f2ff', edgecolors='white', linewidth=0.2, alpha=0.8)
|
|
|
|
def update(frame):
|
|
global pos, vel
|
|
forces = np.zeros((N_particles, 2))
|
|
|
|
for i in range(N_particles):
|
|
delta = pos - pos[i]
|
|
dist_sq = np.sum(delta**2, axis=1)
|
|
dist = np.sqrt(dist_sq) + 0.001
|
|
|
|
# Interaction mask: only particles within R_max see each other
|
|
mask = (dist > 0) & (dist < R_max)
|
|
|
|
r_sq = dist_sq[mask]
|
|
d_vec = delta[mask] / dist[mask, np.newaxis]
|
|
|
|
# EQUAL POWER CALCULATION (Both are 1/r^2)
|
|
# Attraction represents cavitation (Bjerknes)
|
|
f_attr = k_attr / (r_sq + soft_attr)
|
|
|
|
# Repulsion represents orbital dipoles (Coulomb)
|
|
# Higher k_repel makes the "atom" larger
|
|
f_repel = -k_repel / (r_sq + soft_repel)
|
|
|
|
# Combine forces into a single vector
|
|
forces[i] = np.sum(d_vec * (f_attr + f_repel)[:, np.newaxis], axis=0)
|
|
|
|
# ADDING THE "PROCESS": Tiny random fluctuations like in real superfluid
|
|
random_vibration = (np.random.rand(N_particles, 2) - 0.5) * 0.2
|
|
|
|
# Physics step: momentum + forces + heat
|
|
vel = vel * damping + forces * dt + random_vibration
|
|
|
|
# Preventing "Hyper-speed" errors
|
|
v_speed = np.linalg.norm(vel, axis=1, keepdims=True)
|
|
vel = np.where(v_speed > 14.0, vel * (14.0 / v_speed), vel)
|
|
|
|
pos += vel * dt
|
|
|
|
# BOUNCE OFF WALLS
|
|
for d in range(2):
|
|
out_min, out_max = pos[:, d] < 0, pos[:, d] > box_size
|
|
if np.any(out_min): pos[out_min, d], vel[out_min, d] = 0, -vel[out_min, d] * 0.5
|
|
if np.any(out_max): pos[out_max, d], vel[out_max, d] = box_size, -vel[out_max, d] * 0.5
|
|
|
|
scatter.set_offsets(pos)
|
|
return scatter,
|
|
|
|
plt.close()
|
|
anim = FuncAnimation(fig, update, frames=steps, interval=30, blit=True)
|
|
HTML(anim.to_jshtml())
|