Files
Atomizer/.claude/skills/modules/extractors-catalog.md
Antoine 602560c46a feat: Add MLP surrogate with Turbo Mode for 100x faster optimization
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>
2025-12-06 20:01:59 -05:00

290 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Extractors Catalog Module
**Last Updated**: December 5, 2025
**Version**: 1.0
**Type**: Optional Module
This module documents all available extractors in the Atomizer framework. Load this when the user asks about result extraction or needs to understand what extractors are available.
---
## When to Load
- User asks "what extractors are available?"
- User needs to extract results from OP2/BDF files
- Setting up a new study with custom extraction needs
- Debugging extraction issues
---
## PR.1 Extractor Catalog
| ID | Extractor | Module | Function | Input | Output | Returns |
|----|-----------|--------|----------|-------|--------|---------|
| E1 | **Displacement** | `optimization_engine.extractors.extract_displacement` | `extract_displacement(op2_file, subcase=1)` | `.op2` | mm | `{'max_displacement': float, 'max_disp_node': int, 'max_disp_x/y/z': float}` |
| E2 | **Frequency** | `optimization_engine.extractors.extract_frequency` | `extract_frequency(op2_file, subcase=1, mode_number=1)` | `.op2` | Hz | `{'frequency': float, 'mode_number': int, 'eigenvalue': float, 'all_frequencies': list}` |
| E3 | **Von Mises Stress** | `optimization_engine.extractors.extract_von_mises_stress` | `extract_solid_stress(op2_file, subcase=1, element_type='cquad4')` | `.op2` | MPa | `{'max_von_mises': float, 'max_stress_element': int}` |
| E4 | **BDF Mass** | `optimization_engine.extractors.bdf_mass_extractor` | `extract_mass_from_bdf(bdf_file)` | `.dat`/`.bdf` | kg | `float` (mass in kg) |
| E5 | **CAD Expression Mass** | `optimization_engine.extractors.extract_mass_from_expression` | `extract_mass_from_expression(prt_file, expression_name='p173')` | `.prt` + `_temp_mass.txt` | kg | `float` (mass in kg) |
| E6 | **Field Data** | `optimization_engine.extractors.field_data_extractor` | `FieldDataExtractor(field_file, result_column, aggregation)` | `.fld`/`.csv` | varies | `{'value': float, 'stats': dict}` |
| E7 | **Stiffness** | `optimization_engine.extractors.stiffness_calculator` | `StiffnessCalculator(field_file, op2_file, force_component, displacement_component)` | `.fld` + `.op2` | N/mm | `{'stiffness': float, 'displacement': float, 'force': float}` |
| E11 | **Part Mass & Material** | `optimization_engine.extractors.extract_part_mass_material` | `extract_part_mass_material(prt_file)` | `.prt` | kg + dict | `{'mass_kg': float, 'volume_mm3': float, 'material': {'name': str}, ...}` |
**For Zernike extractors (E8-E10)**, see the [zernike-optimization module](./zernike-optimization.md).
---
## PR.2 Extractor Code Snippets (COPY-PASTE)
### E1: Displacement Extraction
```python
from optimization_engine.extractors.extract_displacement import extract_displacement
disp_result = extract_displacement(op2_file, subcase=1)
max_displacement = disp_result['max_displacement'] # mm
max_node = disp_result['max_disp_node'] # Node ID
```
**Return Dictionary**:
```python
{
'max_displacement': 0.523, # Maximum magnitude (mm)
'max_disp_node': 1234, # Node ID with max displacement
'max_disp_x': 0.123, # X component at max node
'max_disp_y': 0.456, # Y component at max node
'max_disp_z': 0.234 # Z component at max node
}
```
### E2: Frequency Extraction
```python
from optimization_engine.extractors.extract_frequency import extract_frequency
# Get first mode frequency
freq_result = extract_frequency(op2_file, subcase=1, mode_number=1)
frequency = freq_result['frequency'] # Hz
# Get all frequencies
all_freqs = freq_result['all_frequencies'] # List of all mode frequencies
```
**Return Dictionary**:
```python
{
'frequency': 125.4, # Requested mode frequency (Hz)
'mode_number': 1, # Mode number requested
'eigenvalue': 6.21e5, # Eigenvalue (rad/s)^2
'all_frequencies': [125.4, 234.5, 389.2, ...] # All mode frequencies
}
```
### E3: Stress Extraction
```python
from optimization_engine.extractors.extract_von_mises_stress import extract_solid_stress
# For shell elements (CQUAD4, CTRIA3)
stress_result = extract_solid_stress(op2_file, subcase=1, element_type='cquad4')
# For solid elements (CTETRA, CHEXA)
stress_result = extract_solid_stress(op2_file, subcase=1, element_type='ctetra')
max_stress = stress_result['max_von_mises'] # MPa
```
**Return Dictionary**:
```python
{
'max_von_mises': 187.5, # Maximum von Mises stress (MPa)
'max_stress_element': 5678, # Element ID with max stress
'mean_stress': 45.2, # Mean stress across all elements
'stress_distribution': {...} # Optional: full distribution data
}
```
### E4: BDF Mass Extraction
```python
from optimization_engine.extractors.bdf_mass_extractor import extract_mass_from_bdf
mass_kg = extract_mass_from_bdf(str(dat_file)) # kg
```
**Note**: Calculates mass from element properties and material density in the BDF/DAT file.
### E5: CAD Expression Mass
```python
from optimization_engine.extractors.extract_mass_from_expression import extract_mass_from_expression
mass_kg = extract_mass_from_expression(model_file, expression_name="p173") # kg
```
**Note**: Requires `_temp_mass.txt` to be written by solve journal. The expression name is the NX expression that contains the mass value.
### E6: Field Data Extraction
```python
from optimization_engine.extractors.field_data_extractor import FieldDataExtractor
# Create extractor
extractor = FieldDataExtractor(
field_file="results.fld",
result_column="Temperature",
aggregation="max" # or "min", "mean", "sum"
)
result = extractor.extract()
value = result['value'] # Aggregated value
stats = result['stats'] # Full statistics
```
### E7: Stiffness Calculation
```python
# Simple stiffness from displacement (most common)
applied_force = 1000.0 # N - MUST MATCH YOUR MODEL'S APPLIED LOAD
stiffness = applied_force / max(abs(max_displacement), 1e-6) # N/mm
# Or using StiffnessCalculator for complex cases
from optimization_engine.extractors.stiffness_calculator import StiffnessCalculator
calc = StiffnessCalculator(
field_file="displacement.fld",
op2_file="results.op2",
force_component="Fz",
displacement_component="Tz"
)
result = calc.calculate()
stiffness = result['stiffness'] # N/mm
```
### E11: Part Mass & Material Extraction
```python
from optimization_engine.extractors import extract_part_mass_material, extract_part_mass
# Full extraction with all properties
result = extract_part_mass_material(prt_file)
mass_kg = result['mass_kg'] # kg
volume = result['volume_mm3'] # mm³
area = result['surface_area_mm2'] # mm²
cog = result['center_of_gravity_mm'] # [x, y, z] mm
material = result['material']['name'] # e.g., "Aluminum_2014"
# Simple mass-only extraction
mass_kg = extract_part_mass(prt_file) # kg
```
**Return Dictionary**:
```python
{
'mass_kg': 0.1098, # Mass in kg
'mass_g': 109.84, # Mass in grams
'volume_mm3': 39311.99, # Volume in mm³
'surface_area_mm2': 10876.71, # Surface area in mm²
'center_of_gravity_mm': [0, 42.3, 39.6], # CoG in mm
'material': {
'name': 'Aluminum_2014', # Material name (or None)
'density': None, # Density if available
'density_unit': 'kg/mm^3'
},
'num_bodies': 1 # Number of solid bodies
}
```
**Prerequisites**: Run the NX journal first to create the temp file:
```bash
run_journal.exe nx_journals/extract_part_mass_material.py -args model.prt
```
---
## Extractor Selection Guide
| Need | Extractor | When to Use |
|------|-----------|-------------|
| Max deflection | E1 | Static analysis displacement check |
| Natural frequency | E2 | Modal analysis, resonance avoidance |
| Peak stress | E3 | Strength validation, fatigue life |
| FEM mass | E4 | When mass is from mesh elements |
| CAD mass | E5 | When mass is from NX expression |
| Temperature/Custom | E6 | Thermal or custom field results |
| k = F/δ | E7 | Stiffness maximization |
| Wavefront error | E8-E10 | Telescope/mirror optimization |
| Part mass + material | E11 | Direct from .prt file with material info |
---
## Engineering Result Types
| Result Type | Nastran SOL | Output File | Extractor |
|-------------|-------------|-------------|-----------|
| Static Stress | SOL 101 | `.op2` | E3: `extract_solid_stress` |
| Displacement | SOL 101 | `.op2` | E1: `extract_displacement` |
| Natural Frequency | SOL 103 | `.op2` | E2: `extract_frequency` |
| Buckling Load | SOL 105 | `.op2` | `extract_buckling` |
| Modal Shapes | SOL 103 | `.op2` | `extract_mode_shapes` |
| Mass | - | `.dat`/`.bdf` | E4: `bdf_mass_extractor` |
| Stiffness | SOL 101 | `.fld` + `.op2` | E7: `stiffness_calculator` |
---
## Common Objective Formulations
### Stiffness Maximization
- k = F/δ (force/displacement)
- Maximize k or minimize 1/k (compliance)
- Requires consistent load magnitude across trials
### Mass Minimization
- Extract from BDF element properties + material density
- Units: typically kg (NX uses kg-mm-s)
### Stress Constraints
- Von Mises < σ_yield / safety_factor
- Account for stress concentrations
### Frequency Constraints
- f₁ > threshold (avoid resonance)
- Often paired with mass minimization
---
## Adding New Extractors
When the study needs result extraction not covered by existing extractors (E1-E10):
```
STEP 1: Check existing extractors in this catalog
├── If exists → IMPORT and USE it (done!)
└── If missing → Continue to STEP 2
STEP 2: Create extractor in optimization_engine/extractors/
├── File: extract_{feature}.py
├── Follow existing extractor patterns
└── Include comprehensive docstrings
STEP 3: Add to __init__.py
└── Export functions in optimization_engine/extractors/__init__.py
STEP 4: Update this module
├── Add to Extractor Catalog table
└── Add code snippet
STEP 5: Document in SYS_12_EXTRACTOR_LIBRARY.md
```
See [EXT_01_CREATE_EXTRACTOR](../../docs/protocols/extensions/EXT_01_CREATE_EXTRACTOR.md) for full guide.
---
## Cross-References
- **System Protocol**: [SYS_12_EXTRACTOR_LIBRARY](../../docs/protocols/system/SYS_12_EXTRACTOR_LIBRARY.md)
- **Extension Guide**: [EXT_01_CREATE_EXTRACTOR](../../docs/protocols/extensions/EXT_01_CREATE_EXTRACTOR.md)
- **Zernike Extractors**: [zernike-optimization module](./zernike-optimization.md)
- **Core Skill**: [study-creation-core](../core/study-creation-core.md)