- 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>
334 lines
9.8 KiB
Markdown
334 lines
9.8 KiB
Markdown
# 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:
|
|
|
|
1. **extract_displacement.py**
|
|
- `extract_displacement(op2_file, subcase)` → max displacement in mm
|
|
- Returns: `{'max_displacement': float, 'node_id': int}`
|
|
|
|
2. **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}`
|
|
|
|
3. **extract_frequency.py**
|
|
- `extract_frequency(op2_file, subcase, mode_number)` → frequency in Hz
|
|
- Returns: `{'frequency': float, 'mode': int, 'eigenvalue': float}`
|
|
|
|
4. **extract_mass_from_bdf.py**
|
|
- `extract_mass_from_bdf(bdf_file)` → FEM mass in kg
|
|
- Returns: `{'mass_kg': float, 'cg': [x, y, z], 'inertia': [[...]]}`
|
|
|
|
5. **extract_mass_from_expression.py**
|
|
- `extract_mass_from_expression(prt_file, expression_name)` → CAD mass in kg
|
|
- Returns: `float` (mass value from NX expression)
|
|
|
|
6. **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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
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:
|
|
|
|
```python
|
|
# ❌ 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:
|
|
|
|
```python
|
|
# ✅ 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:
|
|
|
|
1. **Parallel Coordinates Plot**
|
|
- Structure: Design Variables → Objectives → Constraints
|
|
- Color-coded axes (blue/green/yellow)
|
|
- Interactive trial selection
|
|
- Feasibility coloring (green = feasible, red = infeasible)
|
|
|
|
2. **Pareto Front Plot**
|
|
- 2D scatter for bi-objective problems
|
|
- Shows trade-offs between objectives
|
|
- Highlights non-dominated solutions
|
|
|
|
3. **Real-Time Updates**
|
|
- WebSocket connection for live monitoring
|
|
- Backend: FastAPI (port 8000)
|
|
- Frontend: React + Vite (port 3003)
|
|
|
|
### Dashboard Access:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
1. **Extractor Selection**
|
|
- Always prefer centralized extractors over custom OP2 code
|
|
- Match extractor to result type (displacement, stress, frequency, mass)
|
|
|
|
2. **Multi-Objective Optimization**
|
|
- Identify conflicting objectives requiring Pareto analysis
|
|
- Use NSGA-II for 2-3 objectives
|
|
- Use proper semantic directions (no negative values)
|
|
|
|
3. **Multi-Solution Workflows**
|
|
- Detect when static + modal analysis is needed
|
|
- Flag requirement for `SolveAllSolutions()` protocol
|
|
- Identify separate OP2 files per solution
|
|
|
|
4. **Dashboard Integration**
|
|
- Suggest parallel coordinates for high-dimensional problems
|
|
- Recommend Pareto front visualization for multi-objective
|
|
- Note real-time monitoring capability
|
|
|
|
5. **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.
|