feat: Add Zernike GNN surrogate module and M1 mirror V12/V13 studies

This commit introduces the GNN-based surrogate for Zernike mirror optimization
and the M1 mirror study progression from V12 (GNN validation) to V13 (pure NSGA-II).

## GNN Surrogate Module (optimization_engine/gnn/)

New module for Graph Neural Network surrogate prediction of mirror deformations:

- `polar_graph.py`: PolarMirrorGraph - fixed 3000-node polar grid structure
- `zernike_gnn.py`: ZernikeGNN with design-conditioned message passing
- `differentiable_zernike.py`: GPU-accelerated Zernike fitting and objectives
- `train_zernike_gnn.py`: ZernikeGNNTrainer with multi-task loss
- `gnn_optimizer.py`: ZernikeGNNOptimizer for turbo mode (~900k trials/hour)
- `extract_displacement_field.py`: OP2 to HDF5 field extraction
- `backfill_field_data.py`: Extract fields from existing FEA trials

Key innovation: Design-conditioned convolutions that modulate message passing
based on structural design parameters, enabling accurate field prediction.

## M1 Mirror Studies

### V12: GNN Field Prediction + FEA Validation
- Zernike GNN trained on V10/V11 FEA data (238 samples)
- Turbo mode: 5000 GNN predictions → top candidates → FEA validation
- Calibration workflow for GNN-to-FEA error correction
- Scripts: run_gnn_turbo.py, validate_gnn_best.py, compute_full_calibration.py

### V13: Pure NSGA-II FEA (Ground Truth)
- Seeds 217 FEA trials from V11+V12
- Pure multi-objective NSGA-II without any surrogate
- Establishes ground-truth Pareto front for GNN accuracy evaluation
- Narrowed blank_backface_angle range to [4.0, 5.0]

## Documentation Updates

- SYS_14: Added Zernike GNN section with architecture diagrams
- CLAUDE.md: Added GNN module reference and quick start
- V13 README: Study documentation with seeding strategy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Antoine
2025-12-10 08:44:04 -05:00
parent c6f39bfd6c
commit 96b196de58
22 changed files with 8329 additions and 2 deletions

View File

