#!/usr/bin/env python3
"""
Bola Physics Test for Quarks

Tests different rotational geometries for quark confinement:

1. ATOMIC MODEL: Single particle on spacetime ball
   - F = ℏ²/(γmr³) [electron on proton]

2. BOLA MODEL: Two particles leashed together
   - F = 2ℏ²s²/(γm*d³) [two quarks spinning around center of mass]

3. TRIPLE BOLA: Three particles (actual proton)
   - F = 3ℏ²s²/(γm*d³) [three quarks around common center]

4. REDUCED MASS MODELS: Account for multi-body physics

The key insight: quarks aren't standing on a ball - they're spinning 
together like a bola, sharing angular momentum.

Author: Andre Heinecke & AI Collaborators
Date: June 2025  
License: CC BY-SA 4.0
"""

import numpy as np
import sys
import math

# ==============================================================================
# PHYSICAL CONSTANTS
# ==============================================================================

HBAR = 1.054e-34           # J⋅s
C = 2.99792458e8           # m/s
E_CHARGE = 1.602176634e-19 # C

# V21 baseline parameters
V21_PARAMS = {
    'hbar': 1.054e-34,
    'quark_mass': 4e-30,        # kg
    'proton_radius': 1.0e-15,   # m  
    'string_tension': 1.4e5,    # N
    'target_force': 8.2e5,      # N
    'quark_spin': 0.5
}

# ==============================================================================
# GEOMETRIC MODELS
# ==============================================================================

def atomic_model(hbar, m, r, sigma=0, s=1, gamma=1.0):
    """
    Single particle on spacetime ball (like electron on proton)
    F = ℏ²s²/(γmr³) + σ
    """
    F_geometric = (hbar**2 * s**2) / (gamma * m * r**3)
    F_confinement = sigma
    F_total = F_geometric + F_confinement
    
    return {
        'model': 'atomic',
        'F_geometric': F_geometric,
        'F_confinement': F_confinement,
        'F_total': F_total,
        'description': f'Single particle, s={s}, r={r*1e15:.1f}fm'
    }

def bola_two_body(hbar, m, d, sigma, s=0.5, gamma=1.0):
    """
    Two particles leashed together, spinning around center of mass
    
    Physics:
    - Each particle at distance d/2 from center of mass
    - Total angular momentum L = 2 * (m * v * d/2) = m * v * d = ℏ * s_total
    - Each particle has s_total/2 angular momentum
    - Centripetal force: F = m * v² / (d/2) = 2mv²/d
    - With v = ℏ*s_total/(m*d), get F = 2ℏ²s_total²/(m*d³)
    """
    
    # Total angular momentum distributed between particles
    s_total = 2 * s  # Each particle contributes s/2
    
    # Geometric force from bola rotation
    F_geometric = 2 * (hbar**2 * s_total**2) / (gamma * m * d**3)
    
    # String tension between particles
    F_confinement = sigma
    
    F_total = F_geometric + F_confinement
    
    return {
        'model': 'bola_2body',
        'F_geometric': F_geometric,
        'F_confinement': F_confinement,
        'F_total': F_total,
        'description': f'Two-body bola, s_each={s}, d={d*1e15:.1f}fm'
    }

def bola_three_body(hbar, m, d, sigma, s=1/3, gamma=1.0):
    """
    Three particles (actual proton: uud quarks) in triangular rotation
    
    Physics:
    - Three quarks in equilateral triangle, side length d
    - Distance from center to each quark: r = d/√3
    - Each quark contributes s to total angular momentum
    - Total L = 3 * m * v * r = ℏ * s_total where s_total = 3*s
    """
    
    # Geometry of equilateral triangle
    r_center = d / math.sqrt(3)  # Distance from center to vertex
    s_total = 3 * s  # Total angular momentum
    
    # Each quark experiences centripetal force toward center
    # F = m * v² / r where v = ℏ*s_total/(3*m*r)
    v = (hbar * s_total) / (3 * m * r_center)
    F_geometric = m * v**2 / r_center
    
    # Alternative: Direct formula
    # F_geometric = (ℏ²s_total²) / (9*m*r_center³) * 3
    F_geometric_alt = 3 * (hbar**2 * s_total**2) / (9 * gamma * m * r_center**3)
    
    F_confinement = sigma
    F_total = F_geometric + F_confinement
    
    return {
        'model': 'bola_3body',
        'F_geometric': F_geometric,
        'F_geometric_alt': F_geometric_alt,
        'F_confinement': F_confinement,
        'F_total': F_total,
        'description': f'Three-body bola, s_each={s}, d={d*1e15:.1f}fm'
    }

