# Study: 01_doe_landscape — Hydrotech Beam > See [../../README.md](../../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 ```bash pip install -r requirements.txt ``` Requires: Python 3.10+, optuna, scipy, numpy, pandas. ### Development Run (stub solver) ```bash # 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) ```bash # 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-dir` can be relative — the code resolves it with `Path.resolve()`. NX requires fully resolved paths (no `..` components). ### Resume Interrupted Study ```bash 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`** — wraps `optimization_engine` NXSolver 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) 1. **Path resolution:** Use `Path.resolve()` NOT `Path.absolute()` on Windows. `.absolute()` doesn't resolve `..` components — NX can't follow them. 2. **File references:** NX `.sim` files have absolute internal refs to `.fem`/`.prt`. Never copy model files to iteration folders — solve in-place with backup/restore. 3. **NX version:** Must match exactly. Model files from 2512 won't load in 2412 ("Part file is from a newer version"). 4. **pyNastran:** Warns about unsupported NX version 2512 but works fine. Safe to ignore. ## References - [OPTIMIZATION_STRATEGY.md](./OPTIMIZATION_STRATEGY.md) — Full strategy document - [../../BREAKDOWN.md](../../BREAKDOWN.md) — Tech Lead's technical analysis - [../../DECISIONS.md](../../DECISIONS.md) — Decision log - [../../CONTEXT.md](../../CONTEXT.md) — Project context & expression map --- *Code: 🏗️ Study Builder (Technical Lead) | Strategy: ⚡ Optimizer Agent | Updated: 2026-02-11*