- Default r_f raised from 1.5mm to 6mm (machining constraint)
- Default min_pocket_radius raised to 6mm
- Pockets that can't fit r_f at any corner (within 80% tolerance) are
skipped entirely — left solid for more stiffness in tight areas
- Result: 26 pockets (was 432), 187 NX entities (was 13,061)
- Min fillet radius: 4.88mm, all >= 4.8mm (80% of 6mm)
- Mass: 4,601g (was 3,480g — more solid = heavier but manufacturable)
Model curves (part.Curves.CreateLine) are SmartObjects that can't be added
to a sketch via AddGeometry. Switch to SketchLineBuilder which creates
native sketch geometry directly (SetStartPoint/SetEndPoint/Commit).
- Extract mass RIGHT AFTER geometry rebuild while part is work part
- Replace unreliable p173 expression lookup with MeasureManager
- Skip re-extraction if mass already captured during rebuild
- Relax displacement constraint to 20mm (DEC-HB-012, CEO approved)
Root cause: journal hardcoded M1_Blank for bracket, failed silently on Beam.prt
Fix by: NX Expert + Manager diagnosis
Bug 1 — Journal (solve_simulation.py simple workflow):
Expression lookup for p173 fails silently for derived/measurement
expressions, so _temp_mass.txt was never written. Added MeasureManager
fallback via extract_part_mass() (already used in assembly workflow).
Bug 2 — Extractor (extract_mass_from_expression.py):
Journal writes 'p173=<value>' format but extractor tried float() on
the whole content including 'p173='. Added key=value parsing.
Defense in depth — nx_interface.py:
Added stdout parsing fallback: if _temp_mass.txt still missing, parse
mass from journal output captured via solver.py stdout passthrough.
Files changed:
- optimization_engine/nx/solve_simulation.py — MeasureManager fallback
- optimization_engine/extractors/extract_mass_from_expression.py — key=value parse
- optimization_engine/nx/solver.py — include stdout in result dict
- projects/hydrotech-beam/studies/01_doe_landscape/nx_interface.py — stdout fallback
Tags: hydrotech-beam, mass-extraction
- Journal now extracts p173 mass expression and writes _temp_mass.txt
- history.get_study_summary() called before history.close()
- Optuna nan rejection: fallback to INFEASIBLE_MASS penalty
- pyNastran warning 'nx 2512 not supported' is harmless (reads fine)
Root cause: Path.absolute() on Windows does NOT resolve '..' components.
sim_file_path was reaching NX as '...\studies\01_doe_landscape\..\..\models\Beam_sim1.sim'
NX likely can't resolve referenced parts from a path with '..' in it.
Fixes:
- nx_interface.py: glob from self.model_dir (resolved) not model_dir (raw)
- solver.py: sim_file.resolve() instead of sim_file.absolute()
- solve_simulation.py: os.path.abspath(sim_file_path) at entry point
- Diagnostic logging still in place for next run
Need to see why Parts.Open returns None even from the master model folder.
Logs: basePart1 type/name/path, unloaded parts status, file existence checks.
NX .sim files store absolute internal references to .fem/.prt files.
Copying them to iteration folders breaks these references (Parts.Open
returns None). Instead:
1. Backup master model once at study start
2. Restore from backup before each trial (isolation)
3. Solve on master model in-place (NX references intact)
4. Archive solver outputs (OP2/F06) + params.exp to iterations/iterNNN/
5. params.exp in each iteration: import into NX to recreate any trial
iteration_manager.py kept for future use but not wired in.
- history.db: SQLite append-only, never deleted by --clean
- history.csv: Auto-exported after each trial (live updates)
- Logs: DVs, results, feasibility, status, solve time, iter path
- Cross-study queries: full lineage across all runs/phases
- --clean only resets Optuna DB, history preserved
- Each iteration gets full model files in iterations/iterNNN/ (openable in NX)
- Retention: keep last 10 + best 3 with full models, strip the rest
- Stripped iterations keep solver outputs (OP2, F06, params, results)
- All paths resolved to absolute before passing to NX (fixes reference issue)
- iteration_manager.py: reusable for future studies