From d23b08db8ca407be2c56af576938404cdc48aab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B2=BD=EC=A2=85?= Date: Thu, 11 Jun 2026 13:39:58 +0900 Subject: [PATCH] docs: define 3d euler beam uel interface --- PROGRESS.md | 11 +- docs/io-definitions/uel-3d-euler-beam.md | 378 +++++++++++++++++++++++ phases/uel-3d-euler-beam/index.json | 3 +- 3 files changed, 387 insertions(+), 5 deletions(-) create mode 100644 docs/io-definitions/uel-3d-euler-beam.md diff --git a/PROGRESS.md b/PROGRESS.md index 483bd11..6260827 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -5,8 +5,8 @@ - Active objective: 3D Euler-Bernoulli beam Abaqus/Standard `UEL` - Active phase: `phases/uel-3d-euler-beam` - Active owner: unassigned -- Current status: completed `phases/uel-3d-euler-beam/step3.md` numerical-review step -- Next action: execute `phases/uel-3d-euler-beam/step4.md` interface-contract step +- Current status: completed `phases/uel-3d-euler-beam/step4.md` interface-contract step +- Next action: execute `phases/uel-3d-euler-beam/step5.md` test/reference model planning step ## Completed @@ -25,6 +25,9 @@ - Completed step 3 numerical review for `uel-3d-euler-beam`. - Created `docs/numerical-reviews/uel-3d-euler-beam.md`. - Updated `phases/uel-3d-euler-beam/index.json` step 3 to `completed`. +- Completed step 4 interface contract for `uel-3d-euler-beam`. + - Created `docs/io-definitions/uel-3d-euler-beam.md`. + - Updated `phases/uel-3d-euler-beam/index.json` step 4 to `completed`. ## In Progress @@ -36,7 +39,7 @@ ## Last Verification -Latest verification after completing step 3 numerical review: +Latest verification after completing step 4 interface contract: ```bash python -m unittest discover -s scripts -p "test_*.py" @@ -53,5 +56,5 @@ Result: all passed. - Read `AGENTS.md`, `PLAN.md`, `PROGRESS.md`, and `WORKNOTE.md`. - Confirm no other owner is active in this file. -- Start `phases/uel-3d-euler-beam/step4.md`. +- Start `phases/uel-3d-euler-beam/step5.md`. - Update this file when step status changes or before handing off. diff --git a/docs/io-definitions/uel-3d-euler-beam.md b/docs/io-definitions/uel-3d-euler-beam.md new file mode 100644 index 0000000..a6af398 --- /dev/null +++ b/docs/io-definitions/uel-3d-euler-beam.md @@ -0,0 +1,378 @@ +# 3D Euler-Bernoulli Beam UEL I/O Definition + +## Metadata +- feature_id: uel-3d-euler-beam +- source_requirement: `docs/requirements/uel-3d-euler-beam.md` +- source_research: `docs/research/uel-3d-euler-beam-research.md` +- source_formulation: `docs/formulations/uel-3d-euler-beam.md` +- source_numerical_review: `docs/numerical-reviews/uel-3d-euler-beam.md` +- status: ready-for-reference-model-planning +- owner_agent: io-definition-agent +- date: 2026-06-11 + +## Scope and Compatibility Statement + +- input_format: Abaqus input file (`.inp`) plus Abaqus/Standard `UEL` call data +- entry_point: Abaqus/Standard `UEL` +- compatibility: only the keyword, argument, and CSV subset defined here is supported +- solver_execution_policy: Abaqus jobs are run outside this repository by the user +- result_policy: this repository validates externally generated ODB-extracted CSV artifacts and does not parse ODB files + +This interface contract deliberately avoids claiming full Abaqus input compatibility. It defines the first-scope two-node, small-displacement, linear elastic 3D Euler-Bernoulli beam `UEL` only. + +## Abaqus/Standard UEL ABI Contract + +The Abaqus/Standard production wrapper must preserve the manual `UEL` signature and include convention: + +```fortran + SUBROUTINE UEL(RHS, AMATRX, SVARS, ENERGY, NDOFEL, + 1 NRHS, NSVARS, PROPS, NPROPS, COORDS, MCRD, NNODE, + 2 U, DU, V, A, JTYPE, TIME, DTIME, KSTEP, KINC, JELEM, + 3 PARAMS, NDLOAD, JDLTYP, ADLMAG, PREDEF, NPREDF, + 4 LFLAGS, MLVARX, DDLMAG, MDLOAD, PNEWDT, JPROPS, + 5 NJPROP, PERIOD) + + INCLUDE 'ABA_PARAM.INC' + + DIMENSION RHS(MLVARX,*), AMATRX(NDOFEL,NDOFEL), + 1 SVARS(*), ENERGY(8), PROPS(*), COORDS(MCRD,NNODE), + 2 U(NDOFEL), DU(MLVARX,*), V(NDOFEL), A(NDOFEL), + 3 TIME(2), PARAMS(*), JDLTYP(MDLOAD,*), + 4 ADLMAG(MDLOAD,*), DDLMAG(MDLOAD,*), + 5 PREDEF(2,NPREDF,NNODE), LFLAGS(*), JPROPS(*) +``` + +The wrapper must keep `aba_param.inc` / `ABA_PARAM.INC` as an Abaqus/Standard include, not a project-local replacement. The no-Abaqus kernel may use its own pure calculation interface, but that kernel interface is not defined in this document as source layout. + +## Supported ABI Shape + +| argument or count | supported value | validation rule | +| --- | --- | --- | +| `NNODE` | `2` | reject anything else | +| `NDOFEL` | `12` | reject anything else | +| active DOFs per node | `1,2,3,4,5,6` | input keyword and kernel vector order must match | +| `MCRD` | `>= 3` | read only `COORDS(1:3,1:2)` | +| `NPROPS` | `9` | reject anything else | +| `NJPROP` | `0` | first scope uses no integer properties | +| `NSVARS` | `0` | first scope stores no persistent state | +| `NRHS` | `1` | reject multi-RHS procedures | +| `MLVARX` | `>= 12` | required for `RHS(1:12,1)` and `DU(1:12,1)` addressing | +| `NDLOAD` | `0` | element-generated distributed loads are unsupported | +| `MDLOAD` | any Abaqus value | no `JDLTYP`, `ADLMAG`, or `DDLMAG` entries are used because `NDLOAD=0` is required | +| `NPREDF` | any Abaqus value | predefined fields are ignored; thermal and field coupling are unsupported | + +Unsupported shape values are fatal input-contract violations. They must not silently produce zero stiffness or zero residual. + +## DOF Ordering and Kernel Mapping + +Abaqus element vector ordering is node-major: + +```text +1 node 1 U1 +2 node 1 U2 +3 node 1 U3 +4 node 1 UR1 +5 node 1 UR2 +6 node 1 UR3 +7 node 2 U1 +8 node 2 U2 +9 node 2 U3 +10 node 2 UR1 +11 node 2 UR2 +12 node 2 UR3 +``` + +The wrapper passes this global vector order directly to the beam kernel as `q_global`. The kernel then applies the formulation transform: + +```text +q_local = T*q_global +K_global = T^T*k_local*T +RHS = -K_global*q_global +``` + +No permutation is allowed between Abaqus `U(1:12)` and the kernel global vector. The local vector has the same node-major layout after projection to the local frame: + +```text +[u1, v1, w1, th1_1, th2_1, th3_1, u2, v2, w2, th1_2, th2_2, th3_2] +``` + +## `PROPS` and `JPROPS` Schema + +The first-scope interface uses `PROPS` only. `JPROPS` is not used. + +| index | name | unit | required rule | semantic | +| --- | --- | --- | --- | --- | +| `PROPS(1)` | `E` | force / length^2 | finite and `> 0` | Young's modulus | +| `PROPS(2)` | `G` | force / length^2 | finite and `> 0` | shear modulus for Saint-Venant torsion | +| `PROPS(3)` | `A` | length^2 | finite and `> 0` | cross-sectional area | +| `PROPS(4)` | `Iy` | length^4 | finite and `> 0` | second moment about local 2; couples local `w/th2` | +| `PROPS(5)` | `Iz` | length^4 | finite and `> 0` | second moment about local 3; couples local `v/th3` | +| `PROPS(6)` | `J` | length^4 | finite and `> 0` | Saint-Venant torsion constant | +| `PROPS(7)` | `a_ref_1` | dimensionless direction component | finite | global approximate local 2 reference x-component | +| `PROPS(8)` | `a_ref_2` | dimensionless direction component | finite | global approximate local 2 reference y-component | +| `PROPS(9)` | `a_ref_3` | dimensionless direction component | finite | global approximate local 2 reference z-component | + +Orientation vector rules: + +- `a_ref = [PROPS(7), PROPS(8), PROPS(9)]` is a global direction vector, not a point coordinate. +- The vector magnitude is arbitrary because the kernel normalizes its projection. +- Reject `norm(a_ref) <= 1.0e-12`. +- Reject `norm(a_ref - dot(a_ref,e1)*e1) / norm(a_ref) <= 1.0e-8`, where `e1` is the node 1 to node 2 beam axis. +- The accepted local frame is `e1 = node1->node2`, `e2 = normalized projected a_ref`, and `e3 = cross(e1,e2)`. + +`JPROPS` policy: + +- `NJPROP` must be `0`. +- No integer flags, versions, orientation modes, or diagnostics are accepted in first scope. +- Any future `JPROPS` use requires a revised interface contract and new tests. + +## Abaqus Input Keyword Subset + +The reference model plan should use this `.inp` subset. + +| keyword | support_status | required parameters | mapped concept | notes | +| --- | --- | --- | --- | --- | +| `*HEADING` | supported | none | model title | optional | +| `*NODE` | supported | none | node label and global coordinates | at least 3 coordinates per node for UEL geometry | +| `*ELEMENT` | supported | `TYPE=U1` or the approved user element type, optional `ELSET` | two-node UEL connectivity | connectivity order defines local axis 1 | +| `*ELSET` | supported | `ELSET` | element set | needed for `*UEL PROPERTY` | +| `*NSET` | supported | `NSET` | node set | recommended for BC/load/output selection | +| `*USER ELEMENT` | supported | `TYPE=U1`, `NODES=2`, `COORDINATES=3`, `PROPERTIES=9`, `VARIABLES=0` | UEL declaration | omit `UNSYMM`; omit `I PROPERTIES` | +| `*UEL PROPERTY` | supported | `ELSET` | real property assignment | data order is `PROPS(1:9)` | +| `*BOUNDARY` | supported | standard nodal DOF constraints | essential boundary conditions | DOFs 1-6 allowed | +| `*CLOAD` | supported | standard nodal concentrated load | external nodal loads/moments | loads are assembled by Abaqus outside UEL | +| `*STEP` | supported | optional `NAME` | analysis step | static only | +| `*STATIC` | supported | default or direct static data | small-displacement static procedure | no dynamics | +| `*OUTPUT` | supported | none | output request root | optional but required for external artifacts | +| `*NODE OUTPUT` | supported | `NSET` recommended | nodal CSV extraction source | request `U`, optional `UR`, `RF`/reaction moments as available | +| `*END STEP` | supported | none | step terminator | required | + +Unsupported in first scope: + +- `*DLOAD`, `*DSLOAD`, body forces, pressure loads, and distributed load generation +- `*MASS`, density, modal, transient, damping, and dynamic procedures +- `*BEAM SECTION`, `*BEAM GENERAL SECTION`, offsets, warping, and native beam section keywords for this UEL +- `*ORIENTATION` as the source of UEL orientation; use `PROPS(7:9)` instead +- material model keywords for UEL stiffness; use `*UEL PROPERTY` real values instead +- nonlinear geometry, follower loads, thermal expansion, predefined field coupling, plasticity, damage, creep, and viscoelastic behavior + +### Required `*USER ELEMENT` Shape + +The reference input deck should declare the user element with this logical content: + +```text +*USER ELEMENT, TYPE=U1, NODES=2, COORDINATES=3, PROPERTIES=9, VARIABLES=0 +1, 2, 3, 4, 5, 6 +``` + +If the final reference model chooses a different `TYPE=Un` identifier to avoid conflicts, the same `NODES`, `COORDINATES`, `PROPERTIES`, `VARIABLES`, and active DOF contract still applies. + +### Required `*UEL PROPERTY` Data Order + +```text +*UEL PROPERTY, ELSET= +E, G, A, Iy, Iz, J, a_ref_1, a_ref_2 +a_ref_3 +``` + +Line breaks may follow Abaqus input formatting rules, but the logical property order is fixed. + +## Subroutine Parameter Contract + +| parameter | direction | first-scope responsibility | +| --- | --- | --- | +| `RHS(MLVARX,*)` | output | Initialize requested storage to zero every call; for supported residual requests, set `RHS(1:12,1) = -K_global*U(1:12)`. | +| `AMATRX(NDOFEL,NDOFEL)` | output | Initialize all `12x12` entries to zero every call; for supported stiffness requests, set all entries to `K_global`. | +| `SVARS(*)` | input/output | unused; require `NSVARS=0`; do not store diagnostics in first scope. | +| `ENERGY(8)` | input/output | set `ENERGY(1:8)=0.0` every supported call; do not use as validation evidence in first scope. | +| `NDOFEL` | input | must equal `12`. | +| `NRHS` | input | must equal `1`. | +| `NSVARS` | input | must equal `0`. | +| `PROPS(*)` | input | must contain the 9 real values defined above. | +| `NPROPS` | input | must equal `9`. | +| `COORDS(MCRD,NNODE)` | input | read `COORDS(1:3,1)` and `COORDS(1:3,2)` as original global node coordinates. | +| `MCRD` | input | must be at least `3`. | +| `NNODE` | input | must equal `2`. | +| `U(NDOFEL)` | input | total current nodal DOF estimate; used for static residual. | +| `DU(MLVARX,*)` | input | not used for first-scope static residual; may be used only by no-Abaqus tests to confirm it is ignored. | +| `V(NDOFEL)` | input | ignored; dynamics out of scope. | +| `A(NDOFEL)` | input | ignored; dynamics out of scope. | +| `JTYPE` | input | not used except optional diagnostics; element type compatibility is enforced by `.inp` contract. | +| `TIME(2)` | input | ignored for linear static stiffness/residual; may be copied to diagnostics only. | +| `DTIME` | input | ignored; no time-step-dependent behavior. | +| `KSTEP`, `KINC` | input | not used in calculations; may be used only for diagnostics. | +| `JELEM` | input | element label for diagnostics and traceability. | +| `PARAMS(*)` | input | ignored; no dynamic procedure parameters supported. | +| `NDLOAD` | input | must equal `0`; distributed loads unsupported. | +| `JDLTYP`, `ADLMAG`, `DDLMAG`, `MDLOAD` | input | ignored only after confirming `NDLOAD=0`. | +| `PREDEF`, `NPREDF` | input | ignored; predefined fields unsupported. | +| `LFLAGS(*)` | input | used to identify small-displacement static request and requested contribution. | +| `MLVARX` | input | must be at least `12`. | +| `PNEWDT` | input/output | do not modify for valid supported calls; invalid immutable inputs must fail explicitly rather than rely on cutback recovery. | +| `JPROPS(*)`, `NJPROP` | input | require `NJPROP=0`; `JPROPS` ignored. | +| `PERIOD` | input | ignored; not used in static analysis. | + +## Supported `LFLAGS` Behavior + +The first-scope wrapper supports only small-displacement static calls: + +- require `LFLAGS(2)=0` +- support `LFLAGS(3)=1`, `2`, or `5` +- require `NRHS=1` + +Contribution rules: + +| condition | `AMATRX` | `RHS` | policy | +| --- | --- | --- | --- | +| `LFLAGS(3)=1` | `K_global` | `-K_global*U` | primary static call | +| `LFLAGS(3)=2` | `K_global` | zero | stiffness-only request | +| `LFLAGS(3)=5` | zero | `-K_global*U` | residual-only request | +| any other `LFLAGS(3)` | none | none | unsupported fatal diagnostic | + +Unsupported request examples include mass, damping, dynamics, half-step residuals, perturbation-only behavior, and large-displacement kinematics. + +## Validation Rules and Diagnostics + +Invalid input must be caught before matrix assembly. The implementation may choose the exact Abaqus-compatible fatal-reporting mechanism later, but it must preserve these diagnostic identifiers and meanings in tests or logs where feasible. + +| id | condition | expected behavior | +| --- | --- | --- | +| `UEL3DEB-E001` | `NDOFEL /= 12` | fatal unsupported element DOF count | +| `UEL3DEB-E002` | `NNODE /= 2` | fatal unsupported topology | +| `UEL3DEB-E003` | `MCRD < 3` | fatal missing 3D coordinates | +| `UEL3DEB-E004` | `NPROPS /= 9` | fatal wrong real property count | +| `UEL3DEB-E005` | `NJPROP /= 0` | fatal unsupported integer properties | +| `UEL3DEB-E006` | `NSVARS /= 0` | fatal unsupported state variables | +| `UEL3DEB-E007` | `NRHS /= 1` | fatal unsupported RHS count | +| `UEL3DEB-E008` | `MLVARX < 12` | fatal invalid RHS/DU leading dimension | +| `UEL3DEB-E009` | any required coordinate, `U`, or `PROPS` value is NaN or infinite | fatal nonfinite input | +| `UEL3DEB-E010` | `E`, `G`, `A`, `Iy`, `Iz`, or `J <= 0` | fatal nonpositive physical property | +| `UEL3DEB-E011` | element length `L <= 1.0e-12*max(1,norm(X1),norm(X2))` | fatal zero or near-zero element length | +| `UEL3DEB-E012` | `norm(a_ref) <= 1.0e-12` | fatal zero orientation reference | +| `UEL3DEB-E013` | `norm(a_perp)/norm(a_ref) <= 1.0e-8` | fatal near-parallel orientation reference | +| `UEL3DEB-E014` | `LFLAGS(2) /= 0` | fatal unsupported large-displacement or non-small-displacement request | +| `UEL3DEB-E015` | unsupported `LFLAGS(3)` | fatal unsupported contribution request | +| `UEL3DEB-E016` | `NDLOAD /= 0` | fatal unsupported element load input | + +For valid supported calls, the wrapper should set deterministic outputs for the requested contribution and should not modify `PNEWDT`. + +## Thin Wrapper Boundary + +The Abaqus ABI wrapper owns: + +- preserving the exact `UEL` signature and `ABA_PARAM.INC` include +- validating argument counts, dimensions, request flags, and property values +- extracting `X1`, `X2`, `U(1:12)`, and `PROPS(1:9)` +- mapping `LFLAGS` to requested stiffness/residual operations +- writing `AMATRX`, `RHS`, `SVARS`, `ENERGY`, and `PNEWDT` according to this contract +- reporting diagnostics with `JELEM`, `KSTEP`, and `KINC` when available + +The no-Abaqus beam kernel conceptually owns: + +- local frame construction from `X1`, `X2`, and `a_ref` +- local stiffness matrix assembly +- local-to-global transformation +- internal force and residual calculation +- numerical status reporting for invalid geometry or properties + +This document does not prescribe Fortran module names, source files, helper APIs, or data structures. + +## External CSV Extraction Schema + +All CSV files are externally generated from Abaqus results by the user. They must be placed under `references/uel-3d-euler-beam//extracted/` and declared in that model's `metadata.json`. + +### Required Common Columns + +Every comparison CSV row must include: + +| column | type | rule | +| --- | --- | --- | +| `step` | string | Abaqus step name or stable step index | +| `frame` | integer | frame or increment index | +| `time` | float | step time or total time used by extraction | +| `instance` | string | Abaqus instance name, or `ASSEMBLY` if not applicable | +| `node_label` | integer | Abaqus node label for nodal files | +| `quantity` | string | extracted output quantity, for example `U`, `UR`, `RF`, or `RM` | +| `component` | string | component label listed below | +| `coordinate_system` | string | must be `GLOBAL` for first-scope comparison | +| `unit` | string | declared user-consistent unit | +| `value` | float | numeric extracted value | + +The CSV schema uses long format, one component per row, to avoid ambiguity between translational and rotational quantities. + +### `nodal_displacements.csv` + +Required for external solver-result comparison. + +Allowed component rows: + +| quantity | component | unit type | required | +| --- | --- | --- | --- | +| `U` | `U1`, `U2`, `U3` | length | yes | +| `UR` | `UR1`, `UR2`, `UR3` | radian | optional unless the reference model compares rotations | + +Tolerance defaults: + +- displacement absolute tolerance: `1.0e-8` in declared length units +- rotation absolute tolerance: `1.0e-8` radians unless the reference model narrows it +- relative tolerance: reference model may add scale-aware relative tolerance when needed + +### `reactions.csv` + +Required for external solver-result comparison at constrained nodes. + +Allowed component rows: + +| quantity | component | unit type | required | +| --- | --- | --- | --- | +| `RF` | `RF1`, `RF2`, `RF3` | force | yes for constrained translational DOFs | +| `RM` | `RM1`, `RM2`, `RM3` | force*length | required when constrained rotational DOFs are part of the benchmark comparison | + +If the user's Abaqus extraction names rotational reactions differently, `metadata.json` must map the raw Abaqus variable/component name to the project component labels above. + +Tolerance defaults: + +- force and moment relative tolerance: `1.0e-6` +- absolute tolerance: Reference Model Agent must define a scale-aware floor for each benchmark if the expected reaction can be near zero + +### Optional Element-Level CSVs + +No element force, stress, strain, section force, or energy CSV is required or approved for first-scope external comparison. Such CSVs require a later `SVARS` or output-recovery contract. + +## Reference Artifact Metadata Requirements + +Each external reference model must include metadata fields sufficient for `scripts/validate_reference_artifacts.py` plus feature-level declarations: + +- `feature_id`: `uel-3d-euler-beam` +- Abaqus version and precision +- compiler vendor/name/version used for the user subroutine build, when applicable +- user subroutine source file hashes after implementation exists +- `model.inp` path and hash +- declared extracted CSV files and their schema version +- ODB extraction provenance, including extraction script name/version if available +- unit declarations for length, force, stress, moment, and rotation +- coordinate system declaration: `GLOBAL` for nodal comparison CSVs + +## Open Issues and Downstream Handoff + +### Reference Model Agent + +- Use the keyword subset and property order in this document for `model.inp` examples. +- Include no-Abaqus tests for exact `PROPS(1:9)` mapping, `NJPROP=0`, `NSVARS=0`, `NDOFEL=12`, `NNODE=2`, and active DOF order. +- Include negative tests for every `UEL3DEB-E###` validation rule that is practical in the no-Abaqus harness. +- Define benchmark-specific CSV filenames and near-zero absolute reaction tolerances. +- Keep external artifact generation outside this repository. + +### Implementation Planning Agent + +- Preserve the Abaqus `UEL` signature exactly in the wrapper. +- Keep the wrapper thin and route only validated arrays/scalars to a no-Abaqus beam kernel. +- Implement deterministic zeroing for non-requested `AMATRX`/`RHS` in no-Abaqus drivers so tests are stable. +- Do not implement `SVARS`, `ENERGY`, distributed loads, dynamics, `JPROPS`, or `*ORIENTATION` support in first scope. + +### Reference Verification Agent + +- Validate only externally generated CSVs declared in metadata. +- Match rows by `step`, `frame`, `instance`, `node_label`, `quantity`, `component`, `coordinate_system`, and `unit`. +- Reject CSVs with missing units, missing coordinate systems, unsupported component labels, or undeclared files. +- Compare first-scope external results using nodal displacement and reaction CSVs only. diff --git a/phases/uel-3d-euler-beam/index.json b/phases/uel-3d-euler-beam/index.json index 683435a..f009d06 100644 --- a/phases/uel-3d-euler-beam/index.json +++ b/phases/uel-3d-euler-beam/index.json @@ -29,7 +29,8 @@ { "step": 4, "name": "interface", - "status": "pending" + "status": "completed", + "summary": "Created docs/io-definitions/uel-3d-euler-beam.md with the Abaqus/Standard UEL signature, supported ABI shape, DOF and kernel mapping, PROPS/JPROPS and orientation schema, input keyword subset, LFLAGS/RHS/AMATRX/SVARS/ENERGY/PNEWDT responsibilities, validation diagnostics, CSV extraction schemas, and thin-wrapper boundary." }, { "step": 5,