# Example: Trajectory-Based Optimization for M1 Mirror # ===================================================== # # This config uses the Zernike Trajectory Method for mode-specific optimization. # Instead of weighted RMS at discrete angles, we optimize integrated metrics # across the full 20°-60° operating range. # # Recommended optimizer: SAT (Surrogate-Assisted Tuning) # - Handles expensive FEA evaluations efficiently # - Good for 10-20 design variables # - Builds surrogate model for intelligent sampling study: name: "M1_Trajectory_SAT3" description: "Mode-specific optimization using Zernike trajectory metrics" optimizer: type: sat # Surrogate-Assisted Tuning config: n_initial: 20 # Initial random samples n_iterations: 100 # Total iterations surrogate: gp # Gaussian Process surrogate acquisition: ei # Expected Improvement # Alternative: TPE (faster, good for single objective) # optimizer: # type: tpe # config: # n_trials: 150 # n_startup_trials: 20 # ============================================================================= # DESIGN VARIABLES # ============================================================================= # These are your wiffle tree and geometry parameters. # Adjust ranges based on your current best design. design_variables: # Wiffle tree radial positions (mm) - id: dv_wiffle_r1 name: "Wiffle R1 (inner ring)" type: continuous bounds: [180, 220] - id: dv_wiffle_r2 name: "Wiffle R2 (middle ring)" type: continuous bounds: [320, 380] - id: dv_wiffle_r3 name: "Wiffle R3 (outer ring)" type: continuous bounds: [480, 540] # Wiffle tree angular offsets (degrees) - id: dv_wiffle_theta name: "Wiffle angular offset" type: continuous bounds: [-5, 5] # Rib geometry - id: dv_rib_thickness name: "Rib thickness" type: continuous bounds: [8, 15] # ============================================================================= # EXTRACTORS # ============================================================================= extractors: # Primary: Trajectory-based analysis (5 angles) - id: ext_trajectory name: "Zernike Trajectory" type: zernike_trajectory config: reference_angle: 20.0 # Angles auto-detected from OP2 subcase labels # Fallback: Standard Zernike (for comparison) - id: ext_zernike_40 name: "Zernike 40° vs 20°" type: zernike_opd config: subcase: "40" reference_subcase: "20" # ============================================================================= # OBJECTIVES # ============================================================================= # # RECOMMENDED: Start with total_filtered_rms_nm as single objective. # Once you find a good region, switch to multi-objective with mode-specific. objectives: # PRIMARY: Total integrated RMS (single number for optimizer) - id: obj_total name: "Total Integrated RMS" source: extractor_id: ext_trajectory output_name: total_filtered_rms_nm direction: minimize weight: 1.0 # SECONDARY: Coma (almost entirely lateral-driven) # Useful if you want to specifically target coma reduction - id: obj_coma name: "Coma Integrated RMS" source: extractor_id: ext_trajectory output_name: coma_rms_nm direction: minimize weight: 0.0 # Set to 0 for logging only, increase for multi-objective # SECONDARY: Astigmatism - id: obj_astig name: "Astigmatism Integrated RMS" source: extractor_id: ext_trajectory output_name: astigmatism_rms_nm direction: minimize weight: 0.0 # ============================================================================= # CONSTRAINTS # ============================================================================= constraints: # Model quality check: R² should stay high - id: con_r2 name: "Linear fit quality" source: extractor_id: ext_trajectory output_name: linear_fit_r2 type: hard operator: ">=" threshold: 0.95 # Performance constraint from requirements - id: con_wfe_40 name: "WFE at 40° < 14nm" source: extractor_id: ext_zernike_40 output_name: filtered_rms_nm type: hard operator: "<=" threshold: 14.0 # ============================================================================= # EXECUTION # ============================================================================= execution: # NX journal for FEA journal: "nx_journals/run_fea_multi_subcase.py" # Subcases to solve (must include all trajectory angles) subcases: [90, 20, 30, 40, 50, 60] # Timeout per iteration timeout_seconds: 600 # Parallelism (if NX licenses available) parallel: 1