feat: Add AtomizerField training data export and intelligent model discovery
Major additions: - Training data export system for AtomizerField neural network training - Bracket stiffness optimization study with 50+ training samples - Intelligent NX model discovery (auto-detect solutions, expressions, mesh) - Result extractors module for displacement, stress, frequency, mass - User-generated NX journals for advanced workflows - Archive structure for legacy scripts and test outputs - Protocol documentation and dashboard launcher 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,32 @@
|
||||
Nastran BUFFSIZE=32769 $(c:/program files/siemens/nx2412/nxnastran/conf/nastran.rcf[1])
|
||||
Nastran BUFFPOOL=20.0X $(c:/program files/siemens/nx2412/nxnastran/conf/nastran.rcf[4])
|
||||
Nastran DIAGA=128 DIAGB=0 $(c:/program files/siemens/nx2412/nxnastran/conf/nastran.rcf[7])
|
||||
Nastran REAL=8545370112 $(Memory limit for MPI and other specialized modules)
|
||||
JID='C:\Users\antoi\Documents\Atomaste\Atomizer\studies\bracket_stiffness_optimization_atomizerfield\1_setup\model\bracket_sim1-solution_1.dat'
|
||||
OUT='./bracket_sim1-solution_1'
|
||||
MEM=3846123520
|
||||
MACH='Intel64 Family 6 Model 183 Stepping 1'
|
||||
OPER='Windows 10'
|
||||
OSV=' '
|
||||
MODEL='Intel(R) Core(TM) i7-14700HX (AntoineThinkpad)'
|
||||
CONFIG=8666
|
||||
NPROC=28
|
||||
symbol=DELDIR='c:/program files/siemens/nx2412/nxnastran/scnas/nast/del' $(program default)
|
||||
symbol=DEMODIR='c:/program files/siemens/nx2412/nxnastran/scnas/nast/demo' $(program default)
|
||||
symbol=SSSALTERDIR='c:/program files/siemens/nx2412/nxnastran/scnas/nast/misc/sssalter' $(program default)
|
||||
symbol=TPLDIR='c:/program files/siemens/nx2412/nxnastran/scnas/nast/tpl' $(program default)
|
||||
SDIR='c:/users/antoi/appdata/local/temp/bracket_sim1-solution_1.T199472_25'
|
||||
DBS='c:/users/antoi/appdata/local/temp/bracket_sim1-solution_1.T199472_25'
|
||||
SCR=yes
|
||||
SMEM=20.0X
|
||||
NEWDEL='c:/program files/siemens/nx2412/nxnastran/scnas/em64tntl/SSS'
|
||||
DEL='NXNDEF'
|
||||
AUTH='29000@AntoineThinkpad'
|
||||
AUTHQUE=0
|
||||
MSGCAT='c:/program files/siemens/nx2412/nxnastran/scnas/em64tntl/analysis.msg'
|
||||
MSGDEST='f06'
|
||||
PROG=bundle
|
||||
NEWS='c:/program files/siemens/nx2412/nxnastran/scnas/nast/news.txt'
|
||||
UMATLIB='libnxumat.dll'
|
||||
UCRPLIB='libucreep.dll'
|
||||
USOLLIB='libusol.dll'
|
||||
@@ -0,0 +1,91 @@
|
||||
"""
|
||||
NX Journal - Export Displacement Field for Bracket Stiffness Analysis
|
||||
=====================================================================
|
||||
|
||||
This journal exports the z-displacement field from a ResultProbe to a .fld file.
|
||||
|
||||
Usage:
|
||||
run_journal.exe export_displacement_field.py [sim_file_path]
|
||||
|
||||
If sim_file_path is not provided, uses Bracket_sim1.sim in the same directory.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import math
|
||||
from pathlib import Path
|
||||
import NXOpen
|
||||
import NXOpen.CAE
|
||||
import NXOpen.Fields
|
||||
|
||||
|
||||
def main(args):
|
||||
"""
|
||||
Export displacement field from NX simulation results.
|
||||
|
||||
Args:
|
||||
args: Command line arguments, optionally including sim file path
|
||||
|
||||
The ResultProbe should already be defined in the simulation file
|
||||
with z-displacement as the measured quantity.
|
||||
"""
|
||||
theSession = NXOpen.Session.GetSession()
|
||||
|
||||
# Determine sim file to open
|
||||
if len(args) > 0:
|
||||
sim_file = Path(args[0])
|
||||
else:
|
||||
# Default: Bracket_sim1.sim in same directory as this journal
|
||||
journal_dir = Path(__file__).parent
|
||||
sim_file = journal_dir / "Bracket_sim1.sim"
|
||||
|
||||
if not sim_file.exists():
|
||||
print(f"ERROR: Simulation file not found: {sim_file}")
|
||||
return 1
|
||||
|
||||
# Open the simulation file
|
||||
print(f"Opening simulation: {sim_file}")
|
||||
try:
|
||||
basePart1, partLoadStatus1 = theSession.Parts.OpenBaseDisplay(str(sim_file))
|
||||
partLoadStatus1.Dispose()
|
||||
except Exception as e:
|
||||
print(f"ERROR: Failed to open simulation: {e}")
|
||||
return 1
|
||||
|
||||
workSimPart = theSession.Parts.BaseWork
|
||||
if workSimPart is None:
|
||||
print("ERROR: No work part loaded after opening simulation.")
|
||||
return 1
|
||||
|
||||
# Get the FieldManager
|
||||
fieldManager = workSimPart.FindObject("FieldManager")
|
||||
if fieldManager is None:
|
||||
print("ERROR: FieldManager not found. Make sure simulation results are loaded.")
|
||||
return 1
|
||||
|
||||
# Find the ResultProbe (should be pre-configured for z-displacement)
|
||||
resultProbe = fieldManager.FindObject("ResultProbe")
|
||||
if resultProbe is None:
|
||||
print("ERROR: ResultProbe not found. Please create a ResultProbe for z-displacement.")
|
||||
return 1
|
||||
|
||||
# Prepare probe array for export
|
||||
probes = [NXOpen.CAE.ResultProbe.Null] * 1
|
||||
probes[0] = resultProbe
|
||||
|
||||
# Determine output file path (same directory as this journal)
|
||||
journal_dir = Path(__file__).parent
|
||||
output_file = journal_dir / "export_field_dz.fld"
|
||||
|
||||
# Export to field file
|
||||
print(f"Exporting displacement field to: {output_file}")
|
||||
theSession.ResultManager.ExportProbesToFieldFile(probes, str(output_file))
|
||||
|
||||
print(f"[OK] Successfully exported displacement field")
|
||||
print(f" Output: {output_file}")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit_code = main(sys.argv[1:])
|
||||
sys.exit(exit_code)
|
||||
@@ -0,0 +1,48 @@
|
||||
FIELD: [ResultProbe] : [TABLE]
|
||||
FIELD LOCK STATE: [NO]
|
||||
DUPLICATE_VALUE_OPTION: [0]
|
||||
PARAMETERIZE INDEPENDENT DOMAIN: [NO]
|
||||
PERSIST INTERPOL: [NO]
|
||||
CREATE INTERPOLATOR: [NO]
|
||||
FALLBACK DEFAULT INTERPOLATOR: [YES]
|
||||
INTERPOL: [4]
|
||||
VALUES OUTSIDE: [2]
|
||||
REMOVE DELAUNAY SLIVERS: [NO]
|
||||
INDEP VAR: [step] : [] : [] : [0]
|
||||
BOUNDS: [0] : [YES] : [0] : [YES] : [27] : [0]
|
||||
INDEP VAR: [node_id] : [] : [] : [5]
|
||||
BOUNDS: [3] : [YES] : [413] : [YES] : [27] : [407]
|
||||
DEP VAR: [x] : [Length] : [mm] : [0]
|
||||
DESCRIPTION: ResultProbe
|
||||
DESCRIPTION: dz
|
||||
DESCRIPTION: 21-Nov-25
|
||||
DESCRIPTION: 19:25:36
|
||||
START DATA
|
||||
0, 407, -0.0941346362233162
|
||||
0, 408, -0.0937454551458359
|
||||
0, 409, -0.0935764610767365
|
||||
0, 410, -0.0935385450720787
|
||||
0, 411, -0.0980110093951225
|
||||
0, 412, -0.0959530174732208
|
||||
0, 413, -0.094814196228981
|
||||
0, 3, -0.10150358080864
|
||||
0, 6, -0.101503469049931
|
||||
0, 14, -0.0935568511486053
|
||||
0, 11, -0.0935568138957024
|
||||
0, 113, -0.0937929674983025
|
||||
0, 114, -0.0942020565271378
|
||||
0, 115, -0.0935586988925934
|
||||
0, 116, -0.0936075374484062
|
||||
0, 117, -0.0979839861392975
|
||||
0, 118, -0.0960513949394226
|
||||
0, 119, -0.0949068069458008
|
||||
0, 52, -0.101693071424961
|
||||
0, 145, -0.0942021608352661
|
||||
0, 146, -0.093793049454689
|
||||
0, 147, -0.0935587361454964
|
||||
0, 148, -0.093607597053051
|
||||
0, 149, -0.0979839861392975
|
||||
0, 150, -0.0960515514016151
|
||||
0, 151, -0.0949069485068321
|
||||
0, 122, -0.0935398191213608
|
||||
END DATA
|
||||
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"study_name": "bracket_stiffness_optimization_atomizerfield",
|
||||
"description": "Bracket Stiffness Optimization with AtomizerField Neural Acceleration - Multi-objective optimization of bracket geometry for maximum stiffness and minimum mass",
|
||||
"engineering_context": "L-bracket optimization for mounting applications. Uses AtomizerField neural surrogate for accelerated optimization after initial FEA exploration phase.",
|
||||
|
||||
"template_info": {
|
||||
"category": "structural",
|
||||
"analysis_type": "static",
|
||||
"typical_applications": ["mounting brackets", "L-brackets", "support structures"],
|
||||
"based_on": "bracket_stiffness_optimization_V3",
|
||||
"neural_enabled": true
|
||||
},
|
||||
|
||||
"optimization_settings": {
|
||||
"protocol": "protocol_11_multi_objective",
|
||||
"n_trials": 100,
|
||||
"sampler": "NSGAIISampler",
|
||||
"pruner": null,
|
||||
"timeout_per_trial": 400,
|
||||
"fea_exploration_trials": 50,
|
||||
"neural_acceleration_trials": 50
|
||||
},
|
||||
|
||||
"design_variables": [
|
||||
{
|
||||
"parameter": "support_angle",
|
||||
"bounds": [20, 70],
|
||||
"description": "Angle of the support arm (degrees)",
|
||||
"units": "degrees"
|
||||
},
|
||||
{
|
||||
"parameter": "tip_thickness",
|
||||
"bounds": [30, 60],
|
||||
"description": "Thickness at the bracket tip (mm)",
|
||||
"units": "mm"
|
||||
}
|
||||
],
|
||||
|
||||
"objectives": [
|
||||
{
|
||||
"name": "stiffness",
|
||||
"goal": "maximize",
|
||||
"weight": 1.0,
|
||||
"description": "Structural stiffness (inverse of max displacement)",
|
||||
"extraction": {
|
||||
"action": "extract_displacement",
|
||||
"domain": "result_extraction",
|
||||
"params": {
|
||||
"result_type": "displacement",
|
||||
"metric": "max",
|
||||
"invert_for_stiffness": true
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "mass",
|
||||
"goal": "minimize",
|
||||
"weight": 0.1,
|
||||
"description": "Total bracket mass (kg)",
|
||||
"extraction": {
|
||||
"action": "extract_mass",
|
||||
"domain": "result_extraction",
|
||||
"params": {
|
||||
"result_type": "mass",
|
||||
"metric": "total"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"constraints": [
|
||||
{
|
||||
"name": "mass_limit",
|
||||
"type": "less_than",
|
||||
"threshold": 0.2,
|
||||
"description": "Maximum mass constraint (kg)",
|
||||
"extraction": {
|
||||
"action": "extract_mass",
|
||||
"domain": "result_extraction",
|
||||
"params": {
|
||||
"result_type": "mass",
|
||||
"metric": "total"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
"simulation": {
|
||||
"model_file": "Bracket.prt",
|
||||
"sim_file": "Bracket_sim1.sim",
|
||||
"fem_file": "Bracket_fem1.fem",
|
||||
"solver": "nastran",
|
||||
"analysis_types": ["static"],
|
||||
"solution_name": "Solution 1",
|
||||
"dat_file": "bracket_sim1-solution_1.dat",
|
||||
"op2_file": "bracket_sim1-solution_1.op2",
|
||||
"field_export_journal": "export_displacement_field.py",
|
||||
"field_output_file": "export_field_dz.fld"
|
||||
},
|
||||
|
||||
"result_extraction": {
|
||||
"mass": {
|
||||
"method": "bdf_mass_extractor",
|
||||
"source": "bracket_sim1-solution_1.dat",
|
||||
"extractor_module": "optimization_engine.extractors.bdf_mass_extractor",
|
||||
"function": "extract_mass_from_bdf",
|
||||
"output_unit": "kg"
|
||||
},
|
||||
"stiffness": {
|
||||
"method": "stiffness_calculator",
|
||||
"displacement_source": "export_field_dz.fld",
|
||||
"force_source": "bracket_sim1-solution_1.op2",
|
||||
"extractor_module": "optimization_engine.extractors.stiffness_calculator",
|
||||
"force_component": "fz",
|
||||
"displacement_component": "z",
|
||||
"output_unit": "N/mm"
|
||||
},
|
||||
"displacement": {
|
||||
"method": "op2_displacement",
|
||||
"source": "bracket_sim1-solution_1.op2",
|
||||
"extractor_module": "optimization_engine.extractors.extract_displacement",
|
||||
"function": "extract_displacement",
|
||||
"output_unit": "mm"
|
||||
}
|
||||
},
|
||||
|
||||
"reporting": {
|
||||
"generate_plots": true,
|
||||
"save_incremental": true,
|
||||
"llm_summary": true,
|
||||
"generate_pareto_front": true
|
||||
},
|
||||
|
||||
"training_data_export": {
|
||||
"enabled": true,
|
||||
"export_dir": "atomizer_field_training_data/bracket_stiffness_optimization_atomizerfield",
|
||||
"export_every_n_trials": 1,
|
||||
"include_mesh": true,
|
||||
"compress": false
|
||||
},
|
||||
|
||||
"neural_acceleration": {
|
||||
"enabled": true,
|
||||
"min_training_points": 50,
|
||||
"auto_train": true,
|
||||
"epochs": 100,
|
||||
"validation_split": 0.2,
|
||||
"retrain_threshold": 25,
|
||||
"model_type": "parametric"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,48 @@
|
||||
# Dashboard Access
|
||||
|
||||
## Quick Links
|
||||
|
||||
| Dashboard | URL | Purpose |
|
||||
|-----------|-----|---------|
|
||||
| **Atomizer Dashboard** | [http://localhost:3003](http://localhost:3003) | Live Pareto plots, optimization monitoring |
|
||||
| **Optuna Dashboard** | [http://localhost:8081](http://localhost:8081) | Trial history, hyperparameter importance |
|
||||
|
||||
## Starting the Dashboards
|
||||
|
||||
### Atomizer Dashboard (Recommended)
|
||||
```bash
|
||||
# From project root - Terminal 1 (backend)
|
||||
cd atomizer-dashboard/backend
|
||||
python -m uvicorn api.main:app --host 0.0.0.0 --port 8000 --reload
|
||||
|
||||
# From project root - Terminal 2 (frontend)
|
||||
cd atomizer-dashboard/frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Optuna Dashboard (This Study Only)
|
||||
```bash
|
||||
# From this study directory
|
||||
optuna-dashboard sqlite:///2_results/study.db --port 8081
|
||||
|
||||
# Or from project root
|
||||
optuna-dashboard sqlite:///studies/bracket_stiffness_optimization_atomizerfield/2_results/study.db --port 8081
|
||||
```
|
||||
|
||||
## What Each Dashboard Shows
|
||||
|
||||
### Atomizer Dashboard (localhost:3003)
|
||||
- **Pareto Front**: Interactive scatter plot of stiffness vs mass
|
||||
- **Parallel Coordinates**: Visualize how design variables affect objectives
|
||||
- **Study List**: Compare multiple optimization studies
|
||||
- **Trial Progress**: Real-time updates during optimization
|
||||
|
||||
### Optuna Dashboard (localhost:8081)
|
||||
- **Trial History**: Complete log of all trials with parameters and values
|
||||
- **Hyperparameter Importance**: Which variables matter most
|
||||
- **Optimization History**: Convergence over time
|
||||
- **Slice Plots**: 1D parameter sensitivity
|
||||
|
||||
---
|
||||
|
||||
**Tip**: The Atomizer Dashboard connects to any running study automatically. The Optuna Dashboard is study-specific and requires the database path.
|
||||
449
studies/bracket_stiffness_optimization_atomizerfield/README.md
Normal file
449
studies/bracket_stiffness_optimization_atomizerfield/README.md
Normal file
@@ -0,0 +1,449 @@
|
||||
# Bracket Stiffness Optimization - AtomizerField
|
||||
|
||||
Multi-objective bracket geometry optimization with neural network acceleration.
|
||||
|
||||
**Created**: 2025-11-26
|
||||
**Protocol**: Protocol 11 (Multi-Objective NSGA-II)
|
||||
**Status**: Ready to Run
|
||||
|
||||
---
|
||||
|
||||
## 1. Engineering Problem
|
||||
|
||||
### 1.1 Objective
|
||||
|
||||
Optimize an L-bracket mounting structure to maximize structural stiffness while minimizing mass, subject to manufacturing constraints.
|
||||
|
||||
### 1.2 Physical System
|
||||
|
||||
- **Component**: L-shaped mounting bracket
|
||||
- **Material**: Steel (density ρ defined in NX model)
|
||||
- **Loading**: Static force applied in Z-direction
|
||||
- **Boundary Conditions**: Fixed support at mounting face
|
||||
- **Analysis Type**: Linear static (Nastran SOL 101)
|
||||
|
||||
---
|
||||
|
||||
## 2. Mathematical Formulation
|
||||
|
||||
### 2.1 Objectives
|
||||
|
||||
| Objective | Goal | Weight | Formula | Units |
|
||||
|-----------|------|--------|---------|-------|
|
||||
| Stiffness | maximize | 1.0 | $k = \frac{F}{\delta_{max}}$ | N/mm |
|
||||
| Mass | minimize | 0.1 | $m = \sum_{e} \rho_e V_e$ | kg |
|
||||
|
||||
Where:
|
||||
- $k$ = structural stiffness
|
||||
- $F$ = applied force magnitude (N)
|
||||
- $\delta_{max}$ = maximum absolute displacement (mm)
|
||||
- $\rho_e$ = element material density (kg/mm³)
|
||||
- $V_e$ = element volume (mm³)
|
||||
|
||||
### 2.2 Design Variables
|
||||
|
||||
| Parameter | Symbol | Bounds | Units | Description |
|
||||
|-----------|--------|--------|-------|-------------|
|
||||
| Support Angle | $\theta$ | [20, 70] | degrees | Angle of the support arm relative to base |
|
||||
| Tip Thickness | $t$ | [30, 60] | mm | Thickness at the bracket tip |
|
||||
|
||||
**Design Space**:
|
||||
$$\mathbf{x} = [\theta, t]^T \in \mathbb{R}^2$$
|
||||
$$20 \leq \theta \leq 70$$
|
||||
$$30 \leq t \leq 60$$
|
||||
|
||||
### 2.3 Constraints
|
||||
|
||||
| Constraint | Type | Formula | Threshold | Handling |
|
||||
|------------|------|---------|-----------|----------|
|
||||
| Mass Limit | Inequality | $g_1(\mathbf{x}) = m - m_{max}$ | $m_{max} = 0.2$ kg | Infeasible if violated |
|
||||
|
||||
**Feasible Region**:
|
||||
$$\mathcal{F} = \{\mathbf{x} : g_1(\mathbf{x}) \leq 0\}$$
|
||||
|
||||
### 2.4 Multi-Objective Formulation
|
||||
|
||||
**Pareto Optimization Problem**:
|
||||
$$\max_{\mathbf{x} \in \mathcal{F}} \quad k(\mathbf{x})$$
|
||||
$$\min_{\mathbf{x} \in \mathcal{F}} \quad m(\mathbf{x})$$
|
||||
|
||||
**Pareto Dominance**: Solution $\mathbf{x}_1$ dominates $\mathbf{x}_2$ if:
|
||||
- $k(\mathbf{x}_1) \geq k(\mathbf{x}_2)$ and $m(\mathbf{x}_1) \leq m(\mathbf{x}_2)$
|
||||
- With at least one strict inequality
|
||||
|
||||
---
|
||||
|
||||
## 3. Optimization Algorithm
|
||||
|
||||
### 3.1 NSGA-II Configuration
|
||||
|
||||
| Parameter | Value | Description |
|
||||
|-----------|-------|-------------|
|
||||
| Algorithm | NSGA-II | Non-dominated Sorting Genetic Algorithm II |
|
||||
| Population | auto | Managed by Optuna |
|
||||
| Directions | `['maximize', 'minimize']` | (stiffness, mass) |
|
||||
| Sampler | `NSGAIISampler` | Multi-objective sampler |
|
||||
| Trials | 100 | 50 FEA + 50 neural |
|
||||
|
||||
**NSGA-II Properties**:
|
||||
- Fast non-dominated sorting: $O(MN^2)$ where $M$ = objectives, $N$ = population
|
||||
- Crowding distance for diversity preservation
|
||||
- Binary tournament selection with crowding comparison
|
||||
|
||||
### 3.2 Return Format
|
||||
|
||||
```python
|
||||
def objective(trial) -> Tuple[float, float]:
|
||||
# ... simulation and extraction ...
|
||||
return (stiffness, mass) # Tuple, NOT negated
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Simulation Pipeline
|
||||
|
||||
### 4.1 Trial Execution Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ TRIAL n EXECUTION │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 1. OPTUNA SAMPLES (NSGA-II) │
|
||||
│ θ = trial.suggest_float("support_angle", 20, 70) │
|
||||
│ t = trial.suggest_float("tip_thickness", 30, 60) │
|
||||
│ │
|
||||
│ 2. NX PARAMETER UPDATE │
|
||||
│ Module: optimization_engine/nx_updater.py │
|
||||
│ Action: Bracket.prt expressions ← {θ, t} │
|
||||
│ │
|
||||
│ 3. HOOK: PRE_SOLVE │
|
||||
│ → Log trial start, validate design bounds │
|
||||
│ │
|
||||
│ 4. NX SIMULATION (Nastran SOL 101) │
|
||||
│ Module: optimization_engine/solve_simulation.py │
|
||||
│ Input: Bracket_sim1.sim │
|
||||
│ Output: .dat, .op2, .f06 │
|
||||
│ │
|
||||
│ 5. HOOK: POST_SOLVE │
|
||||
│ → Run export_displacement_field.py │
|
||||
│ → Generate export_field_dz.fld │
|
||||
│ │
|
||||
│ 6. RESULT EXTRACTION │
|
||||
│ Mass ← bdf_mass_extractor(.dat) │
|
||||
│ Stiffness ← stiffness_calculator(.fld, .op2) │
|
||||
│ │
|
||||
│ 7. HOOK: POST_EXTRACTION │
|
||||
│ → Export BDF/OP2 to training data directory │
|
||||
│ │
|
||||
│ 8. CONSTRAINT EVALUATION │
|
||||
│ mass ≤ 0.2 kg → feasible/infeasible │
|
||||
│ │
|
||||
│ 9. RETURN TO OPTUNA │
|
||||
│ return (stiffness, mass) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 Hooks Configuration
|
||||
|
||||
| Hook Point | Function | Purpose |
|
||||
|------------|----------|---------|
|
||||
| `PRE_SOLVE` | `log_trial_start()` | Log design variables, trial number |
|
||||
| `POST_SOLVE` | `export_field_data()` | Run NX journal for .fld export |
|
||||
| `POST_EXTRACTION` | `export_training_data()` | Save BDF/OP2 for neural training |
|
||||
|
||||
---
|
||||
|
||||
## 5. Result Extraction Methods
|
||||
|
||||
### 5.1 Mass Extraction
|
||||
|
||||
| Attribute | Value |
|
||||
|-----------|-------|
|
||||
| **Extractor** | `bdf_mass_extractor` |
|
||||
| **Module** | `optimization_engine.extractors.bdf_mass_extractor` |
|
||||
| **Function** | `extract_mass_from_bdf()` |
|
||||
| **Source** | `bracket_sim1-solution_1.dat` |
|
||||
| **Output** | kg |
|
||||
|
||||
**Algorithm**:
|
||||
$$m = \sum_{e=1}^{N_{elem}} m_e = \sum_{e=1}^{N_{elem}} \rho_e \cdot V_e$$
|
||||
|
||||
Where element volume $V_e$ is computed from BDF geometry (CTETRA, CHEXA, etc.).
|
||||
|
||||
**Code**:
|
||||
```python
|
||||
from optimization_engine.extractors.bdf_mass_extractor import extract_mass_from_bdf
|
||||
|
||||
mass_kg = extract_mass_from_bdf("1_setup/model/bracket_sim1-solution_1.dat")
|
||||
```
|
||||
|
||||
### 5.2 Stiffness Extraction
|
||||
|
||||
| Attribute | Value |
|
||||
|-----------|-------|
|
||||
| **Extractor** | `stiffness_calculator` |
|
||||
| **Module** | `optimization_engine.extractors.stiffness_calculator` |
|
||||
| **Displacement Source** | `export_field_dz.fld` |
|
||||
| **Force Source** | `bracket_sim1-solution_1.op2` |
|
||||
| **Components** | Force: $F_z$, Displacement: $\delta_z$ |
|
||||
| **Output** | N/mm |
|
||||
|
||||
**Algorithm**:
|
||||
$$k = \frac{F_z}{\delta_{max,z}}$$
|
||||
|
||||
Where:
|
||||
- $F_z$ = applied force in Z-direction (extracted from OP2 OLOAD resultant)
|
||||
- $\delta_{max,z} = \max_{i \in nodes} |u_{z,i}|$ (from field export)
|
||||
|
||||
**Code**:
|
||||
```python
|
||||
from optimization_engine.extractors.stiffness_calculator import StiffnessCalculator
|
||||
|
||||
calculator = StiffnessCalculator(
|
||||
field_file="1_setup/model/export_field_dz.fld",
|
||||
op2_file="1_setup/model/bracket_sim1-solution_1.op2",
|
||||
force_component="fz",
|
||||
displacement_component="z"
|
||||
)
|
||||
result = calculator.calculate()
|
||||
stiffness = result['stiffness'] # N/mm
|
||||
```
|
||||
|
||||
### 5.3 Field Data Format
|
||||
|
||||
**NX Field Export** (.fld):
|
||||
```
|
||||
FIELD: [ResultProbe] : [TABLE]
|
||||
RESULT TYPE: Displacement
|
||||
COMPONENT: Z
|
||||
START DATA
|
||||
step, node_id, value
|
||||
0, 396, -0.086716040968895
|
||||
0, 397, -0.091234567890123
|
||||
...
|
||||
END DATA
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Neural Acceleration (AtomizerField)
|
||||
|
||||
### 6.1 Configuration
|
||||
|
||||
| Setting | Value | Description |
|
||||
|---------|-------|-------------|
|
||||
| `enabled` | `true` | Neural surrogate active |
|
||||
| `min_training_points` | 50 | FEA trials before auto-training |
|
||||
| `auto_train` | `true` | Trigger training automatically |
|
||||
| `epochs` | 100 | Training epochs |
|
||||
| `validation_split` | 0.2 | 20% holdout for validation |
|
||||
| `retrain_threshold` | 25 | Retrain after N new FEA points |
|
||||
| `model_type` | `parametric` | Input: design params only |
|
||||
|
||||
### 6.2 Surrogate Model
|
||||
|
||||
**Input**: $\mathbf{x} = [\theta, t]^T \in \mathbb{R}^2$
|
||||
|
||||
**Output**: $\hat{\mathbf{y}} = [\hat{k}, \hat{m}]^T \in \mathbb{R}^2$
|
||||
|
||||
**Architecture**: Parametric neural network (MLP)
|
||||
|
||||
**Training Objective**:
|
||||
$$\mathcal{L} = \frac{1}{N} \sum_{i=1}^{N} \left[ (k_i - \hat{k}_i)^2 + (m_i - \hat{m}_i)^2 \right]$$
|
||||
|
||||
### 6.3 Training Data Location
|
||||
|
||||
```
|
||||
atomizer_field_training_data/bracket_stiffness_optimization_atomizerfield/
|
||||
├── trial_0001/
|
||||
│ ├── input/model.bdf # Mesh + design parameters
|
||||
│ ├── output/model.op2 # FEA displacement/stress results
|
||||
│ └── metadata.json # {support_angle, tip_thickness, stiffness, mass}
|
||||
├── trial_0002/
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 6.4 Expected Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| FEA time per trial | 10-30 min |
|
||||
| Neural time per trial | ~4.5 ms |
|
||||
| Speedup | ~2,200x |
|
||||
| Expected R² | > 0.95 (after 50 samples) |
|
||||
|
||||
---
|
||||
|
||||
## 7. Study File Structure
|
||||
|
||||
```
|
||||
bracket_stiffness_optimization_atomizerfield/
|
||||
│
|
||||
├── 1_setup/ # INPUT CONFIGURATION
|
||||
│ ├── model/ # NX Model Files
|
||||
│ │ ├── Bracket.prt # Parametric part
|
||||
│ │ │ └── Expressions: support_angle, tip_thickness
|
||||
│ │ ├── Bracket_sim1.sim # Simulation (SOL 101)
|
||||
│ │ ├── Bracket_fem1.fem # FEM mesh (auto-updated)
|
||||
│ │ ├── bracket_sim1-solution_1.dat # Nastran BDF input
|
||||
│ │ ├── bracket_sim1-solution_1.op2 # Binary results
|
||||
│ │ ├── bracket_sim1-solution_1.f06 # Text summary
|
||||
│ │ ├── export_displacement_field.py # Field export journal
|
||||
│ │ └── export_field_dz.fld # Z-displacement field
|
||||
│ │
|
||||
│ ├── optimization_config.json # Study configuration
|
||||
│ └── workflow_config.json # Workflow metadata
|
||||
│
|
||||
├── 2_results/ # OUTPUT (auto-generated)
|
||||
│ ├── study.db # Optuna SQLite database
|
||||
│ ├── optimization_history.json # Trial history
|
||||
│ ├── pareto_front.json # Pareto-optimal solutions
|
||||
│ ├── optimization.log # Structured log
|
||||
│ └── reports/ # Generated reports
|
||||
│ └── optimization_report.md # Full results report
|
||||
│
|
||||
├── run_optimization.py # Entry point
|
||||
├── reset_study.py # Database reset
|
||||
└── README.md # This blueprint
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Results Location
|
||||
|
||||
After optimization completes, results will be generated in `2_results/`:
|
||||
|
||||
| File | Description | Format |
|
||||
|------|-------------|--------|
|
||||
| `study.db` | Optuna database with all trials | SQLite |
|
||||
| `optimization_history.json` | Full trial history | JSON |
|
||||
| `pareto_front.json` | Pareto-optimal solutions | JSON |
|
||||
| `optimization.log` | Execution log | Text |
|
||||
| `reports/optimization_report.md` | **Full Results Report** | Markdown |
|
||||
|
||||
### 8.1 Results Report Contents
|
||||
|
||||
The generated `optimization_report.md` will contain:
|
||||
|
||||
1. **Optimization Summary** - Best solutions, convergence status
|
||||
2. **Pareto Front Analysis** - All non-dominated solutions with trade-off visualization
|
||||
3. **Parameter Correlations** - Design variable vs objective relationships
|
||||
4. **Convergence History** - Objective values over trials
|
||||
5. **Constraint Satisfaction** - Feasibility statistics
|
||||
6. **Neural Surrogate Performance** - Training loss, validation R², prediction accuracy
|
||||
7. **Algorithm Statistics** - NSGA-II population diversity, hypervolume indicator
|
||||
8. **Recommendations** - Suggested optimal configurations
|
||||
|
||||
---
|
||||
|
||||
## 9. Quick Start
|
||||
|
||||
### Staged Workflow (Recommended)
|
||||
|
||||
```bash
|
||||
# STAGE 1: DISCOVER - Clean old files, run ONE solve, discover available outputs
|
||||
python run_optimization.py --discover
|
||||
|
||||
# STAGE 2: VALIDATE - Run single trial to validate extraction works
|
||||
python run_optimization.py --validate
|
||||
|
||||
# STAGE 3: TEST - Run 3-trial integration test
|
||||
python run_optimization.py --test
|
||||
|
||||
# STAGE 4: TRAIN - Collect FEA training data for neural surrogate
|
||||
python run_optimization.py --train --trials 50
|
||||
|
||||
# STAGE 5: RUN - Official optimization
|
||||
python run_optimization.py --run --trials 100
|
||||
|
||||
# With neural acceleration (after training)
|
||||
python run_optimization.py --run --trials 100 --enable-nn --resume
|
||||
```
|
||||
|
||||
### Stage Descriptions
|
||||
|
||||
| Stage | Command | Purpose | When to Use |
|
||||
|-------|---------|---------|-------------|
|
||||
| **DISCOVER** | `--discover` | Scan model, clean files, run 1 solve, report outputs | First time setup |
|
||||
| **VALIDATE** | `--validate` | Run 1 trial with full extraction pipeline | After discover |
|
||||
| **TEST** | `--test` | Run 3 trials, check consistency | Before long runs |
|
||||
| **TRAIN** | `--train` | Collect FEA data for neural network | Building surrogate |
|
||||
| **RUN** | `--run` | Official optimization | Production runs |
|
||||
|
||||
### Additional Options
|
||||
|
||||
```bash
|
||||
# Clean old Nastran files before any stage
|
||||
python run_optimization.py --discover --clean
|
||||
|
||||
# Resume from existing study
|
||||
python run_optimization.py --run --trials 50 --resume
|
||||
|
||||
# Reset study (delete database)
|
||||
python reset_study.py
|
||||
python reset_study.py --clean # Also clean Nastran files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Dashboard Access
|
||||
|
||||
### Live Monitoring
|
||||
|
||||
| Dashboard | URL | Purpose |
|
||||
|-----------|-----|---------|
|
||||
| **Atomizer Dashboard** | [http://localhost:3003](http://localhost:3003) | Live optimization monitoring, Pareto plots |
|
||||
| **Optuna Dashboard** | [http://localhost:8081](http://localhost:8081) | Trial history, hyperparameter importance |
|
||||
|
||||
### Starting Dashboards
|
||||
|
||||
```bash
|
||||
# Start Atomizer Dashboard (from project root)
|
||||
cd atomizer-dashboard/frontend && npm run dev
|
||||
cd atomizer-dashboard/backend && python -m uvicorn api.main:app --port 8000
|
||||
|
||||
# Start Optuna Dashboard (for this study)
|
||||
optuna-dashboard sqlite:///2_results/study.db --port 8081
|
||||
```
|
||||
|
||||
### What You'll See
|
||||
|
||||
**Atomizer Dashboard** (localhost:3003):
|
||||
- Real-time Pareto front visualization
|
||||
- Parallel coordinates plot for design variables
|
||||
- Trial progress and success/failure rates
|
||||
- Study comparison across multiple optimizations
|
||||
|
||||
**Optuna Dashboard** (localhost:8081):
|
||||
- Trial history with all parameters and objectives
|
||||
- Hyperparameter importance analysis
|
||||
- Optimization history plots
|
||||
- Slice plots for parameter sensitivity
|
||||
|
||||
---
|
||||
|
||||
## 11. Configuration Reference
|
||||
|
||||
**File**: `1_setup/optimization_config.json`
|
||||
|
||||
| Section | Key | Description |
|
||||
|---------|-----|-------------|
|
||||
| `optimization_settings.protocol` | `protocol_11_multi_objective` | Algorithm selection |
|
||||
| `optimization_settings.sampler` | `NSGAIISampler` | Optuna sampler |
|
||||
| `optimization_settings.n_trials` | `100` | Total trials |
|
||||
| `design_variables[]` | `[support_angle, tip_thickness]` | Params to optimize |
|
||||
| `objectives[]` | `[stiffness, mass]` | Objectives with goals |
|
||||
| `constraints[]` | `[mass_limit]` | Constraints with thresholds |
|
||||
| `result_extraction.*` | Extractor configs | How to get results |
|
||||
| `neural_acceleration.*` | Neural settings | AtomizerField config |
|
||||
| `training_data_export.*` | Export settings | Training data location |
|
||||
|
||||
---
|
||||
|
||||
## 12. References
|
||||
|
||||
- **Deb, K. et al.** (2002). A Fast and Elitist Multiobjective Genetic Algorithm: NSGA-II. *IEEE Transactions on Evolutionary Computation*.
|
||||
- **pyNastran Documentation**: BDF/OP2 parsing
|
||||
- **Optuna Documentation**: Multi-objective optimization with NSGA-II
|
||||
@@ -0,0 +1,51 @@
|
||||
"""Reset bracket stiffness optimization study by deleting database and optionally cleaning Nastran files."""
|
||||
import optuna
|
||||
from pathlib import Path
|
||||
import argparse
|
||||
|
||||
study_dir = Path(__file__).parent
|
||||
storage = f"sqlite:///{study_dir / '2_results' / 'study.db'}"
|
||||
study_name = "bracket_stiffness_optimization_atomizerfield"
|
||||
|
||||
def clean_nastran_files():
|
||||
"""Remove old Nastran solver output files."""
|
||||
model_dir = study_dir / "1_setup" / "model"
|
||||
nastran_extensions = ['*.op2', '*.f06', '*.log', '*.f04', '*.pch', '*.DBALL', '*.MASTER', '*.asg', '*.diag']
|
||||
temp_patterns = ['_temp*.txt', '*_temp_*']
|
||||
|
||||
deleted = []
|
||||
for pattern in nastran_extensions + temp_patterns:
|
||||
for f in model_dir.glob(pattern):
|
||||
try:
|
||||
f.unlink()
|
||||
deleted.append(f.name)
|
||||
except Exception as e:
|
||||
print(f"[WARNING] Could not delete {f.name}: {e}")
|
||||
|
||||
return deleted
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Reset bracket optimization study")
|
||||
parser.add_argument('--clean', action='store_true', help='Also clean Nastran output files')
|
||||
parser.add_argument('--clean-only', action='store_true', help='Only clean Nastran files, keep database')
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.clean_only:
|
||||
try:
|
||||
optuna.delete_study(study_name=study_name, storage=storage)
|
||||
print(f"[OK] Deleted study: {study_name}")
|
||||
except KeyError:
|
||||
print(f"[INFO] Study '{study_name}' not found (database may not exist)")
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error: {e}")
|
||||
|
||||
if args.clean or args.clean_only:
|
||||
deleted = clean_nastran_files()
|
||||
if deleted:
|
||||
print(f"[OK] Deleted {len(deleted)} Nastran files:")
|
||||
for f in deleted[:5]:
|
||||
print(f" - {f}")
|
||||
if len(deleted) > 5:
|
||||
print(f" ... and {len(deleted) - 5} more")
|
||||
else:
|
||||
print("[INFO] No Nastran files to clean")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,333 +0,0 @@
|
||||
# Auto-generated journal for solving Beam_sim1.sim
|
||||
import sys
|
||||
sys.argv = ['', r'C:\Users\antoi\Documents\Atomaste\Atomizer\studies\uav_arm_optimization\1_setup\model\Beam_sim1.sim', None, 'beam_half_core_thickness=5.543272595780111', 'beam_face_thickness=2.36655422332811', 'holes_diameter=27.930376572591207', 'hole_count=13.212098121132765'] # Set argv for the main function
|
||||
"""
|
||||
NX Journal Script to Solve Simulation in Batch Mode
|
||||
|
||||
This script opens a .sim file, updates the FEM, and solves it through the NX API.
|
||||
Usage: run_journal.exe solve_simulation.py <sim_file_path>
|
||||
|
||||
Based on recorded NX journal pattern for solving simulations.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import NXOpen
|
||||
import NXOpen.Assemblies
|
||||
import NXOpen.CAE
|
||||
|
||||
|
||||
def main(args):
|
||||
"""
|
||||
Open and solve a simulation file with updated expression values.
|
||||
|
||||
Args:
|
||||
args: Command line arguments
|
||||
args[0]: .sim file path
|
||||
args[1]: solution_name (optional, e.g., "Solution_Normal_Modes" or None for default)
|
||||
args[2+]: expression updates as "name=value" pairs
|
||||
"""
|
||||
if len(args) < 1:
|
||||
print("ERROR: No .sim file path provided")
|
||||
print("Usage: run_journal.exe solve_simulation.py <sim_file_path> [solution_name] [expr1=val1] [expr2=val2] ...")
|
||||
return False
|
||||
|
||||
sim_file_path = args[0]
|
||||
|
||||
# Parse solution name if provided (args[1])
|
||||
solution_name = args[1] if len(args) > 1 and args[1] != 'None' else None
|
||||
|
||||
# Extract base name from sim file (e.g., "Beam_sim1.sim" -> "Beam")
|
||||
import os
|
||||
sim_filename = os.path.basename(sim_file_path)
|
||||
part_base_name = sim_filename.split('_sim')[0] if '_sim' in sim_filename else sim_filename.split('.sim')[0]
|
||||
|
||||
# Parse expression updates from args[2+] as "name=value" pairs
|
||||
expression_updates = {}
|
||||
for arg in args[2:]:
|
||||
if '=' in arg:
|
||||
name, value = arg.split('=', 1)
|
||||
expression_updates[name] = float(value)
|
||||
|
||||
print(f"[JOURNAL] Opening simulation: {sim_file_path}")
|
||||
print(f"[JOURNAL] Detected part base name: {part_base_name}")
|
||||
if solution_name:
|
||||
print(f"[JOURNAL] Will solve specific solution: {solution_name}")
|
||||
else:
|
||||
print(f"[JOURNAL] Will solve default solution (Solution 1)")
|
||||
if expression_updates:
|
||||
print(f"[JOURNAL] Will update expressions:")
|
||||
for name, value in expression_updates.items():
|
||||
print(f"[JOURNAL] {name} = {value}")
|
||||
|
||||
try:
|
||||
theSession = NXOpen.Session.GetSession()
|
||||
|
||||
# Set load options to load linked parts from directory
|
||||
print("[JOURNAL] Setting load options for linked parts...")
|
||||
import os
|
||||
working_dir = os.path.dirname(os.path.abspath(sim_file_path))
|
||||
|
||||
# Complete load options setup (from recorded journal)
|
||||
theSession.Parts.LoadOptions.LoadLatest = False
|
||||
theSession.Parts.LoadOptions.ComponentLoadMethod = NXOpen.LoadOptions.LoadMethod.FromDirectory
|
||||
|
||||
searchDirectories = [working_dir]
|
||||
searchSubDirs = [True]
|
||||
theSession.Parts.LoadOptions.SetSearchDirectories(searchDirectories, searchSubDirs)
|
||||
|
||||
theSession.Parts.LoadOptions.ComponentsToLoad = NXOpen.LoadOptions.LoadComponents.All
|
||||
theSession.Parts.LoadOptions.PartLoadOption = NXOpen.LoadOptions.LoadOption.FullyLoad
|
||||
theSession.Parts.LoadOptions.SetInterpartData(True, NXOpen.LoadOptions.Parent.All)
|
||||
theSession.Parts.LoadOptions.AllowSubstitution = False
|
||||
theSession.Parts.LoadOptions.GenerateMissingPartFamilyMembers = True
|
||||
theSession.Parts.LoadOptions.AbortOnFailure = False
|
||||
|
||||
referenceSets = ["As Saved", "Use Simplified", "Use Model", "Entire Part", "Empty"]
|
||||
theSession.Parts.LoadOptions.SetDefaultReferenceSets(referenceSets)
|
||||
theSession.Parts.LoadOptions.ReferenceSetOverride = False
|
||||
|
||||
print(f"[JOURNAL] Load directory set to: {working_dir}")
|
||||
|
||||
# Close any currently open sim file to force reload from disk
|
||||
print("[JOURNAL] Checking for open parts...")
|
||||
try:
|
||||
current_work = theSession.Parts.BaseWork
|
||||
if current_work and hasattr(current_work, 'FullPath'):
|
||||
current_path = current_work.FullPath
|
||||
print(f"[JOURNAL] Closing currently open part: {current_path}")
|
||||
# Close without saving (we want to reload from disk)
|
||||
partCloseResponses1 = [NXOpen.BasePart.CloseWholeTree]
|
||||
theSession.Parts.CloseAll(partCloseResponses1)
|
||||
print("[JOURNAL] Parts closed")
|
||||
except Exception as e:
|
||||
print(f"[JOURNAL] No parts to close or error closing: {e}")
|
||||
|
||||
# Open the .sim file (now will load fresh from disk with updated .prt files)
|
||||
print(f"[JOURNAL] Opening simulation fresh from disk...")
|
||||
basePart1, partLoadStatus1 = theSession.Parts.OpenActiveDisplay(
|
||||
sim_file_path,
|
||||
NXOpen.DisplayPartOption.AllowAdditional
|
||||
)
|
||||
|
||||
workSimPart = theSession.Parts.BaseWork
|
||||
displaySimPart = theSession.Parts.BaseDisplay
|
||||
|
||||
print(f"[JOURNAL] Simulation opened successfully")
|
||||
partLoadStatus1.Dispose()
|
||||
|
||||
# Switch to simulation application
|
||||
theSession.ApplicationSwitchImmediate("UG_APP_SFEM")
|
||||
|
||||
simPart1 = workSimPart
|
||||
theSession.Post.UpdateUserGroupsFromSimPart(simPart1)
|
||||
|
||||
# STEP 1: Try to switch to part and update expressions (optional for some models)
|
||||
print(f"[JOURNAL] STEP 1: Checking for {part_base_name}.prt geometry...")
|
||||
geometry_updated = False
|
||||
try:
|
||||
# Find the main part (may not exist for embedded geometry models)
|
||||
bracketPart = None
|
||||
try:
|
||||
bracketPart = theSession.Parts.FindObject(part_base_name)
|
||||
except:
|
||||
pass
|
||||
|
||||
if bracketPart:
|
||||
print(f"[JOURNAL] Found {part_base_name} part, updating geometry...")
|
||||
# Make Bracket the active display part
|
||||
status, partLoadStatus = theSession.Parts.SetActiveDisplay(
|
||||
bracketPart,
|
||||
NXOpen.DisplayPartOption.AllowAdditional,
|
||||
NXOpen.PartDisplayPartWorkPartOption.UseLast
|
||||
)
|
||||
partLoadStatus.Dispose()
|
||||
|
||||
workPart = theSession.Parts.Work
|
||||
|
||||
# CRITICAL: Apply expression changes BEFORE updating geometry
|
||||
expressions_updated = []
|
||||
|
||||
# Apply all expression updates dynamically
|
||||
for expr_name, expr_value in expression_updates.items():
|
||||
print(f"[JOURNAL] Applying {expr_name} = {expr_value}")
|
||||
try:
|
||||
expr_obj = workPart.Expressions.FindObject(expr_name)
|
||||
if expr_obj:
|
||||
# Use millimeters as default unit for geometric parameters
|
||||
unit_mm = workPart.UnitCollection.FindObject("MilliMeter")
|
||||
workPart.Expressions.EditExpressionWithUnits(expr_obj, unit_mm, str(expr_value))
|
||||
expressions_updated.append(expr_obj)
|
||||
print(f"[JOURNAL] {expr_name} updated successfully")
|
||||
else:
|
||||
print(f"[JOURNAL] WARNING: {expr_name} expression not found!")
|
||||
except Exception as e:
|
||||
print(f"[JOURNAL] ERROR updating {expr_name}: {e}")
|
||||
|
||||
# Make expressions up to date
|
||||
if expressions_updated:
|
||||
print(f"[JOURNAL] Making {len(expressions_updated)} expression(s) up to date...")
|
||||
for expr in expressions_updated:
|
||||
markId_expr = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Invisible, "Make Up to Date")
|
||||
objects1 = [expr]
|
||||
theSession.UpdateManager.MakeUpToDate(objects1, markId_expr)
|
||||
theSession.DeleteUndoMark(markId_expr, None)
|
||||
|
||||
# CRITICAL: Update the geometry model - rebuilds features with new expressions
|
||||
print(f"[JOURNAL] Rebuilding geometry with new expression values...")
|
||||
markId_update = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Invisible, "NX update")
|
||||
nErrs = theSession.UpdateManager.DoUpdate(markId_update)
|
||||
theSession.DeleteUndoMark(markId_update, "NX update")
|
||||
print(f"[JOURNAL] {part_base_name} geometry updated ({nErrs} errors)")
|
||||
|
||||
# Extract mass from expression p173 if it exists and write to temp file
|
||||
try:
|
||||
mass_expr = workPart.Expressions.FindObject("p173")
|
||||
if mass_expr:
|
||||
mass_kg = mass_expr.Value
|
||||
mass_output_file = os.path.join(working_dir, "_temp_mass.txt")
|
||||
with open(mass_output_file, 'w') as f:
|
||||
f.write(str(mass_kg))
|
||||
print(f"[JOURNAL] Mass from p173: {mass_kg:.6f} kg ({mass_kg * 1000:.2f} g)")
|
||||
print(f"[JOURNAL] Mass written to: {mass_output_file}")
|
||||
except:
|
||||
pass # Expression p173 might not exist in all models
|
||||
|
||||
geometry_updated = True
|
||||
else:
|
||||
print(f"[JOURNAL] {part_base_name} part not found - may be embedded in sim file")
|
||||
except Exception as e:
|
||||
print(f"[JOURNAL] Could not update {part_base_name}.prt: {e}")
|
||||
print(f"[JOURNAL] Continuing with sim-only solve...")
|
||||
|
||||
# STEP 2: Try to switch to FEM part and update (optional for some models)
|
||||
fem_part_name = f"{part_base_name}_fem1"
|
||||
print(f"[JOURNAL] STEP 2: Checking for {fem_part_name}.fem...")
|
||||
fem_updated = False
|
||||
try:
|
||||
# Find the FEM part (may not exist or may have different name)
|
||||
femPart1 = None
|
||||
try:
|
||||
femPart1 = theSession.Parts.FindObject(fem_part_name)
|
||||
except:
|
||||
# Try with _i suffix for idealized FEM
|
||||
try:
|
||||
femPart1 = theSession.Parts.FindObject(f"{fem_part_name}_i")
|
||||
except:
|
||||
pass
|
||||
|
||||
if femPart1:
|
||||
print(f"[JOURNAL] Found FEM part, updating...")
|
||||
# Make FEM the active display part
|
||||
status, partLoadStatus = theSession.Parts.SetActiveDisplay(
|
||||
femPart1,
|
||||
NXOpen.DisplayPartOption.AllowAdditional,
|
||||
NXOpen.PartDisplayPartWorkPartOption.SameAsDisplay
|
||||
)
|
||||
partLoadStatus.Dispose()
|
||||
|
||||
workFemPart = theSession.Parts.BaseWork
|
||||
|
||||
# CRITICAL: Update FE Model - regenerates FEM with new geometry
|
||||
print("[JOURNAL] Updating FE Model...")
|
||||
fEModel1 = workFemPart.FindObject("FEModel")
|
||||
if fEModel1:
|
||||
fEModel1.UpdateFemodel()
|
||||
print("[JOURNAL] FE Model updated with new geometry!")
|
||||
fem_updated = True
|
||||
else:
|
||||
print("[JOURNAL] WARNING: Could not find FEModel object")
|
||||
else:
|
||||
print(f"[JOURNAL] FEM part not found - may be embedded in sim file")
|
||||
except Exception as e:
|
||||
print(f"[JOURNAL] Could not update FEM: {e}")
|
||||
print(f"[JOURNAL] Continuing with sim-only solve...")
|
||||
|
||||
# STEP 3: Switch back to sim part
|
||||
print("[JOURNAL] STEP 3: Switching back to sim part...")
|
||||
try:
|
||||
status, partLoadStatus = theSession.Parts.SetActiveDisplay(
|
||||
simPart1,
|
||||
NXOpen.DisplayPartOption.AllowAdditional,
|
||||
NXOpen.PartDisplayPartWorkPartOption.UseLast
|
||||
)
|
||||
partLoadStatus.Dispose()
|
||||
workSimPart = theSession.Parts.BaseWork
|
||||
print("[JOURNAL] Switched back to sim part")
|
||||
except Exception as e:
|
||||
print(f"[JOURNAL] WARNING: Error switching to sim part: {e}")
|
||||
|
||||
# Note: Old output files are deleted by nx_solver.py before calling this journal
|
||||
# This ensures NX performs a fresh solve
|
||||
|
||||
# Solve the simulation
|
||||
print("[JOURNAL] Starting solve...")
|
||||
markId3 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Start")
|
||||
theSession.SetUndoMarkName(markId3, "Solve Dialog")
|
||||
|
||||
markId5 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Invisible, "Solve")
|
||||
|
||||
theCAESimSolveManager = NXOpen.CAE.SimSolveManager.GetSimSolveManager(theSession)
|
||||
|
||||
# Get the simulation object
|
||||
simSimulation1 = workSimPart.FindObject("Simulation")
|
||||
|
||||
# Get the solution(s) to solve - either specific or all
|
||||
if solution_name:
|
||||
# Solve specific solution in background mode
|
||||
solution_obj_name = f"Solution[{solution_name}]"
|
||||
print(f"[JOURNAL] Looking for solution: {solution_obj_name}")
|
||||
simSolution1 = simSimulation1.FindObject(solution_obj_name)
|
||||
psolutions1 = [simSolution1]
|
||||
|
||||
numsolutionssolved1, numsolutionsfailed1, numsolutionsskipped1 = theCAESimSolveManager.SolveChainOfSolutions(
|
||||
psolutions1,
|
||||
NXOpen.CAE.SimSolution.SolveOption.Solve,
|
||||
NXOpen.CAE.SimSolution.SetupCheckOption.CompleteDeepCheckAndOutputErrors,
|
||||
NXOpen.CAE.SimSolution.SolveMode.Background
|
||||
)
|
||||
else:
|
||||
# Solve ALL solutions using SolveAllSolutions API (Foreground mode)
|
||||
# This ensures all solutions (static + modal, etc.) complete before returning
|
||||
print(f"[JOURNAL] Solving all solutions using SolveAllSolutions API (Foreground mode)...")
|
||||
|
||||
numsolutionssolved1, numsolutionsfailed1, numsolutionsskipped1 = theCAESimSolveManager.SolveAllSolutions(
|
||||
NXOpen.CAE.SimSolution.SolveOption.Solve,
|
||||
NXOpen.CAE.SimSolution.SetupCheckOption.CompleteCheckAndOutputErrors,
|
||||
NXOpen.CAE.SimSolution.SolveMode.Foreground,
|
||||
False
|
||||
)
|
||||
|
||||
theSession.DeleteUndoMark(markId5, None)
|
||||
theSession.SetUndoMarkName(markId3, "Solve")
|
||||
|
||||
print(f"[JOURNAL] Solve completed!")
|
||||
print(f"[JOURNAL] Solutions solved: {numsolutionssolved1}")
|
||||
print(f"[JOURNAL] Solutions failed: {numsolutionsfailed1}")
|
||||
print(f"[JOURNAL] Solutions skipped: {numsolutionsskipped1}")
|
||||
|
||||
# NOTE: When solution_name=None, we use Foreground mode to ensure all solutions
|
||||
# complete before returning. When solution_name is specified, Background mode is used.
|
||||
|
||||
# Save the simulation to write all output files
|
||||
print("[JOURNAL] Saving simulation to ensure output files are written...")
|
||||
simPart2 = workSimPart
|
||||
partSaveStatus1 = simPart2.Save(
|
||||
NXOpen.BasePart.SaveComponents.TrueValue,
|
||||
NXOpen.BasePart.CloseAfterSave.FalseValue
|
||||
)
|
||||
partSaveStatus1.Dispose()
|
||||
print("[JOURNAL] Save complete!")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"[JOURNAL] ERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
success = main(sys.argv[1:])
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
605
studies/uav_arm_optimization/1_setup/training_points.json
Normal file
605
studies/uav_arm_optimization/1_setup/training_points.json
Normal file
@@ -0,0 +1,605 @@
|
||||
{
|
||||
"n_samples": 100,
|
||||
"samples": [
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 10,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 50,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 39.11495337147077,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 49.16136204667126,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 46.01390570274639,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 21.217421810082225,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 20.082080394289246,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 18.109191416954808,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 14.539656664891888,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 30.59773230671056,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 21.681163899392473,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 28.46337650045196,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 15.380826141903691,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 38.386915057604675,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 40.857186570249944,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 44.42611172446365,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 48.98104904851064,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 35.445125663580384,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 34.971806113930754,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 23.231150155800222,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 44.25795107538616,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 24.49665135602796,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 28.659990293016172,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 38.70363840447788,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 18.02270852251754,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 22.713565671834345,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 32.8009495704188,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 37.968633351685945,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 27.88125642755058,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 24.06867795722209,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 10.868203436695604,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 46.46090807629757,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 45.197883656600055,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 18.89054227984153,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 13.728289062601483,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 16.3852783373898,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 26.293935606071294,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 47.17246359286906,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 40.31830047745593,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 39.60652765514554,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 30.42448774231645,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 10.130002564625293,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 29.890374290050058,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 34.36676678898456,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 13.194801029457086,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 23.731139134484753,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 13.861106063688137,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 11.657686495054072,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 46.96492489101252,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 11.9348508806982,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 36.11748365875024,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 36.573126349659724,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 20.713932768475075,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 41.36579894391118,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 33.00273217350339,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 17.27837755732581,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 45.27258926142547,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 49.684350374874484,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 34.27387643267321,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 37.552219239493375,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 10.984274656380851,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 19.99150629334429,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 15.127313932396937,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 41.61756802031489,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 42.07050903543811,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 10,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 31.315875065239247,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 27.111162449068964,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 32.23317396479806,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 42.72156186555336,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 22.354573614683687,
|
||||
"hole_count": 12
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 25.86632641580976,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 16.726188122745427,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 16.077740537569333,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 37.11940280003448,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 42.936448307719736,
|
||||
"hole_count": 14
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 12.455440499239165,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 33.43834402820413,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 31.649491411453504,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 25.05471928757126,
|
||||
"hole_count": 9
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 48.3438679647506,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 7,
|
||||
"beam_face_thickness": 3,
|
||||
"holes_diameter": 47.92076550008274,
|
||||
"hole_count": 8
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 5,
|
||||
"beam_face_thickness": 1,
|
||||
"holes_diameter": 25.572915964489866,
|
||||
"hole_count": 13
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 43.65316133095015,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 6,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 29.14076579621568,
|
||||
"hole_count": 10
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 9,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 19.173860398899862,
|
||||
"hole_count": 11
|
||||
},
|
||||
{
|
||||
"beam_half_core_thickness": 8,
|
||||
"beam_face_thickness": 2,
|
||||
"holes_diameter": 27.556141506046885,
|
||||
"hole_count": 12
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
studies/uav_arm_optimization/2_results/training_data.db
Normal file
BIN
studies/uav_arm_optimization/2_results/training_data.db
Normal file
Binary file not shown.
Reference in New Issue
Block a user