# 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)