feat: Add LLM-native development roadmap and reorganize documentation
- Add DEVELOPMENT_ROADMAP.md with 7-phase plan for LLM-driven optimization - Phase 1: Plugin system with lifecycle hooks - Phase 2: Natural language configuration interface - Phase 3: Dynamic code generation for custom objectives - Phase 4: Intelligent analysis and decision support - Phase 5: Automated HTML/PDF reporting - Phase 6: NX MCP server integration - Phase 7: Self-improving feature registry - Update README.md to reflect LLM-native philosophy - Emphasize natural language workflows - Link to development roadmap - Update architecture diagrams - Add future capability examples - Reorganize documentation structure - Move old dev docs to docs/archive/ - Clean up root directory - Preserve all working optimization engine code This sets the foundation for transforming Atomizer into an AI-powered engineering assistant that can autonomously configure optimizations, generate custom analysis code, and provide intelligent recommendations.
This commit is contained in:
130
docs/archive/STRESS_EXTRACTION_FIXED.md
Normal file
130
docs/archive/STRESS_EXTRACTION_FIXED.md
Normal file
@@ -0,0 +1,130 @@
|
||||
# Stress Extraction Fix - Complete ✅
|
||||
|
||||
## Problem Summary
|
||||
Stress extraction from NX Nastran OP2 files was returning **0.0 MPa** instead of expected values (~113 MPa).
|
||||
|
||||
## Root Causes Identified
|
||||
|
||||
### 1. pyNastran API Structure (Primary Issue)
|
||||
**Problem**: The OP2 object uses dotted attribute names like `'stress.chexa_stress'` (not `op2.stress.chexa_stress`)
|
||||
|
||||
**Solution**: Check for dotted attribute names using `hasattr(op2, 'stress.chexa_stress')`
|
||||
|
||||
### 2. Von Mises Stress Index
|
||||
**Problem**: Originally tried to use last column for all elements
|
||||
|
||||
**Solution**:
|
||||
- Solid elements (CHEXA, CTETRA, CPENTA): Use **index 9**
|
||||
- Shell elements (CQUAD4, CTRIA3): Use **last column (-1)**
|
||||
|
||||
### 3. Units Conversion (Critical!)
|
||||
**Problem**: NX Nastran outputs stress in **kPa** (kiloPascals), not MPa
|
||||
|
||||
**Solution**: Divide by 1000 to convert kPa → MPa
|
||||
|
||||
## Code Changes
|
||||
|
||||
### File: [op2_extractor_example.py](optimization_engine/result_extractors/op2_extractor_example.py)
|
||||
|
||||
#### Change 1: API Access Pattern (Lines 97-107)
|
||||
```python
|
||||
# Try format 1: Attribute name with dot (e.g., 'stress.chexa_stress')
|
||||
dotted_name = f'stress.{table_name}'
|
||||
if hasattr(op2, dotted_name):
|
||||
stress_table = getattr(op2, dotted_name)
|
||||
# Try format 2: Nested attribute op2.stress.chexa_stress
|
||||
elif hasattr(op2, 'stress') and hasattr(op2.stress, table_name):
|
||||
stress_table = getattr(op2.stress, table_name)
|
||||
# Try format 3: Direct attribute op2.chexa_stress (older pyNastran)
|
||||
elif hasattr(op2, table_name):
|
||||
stress_table = getattr(op2, table_name)
|
||||
```
|
||||
|
||||
#### Change 2: Correct Index for Solid Elements (Lines 120-126)
|
||||
```python
|
||||
if table_name in ['chexa_stress', 'ctetra_stress', 'cpenta_stress']:
|
||||
# Solid elements: data shape is [itime, nnodes, 10]
|
||||
# Index 9 is von_mises [oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, von_mises]
|
||||
stresses = stress_data.data[0, :, 9]
|
||||
else:
|
||||
# Shell elements: von Mises is last column
|
||||
stresses = stress_data.data[0, :, -1]
|
||||
```
|
||||
|
||||
#### Change 3: Units Conversion (Lines 141-143)
|
||||
```python
|
||||
# CRITICAL: NX Nastran outputs stress in kPa (mN/mm²), convert to MPa
|
||||
# 1 kPa = 0.001 MPa
|
||||
max_stress_overall_mpa = max_stress_overall / 1000.0
|
||||
```
|
||||
|
||||
## Test Results
|
||||
|
||||
### Before Fix
|
||||
```
|
||||
Max von Mises: 0.00 MPa
|
||||
Element ID: None
|
||||
```
|
||||
|
||||
### After Fix
|
||||
```
|
||||
Max von Mises: 113.09 MPa
|
||||
Element ID: 83
|
||||
Element type: chexa
|
||||
```
|
||||
|
||||
## How to Test
|
||||
|
||||
```bash
|
||||
# In test_env environment
|
||||
conda activate test_env
|
||||
python examples/test_stress_direct.py
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
- Max stress: ~113.09 MPa
|
||||
- Element: 83 (CHEXA)
|
||||
- Status: SUCCESS!
|
||||
|
||||
## Technical Details
|
||||
|
||||
### pyNastran Data Structure
|
||||
```
|
||||
OP2 Object Attributes (NX 2412.5):
|
||||
├── 'stress.chexa_stress' (dotted attribute name)
|
||||
├── 'stress.cpenta_stress'
|
||||
└── [other element types...]
|
||||
|
||||
stress_data structure:
|
||||
├── data[itime, nnodes, 10] for solid elements
|
||||
│ └── [oxx, oyy, ozz, txy, tyz, txz, o1, o2, o3, von_mises]
|
||||
│ 0 1 2 3 4 5 6 7 8 9
|
||||
└── element_node[:, 0] = element IDs
|
||||
```
|
||||
|
||||
### Units in NX Nastran OP2
|
||||
- Stress units: **kPa** (kilopascals) = mN/mm²
|
||||
- To convert to MPa: divide by 1000
|
||||
- Example: 113094.73 kPa = 113.09 MPa
|
||||
|
||||
## Files Modified
|
||||
- [optimization_engine/result_extractors/op2_extractor_example.py](optimization_engine/result_extractors/op2_extractor_example.py) - Main extraction logic
|
||||
|
||||
## Files Created for Testing
|
||||
- [examples/test_stress_direct.py](examples/test_stress_direct.py) - Direct stress extraction test
|
||||
- [examples/test_stress_fix.py](examples/test_stress_fix.py) - Verification script
|
||||
- [examples/debug_op2_stress.py](examples/debug_op2_stress.py) - Deep OP2 diagnostic
|
||||
|
||||
## Next Steps
|
||||
1. ✅ Stress extraction working
|
||||
2. ✅ Units conversion applied
|
||||
3. ✅ Compatible with multiple pyNastran versions
|
||||
4. ⏭️ Test complete optimization pipeline
|
||||
5. ⏭️ Integrate with NX solver execution
|
||||
|
||||
## Compatibility
|
||||
- ✅ NX Nastran 2412.5
|
||||
- ✅ pyNastran (latest version with dotted attribute names)
|
||||
- ✅ Older pyNastran versions (fallback to direct attributes)
|
||||
- ✅ CHEXA, CPENTA, CTETRA solid elements
|
||||
- ✅ CQUAD4, CTRIA3 shell elements
|
||||
Reference in New Issue
Block a user