Files
Atomizer/projects/hydrotech-beam/studies/01_doe_landscape
Anto01 40213578ad merge: recover Gitea state - HQ docs, cluster setup, isogrid work
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>
2026-02-16 12:22:33 -05:00
..
2026-02-15 08:00:21 +00:00
2026-02-15 08:00:21 +00:00
2026-02-15 08:00:21 +00:00
2026-02-15 08:00:21 +00:00
2026-02-15 08:00:21 +00:00

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 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

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-dir can be relative — the code resolves it with Path.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 — 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


Code: 🏗️ Study Builder (Technical Lead) | Strategy: Optimizer Agent | Updated: 2026-02-11