"""
Test: Bekenstein-Hawking entropy and holographic scaling
=========================================================

Standard result:
For a Schwarzschild black hole, the entropy is:

    S_BH = A / (4 G hbar / c^3) = k_B * A / (4 l_P^2)

where A = 4*pi*Rs^2 is the horizon area and l_P = sqrt(G hbar / c^3)
is the Planck length. In natural units (G = c = hbar = k_B = 1):

    S_BH = A / 4

This is the famous "area law" -- entropy scales with the horizon's
2D surface area, not with the 3D volume it contains. This is the
content of the holographic principle: the degrees of freedom of a
gravitating region are encoded on its boundary, not distributed
through its interior.

This is genuinely mysterious in standard physics. QFT on a local
continuum gives volume-scaling entropy (V-law). Black hole entropy
scales with area. Something non-local is going on.

Framework question:
-------------------
Does the framework have a natural account of why entropy scales with
area rather than volume?

Basic idea:
- In the framework, a black hole is a region of brane with extreme
  w4 embedding.
- The "degrees of freedom" relevant to the entropy are... what, exactly?
- If they're degrees of freedom of brane-fields (3-volume), we get V-law.
- If they're degrees of freedom of the embedding itself (a 2-surface
  bounding the embedded region), we get A-law.

The holographic principle says the answer is the latter. Does the
framework naturally give this?

This is where it gets interesting: the horizon in the framework is
the boundary between the "flat" part of the brane and the "extremely
w4-extended" part. The embedding profile is determined by ONE function
(the w4 height) over the brane. In the embedded region, this function
extends deep into w4. In the flat region, it sits at baseline.

The transition happens across the horizon (a 2-surface in brane terms).
If the "information" about the embedded region's state is encoded in
the PROFILE OF THE BOUNDARY (the horizon), not in the interior volume,
then area-scaling follows naturally.
"""

import numpy as np
from scipy.integrate import quad

print("="*72)
print("TEST: Bekenstein-Hawking entropy and area-law scaling")
print("="*72)
print()

# Natural units
G = 1.0
c = 1.0
hbar = 1.0
kB = 1.0

def bh_entropy(M):
    """Bekenstein-Hawking entropy for Schwarzschild BH of mass M."""
    Rs = 2 * G * M / c**2
    A = 4 * np.pi * Rs**2
    return A / (4 * G * hbar / c**3)

# Verify S ~ M^2 (area law)
print("STANDARD AREA LAW VERIFICATION:")
print("-"*72)
print(f"{'M':>10} {'Rs':>10} {'A':>12} {'S = A/4':>12} {'S/M^2':>10}")
for M in [1, 2, 5, 10, 100]:
    S = bh_entropy(M)
    Rs = 2*M
    A = 4*np.pi*Rs**2
    print(f"{M:>10} {Rs:>10} {A:>12.4f} {S:>12.4f} {S/M**2:>10.6f}")
print(f"(Expected S/M^2 = 4*pi = {4*np.pi:.6f})")
print()

print("="*72)
print("WHY AREA LAW IS SURPRISING IN STANDARD QFT")
print("="*72)
print()
print("Naive QFT entropy in a region of volume V with UV cutoff Lambda:")
print("  S ~ V * Lambda^3")
print("If Lambda is the Planck scale (natural UV cutoff for gravity),")
print("  S_naive ~ V / l_P^3  (VOLUME law)")
print()
print("For a BH of radius R, V ~ R^3, so S_naive ~ R^3.")
print("But observed: S_BH ~ R^2 (AREA law).")
print()
print("Missing factor: S_naive / S_BH ~ R, which for astrophysical BHs is")
print("a factor of ~10^38. This is the holographic puzzle: why is the entropy")
print("so much smaller than naive QFT predicts?")
print()

# Now the framework argument:

print("="*72)
print("FRAMEWORK ARGUMENT")
print("="*72)
print()
print("In the framework, the black hole interior has a specific structure:")
print("the brane is embedded deeply in w4, extending into the ambient")
print("direction. Points 'inside' the horizon are on the brane, but at")
print("w4 positions that make them inaccessible to outside observers.")
print()
print("The question of how many independent degrees of freedom the")
print("embedded region supports is the question of how much the embedding")
print("can vary.")
print()
print("Key observation: the embedding profile w4(x, y, z) is specified")
print("by ITS BOUNDARY CONDITIONS at the horizon (2-surface) plus its")
print("evolution inside. Inside the horizon, the embedding is determined")
print("by a deterministic evolution from the horizon condition -- not")
print("independent at every interior point.")
print()
print("Compare:")
print("  - A 3D field in a 3D region: independent values at each of V/l^3")
print("    lattice sites. DOF ~ V.")
print("  - A 2D boundary condition propagating into a 3D region by a")
print("    deterministic PDE: only the 2D boundary data is independent.")
print("    DOF ~ A.")
print()
print("This is the natural explanation of area scaling: the interior isn't")
print("free to carry independent information; it's the deterministic")
print("continuation of boundary data.")
print()

# Can we make this more quantitative? Let's try a specific toy model.

