Merge recovery/gitea-before-force-push to restore: - hq/ directory (cluster setup, docker-compose, configs) - docs/hq/ (12+ HQ planning docs) - docs/guides/ (documentation boundaries, PKM standard) - docs/plans/ (model introspection master plan) - Isogrid extraction work - Hydrotech-beam: keep local DOE results, remove Syncthing conflicts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Study: 01_doe_landscape — Hydrotech Beam
See ../../README.md for project overview.
Purpose
Map the design space of the Hydrotech sandwich I-beam to identify feasible regions, characterize variable sensitivities, and prepare data for Phase 2 (TPE optimization). This is Phase 1 of the two-phase strategy (DEC-HB-002).
Quick Facts
| Item | Value |
|---|---|
| Objective | Minimize mass (kg) |
| Constraints | Tip displacement ≤ 10 mm, Von Mises stress ≤ 130 MPa |
| Design variables | 4 (3 continuous + 1 integer) |
| Algorithm | Phase 1: LHS DoE (50 trials + 1 baseline) |
| Total budget | 51 evaluations |
| Constraint handling | Deb's feasibility rules (Optuna constraint interface) |
| Status | ✅ Pipeline operational — first results obtained 2026-02-11 |
| Solver | DesigncenterNX 2512 (NX Nastran SOL 101) |
| Solve time | ~12 s/trial (~10 min for full DOE) |
| First results | Displacement=17.93mm, Stress=111.9MPa |
Design Variables (confirmed via NX binary introspection)
| ID | NX Expression | Range | Type | Baseline | Unit |
|---|---|---|---|---|---|
| DV1 | beam_half_core_thickness |
10–40 | Continuous | 25.162 | mm |
| DV2 | beam_face_thickness |
10–40 | Continuous | 21.504 | mm |
| DV3 | holes_diameter |
150–450 | Continuous | 300 | mm |
| DV4 | hole_count |
5–15 | Integer | 10 | — |
Usage
Prerequisites
pip install -r requirements.txt
Requires: Python 3.10+, optuna, scipy, numpy, pandas.
Development Run (stub solver)
# From the study directory:
cd projects/hydrotech-beam/studies/01_doe_landscape/
# Run with synthetic results (for pipeline testing):
python run_doe.py --backend stub
# With verbose logging:
python run_doe.py --backend stub -v
# Custom study name:
python run_doe.py --backend stub --study-name my_test_run
Production Run (NXOpen on Windows)
# On dalidou (Windows node with DesigncenterNX 2512):
cd C:\Users\antoi\Atomizer\projects\hydrotech-beam\studies\01_doe_landscape
conda activate atomizer
python run_doe.py --backend nxopen --model-dir "../../models"
⚠️
--model-dircan be relative — the code resolves it withPath.resolve(). NX requires fully resolved paths (no..components).
Resume Interrupted Study
python run_doe.py --backend stub --resume --study-name hydrotech_beam_doe_phase1
CLI Options
| Flag | Default | Description |
|---|---|---|
--backend |
stub |
stub (testing) or nxopen (real NX) |
--model-dir |
— | Path to NX model files (required for nxopen) |
--study-name |
hydrotech_beam_doe_phase1 |
Optuna study name |
--n-samples |
50 | Number of LHS sample points |
--seed |
42 | Random seed for reproducibility |
--results-dir |
results/ |
Output directory |
--resume |
false | Resume existing study |
--clean |
false | Delete Optuna DB and start fresh (history DB preserved) |
-v |
false | Verbose (DEBUG) logging |
Files
| File | Description |
|---|---|
run_doe.py |
Main entry point — orchestrates the DoE study |
sampling.py |
LHS generation with stratified integer sampling |
geometric_checks.py |
Pre-flight geometric feasibility filter |
nx_interface.py |
AtomizerNXSolver wrapping optimization_engine |
iteration_manager.py |
Smart retention — last 10 + best 3 with full data |
requirements.txt |
Python dependencies |
OPTIMIZATION_STRATEGY.md |
Full strategy document |
results/ |
Output directory (CSV, JSON, Optuna DB) |
iterations/ |
Per-trial archived outputs |
Output Files
After a study run, results/ will contain:
| File | Description |
|---|---|
doe_results.csv |
All trials — DVs, objectives, constraints, status |
doe_summary.json |
Study metadata, statistics, best feasible design |
optuna_study.db |
SQLite database (Optuna persistence, resume support) |
history.db |
Persistent SQLite — all DVs, results, feasibility (survives --clean) |
history.csv |
CSV mirror of history DB |
Iteration Folders
Each trial produces iterations/iterNNN/ containing:
| File | Description |
|---|---|
params.json |
Design variable values for this trial |
params.exp |
NX expression file used for this trial |
results.json |
Extracted results (mass, displacement, stress, feasibility) |
*.op2 |
Nastran binary results (for post-processing) |
*.f06 |
Nastran text output (for debugging) |
Smart retention policy (runs every 5 iterations):
- Keep last 10 iterations with full data
- Keep best 3 feasible iterations with full data
- Strip model files from all others, keep solver outputs
Architecture
run_doe.py
├── sampling.py Generate 50 LHS + 1 baseline
│ └── scipy.stats.qmc.LatinHypercube
├── geometric_checks.py Pre-flight feasibility filter
│ ├── Hole overlap: span/(n-1) - d ≥ 30mm
│ └── Web clearance: 500 - 2·face - d > 0
├── nx_interface.py AtomizerNXSolver (wraps optimization_engine)
│ ├── NXStubSolver → synthetic results (development)
│ └── AtomizerNXSolver → real DesigncenterNX 2512 SOL 101 (production)
├── iteration_manager.py Smart retention (last 10 + best 3)
├── Optuna study
│ ├── SQLite storage (resume support)
│ ├── Enqueued trials (deterministic LHS)
│ └── Deb's feasibility rules (constraint interface)
└── history.db Persistent history (append-only, survives --clean)
Pipeline per Trial
Trial N
│
├── 1. Suggest DVs (from enqueued LHS point)
│
├── 2. Geometric pre-check
│ ├── FAIL → record as infeasible, skip NX
│ └── PASS ↓
│
├── 3. Restore master model from backup
│
├── 4. NX evaluation (IN-PLACE in models/ directory)
│ ├── Write .exp file with trial DVs
│ ├── Open .sim (loads model chain)
│ ├── Import expressions, rebuild geometry
│ ├── Update FEM (remesh)
│ ├── Solve SOL 101 (~12s)
│ └── Extract: mass (p173 → _temp_mass.txt), displacement, stress (via OP2)
│
├── 5. Archive outputs to iterations/iterNNN/
│ └── params.json, params.exp, results.json, OP2, F06
│
├── 6. Record results + constraint violations
│
├── 7. Log to Optuna DB + history.db + CSV
│
└── 8. Smart retention check (every 5 iterations)
Phase 1 → Phase 2 Gate Criteria
Before proceeding to Phase 2 (TPE optimization), these checks must pass:
| Check | Threshold | Action if FAIL |
|---|---|---|
| Feasible points found | ≥ 5 | Expand bounds or relax constraints (escalate to CEO) |
| NX solve success rate | ≥ 80% | Investigate failures, fix model, re-run |
| No systematic crashes at bounds | Visual check | Tighten bounds away from failure region |
Key Design Decisions
- Baseline as Trial 0 — LAC lesson: always validate baseline first
- Pre-flight geometric filter — catches infeasible geometry before NX (saves compute, avoids crashes)
- Stratified integer sampling — ensures all 11 hole_count levels (5-15) are covered
- Deb's feasibility rules — no penalty weight tuning; feasible always beats infeasible
- SQLite persistence — study can be interrupted and resumed
- No surrogates — LAC lesson: direct FEA via TPE beats surrogate + L-BFGS
NX Integration Notes
Solver: DesigncenterNX 2512 (Siemens rebrand of NX). Install: C:\Program Files\Siemens\DesigncenterNX2512.
The nx_interface.py module provides:
NXStubSolver— synthetic results from simplified beam mechanics (for pipeline testing)AtomizerNXSolver— wrapsoptimization_engineNXSolver for real DesigncenterNX 2512 solves
Expression names are exact from binary introspection. Critical: beam_lenght has a typo in NX (no 'h') — use exact spelling.
Outputs extracted from NX:
| Output | Source | Unit | Notes |
|---|---|---|---|
| Mass | Expression p173 → _temp_mass.txt |
kg | Journal extracts after solve |
| Tip displacement | OP2 parse via pyNastran | mm | Max Tz at free end |
| Max VM stress | OP2 parse via pyNastran | MPa | ⚠️ pyNastran returns kPa — divide by 1000 |
Critical Lessons Learned (2026-02-11)
- Path resolution: Use
Path.resolve()NOTPath.absolute()on Windows..absolute()doesn't resolve..components — NX can't follow them. - File references: NX
.simfiles have absolute internal refs to.fem/.prt. Never copy model files to iteration folders — solve in-place with backup/restore. - NX version: Must match exactly. Model files from 2512 won't load in 2412 ("Part file is from a newer version").
- pyNastran: Warns about unsupported NX version 2512 but works fine. Safe to ignore.
References
- OPTIMIZATION_STRATEGY.md — Full strategy document
- ../../BREAKDOWN.md — Tech Lead's technical analysis
- ../../DECISIONS.md — Decision log
- ../../CONTEXT.md — Project context & expression map
Code: 🏗️ Study Builder (Technical Lead) | Strategy: ⚡ Optimizer Agent | Updated: 2026-02-11