Files
Atomizer/docs/handoff/SETUP_TRAJECTORY_OPTIMIZATION.md

209 lines
5.4 KiB
Markdown
Raw Permalink Normal View History

# Handoff: Set Up Trajectory-Based Optimization for M1 Mirror
**From:** Mario (Clawdbot)
**To:** Claude (Windows/LAC)
**Date:** 2026-01-29
**Context:** M1 GigaBIT mirror optimization using new Zernike Trajectory Method
---
## Summary
A new Zernike Trajectory extractor has been implemented and validated. It provides mode-specific optimization metrics (coma, astigmatism, trefoil, etc.) integrated across the full 20°-60° operating range instead of discrete weighted sums.
**Your task:** Set up an Atomizer optimization study using TPE optimizer with `total_filtered_rms_nm` as the primary objective, logging mode-specific metrics.
---
## What's Already Done
1.**Extractor implemented:** `optimization_engine/extractors/extract_zernike_trajectory.py`
2.**Validated on M1 model:** R² = 1.0 (physics model confirmed)
3.**Documentation:** `docs/physics/ZERNIKE_TRAJECTORY_METHOD.md`
4.**Example config:** `docs/examples/trajectory_optimization_config.yaml`
**Pull latest from Gitea:**
```bash
git pull origin main
```
---
## What You Need to Set Up
### 1. Create New Study: `SAT3_Trajectory`
Location: `studies/SAT3_Trajectory/` (or similar)
### 2. FEA Configuration
The FEA must solve **6 subcases** with these elevation angles:
- 90° (manufacturing reference)
- 20° (measurement/polishing reference)
- 30° (new - for trajectory)
- 40° (primary operational)
- 50° (new - for trajectory)
- 60° (secondary operational)
**Subcase labels in NX must be the angle numbers** (e.g., LABEL = 20, LABEL = 40, etc.)
### 3. Extractor Configuration
Use the trajectory extractor:
```yaml
extractors:
- id: ext_trajectory
name: "Zernike Trajectory"
type: zernike_trajectory
config:
reference_angle: 20.0
# Subcases auto-detected from OP2 labels
```
### 4. Objectives
**Primary objective (what optimizer minimizes):**
```yaml
objectives:
- id: obj_total
name: "Total Integrated RMS"
source:
extractor_id: ext_trajectory
output_name: total_filtered_rms_nm
direction: minimize
weight: 1.0
```
**Secondary objectives (logged but not optimized, weight=0):**
```yaml
- id: obj_coma
name: "Coma RMS"
source:
extractor_id: ext_trajectory
output_name: coma_rms_nm
direction: minimize
weight: 0.0
- id: obj_astig
name: "Astigmatism RMS"
source:
extractor_id: ext_trajectory
output_name: astigmatism_rms_nm
direction: minimize
weight: 0.0
- id: obj_trefoil
name: "Trefoil RMS"
source:
extractor_id: ext_trajectory
output_name: trefoil_rms_nm
direction: minimize
weight: 0.0
- id: obj_spherical
name: "Spherical RMS"
source:
extractor_id: ext_trajectory
output_name: spherical_rms_nm
direction: minimize
weight: 0.0
```
### 5. Optimizer Configuration
**Use TPE (recommended for fresh start):**
```yaml
optimizer:
type: tpe
config:
n_trials: 100
n_startup_trials: 15
```
### 6. Constraints (Optional but Recommended)
```yaml
constraints:
# Sanity check: linear model should fit well
- id: con_r2
name: "Trajectory fit quality"
source:
extractor_id: ext_trajectory
output_name: linear_fit_r2
type: soft
operator: ">="
threshold: 0.95
```
### 7. Design Variables
Use Antoine's existing wiffle tree and geometry parameters. Key ones likely include:
- Wiffle tree radial positions (R1, R2, R3)
- Wiffle tree angular offsets
- Rib thickness
- Back pocket geometry
- Support pad locations
**Ask Antoine for the current parameter names and ranges.**
---
## Validation Checklist
Before running optimization, verify:
- [ ] FEA solves all 6 subcases (90, 20, 30, 40, 50, 60)
- [ ] OP2 contains displacement results for all subcases
- [ ] Subcase labels in OP2 are angle numbers (check with extractor)
- [ ] Extractor returns valid results (run standalone test first)
- [ ] R² ≈ 1.0 (confirms physics model holds)
**Test command:**
```python
from optimization_engine.extractors.extract_zernike_trajectory import extract_zernike_trajectory
result = extract_zernike_trajectory('path/to/solution.op2')
print(f"R² = {result['linear_fit_r2']}")
print(f"Total RMS = {result['total_filtered_rms_nm']} nm")
print(f"Coma RMS = {result['coma_rms_nm']} nm")
```
---
## Expected Outputs
After running the extractor, you should see:
- `total_filtered_rms_nm`: ~4-10 nm (integrated across angles)
- `coma_rms_nm`: ~3-10 nm
- `astigmatism_rms_nm`: ~3-10 nm
- `linear_fit_r2`: ~1.0
During optimization, track:
- How `total_filtered_rms_nm` decreases
- Which modes (coma, astig, etc.) improve most
- Whether R² stays high (if it drops, something is wrong)
---
## Key Files to Reference
| File | Purpose |
|------|---------|
| `docs/physics/ZERNIKE_TRAJECTORY_METHOD.md` | Full method documentation |
| `docs/examples/trajectory_optimization_config.yaml` | Example config |
| `optimization_engine/extractors/extract_zernike_trajectory.py` | Extractor code |
| `2-Projects/P04-GigaBIT-M1/Technical-Analysis/Tensor_Project/TECH-SPEC-Zernike-Trajectory-Optimization.md` | Physics derivation + validation results |
---
## Questions?
If anything is unclear, the tech spec in PKM has the full physics derivation and validation results. The extractor auto-detects angles from OP2 subcase labels, so as long as the FEA is set up correctly, it should "just work."
Good luck! 🚀
---
*Handoff document by Mario (Clawdbot), 2026-01-29*