Versions
FLUKA: N/A
Flair: 3.4-5.2
MCNP: 6.3.0
Operating system: WSL (Ubuntu Linux virtual on Windows)
Description
Hi all,
While developing an MCNP geometry inspector that uses Flair’s Python API (really grateful and genuinely appreciative for Flair, @vasilis! We will be sending another email your way soon for cooperation hopefully), we found three bugs in Flair 3.4-5.2 that affect MCNP model handling. I am reporting them here with patches and validation results in case they are useful.
Bug 1 — PAT_PROP regex rejects numbered parameter keywords
- File:
mcnp/input.py - Problem: The
PAT_PROPregex[a-z][a-z:,]*does not allow digits, so MCNP cell-parameter keywords containing numbers (in our model, this looked likeTMP1=,TMP2=) are not recognized as properties. They leak into geometry expressions and produce input-parsing errors on models that use cell temperatures (like we have). - Fix: Change
[a-z:,]*→[a-z0-9:,]* - This appears when loading not importing the model.
Bug 2 — Left-handed transform silently skips MCNP-only surfaces in MCNP to FLUKA converter
-
File:
convert/mcnp2fluka.py -
Problem: When a surface has a left-handed coordinate transform,
convertBodies()callstransformBody()while the surface still carries its MCNP tag (C/X,C/Y,C/Z,K/X, etc.). SincetransformBody()recognizes only FLUKA tags, the body falls through to, e.g.,log.error("Invalid body C/X")and the transform is silently skipped. To me, it seems like thetransformBody()insidedeck/card.pyis a work in progress maybe? In its current state it accepts FLUKA tags while for MCNP tags it is not fully implemented (only planes). Hence, the geometry then renders with untransformed cylinder positions. -
Fix: Refactor
convertBodies()into three clear paths:- Shared macro bodies (
BOX,RCC,RPP, …): pass through as is. - Normal (right-handed or no-transform): normalize MCNP tag to its FLUKA tag, then add to print.
- Left-handed: normalize first, build a temporary
FlukaCard, calltransformBody()on the FLUKA-native card, extract the transformed FLUKA tag/parameters, then add to print.
Normalization is handled by a set of
_normalize*()helpers (cones toQUA+ nappe plane,SQtoQUA,ELLform normalization,P/P3toPLA, simple remaps likePXtoYZP,C/XtoXCC, etc.) so both the normal and LH paths share the same conversion logic. Final print still goes throughaddCard();FlukaCardis only used as a temporary handle for the left-handed transform application (to overcome the mcnp mode). - Shared macro bodies (
Bug 3 — _transformInfCyl drops cylinder radius after axis change
-
File:
deck/card.py,_transformInfCyl()method -
Problem: When an infinite cylinder (
XCC/YCC/ZCC) is transformed and its axis changes direction (e.g.,ZCCrotated to becomeXCC),changeTag()internally callstrimWhats(), which truncates thewhatarray. The method then restores the two center coordinates withsetWhat(1, …)andsetWhat(2, …), but never restores the radius inwhat(3). The cylinder is printed with the correct axis and center but a missing radius.Reproduction on vanilla:
ZCC before: whats=['S5', '0.0', '0.0', '3.0'] XCC after: whats=['', 0.0, 0.0] ← radius gone -
Fix: Add
self.setWhat(3, CSGCard.fmt(radius))after each axis-change branchNote: this bug is independent of the converter, it affects any code path that calls
transformBody()on an infinite cylinder that changes axis, including standalone scripts using Flair’s Python API.
Patch
Unified diff against Flair 3.4-5.2, in total those are 3 files. Apply with:
cd /usr/local/flair
patch -p1 --dry-run < flair_fixes.patch # preview
patch -p1 < flair_fixes.patch # apply
Verification
We verified the patch with an automated suite covering 37 MCNP surface types × 3 scenarios (no transform, right-handed TR, left-handed *TR) = 111 test cases, all passing. We also ran a 3-model smoke test on larger production inputs to confirm the single-nappe cone path and the extra body-expression terms used for cone nappe planes still behave correctly after full conversion.
| Family | plain | RH tr | LH tr |
|---|---|---|---|
| Planes (PX, PY, PZ, P, P3) | 5/5 | 5/5 | 5/5 |
| Spheres (SO, S, SX, SY, SZ, SPH) | 6/6 | 6/6 | 6/6 |
| Cylinders (C/X, C/Y, C/Z, CX, CY, CZ) | 6/6 | 6/6 | 6/6 |
| Cones (K/X, K/Y, K/Z, KX, KY, KZ) | 6/6 | 6/6 | 6/6 |
| Quadrics (SQ, GQ) | 2/2 | 2/2 | 2/2 |
| Ellipsoids (ELL+, ELL−) | 2/2 | 2/2 | 2/2 |
| Tori (TX, TY, TZ) | 3/3 | 3/3 | 3/3* |
| Macro bodies (BOX, WED, RPP, RCC, REC, TRC, ARB) | 7/7 | 7/7 | 7/7 |
For the RH column, shared macro bodies and tori are validated mainly through wrapper scoping: the emitted body parameters stay at their plain values, and the suite separately checks the expected $start_transform / $end_transform sequence and ROT-DEFI cards.
For the LH column, the shared macro-body cases has the TR applied into the emitted body coordinates.
* The LH torus cases are currently included in the suite, but they should not be read as validated left-handed torus-transform support: the printed TRX / TRY / TRZ parameters remain the same as the plain case since there is no support for them in the transformBody() yet (like translation, or checks for axis aligned rotations only).
Yeah, this test suite is AI generated, as well as refining parts of this topic of course! It is a tool that helps a lot with that!
Each case generates a focused single-surface MCNP deck, runs the full mcnp2fluka converter, and compares the emitted FLUKA body parameters against independently computed expected values (tolerance 1E-08). The suite also checks $start_transform/$end_transform handling, validates the extra body-expression terms used for cone nappe planes, and fails on unexpected converter diagnostics. A separate focused wrapper regression verifies that right-handed transform scopes group and reopen correctly, and that left-handed transforms emit no wrapper cards.
Attachments
flair_fixes.patch— unified diff (3 files)test_model.inp— minimal MCNP model that triggers all three bugs (C/X + CZ with left-handed transforms, TMP1= keywords).- validation logs.
Note: The TMP1 problem appears when loading (not importing) an MCNP input file (because it is thePAT_PROPinsidemcnp/input.py), and the_transformInfCyl()problem happens after an LH is correctly applied to a Fluka converted surface changed from an MCNP tag.
Wish I could also share the larger model that originally exposed the problem (a playground model of a big facility like the SNS), but the patches and test model above ought to cover it. Flair’s plot and geometry input is coming closer to matching MCNP’s internal plotter (and I believe it will be much better).
P.S. If a plot’s elements locations look different between the MCNP and Flair plotters, one has to check if the same basis between both plotters is applied.
Happy to provide more details if needed.
Thank you,
Ramzy
flair_fixes.patch (24.7 KB)
test_model.inp (1.1 KB)
validation_latest.txt (34.5 KB)