Phase 3 implements automated OP2 extraction code generation using pyNastran documentation research. This completes the zero-manual-coding pipeline for FEA optimization workflows. Key Features: - PyNastranResearchAgent for automated OP2 code generation - Documentation research via WebFetch integration - 3 core extraction patterns (displacement, stress, force) - Knowledge base architecture for learned patterns - Successfully tested on real OP2 files Phase 2.9 Integration: - Updated HookGenerator with lifecycle hook generation - Added POST_CALCULATION hook point to hooks.py - Created post_calculation/ plugin directory - Generated hooks integrate seamlessly with HookManager New Files: - optimization_engine/pynastran_research_agent.py (600+ lines) - optimization_engine/hook_generator.py (800+ lines) - optimization_engine/inline_code_generator.py - optimization_engine/plugins/post_calculation/ - tests/test_lifecycle_hook_integration.py - docs/SESSION_SUMMARY_PHASE_3.md - docs/SESSION_SUMMARY_PHASE_2_9.md - docs/SESSION_SUMMARY_PHASE_2_8.md - docs/HOOK_ARCHITECTURE.md Modified Files: - README.md - Added Phase 3 completion status - optimization_engine/plugins/hooks.py - Added POST_CALCULATION hook Test Results: - Phase 3 research agent: PASSED - Real OP2 extraction: PASSED (max_disp=0.362mm) - Lifecycle hook integration: PASSED Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
74 lines
1.9 KiB
Python
74 lines
1.9 KiB
Python
"""
|
|
Extract element forces from CBAR in Z direction from OP2
|
|
Auto-generated by Atomizer Phase 3 - pyNastran Research Agent
|
|
|
|
Pattern: cbar_force
|
|
Element Type: CBAR
|
|
Result Type: force
|
|
API: model.cbar_force[subcase]
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from typing import Dict, Any
|
|
import numpy as np
|
|
from pyNastran.op2.op2 import OP2
|
|
|
|
|
|
def extract_cbar_force(op2_file: Path, subcase: int = 1, direction: str = 'Z'):
|
|
"""
|
|
Extract forces from CBAR elements.
|
|
|
|
Args:
|
|
op2_file: Path to OP2 file
|
|
subcase: Subcase ID
|
|
direction: Force direction ('X', 'Y', 'Z', 'axial', 'torque')
|
|
|
|
Returns:
|
|
Dict with force statistics
|
|
"""
|
|
from pyNastran.op2.op2 import OP2
|
|
import numpy as np
|
|
|
|
model = OP2()
|
|
model.read_op2(str(op2_file))
|
|
|
|
if not hasattr(model, 'cbar_force'):
|
|
raise ValueError("No CBAR force results in OP2")
|
|
|
|
force = model.cbar_force[subcase]
|
|
itime = 0
|
|
|
|
# CBAR force data structure:
|
|
# [bending_moment_a1, bending_moment_a2,
|
|
# bending_moment_b1, bending_moment_b2,
|
|
# shear1, shear2, axial, torque]
|
|
|
|
direction_map = {
|
|
'shear1': 4,
|
|
'shear2': 5,
|
|
'axial': 6,
|
|
'Z': 6, # Commonly axial is Z direction
|
|
'torque': 7
|
|
}
|
|
|
|
col_idx = direction_map.get(direction, direction_map.get(direction.lower(), 6))
|
|
forces = force.data[itime, :, col_idx]
|
|
|
|
return {
|
|
f'max_{direction}_force': float(np.max(np.abs(forces))),
|
|
f'avg_{direction}_force': float(np.mean(np.abs(forces))),
|
|
f'min_{direction}_force': float(np.min(np.abs(forces))),
|
|
'forces_array': forces.tolist()
|
|
}
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# Example usage
|
|
import sys
|
|
if len(sys.argv) > 1:
|
|
op2_file = Path(sys.argv[1])
|
|
result = extract_cbar_force(op2_file)
|
|
print(f"Extraction result: {result}")
|
|
else:
|
|
print("Usage: python {sys.argv[0]} <op2_file>")
|