Files
Atomizer/projects/hydrotech-beam/studies/01_doe_landscape/README.md
Antoine 2fde08daab docs: update KB and project docs with 2026-02-11 progress
- KB Gen 003: NX version (DesigncenterNX 2512), first real results
- sol101-static.md: path resolution lessons, in-place solving, result extraction confirmed
- CONTEXT.md: solver pipeline operational, first results (disp=17.93mm, stress=111.9MPa)
- DECISIONS.md: DEC-HB-008 to DEC-HB-011 (backup/restore, iteration arch, history DB, git workflow)
- optimization_engine/README.md: created (DesigncenterNX support, path resolution, NX file refs)
- studies/01_doe_landscape/README.md: updated architecture, iteration folders, history DB
- _index.md: closed gaps G3,G4,G6,G10-G14, updated generation to 003
2026-02-11 16:39:21 +00:00

236 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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` | 1040 | Continuous | 25.162 | mm |
| DV2 | `beam_face_thickness` | 1040 | Continuous | 21.504 | mm |
| DV3 | `holes_diameter` | 150450 | Continuous | 300 | mm |
| DV4 | `hole_count` | 515 | 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*