fix(fem): write a Sesam superelement Presel and Sestra accept - #374
Merged
Merged
Conversation
An Abaqus-derived superelement (689,596 nodes, 463,192 elements: quadratic
tetrahedra, shells and one beam) could not be read by Presel, and once read
could not be reduced by Sestra. Six defects in the Sesam writer, each confirmed
against the Input Interface File description and then against the programs
themselves.
* **Element record order.** GELMNT1/GELREF1 were emitted grouped by element
block, so internal numbers jumped backwards and Presel stopped at
`ELEMENT n INTERNAL ALREADY EXISTS`. Both blocks are now emitted in increasing
internal element number (printed 6-65, 6-68). Ids are sorted, never renumbered.
* **GUNIVEC on non-beams.** A transformation was created for every sectioned
element and copied into GELREF1 TRANSNO, so shells and solids referenced a
GUNIVEC and Presel rejected them with
`TRANSFORMATION NUMBER 1 DOES NOT EXSIST`. GUNIVEC is defined for beam types
2, 15 and 23 only (printed 6-92); everything else now writes TRANSNO = 0,
default element axes (printed 6-67). A `transno` a caller placed on a non-beam
element itself (a BNTRCOS reference) is passed through untouched.
* **No BNBCD companions for BLDEP.** BLDEP is only valid alongside boundary
codes (printed 6-27). Dependent DOFs now get code 3 and every master node an
explicit all-free record. Masters are deliberately *not* retained: code 4
makes a node a supernode (printed 6-30), and marking masters retained turned
743 internal coupling nodes into unconnected supernodes in Presel. DNV's own
GeniE (V9.2-01) writes every one of its BLDEP masters as `0 0 0 0 0 0` and
reserves code 4 for the assembly interface, which settles what the manual's
wording leaves ambiguous.
* **No way to declare the external interface.** Retained DOFs are now declared
either explicitly, `to_fem(..., metadata={"sesam_retained_dofs": {...}})`, or
by convention through a node set named `SESAM_SUPERNODES`, so a plain "read an
Abaqus INP, write a Sesam FEM" conversion needs no extra argument. The
explicit key overrides the convention outright rather than merging with it.
The reader brings code 4 back as that same set, so the round trip closes.
* **Every node declared with six DOFs.** A solid-only node has three (printed
5-91: "solid type: NDOF=3, ODOF=123"). Writing six left three zero-stiffness
rotations on ~687,000 nodes and Sestra's reduction failed with
`Matrix is not positive definite` on the first one it reached. NDOF is now
derived per node from the elements attached to it, and GNODE, BNBCD, BNMASS
and BNLOAD all follow it; a BC, load, mass or BLDEP term naming a DOF the node
does not have raises instead of writing an invalid record.
* **BELFIX wrote OPT = 3**, which is not a defined value; the record's own data
is the 0..1 degree of fixation OPT = 1 describes (printed 6-8).
Two smaller things in the same area: the nearest-master pairing for a
shell-to-solid coupling was order-dependent (313 of 8,910 slaves flipped between
two equally valid orderings of the same master set, every one an exact distance
tie) and now breaks ties on the lowest node id; and skipped elements leave holes
in the internal element numbering, which is now reported in one warning
alongside the count of what was skipped.
Also removes a dead multi-part branch in the writer: it called
`concatenate_fem_to_single_part`, discarded the returned merged part and re-listed
the assembly's own parts, which the non-destructive merge had left untouched, so
it fell straight into `DoesNotSupportMultiPart`. `fem.formats.general` already
merges properly before the writer is reached.
Validated on the model above: Presel read all 463,085 elements of the earlier
revision and matched 58 supernodes against the global model, and Sestra completed
the reduction without error.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv
PR Review👋 I checked your PR and found no issues. Thanks!
|
This was referenced Sep 22, 2026
🚀 Profiling Results (Top 20 most expensive calls)
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An Abaqus-derived superelement could not be read by Presel, and once read could not be reduced by Sestra. This is six defects in the Sesam writer, each checked against the Input Interface File description and then against the programs themselves.
The model: 689,596 nodes, 463,192 elements — 460,918 quadratic tetrahedra, 2,273 shells, one beam, joined by 8,910 BLDEP relations, with a 58-node external interface.
The defects
Element record order. GELMNT1/GELREF1 were emitted grouped by element block, so internal numbers jumped backwards and Presel stopped at
ELEMENT 15 INTERNAL ALREADY EXISTS. Both blocks now come out in increasing internal element number (printed 6-65, 6-68). Ids are sorted, never renumbered.GUNIVEC on non-beams. A transformation was created for every sectioned element and copied into GELREF1 TRANSNO, so shells and solids referenced a GUNIVEC and Presel rejected them with
TRANSFORMATION NUMBER 1 DOES NOT EXSIST. GUNIVEC is defined for beam types 2, 15 and 23 only (printed 6-92). Everything else now writes TRANSNO = 0 — default element axes, printed 6-67. Worth knowing: ada's own mesher setslocal_zon every shell section, so this fired on all 463k elements.No BNBCD companions for BLDEP. BLDEP is only valid alongside boundary codes (printed 6-27). Dependent DOFs now get code 3 and every master node an explicit all-free record.
Masters are deliberately not retained, which is where this departs from the obvious reading of the manual. Printed 6-27 says the independent node's DOFs should be "retained (4)" — but code 4 is the definition of a supernode (printed 6-30), and following that literally turned 743 internal coupling masters into unconnected supernodes in Presel (801 retained nodes where 58 were intended). DNV's own GeniE V9.2-01 settles it: in a 128k-element file with 169 BLDEP records, all 52 masters carry
0 0 0 0 0 0and the only code-4 nodes are the assembly interface, which is neither master nor dependent.No way to declare the external interface. Retained DOFs can now be declared explicitly —
— or by convention, through a node set named
SESAM_SUPERNODES, so a plain "read an Abaqus INP, write a Sesam FEM" conversion needs no extra argument. The explicit key overrides the convention outright rather than merging with it: naming one set must not silently retain another. The reader brings code 4 back as that same set, so the round trip closes; a partial per-DOF pattern widens to the whole node, with a warning, because a node set cannot carry one.Every node declared with six DOFs. A solid-only node has three — printed 5-91: "solid type: NDOF=3, ODOF=123". Writing six left three zero-stiffness rotations on ~687,000 nodes, and Sestra's reduction failed with:
DOF 4 is the first rotation, and that node is used by five elements, all tetrahedra. NDOF is now derived per node from the elements attached to it, and GNODE, BNBCD, BNMASS and BNLOAD all follow it. A BC, load, mass or BLDEP term naming a DOF the node does not have raises instead of writing an invalid record. On the model above the split is 687,072 three-DOF nodes and 2,524 six-DOF nodes, with no overlap.
BELFIX wrote OPT = 3, which is not a defined value. The record's own data is the 0..1 degree of fixation that OPT = 1 describes (printed 6-8).
Two smaller things in the same area
The nearest-master pairing for a shell-to-solid coupling was order-dependent: 313 of 8,910 slaves flipped between two equally valid orderings of the same master set, every one an exact distance tie (
|Δdistance| = 0.000e+00). It now breaks ties on the lowest node id, so the deck is reproducible.Skipped elements (connectors, unsectioned elements, springs) leave holes in the internal element numbering. That is unchanged behaviour, but it is now reported in one warning alongside the count of what was skipped, since a reader assuming contiguous numbering will mis-associate results.
Also removes a dead multi-part branch in the writer: it called
concatenate_fem_to_single_part, discarded the returned merged part, and re-listed the assembly's own parts — which the non-destructive merge had left untouched — so it fell straight intoDoesNotSupportMultiPart.fem.formats.generalalready merges properly before the writer is reached. Behaviour is identical; only the misleading code goes.Validation
tests/core/femon current main. The 5 failures in that directory are pre-existing:import freetyperaisesRuntimeError: Freetype library not foundin this environment, in image-rendering tests unrelated to this change.Every manual citation refers to the Sesam Input Interface File description, 01-NOV-1996, by its printed page number.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv