- Fixed drone gimbal optimization to use proper semantic directions - Changed from ['minimize', 'minimize'] to ['minimize', 'maximize'] - Updated Claude skill (v2.0) with Phase 3.3 integration - Added centralized extractor library documentation - Added multi-objective optimization (Protocol 11) section - Added NX multi-solution protocol documentation - Added dashboard integration documentation - Fixed Pareto front degenerate issue with proper NSGA-II configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
9.8 KiB
Analyze Optimization Workflow Skill
Last Updated: November 23, 2025 Version: 2.0 - Phase 3.3 Integration
You are analyzing a structural optimization request for the Atomizer system.
When the user provides a request, break it down into atomic workflow steps and classify each step intelligently.
Step Types
1. ENGINEERING FEATURES - Complex FEA/CAE operations needing specialized knowledge:
- Extract results from OP2 files using centralized extractors
- Modify FEA properties (CBUSH/CBAR stiffness, PCOMP layup, material properties)
- Run simulations (SOL101 static, SOL103 modal, etc.)
- Create/modify geometry in NX
- Multi-solution workflows (static + modal, thermal + structural)
2. INLINE CALCULATIONS - Simple math operations (auto-generate Python):
- Calculate average, min, max, sum
- Compare values, compute ratios
- Statistical operations
3. POST-PROCESSING HOOKS - Custom calculations between FEA steps:
- Custom objective functions combining multiple results
- Data transformations
- Filtering/aggregation logic
4. OPTIMIZATION - Algorithm and configuration:
- Single-objective: Optuna TPE, CMA-ES, Random Search
- Multi-objective: NSGA-II (Protocol 11), NSGA-III, MOEA/D
- Design variables and their ranges
- Constraints and objectives
Centralized Extractor Library
Location: optimization_engine/extractors/
Use these standardized extractors instead of custom OP2 code:
Available Extractors:
-
extract_displacement.py
extract_displacement(op2_file, subcase)→ max displacement in mm- Returns:
{'max_displacement': float, 'node_id': int}
-
extract_von_mises_stress.py
extract_solid_stress(op2_file, subcase, element_type)→ max von Mises stress in MPa- Element types:
'ctetra','chexa','cquad4','ctria3' - Returns:
{'max_von_mises': float, 'element_id': int}
-
extract_frequency.py
extract_frequency(op2_file, subcase, mode_number)→ frequency in Hz- Returns:
{'frequency': float, 'mode': int, 'eigenvalue': float}
-
extract_mass_from_bdf.py
extract_mass_from_bdf(bdf_file)→ FEM mass in kg- Returns:
{'mass_kg': float, 'cg': [x, y, z], 'inertia': [[...]]}
-
extract_mass_from_expression.py
extract_mass_from_expression(prt_file, expression_name)→ CAD mass in kg- Returns:
float(mass value from NX expression)
-
op2_extractor.py (Base Class)
OP2Extractor- Base class for custom extractors- Provides common OP2 file handling and error management
Extractor Selection Guide:
- Displacement → Use
extract_displacement - Von Mises Stress (solids/shells) → Use
extract_solid_stress - Natural Frequency (modal analysis) → Use
extract_frequency - Mass (from FEM) → Use
extract_mass_from_bdf - Mass (from CAD geometry) → Use
extract_mass_from_expression
Multi-Objective Optimization (Protocol 11)
NSGA-II Configuration:
from optuna.samplers import NSGAIISampler
study = optuna.create_study(
study_name="study_name",
storage="sqlite:///study.db",
directions=['minimize', 'maximize'], # Semantic directions
sampler=NSGAIISampler()
)
Key Concepts:
- Pareto Front: Set of non-dominated solutions
- Semantic Directions:
['minimize', 'maximize']- NEVER use negative values - Trade-offs: Conflicting objectives (e.g., minimize mass vs maximize stiffness)
- Feasibility: Solutions must satisfy all constraints
- Visualization: Parallel Coordinates Plot + Pareto Front scatter plot
Multi-Objective Return Format:
def objective(trial: optuna.Trial) -> tuple:
"""
Returns:
(obj1, obj2): Tuple for NSGA-II
"""
# Extract objectives
mass = extract_mass(...) # to minimize
freq = extract_frequency(...) # to maximize
# Return POSITIVE values - directions handled by study config
return (mass, freq)
Common Pitfall - AVOID:
# ❌ WRONG: Using negative values to simulate maximization
return (mass, -frequency) # Creates degenerate Pareto front
# ✅ CORRECT: Use proper semantic directions
return (mass, frequency) # Study configured with ['minimize', 'maximize']
NX Multi-Solution Protocol
Critical Protocol: When simulations have multiple solutions (e.g., Solution 1 = Static, Solution 2 = Modal):
Required API:
# ✅ CORRECT: Use SolveAllSolutions() with Foreground mode
result = nx_solver.run_simulation(
sim_file=sim_file,
working_dir=model_dir,
expression_updates=design_vars,
solution_name=None # Solve ALL solutions
)
Why This Matters:
SolveChainOfSolutions()with Background mode only solves the first solution- Causes stale OP2 files and identical results across trials
SolveAllSolutions()ensures all solutions complete before returning- See:
docs/NX_MULTI_SOLUTION_PROTOCOL.md
Dashboard Integration
Visualization Features:
-
Parallel Coordinates Plot
- Structure: Design Variables → Objectives → Constraints
- Color-coded axes (blue/green/yellow)
- Interactive trial selection
- Feasibility coloring (green = feasible, red = infeasible)
-
Pareto Front Plot
- 2D scatter for bi-objective problems
- Shows trade-offs between objectives
- Highlights non-dominated solutions
-
Real-Time Updates
- WebSocket connection for live monitoring
- Backend: FastAPI (port 8000)
- Frontend: React + Vite (port 3003)
Dashboard Access:
# Backend
cd atomizer-dashboard/backend && python -m uvicorn api.main:app --reload
# Frontend
cd atomizer-dashboard/frontend && npm run dev
# Access: http://localhost:3003
Important Distinctions
Element Types:
- CBUSH vs CBAR vs CBEAM are different 1D elements
- CQUAD4 vs CTRIA3 are shell elements
- CTETRA vs CHEXA are solid elements
Result Types:
- Element forces vs Reaction forces are DIFFERENT
- Von Mises stress vs Principal stress
- Displacement magnitude vs Component displacement
Data Sources:
- OP2 file (FEA results) → Use extractors
- .prt expression (CAD parameters) → Use
extract_mass_from_expression - .fem/.bdf file (FEM model) → Use
extract_mass_from_bdf - Multi-solution OP2 files:
solution_1.op2,solution_2.op2
Optimization Algorithms:
- TPE (Tree-structured Parzen Estimator): Single-objective, adaptive
- NSGA-II: Multi-objective, Pareto-based
- CMA-ES: Single-objective, gradient-free
- Random Search: Baseline comparison
Output Format
Return a detailed JSON analysis with this structure:
{
"engineering_features": [
{
"action": "extract_frequency",
"domain": "result_extraction",
"description": "Extract fundamental frequency from modal analysis using centralized extractor",
"params": {
"extractor": "extract_frequency",
"op2_file": "solution_2.op2",
"subcase": 1,
"mode_number": 1
},
"why_engineering": "Uses centralized extractor library for standardized OP2 extraction"
},
{
"action": "extract_mass",
"domain": "result_extraction",
"description": "Extract mass from CAD expression p173",
"params": {
"extractor": "extract_mass_from_expression",
"prt_file": "Model.prt",
"expression_name": "p173"
},
"why_engineering": "Reads NX expression value directly from part file"
}
],
"inline_calculations": [
{
"action": "convert_units",
"description": "Convert mass from kg to grams",
"params": {
"input": "mass_kg",
"operation": "multiply",
"factor": 1000.0
},
"code_hint": "mass_g = mass_kg * 1000.0"
}
],
"post_processing_hooks": [],
"optimization": {
"protocol": "protocol_11_multi_objective",
"algorithm": "NSGAIISampler",
"type": "multi_objective",
"design_variables": [
{
"parameter": "beam_thickness",
"type": "NX_expression",
"bounds": [5.0, 10.0],
"unit": "mm"
}
],
"objectives": [
{
"name": "mass",
"type": "minimize",
"target": "mass_g",
"unit": "g"
},
{
"name": "frequency",
"type": "maximize",
"target": "fundamental_freq",
"unit": "Hz"
}
],
"constraints": [
{
"name": "max_displacement",
"type": "less_than",
"threshold": 1.5,
"unit": "mm"
}
],
"multi_solution_workflow": {
"required": true,
"solutions": ["static", "modal"],
"protocol": "SolveAllSolutions with Foreground mode"
}
},
"dashboard": {
"visualization": "parallel_coordinates + pareto_front",
"backend_port": 8000,
"frontend_port": 3003
},
"summary": {
"total_steps": 3,
"engineering_needed": 2,
"auto_generate": 1,
"uses_centralized_extractors": true,
"multi_objective": true,
"multi_solution_workflow": true,
"research_needed": []
}
}
Analysis Guidelines
Be intelligent about:
-
Extractor Selection
- Always prefer centralized extractors over custom OP2 code
- Match extractor to result type (displacement, stress, frequency, mass)
-
Multi-Objective Optimization
- Identify conflicting objectives requiring Pareto analysis
- Use NSGA-II for 2-3 objectives
- Use proper semantic directions (no negative values)
-
Multi-Solution Workflows
- Detect when static + modal analysis is needed
- Flag requirement for
SolveAllSolutions()protocol - Identify separate OP2 files per solution
-
Dashboard Integration
- Suggest parallel coordinates for high-dimensional problems
- Recommend Pareto front visualization for multi-objective
- Note real-time monitoring capability
-
Protocol Selection
- Protocol 11: Multi-objective NSGA-II
- Protocol 10: Single-objective with intelligent strategies
- Legacy: Basic single-objective TPE
Return ONLY the JSON analysis, no other text.