fix: add abaqus uel wrapper contract
This commit is contained in:
@@ -3,10 +3,14 @@
|
||||
## Metadata
|
||||
- feature_id: abaqus-uel-subroutines
|
||||
- related_feature: `uel-3d-euler-beam`
|
||||
- status: ready-for-interface-correction
|
||||
- status: implemented-follow-up
|
||||
- owner_agent: research-agent
|
||||
- date: 2026-06-12
|
||||
|
||||
## Follow-up Status
|
||||
|
||||
The findings below captured the pre-correction state after the initial step 7 implementation. The follow-up correction in `docs/corrections/uel-3d-euler-beam-uel-abi-correction.md` adds the missing Abaqus-callable wrapper, changes the Abaqus-facing state-variable policy to `NSVARS>=1` / `VARIABLES=1`, and adds `LFLAGS(1)` and `LFLAGS(4)` validation.
|
||||
|
||||
## Research Questions
|
||||
- Abaqus/Standard가 실제로 호출하는 `UEL` subroutine의 positional ABI는 무엇인가?
|
||||
- `RHS`, `AMATRX`, `SVARS`, `ENERGY`, `PNEWDT`, `LFLAGS`의 update 책임은 무엇인가?
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
## Implementation Scope
|
||||
|
||||
Post-step ABI correction note: the original step 7 implementation deliberately deferred the fixed-form Abaqus `UEL` wrapper. The follow-up correction report `docs/corrections/uel-3d-euler-beam-uel-abi-correction.md` supersedes that deferred-wrapper status and records the added wrapper, `NSVARS>=1` policy, and `LFLAGS(1)/(4)` checks.
|
||||
|
||||
Production source added in this step:
|
||||
|
||||
- `src/fortran/uel_3d_euler_beam_kernel.f90`
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
# 3D Euler-Bernoulli Beam UEL ABI Correction Report
|
||||
|
||||
## Metadata
|
||||
- feature_id: uel-3d-euler-beam
|
||||
- source_failure_report: `docs/abaqus-uel-subroutines-research.md`
|
||||
- source_implementation_report: `docs/build-test-reports/uel-3d-euler-beam-green.md`
|
||||
- source_implementation_plan: N/A; correction follows the post-review research findings
|
||||
- status: corrected-for-build-test
|
||||
- owner_agent: correction-agent
|
||||
- date: 2026-06-12
|
||||
|
||||
## Failure Triage
|
||||
- classification: upstream-contract plus implementation defect
|
||||
- first_failed_command: `python -m unittest scripts.test_uel_3d_euler_beam_uel`; `python scripts/validate_fortran.py`
|
||||
- failed_target_or_test: missing Abaqus `UEL` wrapper; adapter rejected `NSVARS=1`
|
||||
- evidence_tail: wrapper source-smoke failed because `src/fortran/uel_3d_euler_beam_uel.for` was missing; Fortran ABI test failed with `actual=6 expected=0` for a valid `NSVARS=1` static call
|
||||
- triage_decision: implementation-owned correction allowed after research clarified the Abaqus manual ABI
|
||||
|
||||
## Root Cause Summary
|
||||
- root_cause_type: implementation boundary defect and stale interface policy
|
||||
- summary: the step 7 code implemented a testable kernel and no-Abaqus adapter, but did not expose the top-level Abaqus `SUBROUTINE UEL(...)`. The adapter also kept the pre-research `NSVARS=0` policy, conflicting with the documented `*USER ELEMENT, VARIABLES` requirement for a positive allocation.
|
||||
- why_minimal_fix_is_allowed: the correction preserves the existing kernel formulation and only fixes the Abaqus-facing call boundary, state-variable allocation check, and static-procedure `LFLAGS` validation.
|
||||
|
||||
## Correction Scope
|
||||
|
||||
| file | change_type | reason | in_scope |
|
||||
| --- | --- | --- | --- |
|
||||
| `src/fortran/uel_3d_euler_beam_uel.for` | source | add fixed-form Abaqus `UEL` wrapper with manual signature, `ABA_PARAM.INC`, manual dimensions, adapter call, and fatal `XIT` path | true |
|
||||
| `src/fortran/uel_3d_euler_beam_abi_adapter.f90` | source | accept `NSVARS>=1`, use explicit/manual-style array bounds, and validate `LFLAGS(1)` / `LFLAGS(4)` | true |
|
||||
| `src/fortran/uel_3d_euler_beam_kernel.f90` | source | add status ids for unsupported `LFLAGS(1)` and `LFLAGS(4)` | true |
|
||||
| `scripts/test_uel_3d_euler_beam_uel.py` | test | verify wrapper signature, include, dimensions, adapter call, and fatal path without requiring Abaqus include files | true |
|
||||
| `tests/test_uel_3d_euler_beam_uel.py` | test | expose a related test path for the production-source TDD guard | true |
|
||||
| `tests/fortran/uel_3d_euler_beam/test_abi_static.f90` | test | update valid adapter calls to `NSVARS=1` and explicit static `LFLAGS` values | true |
|
||||
| `tests/fortran/uel_3d_euler_beam/test_invalid_inputs.f90` | test | add `NSVARS<1`, `LFLAGS(1)`, and `LFLAGS(4)` diagnostics | true |
|
||||
| `tests/fortran/test_uel_3d_euler_beam_abi_adapter.f90` | test | update source-smoke adapter call to the corrected policy | true |
|
||||
| `docs/io-definitions/uel-3d-euler-beam.md` | documentation | align current interface contract with the implemented Abaqus-facing policy | true |
|
||||
| `docs/reference-models/uel-3d-euler-beam.md` | documentation | align test model and input-deck requirements with `VARIABLES=1` and wrapper source-smoke | true |
|
||||
|
||||
Excluded files:
|
||||
- reference artifacts: unchanged
|
||||
- tolerances: unchanged
|
||||
- formulation matrix/residual equations: unchanged
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
| order | command | exit_code | result | evidence |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | `python -m unittest scripts.test_uel_3d_euler_beam_uel` before implementation | 1 | RED | failed because `src/fortran/uel_3d_euler_beam_uel.for` did not exist |
|
||||
| 2 | `python scripts/validate_fortran.py` before implementation | 1 | RED | `uel_3d_euler_beam_abi_static` failed because `NSVARS=1` returned `UEL3DEB_E006_NSVARS` |
|
||||
| 3 | `python -m unittest scripts.test_uel_3d_euler_beam_uel` after implementation | 0 | pass | wrapper source-smoke passed |
|
||||
| 4 | `python scripts/validate_fortran.py` after implementation | 0 | pass | all six no-Abaqus Fortran manifest executables compiled and passed with Intel `ifx` |
|
||||
| 5 | `python -m unittest discover -s scripts -p "test_*.py"` | 0 | pass | 60 Python harness/source-smoke tests passed |
|
||||
| 6 | `python scripts/validate_workspace.py` | 0 | pass | reference artifact metadata validation and Fortran validation succeeded |
|
||||
| 7 | `git diff --check` | 0 | pass | no whitespace errors; line-ending warnings only |
|
||||
|
||||
## Traceability
|
||||
|
||||
| requirement_or_finding | corrected_file | acceptance_criterion |
|
||||
| --- | --- | --- |
|
||||
| C-UEL-001 / C-UEL-002 | `src/fortran/uel_3d_euler_beam_uel.for` | top-level external `SUBROUTINE UEL(...)` exists with manual ABI arguments |
|
||||
| C-UEL-003 | `src/fortran/uel_3d_euler_beam_uel.for`, `src/fortran/uel_3d_euler_beam_abi_adapter.f90` | Abaqus-facing boundary uses manual dimensions; adapter remains testable |
|
||||
| C-UEL-004 | `src/fortran/uel_3d_euler_beam_abi_adapter.f90`, `docs/io-definitions/uel-3d-euler-beam.md` | valid static adapter calls use `NSVARS=1`; `NSVARS<1` returns `UEL3DEB_E006_NSVARS` |
|
||||
| C-UEL-005 | `src/fortran/uel_3d_euler_beam_abi_adapter.f90` | unsupported `LFLAGS(1)` and `LFLAGS(4)` return dedicated diagnostics |
|
||||
|
||||
## Handoff Recommendation
|
||||
|
||||
| target_agent | reason | required_input |
|
||||
| --- | --- | --- |
|
||||
| Build/Test Executor Agent | run full workspace validation after correction | this report and command evidence |
|
||||
| Reference Verification Agent | update external model expectations to `VARIABLES=1` before user-generated Abaqus artifacts are prepared | corrected I/O and reference-model documents |
|
||||
| Physics Evaluation Agent | no formulation behavior changed; external CSV physics checks remain pending | future user-provided reference bundles |
|
||||
|
||||
## Stop Condition
|
||||
- repeated_failure: false
|
||||
- upstream_ambiguity: false
|
||||
- reference_artifact_gap: true
|
||||
- environment_blocker: false
|
||||
- next_required_decision: user must still provide external Abaqus artifacts before solver-result validation can complete
|
||||
@@ -54,7 +54,7 @@ The wrapper must keep `aba_param.inc` / `ABA_PARAM.INC` as an Abaqus/Standard in
|
||||
| `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 |
|
||||
| `NSVARS` | `>= 1` | Abaqus `*USER ELEMENT` state-variable allocation must be positive; first scope leaves allocated `SVARS` entries unchanged |
|
||||
| `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 |
|
||||
@@ -137,7 +137,7 @@ The reference model plan should use this `.inp` subset.
|
||||
| `*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` |
|
||||
| `*USER ELEMENT` | supported | `TYPE=U1`, `NODES=2`, `COORDINATES=3`, `PROPERTIES=9`, `VARIABLES=1` | UEL declaration | omit `UNSYMM`; omit `I PROPERTIES`; `SVARS(1)` is unused |
|
||||
| `*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 |
|
||||
@@ -161,7 +161,7 @@ Unsupported in first scope:
|
||||
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
|
||||
*USER ELEMENT, TYPE=U1, NODES=2, COORDINATES=3, PROPERTIES=9, VARIABLES=1
|
||||
1, 2, 3, 4, 5, 6
|
||||
```
|
||||
|
||||
@@ -183,11 +183,11 @@ Line breaks may follow Abaqus input formatting rules, but the logical property o
|
||||
| --- | --- | --- |
|
||||
| `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. |
|
||||
| `SVARS(*)` | input/output | unused; require `NSVARS>=1` for Abaqus keyword compatibility; 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`. |
|
||||
| `NSVARS` | input | must be at least `1`. |
|
||||
| `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. |
|
||||
@@ -218,6 +218,8 @@ The first-scope wrapper supports only small-displacement static calls:
|
||||
|
||||
- require `LFLAGS(2)=0`
|
||||
- support `LFLAGS(3)=1`, `2`, or `5`
|
||||
- require `LFLAGS(1)=1` or `2` for static procedure calls
|
||||
- require `LFLAGS(4)=0` for general-step behavior, not perturbation-only output
|
||||
- require `NRHS=1`
|
||||
|
||||
Contribution rules:
|
||||
@@ -242,7 +244,7 @@ Invalid input must be caught before matrix assembly. The implementation may choo
|
||||
| `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-E006` | `NSVARS < 1` | fatal missing Abaqus state-variable allocation |
|
||||
| `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 |
|
||||
@@ -253,6 +255,8 @@ Invalid input must be caught before matrix assembly. The implementation may choo
|
||||
| `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 |
|
||||
| `UEL3DEB-E017` | `LFLAGS(1)` is not `1` or `2` | fatal unsupported non-static procedure request |
|
||||
| `UEL3DEB-E018` | `LFLAGS(4) /= 0` | fatal unsupported perturbation-output request |
|
||||
|
||||
For valid supported calls, the wrapper should set deterministic outputs for the requested contribution and should not modify `PNEWDT`.
|
||||
|
||||
@@ -358,7 +362,7 @@ Each external reference model must include metadata fields sufficient for `scrip
|
||||
### 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 no-Abaqus tests for exact `PROPS(1:9)` mapping, `NJPROP=0`, `NSVARS>=1`, `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.
|
||||
|
||||
@@ -31,7 +31,7 @@ Production source paths planned for later steps:
|
||||
| --- | --- | --- |
|
||||
| `src/fortran/uel_3d_euler_beam_kernel.f90` | pure/testable beam geometry, local stiffness, transform, residual, and validation logic | compiled by all no-Abaqus kernel and ABI adapter tests |
|
||||
| `src/fortran/uel_3d_euler_beam_abi_adapter.f90` | Abaqus-array adapter logic without the literal Abaqus `UEL` entry point | compiled by no-Abaqus ABI mapping tests |
|
||||
| `src/fortran/uel_3d_euler_beam_uel.for` | thin Abaqus/Standard fixed-form `UEL` wrapper preserving the manual signature and `ABA_PARAM.INC` include | not required for no-Abaqus compile in first RED tests; later wrapper smoke can be added when an Abaqus-compatible include environment is available |
|
||||
| `src/fortran/uel_3d_euler_beam_uel.for` | thin Abaqus/Standard fixed-form `UEL` wrapper preserving the manual signature and `ABA_PARAM.INC` include | checked by Python source-smoke because the file depends on Abaqus-provided include and `XIT` |
|
||||
|
||||
Planned test source paths for step 6:
|
||||
|
||||
@@ -43,6 +43,7 @@ Planned test source paths for step 6:
|
||||
| `tests/fortran/uel_3d_euler_beam/test_kernel_transform_modes.f90` | transformation, symmetry, reversed node order, and rigid-body mode tests |
|
||||
| `tests/fortran/uel_3d_euler_beam/test_abi_static.f90` | no-Abaqus ABI adapter tests for `RHS`, `AMATRX`, `ENERGY`, dimensions, and `LFLAGS` |
|
||||
| `tests/fortran/uel_3d_euler_beam/test_invalid_inputs.f90` | validation diagnostics and unsupported-request tests |
|
||||
| `scripts/test_uel_3d_euler_beam_uel.py` | source-smoke contract for the fixed-form Abaqus `UEL` wrapper signature and dimensions |
|
||||
|
||||
Step 6 RED expectation:
|
||||
|
||||
@@ -123,10 +124,10 @@ Step 6 should create this planned manifest:
|
||||
| NOA-A-RHS-001 | `uel_3d_euler_beam_abi_static` | ABI/residual | verify `RHS(1:12,1)=-K_global*U(1:12)` for `LFLAGS(3)=1` and `5` | compile failure or wrong sign | REQ-009 |
|
||||
| NOA-A-AMATRX-001 | `uel_3d_euler_beam_abi_static` | ABI/stiffness | verify `AMATRX=K_global` for `LFLAGS(3)=1` and `2` and zeroed matrix for residual-only requests | compile failure or mapping mismatch | REQ-003, REQ-004, REQ-008 |
|
||||
| NOA-A-PROPS-001 | `uel_3d_euler_beam_abi_static` | ABI/property mapping | verify `PROPS(1:9)` maps to `E,G,A,Iy,Iz,J,a_ref_1,a_ref_2,a_ref_3` exactly | compile failure or property permutation mismatch | REQ-005, REQ-007 |
|
||||
| NOA-A-ENERGY-001 | `uel_3d_euler_beam_abi_static` | ABI/output policy | verify `ENERGY(1:8)=0.0`, `NSVARS=0`, and `PNEWDT` is not changed for valid supported calls | compile failure or output policy mismatch | REQ-010 |
|
||||
| NOA-A-ENERGY-001 | `uel_3d_euler_beam_abi_static` | ABI/output policy | verify `ENERGY(1:8)=0.0`, `NSVARS>=1`, and `PNEWDT` is not changed for valid supported calls | compile failure or output policy mismatch | REQ-010 |
|
||||
| NOA-I-SHAPE-001 | `uel_3d_euler_beam_invalid_inputs` | negative | verify diagnostics for `NDOFEL`, `NNODE`, `MCRD`, `NPROPS`, `NJPROP`, `NSVARS`, `NRHS`, `MLVARX` violations | compile failure or missing diagnostic | REQ-003, REQ-006 |
|
||||
| NOA-I-PHYS-001 | `uel_3d_euler_beam_invalid_inputs` | negative | verify diagnostics for nonfinite coordinates/properties, nonpositive `E,G,A,Iy,Iz,J`, zero length, zero orientation, and near-parallel orientation | compile failure or missing diagnostic | REQ-006, REQ-007 |
|
||||
| NOA-I-LFLAGS-001 | `uel_3d_euler_beam_invalid_inputs` | negative | verify diagnostics for unsupported `LFLAGS(2)`, unsupported `LFLAGS(3)`, and `NDLOAD /= 0` | compile failure or missing diagnostic | REQ-010 |
|
||||
| NOA-I-LFLAGS-001 | `uel_3d_euler_beam_invalid_inputs` | negative | verify diagnostics for unsupported `LFLAGS(1)`, unsupported `LFLAGS(2)`, unsupported `LFLAGS(3)`, unsupported `LFLAGS(4)`, and `NDLOAD /= 0` | compile failure or missing diagnostic | REQ-010 |
|
||||
|
||||
Default no-Abaqus tolerances:
|
||||
|
||||
@@ -143,10 +144,11 @@ The production `UEL` wrapper itself should remain a thin Abaqus ABI entry point.
|
||||
|
||||
The ABI adapter tests must verify:
|
||||
|
||||
- `NDOFEL=12`, `NNODE=2`, `MCRD>=3`, `NPROPS=9`, `NJPROP=0`, `NSVARS=0`, `NRHS=1`, and `MLVARX>=12`
|
||||
- `NDOFEL=12`, `NNODE=2`, `MCRD>=3`, `NPROPS=9`, `NJPROP=0`, `NSVARS>=1`, `NRHS=1`, and `MLVARX>=12`
|
||||
- `COORDS(1:3,1:2)` maps to `X1`, `X2`
|
||||
- `U(1:12)` maps to the global kernel vector without permutation
|
||||
- `PROPS(1:9)` maps exactly to the interface contract
|
||||
- `LFLAGS(1)=1|2`, `LFLAGS(2)=0`, `LFLAGS(3)=1|2|5`, and `LFLAGS(4)=0` select the supported static general-step path
|
||||
- `LFLAGS(3)=1`, `2`, and `5` select the expected `AMATRX` and `RHS` outputs
|
||||
- non-requested `AMATRX` or `RHS` storage is deterministically zeroed by the no-Abaqus adapter
|
||||
- `ENERGY(1:8)` is zeroed and `SVARS` is unused
|
||||
@@ -252,7 +254,7 @@ Every external `model.inp` must stay within the supported keyword subset from `d
|
||||
- `*ELEMENT`
|
||||
- `*ELSET`
|
||||
- `*NSET`
|
||||
- `*USER ELEMENT, TYPE=U1, NODES=2, COORDINATES=3, PROPERTIES=9, VARIABLES=0`
|
||||
- `*USER ELEMENT, TYPE=U1, NODES=2, COORDINATES=3, PROPERTIES=9, VARIABLES=1`
|
||||
- active DOF line: `1, 2, 3, 4, 5, 6`
|
||||
- `*UEL PROPERTY, ELSET=<uel_element_set>` with data order `E,G,A,Iy,Iz,J,a_ref_1,a_ref_2,a_ref_3`
|
||||
- `*BOUNDARY`
|
||||
|
||||
Reference in New Issue
Block a user