Added JSON Schema: - optimization_engine/schemas/atomizer_spec_v2.json Migrated 28 studies to AtomizerSpec v2.0 format: - Drone_Gimbal studies (1) - M1_Mirror studies (21) - M2_Mirror studies (2) - SheetMetal_Bracket studies (4) Each atomizer_spec.json is the unified configuration containing: - Design variables with bounds and expressions - Extractors (standard and custom) - Objectives and constraints - Optimization algorithm settings - Canvas layout information
M1 Mirror Cost Reduction Optimization
TPE single-objective optimization targeting mass reduction while maintaining optical performance.
Created: 2025-12-17 Protocol: TPE (Tree-structured Parzen Estimator) with Weighted Sum Status: Ready to Run Baseline: Best design from V11-V15 campaign (Trial #725, WS=121.72)
1. Engineering Problem
1.1 Objective
Reduce the mass of the M1 telescope primary mirror while maintaining acceptable wavefront error (WFE) performance across operational elevation angles and manufacturing orientation.
1.2 Physical System
- Component: M1 Primary Mirror Assembly with whiffle-tree support
- Material: Zerodur Class 2 glass ceramic (E=91 GPa, density=2.53 g/cm³, CTE~0)
- Baseline Mass: 91.02 kg
- Loading: Self-weight gravity at multiple elevation angles
- Boundary Conditions: 18-point whiffle-tree axial support, 3-point lateral support
- Analysis Type: Linear static (Nastran SOL 101) with 4 subcases (20, 40, 60, 90 deg)
1.3 Optical Workflow
Reference: 20 deg (interferometer baseline)
Operational Tracking:
- 40 deg - 20 deg = tracking deformation at 40 deg
- 60 deg - 20 deg = tracking deformation at 60 deg
Manufacturing:
- 90 deg - 20 deg = polishing correction needed
1.4 Cost Reduction Strategy
This study explores geometry parameters that affect mass:
blank_backface_angle: Increases blank taper, reducing material volumeinner_circular_rib_dia: Controls rib structure extentwhiffle_*: Support geometry (indirect mass effect via blank shape)
2. Mathematical Formulation
2.1 Objectives
| Objective | Goal | Weight | Formula | Target | Units |
|---|---|---|---|---|---|
| Operational 40-20 | minimize | 5.0 | \text{RMS}_{filt}(Z_{40} - Z_{20}) |
4.0 | nm |
| Operational 60-20 | minimize | 5.0 | \text{RMS}_{filt}(Z_{60} - Z_{20}) |
10.0 | nm |
| Manufacturing 90-20 | minimize | 2.0 | \text{RMS}_{J1-J3}(Z_{90} - Z_{20}) |
20.0 | nm |
| Mass | minimize | 1.0 | M1_Blank part mass | - | kg |
Where:
Z_\theta= Zernike coefficients at elevation angle\theta\text{RMS}_{filt}= RMS with J1-J4 (piston, tip, tilt, defocus) removed\text{RMS}_{J1-J3}= RMS with only J1-J3 (piston, tip, tilt) removed
2.2 Weighted Sum Objective
f(\mathbf{x}) = 5 \cdot O_{40-20} + 5 \cdot O_{60-20} + 2 \cdot O_{mfg} + 1 \cdot M_{kg}
This formulation:
- Prioritizes optical performance (5+5=10 weight on tracking)
- Includes manufacturing workload (2 weight)
- Adds mass as secondary objective (1 weight)
2.3 Design Variables
| Parameter | Symbol | Bounds | Baseline | Units | Enabled | Description |
|---|---|---|---|---|---|---|
| whiffle_min | w_{min} |
[30.0, 72.0] | 58.63 | mm | Yes | Whiffle tree minimum extent |
| whiffle_outer_to_vertical | w_{ov} |
[60.0, 80.0] | 77.96 | deg | Yes | Whiffle outer to vertical angle |
| whiffle_triangle_closeness | w_{tc} |
[65.0, 80.0] | 67.33 | mm | Yes | Whiffle triangle spacing |
| blank_backface_angle | \beta |
[4.5, 5.0] | 4.50 | deg | Yes | Mirror blank backface taper |
| inner_circular_rib_dia | d_{rib} |
[480.0, 620.0] | 537.86 | mm | Yes | Inner rib diameter |
| lateral_inner_angle | \alpha_i |
[25.0, 30.0] | 27.70 | deg | No | (Fixed) |
| lateral_outer_angle | \alpha_o |
[11.0, 17.0] | 13.03 | deg | No | (Fixed) |
| lateral_outer_pivot | p_o |
[9.0, 12.0] | 11.24 | mm | No | (Fixed) |
| lateral_inner_pivot | p_i |
[5.0, 12.0] | 8.16 | mm | No | (Fixed) |
| lateral_middle_pivot | p_m |
[15.0, 27.0] | 22.88 | mm | No | (Fixed) |
| lateral_closeness | c_l |
[9.5, 12.5] | 9.84 | mm | No | (Fixed) |
Active Design Space: \mathbf{x} \in \mathbb{R}^{5} (5 enabled parameters)
3. Optimization Algorithm
3.1 TPE Configuration
| Parameter | Value | Description |
|---|---|---|
| Algorithm | TPE | Tree-structured Parzen Estimator |
| n_trials | 150 | Total FEA simulations |
| n_startup_trials | 15 | Random exploration before TPE |
| multivariate | True | Model parameter correlations |
| n_ei_candidates | 24 | Expected improvement candidates |
| gamma | 0.25 | Good/bad split threshold |
| seed | 42 | Reproducibility |
3.2 Explore/Exploit Balance
Trials 1-15: Random sampling (exploration)
Trials 16-150: TPE-guided sampling (exploitation with adaptive exploration)
TPE dynamically balances exploration vs exploitation based on:
- Parzen estimator of "good" trials (top 25%)
- Expected improvement acquisition function
- Multivariate modeling of parameter correlations
3.3 Optimization Flow
┌─────────────────────────────────────────────────────────────────────┐
│ TPE OPTIMIZATION LOOP │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ FOR trial = 1 to 150: │
│ │ │
│ ├─ 1. SAMPLE PARAMETERS │
│ │ └─ trial 1-15: Random (uniform) │
│ │ └─ trial 16+: TPE (Expected Improvement) │
│ │ │
│ ├─ 2. UPDATE NX GEOMETRY │
│ │ └─ Import expressions to M1_Blank.prt │
│ │ └─ Rebuild geometry with DoUpdate() │
│ │ │
│ ├─ 3. EXTRACT MASS │
│ │ └─ MeasureManager.NewMassProperties() │
│ │ └─ Write _temp_mass.txt │
│ │ │
│ ├─ 4. RUN FEA SIMULATION │
│ │ └─ Update FEM mesh │
│ │ └─ Solve Nastran SOL 101 (4 subcases) │
│ │ └─ Generate .op2 results │
│ │ │
│ ├─ 5. EXTRACT OBJECTIVES │
│ │ └─ Parse OP2 with ZernikeExtractor │
│ │ └─ Compute relative filtered RMS │
│ │ └─ Read mass from temp file │
│ │ │
│ ├─ 6. COMPUTE WEIGHTED SUM │
│ │ └─ WS = 5*obj40 + 5*obj60 + 2*mfg + 1*mass │
│ │ │
│ ├─ 7. ARCHIVE IF BEST │
│ │ └─ Copy iteration folder to best_design_archive/ │
│ │ │
│ └─ 8. UPDATE OPTUNA STUDY │
│ └─ Record trial value and user attributes │
│ │
│ END FOR │
│ │
│ SAVE FINAL RESULTS │
│ │
└─────────────────────────────────────────────────────────────────────┘
4. Result Extraction Methods
4.1 Zernike WFE Extraction
| Attribute | Value |
|---|---|
| Extractor | ZernikeExtractor.extract_relative() |
| Module | optimization_engine.extractors.extract_zernike |
| Source | .op2 file from NX Nastran |
| Output | nm (nanometers) |
Algorithm:
- Parse OP2 displacement results for target and reference subcases
- Fit Zernike polynomials (Noll indexing, J1-J50)
- Compute difference:
\Delta Z_j = Z_j^{target} - Z_j^{ref} - Filter low orders (J1-J4 for operational, J1-J3 for manufacturing)
- Compute RMS:
\text{RMS} = \sqrt{\sum_{j} \Delta Z_j^2}
4.2 Part Mass Extraction
| Attribute | Value |
|---|---|
| Extractor | MeasureManager.NewMassProperties() |
| Source | M1_Blank.prt (NX part file) |
| Output | kg (kilograms) |
Algorithm:
- Get all solid bodies from M1_Blank part
- Create mass properties measurement with 99% accuracy
- Extract mass from measureBodies.Mass
- Write to
_temp_mass.txtin iteration folder
Code:
# Mass extraction (in solve_simulation.py)
measureManager = part.MeasureManager
uc = part.UnitCollection
mass_units = [uc.GetBase("Area"), uc.GetBase("Volume"),
uc.GetBase("Mass"), uc.GetBase("Length")]
measureBodies = measureManager.NewMassProperties(mass_units, 0.99, bodies)
mass_kg = measureBodies.Mass
5. Baseline Design (V11-V15 Best)
5.1 Source
| Attribute | Value |
|---|---|
| Study | m1_mirror_adaptive_V14 |
| Trial | #725 |
| Iteration | iter242 |
| Source | FEA |
| Archived | 2025-12-12 |
5.2 Baseline Objectives
| Objective | Value | Target | Status |
|---|---|---|---|
| 40-20 | 5.99 nm | 4.0 nm | Above target |
| 60-20 | 13.10 nm | 10.0 nm | Above target |
| MFG | 26.28 nm | 20.0 nm | Above target |
| Mass | 91.02 kg | - | Baseline |
| Weighted Sum | 121.72 | - | - |
5.3 Baseline Parameters
| Parameter | Value | Units |
|---|---|---|
| lateral_inner_angle | 27.70 | deg |
| lateral_outer_angle | 13.03 | deg |
| lateral_outer_pivot | 11.24 | mm |
| lateral_inner_pivot | 8.16 | mm |
| lateral_middle_pivot | 22.88 | mm |
| lateral_closeness | 9.84 | mm |
| whiffle_min | 58.63 | mm |
| whiffle_outer_to_vertical | 77.96 | deg |
| whiffle_triangle_closeness | 67.33 | mm |
| blank_backface_angle | 4.31 | deg |
| inner_circular_rib_dia | 537.86 | mm |
6. Study File Structure
m1_mirror_cost_reduction/
│
├── 1_setup/ # INPUT CONFIGURATION
│ ├── model/ # NX Model Files
│ │ ├── ASSY_M1.prt # Assembly
│ │ ├── M1_Blank.prt # Mirror blank (mass source)
│ │ ├── M1_Blank_fem1.fem # FEM mesh
│ │ ├── M1_Blank_fem1_i.prt # Idealized part
│ │ ├── M1_Vertical_Support_Skeleton.prt
│ │ ├── M1_Vertical_Support_Skeleton_fem1.fem
│ │ ├── M1_Vertical_Support_Skeleton_fem1_i.prt
│ │ ├── ASSY_M1_assyfem1.afm # Assembly FEM
│ │ └── ASSY_M1_assyfem1_sim1.sim # Simulation file
│ └── optimization_config.json # Study configuration
│
├── 2_iterations/ # FEA iteration folders
│ └── iter{N}/ # Per-trial working directory
│ ├── [model files] # Copied NX files
│ ├── params.exp # Expression values
│ ├── _temp_mass.txt # Extracted mass
│ ├── _temp_part_properties.json # Full mass properties
│ ├── *.dat # Nastran input deck
│ ├── *.op2 # Results (binary)
│ ├── *.f06 # Results (text)
│ └── results/ # Processed outputs
│
├── 3_results/ # OUTPUT
│ ├── study.db # Optuna SQLite database
│ ├── optimization.log # Execution log
│ ├── optimization_summary.json # Final results summary
│ └── best_design_archive/ # Archived best designs
│ └── {timestamp}/ # Per-improvement snapshot
│ ├── [model files]
│ ├── params.exp
│ └── _archive_info.json
│
├── run_optimization.py # Main entry point
└── README.md # This documentation
7. Quick Start
7.1 Run Commands
# Navigate to study
cd C:\Users\antoi\Atomizer\studies\m1_mirror_cost_reduction
# Activate environment
conda activate atomizer
# Run optimization (150 trials)
python run_optimization.py --start --trials 150
# Resume if interrupted
python run_optimization.py --start --trials 150 --resume
# Single test trial
python run_optimization.py --test
7.2 Command Line Options
| Option | Default | Description |
|---|---|---|
--start |
- | Required to begin optimization |
--trials |
100 | Number of FEA trials to run |
--resume |
False | Resume from existing study.db |
--test |
False | Run single test trial |
8. Expected Runtime
| Phase | Time per Trial | Total (150 trials) |
|---|---|---|
| Geometry update | ~45s | ~1.9 hr |
| FEA solve | ~90s | ~3.8 hr |
| Extraction | ~15s | ~0.6 hr |
| Total | ~2.5 min | ~6-7 hours |
9. Configuration Reference
File: 1_setup/optimization_config.json
| Section | Key | Description |
|---|---|---|
optimization.algorithm |
TPE | Single-objective optimizer |
optimization.n_trials |
150 | Total trials planned |
optimization.n_startup_trials |
15 | Random exploration phase |
optimization.multivariate |
true | Model correlations |
design_variables[] |
11 params | 5 enabled, 6 fixed |
objectives[] |
4 objectives | WFE (3) + Mass (1) |
nx_settings.nx_install_path |
DesigncenterNX2512 | NX version |
10. Success Criteria
| Metric | Target | Priority |
|---|---|---|
| Mass reduction | >3 kg (to <88 kg) | Primary |
| 40-20 degradation | <2 nm increase | Secondary |
| 60-20 degradation | <3 nm increase | Secondary |
| MFG impact | Acceptable increase | Tertiary |
11. References
- Optuna Documentation: Tree-structured Parzen Estimator (TPE)
- Noll, R.J. (1976). Zernike polynomials and atmospheric turbulence. JOSA.
- V11-V15 Campaign: Previous optimization studies establishing baseline
Generated by Atomizer Framework - M1 Mirror Cost Reduction Study