Overview & Extraction Notes
This page documents the extraction methodology and technical context for the 1980 Spacetrack Report No. 3 — the canonical reference for the SGP4, SDP4, SGP, SGP8, and SDP8 satellite propagation models. The report contains both the mathematical theory and the FORTRAN IV source code that implements it.
Extraction Inventory
Section titled “Extraction Inventory”Chapters (17 files)
Section titled “Chapters (17 files)”Vision-based transcription from 300 DPI page images (91 pages, approximately 25 MB of source imagery). All equations were transcribed to LaTeX, all tables to markdown.
| File | Content |
|---|---|
00-title.md | Title page, authors, distribution |
01-introduction.md | Purpose and scope |
02-propagation-models.md | Model overview and selection criteria |
03-compatibility.md | Element set compatibility requirements |
04-general-description.md | Mathematical framework |
05-sgp-model.md | Simplified General Perturbations |
06-sgp4-model.md | SGP4 (Brouwer mean elements) |
07-sdp4-model.md | SDP4 (deep-space extension) |
08-sgp8-model.md | SGP8 (Hoots drag model) |
09-sdp8-model.md | SDP8 (deep-space with SGP8 drag) |
10-deep-space.md | DEEP subroutine theory |
11-driver-functions.md | Driver and I/O routines |
12-users-guide.md | Usage instructions |
13-test-cases.md | 25 reference test vectors |
14-sample-implementation.md | Complete FORTRAN source listing |
15-acknowledgements.md | Contributors |
16-references.md | Bibliography |
17-form.md | Standard form (DD 1473) |
FORTRAN Source (10 files + Makefile)
Section titled “FORTRAN Source (10 files + Makefile)”| File | Lines | Description |
|---|---|---|
sgp.f | 109 | SGP model (Simplified General Perturbations) |
sgp4.f | 215 | SGP4 model with Brouwer mean elements |
sdp4.f | 187 | SDP4 deep-space model (calls DEEP) |
sgp8.f | 185 | SGP8 model with Hoots drag |
sdp8.f | 226 | SDP8 deep-space model (column 72 fix applied) |
deep.f | 451 | DEEP subroutine — lunar-solar perturbations |
driver.f | 113 | Main driver program with WGS-72 constants |
actan.f | 22 | Four-quadrant arctangent |
fmod2p.f | 11 | Modulo |
thetag.f | 22 | Greenwich sidereal angle |
Makefile | — | Build configuration for gfortran |
Data Artifacts
Section titled “Data Artifacts”| File | Format | Content |
|---|---|---|
test_cases.csv | CSV | 25 reference vectors in tabular form |
test_cases.json | JSON | Same vectors with structured metadata |
constants.json | JSON | WGS-72 constants as used in the code |
symbols.json | JSON | Variable name to symbol mapping |
tle_format.md | Markdown | TLE format specification |
tle_format.json | JSON | Sub-field breakdowns including implied-decimal-with-exponent encoding |
TLE Format
Section titled “TLE Format”Both the internal G-card format (used within NORAD) and the public two-line element format were
captured. The JSON specification includes sub-field breakdowns for the implied-decimal-with-exponent
encoding scheme — the format where 66816-4 means .
The Transcription Problem
Section titled “The Transcription Problem”FORTRAN IV uses fixed-format source inherited from the 80-column punch card:
| Columns | Purpose |
|---|---|
| 1—5 | Statement labels (numeric) |
| 6 | Continuation character (any non-blank, non-zero) |
| 7—72 | Source code — the only columns the compiler reads |
| 73—80 | Sequence numbers (silently ignored by compiler) |
The column 72 boundary is the root of the problem. Anything past column 72 is silently discarded. A single extra space of indentation pushes a character from column 72 to column 73, and the compiler throws it away without warning. In monospaced text without column rulers, this boundary is completely invisible.
Historical Divergence
Section titled “Historical Divergence”Consider three organizations (A, B, C) that independently transcribed the printed source in the 1980s:
- Organization A introduces a column-shift error in the drag calculation
- Organization B makes a different transcription error in the Kepler solver
- Organization C gets a clean copy but applies a “fix” to compensate for a bug they found (which was actually a transcription artifact from a copy they received from A)
Twenty-five years later, all three have implementations that claim to be “SGP4” but produce different results. Each has accumulated compensating modifications built on top of their particular transcription errors.
The Vallado Rev-1 paper was the
reconciliation effort that documented this divergence. Our own 2026 extraction reproduced the
same class of error: a vision-based LLM transcription pushed the I in *COSI to column 73
in sdp8.f, turning a multiplication by cosine of inclination into a bare *COS function
call with no arguments. The compiler accepted it silently.
Implicit Typing and Double Precision
Section titled “Implicit Typing and Double Precision”FORTRAN IV’s implicit typing convention: variables beginning with I through N are INTEGER,
all others are REAL. The DEEP subroutine’s DPSEC entry point receives a parameter T that
must be DOUBLE PRECISION for adequate accuracy, but the implicit rules make it REAL. An
explicit DOUBLE PRECISION T declaration is required.
DECODE Statement
Section titled “DECODE Statement”The original source uses DECODE, a DEC/VAX extension for reading from in-memory character
buffers. This was replaced with standard FORTRAN 77 READ with an internal unit for portability.
CHARACTER Array Syntax
Section titled “CHARACTER Array Syntax”The original CHARACTER ABUF*80(2) places the length specifier between the variable name and
the dimension — a non-standard syntax. Modern compilers require CHARACTER*80 ABUF(2).
Hollerith Constants
Section titled “Hollerith Constants”Hollerith constants (e.g., 6HSGP4 ) are a pre-CHARACTER*N technique for storing text data
in numeric variables. The gfortran compiler still supports them when the -w flag suppresses
warnings.
Static Local Variable Allocation
Section titled “Static Local Variable Allocation”FORTRAN IV allocated all local variables statically — they persist across subroutine calls.
Without the -fno-automatic compiler flag, modern Fortran places locals on the stack, and
carefully computed coefficients in the initialization path are destroyed when the subroutine
returns and is called again for propagation.
ENTRY Point Architecture
Section titled “ENTRY Point Architecture”The DEEP subroutine uses three ENTRY points (DPINIT, DPSEC, DPPER) to provide three
distinct interfaces into a single routine that shares state through local variables. This was
an efficient design in 1980 — today it would be a module or object with methods.
Cross-Entry Dummy Argument Sharing
Section titled “Cross-Entry Dummy Argument Sharing”In FORTRAN IV, all entry points in a subroutine shared a single argument area. Calling DPINIT
would set up arguments that DPSEC could later read from the same memory locations. Modern
gfortran gives each entry point its own calling convention, breaking this assumption. The fix:
save cross-entry arguments to local variables (SIQSAV, CIQSAV, OGDSAV, TSAVE) during
initialization and read from them during secular and periodic updates.
Miscompilation at -O1 and Above
Section titled “Miscompilation at -O1 and Above”ASSIGNED GOTO
Section titled “ASSIGNED GOTO”The original code uses ASSIGNED GOTO for computed dispatch — a statement that stores a label
in an integer variable and later branches to it. This feature was removed from Fortran 95 but
remains supported by gfortran with warnings suppressed.
WGS-72 Constants
Section titled “WGS-72 Constants”The code deliberately hardcodes WGS-72 geodetic constants because TLE element sets are fitted using WGS-72. Key values:
| Constant | Symbol | Value |
|---|---|---|
| Earth radius | 6378.135 km | |
| Gravitational parameter | 398600.8 km/s | |
XJ2 | ||
XJ3 | ||
XJ4 | ||
XKE |
Model Selection
Section titled “Model Selection”The near-earth/deep-space boundary is an orbital period of 225 minutes. The threshold constant
.15625 in the code is (minutes per day). Satellites with period min
are routed to SDP4/SDP8; those below go to SGP4/SGP8.
Kepler’s Equation
Section titled “Kepler’s Equation”The iterative solver uses Newton-Raphson with a convergence tolerance of E6A = 1.0E-6 and a
hard limit of 10 iterations. For nearly circular orbits this converges in 2—3 iterations. The
Rev-1 paper documents a convergence failure
for high-eccentricity orbits () where the iteration limit was insufficient.
Compilation
Section titled “Compilation”For complete compilation instructions, compiler flags, and detailed discussion of each compatibility fix, see the FORTRAN source overview.
Test Case Validation
Section titled “Test Case Validation”All 25 reference vectors from Chapter 13 were verified against the compiled binary:
| Model | Type | Max Position Error | Max Velocity Error |
|---|---|---|---|
| SGP | Near-earth | 0.011 km | 0.000012 km/s |
| SGP4 | Near-earth | 0.001 km | 0.000001 km/s |
| SGP8 | Near-earth | 0.000 km | 0.000000 km/s |
| SDP4 | Deep-space | 1.769 km | 0.001366 km/s |
| SDP8 | Deep-space | 1.463 km | 0.000680 km/s |
Near-earth models achieve sub-meter agreement with the printed reference values. Deep-space
models show 1—2 km drift at large propagation times ( min) due to the precision
difference between our full double-precision compilation (-fdefault-real-8) and the original
mixed single/double precision arithmetic.