"use client"; import { useEffect, useRef, useState } from "react"; import Katex from "@/components/Katex"; export default function DiagnosticsPage() { const canvasRef = useRef(null); // Simulation Settings const [witnessIntensity, setWitnessIntensity] = useState(5.0); // Coupling strength K const [couplingDistance, setCouplingDistance] = useState(65); // Interaction radius const [systemSpeed, setSystemSpeed] = useState(1.5); // Time step dt const [coherenceIndex, setCoherenceIndex] = useState(0.0); // Order parameter r const [activeNodesCount, setActiveNodesCount] = useState(0); // Keep setting values in refs for the animation loop to prevent dependency lag const settingsRef = useRef({ witnessIntensity, couplingDistance, systemSpeed }); useEffect(() => { settingsRef.current = { witnessIntensity, couplingDistance, systemSpeed }; }, [witnessIntensity, couplingDistance, systemSpeed]); useEffect(() => { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; let animationFrameId; let width = canvas.width = canvas.offsetWidth; let height = canvas.height = canvas.offsetHeight; // Handle Resize const handleResize = () => { if (!canvas) return; width = canvas.width = canvas.offsetWidth; height = canvas.height = canvas.offsetHeight; }; window.addEventListener("resize", handleResize); // Grid Configuration const cols = Math.floor(width / 35); const rows = Math.floor(height / 35); const nodes = []; // Initialize Nodes in a grid with random phases for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { const x = (c + 0.5) * (width / cols); const y = (r + 0.5) * (height / rows); nodes.push({ x, y, row: r, col: c, phase: Math.random() * Math.PI * 2, // theta in [0, 2pi] naturalFreq: 0.05 + Math.random() * 0.05, // omega_i pulseRadius: 0, isTriggered: false, }); } } setActiveNodesCount(nodes.length); // Simulation Loop const draw = () => { ctx.fillStyle = "rgba(3, 2, 6, 0.25)"; // Trail effect for waves ctx.fillRect(0, 0, width, height); // Draw Grid Background lines subtly ctx.strokeStyle = "rgba(255, 255, 255, 0.015)"; ctx.lineWidth = 1; for (let c = 0; c <= cols; c++) { const x = c * (width / cols); ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, height); ctx.stroke(); } for (let r = 0; r <= rows; r++) { const y = r * (height / rows); ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(width, y); ctx.stroke(); } const { witnessIntensity: K, couplingDistance: distThresh, systemSpeed: speed } = settingsRef.current; const dt = 0.05 * speed; // Update phases using Kuramoto-like coupling model: // d(theta_i)/dt = omega_i + (K / N) * sum( sin(theta_j - theta_i) ) const newPhases = new Array(nodes.length); let sumSinOrder = 0; let sumCosOrder = 0; for (let i = 0; i < nodes.length; i++) { const nodeA = nodes[i]; let couplingSum = 0; let neighborsCount = 0; for (let j = 0; j < nodes.length; j++) { if (i === j) continue; const nodeB = nodes[j]; const dx = nodeB.x - nodeA.x; const dy = nodeB.y - nodeA.y; const distSq = dx * dx + dy * dy; if (distSq < distThresh * distThresh) { couplingSum += Math.sin(nodeB.phase - nodeA.phase); neighborsCount++; } } // Apply coupling integration const couplingFactor = neighborsCount > 0 ? (K * 0.1) / neighborsCount : 0; newPhases[i] = nodeA.phase + (nodeA.naturalFreq + couplingFactor * couplingSum) * dt; // Keep phase in [0, 2pi] newPhases[i] = (newPhases[i] + Math.PI * 2) % (Math.PI * 2); // Accumulate order parameter coordinates (r * e^{i*psi}) sumCosOrder += Math.cos(nodeA.phase); sumSinOrder += Math.sin(nodeA.phase); } // Calculate Kuramoto Order Parameter (Coherence Factor r) const r = Math.sqrt(Math.pow(sumCosOrder / nodes.length, 2) + Math.pow(sumSinOrder / nodes.length, 2)); setCoherenceIndex(r); // Update phases and draw nodes and bonds for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; node.phase = newPhases[i]; // Wave propagation pulses if (node.isTriggered) { node.pulseRadius += 6 * speed; ctx.beginPath(); ctx.arc(node.x, node.y, node.pulseRadius, 0, Math.PI * 2); ctx.strokeStyle = `rgba(6, 182, 212, ${Math.max(0, 1 - node.pulseRadius / 150) * 0.4})`; ctx.lineWidth = 1.5; ctx.stroke(); // Phase lock nodes inside the propagating pulse ring for (let j = 0; j < nodes.length; j++) { if (i === j) continue; const other = nodes[j]; const dx = other.x - node.x; const dy = other.y - node.y; const distance = Math.sqrt(dx * dx + dy * dy); // If inside the front expansion ring if (distance < node.pulseRadius && distance > node.pulseRadius - 12) { // Pull other node's phase towards the anchor phase other.phase = (other.phase * 0.85 + node.phase * 0.15) % (Math.PI * 2); } } if (node.pulseRadius > 180) { node.isTriggered = false; node.pulseRadius = 0; } } // Draw bonds between synchronized neighbors for (let j = i + 1; j < nodes.length; j++) { const other = nodes[j]; const dx = other.x - node.x; const dy = other.y - node.y; const distSq = dx * dx + dy * dy; if (distSq < distThresh * distThresh) { const phaseDiff = Math.abs(Math.sin(other.phase - node.phase)); // Only draw bond lines for synchronized nodes if (phaseDiff < 0.25) { ctx.beginPath(); ctx.moveTo(node.x, node.y); ctx.lineTo(other.x, other.y); // Cyan for highly coupled, violet when order parameter is lower const opacity = (1 - phaseDiff * 4) * 0.12 * (r + 0.1); ctx.strokeStyle = r > 0.85 ? `rgba(6, 182, 212, ${opacity * 1.5})` : `rgba(139, 92, 246, ${opacity})`; ctx.lineWidth = 0.8; ctx.stroke(); } } } // Calculate node color based on phase // Violet: HSL 270, Cyan: HSL 190 const hue = 270 - (node.phase / (Math.PI * 2)) * 80; const color = `hsla(${hue}, 80%, 65%, ${0.5 + Math.sin(node.phase) * 0.2})`; // Draw Node ctx.beginPath(); ctx.arc(node.x, node.y, 3.5, 0, Math.PI * 2); ctx.fillStyle = color; ctx.shadowBlur = r > 0.8 ? 8 : 0; ctx.shadowColor = r > 0.8 ? "#06b6d4" : "#8b5cf6"; ctx.fill(); ctx.shadowBlur = 0; // reset } animationFrameId = requestAnimationFrame(draw); }; draw(); // Click handler mapping to trigger local phase lock waves const handleCanvasClick = (e) => { const rect = canvas.getBoundingClientRect(); let clientX, clientY; if (e.touches && e.touches.length > 0) { clientX = e.touches[0].clientX; clientY = e.touches[0].clientY; } else { clientX = e.clientX; clientY = e.clientY; } const clickX = clientX - rect.left; const clickY = clientY - rect.top; // Find closest node let closestNode = null; let minDist = Infinity; for (const node of nodes) { const dx = node.x - clickX; const dy = node.y - clickY; const dist = dx * dx + dy * dy; if (dist < minDist) { minDist = dist; closestNode = node; } } // Trigger wave if (closestNode) { closestNode.isTriggered = true; closestNode.pulseRadius = 0; closestNode.phase = 0; // Phase lock trigger seed } }; canvas.addEventListener("mousedown", handleCanvasClick); canvas.addEventListener("touchstart", handleCanvasClick, { passive: true }); // Bind event controllers to window object for access by React buttons const handleScramble = () => { for (const node of nodes) { node.phase = Math.random() * Math.PI * 2; node.isTriggered = false; } }; const handleGlobalPhaseLock = () => { const centerNode = nodes[Math.floor(nodes.length / 2)]; if (centerNode) { centerNode.isTriggered = true; centerNode.pulseRadius = 0; centerNode.phase = Math.PI; } // Slightly bias all nodes to center phase for (const node of nodes) { node.phase = (node.phase * 0.4 + Math.PI * 0.6) % (Math.PI * 2); } }; window.handleScramble = handleScramble; window.handleGlobalPhaseLock = handleGlobalPhaseLock; return () => { cancelAnimationFrame(animationFrameId); window.removeEventListener("resize", handleResize); if (canvas) { canvas.removeEventListener("mousedown", handleCanvasClick); } delete window.handleScramble; delete window.handleGlobalPhaseLock; }; }, []); return (
Observe emergent self-referential phase waves inside the Intellecton lattice grid. Adjust coupling variables to observe collective phase-locking.
The phase-coupling factor between neighboring Intellecton nodes. Higher values force faster global synchronization.
Determines the spatial neighborhood range for self-referential coupling waves.
The overall integration time step velocity for self-referential oscillator ticks.
This lattice represents distributed agents governed by the self-referential witness function