SpectraRust/CLAUDE.md
2026-03-27 11:59:23 +08:00

5.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Fortran stellar atmosphere modeling suite being refactored to Rust. Strategy: split Fortran into modules first, then incrementally rewrite in Rust.

  • TLUSTY 208: Non-LTE stellar atmosphere calculator (~50,000 lines → 304 modules)
  • SYNSPEC 54: Synthetic spectrum evaluator (~24,000 lines → 168 modules)
  • Progress: ~318 Rust modules (290 in tlusty/math, 28 in synspec/math)

Environment Variables

export TL208=/home/fmq/program/tlusty
export TLUSTY=$TL208/tl208-s54
export LINELIST=$TL208/linelist
export IRON=$TL208/irondata
export OPTABLES=$TL208/optables

Build Commands

Rust

cargo build              # Debug build
cargo build --release    # Release build
cargo test               # Run all tests (includes Fortran comparison tests)
cargo test test_expo     # Run specific test

Fortran

# Production (single file)
gfortran -O3 -fno-automatic -mcmodel=large -o tlusty/tlusty.exe tlusty/tlusty208.f
gfortran -O3 -fno-automatic -mcmodel=large -o synspec/synspec.exe synspec/synspec54.f

# Development (modular)
cd $TLUSTY/rust/tlusty/extracted && make    # Output: build/tlusty_extracted

Fortran compile flags:

  • -mcmodel=large: Required for large COMMON blocks (>2GB address space)
  • -fno-automatic: Static storage (old Fortran compatibility)
  • Never use -ffixed-line-length-none: Breaks columns 73-80 handling

Rust Architecture

src/
├── lib.rs                    # Module exports
├── tlusty/                   # TLUSTY implementation
│   ├── mod.rs               # Module exports + runner
│   ├── data.rs              # Static data arrays (BLOCK DATA)
│   ├── runner.rs            # Main program skeleton (incomplete)
│   ├── math/                # Pure math functions (290 modules)
│   │   ├── ali/             # Accelerated Lambda Iteration
│   │   ├── atomic/          # Atomic physics
│   │   ├── continuum/       # Continuum opacity
│   │   ├── eos/             # Equation of state
│   │   ├── solvers/         # Linear equation solvers
│   │   ├── special/         # Special functions (expint, voigt, etc.)
│   │   └── ...              # Other physics categories
│   ├── state/               # COMMON block translations as structs
│   │   ├── constants.rs     # Physical/math constants, array dimensions
│   │   ├── config.rs        # Runtime config
│   │   ├── atomic.rs        # Atomic/ion/level data
│   │   ├── model.rs         # Atmosphere model state (largest struct)
│   │   ├── arrays.rs        # Main linear equation arrays
│   │   ├── iterat.rs        # Iteration control
│   │   ├── alipar.rs        # ALI arrays
│   │   └── odfpar.rs        # ODF data
│   └── io/                  # Fortran-compatible I/O
│       ├── reader.rs        # Free-format input reader
│       ├── writer.rs        # Formatted output
│       ├── model.rs         # fort.7/fort.8 model files
│       ├── start.rs         # Initialization
│       └── ...              # Other I/O routines
└── synspec/                  # SYNSPEC implementation
    └── math/                # Math functions (28 modules)

Running Tests

Rust Tests

cargo test                                    # All unit tests
cargo test --test fortran_comparison          # Fortran comparison tests only

Fortran Integration Tests

# TLUSTY: H-He model test
cd $TLUSTY/tests/tlusty/hhe
$TLUSTY/tlusty/tlusty.exe < hhe35lt.5 > hhe35lt.6
cp fort.7 hhe35lt.7
diff hhe35lt.7 hhe35lt.7.bak

# SYNSPEC: spectrum test
cd $TLUSTY/tests/synspec/hhe
ln -sf $TLUSTY/data data
cp hhe35nl.7 fort.8
ln -sf fort.55.con fort.55
$TLUSTY/synspec/synspec.exe < hhe35nl.5

Refactoring Workflow

  1. Find pure functions: Check $TLUSTY/rust/tlusty/extracted/_PURE_UNITS.txt for units without COMMON dependencies
  2. Choose category: Place in appropriate src/tlusty/math/<category>/ subdirectory
  3. Translate: Create <name>.rs, add to category's mod.rs
  4. Verify: Add test case in tests/fortran_comparison.rs with Fortran reference values

Key Architecture

TLUSTY COMMON blocks (mapped to src/tlusty/state/ structs):

  • BASICS.FORconstants.rs: Array dimensions (MDEPTH=100, MFREQ=135000, MLEVEL=1134)
  • ATOMIC.FORatomic.rs: Atomic masses, abundances, energy levels
  • MODELQ.FORmodel.rs: Temperature, density, populations
  • ARRAY1.FORarrays.rs: Main linear equation arrays

SYNSPEC reads model atmosphere from fort.8, outputs spectrum to fort.7

File unit numbers (see src/tlusty/io/mod.rs):

  • Unit 5: Standard input (fort.5)
  • Unit 7: Model output (fort.7)
  • Unit 8: Model input (fort.8)

Fortran → Rust Translation Notes

Critical patterns to avoid mistakes:

  • Index conversion: Fortran 1-indexed → Rust 0-indexed. arr(i)arr[i-1], DO I=1,Nfor i in 0..n
  • Expression precedence: -LOG(X) is -(LOG(X)), not LOG(-X)
  • Decrementing loops: Use isize/i32 when loop variable may become negative
  • COMMON dependency: Check INCLUDE statements before assuming a function is pure
  • Large structs: Functions with many COMMON dependencies use lifetime structs:
    pub struct Params<'a> {
        pub input: &'a [f64],
        pub output: &'a mut [f64],
    }
    
  • Type inference: (z1 - z2).powi(2) may fail; use (z1 - z2) * (z1 - z2)
  • Test tolerance: Polynomial approximations (Abramowitz-Stegun) need relaxed tolerance (~1e-7)