From 1c561cef867f6dbf2b2b65468a5a6098b501116b Mon Sep 17 00:00:00 2001 From: backlundtransform Date: Mon, 22 Jun 2026 11:11:23 +0200 Subject: [PATCH 1/3] feat(physics): add relativity module (special + Schwarzschild + classic GR tests) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New Physics.Relativity namespace — the first tranche of the astro/gravitation expansion (special relativity + weak-field general relativity). - SpecialRelativity: Lorentz factor, time dilation, length contraction, relativistic momentum/energy (rest/total/kinetic), energy–momentum relation, relativistic velocity addition, longitudinal Doppler, rapidity. KineticEnergy uses the cancellation-free form mc²·β²/(s(1+s)) so it stays accurate at the low speeds where it is most used (reduces cleanly to ½mv²). - Schwarzschild: gravitational radius, photon sphere, ISCO, gravitational time-dilation factor and redshift, clock-rate ratio between radii, escape velocity (= c at the horizon). - GeneralRelativity: the classical tests — perihelion precession (per orbit and arcsec/century), light deflection, Shapiro delay. Validated against known values: Mercury precession ≈ 43″/century, light deflection at the Sun's limb ≈ 1.75″, Schwarzschild radius of the Sun ≈ 2953 m. 23 new tests, all passing; core builds on all target frameworks. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../NumericTest/GeneralRelativityTests.cs | 72 +++++++++ Numerics/NumericTest/SchwarzschildTests.cs | 66 ++++++++ .../NumericTest/SpecialRelativityTests.cs | 85 ++++++++++ .../Physics/Relativity/GeneralRelativity.cs | 99 ++++++++++++ .../Physics/Relativity/Schwarzschild.cs | 92 +++++++++++ .../Physics/Relativity/SpecialRelativity.cs | 150 ++++++++++++++++++ 6 files changed, 564 insertions(+) create mode 100644 Numerics/NumericTest/GeneralRelativityTests.cs create mode 100644 Numerics/NumericTest/SchwarzschildTests.cs create mode 100644 Numerics/NumericTest/SpecialRelativityTests.cs create mode 100644 Numerics/Numerics/Physics/Relativity/GeneralRelativity.cs create mode 100644 Numerics/Numerics/Physics/Relativity/Schwarzschild.cs create mode 100644 Numerics/Numerics/Physics/Relativity/SpecialRelativity.cs diff --git a/Numerics/NumericTest/GeneralRelativityTests.cs b/Numerics/NumericTest/GeneralRelativityTests.cs new file mode 100644 index 0000000..433d62e --- /dev/null +++ b/Numerics/NumericTest/GeneralRelativityTests.cs @@ -0,0 +1,72 @@ +using System; +using CSharpNumerics.Physics.Constants; +using CSharpNumerics.Physics.Relativity; + +namespace NumericsTests; + +[TestClass] +public class GeneralRelativityTests +{ + private const double SolarMass = PhysicsConstants.SolarMass; + private const double RadToArcsec = 180.0 / Math.PI * 3600.0; + + // Mercury's orbit + private const double MercurySemiMajorAxis = 5.79e10; // m + private const double MercuryEccentricity = 0.2056; + private const double MercuryPeriodDays = 87.969; + + [TestMethod] + public void PerihelionPrecession_Mercury_PerOrbit() + { + // ≈ 5.0×10⁻⁷ rad per orbit + double perOrbit = GeneralRelativity.PerihelionPrecessionPerOrbit( + MercurySemiMajorAxis, MercuryEccentricity, SolarMass); + Assert.AreEqual(5.02e-7, perOrbit, 0.1e-7); + } + + [TestMethod] + public void PerihelionPrecession_Mercury_IsAbout43ArcsecPerCentury() + { + double arcsec = GeneralRelativity.PerihelionPrecessionArcsecPerCentury( + MercurySemiMajorAxis, MercuryEccentricity, SolarMass, MercuryPeriodDays); + Assert.AreEqual(43.0, arcsec, 1.0); + } + + [TestMethod] + public void LightDeflection_AtSunLimb_IsAbout1Point75Arcsec() + { + double sunRadius = 6.957e8; // m + double radians = GeneralRelativity.LightDeflection(sunRadius, SolarMass); + Assert.AreEqual(1.75, radians * RadToArcsec, 0.02); + } + + [TestMethod] + public void LightDeflection_ScalesInverselyWithImpactParameter() + { + double a = GeneralRelativity.LightDeflection(1.0e9, SolarMass); + double b = GeneralRelativity.LightDeflection(2.0e9, SolarMass); + Assert.AreEqual(a / 2.0, b, a * 1e-12); + } + + [TestMethod] + public void ShapiroDelay_IsPositive_AndGrowsWithMass() + { + double au = PhysicsConstants.AstronomicalUnit; + double sunRadius = 6.957e8; + double delay = GeneralRelativity.ShapiroDelay(au, au, sunRadius, SolarMass); + + Assert.IsTrue(delay > 0.0); + // Earth–graze–Earth one-way excess delay is on the order of 0.1 ms. + Assert.AreEqual(1.2e-4, delay, 0.3e-4); + + double heavier = GeneralRelativity.ShapiroDelay(au, au, sunRadius, 2.0 * SolarMass); + Assert.IsTrue(heavier > delay); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void ShapiroDelay_RadiusBelowImpactParameter_Throws() + { + GeneralRelativity.ShapiroDelay(1.0e8, 1.0e12, 5.0e8, SolarMass); + } +} diff --git a/Numerics/NumericTest/SchwarzschildTests.cs b/Numerics/NumericTest/SchwarzschildTests.cs new file mode 100644 index 0000000..58c5dcc --- /dev/null +++ b/Numerics/NumericTest/SchwarzschildTests.cs @@ -0,0 +1,66 @@ +using System; +using CSharpNumerics.Physics.Constants; +using CSharpNumerics.Physics.Relativity; + +namespace NumericsTests; + +[TestClass] +public class SchwarzschildTests +{ + private const double C = PhysicsConstants.SpeedOfLight; + private const double SolarMass = PhysicsConstants.SolarMass; + + [TestMethod] + public void Radius_OfSun_IsAboutTwoPointNineKilometres() + { + // r_s(Sun) ≈ 2953 m + Assert.AreEqual(2953.0, Schwarzschild.Radius(SolarMass), 5.0); + } + + [TestMethod] + public void PhotonSphere_And_Isco_AreMultiplesOfSchwarzschildRadius() + { + double rs = Schwarzschild.Radius(SolarMass); + Assert.AreEqual(1.5 * rs, Schwarzschild.PhotonSphereRadius(SolarMass), rs * 1e-12); + Assert.AreEqual(3.0 * rs, Schwarzschild.Isco(SolarMass), rs * 1e-12); + } + + [TestMethod] + public void TimeDilationFactor_FarFromMass_ApproachesOne() + { + double factor = Schwarzschild.TimeDilationFactor(1.0e12, SolarMass); + Assert.IsTrue(factor < 1.0); + Assert.AreEqual(1.0, factor, 1e-5); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void TimeDilationFactor_AtHorizon_Throws() + { + double rs = Schwarzschild.Radius(SolarMass); + Schwarzschild.TimeDilationFactor(rs, SolarMass); + } + + [TestMethod] + public void Redshift_IsPositive_AndSmallFarFromMass() + { + double z = Schwarzschild.Redshift(1.0e9, SolarMass); + Assert.IsTrue(z > 0.0); + Assert.IsTrue(z < 1e-5); + } + + [TestMethod] + public void ClockRateRatio_LowerClockRunsSlow() + { + // Clock deeper in the well (smaller r) ticks slower than the higher one. + double ratio = Schwarzschild.ClockRateRatio(1.0e7, 1.0e9, SolarMass); + Assert.IsTrue(ratio < 1.0); + } + + [TestMethod] + public void EscapeVelocity_AtSchwarzschildRadius_EqualsSpeedOfLight() + { + double rs = Schwarzschild.Radius(SolarMass); + Assert.AreEqual(C, Schwarzschild.EscapeVelocity(rs, SolarMass), 1.0); + } +} diff --git a/Numerics/NumericTest/SpecialRelativityTests.cs b/Numerics/NumericTest/SpecialRelativityTests.cs new file mode 100644 index 0000000..4a686fb --- /dev/null +++ b/Numerics/NumericTest/SpecialRelativityTests.cs @@ -0,0 +1,85 @@ +using System; +using CSharpNumerics.Physics.Constants; +using CSharpNumerics.Physics.Relativity; + +namespace NumericsTests; + +[TestClass] +public class SpecialRelativityTests +{ + private const double C = PhysicsConstants.SpeedOfLight; + + [TestMethod] + public void LorentzFactor_AtRest_IsOne() + { + Assert.AreEqual(1.0, SpecialRelativity.LorentzFactor(0.0), 1e-15); + } + + [TestMethod] + public void LorentzFactor_At080c_IsFiveThirds() + { + // γ = 1/√(1 − 0.64) = 1/0.6 = 5/3 + Assert.AreEqual(5.0 / 3.0, SpecialRelativity.LorentzFactor(0.8 * C), 1e-9); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentOutOfRangeException))] + public void LorentzFactor_AtLightSpeed_Throws() + { + SpecialRelativity.LorentzFactor(C); + } + + [TestMethod] + public void TimeDilation_MovingClockRunsSlow() + { + // 1 s of proper time at 0.8c → 5/3 s of coordinate time + Assert.AreEqual(5.0 / 3.0, SpecialRelativity.TimeDilation(1.0, 0.8 * C), 1e-9); + } + + [TestMethod] + public void LengthContraction_At080c_IsThreeFifths() + { + Assert.AreEqual(0.6, SpecialRelativity.LengthContraction(1.0, 0.8 * C), 1e-9); + } + + [TestMethod] + public void KineticEnergy_LowSpeed_MatchesClassicalLimit() + { + // (γ − 1)mc² → ½mv² for v ≪ c + double m = 2.0, v = 1000.0; + double classical = 0.5 * m * v * v; + Assert.AreEqual(classical, SpecialRelativity.KineticEnergy(m, v), 1.0); + } + + [TestMethod] + public void AddVelocities_HalfPlusHalf_IsBelowLight() + { + // (0.5c + 0.5c)/(1 + 0.25) = 0.8c + Assert.AreEqual(0.8 * C, SpecialRelativity.AddVelocities(0.5 * C, 0.5 * C), 1.0); + } + + [TestMethod] + public void DopplerFactor_Receding_IsRedshift() + { + // β = 0.6 → √(0.4/1.6) = 0.5 (observed frequency halved) + Assert.AreEqual(0.5, SpecialRelativity.DopplerFactor(0.6 * C), 1e-12); + } + + [TestMethod] + public void EnergyFromMomentum_MatchesTotalEnergy() + { + double m = 1.0, v = 0.9 * C; + double p = SpecialRelativity.Momentum(m, v); + double expected = SpecialRelativity.TotalEnergy(m, v); + Assert.AreEqual(expected, SpecialRelativity.EnergyFromMomentum(m, p), expected * 1e-12); + } + + [TestMethod] + public void Rapidity_AddsLinearlyUnderVelocityComposition() + { + double u = 0.3 * C, v = 0.4 * C; + double combined = SpecialRelativity.Rapidity(SpecialRelativity.AddVelocities(u, v)); + double sum = SpecialRelativity.Rapidity(u) + SpecialRelativity.Rapidity(v); + Assert.AreEqual(sum, combined, 1e-9); + } +} diff --git a/Numerics/Numerics/Physics/Relativity/GeneralRelativity.cs b/Numerics/Numerics/Physics/Relativity/GeneralRelativity.cs new file mode 100644 index 0000000..5b7c256 --- /dev/null +++ b/Numerics/Numerics/Physics/Relativity/GeneralRelativity.cs @@ -0,0 +1,99 @@ +using System; +using CSharpNumerics.Physics.Constants; + +namespace CSharpNumerics.Physics.Relativity; + +/// +/// Weak-field general-relativistic effects — the classical tests of GR: +/// perihelion precession, gravitational light deflection, and the Shapiro +/// time delay. Masses are in kg, lengths in metres, angles in radians. +/// +public static class GeneralRelativity +{ + private const double G = PhysicsConstants.GravitationalConstant; + private const double C = PhysicsConstants.SpeedOfLight; + private const double C2 = C * C; + private const double C3 = C * C * C; + + private const double RadiansToArcseconds = 180.0 / Math.PI * 3600.0; + + /// + /// Relativistic perihelion precession per orbit (radians): + /// Δϖ = 6πGM / (c²·a·(1 − e²)). + /// For Mercury this is ≈ 5.0×10⁻⁷ rad per orbit (≈ 43″ per century). + /// + /// Orbital semi-major axis a (m). + /// Orbital eccentricity e, 0 ≤ e < 1. + /// Mass of the central body (kg). + public static double PerihelionPrecessionPerOrbit(double semiMajorAxis, double eccentricity, double centralMass) + { + if (semiMajorAxis <= 0) + throw new ArgumentOutOfRangeException(nameof(semiMajorAxis), "Semi-major axis must be positive."); + if (eccentricity < 0 || eccentricity >= 1) + throw new ArgumentOutOfRangeException(nameof(eccentricity), "Eccentricity must be in [0, 1)."); + + double latusFactor = semiMajorAxis * (1.0 - eccentricity * eccentricity); + return 6.0 * Math.PI * G * centralMass / (C2 * latusFactor); + } + + /// + /// Relativistic perihelion precession in arcseconds per century, given the + /// orbital period. Convenience wrapper around + /// . + /// + /// Semi-major axis a (m). + /// Eccentricity e, 0 ≤ e < 1. + /// Central mass (kg). + /// Orbital period (days). + public static double PerihelionPrecessionArcsecPerCentury( + double semiMajorAxis, double eccentricity, double centralMass, double orbitalPeriodDays) + { + if (orbitalPeriodDays <= 0) + throw new ArgumentOutOfRangeException(nameof(orbitalPeriodDays), "Period must be positive."); + + double perOrbit = PerihelionPrecessionPerOrbit(semiMajorAxis, eccentricity, centralMass); + double orbitsPerCentury = 36525.0 / orbitalPeriodDays; + return perOrbit * orbitsPerCentury * RadiansToArcseconds; + } + + /// + /// Gravitational deflection of light passing a mass at impact parameter + /// : α = 4GM / (c²·b) radians. + /// For a ray grazing the Sun's limb this is ≈ 1.75″. + /// + /// Closest approach distance b (m). + /// Deflecting mass (kg). + public static double LightDeflection(double impactParameter, double centralMass) + { + if (impactParameter <= 0) + throw new ArgumentOutOfRangeException(nameof(impactParameter), "Impact parameter must be positive."); + + return 4.0 * G * centralMass / (C2 * impactParameter); + } + + /// + /// Shapiro time delay (seconds) — the extra one-way light-travel time for a + /// signal passing a mass at impact parameter + /// , between a source at radial distance + /// and a receiver at : + /// Δt = (2GM/c³)·ln[ (r₁+√(r₁²−b²))(r₂+√(r₂²−b²)) / b² ]. + /// + /// Radial distance of the source from the mass (m). + /// Radial distance of the receiver from the mass (m). + /// Impact parameter b of the signal path (m). + /// Mass causing the delay (kg). + public static double ShapiroDelay(double r1, double r2, double impactParameter, double centralMass) + { + if (impactParameter <= 0) + throw new ArgumentOutOfRangeException(nameof(impactParameter), "Impact parameter must be positive."); + if (r1 < impactParameter || r2 < impactParameter) + throw new ArgumentOutOfRangeException(nameof(r1), + "Both radial distances must be at least the impact parameter."); + + double x1 = Math.Sqrt(r1 * r1 - impactParameter * impactParameter); + double x2 = Math.Sqrt(r2 * r2 - impactParameter * impactParameter); + double argument = (r1 + x1) * (r2 + x2) / (impactParameter * impactParameter); + + return 2.0 * G * centralMass / C3 * Math.Log(argument); + } +} diff --git a/Numerics/Numerics/Physics/Relativity/Schwarzschild.cs b/Numerics/Numerics/Physics/Relativity/Schwarzschild.cs new file mode 100644 index 0000000..1ab079e --- /dev/null +++ b/Numerics/Numerics/Physics/Relativity/Schwarzschild.cs @@ -0,0 +1,92 @@ +using System; +using CSharpNumerics.Physics.Constants; + +namespace CSharpNumerics.Physics.Relativity; + +/// +/// Geometry of the Schwarzschild solution — the spacetime around a static, +/// uncharged, spherically symmetric mass. Provides the characteristic radii +/// and the gravitational time-dilation / redshift experienced by a static +/// observer outside the mass. Masses are in kg, radii in metres. +/// +public static class Schwarzschild +{ + private const double G = PhysicsConstants.GravitationalConstant; + private const double C = PhysicsConstants.SpeedOfLight; + private const double C2 = C * C; + + /// + /// Schwarzschild (gravitational) radius r_s = 2GM/c². The event horizon of + /// a non-rotating black hole of this mass. + /// + public static double Radius(double mass) + { + if (mass < 0) throw new ArgumentOutOfRangeException(nameof(mass), "Mass must be non-negative."); + return 2.0 * G * mass / C2; + } + + /// + /// Photon-sphere radius r = 3GM/c² = 1.5·r_s, where light can orbit on + /// (unstable) circular null geodesics. + /// + public static double PhotonSphereRadius(double mass) + { + return 1.5 * Radius(mass); + } + + /// + /// Innermost stable circular orbit (ISCO) for a massive test particle, + /// r = 6GM/c² = 3·r_s. Inside this radius no stable circular orbit exists. + /// + public static double Isco(double mass) + { + return 3.0 * Radius(mass); + } + + /// + /// Gravitational time-dilation factor dτ/dt = √(1 − r_s/r) for a static + /// observer at : their proper time runs slow + /// relative to a clock at infinity. + /// + /// Areal radius (m), must be greater than r_s. + /// Central mass (kg). + /// If r ≤ r_s. + public static double TimeDilationFactor(double radius, double mass) + { + double rs = Radius(mass); + if (radius <= rs) + throw new ArgumentOutOfRangeException(nameof(radius), + "Radius must be outside the Schwarzschild radius."); + + return Math.Sqrt(1.0 - rs / radius); + } + + /// + /// Gravitational redshift z = 1/√(1 − r_s/r) − 1 of light emitted by a + /// static source at and received at infinity. + /// + public static double Redshift(double radius, double mass) + { + return 1.0 / TimeDilationFactor(radius, mass) - 1.0; + } + + /// + /// Ratio of clock rates between two static radii, dτ(r1)/dτ(r2) + /// = √((1 − r_s/r1)/(1 − r_s/r2)). Values < 1 mean the clock at + /// runs slow relative to the upper one. + /// + public static double ClockRateRatio(double radiusLower, double radiusUpper, double mass) + { + return TimeDilationFactor(radiusLower, mass) / TimeDilationFactor(radiusUpper, mass); + } + + /// + /// Newtonian escape velocity √(2GM/r). In the Schwarzschild geometry this + /// equals c exactly at the event horizon (r = r_s). + /// + public static double EscapeVelocity(double radius, double mass) + { + if (radius <= 0) throw new ArgumentOutOfRangeException(nameof(radius), "Radius must be positive."); + return Math.Sqrt(2.0 * G * mass / radius); + } +} diff --git a/Numerics/Numerics/Physics/Relativity/SpecialRelativity.cs b/Numerics/Numerics/Physics/Relativity/SpecialRelativity.cs new file mode 100644 index 0000000..f843ef0 --- /dev/null +++ b/Numerics/Numerics/Physics/Relativity/SpecialRelativity.cs @@ -0,0 +1,150 @@ +using System; +using CSharpNumerics.Physics.Constants; + +namespace CSharpNumerics.Physics.Relativity; + +/// +/// Special-relativistic kinematics and dynamics in flat spacetime. +/// All speeds are in m/s and must be strictly below the speed of light. +/// These quantities are the foundation for the general-relativistic models +/// (Schwarzschild geometry, GPS-style clock corrections, etc.). +/// +public static class SpecialRelativity +{ + private const double C = PhysicsConstants.SpeedOfLight; + private const double C2 = C * C; + + /// + /// Lorentz factor γ = 1 / √(1 − v²/c²). + /// + /// Speed in m/s (sign is irrelevant). + /// γ ≥ 1. + /// If |v| ≥ c. + public static double LorentzFactor(double velocity) + { + double beta2 = velocity * velocity / C2; + if (beta2 >= 1.0) + throw new ArgumentOutOfRangeException(nameof(velocity), "Speed must be below the speed of light."); + + return 1.0 / Math.Sqrt(1.0 - beta2); + } + + /// + /// Time dilation: the coordinate time Δt elapsed in the rest frame while a + /// clock moving at measures proper time + /// . Δt = γ·Δτ (the moving clock runs slow). + /// + public static double TimeDilation(double properTime, double velocity) + { + return LorentzFactor(velocity) * properTime; + } + + /// + /// Length contraction: the length L = L₀/γ measured for an object whose + /// proper (rest-frame) length is when it + /// moves at along the measured direction. + /// + public static double LengthContraction(double properLength, double velocity) + { + return properLength / LorentzFactor(velocity); + } + + /// + /// Relativistic momentum p = γ·m·v. + /// + public static double Momentum(double mass, double velocity) + { + return LorentzFactor(velocity) * mass * velocity; + } + + /// + /// Rest energy E₀ = m·c². + /// + public static double RestEnergy(double mass) + { + return mass * C2; + } + + /// + /// Total relativistic energy E = γ·m·c². + /// + public static double TotalEnergy(double mass, double velocity) + { + return LorentzFactor(velocity) * mass * C2; + } + + /// + /// Relativistic kinetic energy E_k = (γ − 1)·m·c². + /// Evaluated as m·c²·β²/(s·(1 + s)) with s = √(1 − β²), which is + /// algebraically identical to (γ − 1)·m·c² but avoids the catastrophic + /// cancellation of computing γ − 1 directly at low speeds (where it + /// correctly reduces to the classical ½·m·v²). + /// + public static double KineticEnergy(double mass, double velocity) + { + double beta2 = velocity * velocity / C2; + if (beta2 >= 1.0) + throw new ArgumentOutOfRangeException(nameof(velocity), "Speed must be below the speed of light."); + + double s = Math.Sqrt(1.0 - beta2); + return mass * C2 * beta2 / (s * (1.0 + s)); + } + + /// + /// Total energy from the energy–momentum relation E = √((p·c)² + (m·c²)²). + /// + public static double EnergyFromMomentum(double mass, double momentum) + { + double pc = momentum * C; + double mc2 = mass * C2; + return Math.Sqrt(pc * pc + mc2 * mc2); + } + + /// + /// Relativistic velocity addition: combines two collinear velocities + /// s = (u + v) / (1 + u·v/c²). The result is always below c when both + /// inputs are. + /// + public static double AddVelocities(double u, double v) + { + return (u + v) / (1.0 + u * v / C2); + } + + /// + /// Relativistic longitudinal Doppler factor f_observed / f_source for purely + /// radial motion: √((1 − β)/(1 + β)), with β = v/c. + /// + /// Radial speed in m/s. Positive = receding (redshift), + /// negative = approaching (blueshift). + public static double DopplerFactor(double velocity) + { + double beta = velocity / C; + if (Math.Abs(beta) >= 1.0) + throw new ArgumentOutOfRangeException(nameof(velocity), "Speed must be below the speed of light."); + + return Math.Sqrt((1.0 - beta) / (1.0 + beta)); + } + + /// + /// Observed frequency under the relativistic longitudinal Doppler effect. + /// + /// Emitted frequency (Hz). + /// Radial speed in m/s. Positive = receding. + public static double ObservedFrequency(double sourceFrequency, double velocity) + { + return sourceFrequency * DopplerFactor(velocity); + } + + /// + /// Rapidity φ = artanh(v/c), the additive measure of velocity + /// (rapidities add linearly under collinear boosts). + /// + public static double Rapidity(double velocity) + { + double beta = velocity / C; + if (Math.Abs(beta) >= 1.0) + throw new ArgumentOutOfRangeException(nameof(velocity), "Speed must be below the speed of light."); + + return 0.5 * Math.Log((1.0 + beta) / (1.0 - beta)); + } +} From 255ad68b3c323cf21c6a6c8b32406eadc2c2ca18 Mon Sep 17 00:00:00 2001 From: backlundtransform Date: Mon, 22 Jun 2026 17:19:10 +0200 Subject: [PATCH 2/3] docs(physics): document the Relativity module in Physics/README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a Relativity section (special relativity, Schwarzschild geometry, classical GR tests) matching the existing per-module style, with worked examples and the known reference values (γ at 0.8c, Sun's Schwarzschild radius, Mercury ~43"/century, 1.75" light deflection). Co-Authored-By: Claude Opus 4.8 (1M context) --- Numerics/Numerics/Physics/README.md | 103 ++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/Numerics/Numerics/Physics/README.md b/Numerics/Numerics/Physics/README.md index 5df54fe..bd2649a 100644 --- a/Numerics/Numerics/Physics/README.md +++ b/Numerics/Numerics/Physics/README.md @@ -692,6 +692,109 @@ double esiVenus = AstronomyExtensions.CalculateEsi(0.95, 0.95, 0.93, 737); // --- +## 🌌 Relativity + +The `Physics.Relativity` namespace covers **special relativity** (flat-spacetime kinematics and dynamics) and **weak-field general relativity** (Schwarzschild geometry and the classical tests of GR). Speeds are in m/s, masses in kg, lengths in metres, angles in radians. + +### Special Relativity + +```csharp +using CSharpNumerics.Physics.Relativity; +using CSharpNumerics.Physics.Constants; + +double c = PhysicsConstants.SpeedOfLight; + +// Lorentz factor γ = 1/√(1 − v²/c²) +double gamma = SpecialRelativity.LorentzFactor(0.8 * c); // 5/3 ≈ 1.6667 + +// Time dilation: coordinate time for 1 s of proper time at 0.8c +double dt = SpecialRelativity.TimeDilation(1.0, 0.8 * c); // 1.6667 s + +// Length contraction: L = L₀/γ +double L = SpecialRelativity.LengthContraction(1.0, 0.8 * c); // 0.6 m + +// Momentum and energy +double p = SpecialRelativity.Momentum(mass: 1.0, velocity: 0.9 * c); // γmv +double E0 = SpecialRelativity.RestEnergy(1.0); // mc² +double E = SpecialRelativity.TotalEnergy(1.0, 0.9 * c); // γmc² +double Ek = SpecialRelativity.KineticEnergy(1.0, 0.9 * c); // (γ−1)mc² +double Ep = SpecialRelativity.EnergyFromMomentum(1.0, p); // √((pc)²+(mc²)²) + +// Relativistic velocity addition — never exceeds c +double s = SpecialRelativity.AddVelocities(0.5 * c, 0.5 * c); // 0.8c + +// Longitudinal Doppler (positive velocity = receding → redshift) +double factor = SpecialRelativity.DopplerFactor(0.6 * c); // 0.5 +double fObs = SpecialRelativity.ObservedFrequency(1.0e9, 0.6 * c); // 0.5 GHz + +// Rapidity — adds linearly under collinear boosts +double phi = SpecialRelativity.Rapidity(0.6 * c); +``` + +> `KineticEnergy` is evaluated as `mc²·β²/(s(1+s))` with `s = √(1−β²)` — algebraically identical to `(γ−1)mc²` but free of the catastrophic cancellation the direct form suffers at low speeds (where it correctly reduces to ½mv²). + +### Schwarzschild Geometry + +Geometry around a static, uncharged, spherically symmetric mass. + +```csharp +using CSharpNumerics.Physics.Relativity; +using CSharpNumerics.Physics.Constants; + +double M = PhysicsConstants.SolarMass; + +// Characteristic radii +double rs = Schwarzschild.Radius(M); // 2GM/c² ≈ 2953 m (Sun) +double rPh = Schwarzschild.PhotonSphereRadius(M); // 1.5·rs +double rIsco = Schwarzschild.Isco(M); // 3·rs (= 6GM/c²) + +// Gravitational time dilation & redshift for a static observer at radius r +double r = 7.0e8; +double dtau_dt = Schwarzschild.TimeDilationFactor(r, M); // √(1 − rs/r) +double z = Schwarzschild.Redshift(r, M); // 1/√(1−rs/r) − 1 + +// Clock-rate ratio between two radii (the lower clock runs slow) +double ratio = Schwarzschild.ClockRateRatio(radiusLower: 1e7, radiusUpper: 1e9, mass: M); + +// Escape velocity √(2GM/r) — equals c exactly at the horizon +double vEsc = Schwarzschild.EscapeVelocity(rs, M); // = c +``` + +### Classical Tests of General Relativity + +Weak-field effects: perihelion precession, light deflection, and the Shapiro delay. + +```csharp +using CSharpNumerics.Physics.Relativity; +using CSharpNumerics.Physics.Constants; + +double M = PhysicsConstants.SolarMass; + +// Perihelion precession Δϖ = 6πGM / (c²·a(1−e²)) +double perOrbit = GeneralRelativity.PerihelionPrecessionPerOrbit( + semiMajorAxis: 5.79e10, eccentricity: 0.2056, centralMass: M); // ≈ 5.0e-7 rad/orbit + +double arcsecPerCentury = GeneralRelativity.PerihelionPrecessionArcsecPerCentury( + 5.79e10, 0.2056, M, orbitalPeriodDays: 87.969); // ≈ 43″ (Mercury) + +// Light deflection α = 4GM / (c²·b) +double deflection = GeneralRelativity.LightDeflection( + impactParameter: 6.957e8, centralMass: M); // ≈ 1.75″ at the Sun's limb + +// Shapiro time delay for a signal grazing the mass +double au = PhysicsConstants.AstronomicalUnit; +double delay = GeneralRelativity.ShapiroDelay( + r1: au, r2: au, impactParameter: 6.957e8, centralMass: M); +``` + +| Class | Covers | +|-------|--------| +| `SpecialRelativity` | Lorentz factor, time dilation, length contraction, momentum/energy, velocity addition, Doppler, rapidity | +| `Schwarzschild` | gravitational radius, photon sphere, ISCO, time-dilation factor & redshift, clock-rate ratio, escape velocity | +| `GeneralRelativity` | perihelion precession, light deflection, Shapiro delay | + +--- + ## 🔄 Oscillations The `Physics.Oscillations` namespace provides one-dimensional oscillator models with both **analytic** and **numerical** solutions. All oscillators implement `IOscillator` for a consistent API. From b9379f2623b437f17dd5e7802ff7218c01976cfb Mon Sep 17 00:00:00 2001 From: backlundtransform Date: Wed, 24 Jun 2026 11:36:57 +0200 Subject: [PATCH 3/3] update git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b02de1b..f93f341 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ _ReSharper*/ .vs/ #Nuget packages folder packages/ +/.claude/settings.json