Skip to main content

Autodiff Solver API

The autodiff_curvature module provides exact derivative computations for warp metrics using PyTorch's automatic differentiation, eliminating numerical artifacts from finite difference schemes.

Overview

Traditional finite difference methods introduce discretization errors that become severe for warp metrics with:

  • Stiff bubble walls (σ → ∞)
  • Superluminal velocities (v > c)
  • Sharp spatial transitions

The autodiff solver computes exact analytical derivatives through the computational graph, providing:

  • Perfect accuracy - no discretization errors
  • Numerical stability - works for extreme parameters
  • GPU acceleration - optimized tensor operations
  • Automatic differentiation - exact chain rule application

Core Classes

AutodiffCurvatureSolver

Main solver class for computing curvature tensors using automatic differentiation.

from core.solver.autodiff_curvature import AutodiffCurvatureSolver

solver = AutodiffCurvatureSolver(device=None) # Auto-detect GPU/CPU

Methods

get_christoffel_symbols_autodiff(g_cov, coords)

Compute Christoffel symbols of the second kind using exact derivatives.

Formula: Γ^α_βγ = ½ g^αδ (∂_γ g_δβ + ∂_β g_δγ - ∂_δ g_βγ)

Parameters:

  • g_cov (torch.Tensor): Covariant metric tensor (4, 4, T, X, Y, Z)
  • coords (dict): Dictionary of coordinate grids {'t': t_grid, 'x': x_grid, ...}

Returns:

  • gamma (torch.Tensor): Christoffel symbols (4, 4, 4, T, X, Y, Z)

Example:

# Prepare metric with gradient-enabled coordinates
t_grid = torch.linspace(-1, 1, 10, requires_grad=True)
x_grid = torch.linspace(-5, 5, 20, requires_grad=True)
y_grid = torch.linspace(-5, 5, 20, requires_grad=True)
z_grid = torch.linspace(-5, 5, 20, requires_grad=True)

coords = {
't': t_grid.clone().detach(), # Autodiff needs gradient tracking
'x': x_grid.clone().detach(),
'y': y_grid.clone().detach(),
'z': z_grid.clone().detach()
}

# Compute exact Christoffel symbols
gamma = solver.get_christoffel_symbols_autodiff(metric.tensor, coords)
get_ricci_tensor_autodiff(g_cov, coords)

Compute Ricci tensor using exact derivatives of Christoffel symbols.

Formula: R_μν = ∂_α Γ^α_μν - ∂_ν Γ^α_μα + Γ^α_βα Γ^β_μν - Γ^α_βν Γ^α_μα

Parameters:

  • g_cov (torch.Tensor): Covariant metric tensor
  • coords (dict): Coordinate grids with requires_grad=True

Returns:

  • R_cov (torch.Tensor): Ricci tensor (4, 4, T, X, Y, Z)

Example:

ricci = solver.get_ricci_tensor_autodiff(metric.tensor, coords)

# Analyze curvature invariants
ricci_scalar = solver.get_ricci_scalar_autodiff(metric.tensor, coords)
kretschmann = compute_kretschmann_scalar(ricci, metric)
get_ricci_scalar_autodiff(g_cov, coords)

Compute Ricci scalar R = g^μν R_μν using autodiff.

Parameters:

  • g_cov (torch.Tensor): Covariant metric tensor
  • coords (dict): Coordinate grids

Returns:

  • R (torch.Tensor): Ricci scalar (T, X, Y, Z)

Convenience Functions

get_christoffel_symbols()

Unified interface supporting both autodiff and finite difference methods.

from core.solver.autodiff_curvature import get_christoffel_symbols

# Autodiff method (exact)
gamma_autodiff = get_christoffel_symbols(
g_cov=metric.tensor,
grid_scaling=metric.grid_scaling,
method="autodiff",
coords=coords # Required for autodiff
)

# Finite difference method (traditional)
gamma_fd = get_christoffel_symbols(
g_cov=metric.tensor,
grid_scaling=metric.grid_scaling,
method="finite_diff" # No coords needed
)

Preparing Metrics for Autodiff

To use autodiff, metric tensors must be computed using gradient-enabled coordinates:

import torch
from core.metrics.alcubierre import shape_function_alcubierre

def create_autodiff_metric(grid_size, v, R, sigma):
"""Create warp metric with autodiff support"""

T, X, Y, Z = grid_size

# Enable gradients for coordinates
t = torch.linspace(0, 1, T, requires_grad=True)
x = torch.linspace(-10, 10, X, requires_grad=True)
y = torch.linspace(-10, 10, Y, requires_grad=True)
z = torch.linspace(-10, 10, Z, requires_grad=True)

# Create meshgrids
t_mesh, x_mesh, y_mesh, z_mesh = torch.meshgrid(
t, x, y, z, indexing='ij'
)

# Compute metric components using these coordinates
x_s = t_mesh * (v * C) # Bubble center movement
r = torch.sqrt((x_mesh - x_s)**2 + y_mesh**2 + z_mesh**2)

