2025-11-16 21:29:54 -05:00
|
|
|
"""
|
|
|
|
|
Test LLM Optimization Runner with Bracket Problem
|
|
|
|
|
|
|
|
|
|
Objective: Maximize displacement
|
|
|
|
|
Constraint: Stress must remain under safety factor of 4
|
|
|
|
|
|
|
|
|
|
Assuming Aluminum 6061-T6:
|
|
|
|
|
- Yield Strength: 276 MPa
|
|
|
|
|
- Safety Factor: 4
|
|
|
|
|
- Allowable Stress: 276 / 4 = 69 MPa
|
|
|
|
|
|
|
|
|
|
This test validates Phase 3.2 LLM-enhanced optimization with stress constraints.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
|
|
refactor: Major reorganization of optimization_engine module structure
BREAKING CHANGE: Module paths have been reorganized for better maintainability.
Backwards compatibility aliases with deprecation warnings are provided.
New Structure:
- core/ - Optimization runners (runner, intelligent_optimizer, etc.)
- processors/ - Data processing
- surrogates/ - Neural network surrogates
- nx/ - NX/Nastran integration (solver, updater, session_manager)
- study/ - Study management (creator, wizard, state, reset)
- reporting/ - Reports and analysis (visualizer, report_generator)
- config/ - Configuration management (manager, builder)
- utils/ - Utilities (logger, auto_doc, etc.)
- future/ - Research/experimental code
Migration:
- ~200 import changes across 125 files
- All __init__.py files use lazy loading to avoid circular imports
- Backwards compatibility layer supports old import paths with warnings
- All existing functionality preserved
To migrate existing code:
OLD: from optimization_engine.nx_solver import NXSolver
NEW: from optimization_engine.nx.solver import NXSolver
OLD: from optimization_engine.runner import OptimizationRunner
NEW: from optimization_engine.core.runner import OptimizationRunner
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 12:30:59 -05:00
|
|
|
from optimization_engine.future.llm_optimization_runner import LLMOptimizationRunner
|
2025-11-16 21:29:54 -05:00
|
|
|
|
|
|
|
|
# LLM workflow for bracket optimization
|
|
|
|
|
# Goal: Maximize displacement while keeping stress below safety factor
|
|
|
|
|
llm_workflow = {
|
|
|
|
|
'engineering_features': [
|
|
|
|
|
{
|
|
|
|
|
'action': 'extract_displacement',
|
|
|
|
|
'domain': 'result_extraction',
|
|
|
|
|
'description': 'Extract displacement results from OP2 file',
|
|
|
|
|
'params': {'result_type': 'displacement'}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'action': 'extract_solid_stress',
|
|
|
|
|
'domain': 'result_extraction',
|
|
|
|
|
'description': 'Extract von Mises stress from solid elements',
|
|
|
|
|
'params': {
|
|
|
|
|
'result_type': 'stress',
|
|
|
|
|
'element_type': 'ctetra'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
'inline_calculations': [
|
|
|
|
|
{
|
|
|
|
|
'action': 'calculate_safety_factor',
|
|
|
|
|
'params': {
|
|
|
|
|
'input': 'max_von_mises',
|
|
|
|
|
'yield_strength': 276.0, # MPa for Aluminum 6061-T6
|
|
|
|
|
'operation': 'divide'
|
|
|
|
|
},
|
|
|
|
|
'code_hint': 'safety_factor = 276.0 / max_von_mises'
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
'action': 'negate_displacement',
|
|
|
|
|
'params': {
|
|
|
|
|
'input': 'max_displacement',
|
|
|
|
|
'operation': 'negate'
|
|
|
|
|
},
|
|
|
|
|
'code_hint': 'neg_displacement = -max_displacement'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
'post_processing_hooks': [
|
|
|
|
|
{
|
|
|
|
|
'action': 'weighted_objective',
|
|
|
|
|
'params': {
|
|
|
|
|
'inputs': ['neg_displacement'],
|
|
|
|
|
'weights': [1.0],
|
|
|
|
|
'objective': 'minimize'
|
|
|
|
|
},
|
|
|
|
|
'description': 'Minimize negative displacement (maximize actual displacement)'
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
'optimization': {
|
|
|
|
|
'algorithm': 'TPE',
|
|
|
|
|
'direction': 'minimize', # Minimize negative displacement = maximize displacement
|
|
|
|
|
'design_variables': [
|
|
|
|
|
{
|
|
|
|
|
'parameter': 'wall_thickness',
|
|
|
|
|
'min': 3.0,
|
|
|
|
|
'max': 8.0,
|
|
|
|
|
'units': 'mm'
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def dummy_updater(design_vars):
|
|
|
|
|
"""Dummy model updater for testing."""
|
|
|
|
|
print(f" [Test] Would update model with: {design_vars}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def dummy_runner():
|
|
|
|
|
"""Dummy simulation runner for testing."""
|
|
|
|
|
print(" [Test] Would run NX simulation...")
|
|
|
|
|
# Return path to existing test OP2
|
|
|
|
|
return Path('tests/bracket_sim1-solution_1.op2')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
print("=" * 80)
|
|
|
|
|
print("Test: LLM Runner with Bracket Problem")
|
|
|
|
|
print("=" * 80)
|
|
|
|
|
print()
|
|
|
|
|
print("Problem Definition:")
|
|
|
|
|
print(" Objective: MAXIMIZE displacement")
|
|
|
|
|
print(" Constraint: Stress must remain below yield/SF")
|
|
|
|
|
print(" Material: Aluminum 6061-T6 (Yield = 276 MPa)")
|
|
|
|
|
print(" Safety Factor: 4.0")
|
|
|
|
|
print(" Allowable Stress: 69 MPa")
|
|
|
|
|
print()
|
|
|
|
|
print("LLM Workflow:")
|
|
|
|
|
print(f" Engineering features: {len(llm_workflow['engineering_features'])}")
|
|
|
|
|
print(f" Inline calculations: {len(llm_workflow['inline_calculations'])}")
|
|
|
|
|
print(f" Post-processing hooks: {len(llm_workflow['post_processing_hooks'])}")
|
|
|
|
|
print(f" Design variables: {len(llm_workflow['optimization']['design_variables'])}")
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
# Initialize LLM runner
|
|
|
|
|
print("Initializing LLM optimization runner...")
|
|
|
|
|
try:
|
|
|
|
|
runner = LLMOptimizationRunner(
|
|
|
|
|
llm_workflow=llm_workflow,
|
|
|
|
|
model_updater=dummy_updater,
|
|
|
|
|
simulation_runner=dummy_runner,
|
|
|
|
|
study_name='bracket_maximize_disp_constrained'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
print("=" * 80)
|
|
|
|
|
print("Runner Initialized Successfully!")
|
|
|
|
|
print("=" * 80)
|
|
|
|
|
print(f" Extractors generated: {len(runner.extractors)}")
|
|
|
|
|
print(f" Inline calculations: {len(runner.inline_code)}")
|
|
|
|
|
hook_summary = runner.hook_manager.get_summary()
|
|
|
|
|
print(f" Hooks loaded: {hook_summary['enabled_hooks']}")
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
|
|
print("To run full optimization, call runner.run_optimization(n_trials=50)")
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"\nERROR during initialization: {e}")
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
sys.exit(1)
|