# 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 ```bash 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 ```bash 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 ```bash # 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 ```bash cargo test # All unit tests cargo test --test fortran_comparison # Fortran comparison tests only ``` ### Fortran Integration Tests ```bash # 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//` subdirectory 3. **Translate**: Create `.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.FOR` → `constants.rs`: Array dimensions (`MDEPTH`=100, `MFREQ`=135000, `MLEVEL`=1134) - `ATOMIC.FOR` → `atomic.rs`: Atomic masses, abundances, energy levels - `MODELQ.FOR` → `model.rs`: Temperature, density, populations - `ARRAY1.FOR` → `arrays.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,N` → `for 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: ```rust 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)