def reduced_mass_model(m1, m2, hbar, d, sigma, s=0.5, gamma=1.0):
    """
    Two different masses leashed together (e.g., up and down quarks)
    Uses reduced mass μ = m1*m2/(m1+m2)
    """
    
    # Reduced mass
    mu = (m1 * m2) / (m1 + m2)
    
    # Center of mass distances
    r1 = m2 * d / (m1 + m2)  # Distance of m1 from center
    r2 = m1 * d / (m1 + m2)  # Distance of m2 from center
    
    # Angular momentum constraint: L = mu * v * d = ℏ * s
    v = (hbar * s) / (mu * d)
    
    # Forces on each mass
    F1 = m1 * v**2 / r1
    F2 = m2 * v**2 / r2
    
    # Average force (what we measure)
    F_geometric = (F1 + F2) / 2
    F_confinement = sigma
    F_total = F_geometric + F_confinement
    
    return {
        'model': 'reduced_mass',
        'F_geometric': F_geometric,
        'F_confinement': F_confinement, 
        'F_total': F_total,
        'F1': F1,
        'F2': F2,
        'reduced_mass': mu,
        'description': f'Reduced mass μ={mu*1e30:.1f}×10⁻³⁰kg, d={d*1e15:.1f}fm'
    }

# ==============================================================================
# TEST FUNCTIONS
# ==============================================================================

def test_geometric_models():
    """Compare different geometric models with v21 parameters"""
    
    print("GEOMETRIC MODEL COMPARISON")
    print("="*60)
    print(f"Target force: {V21_PARAMS['target_force']:.1e} N")
    print(f"Using v21 parameters: m={V21_PARAMS['quark_mass']*1e30:.1f}×10⁻³⁰kg, r/d=1.0fm")
    print()
    
    p = V21_PARAMS
    
    # Test different models
    models = []
    
    # 1. Original atomic model (s²)
    atomic_with_s2 = atomic_model(p['hbar'], p['quark_mass'], p['proton_radius'], 
                                  p['string_tension'], s=p['quark_spin'])
    models.append(atomic_with_s2)
    
    # 2. Atomic model without s² (s=1)
    atomic_no_s2 = atomic_model(p['hbar'], p['quark_mass'], p['proton_radius'],
                               p['string_tension'], s=1)
    models.append(atomic_no_s2)
    
    # 3. Two-body bola
    bola_2 = bola_two_body(p['hbar'], p['quark_mass'], p['proton_radius'],
                          p['string_tension'], s=p['quark_spin'])
    models.append(bola_2)
    
    # 4. Three-body bola (actual proton)
    bola_3 = bola_three_body(p['hbar'], p['quark_mass'], p['proton_radius'],
                            p['string_tension'], s=1/3)
    models.append(bola_3)
    
    # 5. Reduced mass (up + down quark)
    m_up = 2.16e-30    # kg (2.16 MeV/c²)
    m_down = 4.67e-30  # kg (4.67 MeV/c²)
    reduced = reduced_mass_model(m_up, m_down, p['hbar'], p['proton_radius'],
                               p['string_tension'], s=0.5)
    models.append(reduced)
    
    # Display results
    print(f"{'Model':<15} {'F_total(N)':<12} {'Agreement%':<12} {'Geom%':<8} {'Description'}")
    print("-" * 80)
    
    for model in models:
        agreement = model['F_total'] / p['target_force'] * 100
        geom_percent = model['F_geometric'] / model['F_total'] * 100
        
        print(f"{model['model']:<15} {model['F_total']:<12.2e} {agreement:<12.1f} "
              f"{geom_percent:<8.1f} {model['description']}")

def test_bola_scaling():
    """Test how bola models scale with separation distance"""
    
    print(f"\n" + "="*60)
    print("BOLA SCALING ANALYSIS")
    print("="*60)
    
    distances = [0.5e-15, 0.8e-15, 1.0e-15, 1.2e-15, 1.5e-15]  # meters
    
    print(f"{'d(fm)':<8} {'2-body':<12} {'3-body':<12} {'Agreement_2':<12} {'Agreement_3':<12}")
    print("-" * 65)
    
    p = V21_PARAMS
    
    for d in distances:
        d_fm = d * 1e15
        
        # Two-body bola
        bola_2 = bola_two_body(p['hbar'], p['quark_mass'], d, p['string_tension'])
        
        # Three-body bola  
        bola_3 = bola_three_body(p['hbar'], p['quark_mass'], d, p['string_tension'])
        
        agree_2 = bola_2['F_total'] / p['target_force'] * 100
        agree_3 = bola_3['F_total'] / p['target_force'] * 100
        
        print(f"{d_fm:<8.1f} {bola_2['F_total']:<12.2e} {bola_3['F_total']:<12.2e} "
              f"{agree_2:<12.1f} {agree_3:<12.1f}")

