196 lines
6.1 KiB
Python
196 lines
6.1 KiB
Python
|
|
"""
|
||
|
|
Test script for Phase 3 extractors (Multi-Physics)
|
||
|
|
===================================================
|
||
|
|
|
||
|
|
Tests:
|
||
|
|
- Temperature extraction (extract_temperature)
|
||
|
|
- Thermal gradient extraction (extract_temperature_gradient)
|
||
|
|
- Modal mass extraction (extract_modal_mass)
|
||
|
|
|
||
|
|
Run with:
|
||
|
|
conda activate atomizer
|
||
|
|
python -m optimization_engine.extractors.test_phase3_extractors
|
||
|
|
"""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
# Add project root to path
|
||
|
|
project_root = Path(__file__).parents[2]
|
||
|
|
sys.path.insert(0, str(project_root))
|
||
|
|
|
||
|
|
|
||
|
|
def test_imports():
|
||
|
|
"""Test that all Phase 3 extractors can be imported."""
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("Testing Phase 3 Extractor Imports")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
try:
|
||
|
|
from optimization_engine.extractors import (
|
||
|
|
extract_temperature,
|
||
|
|
extract_temperature_gradient,
|
||
|
|
extract_heat_flux,
|
||
|
|
get_max_temperature,
|
||
|
|
extract_modal_mass,
|
||
|
|
extract_frequencies,
|
||
|
|
get_first_frequency,
|
||
|
|
get_modal_mass_ratio,
|
||
|
|
)
|
||
|
|
print("✓ All Phase 3 extractors imported successfully!")
|
||
|
|
return True
|
||
|
|
except ImportError as e:
|
||
|
|
print(f"✗ Import failed: {e}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
|
||
|
|
def test_temperature_extractor(op2_file: str = None):
|
||
|
|
"""Test temperature extraction."""
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("Testing extract_temperature")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
from optimization_engine.extractors import extract_temperature
|
||
|
|
|
||
|
|
if op2_file and Path(op2_file).exists():
|
||
|
|
result = extract_temperature(op2_file, subcase=1)
|
||
|
|
print(f"Result: {result}")
|
||
|
|
|
||
|
|
if result['success']:
|
||
|
|
print(f" Max temperature: {result['max_temperature']}")
|
||
|
|
print(f" Min temperature: {result['min_temperature']}")
|
||
|
|
print(f" Avg temperature: {result['avg_temperature']}")
|
||
|
|
print(f" Node count: {result['node_count']}")
|
||
|
|
else:
|
||
|
|
print(f" Note: {result['error']}")
|
||
|
|
print(" (This is expected for non-thermal OP2 files)")
|
||
|
|
else:
|
||
|
|
# Test with non-existent file to verify error handling
|
||
|
|
result = extract_temperature("nonexistent.op2")
|
||
|
|
if not result['success'] and 'not found' in result['error']:
|
||
|
|
print("✓ Error handling works correctly for missing files")
|
||
|
|
else:
|
||
|
|
print("✗ Error handling issue")
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_temperature_gradient(op2_file: str = None):
|
||
|
|
"""Test temperature gradient extraction."""
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("Testing extract_temperature_gradient")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
from optimization_engine.extractors import extract_temperature_gradient
|
||
|
|
|
||
|
|
if op2_file and Path(op2_file).exists():
|
||
|
|
result = extract_temperature_gradient(op2_file, subcase=1)
|
||
|
|
print(f"Result: {result}")
|
||
|
|
else:
|
||
|
|
result = extract_temperature_gradient("nonexistent.op2")
|
||
|
|
if not result['success']:
|
||
|
|
print("✓ Error handling works correctly")
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_modal_mass_extractor(f06_file: str = None):
|
||
|
|
"""Test modal mass extraction."""
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("Testing extract_modal_mass")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
from optimization_engine.extractors import extract_modal_mass, get_first_frequency
|
||
|
|
|
||
|
|
if f06_file and Path(f06_file).exists():
|
||
|
|
# Test all modes
|
||
|
|
result = extract_modal_mass(f06_file, mode=None)
|
||
|
|
print(f"All modes result:")
|
||
|
|
if result['success']:
|
||
|
|
print(f" Mode count: {result['mode_count']}")
|
||
|
|
print(f" Frequencies: {result['frequencies'][:5]}..." if len(result.get('frequencies', [])) > 5 else f" Frequencies: {result.get('frequencies', [])}")
|
||
|
|
else:
|
||
|
|
print(f" Note: {result['error']}")
|
||
|
|
|
||
|
|
# Test specific mode
|
||
|
|
result = extract_modal_mass(f06_file, mode=1)
|
||
|
|
print(f"\nMode 1 result:")
|
||
|
|
if result['success']:
|
||
|
|
print(f" Frequency: {result['frequency']} Hz")
|
||
|
|
print(f" Modal mass X: {result.get('modal_mass_x')}")
|
||
|
|
print(f" Modal mass Y: {result.get('modal_mass_y')}")
|
||
|
|
print(f" Modal mass Z: {result.get('modal_mass_z')}")
|
||
|
|
else:
|
||
|
|
print(f" Note: {result['error']}")
|
||
|
|
|
||
|
|
# Test convenience function
|
||
|
|
freq = get_first_frequency(f06_file)
|
||
|
|
print(f"\nFirst frequency (convenience): {freq} Hz")
|
||
|
|
else:
|
||
|
|
result = extract_modal_mass("nonexistent.f06")
|
||
|
|
if not result['success'] and 'not found' in result['error']:
|
||
|
|
print("✓ Error handling works correctly for missing files")
|
||
|
|
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def find_test_files():
|
||
|
|
"""Find available test files in studies."""
|
||
|
|
studies_dir = project_root / "studies"
|
||
|
|
op2_files = list(studies_dir.rglob("*.op2"))
|
||
|
|
f06_files = list(studies_dir.rglob("*.f06"))
|
||
|
|
|
||
|
|
print(f"\nFound {len(op2_files)} OP2 files and {len(f06_files)} F06 files")
|
||
|
|
|
||
|
|
return op2_files, f06_files
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
print("=" * 60)
|
||
|
|
print("PHASE 3 EXTRACTOR TESTS")
|
||
|
|
print("Multi-Physics: Thermal & Dynamic")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
# Test imports first
|
||
|
|
if not test_imports():
|
||
|
|
print("\n✗ Import test failed. Cannot continue.")
|
||
|
|
return 1
|
||
|
|
|
||
|
|
# Find test files
|
||
|
|
op2_files, f06_files = find_test_files()
|
||
|
|
|
||
|
|
# Use first available files for testing
|
||
|
|
op2_file = str(op2_files[0]) if op2_files else None
|
||
|
|
f06_file = str(f06_files[0]) if f06_files else None
|
||
|
|
|
||
|
|
if op2_file:
|
||
|
|
print(f"\nUsing OP2 file: {op2_file}")
|
||
|
|
if f06_file:
|
||
|
|
print(f"Using F06 file: {f06_file}")
|
||
|
|
|
||
|
|
# Run tests
|
||
|
|
test_temperature_extractor(op2_file)
|
||
|
|
test_temperature_gradient(op2_file)
|
||
|
|
test_modal_mass_extractor(f06_file)
|
||
|
|
|
||
|
|
print("\n" + "=" * 60)
|
||
|
|
print("PHASE 3 TESTS COMPLETE")
|
||
|
|
print("=" * 60)
|
||
|
|
|
||
|
|
print("""
|
||
|
|
Summary:
|
||
|
|
- Temperature extraction: Ready for thermal OP2 files (SOL 153/159)
|
||
|
|
- Thermal gradient: Ready (approximation based on temperature range)
|
||
|
|
- Heat flux: Ready for thermal OP2 files
|
||
|
|
- Modal mass: Ready for modal F06 files (SOL 103)
|
||
|
|
|
||
|
|
Note: Full testing requires thermal and modal analysis result files.
|
||
|
|
The extractors will return appropriate error messages for non-thermal/modal data.
|
||
|
|
""")
|
||
|
|
|
||
|
|
return 0
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
sys.exit(main())
|