Phase 3.3: Multi-objective optimization fix, updated docs & Claude skill

- 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>
This commit is contained in:
2025-11-24 07:49:48 -05:00
parent f76bd52894
commit dd7f0c0f82
7 changed files with 1529 additions and 220 deletions

View File

@@ -1,5 +1,8 @@
# 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.
@@ -7,10 +10,11 @@ When the user provides a request, break it down into atomic workflow steps and c
## Step Types
**1. ENGINEERING FEATURES** - Complex FEA/CAE operations needing specialized knowledge:
- Extract results from OP2 files (displacement, stress, strain, element forces, etc.)
- Extract results from OP2 files using centralized extractors
- Modify FEA properties (CBUSH/CBAR stiffness, PCOMP layup, material properties)
- Run simulations (SOL101, SOL103, etc.)
- 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
@@ -23,18 +27,179 @@ When the user provides a request, break it down into atomic workflow steps and c
- Filtering/aggregation logic
**4. OPTIMIZATION** - Algorithm and configuration:
- Optuna, genetic algorithm, etc.
- Single-objective: Optuna TPE, CMA-ES, Random Search
- Multi-objective: NSGA-II (Protocol 11), NSGA-III, MOEA/D
- Design variables and their ranges
- Multi-objective vs single objective
- 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
- "extract forces from 1D elements" → ENGINEERING FEATURE (needs pyNastran/OP2 knowledge)
- "find average of forces" → INLINE CALCULATION (simple Python: sum/len)
- "compare max to average and create metric" → POST-PROCESSING HOOK (custom logic)
- Element forces vs Reaction forces are DIFFERENT (element internal forces vs nodal reactions)
- CBUSH vs CBAR are different element types with different properties
- Extract from OP2 vs Read from .prt expression are different domains
### 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
@@ -44,80 +209,125 @@ Return a detailed JSON analysis with this structure:
{
"engineering_features": [
{
"action": "extract_1d_element_forces",
"action": "extract_frequency",
"domain": "result_extraction",
"description": "Extract element forces from 1D elements (CBAR) in Z direction from OP2 file",
"description": "Extract fundamental frequency from modal analysis using centralized extractor",
"params": {
"element_types": ["CBAR"],
"result_type": "element_force",
"direction": "Z"
"extractor": "extract_frequency",
"op2_file": "solution_2.op2",
"subcase": 1,
"mode_number": 1
},
"why_engineering": "Requires pyNastran library and OP2 file format knowledge"
"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": "calculate_average",
"description": "Calculate average of extracted forces",
"action": "convert_units",
"description": "Convert mass from kg to grams",
"params": {
"input": "forces_z",
"operation": "mean"
"input": "mass_kg",
"operation": "multiply",
"factor": 1000.0
},
"code_hint": "avg = sum(forces_z) / len(forces_z)"
},
{
"action": "find_minimum",
"description": "Find minimum force value",
"params": {
"input": "forces_z",
"operation": "min"
},
"code_hint": "min_val = min(forces_z)"
}
],
"post_processing_hooks": [
{
"action": "custom_objective_metric",
"description": "Compare minimum to average and create objective metric to minimize",
"params": {
"inputs": ["min_force", "avg_force"],
"formula": "min_force / avg_force",
"objective": "minimize"
},
"why_hook": "Custom business logic that combines multiple calculations"
"code_hint": "mass_g = mass_kg * 1000.0"
}
],
"post_processing_hooks": [],
"optimization": {
"algorithm": "genetic_algorithm",
"protocol": "protocol_11_multi_objective",
"algorithm": "NSGAIISampler",
"type": "multi_objective",
"design_variables": [
{
"parameter": "cbar_stiffness_x",
"type": "FEA_property",
"element_type": "CBAR",
"direction": "X"
"parameter": "beam_thickness",
"type": "NX_expression",
"bounds": [5.0, 10.0],
"unit": "mm"
}
],
"objectives": [
{
"name": "mass",
"type": "minimize",
"target": "custom_objective_metric"
"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": 5,
"engineering_needed": 1,
"auto_generate": 4,
"research_needed": ["1D element force extraction", "Genetic algorithm implementation"]
"total_steps": 3,
"engineering_needed": 2,
"auto_generate": 1,
"uses_centralized_extractors": true,
"multi_objective": true,
"multi_solution_workflow": true,
"research_needed": []
}
}
```
Be intelligent about:
- Distinguishing element types (CBUSH vs CBAR vs CBEAM)
- Directions (X vs Y vs Z)
- Metrics (min vs max vs average)
- Algorithms (Optuna TPE vs genetic algorithm vs gradient-based)
- Data sources (OP2 file vs .prt expression vs .fem file)
## Analysis Guidelines
Return ONLY the JSON analysis, no other text.
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.