def test_spin_distribution():
    """Test different ways of distributing angular momentum in bola"""
    
    print(f"\n" + "="*60)
    print("ANGULAR MOMENTUM DISTRIBUTION")
    print("="*60)
    
    print("How should total angular momentum be distributed among quarks?")
    print()
    
    p = V21_PARAMS
    
    # Test different total angular momentum values
    spin_configs = [
        ("Each s=1/2, total=1", 0.5, 2),      # Two quarks each with s=1/2
        ("Each s=1/3, total=1", 1/3, 3),     # Three quarks each with s=1/3  
        ("Each s=1/2, total=3/2", 0.5, 3),   # Three quarks each with s=1/2
        ("Each s=1, total=2", 1.0, 2),       # Two quarks each with s=1
        ("Each s=1, total=3", 1.0, 3),       # Three quarks each with s=1
    ]
    
    print(f"{'Configuration':<20} {'s_each':<8} {'N_quarks':<10} {'F_total':<12} {'Agreement%':<12}")
    print("-" * 75)
    
    for desc, s_each, n_quarks in spin_configs:
        if n_quarks == 2:
            result = bola_two_body(p['hbar'], p['quark_mass'], p['proton_radius'],
                                 p['string_tension'], s=s_each)
        else:
            result = bola_three_body(p['hbar'], p['quark_mass'], p['proton_radius'],
                                   p['string_tension'], s=s_each)
        
        agreement = result['F_total'] / p['target_force'] * 100
        
        print(f"{desc:<20} {s_each:<8.2f} {n_quarks:<10} {result['F_total']:<12.2e} {agreement:<12.1f}")

def test_physical_interpretation():
    """Explore what the models tell us about quark physics"""
    
    print(f"\n" + "="*60)
    print("PHYSICAL INTERPRETATION")
    print("="*60)
    
    p = V21_PARAMS
    
    print("What does each model predict about quark motion?")
    print()
    
    # Calculate velocities for different models
    models_to_test = [
        ("Atomic s=1/2", lambda: atomic_model(p['hbar'], p['quark_mass'], p['proton_radius'], 0, s=0.5)),
        ("Atomic s=1", lambda: atomic_model(p['hbar'], p['quark_mass'], p['proton_radius'], 0, s=1)),
        ("Bola 2-body", lambda: bola_two_body(p['hbar'], p['quark_mass'], p['proton_radius'], 0)),
        ("Bola 3-body", lambda: bola_three_body(p['hbar'], p['quark_mass'], p['proton_radius'], 0))
    ]
    
    print(f"{'Model':<15} {'v/c':<8} {'F_geom(N)':<12} {'Note'}")
    print("-" * 50)
    
    for name, model_func in models_to_test:
        result = model_func()
        
        # Estimate velocity from angular momentum
        if 'atomic' in name:
            if 's=1/2' in name:
                s = 0.5
            else:
                s = 1.0
            v = (p['hbar'] * s) / (p['quark_mass'] * p['proton_radius'])
        else:
            # For bola models, estimate average velocity
            s_total = 1.0  # Assume total L = ℏ
            if '2-body' in name:
                v = (p['hbar'] * s_total) / (2 * p['quark_mass'] * p['proton_radius']/2)
            else:
                v = (p['hbar'] * s_total) / (3 * p['quark_mass'] * p['proton_radius']/math.sqrt(3))
        
        v_over_c = v / C
        
        note = ""
        if v_over_c > 0.1:
            note = "relativistic!"
        elif v_over_c > 0.01:
            note = "fast"
        
        print(f"{name:<15} {v_over_c:<8.3f} {result['F_geometric']:<12.2e} {note}")

# ==============================================================================
# MAIN TEST ROUTINE
# ==============================================================================

def main():
    """Run all bola physics tests"""
    
    print("BOLA PHYSICS TEST FOR QUARKS")
    print("="*70)
    print("Testing different rotational geometries for quark confinement")
    print("Key insight: Quarks spin together like bola, not single particles on balls")
    print()
    
    test_geometric_models()
    test_bola_scaling()
    test_spin_distribution()
    test_physical_interpretation()
    
    print(f"\n" + "="*70)
    print("CONCLUSIONS")
    print("="*70)
    
    print("Key insights from bola model:")
    print("1. Multi-particle systems have different rotational dynamics")
    print("2. Angular momentum distribution affects force calculations")
    print("3. Geometry matters: 2-body vs 3-body vs single particle")
    print("4. The 'leash' connects particles in shared rotation")
    print("5. This explains why s=1/2 worked in v21 (shared angular momentum)")
    
    print(f"\nThe bola model suggests quarks are not isolated particles")
    print(f"but components of a rotating, bound multi-particle system.")
    print(f"This is fundamentally different from atoms (single particle on ball).")

if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] in ['-h', '--help']:
        print("Usage: python bola_physics_test.py")
        print("  Tests bola vs atomic models for quark confinement")
        print("  Explores multi-particle rotational dynamics")
        sys.exit(0)
    
    main()