# Shape function with autodiff
f_s = shape_function_alcubierre(r, R, sigma)
beta_x = -v * f_s

# Assemble metric tensor
g = torch.zeros((4, 4, T, X, Y, Z))
g[0, 0] = -1.0 + beta_x**2
g[0, 1] = beta_x
g[1, 0] = beta_x
g[1, 1] = 1.0
g[2, 2] = 1.0
g[3, 3] = 1.0

coords = {'t': t_mesh, 'x': x_mesh, 'y': y_mesh, 'z': z_mesh}

return g, coords

# Usage
metric, coords = create_autodiff_metric((4, 16, 16, 16), v=2.5, R=4.0, sigma=50.0)

Performance Comparison

Accuracy

Methodσ = 5σ = 20σ = 50σ = 100
Autodiff✅ Exact✅ Exact✅ Exact✅ Exact
Finite Diff✅ Good⚠️ Degraded❌ Unstable❌ Failed

Speed

MethodSmall Grid (16³)Medium Grid (32³)Large Grid (64³)
Autodiff~120ms~850ms~6.8s
Finite Diff~45ms~180ms~1.2s

Note: Autodiff is slower but provides exact derivatives. Use for validation or critical accuracy requirements.

Usage Guidelines

When to Use Autodiff

Recommended for:

  • Stiff bubble walls (σ > 20)
  • Validation of finite difference results
  • Energy condition verification (avoid false positives)
  • Research publications requiring maximum accuracy
  • Novel/untested metric configurations

Use Finite Difference for:

  • Large-scale exploratory simulations
  • Real-time visualization
  • Well-tested metric configurations with moderate σ
  • Performance-critical applications

Best Practices

  1. Start with finite difference for exploration
  2. Switch to autodiff for production results
  3. Validate both methods for consistency
  4. Use autodiff when energy condition violations are suspected

Troubleshooting

Common Issues

"One of the differentiated Tensors appears to not have been used"

Problem: Metric components don't depend on gradient-enabled coordinates.

Solution: Ensure metric is computed using coordinates with requires_grad=True.

CUDA Out of Memory

Problem: Autodiff requires more memory for computational graph.

Solution:

  • Reduce grid size
  • Use float32 instead of float64
  • Process in batches

Slow Performance

Problem: Autodiff is inherently slower than finite differences.

Solution:

  • Use smaller grids during development
  • Only use autodiff for final results
  • Consider mixed-precision computation

Examples

Complete Example: Energy Analysis

import torch
from core.solver.autodiff_curvature import AutodiffCurvatureSolver

def analyze_warp_energy():
"""Analyze exotic matter requirements using exact derivatives"""

# Create stiff bubble
g, coords = create_autodiff_metric(
grid_size=(4, 24, 24, 24),
v=2.0, # Superluminal
R=6.0,
sigma=80.0 # Very stiff walls
)

# Compute exact curvature
solver = AutodiffCurvatureSolver()

# Ricci tensor
R_cov = solver.get_ricci_tensor_autodiff(g, coords)

# Einstein tensor: G = R - ½Rg
R_scalar = solver.get_ricci_scalar_autodiff(g, coords)
g_inv = torch.inverse(g.permute(2,3,4,5,0,1)).permute(4,5,0,1,2,3)

G = R_cov - 0.5 * R_scalar * g_inv

# Energy tensor: T = G/(8π)
T = G / (8 * torch.pi)

# Analyze negative energy regions
negative_mask = T[0, 0] < 0 # Energy density T₀₀
negative_energy = T[0, 0][negative_mask]

print(f"Negative energy regions: {negative_mask.sum().item()}")
print(f"Max exotic density: {negative_energy.abs().max().item():.6e}")
print(f"Total exotic mass: {negative_energy.sum().item():.6e}")

return T, negative_mask

# Run analysis
energy_tensor, exotic_regions = analyze_warp_energy()

Validation Example: Method Comparison

def validate_autodiff_accuracy():
"""Compare autodiff vs finite difference"""

# Test metric
g, coords = create_autodiff_metric((4, 16, 16, 16), v=1.5, R=4.0, sigma=30.0)

# Autodiff result
solver = AutodiffCurvatureSolver()
gamma_autodiff = solver.get_christoffel_symbols_autodiff(g, coords)

# Finite difference result
from core.solver.finite_difference import take_finite_difference_1
# ... (compute gamma_fd)

# Compare
diff = (gamma_autodiff - gamma_fd).abs()
relative_error = diff.max() / gamma_autodiff.abs().max()

print(f"Max difference: {diff.max().item():.6e}")
print(f"Relative error: {relative_error.item():.6%}")

# Autodiff should be more accurate for stiff metrics
if relative_error > 0.01: # 1% threshold
print("⚠️ Significant difference detected - autodiff recommended")
else:
print("✅ Methods agree - finite difference acceptable")

validate_autodiff_accuracy()

References