AUTOMATED ZERO-DRIFT TRACKER — Secant Method Optimization for κ*

INSTALL MONAD SERIES 11.1 — PURE PHYSICS SOLVER FIRST - THEN RUN AUTOMATED ZERO-DRIFT TRACKER #!/usr/bin/env python3 """ ================================================================================ MONAD SERIES 11.1 — PURE PHYSICS SOLVER (CLARITY + SAFE REGULARIZATION) ================================================================================ This is a light, non-physical-change refactor of the original solver. Purpose: - Make the primitive / constitutive distinction explicit: - Psi_field: the primitive evolved field (Pxy) - Psi_const: the constitutive reconstruction Ψ(Ik(Π)) - Use safer sqrt-based regularizers for sign-like smoothing. - Improve finite-check messages for easier debugging. - Preserve all original PDEs, constitutive functional forms and dynamics. - Keep Π as the sole prognostic state (Version A behavior). - Add clarifying docstrings/comments where helpful. Run: python monad_series11.1_purephysics.py --steps 1000 --N 16 --kappa 0.3 ================================================================================ """ import sys import argparse import numpy as np import time # ============================================================================== # FILTER COLAB -f ARGUMENT # ============================================================================== def parse_colab_args(): """Parse arguments, filtering Colab's -f flag.""" raw_args = sys.argv[1:] filtered = [] skip = False for i, arg in enumerate(raw_args): if skip: skip = False continue if arg == '-f' and i + 1 < len(raw_args): skip = True continue filtered.append(arg) parser = argparse.ArgumentParser(description='Monad Series 11.1 Pure Physics Solver') parser.add_argument('--steps', type=int, default=25000, help='Steps per run') parser.add_argument('--N', type=int, default=16, help='Grid size (16 or 32 for CPU)') parser.add_argument('--dt', type=float, default=5e-6, help='Timestep') parser.add_argument('--c', type=float, default=0.5, help='Wave speed') parser.add_argument('--kappa', type=float, default=0.3, help='Coupling parameter') parser.add_argument('--ko_sigma', type=float, default=0.045, help='KO dissipation') parser.add_argument('--amplitude', type=float, default=2.5, help='Initial amplitude') parser.add_argument('--diag', type=int, default=1000, help='Diagnostic interval') parser.add_argument('--no_cfl_check', action='store_true', default=False, help='Skip CFL warning') return parser.parse_args(filtered) # ============================================================================== # CPU DIFF-OPERATOR KERNELS (VECTORIZED NumPy) # ============================================================================== def cpu_grad_2d(F, dx): """Compute 2D gradient using central differences (vectorized).""" dx = float(dx) gx = (np.roll(F, -1, axis=0) - np.roll(F, 1, axis=0)) / (2.0 * dx) gy = (np.roll(F, -1, axis=1) - np.roll(F, 1, axis=1)) / (2.0 * dx) return gx, gy def cpu_lap_2d(F, dx): """Compute 2D Laplacian (vectorized).""" dx2 = float(dx) * float(dx) lap = (np.roll(F, -1, axis=0) + np.roll(F, 1, axis=0) + np.roll(F, -1, axis=1) + np.roll(F, 1, axis=1) - 4.0 * F) / dx2 return lap def cpu_ko_2d(F, dx, sigma): """4th-order Kreiss-Oliger dissipation (vectorized).""" sigma = float(sigma) dx4 = float(dx)**4 d4x = (np.roll(F, -2, axis=0) - 4.0*np.roll(F, -1, axis=0) + 6.0*F - 4.0*np.roll(F, 1, axis=0) + np.roll(F, 2, axis=0)) d4y = (np.roll(F, -2, axis=1) - 4.0*np.roll(F, -1, axis=1) + 6.0*F - 4.0*np.roll(F, 1, axis=1) + np.roll(F, 2, axis=1)) return -(sigma / 16.0) * (d4x + d4y) / dx4 # ============================================================================== # INVARIANT DECOMPOSITION OF Π (EXACTLY INVERTIBLE) # ============================================================================== def decompose_pi(Pxx, Pxy, Pyy): """Decompose symmetric tensor Π into invariant stress modes.""" Lam = Pxx + Pyy S = Pxx - Pyy Psi = Pxy return S, Psi, Lam def reconstruct_pi(S, Psi, Lam): """Reconstruct Π from invariant stress modes (exact inverse).""" Pxx = (Lam + S) / 2.0 Pyy = (Lam - S) / 2.0 Pxy = Psi return Pxx, Pxy, Pyy # ============================================================================== # CONSTITUTIVE EVALUATION FROM INVARIANTS # ============================================================================== # NOTE: This function computes diagnostic/constitutive quantities from Π. # It does NOT alter Π itself. The solver treats Π as primitive. # Return keys: # - Psi_field : the primitive Pxy passed in # - Psi_const : the constitutive reconstruction Ψ(Ik(Π)) # - dPsi_const_dI* : derivatives of Ψ_const wrt invariants (for modulatory terms) # ============================================================================== def evaluate_monad_from_pi(Pxx, Pxy, Pyy, Pi_max=5.9259, anchor=0.0, kappa=0.3, eta=0.2, beta=0.5, gamma=0.2, m2=0.1, alpha=0.4, delta=0.15, eps=1e-15): """ Evaluate ALL FRCMFD quantities from the Monad tensor Π. This returns both the primitive field (Psi_field == Pxy) and the constitutive reconstruction Psi_const = Ψ(Ik). The solver uses Psi_field for evolution and Psi_const for diagnostics / emergent geometry. """ S, Psi_field, Lam = decompose_pi(Pxx, Pxy, Pyy) psi_mag_sq = Psi_field**2 # Invariants I1 = np.abs(S) + np.abs(Lam) I2 = S**2 - psi_mag_sq + Lam**2 I3 = np.abs(S**3) + np.abs(Lam**3) I4 = S**4 - psi_mag_sq**2 + Lam**4 Ih1 = np.maximum(I1 / Pi_max, eps) Ih2 = I2 / (Pi_max**2) Ih3 = I3 / (Pi_max**3) Ih4 = I4 / (Pi_max**4) sqrt_Ih1 = np.sqrt(Ih1) # Constitutive functional form (unchanged): expf = np.exp(-0.5 * (Ih2**2 + Ih3**3 + Ih4**4)) lf = (1.0 / sqrt_Ih1) - 1.0 Psi_const = (1.0 / Pi_max) * lf * expf + anchor # Derivatives of Psi_const wrt invariants (chain-rule components) I1_safe = np.maximum(I1, eps) dPsi_dI1 = -1.0 / (2.0 * Pi_max * I1_safe * sqrt_Ih1) * expf base = (1.0 / Pi_max) * lf * expf dPsi_dI2 = -Ih2 / (Pi_max**2) * base dPsi_dI3 = -1.5 * (Ih3**2) / (Pi_max**3) * base dPsi_dI4 = -2.0 * (Ih4**3) / (Pi_max**4) * base # Safer smooth sign approximations (use sqrt-based regularizer) eps2 = 1e-10 s_smooth = S / np.sqrt(S**2 + eps2) lam_smooth = Lam / np.sqrt(Lam**2 + eps2) # Compose modulatory multipliers using derivatives of Psi_const M_T = dPsi_dI1 * s_smooth + dPsi_dI2 * 2.0 * S + dPsi_dI3 * 3.0 * S * np.abs(S) + dPsi_dI4 * 4.0 * S**3 M_T = np.clip(M_T, -1e6, 1e6) M_C = dPsi_dI1 * lam_smooth + dPsi_dI2 * 2.0 * Lam + dPsi_dI3 * 3.0 * Lam * np.abs(Lam) + dPsi_dI4 * 4.0 * Lam**3 M_C = np.clip(M_C, -1e6, 1e6) M_R = np.clip(dPsi_dI2 * 2.0, -1e6, 1e6) # Constitutive diagnostic / drift measure (unchanged form) D_drift = np.abs( np.clip(np.log(np.maximum(np.abs(Psi_const - anchor) * Pi_max, eps)), -20, 20) + 0.5 * (np.clip(np.log(np.maximum(Ih1, eps)), -20, 20) + Ih2**2 + Ih3**3 + Ih4**4) ) return { 'S': S, 'Psi_field': Psi_field, 'Psi_const': Psi_const, 'Lam': Lam, 'dPsi_const_dI1': dPsi_dI1, 'dPsi_const_dI2': dPsi_dI2, 'dPsi_const_dI3': dPsi_dI3, 'dPsi_const_dI4': dPsi_dI4, 'M_T': M_T, 'M_C': M_C, 'M_R': M_R, 'D_drift': D_drift } # ============================================================================== # PURE PHYSICS SOLVER — NO DIAGNOSTICS, NO DATA PIPELINE # ============================================================================== class MonadSolver11Pure: """ Series 11.1: Pure physics solver — clarity fixes and safe regularization. KEY PRINCIPLE (Version A): - Π (Pxx, Pxy, Pyy) is the primitive dynamical variable and evolves. - Ψ_const = Ψ(Ik(Π)) is reconstructed diagnostically (emergent geometry). - By default, Ψ_const does NOT feed back into the time evolution. (Constitutive feedback is a well-defined separate extension.) """ def __init__(self, config): self.config = config self.N = int(config['N']) self.dx = float(config['dx']) self.dt = float(config['dt']) self.c2 = float(config.get('c', 0.5)**2) self.kappa = float(config.get('kappa', 0.3)) self.eta = float(config.get('eta', 0.2)) self.beta = float(config.get('beta', 0.5)) self.gamma = float(config.get('gamma', 0.2)) self.m2 = float(config.get('m2', 0.1)) self.alpha = float(config.get('alpha', 0.4)) self.delta = float(config.get('delta', 0.15)) self.Pi_max = float(config.get('Pi_max', 5.9259)) self.ko_sigma = float(config.get('ko_sigma', 0.045)) self.anchor = float(config.get('anchor', 0.0)) self.step = 0 self.time = 0.0 # Fields self.Pxx = None self.Pxy = None self.Pyy = None self.Uxx = None self.Uxy = None self.Uyy = None def init_gaussian(self, amplitude=2.5, width=4.0): """Initialize the Monad tensor Π with Gaussian profiles.""" N, dx = self.N, self.dx half_width = (N * dx) / 2.0 x = np.linspace(-half_width, half_width, N, endpoint=False) y = np.linspace(-half_width, half_width, N, endpoint=False) X, Y = np.meshgrid(x, y) R2 = X**2 + Y**2 amplitude = float(amplitude) width = float(width) self.Pxx = amplitude * np.exp(-R2 / (2.0 * width**2)) self.Pxy = 0.5 * amplitude * np.exp(-R2 / (2.0 * (width * 1.2)**2)) self.Pyy = 0.7 * amplitude * np.exp(-R2 / (2.0 * (width * 0.8)**2)) self.Uxx = np.zeros_like(self.Pxx) self.Uxy = np.zeros_like(self.Pxy) self.Uyy = np.zeros_like(self.Pyy) # Small perturbation np.random.seed(42) noise_scale = 1e-8 * amplitude self.Pxx += np.random.normal(0, noise_scale, self.Pxx.shape) self.Pxy += np.random.normal(0, noise_scale, self.Pxy.shape) self.Pyy += np.random.normal(0, noise_scale, self.Pyy.shape) return self def _finite_check(self): """Check for NaNs/Infs and report which field fails for easier debugging.""" if self.Pxx is None or self.Pxy is None or self.Pyy is None: raise RuntimeError("Fields are not initialized (Pxx/Pxy/Pyy are None)") if not np.all(np.isfinite(self.Pxx)): raise RuntimeError("NaN/Inf detected in Pxx") if not np.all(np.isfinite(self.Pxy)): raise RuntimeError("NaN/Inf detected in Pxy") if not np.all(np.isfinite(self.Pyy)): raise RuntimeError("NaN/Inf detected in Pyy") if not np.all(np.isfinite(self.Uxx)): raise RuntimeError("NaN/Inf detected in Uxx") if not np.all(np.isfinite(self.Uxy)): raise RuntimeError("NaN/Inf detected in Uxy") if not np.all(np.isfinite(self.Uyy)): raise RuntimeError("NaN/Inf detected in Uyy") def derivatives(self): """Compute time derivatives of the ONE Monad tensor Π. IMPORTANT: This uses the primitive field (Psi_field == Pxy) for dynamics. Constituive quantities (Psi_const) are used only where modulatory multipliers computed from derivatives of Psi_const are intentionally included. """ dx = self.dx # Diagnostics from current state (returns both primitive and constitutive quantities) results = evaluate_monad_from_pi( self.Pxx, self.Pxy, self.Pyy, self.Pi_max, self.anchor, self.kappa, self.eta, self.beta, self.gamma, self.m2, self.alpha, self.delta ) S = results['S'] Psi_field = results['Psi_field'] # primitive Pxy Lam = results['Lam'] M_T = results['M_T'] M_C = results['M_C'] M_R = results['M_R'] # Laplacians lapPxx = cpu_lap_2d(self.Pxx, dx) lapPxy = cpu_lap_2d(self.Pxy, dx) lapPyy = cpu_lap_2d(self.Pyy, dx) # Gradients of stress modes (use primitive field gradients for dynamics) gSx, gSy = cpu_grad_2d(S, dx) gLx, gLy = cpu_grad_2d(Lam, dx) gPx, gPy = cpu_grad_2d(Psi_field, dx) # primitive gradients gS2 = gSx**2 + gSy**2 gL2 = gLx**2 + gLy**2 gP2 = gPx**2 + gPy**2 ps_field = Psi_field**2 ls = Lam**2 # Kinematic dPxx = self.Uxx dPxy = self.Uxy dPyy = self.Uyy # Momentum (force from action) - uses primitive psi_field where originally designed dUxx = (self.c2 * lapPxx - self.beta * self.Pxx - self.gamma * self.Pxx * self.Pxx**2 - self.kappa * ps_field - self.eta * self.Pxx * ls + self.kappa * self.Pxx * M_T * gS2) dUxy = (self.c2 * lapPxy - self.m2 * self.Pxy - 2.0 * self.kappa * self.Pxx * self.Pxy - self.eta * self.Pxy * ls - self.kappa * self.Pxy * M_R * gP2) dUyy = (self.c2 * lapPyy - self.alpha * self.Pyy - self.delta * self.Pyy * self.Pyy**2 - self.kappa * self.Pxx * self.Pyy - self.eta * ps_field * self.Pyy + self.kappa * self.Pyy * M_C * gL2) # KO dissipation if self.ko_sigma > 0: dUxx += cpu_ko_2d(self.Uxx, dx, self.ko_sigma) dUxy += cpu_ko_2d(self.Uxy, dx, self.ko_sigma) dUyy += cpu_ko_2d(self.Uyy, dx, self.ko_sigma) return dPxx, dPxy, dPyy, dUxx, dUxy, dUyy def rk3_step(self): """SSP-RK3 timestep.""" dt = self.dt Pxx_n = self.Pxx.copy() Pxy_n = self.Pxy.copy() Pyy_n = self.Pyy.copy() Uxx_n = self.Uxx.copy() Uxy_n = self.Uxy.copy() Uyy_n = self.Uyy.copy() # Stage 1 dPxx1, dPxy1, dPyy1, dUxx1, dUxy1, dUyy1 = self.derivatives() self.Pxx = Pxx_n + dt*dPxx1 self.Pxy = Pxy_n + dt*dPxy1 self.Pyy = Pyy_n + dt*dPyy1 self.Uxx = Uxx_n + dt*dUxx1 self.Uxy = Uxy_n + dt*dUxy1 self.Uyy = Uyy_n + dt*dUyy1 self._finite_check() # Stage 2 dPxx2, dPxy2, dPyy2, dUxx2, dUxy2, dUyy2 = self.derivatives() self.Pxx = 0.75*Pxx_n + 0.25*self.Pxx + 0.25*dt*dPxx2 self.Pxy = 0.75*Pxy_n + 0.25*self.Pxy + 0.25*dt*dPxy2 self.Pyy = 0.75*Pyy_n + 0.25*self.Pyy + 0.25*dt*dPyy2 self.Uxx = 0.75*Uxx_n + 0.25*self.Uxx + 0.25*dt*dUxx2 self.Uxy = 0.75*Uxy_n + 0.25*self.Uxy + 0.25*dt*dUxy2 self.Uyy = 0.75*Uyy_n + 0.25*self.Uyy + 0.25*dt*dUyy2 self._finite_check() # Stage 3 dPxx3, dPxy3, dPyy3, dUxx3, dUxy3, dUyy3 = self.derivatives() self.Pxx = (1.0/3.0)*Pxx_n + (2.0/3.0)*self.Pxx + (2.0/3.0)*dt*dPxx3 self.Pxy = (1.0/3.0)*Pxy_n + (2.0/3.0)*self.Pxy + (2.0/3.0)*dt*dPxy3 self.Pyy = (1.0/3.0)*Pyy_n + (2.0/3.0)*self.Pyy + (2.0/3.0)*dt*dPyy3 self.Uxx = (1.0/3.0)*Uxx_n + (2.0/3.0)*self.Uxx + (2.0/3.0)*dt*dUxx3 self.Uxy = (1.0/3.0)*Uxy_n + (2.0/3.0)*self.Uxy + (2.0/3.0)*dt*dUxy3 self.Uyy = (1.0/3.0)*Uyy_n + (2.0/3.0)*self.Uyy + (2.0/3.0)*dt*dUyy3 self._finite_check() self.step += 1 self.time += dt def hamiltonian(self): """Compute Hamiltonian from the Monad tensor Π. NOTE: For emergent metric / potential diagnostics we use Psi_const (the constitutive reconstruction). This makes the Hamiltonian reflect the emergent geometry produced by Ψ_const(Ik). """ dx = self.dx results = evaluate_monad_from_pi( self.Pxx, self.Pxy, self.Pyy, self.Pi_max, self.anchor, self.kappa, self.eta, self.beta, self.gamma, self.m2, self.alpha, self.delta ) S = results['S'] Psi_const = results['Psi_const'] # emergent constitutive reconstruction Lam = results['Lam'] kin = 0.5 * (self.Uxx**2 + self.Uxy**2 + self.Uyy**2) gPxx_x, gPxx_y = cpu_grad_2d(self.Pxx, dx) gPxy_x, gPxy_y = cpu_grad_2d(self.Pxy, dx) gPyy_x, gPyy_y = cpu_grad_2d(self.Pyy, dx) grad = 0.5 * self.c2 * (gPxx_x**2 + gPxx_y**2 + gPxy_x**2 + gPxy_y**2 + gPyy_x**2 + gPyy_y**2) ps = Psi_const**2 pot = (0.5 * self.beta * S**2 + 0.25 * self.gamma * S**4 + 0.5 * self.m2 * ps + 0.5 * self.alpha * Lam**2 + 0.25 * self.delta * Lam**4 + self.kappa * S * ps + self.eta * ps * Lam) return float(np.sum(kin + grad + pot) * dx**2) def run(self, steps, diag_interval=1000): """Run simulation for specified steps.""" print(f"\n{'='*60}") print(f"SERIES 11.1 — PURE PHYSICS SOLVER (CLARITY + SAFE REGULARIZATION)") print(f"{'='*60}") print(f"Grid: {self.N}×{self.N}, dt={self.dt:.6f}, κ={self.kappa:.3f}") print(f"Diagnostics: every {diag_interval} steps") print(f"{'-'*60}") start = time.time() H0 = self.hamiltonian() print(f"Step {0:6d} | H = {H0:.8e}") for step in range(1, steps+1): self.rk3_step() if step % diag_interval == 0: H = self.hamiltonian() dr = abs(H-H0)/max(abs(H0), 1e-30) print(f"Step {step:6d} | H={H:.8e} | ΔH/H={dr:.4e}") if np.isnan(H) or dr > 0.05: print(f"❌ INSTABILITY at step {step}") break elapsed = time.time() - start try: Hf = self.hamiltonian() except Exception: # If hamiltonian computation fails, fallback to last known H (H0) to avoid crash Hf = H0 dr = abs(Hf - H0) / max(abs(H0), 1e-30) print(f"{'-'*60}") print(f"Completed {step} steps in {elapsed:.2f}s ({step/elapsed:.1f} steps/sec)") print(f"{'='*60}") return { 'steps': step, 'H0': float(H0), 'H_final': float(Hf), 'drift_rel': float(dr), 'elapsed': float(elapsed) } # ============================================================================== # MAIN # ============================================================================== if __name__ == "__main__": args = parse_colab_args() print("\n" + "="*80) print("🚀 SERIES 11.1 — PURE PHYSICS SOLVER (CLARITY RELEASE)") print("="*80) print(f"Steps: {args.steps:,}") print(f"Grid: {args.N}×{args.N}") print(f"dt: {args.dt}") print(f"κ: {args.kappa}") print("="*80) print("✅ PURE PHYSICS — No diagnostics, no I/O, no data pipeline") print("✅ ONE Monad tensor Π evolves (3 components: Pxx, Pxy, Pyy)") print("✅ THREE stress modes derived INVARIANTLY from Π:") print(" - Compression (Λ) = trace(Π) = Pxx + Pyy") print(" - Tension (S) = deviatoric = Pxx - Pyy") print(" - Torsion (Ψ) = off-diagonal = Pxy") print("="*80) config = { 'N': args.N, 'dx': 0.4 * (64.0 / args.N), 'dt': args.dt, 'c': args.c, 'kappa': args.kappa, 'eta': 0.2, 'beta': 0.5, 'gamma': 0.2, 'm2': 0.1, 'alpha': 0.4, 'delta': 0.15, 'Pi_max': 5.9259, 'ko_sigma': args.ko_sigma, 'anchor': 0.0, 'no_cfl_check': args.no_cfl_check } # CFL Check c = float(config.get('c', 0.5)) dx = float(config['dx']) dt = float(config['dt']) cfl = c * dt / dx if cfl > 0.5 and not config.get('no_cfl_check', False): print(f" ⚠️ CFL ~ {cfl:.3f} > 0.5 — dt may be too large for stability") print(f" CFL = {cfl:.4f}") solver = MonadSolver11Pure(config) solver.init_gaussian(amplitude=args.amplitude) results = solver.run(steps=args.steps, diag_interval=args.diag) print("\n" + "="*80) print("📊 SERIES 11.1 PURE PHYSICS RESULTS") print("="*80) print(f"Steps completed: {results['steps']:,}/{args.steps:,}") print(f"Initial H: {results['H0']:.8e}") print(f"Final H: {results['H_final']:.8e}") print(f"Drift: {results['drift_rel']:.4e} ({results['drift_rel']*100:.4f}%)") print(f"Time: {results['elapsed']:.2f}s") print(f"Speed: {results['steps']/results['elapsed']:.1f} steps/sec") print("="*80) #!/usr/bin/env python3 """ AUTOMATED ZERO-DRIFT TRACKER — Secant Method Optimization for κ* Finds and verifies the perfect energy-conserving coupling coefficient using: - Run A: κ = 0.58 (lower bound) - Run B: κ = 0.61 (upper bound) - Secant root-finding for rapid convergence - Run C: κ = κ*_estimate (verification) - Polynomial refinement with all 3 points - Run D: κ = κ*_refined (200k decisive test) - Fully automated — no manual intervention required - Saves complete summary to JSON + TAR BASELINE ANCHOR: monad_series11.1_purephysics.py (UNCHANGED) """ import sys import json import time import numpy as np from pathlib import Path from datetime import datetime import tarfile # ============================================================================== # BASELINE ANCHOR - EXPLICIT PATH IMPORT (BYPASSES ALL MODULE CACHE ISSUES) # ============================================================================== import os import importlib.util file_path = "/content/monad_series11.1_purephysics.py" if not os.path.exists(file_path): # Try alternative names alt = "/content/monad_series11_pure.py" if os.path.exists(alt): file_path = alt else: raise FileNotFoundError("❌ Could not find monad_series11.1_purephysics.py") print(f"✅ Loading solver from: {file_path}") spec = importlib.util.spec_from_file_location("solver_module", file_path) solver_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(solver_module) MonadSolver11Pure = solver_module.MonadSolver11Pure evaluate_monad_from_pi = solver_module.evaluate_monad_from_pi cpu_grad_2d = solver_module.cpu_grad_2d print("✅ Solver imported successfully") # ============================================================================== # CONFIGURATION # ============================================================================== BASELINE_CONFIG = { 'N': 64, 'dt': 1.25e-6, 'ko_sigma': 0.045, 'amplitude': 2.5, 'seed': 12345, 'diag_interval': 5000, } OUTDIR = Path("./zero_drift_bracketing") OUTDIR.mkdir(parents=True, exist_ok=True) # Known bracket from previous runs KAPPA_LOW = 0.55 KAPPA_HIGH = 0.65 # ============================================================================== # ENERGY COMPONENT DECOMPOSITION # ============================================================================== def compute_energy_components(solver): """Decompose Hamiltonian into components.""" dx = solver.dx results = evaluate_monad_from_pi( solver.Pxx, solver.Pxy, solver.Pyy, solver.Pi_max, solver.anchor, solver.kappa, solver.eta, solver.beta, solver.gamma, solver.m2, solver.alpha, solver.delta ) S = results.get('S', solver.Pxx - solver.Pyy) Psi_const = results.get('Psi_const', results.get('Psi_field', solver.Pxy)) Lam = results.get('Lam', solver.Pxx + solver.Pyy) # KINETIC H_kin = 0.5 * (solver.Uxx**2 + solver.Uxy**2 + solver.Uyy**2) H_kin_s = float(np.sum(H_kin) * dx**2) # GRADIENT gPxx_x, gPxx_y = cpu_grad_2d(solver.Pxx, dx) gPxy_x, gPxy_y = cpu_grad_2d(solver.Pxy, dx) gPyy_x, gPyy_y = cpu_grad_2d(solver.Pyy, dx) H_grad = 0.5 * solver.c2 * (gPxx_x**2 + gPxx_y**2 + gPxy_x**2 + gPxy_y**2 + gPyy_x**2 + gPyy_y**2) H_grad_s = float(np.sum(H_grad) * dx**2) # POTENTIAL ps = Psi_const**2 H_pot = (0.5 * solver.beta * S**2 + 0.25 * solver.gamma * S**4 + 0.5 * solver.m2 * ps + 0.5 * solver.alpha * Lam**2 + 0.25 * solver.delta * Lam**4 + solver.kappa * S * ps + solver.eta * ps * Lam) H_pot_s = float(np.sum(H_pot) * dx**2) H_total_s = H_kin_s + H_grad_s + H_pot_s return { 'H_total': H_total_s, 'H_kinetic': H_kin_s, 'H_gradient': H_grad_s, 'H_potential': H_pot_s, } # ============================================================================== # SINGLE RUN ENGINE # ============================================================================== def run_single(kappa, steps, label, outdir=OUTDIR): """Run a single simulation at given kappa for given steps.""" config = BASELINE_CONFIG.copy() diag_interval = min(config['diag_interval'], steps // 10) solver_config = { 'N': config['N'], 'dx': 0.4 * (64.0 / config['N']), 'dt': config['dt'], 'c': 0.5, 'kappa': kappa, 'eta': 0.2, 'beta': 0.5, 'gamma': 0.2, 'm2': 0.1, 'alpha': 0.4, 'delta': 0.15, 'Pi_max': 5.9259, 'ko_sigma': config['ko_sigma'], 'anchor': 0.0, 'no_cfl_check': True } print(f"\n{'='*60}") print(f"⚡ RUN: {label}") print(f" κ = {kappa:.5f} | Steps = {steps} | dt = {config['dt']:.2e}") print(f"{'='*60}") solver = MonadSolver11Pure(solver_config) solver.init_gaussian(amplitude=config['amplitude']) history = [] H0 = compute_energy_components(solver) history.append({'step': 0, **H0}) print(f"Step 0: H_total={H0['H_total']:.8e}") for step in range(1, steps + 1): solver.rk3_step() if step % diag_interval == 0 or step == steps: H = compute_energy_components(solver) history.append({'step': step, **H}) if step % (diag_interval * 5) == 0 or step == steps: dr = (H['H_total'] - H0['H_total']) / max(abs(H0['H_total']), 1e-30) print(f" Step {step:6d}: H={H['H_total']:.8e} | Drift={dr*100:+.6f}%") dH = history[-1]['H_total'] - history[0]['H_total'] rel_drift = dH / max(abs(history[0]['H_total']), 1e-30) # Save data timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S") data_file = outdir / f"{label}_{timestamp}.json" with open(data_file, 'w') as f: json.dump(history, f, indent=2, default=float) print(f" Completed {steps} steps") print(f" ΔH = {dH:+.6e} ({rel_drift*100:+.6f}%)") print(f" Data saved to: {data_file}") return dH, history, rel_drift # ============================================================================== # MAIN AUTOMATED BRACKETING ENGINE # ============================================================================== def main(): print("="*80) print("🎯 ZERO-DRIFT AUTOMATED BRACKETING ENGINE") print("="*80) print(f"Baseline bracket: κ ∈ [{KAPPA_LOW}, {KAPPA_HIGH}]") print("Method: Secant root-finding + polynomial refinement") print("Sequence: Run A → Run B → Secant → Run C → Refine → Run D") print("="*80) results_db = [] # ====================================================================== # STEP 1: Run A — Lower bound (κ = 0.58) # ====================================================================== print("\n" + "="*80) print("STEP 1: Run A — Lower Bound (κ = 0.58)") print("="*80) k_A = 0.58 dH_A, hist_A, rel_A = run_single(k_A, 50000, "Run_A_LowerBound") results_db.append({ 'label': 'Run A (Lower Bound)', 'kappa': k_A, 'steps': 50000, 'dH': dH_A, 'rel_drift': rel_A, 'drift_pct': rel_A * 100 }) # ====================================================================== # STEP 2: Run B — Upper bound (κ = 0.61) # ====================================================================== print("\n" + "="*80) print("STEP 2: Run B — Upper Bound (κ = 0.61)") print("="*80) k_B = 0.61 dH_B, hist_B, rel_B = run_single(k_B, 50000, "Run_B_UpperBound") results_db.append({ 'label': 'Run B (Upper Bound)', 'kappa': k_B, 'steps': 50000, 'dH': dH_B, 'rel_drift': rel_B, 'drift_pct': rel_B * 100 }) # ====================================================================== # STEP 3: Secant method — Estimate κ* # ====================================================================== print("\n" + "="*80) print("STEP 3: Secant Root-Finding") print("="*80) # Check sign change if dH_A * dH_B >= 0: print(f"⚠️ WARNING: No sign change between κ={k_A} (ΔH={dH_A:+.6e}) and κ={k_B} (ΔH={dH_B:+.6e})") print(" Proceeding with secant estimate anyway...") # Secant method: k_C = k_A - dH_A * (k_B - k_A) / (dH_B - dH_A) slope = (dH_B - dH_A) / (k_B - k_A) k_secant = k_A - (dH_A / slope) # Clip to safe range k_secant = np.clip(k_secant, KAPPA_LOW, KAPPA_HIGH) print(f" Secant estimate: κ* ≈ {k_secant:.6f}") print(f" Based on: ΔH_A={dH_A:+.6e}, ΔH_B={dH_B:+.6e}") print(f" Slope: {slope:.6e}") # ====================================================================== # STEP 4: Run C — Secant estimate verification # ====================================================================== print("\n" + "="*80) print(f"STEP 4: Run C — Secant Estimate (κ = {k_secant:.6f})") print("="*80) k_C = k_secant dH_C, hist_C, rel_C = run_single(k_C, 50000, f"Run_C_SecantEstimate_{k_C:.6f}") results_db.append({ 'label': f'Run C (Secant Estimate)', 'kappa': k_C, 'steps': 50000, 'dH': dH_C, 'rel_drift': rel_C, 'drift_pct': rel_C * 100 }) # ====================================================================== # STEP 5: Polynomial refinement using all 3 points # ====================================================================== print("\n" + "="*80) print("STEP 5: Polynomial Refinement (3-point linear fit)") print("="*80) k_points = [k_A, k_B, k_C] dH_points = [dH_A, dH_B, dH_C] # Linear fit: dH(k) = a*k + b coeffs = np.polyfit(k_points, dH_points, 1) a, b = coeffs[0], coeffs[1] k_star = -b / a # Clip to safe range k_star = np.clip(k_star, KAPPA_LOW, KAPPA_HIGH) print(f" Linear fit: ΔH = {a:.6e} * κ + {b:.6e}") print(f" κ* (zero-intercept): {k_star:.6f}") # Calculate slope at κ* slope_star = a print(f" Slope at κ*: d(ΔH)/dκ = {slope_star:.6e}") # ====================================================================== # STEP 6: Run D — The Decisive 200k Test # ====================================================================== print("\n" + "="*80) print(f"STEP 6: Run D — Decisive 200k Verification (κ = {k_star:.6f})") print("="*80) dH_D, hist_D, rel_D = run_single(k_star, 200000, f"Run_D_Verification_κ{k_star:.6f}") results_db.append({ 'label': f'Run D (200k Verification)', 'kappa': k_star, 'steps': 200000, 'dH': dH_D, 'rel_drift': rel_D, 'drift_pct': rel_D * 100 }) # ====================================================================== # STEP 7: Summary Report # ====================================================================== print("\n" + "="*80) print("📋 FINAL SUMMARY LEDGER") print("="*80) print(f"{'Run':<25} | {'κ':>12} | {'Steps':>8} | {'ΔH':>14} | {'Drift (%)':>12}") print("-"*80) for r in results_db: print(f"{r['label']:<25} | {r['kappa']:12.6f} | {r['steps']:8d} | {r['dH']:14.6e} | {r['drift_pct']:12.5f}") print("-"*80) print(f"\n🎯 OPTIMAL κ* = {k_star:.6f}") print(f" Decisive 200k test drift: {rel_D*100:.5f}%") print(f" Slope at κ*: d(ΔH)/dκ = {slope_star:.6e}") # Interpret slope if abs(slope_star) > 1.0: print(" 📈 System is HIGHLY sensitive to κ (steep slope)") print(" → Fine-tuned balance point") elif abs(slope_star) > 0.1: print(" 📊 System is MODERATELY sensitive to κ") print(" → Moderate tuning required") else: print(" 📉 System is WEAKLY sensitive to κ (shallow slope)") print(" → Broad neutral basin (robust)") # Determine verdict if abs(rel_D) < 0.0001: verdict = "✅ EXCELLENT: Near-perfect energy conservation at κ*!" elif abs(rel_D) < 0.001: verdict = "✅ GOOD: Very small drift at κ*." elif abs(rel_D) < 0.005: verdict = "⚠️ MODERATE: Significant drift at κ*, but bounded." else: verdict = "⚠️ HIGH: Consider further refinement." print(f" Verdict: {verdict}") # ====================================================================== # STEP 8: Save Summary # ====================================================================== timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S") summary_file = OUTDIR / f"bracketing_summary_{timestamp}.json" summary_data = { 'timestamp': timestamp, 'kappa_star': float(k_star), 'slope_at_kappa_star': float(slope_star), 'runs': results_db, 'verdict': verdict, 'method': 'Secant root-finding + linear refinement', 'baseline_bracket': [KAPPA_LOW, KAPPA_HIGH], 'config': BASELINE_CONFIG } with open(summary_file, 'w') as f: json.dump(summary_data, f, indent=2, default=float) print(f"\n📁 Summary saved to: {summary_file}") # ====================================================================== # STEP 9: Create TAR of results # ====================================================================== print("\n" + "="*80) print("📦 CREATING TAR ARCHIVE") print("="*80) tar_name = f"zero_drift_bracketing_{timestamp}.tar" tar_path = Path("/content") / tar_name with tarfile.open(tar_path, 'w') as tar: for f in OUTDIR.iterdir(): if f.is_file(): tar.add(f, arcname=f.name) print(f" Added: {f.name}") size_kb = tar_path.stat().st_size / 1024 print(f"\n📦 Created: {tar_name} ({size_kb:.1f} KB)") print("\n" + "="*80) print("✅ BRACKETING COMPLETE") print("="*80) print(f"📁 Results saved to: {OUTDIR.resolve()}") print(f"📦 TAR archive: {tar_path}") print("\nTO DOWNLOAD:") print(" 1. Click the folder icon on the left sidebar (Files)") print(" 2. Navigate to /content/") print(f" 3. Right-click on: {tar_name}") print(" 4. Select 'Download'") print("="*80) if __name__ == "__main__": main()

Popular posts from this blog

THE GOLDEN BALLROOM/BUNKER

Conceptual Summary #2: (∂t2​S−c2∇2S+βS3)=σ(x,t)⋅FR​(C[Ψ])

ICE PROUDLY ANNOUNCES NEW “ELITE” TASK FORCE COMMANDER JEREMY DEWITTE