Neural Acceleration (MLP Surrogate): - Add run_nn_optimization.py with hybrid FEA/NN workflow - MLP architecture: 4-layer (64->128->128->64) with BatchNorm/Dropout - Three workflow modes: - --all: Sequential export->train->optimize->validate - --hybrid-loop: Iterative Train->NN->Validate->Retrain cycle - --turbo: Aggressive single-best validation (RECOMMENDED) - Turbo mode: 5000 NN trials + 50 FEA validations in ~12 minutes - Separate nn_study.db to avoid overloading dashboard Performance Results (bracket_pareto_3obj study): - NN prediction errors: mass 1-5%, stress 1-4%, stiffness 5-15% - Found minimum mass designs at boundary (angle~30deg, thick~30mm) - 100x speedup vs pure FEA exploration Protocol Operating System: - Add .claude/skills/ with Bootstrap, Cheatsheet, Context Loader - Add docs/protocols/ with operations (OP_01-06) and system (SYS_10-14) - Update SYS_14_NEURAL_ACCELERATION.md with MLP Turbo Mode docs NX Automation: - Add optimization_engine/hooks/ for NX CAD/CAE automation - Add study_wizard.py for guided study creation - Fix FEM mesh update: load idealized part before UpdateFemodel() New Study: - bracket_pareto_3obj: 3-objective Pareto (mass, stress, stiffness) - 167 FEA trials + 5000 NN trials completed - Demonstrates full hybrid workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
413 lines
12 KiB
Markdown
413 lines
12 KiB
Markdown
# Analyze Model Skill
|
|
|
|
**Last Updated**: December 6, 2025
|
|
**Version**: 2.0 - Added Comprehensive Model Introspection
|
|
|
|
You are helping the user understand their NX model's structure and identify optimization opportunities.
|
|
|
|
## Purpose
|
|
|
|
Extract and present information about an NX model to help the user:
|
|
1. Identify available parametric expressions (potential design variables)
|
|
2. Understand the simulation setup (analysis types, boundary conditions)
|
|
3. Discover material properties
|
|
4. Identify extractable results from OP2 files
|
|
5. Recommend optimization strategies based on model characteristics
|
|
|
|
## Triggers
|
|
|
|
- "analyze this model"
|
|
- "what can I optimize"
|
|
- "show me the expressions"
|
|
- "look at my NX model"
|
|
- "what parameters are available"
|
|
- "introspect my model"
|
|
- "what results are available"
|
|
|
|
## Prerequisites
|
|
|
|
- User must provide path to NX model files (.prt, .sim, .fem) or study directory
|
|
- NX must be available on the system for part/sim introspection
|
|
- OP2 introspection works without NX (pure Python)
|
|
|
|
## Information Gathering
|
|
|
|
Ask these questions if not already provided:
|
|
|
|
1. **Model Location**:
|
|
- "Where is your NX model? (path to .prt file or study directory)"
|
|
- Default: Look in `studies/*/1_setup/model/`
|
|
|
|
2. **Analysis Interest**:
|
|
- "What type of optimization are you considering?" (optional)
|
|
- This helps focus the analysis on relevant aspects
|
|
|
|
---
|
|
|
|
## MANDATORY: Model Introspection
|
|
|
|
**ALWAYS use the introspection module for comprehensive model analysis:**
|
|
|
|
```python
|
|
from optimization_engine.hooks.nx_cad.model_introspection import (
|
|
introspect_part,
|
|
introspect_simulation,
|
|
introspect_op2,
|
|
introspect_study
|
|
)
|
|
|
|
# Option 1: Introspect entire study directory (recommended)
|
|
study_info = introspect_study("studies/my_study/")
|
|
|
|
# Option 2: Introspect individual files
|
|
part_info = introspect_part("path/to/model.prt")
|
|
sim_info = introspect_simulation("path/to/model.sim")
|
|
op2_info = introspect_op2("path/to/results.op2")
|
|
```
|
|
|
|
### What Introspection Extracts
|
|
|
|
| Source | Information Extracted |
|
|
|--------|----------------------|
|
|
| `.prt` | Expressions (count, values, types), bodies, mass, material, features |
|
|
| `.sim` | Solutions, boundary conditions, loads, materials, mesh info, output requests |
|
|
| `.op2` | Available results (displacement, stress, strain, SPC forces, etc.), subcases |
|
|
|
|
### Introspection Report Generation
|
|
|
|
**MANDATORY**: Generate `MODEL_INTROSPECTION.md` for every study:
|
|
|
|
```python
|
|
# Generate and save introspection report
|
|
study_info = introspect_study(study_dir)
|
|
|
|
# Create markdown report
|
|
report = generate_introspection_report(study_info)
|
|
with open(study_dir / "MODEL_INTROSPECTION.md", "w") as f:
|
|
f.write(report)
|
|
```
|
|
|
|
---
|
|
|
|
## Execution Steps
|
|
|
|
### Step 1: Run Comprehensive Introspection
|
|
|
|
**Use the introspection module (MANDATORY)**:
|
|
|
|
```python
|
|
from optimization_engine.hooks.nx_cad.model_introspection import introspect_study
|
|
|
|
# Introspect the entire study
|
|
result = introspect_study("studies/my_study/")
|
|
|
|
if result["success"]:
|
|
# Part information
|
|
for part in result["data"]["parts"]:
|
|
print(f"Part: {part['file']}")
|
|
print(f" Expressions: {part['data'].get('expression_count', 0)}")
|
|
print(f" Bodies: {part['data'].get('body_count', 0)}")
|
|
|
|
# Simulation information
|
|
for sim in result["data"]["simulations"]:
|
|
print(f"Simulation: {sim['file']}")
|
|
print(f" Solutions: {sim['data'].get('solution_count', 0)}")
|
|
|
|
# OP2 results
|
|
for op2 in result["data"]["results"]:
|
|
print(f"OP2: {op2['file']}")
|
|
available = op2['data'].get('available_results', {})
|
|
print(f" Displacement: {available.get('displacement', False)}")
|
|
print(f" Stress: {available.get('stress', False)}")
|
|
```
|
|
|
|
### Step 2: Validate Model Files
|
|
|
|
Check that required files exist:
|
|
|
|
```python
|
|
from pathlib import Path
|
|
|
|
def validate_model_files(model_path: Path) -> dict:
|
|
"""Validate NX model files exist."""
|
|
prt_file = model_path
|
|
base_name = prt_file.stem
|
|
parent_dir = prt_file.parent
|
|
|
|
result = {
|
|
'prt_exists': prt_file.exists(),
|
|
'sim_file': None,
|
|
'fem_file': None,
|
|
'errors': []
|
|
}
|
|
|
|
# Look for simulation file
|
|
sim_patterns = [
|
|
f"{base_name}_sim1.sim",
|
|
f"{base_name}_sim.sim",
|
|
f"{base_name}.sim"
|
|
]
|
|
for pattern in sim_patterns:
|
|
sim_path = parent_dir / pattern
|
|
if sim_path.exists():
|
|
result['sim_file'] = sim_path
|
|
break
|
|
|
|
# Look for FEM file
|
|
fem_patterns = [
|
|
f"{base_name}_fem1.fem",
|
|
f"{base_name}_fem.fem",
|
|
f"{base_name}.fem"
|
|
]
|
|
for pattern in fem_patterns:
|
|
fem_path = parent_dir / pattern
|
|
if fem_path.exists():
|
|
result['fem_file'] = fem_path
|
|
break
|
|
|
|
if not result['prt_exists']:
|
|
result['errors'].append(f"Part file not found: {prt_file}")
|
|
if not result['sim_file']:
|
|
result['errors'].append("No simulation file (.sim) found")
|
|
if not result['fem_file']:
|
|
result['errors'].append("No FEM file (.fem) found - will be created on first solve")
|
|
|
|
return result
|
|
```
|
|
|
|
### Step 3: Extract Expressions (via Introspection)
|
|
|
|
The introspection module extracts expressions automatically:
|
|
|
|
```python
|
|
from optimization_engine.hooks.nx_cad.model_introspection import introspect_part
|
|
|
|
result = introspect_part("path/to/model.prt")
|
|
if result["success"]:
|
|
expressions = result["data"].get("expressions", [])
|
|
for expr in expressions:
|
|
print(f" {expr['name']}: {expr['value']} {expr.get('unit', '')}")
|
|
```
|
|
|
|
### Step 4: Classify Expressions
|
|
|
|
Categorize expressions by likely purpose:
|
|
|
|
| Pattern | Category | Optimization Relevance |
|
|
|---------|----------|----------------------|
|
|
| `*_thickness`, `*_t`, `wall_*` | Structural | High - affects mass & stiffness |
|
|
| `*_diameter`, `*_d`, `hole_*` | Geometric | High - affects mass & stress |
|
|
| `*_radius`, `*_r`, `fillet_*` | Geometric | Medium - affects stress concentration |
|
|
| `*_count`, `n_*`, `num_*` | Discrete | Medium - affects mass & complexity |
|
|
| `*_length`, `*_l`, `span_*` | Dimensional | Context-dependent |
|
|
| `*_angle`, `*_deg` | Orientation | Low-Medium |
|
|
| `material_*`, `mat_*` | Material | Special handling required |
|
|
|
|
### Step 4: Analyze Simulation Setup
|
|
|
|
If .sim file exists, analyze:
|
|
|
|
1. **Solution Types**:
|
|
- SOL 101 (Static) → Displacement, Stress
|
|
- SOL 103 (Modal) → Natural Frequencies
|
|
- SOL 105 (Buckling) → Buckling Load Factor
|
|
- SOL 106 (Nonlinear Static) → Large deformation
|
|
- SOL 112 (Transient) → Dynamic response
|
|
|
|
2. **Load Cases**: Identify applied loads and boundary conditions
|
|
|
|
3. **Material Properties**: Extract material definitions
|
|
|
|
### Step 5: Generate Recommendations
|
|
|
|
Based on analysis, recommend:
|
|
|
|
1. **Design Variables**: Which expressions are good candidates
|
|
2. **Objectives**: What can be optimized
|
|
3. **Constraints**: What should be bounded
|
|
4. **Protocol**: Which optimization protocol fits best
|
|
|
|
## Output Format
|
|
|
|
Present analysis using the **MODEL_INTROSPECTION.md** format:
|
|
|
|
```markdown
|
|
# Model Introspection Report
|
|
|
|
**Study**: {study_name}
|
|
**Generated**: {date}
|
|
**Introspection Version**: 1.0
|
|
|
|
---
|
|
|
|
## 1. Files Discovered
|
|
|
|
| Type | File | Status |
|
|
|------|------|--------|
|
|
| Part (.prt) | {prt_file} | ✓ Found |
|
|
| Simulation (.sim) | {sim_file} | ✓ Found |
|
|
| FEM (.fem) | {fem_file} | ✓ Found |
|
|
| Results (.op2) | {op2_file} | ✓ Found |
|
|
|
|
---
|
|
|
|
## 2. Part Information
|
|
|
|
### Expressions (Potential Design Variables)
|
|
|
|
| Name | Value | Unit | Type | Optimization Candidate |
|
|
|------|-------|------|------|------------------------|
|
|
| thickness | 2.0 | mm | User | ✓ High |
|
|
| hole_diameter | 10.0 | mm | User | ✓ High |
|
|
| p173_mass | 0.125 | kg | Reference | Read-only |
|
|
|
|
### Mass Properties
|
|
|
|
| Property | Value | Unit |
|
|
|----------|-------|------|
|
|
| Mass | 0.125 | kg |
|
|
| Material | Aluminum 6061-T6 | - |
|
|
|
|
---
|
|
|
|
## 3. Simulation Information
|
|
|
|
### Solutions
|
|
|
|
| Solution | Type | Nastran SOL | Status |
|
|
|----------|------|-------------|--------|
|
|
| Solution 1 | Static | SOL 101 | ✓ Active |
|
|
| Solution 2 | Modal | SOL 103 | ✓ Active |
|
|
|
|
### Boundary Conditions
|
|
|
|
| Name | Type | Applied To |
|
|
|------|------|------------|
|
|
| Fixed_Root | SPC | Face_1 |
|
|
|
|
### Loads
|
|
|
|
| Name | Type | Magnitude | Direction |
|
|
|------|------|-----------|-----------|
|
|
| Tip_Force | FORCE | 500 N | -Z |
|
|
|
|
---
|
|
|
|
## 4. Available Results (from OP2)
|
|
|
|
| Result Type | Available | Subcases |
|
|
|-------------|-----------|----------|
|
|
| Displacement | ✓ | 1 |
|
|
| SPC Forces | ✓ | 1 |
|
|
| Stress (CHEXA) | ✓ | 1 |
|
|
| Stress (CPENTA) | ✓ | 1 |
|
|
| Strain Energy | ✗ | - |
|
|
| Frequencies | ✓ | 2 |
|
|
|
|
---
|
|
|
|
## 5. Optimization Recommendations
|
|
|
|
### Suggested Objectives
|
|
|
|
| Objective | Extractor | Source |
|
|
|-----------|-----------|--------|
|
|
| Minimize mass | E4: `extract_mass_from_bdf` | .dat |
|
|
| Maximize stiffness | E1: `extract_displacement` → k=F/δ | .op2 |
|
|
|
|
### Suggested Constraints
|
|
|
|
| Constraint | Type | Threshold | Extractor |
|
|
|------------|------|-----------|-----------|
|
|
| Max stress | less_than | 250 MPa | E3: `extract_solid_stress` |
|
|
|
|
### Recommended Protocol
|
|
|
|
- **Protocol 11 (Multi-Objective NSGA-II)** - Multiple competing objectives
|
|
- Multi-Solution: **Yes** (static + modal)
|
|
|
|
---
|
|
|
|
*Ready to create optimization study? Say "create study" to proceed.*
|
|
```
|
|
|
|
### Saving the Report
|
|
|
|
**MANDATORY**: Save the introspection report to the study directory:
|
|
|
|
```python
|
|
from pathlib import Path
|
|
|
|
def save_introspection_report(study_dir: Path, report_content: str):
|
|
"""Save MODEL_INTROSPECTION.md to study directory."""
|
|
report_path = study_dir / "MODEL_INTROSPECTION.md"
|
|
with open(report_path, 'w') as f:
|
|
f.write(report_content)
|
|
print(f"Saved introspection report: {report_path}")
|
|
|
|
## Error Handling
|
|
|
|
| Error | Recovery |
|
|
|-------|----------|
|
|
| File not found | Ask user for correct path |
|
|
| Invalid NX format | Suggest checking NX version compatibility |
|
|
| No expressions found | Guide user to create expressions in NX |
|
|
| Simulation incomplete | List missing components |
|
|
|
|
## Integration with Other Skills
|
|
|
|
After analysis, can chain to:
|
|
- `/create-study` - Create optimization based on findings
|
|
- `/configure-surrogate` - Setup NN if large-scale optimization needed
|
|
|
|
## Example Conversation
|
|
|
|
```
|
|
USER: Look at my NX model at studies/uav_arm_optimization/1_setup/model/Beam.prt
|
|
|
|
CLAUDE: I'll analyze your UAV arm model. Let me examine its structure...
|
|
|
|
[Runs analysis]
|
|
|
|
MODEL ANALYSIS REPORT
|
|
=====================
|
|
Model: Beam
|
|
Location: studies/uav_arm_optimization/1_setup/model/
|
|
|
|
PARAMETRIC EXPRESSIONS
|
|
----------------------
|
|
Found 4 controllable parameters:
|
|
| Name | Value | Bounds Suggestion |
|
|
|------|-------|------------------|
|
|
| beam_half_core_thickness | 15.0 mm | [5, 25] |
|
|
| beam_face_thickness | 2.0 mm | [1, 5] |
|
|
| holes_diameter | 30.0 mm | [10, 50] |
|
|
| hole_count | 8 | [4, 12] |
|
|
|
|
SIMULATION SETUP
|
|
----------------
|
|
✓ Static Analysis (SOL 101) - for stress/displacement
|
|
✓ Modal Analysis (SOL 103) - for natural frequencies
|
|
Material: Aluminum sandwich panel
|
|
|
|
RECOMMENDATION
|
|
--------------
|
|
This model is well-suited for multi-objective optimization:
|
|
- Objective 1: Minimize mass
|
|
- Objective 2: Maximize first natural frequency
|
|
- Constraint: Keep stress below yield strength
|
|
|
|
Would you like me to create an optimization study with these settings?
|
|
|
|
USER: Yes, but add a displacement constraint of 5mm max
|
|
|
|
CLAUDE: [Invokes create-study skill with analyzed parameters + user constraint]
|
|
```
|
|
|
|
## Notes
|
|
|
|
- Expression extraction requires NX to be running or using file parsing
|
|
- Some expressions may be formula-driven (not directly editable)
|
|
- Material properties may need separate handling
|
|
- Consider mesh quality when recommending optimization bounds
|