print("="*72)
print("TOY MODEL: embedding profile as boundary-determined")
print("="*72)
print()
print("Consider a spherically symmetric embedded region. The w4 embedding")
print("height W(r) for r < R_s is determined by:")
print("  - Boundary condition: W(R_s) = some value (horizon embedding depth)")
print("  - Regularity at r = 0 (or appropriate condition at the 'tip' of the")
print("    embedding)")
print("  - The evolution equation (brane equations, i.e., Einstein equations")
print("    read as embedding equations)")
print()
print("Once W(R_s) and its first derivative are specified on the horizon,")
print("W(r) for r < R_s is determined. So the interior's state is encoded")
print("in 2D boundary data on the horizon (= horizon area).")
print()

# Counting modes:
# On a 2-sphere of radius Rs, expand boundary data in spherical harmonics.
# Modes with angular momentum l have ~2l+1 components.
# UV cutoff: modes with l up to l_max such that the angular wavelength 
# ~Rs/l matches the Planck length.
# l_max ~ Rs / l_P
# Total modes: sum_{l=0}^{l_max} (2l+1) ~ l_max^2 ~ (Rs/l_P)^2 ~ A/l_P^2

print("MODE COUNTING ON HORIZON (2-sphere of radius Rs):")
print("-"*72)
print()
print("Boundary data W(theta, phi) on the horizon 2-sphere can be expanded")
print("in spherical harmonics Y_lm(theta, phi). Modes with ang.mom. l have")
print("(2l+1) independent components.")
print()
print("UV cutoff from Planck scale: angular wavelength Rs/l >= l_P,")
print("so l_max ~ Rs/l_P.")
print()
print("Total independent boundary modes:")
print("  N = sum_{l=0}^{l_max} (2l+1) = (l_max + 1)^2 ~ l_max^2")
print("    ~ (Rs/l_P)^2")
print("    = A/(4*pi*l_P^2)")
print()

# Numerical check
for M in [1, 10, 100, 1000]:
    Rs = 2 * M  # in natural units, l_P = 1
    l_P = 1.0
    l_max = Rs / l_P
    N_modes = (l_max + 1)**2
    A = 4 * np.pi * Rs**2
    S_BH = A / 4
    print(f"  M={M:6}: Rs={Rs:6.1f}, l_max~{l_max:6.1f}, N_modes={N_modes:10.0f}, S_BH={S_BH:10.1f}, ratio={N_modes/S_BH:.4f}")

print()
print("Mode count scales as A, with the right order of magnitude. The exact")
print("prefactor (S_BH = A/4 specifically) requires more careful analysis")
print("of what 'independent mode' means and how it relates to entropy, but")
print("the A-scaling falls out naturally.")
print()

# More careful note on the prefactor:
# The A/4 prefactor in BH entropy is fixed by requiring consistency with
# the Hawking temperature (already derived above via Euclidean periodicity)
# and the first law of black hole thermodynamics (dM = T dS).
# 
# Given T_H = hbar*c^3/(8*pi*G*M*kB), we have dS/dM = 1/T_H = 8*pi*G*M/(hbar*c^3).
# Integrating: S = 4*pi*G*M^2/(hbar*c^3).
# And A = 4*pi*Rs^2 = 4*pi*(2GM/c^2)^2 = 16*pi*G^2*M^2/c^4.
# So S = A / (4*G*hbar/c^3) = A/(4*l_P^2).  ✓

print("="*72)
print("CONNECTION TO HAWKING TEMPERATURE (PREVIOUSLY DERIVED)")
print("="*72)
print()
print("The specific prefactor S = A/(4*l_P^2) is fixed by:")
print("  (a) Hawking temperature T_H from Euclidean periodicity (test 2)")
print("  (b) First law: dM = T_H * dS")
print()
print("Integrating: S = 4*pi*G*M^2/(hbar*c^3) = A/(4*l_P^2).")
print()
print("So the framework's derivation chain:")
print("  1. Embedding geometry forces Euclidean periodicity at horizon -> T_H")
print("  2. Embedding is boundary-determined -> DOF ~ A (not V)")
print("  3. Combining (1) with first law dM = T dS -> S = A/(4*l_P^2)")
print()
print("Both the scaling (area not volume) AND the prefactor (1/4) are")
print("framework-derived, using only the postulate plus standard")
print("thermodynamic machinery.")
print()

print("="*72)
print("VERDICT")
print("="*72)
print()
print("Framework gives natural account of:")
print("  (i) Area-law scaling: boundary data determines interior embedding")
print("      by deterministic evolution, so DOF scale as A not V.")
print("  (ii) Prefactor 1/4: fixed by combining framework-derived T_H with")
print("       first law of BH thermodynamics.")
print()
print("This is a *structural* win: holographic scaling is GENERIC in the")
print("framework, not a mysterious feature needing separate explanation.")
print("The 'holographic principle' -- gravity's tendency to encode bulk")
print("information on boundaries -- is exactly what you'd expect from a")
print("theory where 'bulk' is a brane whose profile is boundary-determined.")
print()
print("Caveats:")
print("  - The mode-counting argument is heuristic, not rigorous.")
print("    A proper derivation would require a more careful quantisation")
print("    of embedding perturbations, which is beyond this test.")
print("  - Requires the 'boundary-determined interior' claim to be rigorous,")
print("    i.e. that Einstein's equations, read as embedding equations,")
print("    propagate boundary data deterministically into the interior.")
print("    This is plausible but needs proper statement.")
