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

10 KiB
Raw Blame History

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.


PR.2 Extractor Code Snippets (COPY-PASTE)

E1: Displacement Extraction

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:

{
    '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

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:

{
    '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

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:

{
    '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

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

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

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

# 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

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:

{
    '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:

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 for full guide.


Cross-References