Repository navigation
Conversation
``*MPC`` inside an ``*Assembly`` names nodes as ``P-1.4``, which is what Abaqus/CAE writes for every assembly-level MPC. ``get_set_from_assembly`` resolves that form to the *node* -- its numeric branch returns ``part.fem.nodes.from_id(4)`` -- while ``mpc_nodes`` fed every non-integer reference straight to ``ref.members``, so ``BEAM, P-1.1, P-1.3`` raised ``AttributeError: 'NodeProxy' object has no attribute 'members'``. ``_read_fem`` guards the assembly-level constraint read against ``KeyError`` only, so the whole import died, not just the constraint. The same model written flat, with bare node ids, read all four of its constraints. ``mpc_nodes`` now expands a ``FemSet`` and takes anything else as the node it is, so the set-name form and the instance-qualified-id form can sit on data lines of one deck. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv
…traints Reported as "a flat (non-*Assembly) deck's constraints are never read". Measured: it reads them. A deck with no *Assembly goes add_fem_without_assembly -> get_fem_from_bulk_str, which has called get_constraints_from_inp since 2021, and the five-constraint deck below (tie, rigid body, coupling, equation, MPC) comes back with all five on the part FEM. The two paths did disagree, but the other way round: the *assembly* path lost the whole deck to an *MPC naming P-1.4, fixed in the preceding commit. So this is the test rather than a fix. Nothing held the two readers to the same answer, and which layout a deck has is a CAE export option, not a modelling decision. Mutations run: reverting the *MPC fix fails it (assembly side raises), and blanking the flat path's ``fem.constraints = get_constraints_from_inp(...)`` fails it too, so it covers both directions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv
… sum of both ``_merged`` gives each (slave, master) pair one record, as the manual requires (BLDEP, section 7.2.14: "The same combination of SLAVE and MASTER may occur only once"), by concatenating the terms of every record on that pair. The term list could then hold one (slave_dof, master_dof) twice, and Sestra adds the betas of a repeated pair together: a deck declaring ``u(1,1) = 1.0 * u(2,1)`` twice was written as NDDOF 1 NDEP 2 with beta 1.0 on both triplets, which is ``u(1,1) = 2.0 * u(2,1)``. Measured on the two-equation case in the new test: terms came out ``((1, 1, 1.0), (1, 1, 1.0))``. What produced the repeat decides what happens to it, and the two cases are not the same fault: * the same beta twice (within 1e-12 relative; duplicates come from the same arithmetic and agree bit for bit) is one dependency declared twice -- an *Equation pasted in again, two Abaqus keywords the reader turned into one relation. Written once, and noted. * two different betas are two incompatible statements about one dof, a *Tie and an *Equation over the same node pair being the usual source. Summing is what neither constraint says and nor is averaging, so the later one is refused by name (OMITTED, with both betas) and the first-declared relation is written. The existing per-dof SUSPECT no longer claims "Sesam sums linear dependencies", which is now true only of two records with different masters, and its key iteration is sorted so the report order is deterministic. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv
…t TypeError Reported as unfixed: ``write_loads`` raising a ``TypeError`` far from the load that caused it. Measured: ``load_str`` already reports through ``conversion_report`` (fixed in Krande#386, no longer ``logger.error`` + ``return None``), but nothing covered it, so nothing would notice it coming back. These pin it. Both mutations were run against the tests. Restoring ``return None`` in place of the OMITTED-and-``""`` reproduces the original failure exactly -- ``TypeError: can only concatenate str (not "NoneType") to str`` at ``case_loads_str``'s ``out_str +=``, which names a string concatenation and not the pressure load. Keeping ``return ""`` but dropping the ``rep.omitted`` call leaves a deck that writes and a report that says nothing: 0 findings where 1 is asserted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv
``PRESCRIBED = 2`` was defined and never written -- "ada's Bc magnitudes are not carried into BNDISPL yet" -- so a ``Bc`` with ``magnitudes`` came out of the Sesam writer as an ordinary clamp and a settlement case became a rigid support: a different structure, and one whose reaction forces are what a settlement case is usually run for. No Input Interface File manual ships with the installed Sestra, so the record was not read off one. Its fields come from Sestra V11.3-00's own diagnostics in ``Bin/DataAccess.dll`` -- "Invalid DTYPE on BNDISPL card. Supported values are 1 (displacement) and 3 (acceleration)", "BNDISPL card is too short for complex loads and dof count given in NDOF field", "Multiple BNDISPL cards are given for a (load case number, internal node number) pair" -- and the layout from solving for it. It is BNLOAD's shape: ``LLC DTYPE COMPLX 0`` / ``NODENO NDOF D1 D2`` / ``D3..Dndof``. Measured, 1 m IPE300 cantilever clamped at x=0 with dz = -0.01 prescribed at the tip and no other loading, Sestra V11.3-00 solving it (tests/fem/test_sesam_prescribed_displacement.py): * FIX code 2 and the BNDISPL record: tip Z = -0.009999999776482582, which is float32's neighbour of -0.01 (a SIN stores nodal results single precision), tip RY = 6.907e-03 free, X = Y = 0. * FIX code 2 and no BNDISPL: "WARNING ... No load is specified", and no displacement result at all. * the BNDISPL record with FIX code 1 instead of 2: the value is ignored, tip Z = 0.0. So the two cards are one statement and neither half is optional, and a settlement is *loading* in Sesam -- BNDISPL declares an LLC. It is written in the load block, into the first load case, and a model whose only loading is a settlement gets a load case opened for it. Only a nonzero magnitude counts: a prescribed zero is a fixed support, so every existing deck is byte-identical. ``not_held.report_bcs`` drops from APPROXIMATED to NOTE for such a BC -- nothing is approximated now -- but keeps saying it, because the value does not survive the way back: the Sesam reader has no BNDISPL card, which is the cross-format gap this leaves behind and which its table now names. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv
PR Review👋 I checked your PR and found no issues. Thanks!
|
🚀 Profiling Results (Top 20 most expensive calls)
|
This was referenced Sep 27, 2026
Closed
Owner
|
Folded into #407. This branch was merged in as-is, with its own merge commit, so every commit and its authorship #407 collects the six format-level FEA PRs (#394, #395, #396, #399, #400, #404) into one, since |
Krande
added a commit
that referenced
this pull request
Sep 27, 2026
…nd verify plates through decks (#407) Folds the six format-level FEA PRs into one, drops the Abaqus/CAE stack, and gives the verification report a plate case built through the deck writers. Folded: #394 (*Tie -> BLDEP facet interpolation), #395 (Sesam super element number), #396 (a symmetric section's zero product of inertia), #399 (.gnx as a first-class format), #400 (Sesam settlement, one BLDEP term per dof pair, instance-qualified *MPC), #404 (surface pressure as BEUSLO). Dropped: #398, #401, #402, #403, #405 -- src/ada/cadit/cae, Part.to_abaqus_cae_script, its tests and verification/genie_vs_abaqus, which drives `abaqus cae noGUI=`. adapy supports formats, not APIs into proprietary software, and a verification entry only a CAE licence can reproduce verifies nothing anyone can check. Salvaged from it, because it is format-level: a T-profile now reaches an Abaqus *Beam Section as section=I with the bottom flange zeroed (it had no mapping at all), and Calculix converts a T to a general section as it already did an I. New: the plate strip case -- an ada.Plate meshed by the meshing module (gmsh), written as a deck per solver, checked against 5 q L^4 / (384 D) and f_n = n^2 pi / (2 L^2) sqrt(D / (rho t)). Code_Aster lands on the eigen closed form to six digits. Writer gaps it exposed, each found by running it rather than reading: * Calculix had no pressure load at all; it now writes *DLOAD ... P. Measured on ccx 2.23 that P, P1 and P2 are bit-identical on a shell, so the label carries no face and only the sign can. * Code_Aster's pressure had never run: FORCE_FACE with FY is a traction along global Y, not a normal pressure, and GROUP_MA named the surface, which has no MED counterpart -- every attempt stopped at <EXCEPTION> <MODELISA7_77>. Now FORCE_COQUE=_F(PRES=...) over the element sets, via the new shared ada.fem.surfaces.pressure_elsets. * Code_Aster refused any eigenvalue analysis with more than one Bc; ASSEMBLAGE's CHARGE takes a tuple. * The Sesam BEUSLO pressure sign was inverted relative to Abaqus, Calculix and Code_Aster. The reference it was tuned against applied its load along global -z on the grounds that -z was "against the plate's +z normal"; the strip's element normals are all -z (measured, all 128), so the reference ran along the normal and the test that pinned it never checked which face was named. Code_Aster reproduces the Sestra magnitude to eight digits with the opposite sign. The measured Sestra numbers are kept exactly as measured; only which face they belong to changed. The Sestra leg runs only where Sestra is installed, so a licensed re-run remains the confirmation worth having. Co-Authored-By: oleandor <oleandor@gmail.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KXGBkUbGK6oYWxm5R2WYVB
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.
Five items flagged during the constraint work (#393/#394) and left open because they were out of that scope. All five turned out to live on
main, not in those PRs, so they are here, one commit each, independent of every open PR and merging cleanly with #393.1. A settlement now reaches Sestra —
BNDISPL, verified against Sestra V11.3-00write_bcs.pysaid it in a comment: "PRESCRIBED = 2 — never written: ada's Bc magnitudes are not carried into BNDISPL yet." ABcwith a magnitude — a support settlement — silently became a fixed support on the Sesam route.No Input Interface File manual ships with the install, so the record layout was not guessed: its field names came from Sestra's own diagnostics in
Bin/DataAccess.dll("Invalid DTYPE on BNDISPL card. Supported values are 1 (displacement) and 3 (acceleration)", "…too short for … dof count given in NDOF field") and the layout from solving for it. It isBNLOAD's shape:LLC DTYPE COMPLX 0/NODENO NDOF D1 D2/D3... Measured on a 1 m IPE300 cantilever with tipdz = -0.01:.SINBNBCDfix code 2 +BNDISPLBNDISPLBNDISPL, fix code 1BNDISPLDTYPE 3So a settlement is loading in Sesam —
BNDISPLdeclares a load case — and the two cards are one statement. Only a non-zero magnitude counts (a prescribed zero is a clamp), so existing decks are byte-identical. The Sesam reader has noBNDISPLcard, so the value does not survive the way back; the cross-format gap table now says that by name instead of the old "not carried yet".2.
BLDEP: one term per(slave_dof, master_dof), not the sum of both_mergedhonours §7.2.14 ("the same combination of SLAVE and MASTER may occur only once") by concatenating a pair's terms into one record — so a(slave_dof, master_dof)appearing twice went out twice, and Sestra adds the betas: two equations declaringu(1,1) = 1.0·u(2,1)producedu(1,1) = 2.0·u(2,1). Decided from what produces it: the same beta twice (bit-for-bit, from the same arithmetic) is one dependency declared twice and is written once with a NOTE; different betas are two incompatible statements — a*Tieand an*Equationon one pair — and the later one is refused by name, OMITTED with both betas, the first written. Records now carry their constraint's name so the report can say which two.3.
*MPCwith instance-qualified nodes no longer kills the importBEAM, P-1.1, P-1.3raisedAttributeError: 'NodeProxy' object has no attribute 'members'—get_set_from_assemblyresolvesP-1.1to the node, andmpc_nodessent every non-int to.members._read_femguards that call againstKeyErroronly, so the whole deck was lost. A set is expanded, anything else is taken as the node it is, soBEAM, P-1.1, P-1.3andTIE, P-1.2, P-1.tipcoexist.4. A flat deck and an
*Assemblydeck read the same constraints — the premise was wrong, the test staysThe flag said a flat (non-
*Assembly) deck's constraints were never read. Measured: they are, all five kinds, and have been since 2021 (101dfdf1d); seven flat-deck shapes probed. The two paths did disagree — the other way round, because item 3 lost the assembly deck. The parity test asked for is here anyway: the same five-constraint model flat and wrapped, equal names and types; it fails if either direction regresses.5. An unsupported load is one OMITTED finding
load_stralready reports OMITTED and returns""(landed in #386) — nothing covered it, and areturn Nonethere brings the original distantTypeError: can only concatenate str (not "NoneType")straight back. Two tests pin it.Verification
Every test was watched failing first, and each fix mutated: BLDEP back to concatenation (2 of 3 fail on the doubled term),
nodes.extend(ref.members)restored (AttributeErrorat reader.py:1322), always-FIXED(3 fail incl. the Sestra one),bndispl_strreturning""(4 fail; Sestra writes no displacement field),load_strreturningNone(theTypeError), and the flat path's constraint read blanked (parity fails).Suite
tests/core: 4277 passed, 22 skipped, 0 failed (+12);tests/fem/test_sesam_prescribed_displacement.pyruns Sestra for real. Lint clean. Re-run independently by the session opening this PR: 48 passed in the changed test files, the Sestra test passing withBNBCDcode 2 andBNDISPL -1.0e-02seen in the deck.The user's Sestra-proven regression deck (
rev32, 344 MB,COMPLETED_WITH_OMISSIONS (5 omitted, 1 approximated, 21188 note)) converted on this branch and on clean 0.91.0 differs by the timestamp only.🤖 Generated with Claude Code
https://claude.ai/code/session_01Nej3bWxJevs9GkH6tg1WKv