Files
Atomizer/optimization_engine/plugins/post_calculation/safety_factor_constraint.py
Anto01 2f3afc3813 feat: Add substudy system with live history tracking and workflow fixes
Major Features:
- Hierarchical substudy system (like NX Solutions/Subcases)
  * Shared model files across all substudies
  * Independent configuration per substudy
  * Continuation support from previous substudies
  * Real-time incremental history updates
- Live history tracking with optimization_history_incremental.json
- Complete bracket_displacement_maximizing study with substudy examples

Core Fixes:
- Fixed expression update workflow to pass design_vars through simulation_runner
  * Restored working NX journal expression update mechanism
  * OP2 timestamp verification instead of file deletion
  * Resolved issue where all trials returned identical objective values
- Fixed LLMOptimizationRunner to pass design variables to simulation runner
- Enhanced NXSolver with timestamp-based file regeneration verification

New Components:
- optimization_engine/llm_optimization_runner.py - LLM-driven optimization runner
- optimization_engine/optimization_setup_wizard.py - Phase 3.3 setup wizard
- studies/bracket_displacement_maximizing/ - Complete substudy example
  * run_substudy.py - Substudy runner with continuation
  * run_optimization.py - Standalone optimization runner
  * config/substudy_template.json - Template for new substudies
  * substudies/coarse_exploration/ - 20-trial coarse search
  * substudies/fine_tuning/ - 50-trial refinement (continuation example)
  * SUBSTUDIES_README.md - Complete substudy documentation

Technical Improvements:
- Incremental history saving after each trial (optimization_history_incremental.json)
- Expression update workflow: .prt update → NX journal receives values → geometry update → FEM update → solve
- Trial indexing fix in substudy result saving
- Updated README with substudy system documentation

Testing:
- Successfully ran 20-trial coarse_exploration substudy
- Verified different objective values across trials (workflow fix validated)
- Confirmed live history updates in real-time
- Tested shared model file usage across substudies

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-16 21:29:54 -05:00

91 lines
2.9 KiB
Python

"""
Safety Factor Constraint Hook - Manual Implementation
This hook enforces a minimum safety factor constraint on stress.
If safety_factor < minimum required, the objective is heavily penalized.
Safety Factor = Yield Strength / Max Stress
For Aluminum 6061-T6:
- Yield Strength: 276 MPa
- Required Safety Factor: 4.0
- Allowable Stress: 69 MPa
Author: Atomizer Development Team
Version: 1.0
"""
from optimization_engine.plugins.hooks import Hook, HookPoint
def safety_factor_constraint_hook(context: dict) -> dict:
"""
Enforce safety factor constraint on optimization.
This hook checks if the calculated safety factor meets the minimum requirement.
If violated, it adds a large penalty to the objective to guide optimization
away from unsafe designs.
Args:
context: Dict containing:
- calculations: Dict with 'safety_factor' value
- results: Dict with stress results
Returns:
Dict with:
- safety_factor_satisfied: bool
- safety_factor_violation: float (0 if satisfied, penalty otherwise)
- constrained_objective: float (original or penalized objective)
"""
calculations = context.get('calculations', {})
# Get safety factor from calculations
safety_factor = calculations.get('safety_factor', 0.0)
# Get objective (negative displacement to maximize)
neg_displacement = calculations.get('neg_displacement', 0.0)
# Required minimum safety factor
min_safety_factor = 4.0
# Check constraint
satisfied = safety_factor >= min_safety_factor
# Calculate violation (how much we're under the limit)
violation = max(0.0, min_safety_factor - safety_factor)
# Apply penalty if constraint violated
if not satisfied:
# Heavy penalty: add large value to objective (we're minimizing)
# Penalty scales with violation severity
penalty = 1000.0 * violation
constrained_objective = neg_displacement + penalty
print(f" [CONSTRAINT VIOLATED] Safety factor {safety_factor:.2f} < {min_safety_factor}")
print(f" [PENALTY APPLIED] Adding {penalty:.2f} to objective")
else:
constrained_objective = neg_displacement
print(f" [CONSTRAINT SATISFIED] Safety factor {safety_factor:.2f} >= {min_safety_factor}")
return {
'safety_factor_satisfied': satisfied,
'safety_factor_violation': violation,
'constrained_objective': constrained_objective,
'objective': constrained_objective # This becomes the final objective
}
# Register hook with plugin system
hook = Hook(
name="safety_factor_constraint",
hook_point=HookPoint.POST_CALCULATION,
function=safety_factor_constraint_hook,
enabled=True,
description="Enforce minimum safety factor constraint with penalty"
)
def register_hooks(hook_manager):
"""Register hooks with the plugin system."""
return [hook]