@@ -0,0 +1,220 @@
{
"$schema": "Atomizer M1 Mirror Adaptive Surrogate Optimization V12",
"study_name": "m1_mirror_adaptive_V12",
"description": "V12 - Adaptive optimization with tuned hyperparameters, ensemble surrogate, and mass constraint (<99kg).",
"source_study": {
"path": "../m1_mirror_adaptive_V11",
"database": "../m1_mirror_adaptive_V11/3_results/study.db",
"model_dir": "../m1_mirror_adaptive_V11/1_setup/model",
"description": "V11 FEA data (107 samples) used for initial surrogate training"
},
"source_model_dir": "C:\\Users\\Antoine\\CADTOMASTE\\Atomizer\\M1-Gigabit\\Latest",
"design_variables": [
{
"name": "lateral_inner_angle",
"expression_name": "lateral_inner_angle",
"min": 25.0,
"max": 28.5,
"baseline": 26.79,
"units": "degrees",
"enabled": true
},
{
"name": "lateral_outer_angle",
"expression_name": "lateral_outer_angle",
"min": 13.0,
"max": 17.0,
"baseline": 14.64,
"units": "degrees",
"enabled": true
},
{
"name": "lateral_outer_pivot",
"expression_name": "lateral_outer_pivot",
"min": 9.0,
"max": 12.0,
"baseline": 10.40,
"units": "mm",
"enabled": true
},
{
"name": "lateral_inner_pivot",
"expression_name": "lateral_inner_pivot",
"min": 9.0,
"max": 12.0,
"baseline": 10.07,
"units": "mm",
"enabled": true
},
{
"name": "lateral_middle_pivot",
"expression_name": "lateral_middle_pivot",
"min": 18.0,
"max": 23.0,
"baseline": 20.73,
"units": "mm",
"enabled": true
},
{
"name": "lateral_closeness",
"expression_name": "lateral_closeness",
"min": 9.5,
"max": 12.5,
"baseline": 11.02,
"units": "mm",
"enabled": true
},
{
"name": "whiffle_min",
"expression_name": "whiffle_min",
"min": 35.0,
"max": 55.0,
"baseline": 40.55,
"units": "mm",
"enabled": true
},
{
"name": "whiffle_outer_to_vertical",
"expression_name": "whiffle_outer_to_vertical",
"min": 68.0,
"max": 80.0,
"baseline": 75.67,
"units": "degrees",
"enabled": true
},
{
"name": "whiffle_triangle_closeness",
"expression_name": "whiffle_triangle_closeness",
"min": 50.0,
"max": 65.0,
"baseline": 60.00,
"units": "mm",
"enabled": true
},
{
"name": "blank_backface_angle",
"expression_name": "blank_backface_angle",
"min": 4,
"max": 5.0,
"baseline": 4.23,
"units": "degrees",
"enabled": true
},
{
"name": "inner_circular_rib_dia",
"expression_name": "inner_circular_rib_dia",
"min": 480.0,
"max": 620.0,
"baseline": 534.00,
"units": "mm",
"enabled": true
}
],
"objectives": [
{
"name": "rel_filtered_rms_40_vs_20",
"description": "Filtered RMS WFE at 40 deg relative to 20 deg reference (operational tracking)",
"direction": "minimize",
"weight": 5.0,
"target": 4.0,
"units": "nm",
"extractor_config": {
"target_subcase": "3",
"reference_subcase": "2",
"metric": "relative_filtered_rms_nm"
}
},
{
"name": "rel_filtered_rms_60_vs_20",
"description": "Filtered RMS WFE at 60 deg relative to 20 deg reference (operational tracking)",
"direction": "minimize",
"weight": 5.0,
"target": 10.0,
"units": "nm",
"extractor_config": {
"target_subcase": "4",
"reference_subcase": "2",
"metric": "relative_filtered_rms_nm"
}
},
{
"name": "mfg_90_optician_workload",
"description": "Manufacturing deformation at 90 deg polishing (J1-J3 filtered RMS)",
"direction": "minimize",
"weight": 1.0,
"target": 20.0,
"units": "nm",
"extractor_config": {
"target_subcase": "1",
"reference_subcase": "2",
"metric": "relative_rms_filter_j1to3"
}
}
],
"zernike_settings": {
"n_modes": 50,
"filter_low_orders": 4,
"displacement_unit": "mm",
"subcases": ["1", "2", "3", "4"],
"subcase_labels": {"1": "90deg", "2": "20deg", "3": "40deg", "4": "60deg"},
"reference_subcase": "2"
},
"constraints": [
{
"name": "mass_limit",
"type": "upper_bound",
"expression_name": "p173",
"max_value": 99.0,
"units": "kg",
"description": "Mirror assembly mass must be under 99kg",
"penalty_weight": 100.0,
"influenced_by": ["blank_backface_angle"]
}
],
"adaptive_settings": {
"max_iterations": 100,
"surrogate_trials_per_iter": 1000,
"fea_batch_size": 5,
"strategy": "hybrid",
"exploration_ratio": 0.3,
"convergence_threshold_nm": 0.3,
"patience": 5,
"min_training_samples": 30,
"retrain_epochs": 300
},
"surrogate_settings": {
"model_type": "ZernikeSurrogate",
"hidden_dims": [128, 256, 256, 128, 64],
"dropout": 0.1,
"learning_rate": 0.001,
"batch_size": 16,
"mc_dropout_samples": 30
},
"nx_settings": {
"nx_install_path": "C:\\Program Files\\Siemens\\NX2506",
"sim_file": "ASSY_M1_assyfem1_sim1.sim",
"solution_name": "Solution 1",
"op2_pattern": "*-solution_1.op2",
"simulation_timeout_s": 900,
"journal_timeout_s": 120,
"op2_timeout_s": 1800,
"auto_start_nx": true
},
"dashboard_settings": {
"trial_source_tag": true,
"fea_marker": "circle",
"nn_marker": "cross",
"fea_color": "#2196F3",
"nn_color": "#FF9800"
}
}