# Atomizer Extractor Library *Auto-generated: 2025-12-07 12:53* This document is automatically generated from the extractor source code. --- ## Quick Reference | Extractor | Category | Phase | Description | |-----------|----------|-------|-------------| | `check_force_equilibrium` | forces | Phase 2 | Check if reaction forces balance applied loads (equilibrium | | `extract_reaction_component` | forces | Phase 2 | Extract maximum absolute value of a specific reaction compon | | `extract_spc_forces` | forces | Phase 2 | Extract SPC (reaction) forces from boundary conditions. | | `extract_total_reaction_force` | forces | Phase 2 | Convenience function to extract total reaction force magnitu | | `extract_frequencies` | general | Phase 3 | Extract natural frequencies from modal analysis F06 file. | | `extract_part_material` | general | Phase 1 | Convenience function to extract just material info. | | `PartMassExtractor` | mass | Phase 1 | Class-based extractor for part mass and material with cachin | | `extract_part_mass` | mass | Phase 1 | Convenience function to extract just the mass in kg. | | `extract_part_mass_material` | mass | Phase 1 | Extract mass and material properties from NX part file. | | `extract_modal_mass` | modal | Phase 3 | Extract modal effective mass from F06 file. | | `get_first_frequency` | modal | Phase 3 | Get first natural frequency from F06 file. | | `get_modal_mass_ratio` | modal | Phase 3 | Get cumulative modal mass ratio for first n modes. | | `ZernikeExtractor` | optical | Phase 1 | Complete Zernike analysis extractor for telescope mirror opt | | `extract_zernike_filtered_rms` | optical | Phase 1 | Extract filtered RMS WFE - the primary metric for mirror opt | | `extract_zernike_from_op2` | optical | Phase 1 | Convenience function to extract Zernike metrics from OP2. | | `extract_zernike_relative_rms` | optical | Phase 1 | Extract relative filtered RMS between two subcases. | | `extract_strain_energy` | strain | Phase 2 | Extract strain energy from structural elements. | | `extract_strain_energy_density` | strain | Phase 2 | Extract strain energy density (energy per volume). | | `extract_total_strain_energy` | strain | Phase 2 | Convenience function to extract total strain energy. | | `extract_max_principal_stress` | stress | Phase 2 | Convenience function to extract maximum principal stress. | | `extract_min_principal_stress` | stress | Phase 2 | Convenience function to extract minimum principal stress. | | `extract_principal_stress` | stress | Phase 2 | Extract principal stresses from solid or shell elements. | | `extract_solid_stress` | stress | Phase 1 | Extract stress from solid elements. | | `extract_heat_flux` | thermal | Phase 3 | Extract element heat flux from thermal analysis OP2 file. | | `extract_temperature` | thermal | Phase 3 | Extract nodal temperatures from thermal analysis OP2 file. | | `extract_temperature_gradient` | thermal | Phase 3 | Extract temperature gradients from thermal analysis. | | `get_max_temperature` | thermal | Phase 3 | Get maximum temperature from OP2 file. | --- ## Forces Extractors ### `check_force_equilibrium` **Module**: `optimization_engine.extractors.extract_spc_forces` **Phase**: Phase 2 **Parameters**: - `op2_file` - `applied_load` = `None` - `tolerance` = `1.0` **Description**: ``` Check if reaction forces balance applied loads (equilibrium check). In a valid static analysis, sum of reactions should equal applied loads. Args: op2_file: Path to .op2 file applied_load: Optional dict of applied loads {'fx': N, 'fy': N, 'fz': N} tolerance: Tolerance for equilibrium check (default 1.0 N) Returns: dict: { 'in_equilibrium': Boolean, 'reaction_sum': [fx, fy, fz], 'imbalance': [dx, dy, dz] (if applied_load provided), 'max_imbalance': Maximum component imbalance } ``` --- ### `extract_reaction_component` **Module**: `optimization_engine.extractors.extract_spc_forces` **Phase**: Phase 2 **Parameters**: - `op2_file` - `component` = `fz` - `subcase` = `1` **Description**: ``` Extract maximum absolute value of a specific reaction component. Args: op2_file: Path to .op2 file component: 'fx', 'fy', 'fz', 'mx', 'my', 'mz' subcase: Subcase ID Returns: Maximum absolute value of the specified component ``` --- ### `extract_spc_forces` **Module**: `optimization_engine.extractors.extract_spc_forces` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` - `component` = `total` **Description**: ``` Extract SPC (reaction) forces from boundary conditions. SPC forces are the reaction forces at constrained nodes. They balance the applied loads and indicate load path through the structure. Args: op2_file: Path to .op2 file subcase: Subcase ID (default 1) component: Which component(s) to return: - 'total': Resultant force magnitude (sqrt(fx^2+fy^2+fz^2)) - 'fx', 'fy', 'fz': Individual force components - 'mx', 'my', 'mz': Individual moment components - 'force': Vector sum of forces only - 'moment': Vector sum of moments only Returns: dict: { 'total_reaction': Total reaction force magnitude, 'max_reaction': Maximum nodal reaction, 'max_reaction_node': Node ID with max reaction, 'sum_fx': Sum of Fx at all nodes, 'sum_fy': Sum of Fy at all nodes, 'sum_fz': Sum of Fz at all nodes, 'sum_mx': Sum of Mx at all nodes, 'sum_my': Sum of My at all nodes, 'sum_mz': Sum of Mz at all nodes, 'node_reactions': Dict of {node_id: [fx,fy,fz,mx,my,mz]}, 'num_constrained_nodes': Number of nodes with SPCs, 'subcase': Subcase ID, 'units': 'N, N-mm (model units)' } Example: >>> result = extract_spc_forces('model.op2') >>> print(f"Total reaction: {result['total_reaction']:.2f} N") >>> print(f"Sum Fz: {result['sum_fz']:.2f} N") ``` --- ### `extract_total_reaction_force` **Module**: `optimization_engine.extractors.extract_spc_forces` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` **Description**: ``` Convenience function to extract total reaction force magnitude. Args: op2_file: Path to .op2 file subcase: Subcase ID Returns: Total reaction force magnitude (N) ``` --- ## General Extractors ### `extract_frequencies` **Module**: `optimization_engine.extractors.extract_modal_mass` **Phase**: Phase 3 **Parameters**: - `f06_file` - `n_modes` = `None` **Description**: ``` Extract natural frequencies from modal analysis F06 file. Simpler version of extract_modal_mass that just gets frequencies. Args: f06_file: Path to F06 file n_modes: Number of modes to extract (default: all) Returns: dict: { 'success': bool, 'frequencies': list of frequencies in Hz, 'mode_count': int, 'first_frequency': float, 'error': str or None } ``` --- ### `extract_part_material` **Module**: `optimization_engine.extractors.extract_part_mass_material` **Phase**: Phase 1 **Parameters**: - `prt_file` - `properties_file` = `None` **Description**: ``` Convenience function to extract just material info. Args: prt_file: Path to .prt file properties_file: Optional explicit path to temp file Returns: Dictionary with 'name', 'density', 'density_unit' Example: >>> mat = extract_part_material('model.prt') >>> print(f"Material: {mat['name']}, Density: {mat['density']}") Material: Steel_304, Density: 7.93e-06 ``` --- ## Mass Extractors ### `PartMassExtractor` **Module**: `optimization_engine.extractors.extract_part_mass_material` **Phase**: Phase 1 **Parameters**: - `prt_file` - `properties_file` = `None` **Description**: ``` Class-based extractor for part mass and material with caching. Use this when you need to extract properties from multiple parts or want to cache results. Example: >>> extractor = PartMassExtractor('model.prt') >>> result = extractor.extract() >>> print(result['mass_kg']) 1.234 ``` --- ### `extract_part_mass` **Module**: `optimization_engine.extractors.extract_part_mass_material` **Phase**: Phase 1 **Parameters**: - `prt_file` - `properties_file` = `None` **Description**: ``` Convenience function to extract just the mass in kg. Args: prt_file: Path to .prt file properties_file: Optional explicit path to temp file Returns: Mass in kilograms (float) Example: >>> mass = extract_part_mass('model.prt') >>> print(f"Mass: {mass:.3f} kg") Mass: 1.234 kg ``` --- ### `extract_part_mass_material` **Module**: `optimization_engine.extractors.extract_part_mass_material` **Phase**: Phase 1 **Parameters**: - `prt_file` - `properties_file` = `None` **Description**: ``` Extract mass and material properties from NX part file. This function reads from a temp JSON file that must be created by running the NX journal: nx_journals/extract_part_mass_material.py Args: prt_file: Path to .prt file (used to locate temp file) properties_file: Optional explicit path to _temp_part_properties.json If not provided, looks in same directory as prt_file Returns: Dictionary containing: - 'mass_kg': Mass in kilograms (float) - 'mass_g': Mass in grams (float) - 'volume_mm3': Volume in mm^3 (float) - 'surface_area_mm2': Surface area in mm^2 (float) - 'center_of_gravity_mm': [x, y, z] in mm (list) - 'moments_of_inertia': {'Ixx', 'Iyy', 'Izz', 'unit'} or None - 'material': {'name', 'density', 'density_unit'} (dict) - 'num_bodies': Number of solid bodies (int) Raises: FileNotFoundError: If prt file or temp properties file not found ValueError: If temp file has invalid format or extraction failed Example: >>> result = extract_part_mass_material('model.prt') >>> print(f"Mass: {result['mass_kg']:.3f} kg") Mass: 1.234 kg >>> print(f"Material: {result['material']['name']}") Material: Aluminum_6061 Note: Before calling this function, you must run the NX journal to create the temp file: ``` run_journal.exe extract_part_mass_material.py model.prt ``` ``` --- ## Modal Extractors ### `extract_modal_mass` **Module**: `optimization_engine.extractors.extract_modal_mass` **Phase**: Phase 3 **Parameters**: - `f06_file` - `mode` = `None` - `direction` = `all` **Description**: ``` Extract modal effective mass from F06 file. Modal effective mass indicates how much of the total mass participates in each mode for each direction. Important for: - Base excitation problems - Seismic analysis - Random vibration Args: f06_file: Path to the F06 results file mode: Mode number to extract (1-indexed). If None, returns all modes. direction: Direction(s) to extract: 'x', 'y', 'z' - single direction 'all' - all directions (default) 'total' - sum of all directions Returns: dict: { 'success': bool, 'modes': list of mode data (if mode=None), 'modal_mass_x': float (kg) - effective mass in X, 'modal_mass_y': float (kg) - effective mass in Y, 'modal_mass_z': float (kg) - effective mass in Z, 'modal_mass_rx': float (kg·m²) - rotational mass about X, 'modal_mass_ry': float (kg·m²) - rotational mass about Y, 'modal_mass_rz': float (kg·m²) - rotational mass about Z, 'participation_x': float (0-1) - participation factor X, 'participation_y': float (0-1) - participation factor Y, 'participation_z': float (0-1) - participation factor Z, 'frequency': float (Hz) - natural frequency, 'cumulative_mass_x': float - cumulative mass fraction X, 'cumulative_mass_y': float - cumulative mass fraction Y, 'cumulative_mass_z': float - cumulative mass fraction Z, 'total_mass': float (kg) - total model mass, 'error': str or None } Example: >>> result = extract_modal_mass("modal_analysis.f06", mode=1) >>> if result['success']: ... print(f"Mode 1 frequency: {result['frequency']:.2f} Hz") ... print(f"X participation: {result['participation_x']*100:.1f}%") ``` --- ### `get_first_frequency` **Module**: `optimization_engine.extractors.extract_modal_mass` **Phase**: Phase 3 **Parameters**: - `f06_file` **Description**: ``` Get first natural frequency from F06 file. Convenience function for optimization constraints. Returns 0 if extraction fails. Args: f06_file: Path to F06 file Returns: float: First natural frequency in Hz, or 0 on failure ``` --- ### `get_modal_mass_ratio` **Module**: `optimization_engine.extractors.extract_modal_mass` **Phase**: Phase 3 **Parameters**: - `f06_file` - `direction` = `z` - `n_modes` = `10` **Description**: ``` Get cumulative modal mass ratio for first n modes. This indicates what fraction of total mass participates in the first n modes. Important for determining if enough modes are included. Args: f06_file: Path to F06 file direction: Direction ('x', 'y', or 'z') n_modes: Number of modes to include Returns: float: Cumulative mass ratio (0-1), or 0 on failure ``` --- ## Optical Extractors ### `ZernikeExtractor` **Module**: `optimization_engine.extractors.extract_zernike` **Phase**: Phase 1 **Parameters**: - `op2_path` - `bdf_path` = `None` - `displacement_unit` = `mm` - `n_modes` = `50` - `filter_orders` = `4` **Description**: ``` Complete Zernike analysis extractor for telescope mirror optimization. This class handles: - Loading OP2 displacement results - Matching with BDF geometry - Computing Zernike coefficients and RMS metrics - Multi-subcase analysis (different gravity orientations) - Relative metrics between subcases Example usage in optimization: extractor = ZernikeExtractor(op2_file, bdf_file) # For single-objective optimization (minimize filtered RMS at 20 deg) result = extractor.extract_subcase('20') objective = result['filtered_rms_nm'] # For multi-subcase optimization all_results = extractor.extract_all_subcases() ``` --- ### `extract_zernike_filtered_rms` **Module**: `optimization_engine.extractors.extract_zernike` **Phase**: Phase 1 **Parameters**: - `op2_file` - `bdf_file` = `None` - `subcase` = `1` - `kwargs` **Description**: ``` Extract filtered RMS WFE - the primary metric for mirror optimization. Filtered RMS removes piston, tip, tilt, and defocus (modes 1-4), which can be corrected by alignment and focus adjustment. Args: op2_file: Path to OP2 file bdf_file: Path to BDF geometry (auto-detected if None) subcase: Subcase identifier **kwargs: Additional arguments for ZernikeExtractor Returns: Filtered RMS WFE in nanometers ``` --- ### `extract_zernike_from_op2` **Module**: `optimization_engine.extractors.extract_zernike` **Phase**: Phase 1 **Parameters**: - `op2_file` - `bdf_file` = `None` - `subcase` = `1` - `displacement_unit` = `mm` - `n_modes` = `50` - `filter_orders` = `4` **Description**: ``` Convenience function to extract Zernike metrics from OP2. This is the main entry point for optimization objectives. Args: op2_file: Path to OP2 results file bdf_file: Path to BDF geometry (auto-detected if None) subcase: Subcase identifier displacement_unit: Unit of displacement in OP2 n_modes: Number of Zernike modes filter_orders: Low-order modes to filter Returns: Dict with: - 'global_rms_nm': Global RMS WFE in nanometers - 'filtered_rms_nm': Filtered RMS (low orders removed) - 'defocus_nm', 'astigmatism_rms_nm', etc.: Individual aberrations ``` --- ### `extract_zernike_relative_rms` **Module**: `optimization_engine.extractors.extract_zernike` **Phase**: Phase 1 **Parameters**: - `op2_file` - `target_subcase` - `reference_subcase` - `bdf_file` = `None` - `kwargs` **Description**: ``` Extract relative filtered RMS between two subcases. Useful for analyzing gravity-induced deformation relative to a reference orientation (e.g., polishing position). Args: op2_file: Path to OP2 file target_subcase: Subcase to analyze reference_subcase: Reference subcase bdf_file: Path to BDF geometry **kwargs: Additional arguments for ZernikeExtractor Returns: Relative filtered RMS WFE in nanometers ``` --- ## Strain Extractors ### `extract_strain_energy` **Module**: `optimization_engine.extractors.extract_strain_energy` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `None` - `top_n` = `10` **Description**: ``` Extract strain energy from structural elements. Strain energy (U) is a measure of the work done to deform the structure: U = 0.5 * integral(sigma * epsilon) dV High strain energy density indicates highly stressed regions. Args: op2_file: Path to .op2 file subcase: Subcase ID (default 1) element_type: Filter by element type (e.g., 'ctetra', 'chexa', 'cquad4') If None, returns total from all elements top_n: Number of top elements to return by strain energy Returns: dict: { 'total_strain_energy': Total strain energy (all elements), 'mean_strain_energy': Mean strain energy per element, 'max_strain_energy': Maximum element strain energy, 'max_energy_element': Element ID with max strain energy, 'top_elements': List of (element_id, energy) tuples, 'energy_by_type': Dict of {element_type: total_energy}, 'num_elements': Total element count, 'subcase': Subcase ID, 'units': 'N-mm (model units)' } Example: >>> result = extract_strain_energy('model.op2') >>> print(f"Total strain energy: {result['total_strain_energy']:.2f} N-mm") >>> print(f"Highest energy element: {result['max_energy_element']}") ``` --- ### `extract_strain_energy_density` **Module**: `optimization_engine.extractors.extract_strain_energy` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `ctetra` **Description**: ``` Extract strain energy density (energy per volume). Strain energy density is useful for identifying critical regions and for material utilization optimization. Args: op2_file: Path to .op2 file subcase: Subcase ID element_type: Element type to analyze Returns: dict: { 'max_density': Maximum strain energy density, 'mean_density': Mean strain energy density, 'total_energy': Total strain energy, 'units': 'N/mm^2 (MPa equivalent)' } Note: This requires element volume data which may not always be available. Falls back to energy-only metrics if volume is unavailable. ``` --- ### `extract_total_strain_energy` **Module**: `optimization_engine.extractors.extract_strain_energy` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` **Description**: ``` Convenience function to extract total strain energy. Args: op2_file: Path to .op2 file subcase: Subcase ID Returns: Total strain energy (N-mm) ``` --- ## Stress Extractors ### `extract_max_principal_stress` **Module**: `optimization_engine.extractors.extract_principal_stress` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `ctetra` **Description**: ``` Convenience function to extract maximum principal stress. Args: op2_file: Path to .op2 file subcase: Subcase ID element_type: Element type Returns: Maximum principal stress value (tension positive) ``` --- ### `extract_min_principal_stress` **Module**: `optimization_engine.extractors.extract_principal_stress` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `ctetra` **Description**: ``` Convenience function to extract minimum principal stress. For solid elements, returns sigma3 (most compressive). For shell elements, returns sigma2. Args: op2_file: Path to .op2 file subcase: Subcase ID element_type: Element type Returns: Minimum principal stress value (compression negative) ``` --- ### `extract_principal_stress` **Module**: `optimization_engine.extractors.extract_principal_stress` **Phase**: Phase 2 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `ctetra` - `principal` = `max` **Description**: ``` Extract principal stresses from solid or shell elements. Principal stresses are the eigenvalues of the stress tensor, ordered as: sigma1 >= sigma2 >= sigma3 (o1 >= o2 >= o3) Args: op2_file: Path to .op2 file subcase: Subcase ID (default 1) element_type: Element type ('ctetra', 'chexa', 'cquad4', 'ctria3') principal: Which principal stress to return: - 'max': Maximum principal (sigma1, tension positive) - 'mid': Middle principal (sigma2) - 'min': Minimum principal (sigma3, compression negative) - 'all': Return all three principals Returns: dict: { 'max_principal': Maximum principal stress value, 'min_principal': Minimum principal stress value, 'mid_principal': Middle principal stress (if applicable), 'max_element': Element ID with maximum principal, 'min_element': Element ID with minimum principal, 'von_mises_max': Max von Mises for comparison, 'element_type': Element type used, 'subcase': Subcase ID, 'units': 'MPa (model units)' } Example: >>> result = extract_principal_stress('model.op2', element_type='ctetra') >>> print(f"Max tension: {result['max_principal']:.2f} MPa") >>> print(f"Max compression: {result['min_principal']:.2f} MPa") ``` --- ### `extract_solid_stress` **Module**: `optimization_engine.extractors.extract_von_mises_stress` **Phase**: Phase 1 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `ctetra` **Description**: ``` Extract stress from solid elements. ``` --- ## Thermal Extractors ### `extract_heat_flux` **Module**: `optimization_engine.extractors.extract_temperature` **Phase**: Phase 3 **Parameters**: - `op2_file` - `subcase` = `1` - `element_type` = `all` **Description**: ``` Extract element heat flux from thermal analysis OP2 file. Args: op2_file: Path to the OP2 results file subcase: Subcase number element_type: Element type to extract ('all', 'ctetra', 'chexa', etc.) Returns: dict: { 'success': bool, 'max_heat_flux': float (W/mm² or model units), 'min_heat_flux': float, 'avg_heat_flux': float, 'max_element_id': int, 'element_count': int, 'unit': str, 'error': str or None } ``` --- ### `extract_temperature` **Module**: `optimization_engine.extractors.extract_temperature` **Phase**: Phase 3 **Parameters**: - `op2_file` - `subcase` = `1` - `nodes` = `None` - `return_field` = `False` **Description**: ``` Extract nodal temperatures from thermal analysis OP2 file. Args: op2_file: Path to the OP2 results file subcase: Subcase number to extract (default: 1) nodes: Optional list of specific node IDs to extract. If None, extracts all nodes. return_field: If True, include full temperature field in result Returns: dict: { 'success': bool, 'max_temperature': float (K or °C depending on model units), 'min_temperature': float, 'avg_temperature': float, 'max_node_id': int (node with max temperature), 'min_node_id': int (node with min temperature), 'node_count': int, 'temperatures': dict (node_id: temp) - only if return_field=True, 'unit': str ('K' or 'C'), 'subcase': int, 'error': str or None } Example: >>> result = extract_temperature("thermal_analysis.op2", subcase=1) >>> if result['success']: ... print(f"Max temp: {result['max_temperature']:.1f} K at node {result['max_node_id']}") ... print(f"Temperature range: {result['min_temperature']:.1f} - {result['max_temperature']:.1f} K") ``` --- ### `extract_temperature_gradient` **Module**: `optimization_engine.extractors.extract_temperature` **Phase**: Phase 3 **Parameters**: - `op2_file` - `subcase` = `1` - `method` = `nodal_difference` **Description**: ``` Extract temperature gradients from thermal analysis. Computes temperature gradients based on nodal temperature differences. This is useful for identifying thermal stress hot spots. Args: op2_file: Path to the OP2 results file subcase: Subcase number method: Gradient calculation method: - 'nodal_difference': Max temperature difference between adjacent nodes - 'element_based': Gradient within elements (requires mesh connectivity) Returns: dict: { 'success': bool, 'max_gradient': float (K/mm or temperature units/length), 'avg_gradient': float, 'temperature_range': float (max - min temperature), 'gradient_location': tuple (node_id_hot, node_id_cold), 'error': str or None } Note: For accurate gradients, element-based calculation requires mesh connectivity which may not be available in all OP2 files. The nodal_difference method provides an approximation based on temperature range. ``` --- ### `get_max_temperature` **Module**: `optimization_engine.extractors.extract_temperature` **Phase**: Phase 3 **Parameters**: - `op2_file` - `subcase` = `1` **Description**: ``` Get maximum temperature from OP2 file. Convenience function for use in optimization constraints. Returns inf if extraction fails. Args: op2_file: Path to OP2 file subcase: Subcase number Returns: float: Maximum temperature or inf on failure ``` ---