feat: Add robust NX expression import system for all expression types
Major Enhancement: - Implemented .exp file-based expression updates via NX journal scripts - Fixes critical issue with feature-linked expressions (e.g., hole_count) - Supports ALL NX expression types including binary-stored ones - Full 4D design space validation completed successfully New Components: 1. import_expressions.py - NX journal for .exp file import - Uses NXOpen.ExpressionCollection.ImportFromFile() - Replace mode overwrites existing values - Automatic model update and save - Comprehensive error handling 2. export_expressions.py - NX journal for .exp file export - Exports all expressions to text format - Used for unit detection and verification 3. Enhanced nx_updater.py - New update_expressions_via_import() method - Automatic unit detection from .exp export - Creates study-variable-only .exp files - Replaces fragile binary .prt editing Technical Details: - .exp Format: [Units]name=value (e.g., [MilliMeter]beam_length=5000) - Unitless expressions: name=value (e.g., hole_count=10) - Robustness: Native NX functionality, no regex failures - Performance: < 1 second per update operation Validation: - Simple Beam Optimization study (4D design space) * beam_half_core_thickness: 10-40 mm * beam_face_thickness: 10-40 mm * holes_diameter: 150-450 mm * hole_count: 5-15 (integer) Results: ✅ 3-trial validation completed successfully ✅ All 4 variables update correctly in all trials ✅ Mesh adaptation verified (hole_count: 6, 15, 11 → different mesh sizes) ✅ Trial 0: 5373 CQUAD4 elements (6 holes) ✅ Trial 1: 5158 CQUAD4 + 1 CTRIA3 (15 holes) ✅ Trial 2: 5318 CQUAD4 (11 holes) Problem Solved: - hole_count expression was not updating with binary .prt editing - Expression stored in feature parameter, not accessible via text regex - Binary format prevented reliable text-based updates Solution: - Use NX native expression import/export - Works for ALL expressions (text and binary-stored) - Automatic unit handling - Model update integrated in journal Documentation: - New: docs/NX_EXPRESSION_IMPORT_SYSTEM.md (comprehensive guide) - Updated: CHANGELOG.md with Phase 3.2 progress - Study: studies/simple_beam_optimization/ (complete example) Files Added: - optimization_engine/import_expressions.py - optimization_engine/export_expressions.py - docs/NX_EXPRESSION_IMPORT_SYSTEM.md - studies/simple_beam_optimization/ (full study) Files Modified: - optimization_engine/nx_updater.py - CHANGELOG.md Compatibility: - NX 2412 tested and verified - Python 3.10+ - Works with all NX expression types 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
# Comprehensive Benchmark Analysis - Simple Beam Optimization
|
||||
|
||||
**Date**: 2025-11-17
|
||||
**Study**: simple_beam_optimization
|
||||
**Model**: Beam.prt (CQUAD4 shell elements)
|
||||
|
||||
## 🔍 Complete Results Analysis
|
||||
|
||||
### Expression Discovery (via .exp export)
|
||||
|
||||
**Total Expressions**: 30 (100% captured with seamless .exp export!)
|
||||
|
||||
**Key Design Variables**:
|
||||
- `beam_half_core_thickness`: 20.0 mm
|
||||
- `beam_face_thickness`: 20.0 mm
|
||||
- `holes_diameter`: 300.0 mm
|
||||
- `hole_count`: 10 (unitless)
|
||||
|
||||
**Mass Expression**:
|
||||
- `p173`: **973.968 kg** ✅
|
||||
|
||||
### OP2 File Analysis
|
||||
|
||||
**File**: beam_sim1-solution_1.op2
|
||||
|
||||
**Available Results**:
|
||||
| Result Type | Status | Subcases | Notes |
|
||||
|-------------|--------|----------|-------|
|
||||
| Displacement | ✅ YES | [1] | Max: 22.12 mm at node 5186 |
|
||||
| Stress | ✅ YES | [1] | Max von Mises: 131.507 MPa at element 454 |
|
||||
| Strain | ❌ NO | - | Not configured in NX simulation |
|
||||
| Element Forces | ❌ NO | - | Not configured in NX simulation |
|
||||
| SPC Forces | ✅ YES | [1] | Reaction forces at constraints |
|
||||
|
||||
**Element Types**: CQUAD4 (shell elements, 9782 elements)
|
||||
|
||||
### F06 File Analysis
|
||||
|
||||
**File**: beam_sim1-solution_1.f06
|
||||
|
||||
**Available Results**:
|
||||
- ❌ NO displacement output
|
||||
- ❌ NO stress output
|
||||
- ❌ NO strain output
|
||||
- ❌ NO force output
|
||||
|
||||
**Conclusion**: F06 file does not contain tabular results. All usable results are in OP2.
|
||||
|
||||
## 📊 Baseline Performance
|
||||
|
||||
**Current Design**:
|
||||
- beam_half_core_thickness = 20 mm
|
||||
- beam_face_thickness = 20 mm
|
||||
- holes_diameter = 300 mm
|
||||
- hole_count = 10
|
||||
|
||||
**Measured Results**:
|
||||
- **Max Displacement**: 22.12 mm (exceeds 10mm target!)
|
||||
- **Max von Mises Stress**: 131.507 MPa (at element 454)
|
||||
- **Mass**: 973.97 kg
|
||||
|
||||
## 🎯 Available Optimization Objectives
|
||||
|
||||
Based on what's actually in the output files:
|
||||
|
||||
### Can Optimize NOW:
|
||||
1. **Displacement** (from OP2)
|
||||
- Minimize max displacement
|
||||
- Constrain to < 10mm
|
||||
- Current: 22.12 mm (VIOLATES constraint!)
|
||||
|
||||
2. **Stress** (from OP2)
|
||||
- Minimize max von Mises stress
|
||||
- Current: 131.507 MPa
|
||||
- Element type: CQUAD4 (shells)
|
||||
|
||||
3. **Mass** (from p173 expression)
|
||||
- Minimize weight
|
||||
- Current: 973.97 kg
|
||||
|
||||
4. **SPC Forces** (from OP2)
|
||||
- Reaction forces at constraints
|
||||
- Could be used as objective or constraint
|
||||
|
||||
### Cannot Optimize (yet):
|
||||
1. **Strain** - Not in output files
|
||||
2. **Element Forces** - Not in output files
|
||||
|
||||
## 📝 Recommended Configuration
|
||||
|
||||
**Full Multi-Objective Optimization (All 3 objectives available NOW!)**
|
||||
```json
|
||||
{
|
||||
"extractors": [
|
||||
{
|
||||
"name": "max_displacement",
|
||||
"action": "extract_displacement"
|
||||
},
|
||||
{
|
||||
"name": "max_stress",
|
||||
"action": "extract_solid_stress"
|
||||
},
|
||||
{
|
||||
"name": "mass",
|
||||
"action": "extract_expression",
|
||||
"parameters": {
|
||||
"expression_name": "p173"
|
||||
}
|
||||
}
|
||||
],
|
||||
"objectives": [
|
||||
{
|
||||
"name": "minimize_displacement",
|
||||
"extractor": "max_displacement",
|
||||
"goal": "minimize",
|
||||
"weight": 0.33
|
||||
},
|
||||
{
|
||||
"name": "minimize_stress",
|
||||
"extractor": "max_stress",
|
||||
"goal": "minimize",
|
||||
"weight": 0.33
|
||||
},
|
||||
{
|
||||
"name": "minimize_mass",
|
||||
"extractor": "mass",
|
||||
"goal": "minimize",
|
||||
"weight": 0.34
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"name": "displacement_limit",
|
||||
"extractor": "max_displacement",
|
||||
"type": "less_than",
|
||||
"value": 10.0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## ✅ What Works
|
||||
|
||||
- ✅ Expression gathering (30/30 expressions captured seamlessly!)
|
||||
- ✅ Displacement extraction from OP2 (max: 22.12 mm)
|
||||
- ✅ Stress extraction from OP2 (max von Mises: 131.507 MPa) **FIXED!**
|
||||
- ✅ Mass extraction from expressions (p173: 973.97 kg)
|
||||
- ✅ Proper unit system handling (MN-MM → MPa conversion)
|
||||
- ✅ SPC forces available if needed
|
||||
- ✅ Load from folder settings working
|
||||
- ✅ FEM file loading working
|
||||
|
||||
## 🔄 Next Steps
|
||||
|
||||
**Immediate (Ready to start!)**:
|
||||
1. Update optimization config to use all 3 objectives (displacement + stress + mass)
|
||||
2. Run validation trials to test complete pipeline
|
||||
3. If successful, run full optimization (50 trials)
|
||||
|
||||
**Baseline to Beat**:
|
||||
- Displacement: 22.12 mm → target < 10 mm
|
||||
- Stress: 131.507 MPa → minimize
|
||||
- Mass: 973.97 kg → minimize
|
||||
0
studies/simple_beam_optimization/README.md
Normal file
0
studies/simple_beam_optimization/README.md
Normal file
18
studies/simple_beam_optimization/baseline_validation.json
Normal file
18
studies/simple_beam_optimization/baseline_validation.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"displacement": {
|
||||
"max_displacement": 22.118558883666992,
|
||||
"max_disp_node": 5186,
|
||||
"units": "mm"
|
||||
},
|
||||
"stress": {
|
||||
"max_von_mises": 131.5071875,
|
||||
"max_stress_element": 454,
|
||||
"element_type": "cquad4",
|
||||
"num_elements": 9782,
|
||||
"units": "MPa"
|
||||
},
|
||||
"mass": {
|
||||
"p173": 973.968443678471,
|
||||
"units": "Kilogram"
|
||||
}
|
||||
}
|
||||
107
studies/simple_beam_optimization/beam_optimization_config.json
Normal file
107
studies/simple_beam_optimization/beam_optimization_config.json
Normal file
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"study_name": "simple_beam_optimization",
|
||||
"description": "Minimize displacement and weight of beam with stress constraint",
|
||||
"substudy_name": "validation_4d_3trials",
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": {
|
||||
"type": "continuous",
|
||||
"min": 10.0,
|
||||
"max": 40.0,
|
||||
"baseline": 20.0,
|
||||
"units": "mm",
|
||||
"description": "Half thickness of beam core"
|
||||
},
|
||||
"beam_face_thickness": {
|
||||
"type": "continuous",
|
||||
"min": 10.0,
|
||||
"max": 40.0,
|
||||
"baseline": 20.0,
|
||||
"units": "mm",
|
||||
"description": "Thickness of beam face sheets"
|
||||
},
|
||||
"holes_diameter": {
|
||||
"type": "continuous",
|
||||
"min": 150.0,
|
||||
"max": 450.0,
|
||||
"baseline": 300.0,
|
||||
"units": "mm",
|
||||
"description": "Diameter of lightening holes"
|
||||
},
|
||||
"hole_count": {
|
||||
"type": "integer",
|
||||
"min": 5,
|
||||
"max": 15,
|
||||
"baseline": 10,
|
||||
"units": "unitless",
|
||||
"description": "Number of lightening holes"
|
||||
}
|
||||
},
|
||||
"extractors": [
|
||||
{
|
||||
"name": "max_displacement",
|
||||
"action": "extract_displacement",
|
||||
"description": "Extract maximum displacement from OP2",
|
||||
"parameters": {
|
||||
"metric": "max"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "max_stress",
|
||||
"action": "extract_solid_stress",
|
||||
"description": "Extract maximum von Mises stress from OP2",
|
||||
"parameters": {
|
||||
"subcase": 1,
|
||||
"element_type": "auto"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mass",
|
||||
"action": "extract_expression",
|
||||
"description": "Extract mass from p173 expression",
|
||||
"parameters": {
|
||||
"expression_name": "p173"
|
||||
}
|
||||
}
|
||||
],
|
||||
"objectives": [
|
||||
{
|
||||
"name": "minimize_displacement",
|
||||
"extractor": "max_displacement",
|
||||
"goal": "minimize",
|
||||
"weight": 0.33,
|
||||
"description": "Minimize maximum displacement (current: 22.12mm, target: <10mm)"
|
||||
},
|
||||
{
|
||||
"name": "minimize_stress",
|
||||
"extractor": "max_stress",
|
||||
"goal": "minimize",
|
||||
"weight": 0.33,
|
||||
"description": "Minimize maximum von Mises stress (current: 131.507 MPa)"
|
||||
},
|
||||
{
|
||||
"name": "minimize_mass",
|
||||
"extractor": "mass",
|
||||
"goal": "minimize",
|
||||
"weight": 0.34,
|
||||
"description": "Minimize beam mass (p173 in kg, current: 973.97kg)"
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"name": "displacement_limit",
|
||||
"extractor": "max_displacement",
|
||||
"type": "less_than",
|
||||
"value": 10.0,
|
||||
"units": "mm",
|
||||
"description": "Maximum displacement must be less than 10mm across entire beam"
|
||||
}
|
||||
],
|
||||
"optimization_settings": {
|
||||
"algorithm": "optuna",
|
||||
"n_trials": 3,
|
||||
"sampler": "TPE",
|
||||
"pruner": "HyperbandPruner",
|
||||
"direction": "minimize",
|
||||
"timeout_per_trial": 600
|
||||
}
|
||||
}
|
||||
BIN
studies/simple_beam_optimization/model/Beam.prt
Normal file
BIN
studies/simple_beam_optimization/model/Beam.prt
Normal file
Binary file not shown.
BIN
studies/simple_beam_optimization/model/Beam_fem1.fem
Normal file
BIN
studies/simple_beam_optimization/model/Beam_fem1.fem
Normal file
Binary file not shown.
BIN
studies/simple_beam_optimization/model/Beam_fem1_i.prt
Normal file
BIN
studies/simple_beam_optimization/model/Beam_fem1_i.prt
Normal file
Binary file not shown.
BIN
studies/simple_beam_optimization/model/Beam_sim1.sim
Normal file
BIN
studies/simple_beam_optimization/model/Beam_sim1.sim
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"directory": "studies\\simple_beam_optimization\\model",
|
||||
"op2_files": [
|
||||
{
|
||||
"file_path": "studies\\simple_beam_optimization\\model\\beam_sim1-solution_1.op2",
|
||||
"subcases": [
|
||||
|
||||
350
studies/simple_beam_optimization/run_optimization.py
Normal file
350
studies/simple_beam_optimization/run_optimization.py
Normal file
@@ -0,0 +1,350 @@
|
||||
"""
|
||||
Simple Beam Optimization Study
|
||||
===============================
|
||||
|
||||
Multi-objective optimization:
|
||||
- Minimize displacement (constraint: < 10mm)
|
||||
- Minimize stress
|
||||
- Minimize mass
|
||||
|
||||
Design Variables:
|
||||
- beam_half_core_thickness: 10-40 mm
|
||||
- beam_face_thickness: 10-40 mm
|
||||
- holes_diameter: 150-450 mm
|
||||
- hole_count: 5-15
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import optuna
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from typing import Dict
|
||||
|
||||
# Add parent directories to path
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
from optimization_engine.nx_updater import NXParameterUpdater
|
||||
from optimization_engine.nx_solver import NXSolver
|
||||
from optimization_engine.result_extractors.generated.extract_displacement import extract_displacement
|
||||
from optimization_engine.result_extractors.generated.extract_solid_stress import extract_solid_stress
|
||||
from optimization_engine.result_extractors.generated.extract_expression import extract_expression
|
||||
|
||||
|
||||
def print_section(title: str):
|
||||
"""Print a section header."""
|
||||
print()
|
||||
print("=" * 80)
|
||||
print(f" {title}")
|
||||
print("=" * 80)
|
||||
print()
|
||||
|
||||
|
||||
def load_config(config_file: Path) -> dict:
|
||||
"""Load JSON configuration."""
|
||||
with open(config_file, 'r') as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def main():
|
||||
print_section("SIMPLE BEAM OPTIMIZATION STUDY")
|
||||
|
||||
# File paths
|
||||
study_dir = Path(__file__).parent
|
||||
config_file = study_dir / "beam_optimization_config.json"
|
||||
prt_file = study_dir / "model" / "Beam.prt"
|
||||
sim_file = study_dir / "model" / "Beam_sim1.sim"
|
||||
|
||||
if not config_file.exists():
|
||||
print(f"ERROR: Config file not found: {config_file}")
|
||||
sys.exit(1)
|
||||
|
||||
if not prt_file.exists():
|
||||
print(f"ERROR: Part file not found: {prt_file}")
|
||||
sys.exit(1)
|
||||
|
||||
if not sim_file.exists():
|
||||
print(f"ERROR: Simulation file not found: {sim_file}")
|
||||
sys.exit(1)
|
||||
|
||||
# Load configuration
|
||||
config = load_config(config_file)
|
||||
|
||||
print("Study Configuration:")
|
||||
print(f" - Study: {config['study_name']}")
|
||||
print(f" - Substudy: {config['substudy_name']}")
|
||||
print(f" - Description: {config['description']}")
|
||||
print()
|
||||
print("Objectives:")
|
||||
for obj in config['objectives']:
|
||||
print(f" - {obj['name']}: weight={obj['weight']}")
|
||||
print()
|
||||
print("Constraints:")
|
||||
for con in config['constraints']:
|
||||
print(f" - {con['name']}: {con['type']} {con['value']} {con['units']}")
|
||||
print()
|
||||
print("Design Variables:")
|
||||
for var_name, var_info in config['design_variables'].items():
|
||||
print(f" - {var_name}: {var_info['min']}-{var_info['max']} {var_info['units']}")
|
||||
print()
|
||||
print(f"Optimization Settings:")
|
||||
print(f" - Algorithm: {config['optimization_settings']['algorithm']}")
|
||||
print(f" - Trials: {config['optimization_settings']['n_trials']}")
|
||||
print(f" - Sampler: {config['optimization_settings']['sampler']}")
|
||||
print()
|
||||
|
||||
# Setup output directory
|
||||
output_dir = study_dir / "substudies" / config['substudy_name']
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print(f"Part file: {prt_file}")
|
||||
print(f"Simulation file: {sim_file}")
|
||||
print(f"Output directory: {output_dir}")
|
||||
print()
|
||||
|
||||
# =========================================================================
|
||||
# DEFINE OBJECTIVE FUNCTION
|
||||
# =========================================================================
|
||||
|
||||
def objective(trial: optuna.Trial) -> float:
|
||||
"""
|
||||
Optuna objective function.
|
||||
|
||||
Evaluates one design point:
|
||||
1. Updates geometry parameters
|
||||
2. Runs FEM simulation
|
||||
3. Extracts results
|
||||
4. Computes weighted multi-objective with penalties
|
||||
"""
|
||||
trial_num = trial.number
|
||||
|
||||
print(f"\n[Trial {trial_num}] Starting...")
|
||||
|
||||
# Sample design variables
|
||||
design_vars = {}
|
||||
for var_name, var_info in config['design_variables'].items():
|
||||
if var_info['type'] == 'continuous':
|
||||
design_vars[var_name] = trial.suggest_float(
|
||||
var_name,
|
||||
var_info['min'],
|
||||
var_info['max']
|
||||
)
|
||||
elif var_info['type'] == 'integer':
|
||||
design_vars[var_name] = trial.suggest_int(
|
||||
var_name,
|
||||
int(var_info['min']),
|
||||
int(var_info['max'])
|
||||
)
|
||||
|
||||
print(f"[Trial {trial_num}] Design variables:")
|
||||
for var_name, var_value in design_vars.items():
|
||||
print(f" - {var_name}: {var_value:.3f}")
|
||||
|
||||
# Create trial directory
|
||||
trial_dir = output_dir / f"trial_{trial_num:03d}"
|
||||
trial_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Copy all 4 files to trial directory (.prt, _i.prt, .fem, .sim)
|
||||
import shutil
|
||||
trial_prt = trial_dir / prt_file.name
|
||||
trial_sim = trial_dir / sim_file.name
|
||||
|
||||
shutil.copy2(prt_file, trial_prt)
|
||||
shutil.copy2(sim_file, trial_sim)
|
||||
|
||||
# Copy FEM file
|
||||
fem_file = prt_file.parent / f"{prt_file.stem}_fem1.fem"
|
||||
if fem_file.exists():
|
||||
trial_fem = trial_dir / fem_file.name
|
||||
shutil.copy2(fem_file, trial_fem)
|
||||
|
||||
# Copy idealized geometry (_i.prt) - contains midsurface thickness data
|
||||
# Pattern: Beam_fem1_i.prt (derived from FEM file name)
|
||||
if fem_file.exists():
|
||||
prt_i_file = prt_file.parent / f"{fem_file.stem}_i.prt"
|
||||
if prt_i_file.exists():
|
||||
trial_prt_i = trial_dir / prt_i_file.name
|
||||
shutil.copy2(prt_i_file, trial_prt_i)
|
||||
|
||||
try:
|
||||
# Update geometry
|
||||
print(f"[Trial {trial_num}] Updating geometry...")
|
||||
updater = NXParameterUpdater(trial_prt)
|
||||
updater.update_expressions(design_vars)
|
||||
|
||||
# Run simulation
|
||||
print(f"[Trial {trial_num}] Running FEM simulation...")
|
||||
solver = NXSolver()
|
||||
result = solver.run_simulation(trial_sim)
|
||||
|
||||
if not result['success']:
|
||||
raise RuntimeError(f"Simulation failed: {result}")
|
||||
|
||||
op2_file = result['op2_file']
|
||||
|
||||
print(f"[Trial {trial_num}] Extracting results...")
|
||||
|
||||
# Extract displacement
|
||||
disp_result = extract_displacement(op2_file)
|
||||
max_disp = disp_result['max_displacement']
|
||||
|
||||
# Extract stress
|
||||
stress_result = extract_solid_stress(op2_file)
|
||||
max_stress = stress_result['max_von_mises']
|
||||
|
||||
# Extract mass
|
||||
mass_result = extract_expression(trial_prt, 'p173')
|
||||
mass = mass_result['p173']
|
||||
|
||||
print(f"[Trial {trial_num}] Results:")
|
||||
print(f" - Displacement: {max_disp:.3f} mm")
|
||||
print(f" - Stress: {max_stress:.3f} MPa")
|
||||
print(f" - Mass: {mass:.3f} kg")
|
||||
|
||||
# Compute weighted multi-objective
|
||||
objective_value = 0.0
|
||||
|
||||
for obj in config['objectives']:
|
||||
if obj['extractor'] == 'max_displacement':
|
||||
value = max_disp
|
||||
elif obj['extractor'] == 'max_stress':
|
||||
value = max_stress
|
||||
elif obj['extractor'] == 'mass':
|
||||
value = mass
|
||||
else:
|
||||
continue
|
||||
|
||||
weight = obj['weight']
|
||||
objective_value += weight * value
|
||||
|
||||
# Apply constraint penalties
|
||||
penalty = 0.0
|
||||
for constraint in config['constraints']:
|
||||
if constraint['extractor'] == 'max_displacement':
|
||||
current_value = max_disp
|
||||
elif constraint['extractor'] == 'max_stress':
|
||||
current_value = max_stress
|
||||
else:
|
||||
continue
|
||||
|
||||
if constraint['type'] == 'less_than':
|
||||
if current_value > constraint['value']:
|
||||
violation = (current_value - constraint['value']) / constraint['value']
|
||||
penalty += 1000.0 * violation
|
||||
print(f"[Trial {trial_num}] CONSTRAINT VIOLATED: {constraint['name']}")
|
||||
print(f" Current: {current_value:.3f}, Limit: {constraint['value']}")
|
||||
|
||||
total_objective = objective_value + penalty
|
||||
|
||||
print(f"[Trial {trial_num}] Objective: {objective_value:.3f}, Penalty: {penalty:.3f}, Total: {total_objective:.3f}")
|
||||
|
||||
# Save trial results
|
||||
trial_results = {
|
||||
'trial_number': trial_num,
|
||||
'design_variables': design_vars,
|
||||
'results': {
|
||||
'max_displacement': max_disp,
|
||||
'max_stress': max_stress,
|
||||
'mass': mass
|
||||
},
|
||||
'objective': objective_value,
|
||||
'penalty': penalty,
|
||||
'total_objective': total_objective,
|
||||
'timestamp': datetime.now().isoformat()
|
||||
}
|
||||
|
||||
with open(trial_dir / "results.json", 'w') as f:
|
||||
json.dump(trial_results, f, indent=2)
|
||||
|
||||
return total_objective
|
||||
|
||||
except Exception as e:
|
||||
print(f"[Trial {trial_num}] FAILED: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return 1e10 # Return large penalty for failed trials
|
||||
|
||||
# =========================================================================
|
||||
# RUN OPTIMIZATION
|
||||
# =========================================================================
|
||||
|
||||
print_section("RUNNING OPTIMIZATION")
|
||||
|
||||
# Create Optuna study
|
||||
study = optuna.create_study(
|
||||
direction='minimize',
|
||||
sampler=optuna.samplers.TPESampler() if config['optimization_settings']['sampler'] == 'TPE' else None
|
||||
)
|
||||
|
||||
# Run optimization
|
||||
print(f"Starting {config['optimization_settings']['n_trials']} optimization trials...")
|
||||
print()
|
||||
|
||||
study.optimize(
|
||||
objective,
|
||||
n_trials=config['optimization_settings']['n_trials'],
|
||||
show_progress_bar=True
|
||||
)
|
||||
|
||||
# =========================================================================
|
||||
# SAVE RESULTS
|
||||
# =========================================================================
|
||||
|
||||
print_section("SAVING RESULTS")
|
||||
|
||||
# Save full study
|
||||
study_file = output_dir / "optuna_study.pkl"
|
||||
import pickle
|
||||
with open(study_file, 'wb') as f:
|
||||
pickle.dump(study, f)
|
||||
|
||||
print(f"Study saved to: {study_file}")
|
||||
|
||||
# Save best trial
|
||||
best_trial = study.best_trial
|
||||
best_results = {
|
||||
'best_trial_number': best_trial.number,
|
||||
'best_params': best_trial.params,
|
||||
'best_value': best_trial.value,
|
||||
'timestamp': datetime.now().isoformat()
|
||||
}
|
||||
|
||||
best_file = output_dir / "best_trial.json"
|
||||
with open(best_file, 'w') as f:
|
||||
json.dump(best_results, f, indent=2)
|
||||
|
||||
print(f"Best trial saved to: {best_file}")
|
||||
print()
|
||||
|
||||
# =========================================================================
|
||||
# PRINT SUMMARY
|
||||
# =========================================================================
|
||||
|
||||
print_section("OPTIMIZATION COMPLETE")
|
||||
|
||||
print(f"Total trials: {len(study.trials)}")
|
||||
print(f"Best trial: {best_trial.number}")
|
||||
print(f"Best objective value: {best_trial.value:.6f}")
|
||||
print()
|
||||
print("Best design variables:")
|
||||
for var_name, var_value in best_trial.params.items():
|
||||
print(f" - {var_name}: {var_value:.3f}")
|
||||
print()
|
||||
|
||||
# Load best trial results to show performance
|
||||
best_trial_dir = output_dir / f"trial_{best_trial.number:03d}"
|
||||
best_results_file = best_trial_dir / "results.json"
|
||||
|
||||
if best_results_file.exists():
|
||||
with open(best_results_file, 'r') as f:
|
||||
best_results = json.load(f)
|
||||
|
||||
print("Best performance:")
|
||||
print(f" - Displacement: {best_results['results']['max_displacement']:.3f} mm")
|
||||
print(f" - Stress: {best_results['results']['max_stress']:.3f} MPa")
|
||||
print(f" - Mass: {best_results['results']['mass']:.3f} kg")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
11
studies/simple_beam_optimization/study_metadata.json
Normal file
11
studies/simple_beam_optimization/study_metadata.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"study_name": "simple_beam_optimization",
|
||||
"description": "Minimize displacement and weight of beam with existing loadcases",
|
||||
"created": "2025-11-17T10:24:09.613688",
|
||||
"status": "benchmarked",
|
||||
"benchmarking_completed": true,
|
||||
"substudies": [
|
||||
"initial_exploration"
|
||||
],
|
||||
"last_benchmarking": "2025-11-17T11:18:40.783813"
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
# Benchmarking Report
|
||||
|
||||
**Study**: simple_beam_optimization
|
||||
**Date**: 2025-11-17T11:18:28.329069
|
||||
**Validation**: ✅ PASSED
|
||||
|
||||
## Model Introspection
|
||||
|
||||
**Expressions Found**: 30
|
||||
|
||||
| Expression | Value | Units |
|
||||
|------------|-------|-------|
|
||||
| Pattern_p7 | None | |
|
||||
| Pattern_p8 | 444.444444444444 | MilliMeter |
|
||||
| Pattern_p9 | None | MilliMeter |
|
||||
| Pattern_p10 | 1.0 | |
|
||||
| Pattern_p11 | 10.0 | MilliMeter |
|
||||
| Pattern_p12 | 0.0 | MilliMeter |
|
||||
| beam_face_thickness | 20.0 | MilliMeter |
|
||||
| beam_half_core_thickness | 20.0 | MilliMeter |
|
||||
| beam_half_height | 250.0 | MilliMeter |
|
||||
| beam_half_width | 150.0 | MilliMeter |
|
||||
| beam_lenght | 5000.0 | MilliMeter |
|
||||
| hole_count | 10.0 | |
|
||||
| holes_diameter | 300.0 | MilliMeter |
|
||||
| p4 | None | MilliMeter |
|
||||
| p5 | 0.0 | MilliMeter |
|
||||
| p6 | 4000.0 | MilliMeter |
|
||||
| p13 | 0.0 | Degrees |
|
||||
| p19 | 4000.0 | MilliMeter |
|
||||
| p34 | 4000.0 | MilliMeter |
|
||||
| p50 | 4000.0 | MilliMeter |
|
||||
| p119 | 4000.0 | MilliMeter |
|
||||
| p130 | 10.0 | |
|
||||
| p132 | 444.444444444444 | MilliMeter |
|
||||
| p134 | 4000.0 | MilliMeter |
|
||||
| p135 | 4000.0 | MilliMeter |
|
||||
| p137 | 1.0 | |
|
||||
| p139 | 10.0 | MilliMeter |
|
||||
| p141 | 0.0 | MilliMeter |
|
||||
| p143 | 0.0 | Degrees |
|
||||
| p173 | 973.968443678471 | Kilogram |
|
||||
|
||||
## OP2 Analysis
|
||||
|
||||
- **Element Types**: CQUAD4
|
||||
- **Result Types**: displacement, stress
|
||||
- **Subcases**: [1]
|
||||
- **Nodes**: 0
|
||||
- **Elements**: 0
|
||||
|
||||
## Baseline Performance
|
||||
|
||||
*No baseline results extracted*
|
||||
|
||||
## Configuration Proposals
|
||||
|
||||
### Proposed Design Variables
|
||||
|
||||
- **Pattern_p7**: ±20% of None
|
||||
- **Pattern_p8**: ±20% of 444.444444444444 MilliMeter
|
||||
- **Pattern_p9**: ±20% of None MilliMeter
|
||||
- **Pattern_p10**: ±20% of 1.0
|
||||
- **Pattern_p11**: ±20% of 10.0 MilliMeter
|
||||
- **Pattern_p12**: ±20% of 0.0 MilliMeter
|
||||
- **beam_face_thickness**: ±20% of 20.0 MilliMeter
|
||||
- **beam_half_core_thickness**: ±20% of 20.0 MilliMeter
|
||||
- **beam_half_height**: ±20% of 250.0 MilliMeter
|
||||
- **beam_half_width**: ±20% of 150.0 MilliMeter
|
||||
- **beam_lenght**: ±20% of 5000.0 MilliMeter
|
||||
- **hole_count**: ±20% of 10.0
|
||||
- **holes_diameter**: ±20% of 300.0 MilliMeter
|
||||
- **p4**: ±20% of None MilliMeter
|
||||
- **p5**: ±20% of 0.0 MilliMeter
|
||||
- **p6**: ±20% of 4000.0 MilliMeter
|
||||
- **p13**: ±20% of 0.0 Degrees
|
||||
- **p19**: ±20% of 4000.0 MilliMeter
|
||||
- **p34**: ±20% of 4000.0 MilliMeter
|
||||
- **p50**: ±20% of 4000.0 MilliMeter
|
||||
- **p119**: ±20% of 4000.0 MilliMeter
|
||||
- **p130**: ±20% of 10.0
|
||||
- **p132**: ±20% of 444.444444444444 MilliMeter
|
||||
- **p134**: ±20% of 4000.0 MilliMeter
|
||||
- **p135**: ±20% of 4000.0 MilliMeter
|
||||
- **p137**: ±20% of 1.0
|
||||
- **p139**: ±20% of 10.0 MilliMeter
|
||||
- **p141**: ±20% of 0.0 MilliMeter
|
||||
- **p143**: ±20% of 0.0 Degrees
|
||||
- **p173**: ±20% of 973.968443678471 Kilogram
|
||||
|
||||
### Proposed Extractors
|
||||
|
||||
- **extract_displacement**: Extract displacement results from OP2 file
|
||||
- **extract_solid_stress**: Extract stress from CQUAD4 elements
|
||||
|
||||
### Proposed Objectives
|
||||
|
||||
- max_displacement (minimize or maximize)
|
||||
- max_von_mises (minimize for safety)
|
||||
@@ -0,0 +1,408 @@
|
||||
{
|
||||
"timestamp": "2025-11-17T11:18:28.329069",
|
||||
"expressions": {
|
||||
"Pattern_p7": {
|
||||
"value": null,
|
||||
"units": "",
|
||||
"formula": "hole_count",
|
||||
"type": "Number"
|
||||
},
|
||||
"Pattern_p8": {
|
||||
"value": 444.444444444444,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"Pattern_p9": {
|
||||
"value": null,
|
||||
"units": "MilliMeter",
|
||||
"formula": "p6",
|
||||
"type": "Number"
|
||||
},
|
||||
"Pattern_p10": {
|
||||
"value": 1.0,
|
||||
"units": "",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"Pattern_p11": {
|
||||
"value": 10.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"Pattern_p12": {
|
||||
"value": 0.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"beam_face_thickness": {
|
||||
"value": 20.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"beam_half_core_thickness": {
|
||||
"value": 20.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"beam_half_height": {
|
||||
"value": 250.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"beam_half_width": {
|
||||
"value": 150.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"beam_lenght": {
|
||||
"value": 5000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"hole_count": {
|
||||
"value": 10.0,
|
||||
"units": "",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"holes_diameter": {
|
||||
"value": 300.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p4": {
|
||||
"value": null,
|
||||
"units": "MilliMeter",
|
||||
"formula": "beam_lenght",
|
||||
"type": "Number"
|
||||
},
|
||||
"p5": {
|
||||
"value": 0.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p6": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p13": {
|
||||
"value": 0.0,
|
||||
"units": "Degrees",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p19": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p34": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p50": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p119": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p130": {
|
||||
"value": 10.0,
|
||||
"units": "",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p132": {
|
||||
"value": 444.444444444444,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p134": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p135": {
|
||||
"value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p137": {
|
||||
"value": 1.0,
|
||||
"units": "",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p139": {
|
||||
"value": 10.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p141": {
|
||||
"value": 0.0,
|
||||
"units": "MilliMeter",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p143": {
|
||||
"value": 0.0,
|
||||
"units": "Degrees",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
},
|
||||
"p173": {
|
||||
"value": 973.968443678471,
|
||||
"units": "Kilogram",
|
||||
"formula": null,
|
||||
"type": "Number"
|
||||
}
|
||||
},
|
||||
"expression_count": 30,
|
||||
"element_types": [
|
||||
"CQUAD4"
|
||||
],
|
||||
"result_types": [
|
||||
"displacement",
|
||||
"stress"
|
||||
],
|
||||
"subcases": [
|
||||
1
|
||||
],
|
||||
"node_count": 0,
|
||||
"element_count": 0,
|
||||
"baseline_op2_path": "studies\\simple_beam_optimization\\model\\beam_sim1-solution_1.op2",
|
||||
"baseline_results": {},
|
||||
"simulation_works": true,
|
||||
"extraction_works": true,
|
||||
"validation_passed": true,
|
||||
"proposed_design_variables": [
|
||||
{
|
||||
"parameter": "Pattern_p7",
|
||||
"current_value": null,
|
||||
"units": "",
|
||||
"suggested_range": "\u00b120% of None "
|
||||
},
|
||||
{
|
||||
"parameter": "Pattern_p8",
|
||||
"current_value": 444.444444444444,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 444.444444444444 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "Pattern_p9",
|
||||
"current_value": null,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of None MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "Pattern_p10",
|
||||
"current_value": 1.0,
|
||||
"units": "",
|
||||
"suggested_range": "\u00b120% of 1.0 "
|
||||
},
|
||||
{
|
||||
"parameter": "Pattern_p11",
|
||||
"current_value": 10.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 10.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "Pattern_p12",
|
||||
"current_value": 0.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 0.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "beam_face_thickness",
|
||||
"current_value": 20.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 20.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "beam_half_core_thickness",
|
||||
"current_value": 20.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 20.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "beam_half_height",
|
||||
"current_value": 250.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 250.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "beam_half_width",
|
||||
"current_value": 150.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 150.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "beam_lenght",
|
||||
"current_value": 5000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 5000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "hole_count",
|
||||
"current_value": 10.0,
|
||||
"units": "",
|
||||
"suggested_range": "\u00b120% of 10.0 "
|
||||
},
|
||||
{
|
||||
"parameter": "holes_diameter",
|
||||
"current_value": 300.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 300.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p4",
|
||||
"current_value": null,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of None MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p5",
|
||||
"current_value": 0.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 0.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p6",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p13",
|
||||
"current_value": 0.0,
|
||||
"units": "Degrees",
|
||||
"suggested_range": "\u00b120% of 0.0 Degrees"
|
||||
},
|
||||
{
|
||||
"parameter": "p19",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p34",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p50",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p119",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p130",
|
||||
"current_value": 10.0,
|
||||
"units": "",
|
||||
"suggested_range": "\u00b120% of 10.0 "
|
||||
},
|
||||
{
|
||||
"parameter": "p132",
|
||||
"current_value": 444.444444444444,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 444.444444444444 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p134",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p135",
|
||||
"current_value": 4000.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 4000.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p137",
|
||||
"current_value": 1.0,
|
||||
"units": "",
|
||||
"suggested_range": "\u00b120% of 1.0 "
|
||||
},
|
||||
{
|
||||
"parameter": "p139",
|
||||
"current_value": 10.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 10.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p141",
|
||||
"current_value": 0.0,
|
||||
"units": "MilliMeter",
|
||||
"suggested_range": "\u00b120% of 0.0 MilliMeter"
|
||||
},
|
||||
{
|
||||
"parameter": "p143",
|
||||
"current_value": 0.0,
|
||||
"units": "Degrees",
|
||||
"suggested_range": "\u00b120% of 0.0 Degrees"
|
||||
},
|
||||
{
|
||||
"parameter": "p173",
|
||||
"current_value": 973.968443678471,
|
||||
"units": "Kilogram",
|
||||
"suggested_range": "\u00b120% of 973.968443678471 Kilogram"
|
||||
}
|
||||
],
|
||||
"proposed_extractors": [
|
||||
{
|
||||
"action": "extract_displacement",
|
||||
"description": "Extract displacement results from OP2 file",
|
||||
"params": {
|
||||
"result_type": "displacement"
|
||||
}
|
||||
},
|
||||
{
|
||||
"action": "extract_solid_stress",
|
||||
"description": "Extract stress from CQUAD4 elements",
|
||||
"params": {
|
||||
"result_type": "stress",
|
||||
"element_type": "cquad4"
|
||||
}
|
||||
}
|
||||
],
|
||||
"proposed_objectives": [
|
||||
"max_displacement (minimize or maximize)",
|
||||
"max_von_mises (minimize for safety)"
|
||||
],
|
||||
"warnings": [],
|
||||
"errors": []
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"study_name": "simple_beam_optimization",
|
||||
"description": "Minimize displacement and weight of beam with stress constraint",
|
||||
"substudy_name": "initial_exploration",
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": {
|
||||
"type": "continuous",
|
||||
"min": 10.0,
|
||||
"max": 40.0,
|
||||
"baseline": 20.0,
|
||||
"units": "mm",
|
||||
"description": "Half thickness of beam core"
|
||||
},
|
||||
"beam_face_thickness": {
|
||||
"type": "continuous",
|
||||
"min": 10.0,
|
||||
"max": 40.0,
|
||||
"baseline": 20.0,
|
||||
"units": "mm",
|
||||
"description": "Thickness of beam face sheets"
|
||||
},
|
||||
"holes_diameter": {
|
||||
"type": "continuous",
|
||||
"min": 150.0,
|
||||
"max": 450.0,
|
||||
"baseline": 300.0,
|
||||
"units": "mm",
|
||||
"description": "Diameter of lightening holes"
|
||||
},
|
||||
"hole_count": {
|
||||
"type": "integer",
|
||||
"min": 5,
|
||||
"max": 20,
|
||||
"baseline": 10,
|
||||
"units": "unitless",
|
||||
"description": "Number of lightening holes"
|
||||
}
|
||||
},
|
||||
"extractors": [
|
||||
{
|
||||
"name": "max_displacement",
|
||||
"action": "extract_displacement",
|
||||
"description": "Extract maximum displacement from OP2",
|
||||
"parameters": {
|
||||
"metric": "max"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "max_von_mises",
|
||||
"action": "extract_solid_stress",
|
||||
"description": "Extract maximum von Mises stress from OP2",
|
||||
"parameters": {
|
||||
"stress_type": "von_mises",
|
||||
"metric": "max"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mass",
|
||||
"action": "extract_expression",
|
||||
"description": "Extract mass from p173 expression",
|
||||
"parameters": {
|
||||
"expression_name": "p173"
|
||||
}
|
||||
}
|
||||
],
|
||||
"objectives": [
|
||||
{
|
||||
"name": "minimize_stress",
|
||||
"extractor": "max_von_mises",
|
||||
"goal": "minimize",
|
||||
"weight": 0.5,
|
||||
"description": "Minimize maximum von Mises stress for structural safety"
|
||||
},
|
||||
{
|
||||
"name": "minimize_weight",
|
||||
"extractor": "mass",
|
||||
"goal": "minimize",
|
||||
"weight": 0.5,
|
||||
"description": "Minimize beam mass (p173 in kg)"
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"name": "displacement_limit",
|
||||
"extractor": "max_displacement",
|
||||
"type": "less_than",
|
||||
"value": 10.0,
|
||||
"units": "mm",
|
||||
"description": "Maximum displacement must be less than 10mm across entire beam"
|
||||
}
|
||||
],
|
||||
"optimization_settings": {
|
||||
"algorithm": "optuna",
|
||||
"n_trials": 50,
|
||||
"sampler": "TPE",
|
||||
"pruner": "HyperbandPruner",
|
||||
"direction": "minimize",
|
||||
"timeout_per_trial": 600
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"study_name": "simple_beam_optimization",
|
||||
"description": "Minimize displacement and weight of beam with stress constraint",
|
||||
"substudy_name": "initial_exploration",
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": {
|
||||
"type": "continuous",
|
||||
"min": 10.0,
|
||||
"max": 40.0,
|
||||
"baseline": 20.0,
|
||||
"units": "mm",
|
||||
"description": "Half thickness of beam core"
|
||||
},
|
||||
"beam_face_thickness": {
|
||||
"type": "continuous",
|
||||
"min": 10.0,
|
||||
"max": 40.0,
|
||||
"baseline": 20.0,
|
||||
"units": "mm",
|
||||
"description": "Thickness of beam face sheets"
|
||||
},
|
||||
"holes_diameter": {
|
||||
"type": "continuous",
|
||||
"min": 150.0,
|
||||
"max": 450.0,
|
||||
"baseline": 300.0,
|
||||
"units": "mm",
|
||||
"description": "Diameter of lightening holes"
|
||||
},
|
||||
"hole_count": {
|
||||
"type": "integer",
|
||||
"min": 5,
|
||||
"max": 20,
|
||||
"baseline": 10,
|
||||
"units": "unitless",
|
||||
"description": "Number of lightening holes"
|
||||
}
|
||||
},
|
||||
"extractors": [
|
||||
{
|
||||
"name": "max_displacement",
|
||||
"action": "extract_displacement",
|
||||
"description": "Extract maximum displacement from OP2",
|
||||
"parameters": {
|
||||
"metric": "max"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "max_von_mises",
|
||||
"action": "extract_solid_stress",
|
||||
"description": "Extract maximum von Mises stress from OP2",
|
||||
"parameters": {
|
||||
"stress_type": "von_mises",
|
||||
"metric": "max"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mass",
|
||||
"action": "extract_expression",
|
||||
"description": "Extract mass from p173 expression",
|
||||
"parameters": {
|
||||
"expression_name": "p173"
|
||||
}
|
||||
}
|
||||
],
|
||||
"objectives": [
|
||||
{
|
||||
"name": "minimize_stress",
|
||||
"extractor": "max_von_mises",
|
||||
"goal": "minimize",
|
||||
"weight": 0.5,
|
||||
"description": "Minimize maximum von Mises stress for structural safety"
|
||||
},
|
||||
{
|
||||
"name": "minimize_weight",
|
||||
"extractor": "mass",
|
||||
"goal": "minimize",
|
||||
"weight": 0.5,
|
||||
"description": "Minimize beam mass (p173 in kg)"
|
||||
}
|
||||
],
|
||||
"constraints": [
|
||||
{
|
||||
"name": "displacement_limit",
|
||||
"extractor": "max_displacement",
|
||||
"type": "less_than",
|
||||
"value": 10.0,
|
||||
"units": "mm",
|
||||
"description": "Maximum displacement must be less than 10mm across entire beam"
|
||||
}
|
||||
],
|
||||
"optimization_settings": {
|
||||
"algorithm": "optuna",
|
||||
"n_trials": 50,
|
||||
"sampler": "TPE",
|
||||
"pruner": "HyperbandPruner",
|
||||
"direction": "minimize",
|
||||
"timeout_per_trial": 600
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"best_trial_number": 0,
|
||||
"best_params": {
|
||||
"beam_half_core_thickness": 29.337408537581144,
|
||||
"beam_face_thickness": 30.46892531252702,
|
||||
"holes_diameter": 355.50168387567,
|
||||
"hole_count": 9
|
||||
},
|
||||
"best_value": 1593.7016555239895,
|
||||
"timestamp": "2025-11-17T12:07:15.761846"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"trial_number": 0,
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": 29.337408537581144,
|
||||
"beam_face_thickness": 30.46892531252702,
|
||||
"holes_diameter": 355.50168387567,
|
||||
"hole_count": 9
|
||||
},
|
||||
"results": {
|
||||
"max_displacement": 22.118558883666992,
|
||||
"max_stress": 131.5071875,
|
||||
"mass": 973.968443678471
|
||||
},
|
||||
"objective": 381.8457671572903,
|
||||
"penalty": 1211.8558883666992,
|
||||
"total_objective": 1593.7016555239895,
|
||||
"timestamp": "2025-11-17T12:07:06.957242"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"best_trial_number": 1,
|
||||
"best_params": {
|
||||
"beam_half_core_thickness": 13.335138090779976,
|
||||
"beam_face_thickness": 36.82522985402573,
|
||||
"holes_diameter": 415.43387770285864,
|
||||
"hole_count": 15
|
||||
},
|
||||
"best_value": 1143.4527894999778,
|
||||
"timestamp": "2025-11-17T12:29:37.481988"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"trial_number": 0,
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": 26.634771334983725,
|
||||
"beam_face_thickness": 23.041706900371068,
|
||||
"holes_diameter": 157.22022765320852,
|
||||
"hole_count": 6
|
||||
},
|
||||
"results": {
|
||||
"max_displacement": 16.740266799926758,
|
||||
"max_stress": 104.73846875,
|
||||
"mass": 1447.02973874444
|
||||
},
|
||||
"objective": 532.0780939045854,
|
||||
"penalty": 674.0266799926758,
|
||||
"total_objective": 1206.104773897261,
|
||||
"timestamp": "2025-11-17T12:28:44.775388"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"trial_number": 1,
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": 13.335138090779976,
|
||||
"beam_face_thickness": 36.82522985402573,
|
||||
"holes_diameter": 415.43387770285864,
|
||||
"hole_count": 15
|
||||
},
|
||||
"results": {
|
||||
"max_displacement": 16.610559463500977,
|
||||
"max_stress": 164.141953125,
|
||||
"mass": 1243.37798234022
|
||||
},
|
||||
"objective": 482.3968431498801,
|
||||
"penalty": 661.0559463500977,
|
||||
"total_objective": 1143.4527894999778,
|
||||
"timestamp": "2025-11-17T12:29:11.287235"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"trial_number": 2,
|
||||
"design_variables": {
|
||||
"beam_half_core_thickness": 19.64544476046235,
|
||||
"beam_face_thickness": 24.671288535930103,
|
||||
"holes_diameter": 305.1411636455331,
|
||||
"hole_count": 11
|
||||
},
|
||||
"results": {
|
||||
"max_displacement": 20.071578979492188,
|
||||
"max_stress": 119.826984375,
|
||||
"mass": 1053.38667475693
|
||||
},
|
||||
"objective": 404.31799532433865,
|
||||
"penalty": 1007.1578979492189,
|
||||
"total_objective": 1411.4758932735576,
|
||||
"timestamp": "2025-11-17T12:29:37.479981"
|
||||
}
|
||||
Reference in New Issue
Block a user