# 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*