docs: define MITC4 shell I/O contract

This commit is contained in:
KOKO\Mimi
2026-08-12 01:23:56 +09:00
parent 8b412f7c80
commit 73dc761282
@@ -0,0 +1,759 @@
# Linear Static MITC4 Shell I/O Definition
## Metadata
- feature_id: `linear-static-mitc4-shell`
- source_requirement: `docs/requirements/linear-static-mitc4-shell.md`
- source_research: `docs/research/linear-static-mitc4-shell-research.md`
- source_formulation: `docs/formulations/mitc4-shell-formulation.md`
- source_numerical_review: `docs/numerical-reviews/linear-static-mitc4-shell-review.md`
- source_commits: requirements `5c3025a`, research `02680dc`, formulation
`6cb0302`, numerical review `ebb2657`, S4 legacy artifacts `57122b0`
- status: `ready-for-reference-model-not-implementation-planning`
- owner_agent: `io-definition-agent`
- date: `2026-08-12`
- authoritative_output: `results.h5`
- hdf5_schema_version: `0`
- current_reference_alias: `reference/shell/` as read-only S4 legacy alias
- missing_reference_family: separate canonical S4R bundle
- implementation_planning_authorized: `false`
This document defines the approved semantic input and output contract for the
linear-static MITC4 shell feature. It does not define parser, model, HDF5-writer, or
comparison-tool C++ APIs and does not claim full Abaqus compatibility or Abaqus
`S4`/`S4R` formulation equivalence.
The user approved the following I/O-specific decisions on `2026-08-12`:
1. `S4` and `S4R` reference artifacts remain separate even though both source types
map to one internal `FESA-MITC4` formulation.
2. The optional positive integer on a `*SHELL SECTION` thickness row is accepted
without a warning and has no semantic effect on FESA quadrature. FESA always uses
the formulation's `2 x 2 x 2` rule.
3. The existing `reference/shell/` files are retained without mutation as an exact
S4 legacy alias. Missing provenance is supplied only by a separately approved
Reference Model contract; it is not inferred here.
4. HDF5 schema version `0` is extended additively with MITC4-specific datasets while
retaining the existing common metadata, nodal-result, diagnostic, CLI, and
failure-atomicity conventions.
Numerical Review has accepted the current linear formulation but has not approved
the drilling default, geometry/director thresholds, U mixed tolerance, or UR warning
threshold. This I/O contract names where those approved values must appear but does
not invent implementation defaults.
## 1. Abaqus Input Scope
- input_format: Abaqus input file (`.inp`)
- supported_analysis: exactly one small-displacement, small-rotation linear-static
step containing four-node `S4` and/or `S4R` shell elements
- ordinary_unit_system: user-consistent; FESA does not infer SI or another unit
system from an `.inp` file
- internal_element_formulation: `FESA-MITC4`
- compatibility_disclaimer: only the keyword locations, parameters, and data grammar
in this document are supported
`supported` means only the documented subset is semantically interpreted. `warning
no-op` means the syntax is consumed and a structured warning is recorded, but no
Domain, AnalysisModel, numerical, or mandatory-output meaning changes. The optional
`*SHELL SECTION` integration-point field is a separately approved silent provenance
field, not a warning no-op keyword.
| keyword | status and allowed location | required parameters and data grammar | semantic mapping | unsupported behavior |
| --- | --- | --- | --- | --- |
| `*HEADING` | supported; optional top-level first keyword | no parameters; zero or more text rows until next keyword | original heading retained as source metadata | nested location or parameters are input errors |
| `*PART` / `*END PART` | supported; top-level model block | `NAME=<part-name>` required; no `*END PART` data | scope for part-local nodes, elements, sets, and shell sections | unclosed/nested part or duplicate name is an input error |
| `*NODE` | supported; part scope | no parameters; each row `node_label,x,y,z` | positive source node label and finite global Cartesian coordinates | wrong arity, duplicate label, or nonfinite value is an input error |
| `*ELEMENT` | supported; part scope | `TYPE=S4` or `TYPE=S4R`; each row `element_label,node_1,node_2,node_3,node_4` | ordered four-node shell connectivity; source type retained separately; internal type is `FESA-MITC4` | another type is `unsupported-element-formulation`; wrong arity, repeated connected node, or dangling node is an error |
| `*NSET` | supported; part or assembly scope | `NSET=<name>`; optional `GENERATE`; assembly scope requires `INSTANCE=<name>`; explicit labels or `first,last,increment` | deterministic node-set membership | mixed-instance set, invalid generate range, duplicate name, or dangling member is an error |
| `*ELSET` | supported; part or assembly scope | `ELSET=<name>`; optional `GENERATE`; assembly scope requires `INSTANCE=<name>`; same row rules as `*NSET` | deterministic element-set membership | mixed-instance set, invalid range, duplicate name, or dangling member is an error |
| `*MATERIAL` | supported; top-level model data | `NAME=<material-name>` required; no data | owns exactly one approved isotropic `*ELASTIC` definition | duplicate name, missing/duplicate elasticity, or another material model is an error |
| `*ELASTIC` | supported; current material scope | no parameters; exactly one row `E,nu` | homogeneous isotropic elasticity; `G=E/(2(1+nu))` | extra row/field, dependency/temperature data, nonfinite value, `E<=0`, or `nu<=-1`/`nu>=0.5` is an error |
| `*SHELL SECTION` | supported; part scope | `ELSET=<name>` and `MATERIAL=<name>` required; exactly one row `thickness[,integration_points]` | one centered homogeneous layer with constant thickness | composite/layer data, offset, orientation, distributed/nodal thickness, missing reference, or conflicting assignment is an error |
| `*ASSEMBLY` / `*END ASSEMBLY` | supported; exactly one top-level assembly | `NAME=<assembly-name>` required; no end data | scope for identity instances and assembly sets | nested/duplicate assembly is `unsupported-nested-assembly` |
| `*INSTANCE` / `*END INSTANCE` | supported; assembly scope | `NAME=<instance-name>`, `PART=<part-name>` required; no intervening data | named identity copy; multiple instances of a part are allowed | translation/rotation data is `unsupported-instance-transform`; duplicate or dangling instance is an error |
| `*BOUNDARY` | supported; top-level model data or sole step | no parameters; each row `target,first_dof,last_dof[,value]`; omitted value is exact zero | prescribed global shell DOFs 1 through 6 | invalid arity/range, unresolved target, or conflicting expanded value is an error |
| `*CLOAD` | supported; sole step | no parameters; each row `target,dof,magnitude` | concentrated global nodal force/moment on DOFs 1 through 6 | invalid arity/DOF, nonfinite magnitude, unresolved target, or drilling-direction aggregate moment is an error |
| `*STEP` / `*END STEP` | supported; exactly one top-level history block | optional `NAME`; optional `NLGEOM=NO`; no end data | one canonical result identity `(Step-1,frame 0)` | second step is `unsupported-multiple-step`; `NLGEOM=YES` is `unsupported-nonlinear-geometry` |
| `*STATIC` | supported; exactly once in sole step | no parameters; exactly one row `initial_increment,time_period,minimum_increment,maximum_increment` | source values retained; exactly one linear solve and frame 0 | another procedure or missing/extra/nonfinite/nonpositive field is an error |
| `*PREPRINT` | warning no-op; top-level | all parameters retained then ignored; no data | accepts generator control | no semantic object is created |
| `*RESTART` | warning no-op; sole step | all parameters retained then ignored; no data | accepts a legacy restart request | no restart state is created |
| `*OUTPUT, FIELD` | warning no-op; sole step | parameters and subordinate variable data retained then ignored | accepts field-output request root | cannot select, suppress, or expand mandatory FESA output |
| `*OUTPUT, HISTORY` | warning no-op; sole step | parameters and subordinate variable data retained then ignored | accepts history-output request root | no history dataset is created |
| `*NODE OUTPUT` | warning no-op; active output request | all parameters and following variable rows ignored | accepts legacy nodal request | cannot change the HDF5 schema |
| `*ELEMENT OUTPUT` | warning no-op; active output request | all parameters and following variable rows ignored | accepts legacy element request | cannot change the HDF5 schema |
| `*CONTACT OUTPUT` | warning no-op; active output request | all parameters and following variable rows ignored | accepts legacy contact-output syntax only | no contact model or output is created |
`*DLOAD`, pressure, gravity, body force, edge traction, follower load, explicit
normal/director input, `*ORIENTATION`, composite/layer controls, `*INCLUDE`, and
model-affecting keywords not listed above are `unsupported-keyword` errors. A mixed
B33/shell model and a shell-beam joint are `unsupported-mixed-element-model`; the
presence of an existing B33 implementation does not expand this feature contract.
Multiple `*ELEMENT` blocks containing `S4`, `S4R`, or both are allowed. Every element
retains its own source element type, and source type never changes FESA quadrature,
tying, drilling, recovery, or numerical path.
### 1.1 Shell-section data rule
The exact accepted data row is
```text
thickness[,integration_points]
```
- `thickness` is a finite `double` strictly greater than zero.
- If present, `integration_points` is a positive base-10 integer.
- The optional field is syntactically accepted without a warning and has no Domain,
quadrature, recovery, or output effect.
- The raw input remains recoverable through the source file/content identity, but
no `source_integration_points` physical property is created.
- FESA stiffness remains four midsurface Gauss locations times two thickness Gauss
locations, including when the source value is `5` as in the S4 legacy deck.
Silently accepting this field is an explicit feature contract, not a general rule
that Abaqus section parameters may be ignored.
### 1.2 Nesting grammar
```text
input-file
:= heading? part+ assembly material+ model-boundary* step EOF
part
:= *PART
node-block+ element-block+ (nset | elset)* shell-section+
*END PART
assembly
:= *ASSEMBLY
instance+ assembly-set*
*END ASSEMBLY
instance
:= *INSTANCE *END INSTANCE
step
:= *STEP *STATIC step-boundary* cload* allowed-no-op* *END STEP
```
All parts close before assembly. Assembly contains only identity instances and
assembly-level sets. Instance-local node/element redefinition, nested assembly,
instance transforms, and dependent/independent mesh semantics are excluded.
## 2. Syntax Policy
- The first non-whitespace character of a keyword line is `*`; `**` begins a comment.
- Comments have no semantic effect but retain normalized file and 1-based line
provenance for neighboring parsed records.
- Keyword names, parameter names, enumerated values, and named-reference lookup are
ASCII case-insensitive. Raw source spelling remains available for identity and
diagnostics.
- Keyword and data fields are comma-separated with surrounding whitespace removed.
A required empty field, an unexpected trailing field, or a malformed numeric token
is an input error.
- Keyword continuation, physical-line continuation, quoted/multiline names, and
include files are unsupported. Each logical keyword or data row is complete on one
physical line.
- Node/element labels and explicit set members are positive base-10 integers.
Internal numeric IDs do not replace preserved source label text.
- All real-valued input is finite. `NaN` and positive/negative infinity are rejected.
- Every parsed keyword, parameter, data row, and semantic entity remains traceable to
normalized file path, 1-based line, raw keyword, and source identity.
- Output-request variable data is a warning no-op only while subordinate to an
allowlisted output keyword. An unexpected standalone data line is an input error.
### 2.1 Duplicate and dangling-reference policy
- Part, assembly, instance, material, set, and section identities are unique in
their documented case-insensitive scope.
- Node and element source labels are unique within a part.
- Multiple identity instances of the same part are distinct through instance name.
- Connectivity, set membership, instance `PART`, section `ELSET`/`MATERIAL`, assembly
set `INSTANCE`, boundary target, and load target all resolve before Domain commit.
- Duplicate definitions use `duplicate-entity`; unresolved references use
`unresolved-reference`. A partial Domain is never passed to analysis.
## 3. Model Data Mapping
### 3.1 Stable source identity and ordering
After identity-instance expansion, each node and element has
```text
SourceEntityId { instance_name, source_label }
```
Raw spelling and the case-insensitive lookup key are separate. Stable internal IDs
follow input part declaration order, instance declaration order, and part-local
entity declaration order. Hash iteration and thread scheduling cannot affect IDs,
director accumulation, result rows, or diagnostics.
Assembly sets name one identity instance and resolve their numeric members to that
instance's part-local source identities. A set cannot mix members from multiple
instances in the approved grammar.
### 3.2 Nodes, elements, sets, material, and section
- A node has global Cartesian coordinates, stable internal ID, source identity,
geometry-derived initial director, and deterministic tangent frame.
- A shell element has ordered connectivity `[node_1,node_2,node_3,node_4]`, stable
internal ID, source identity, preserved source type `S4` or `S4R`, internal type
`FESA-MITC4`, and exactly one resolved section/material.
- Connectivity order fixes natural corners `1=(-1,-1)`, `2=(+1,-1)`,
`3=(+1,+1)`, `4=(-1,+1)` and positive thickness through
`A_xi x A_eta`. Connectivity is not silently reversed.
- Explicit set order follows data rows. Generated sets use inclusive
`first,last,increment` order. Set members remain round-trippable to source identity.
- Material preserves `E` and `nu`; `G=E/(2(1+nu))` is derived.
- Section preserves positive constant thickness and resolved material. It represents
one centered homogeneous isotropic layer.
- Multiple materials, sections, element sets, `S4` blocks, and `S4R` blocks are
allowed when each element resolves to exactly one valid assignment.
### 3.3 Director and geometry preprocessing
Initial directors are semantic model data derived after instance expansion, not
parser-provided rotations.
1. Process accepted shell elements in stable source-element order.
2. Compute each source-order-positive center normal candidate and its `2 x 2`
surface-area weight.
3. At each node, sort incident elements by stable source identity and reject any
nonpositive pairwise normal dot product before averaging.
4. Form and normalize the deterministic area-weighted director.
5. Apply the approved smooth-patch angle criterion.
6. Select the least-aligned global basis axis with fixed `x,y,z` tie order and form
right-handed nodal frame `[a,b,d]`.
The complete center, volume-Gauss, tying, and committed-recovery inventory uses the
formulation's `J`, `j_s`, `a_g`, `c_d`, `r_J`, and `theta_w` measures. Exact numerical
thresholds are required inputs from a future approved Numerical Review decision;
this document supplies no fallback, clamp, point omission, normal flip, or default
axis.
Geometry and director failures are model-validation errors. Duplicate connectivity,
self-intersection, degenerate/reversed geometry, invalid Jacobians, opposed incident
normals, and unapproved sharp folds fail closed.
## 4. History Data Mapping
### 4.1 Step and procedure
Exactly one history object is created. The source step name remains provenance, but
the result identity is literal `Step-1`, frame index `0`. The four `*STATIC` values
are finite positive source data and `minimum_increment <= maximum_increment`; they do
not create increments, iteration history, or additional frames.
`NLGEOM=NO` or omission is accepted. `NLGEOM=YES`, another procedure, or another step
is unsupported. The future nonlinear formulation does not expand this history
contract.
### 4.2 Boundary conditions
Boundary target is a direct source node label or node set and expands to stable
source node identities. `first_dof <= last_dof`, with both in `1..6`. Omitted value
is exact zero; a finite nonzero value is supported. Model-level and step-level
boundaries activate in the sole step. Different prescribed values on one expanded
node/DOF are an error.
| DOF | kinematic component | unit dimension |
| ---: | --- | --- |
| 1 | `U1` | length |
| 2 | `U2` | length |
| 3 | `U3` | length |
| 4 | `UR1` | radian/dimensionless angle |
| 5 | `UR2` | radian/dimensionless angle |
| 6 | `UR3` | radian/dimensionless angle |
### 4.3 Concentrated loads and drilling projection
`*CLOAD` target expansion matches boundary expansion. Rows resolving to the same
node/DOF are accumulated in stable source order before physical admissibility is
tested.
| DOF | load component | unit dimension |
| ---: | --- | --- |
| 1 | `F1` | force |
| 2 | `F2` | force |
| 3 | `F3` | force |
| 4 | `M1` | force*length |
| 5 | `M2` | force*length |
| 6 | `M3` | force*length |
For aggregate nodal moment `M_I` and approved unit director `d_I`, exact-zero moment
is accepted as a separate case. Otherwise compute, without denominator clamping,
```text
rho_M = abs(dot(d_I,M_I)) / norm(M_I)
```
and require `rho_M <= 1e-12`. Failure is `unsupported-drilling-load`. No part of a
rejected physical moment is transferred to numerical drilling stabilization.
### 4.4 Output requests
Allowlisted Abaqus output requests do not activate history output and cannot change
the mandatory HDF5 inventory. FESA writes all datasets in Section 6 on a successful
run even when the input contains no output request. Requested Abaqus variables that
have no FESA dataset do not create empty synthetic physical results.
## 5. Internal Model Contract
- Domain owns the complete immutable-after-mapping definition of nodes, shell
elements, sets, materials, sections, boundary/load data, sole static step, stable
source identities, initial directors, and source formulation labels.
- `S4`/`S4R` remains source metadata. Numerical selection uses one explicit internal
identity, `FESA-MITC4`.
- AnalysisModel is a non-owning view of active Domain objects and does not copy them.
- Nodes/elements do not own equation IDs. Six-DOF numbering, constrained/free maps,
scatter maps, and sparse pattern are DofManager responsibilities.
- Boundary and load records retain both the source target and their deterministic
expanded source-node identities.
- Section/material assignment is resolved before element processing. An element with
zero or multiple assignments is invalid.
- AnalysisState contains only the current linear-static displacement, external and
internal force, full residual/reaction, shell recovery, equilibrium, and energy
rows. No nonlinear director history, iteration state, velocity, or acceleration is
allocated.
- Midsurface generalized rows, section-position stress rows, nodal rows, global
equilibrium rows, and drilling evidence have distinct quantity/location identity.
Values from different locations are never averaged to satisfy a schema.
## 6. Output HDF5 Schema
The sole authoritative output is `results.h5`, schema version `0`. MITC4 extends
that schema additively; it does not migrate or reinterpret B33 datasets. Every
string is UTF-8, every physical real is IEEE-754 float64, stable internal IDs are
uint64, and constraint masks are uint8.
The literal result path identity is `(Step-1,frame 0)`. No history or nonlinear
frame group is created.
### 6.1 Metadata
`/metadata` is a group with these required scalar attributes:
| attribute | required value or meaning |
| --- | --- |
| `schema_version` | integer `0` |
| `feature_id` | `linear-static-mitc4-shell` |
| `solver_version` | executing solver version |
| `source_input_identity` | normalized input path plus auditable content identity |
| `unit_system_label` | ordinary run: `user-consistent-unspecified`; a reference run uses the externally approved label from its Reference Model metadata |
| `coordinate_convention` | `global-cartesian; shell-local=(e1,e2,e3); positive-thickness=+zeta` |
| `internal_formulation` | `FESA-MITC4` |
| `integration_rule` | `2x2x2-gauss; mitc4-edge-midpoint-shear` |
| `step_name` | `Step-1` |
| `frame_index` | integer `0` |
| `drilling_reference_family` | exact approved family identifier used in this run |
| `drilling_nominal_coordinate` | approved dimensionless nominal `rho_d` policy identifier/value |
| `theta_smooth` | approved smooth-patch bound used in validation |
| `tau_ang` | approved `j_s` bound |
| `tau_area` | approved `a_g` bound |
| `tau_dir` | approved `c_d` bound |
| `tau_var` | approved `r_J` bound |
| `theta_warp` | approved `theta_w` bound |
| `drilling_energy_warning_threshold` | approved warning rule identifier/value |
No unapproved stand-in number is legal in these numerical-policy attributes. The writer can
be implementation-ready only after Numerical Review approves their values and
definition identifiers.
### 6.2 Model identity datasets
| exact dataset path | shape/dtype | row identity and fields | attributes/order |
| --- | --- | --- | --- |
| `/model/nodes` | `[node_count]` compound | `internal_node_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `coordinates:float64[3]` | internal node ID ascending; global Cartesian; coordinate unit `length` |
| `/model/elements` | `[element_count]` compound | `internal_element_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `source_element_type:utf8`, `internal_formulation:utf8`, `node_internal_ids:uint64[4]`, `shell_section_internal_id:uint64`, `material_internal_id:uint64` | internal element ID ascending; connectivity in exact source order; source type `S4|S4R`; formulation `FESA-MITC4` |
| `/model/shell/nodal_director` | `[node_count,3]` float64 | `/model/nodes` row | dimensionless global components; unit norm within `1e-12` frame check |
| `/model/shell/nodal_frame` | `[node_count,3,3]` float64 | `/model/nodes` row, axis row `[a,b,d]`, global component column | dimensionless; right-handed and orthonormal |
| `/model/shell/materials` | `[material_count]` compound | `internal_material_id`, raw `name`, `E`, `nu` | stable declaration order; units `[force/length^2,1]` |
| `/model/shell/sections` | `[section_count]` compound | `internal_section_id`, source keyword file/line identity, source ELSET, `material_internal_id`, `thickness` | stable declaration order; centered single layer; thickness unit `length` |
| `/model/nodal_constraint_mask` | `[node_count,6]` uint8 | node row and global DOF order | `0=free`, `1=constrained`; existing HDF5 component names `[UX,UY,UZ,URX,URY,URZ]` |
| `/model/prescribed_displacement` | `[node_count,6]` float64 | same row/component order | constrained entry is prescribed value; free entry is exact zero with mask as authority |
| `/model/shell/midsurface_locations` | `[4,2]` float64 | `location_index` implicit row 1..4; columns `[xi,eta]` | exact order in Section 6.3; dimensionless |
| `/model/shell/section_positions` | `[3]` float64 | rows `BOTTOM,MIDDLE,TOP`; value is `zeta` | exact values `[-1,0,+1]`; physical `z=t*zeta/2` |
The optional source shell-section integration-point field is not written as a
physical model property. Exact source bytes remain auditable through
`source_input_identity`.
### 6.3 Fixed shell location ordering
Let `g=1/sqrt(3)`. Every shell result with a four-location axis uses:
| location index | name | `(xi,eta)` |
| ---: | --- | --- |
| 1 | `GP1` | `(-g,-g)` |
| 2 | `GP2` | `(+g,-g)` |
| 3 | `GP3` | `(+g,+g)` |
| 4 | `GP4` | `(-g,+g)` |
Every three-section-position axis uses `BOTTOM(zeta=-1)`, `MIDDLE(zeta=0)`, then
`TOP(zeta=+1)`. Location indices are not Abaqus integration-point numbers and must
not be relabeled as such in a reference comparison.
### 6.4 Step/frame result datasets
All datasets are mandatory after a successful run, independent of Abaqus output
requests.
| quantity | exact dataset path | shape | row identity and component order | units/coordinates/location |
| --- | --- | --- | --- | --- |
| displacement | `/steps/Step-1/frames/0/nodal/displacement` | `[node_count,6]` float64 | `/model/nodes` row; existing HDF5 component names `[UX,UY,UZ,URX,URY,URZ]` | `[length x3,radian x3]`; global; nodal |
| reaction/full residual | `/steps/Step-1/frames/0/nodal/reaction` | `[node_count,6]` float64 | `/model/nodes` row; `[RF1,RF2,RF3,RM1,RM2,RM3]` | `[force x3,force*length x3]`; global; nodal; constrained entry is physical reaction, free entry is residual evidence |
| local frame | `/steps/Step-1/frames/0/element/shell/local_frame` | `[element_count,4,3,3]` float64 | element row, location row, axis row `[e1,e2,e3]`, global component column | dimensionless; location-specific shell local frame |
| generalized strain | `/steps/Step-1/frames/0/element/shell/generalized_strain` | `[element_count,4,8]` float64 | element row, location row; `[E11,E22,G12,K11,K22,K12,G13,G23]` | `[1,1,1,1/length,1/length,1/length,1,1]`; shell local; midsurface location |
| section resultant | `/steps/Step-1/frames/0/element/shell/section_resultant` | `[element_count,4,8]` float64 | element row, location row; `[N11,N22,N12,M11,M22,M12,Q13,Q23]` | `[force/length x3,force x3,force/length x2]`; shell local; midsurface location |
| in-plane stress | `/steps/Step-1/frames/0/element/shell/stress` | `[element_count,4,3,3]` float64 | element row, location row, section-position row, component `[S11,S22,S12]` | `force/length^2`; shell local; direct bottom/middle/top evaluation |
| drilling stiffness | `/steps/Step-1/frames/0/element/shell/drilling_stiffness` | `[element_count,4]` float64 | element row and source-local node position 1..4 | `force*length`; actual positive `k_d,I` used |
| drilling ratio | `/steps/Step-1/frames/0/element/shell/drilling_ratio` | `[element_count,4]` float64 | same row and source-local node position | dimensionless actual `rho_d,I=k_d,I/D_iso` |
| energy | `/steps/Step-1/frames/0/global/energy` | `[2]` float64 | `[PHYSICAL_STRAIN_ENERGY,DRILLING_STABILIZATION_ENERGY]` | `force*length`; deterministic element reduction |
| force/moment balance | `/steps/Step-1/frames/0/global/equilibrium` | `[6]` float64 | `[FORCE_1,FORCE_2,FORCE_3,MOMENT_1,MOMENT_2,MOMENT_3]` | `[force x3,force*length x3]`; global; moment reference point is global origin `[0,0,0]` |
| verification metrics | `/steps/Step-1/frames/0/global/verification_metrics` | `[3]` float64 | `[FREE_RESIDUAL_NORMALIZED,FORCE_BALANCE_NORMALIZED,MOMENT_BALANCE_NORMALIZED]` | dimensionless; metric-definition IDs and thresholds required as attributes |
| diagnostics | `/diagnostics` | `[diagnostic_count]` compound | `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, `message` | deterministic order; required empty dataset when count is zero |
`S33=0` is a plane-stress assumption and is not emitted. `S13`, `S23`, physical
drilling stress/resultant, and nodally extrapolated/averaged shell stress are not
created. Transverse shear is externally represented through `Q13/Q23`.
Each numeric result dataset has required attributes `component_names`,
`component_unit_dimensions`, `coordinate_system`, `location`, `step_name=Step-1`,
and `frame_index=0`. Shell element results additionally identify their source
element type, internal formulation, midsurface-location dataset, section-position
dataset when applicable, and local-frame dataset.
The verification-metric definitions and approved thresholds remain Numerical Review
dependencies. Until their formula IDs are approved, this path is a fixed schema
reservation and not an implementation default.
### 6.5 Reaction, residual, equilibrium, and energy meaning
`nodal/reaction` stores the assembled full residual `K*d-F`; a duplicate nodal
residual dataset is not written. `/model/nodal_constraint_mask` controls meaning:
- constrained entry: physical reaction;
- free entry: equation-equilibrium residual evidence.
Global force/moment balance uses applied `CLOAD` plus constrained reaction about
the global origin. Free residual entries remain separate evidence and are not added
as physical reactions. Energy is split exactly into physical strain energy and
numerical drilling energy. A near-zero physical-energy denominator is never clamped
to form a misleading ratio; the later approved warning policy must classify that
case explicitly.
### 6.6 Atomic finalization
The writer creates a temporary candidate in the final output directory, writes every
mandatory group/dataset/attribute, validates finite values, shape, identity, and
ordering, flushes, closes, reopens read-only, and self-checks the schema. Only then
may it atomically replace/create the requested final path. A failure preserves any
previous valid final output when possible, removes or quarantines the non-authority
candidate, emits an output diagnostic, and returns exit code `6`.
## 7. FESA HDF5 to Reference CSV Comparison Schema
Authoritative comparison reads `results.h5` and read-only Abaqus CSV artifacts.
A deterministic FESA CSV projection is a debugging/review view only; it is neither
solver output nor a reference artifact.
### 7.1 S4/S4R portfolio separation
- S4 and S4R use distinct `model_id`, input, metadata, and CSV bundles.
- FESA maps both source types to `FESA-MITC4`, but Abaqus S4 and S4R values are not
expected to equal each other on a finite mesh.
- Reference comparison always compares one FESA run with Abaqus rows generated from
the same source model/type.
- Equality of FESA internal numerical rows after changing only source type is a
separate implementation test, not an Abaqus S4-versus-S4R comparison.
### 7.2 Approved S4 legacy alias inventory
The current exact alias is model ID `shell-s4-legacy`:
| role | exact path | SHA-256 | observed inventory |
| --- | --- | --- | --- |
| input | `reference/shell/shell.inp` | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` | 164 lines; `TYPE=S4`; one `*STEP,*STATIC`; `NLGEOM=NO`; generator comment `Abaqus/CAE Learning Edition 2024` |
| displacement | `reference/shell/shell displacements.csv` | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` | 49 finite data rows; U and UR columns |
| reaction | `reference/shell/shell reactions.csv` | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` | 49 finite data rows; RF and RM columns; review-only |
| stress | `reference/shell/shell stresses.csv` | `CBAA6E90400FE561535C4793B126F5A47020FF3FA60026C6F100253F276EFBBE` | nodal-associated S columns including S33; review-only and not location-compatible with mandatory FESA stress rows |
The files were introduced by source commit
`57122b0a1bdcb1a8d0eed55599742751edd534be`. They must not be renamed, rewritten,
zero-clamped, normalized, or repaired. A hash mismatch is
`needs-reference-artifacts`, not permission to restore or change the bundle.
The alias is `recognized-legacy-alias-needs-reference-metadata`. Before numerical
comparison, the Reference Model contract must supply or approve externally:
- generation owner/date and exact provenance;
- user unit system and component unit labels;
- canonical model ID, source input identity, step and final-frame identity;
- global coordinate convention;
- material/section/thickness summary;
- CSV schema version and tolerance policy.
CSV lacks explicit step/frame/unit/coordinate columns. They map to
`(Step-1,frame 0)`, global Cartesian, and documented units if and only if approved
metadata confirms that exact interpretation. Absence or conflict is a
schema/provenance failure; I/O Definition does not infer values.
### 7.3 Separate canonical S4R bundle
At least one S4R reference bundle is still required:
```text
reference/<s4r-model-id>/
model.inp
metadata.json
<s4r-model-id>_displacements.csv
```
`model.inp` must contain the approved subset and `TYPE=S4R`. Metadata records
generator/version/provenance, unit system, coordinate system, model/step/frame,
material/section/thickness, source element type, schema version, and tolerance
policy. Optional reaction/stress artifacts remain nonblocking evidence.
`<s4r-model-id>` is a Reference Model-owned schema variable, not an unresolved
filename placeholder in this I/O contract.
The canonical wide displacement CSV columns are:
```text
step_name,frame_index,instance_name,source_node_label,
coordinate_system,translation_unit,rotation_unit,
U1,U2,U3,UR1,UR2,UR3
```
Rows are unique by `(step_name,frame_index,instance_name,source_node_label)`, all
numeric values are finite, and the component coordinate system is global Cartesian.
### 7.4 Legacy header normalization
After trimming header whitespace, the exact S4 displacement header mapping is:
| legacy column | canonical field/component | FESA HDF5 source |
| --- | --- | --- |
| `Part Instance Name` | `instance_name` | `/model/nodes.instance_name` |
| `Node Label` | `source_node_label` | `/model/nodes.source_label` |
| `U-U1` | displacement `U1` | `nodal/displacement` column 0, HDF5 component `UX` |
| `U-U2` | displacement `U2` | `nodal/displacement` column 1, HDF5 component `UY` |
| `U-U3` | displacement `U3` | `nodal/displacement` column 2, HDF5 component `UZ` |
| `UR-UR1` | displacement `UR1` | `nodal/displacement` column 3, HDF5 component `URX` |
| `UR-UR2` | displacement `UR2` | `nodal/displacement` column 4, HDF5 component `URY` |
| `UR-UR3` | displacement `UR3` | `nodal/displacement` column 5, HDF5 component `URZ` |
Reaction columns are inventoried as `[RF1,RF2,RF3,RM1,RM2,RM3]` when the optional
file passes its schema precheck, but they do not
enter MITC4 Abaqus pass/fail. The legacy stress CSV is not projected onto FESA
integration/section-position rows because it contains a different nodal-associated
location identity and an `S33` column that FESA does not emit. Missing comparison
meaning is recorded as N/A, never repaired by averaging or synthesized rows.
### 7.5 Canonical normalized row
Wide CSV and HDF5 rows normalize in memory to:
```text
model_id, step_name, frame_index, instance_name, source_node_label,
quantity, component, value, unit_dimension, coordinate_system,
hdf5_dataset_path
```
The unique key is all fields except `value`, `unit_dimension`,
`coordinate_system`, and `hdf5_dataset_path`; those remaining fields must agree for
the matched key. Stable ordering is model, step, frame, instance declaration order,
stable source node order, then component order
`[U1,U2,U3,UR1,UR2,UR3]`.
### 7.6 Row-set precheck and comparison policy
Before tolerance evaluation:
1. Verify exact artifact inventory/hash or canonical bundle metadata.
2. Verify input source type matches model contract.
3. Verify one approved static step and final frame identity.
4. Verify expected trimmed headers, finite values, unique row keys, units, coordinate
system, and exact source node/instance identities.
5. Project HDF5 and reference to the same six-component displacement inventory.
6. Fail on any missing, extra, duplicate, nonfinite, schema-mismatched, or
identity-mismatched projected row.
Only `U1/U2/U3` affect pass/fail. `UR1/UR2/UR3` are always compared and reported but
can emit only an approved deterministic nonblocking warning.
For each model, step/frame, quantity, and component group:
```text
reference_scale_c = max(abs(reference_value_i))
row_tolerance_c = absolute_floor_c
+ relative_coefficient_c * reference_scale_c
row_pass = abs(fesa_value-reference_value) <= row_tolerance_c
```
Reference scale uses finite Abaqus values only. A zero scale makes the relative term
zero. No reference or result value is zero-clamped, no row-specific relative
denominator replaces the component scale, and B33 floors/coefficient are not
inherited.
The exact `absolute_floor_c`, `relative_coefficient_c`, and UR warning threshold are
`needs-reference-model-and-numerical-review`. Comparison implementation cannot begin
until those values and their unit context are approved.
The report records every U/UR row, blocking/nonblocking decision, absolute error,
component-scale normalized error, RMS error, displacement/rotation vector-norm
error, worst source row/component, and every UR warning.
## 8. CLI and Diagnostics Contract
```powershell
fesa.exe <model.inp> --output <results.h5>
```
Omitting `--output` uses `results.h5` in the current directory. Unknown option,
missing input, missing output argument, or repeated `--output` is usage failure.
| exit code | meaning |
| ---: | --- |
| `0` | successful analysis and authoritative HDF5 finalization |
| `2` | CLI usage error |
| `3` | input syntax or semantic mapping error, including unsupported keyword, formulation, wrapper, step, or distributed load |
| `4` | model validation error, including section/material property, geometry, director, Jacobian, or drilling-direction aggregate moment |
| `5` | factorization or substitution error |
| `6` | HDF5 write, schema validation, or atomic finalization error |
Each stderr and HDF5 diagnostic has exact field order `severity`, `code`, `file`,
`line`, `keyword`, `entity_identity`, `message`. Source-backed records carry
normalized file and 1-based line; source-less solver/output records use explicit
empty source fields. Order is source declaration order, file line, stable entity ID,
diagnostic code, then discovery order for an otherwise equal key.
The approved shell-specific diagnostic inventory includes:
| code | class/exit | meaning |
| --- | --- | --- |
| `unsupported-element-formulation` | input/3 | element type is not S4/S4R in this feature |
| `unsupported-mixed-element-model` | input/3 | shell and non-shell element/joint semantics are mixed |
| `invalid-shell-connectivity` | input/3 | connectivity arity is not four, a node repeats, or a connected source node is unresolved |
| `unresolved-shell-section` | input/3 | section/material/ELSET reference is unresolved |
| `invalid-shell-section-assignment` | input/3 | an element resolves to zero or multiple shell sections |
| `unsupported-shell-section-option` | input/3 | composite, offset, orientation, variable thickness, or other excluded meaning appears |
| `invalid-shell-thickness` | model/4 | thickness is nonfinite or nonpositive |
| `invalid-shell-material` | model/4 | isotropic material violates finite `E,nu` bounds |
| `invalid-shell-geometry` | model/4 | duplicate, self-intersecting, collapsed, reversed, or threshold-invalid surface geometry |
| `opposed-incident-normal` | model/4 | an incident normal pair has nonpositive dot product before averaging |
| `sharp-shell-fold` | model/4 | incident deviation exceeds approved `theta_smooth` |
| `invalid-shell-director` | model/4 | candidate, average, interpolation, or tangent-frame construction is invalid |
| `invalid-shell-jacobian` | model/4 | required point violates `J/j_s/a_g/c_d/r_J/theta_w` contract |
| `unsupported-drilling-load` | model/4 | nonzero aggregate moment violates `rho_M<=1e-12` |
| `unsupported-distributed-load` | input/3 | DLOAD, pressure, gravity, body/edge/follower load is requested |
The accepted optional `*SHELL SECTION` integration-point field emits no diagnostic.
Allowlisted `*PREPRINT`, `*RESTART`, and output-request no-ops retain their existing
warning behavior.
## 9. Validation Rules
| validation area | required pass condition | failure class |
| --- | --- | --- |
| keyword inventory | supported or exact allowlisted no-op | input, exit 3 |
| nesting/cardinality | closed part/assembly/instance/step; one assembly and one static step | input, exit 3 |
| source identity | duplicates absent; all references resolved; multi-instance identity unique | input, exit 3 |
| element syntax/semantics | only four-node S4/S4R, distinct resolved connectivity, internal FESA-MITC4, no mixed element model | input, exit 3 |
| resolved element geometry | source order satisfies orientation and every approved geometry measure | model, exit 4 |
| material/section syntax | exact row grammar, resolvable references, exactly one centered homogeneous assignment per element | input, exit 3 |
| material/section values | finite approved `E,nu,t` bounds | model, exit 4 |
| director/geometry | deterministic pairwise/average/frame construction and every approved measure threshold passes | model, exit 4 |
| boundary/load syntax | global DOF 1..6, resolved finite values, no conflicting prescribed values | input, exit 3 |
| aggregate nodal moment | exact-zero case or nonzero `rho_M<=1e-12` | model, exit 4 |
| history | sole static Step-1/frame 0, NLGEOM disabled | input, exit 3 |
| HDF5 model | exact paths, dtypes, shapes, IDs, source types, directors, sections, and finite values | output, exit 6 |
| HDF5 results | every mandatory row/location/component exists in stable order and is finite | output, exit 6 |
| S4 legacy alias | exact paths/hashes/headers plus approved external metadata | reference precheck |
| S4R canonical bundle | canonical files, metadata, S4R input, unique finite U/UR rows | reference precheck |
| comparison | exact normalized row-set; U blocking; UR warning-only; approved tolerance | reference verification |
No successful parser/HDF5 implementation, numerical solution, reference comparison,
physics review, or release status follows from approval of this document alone.
## 10. Requirement Traceability
| requirement group | I/O contract coverage | remaining owner |
| --- | --- | --- |
| `001-004`, `021-023`, `030`, `037` | exact step, S4/S4R mapping, source/internal identity, wrapper and no-op policies | Implementation Planning tests |
| `005-010` | six global DOFs, isotropic ELASTIC, single-row SHELL SECTION, exact assignment | Implementation Planning tests |
| `011-016` | auto-director semantic mapping, geometry inventory, fail-closed diagnostics | Numerical Review for thresholds |
| `017-020` | BOUNDARY/CLOAD grammar, deterministic aggregation, `rho_M<=1e-12`, distributed-load rejection | Implementation Planning tests |
| `024-029` | Domain/AnalysisModel/DofManager/AnalysisState semantic ownership and residual meaning | Implementation Planning |
| `031-038` | source-independent MITC4 identity, drilling output evidence, full-integration policy | Numerical Review for coefficient/energy rule |
| `039-048` | additive HDF5 v0 paths, mandatory quantities, location identity, atomic output | Reference Model and Implementation Planning |
| `049-057` | diagnostic/schema hooks and mandatory verification-metric/energy evidence | Numerical Review and planning |
| `058-064` | normalized U/UR rows, row-set precheck, blocking/warning behavior, report inventory | Reference Model and Numerical Review for values |
| `065-072` | exact S4 legacy alias, separate S4R canonical bundle, immutability, displacement-only gate | Reference Model |
## 11. Open Issues and Downstream Handoff
### 11.1 Upstream metadata corrections
The requirements metadata says the previously unobserved `reference/shell/` candidate
was declared as S4R. The observed immutable input is `TYPE=S4`, and the user has now
approved separate S4 and S4R artifacts. A later Requirement/Numerical Review metadata
refresh should correct that observation without changing the core requirement that
both source types map to one FESA formulation.
The current Numerical Review also records `reference/shell/` as unobserved because it
predates the dev-branch merge. Its next rerun should consume this exact alias
inventory and the Reference Model contract.
### 11.2 Numerical Review dependencies
The following values remain explicitly unapproved and have no I/O default:
1. drilling reference family, nodewise `rho_d` range, stable plateau, and nominal;
2. scaled rank/conditioning and U/N/M/Q contamination bounds;
3. drilling-to-physical energy warning classification and threshold;
4. `theta_smooth`;
5. `tau_ang`, `tau_area`, `tau_dir`, `tau_var`, and `theta_warp`;
6. verification-metric formula IDs and acceptance thresholds where not already fixed;
7. component-specific U absolute floors/relative coefficients and UR warning threshold.
Until these are approved, this document is ready for Reference Model design but not
Implementation Planning.
### 11.3 Reference Model Agent
- Write `docs/reference-models/linear-static-mitc4-shell-reference-models.md` using
this exact keyword/HDF5/reference-row contract.
- Register `shell-s4-legacy` without modifying its four files and supply verified
provenance, units, coordinate system, and final-frame identity.
- Provide a separate canonical S4R bundle and additional flat/thin/thick/distorted/
curved models needed for tolerance and director/geometry calibration.
- Propose U mixed-tolerance values and the UR nonblocking warning threshold for
Numerical Review approval.
- Treat reaction/stress artifacts as nonblocking review evidence and do not create
location-equivalence claims absent from this contract.
### 11.4 Numerical Review Agent
- Review Reference Model evidence and close every dependency in Section 11.2.
- Confirm that actual HDF5 drilling and geometry policy attributes reproduce the
approved calibration decision.
- Rerun the numerical gate before authorizing Implementation Planning.
### 11.5 Implementation Planning Agent
- Do not start while `implementation_planning_authorized=false`.
- After approval, convert every supported/unsupported keyword row, source identity,
geometry/director error, drilling-load projection, exact HDF5 path/shape/order,
atomic failure, legacy/canonical row normalization, and U-versus-UR decision into
`RED -> GREEN -> VERIFY` tests.
- Keep distributed loads, mixed beam-shell models, Abaqus reduced integration,
nonlinear state/tangent, and reference artifact mutation outside the plan.
### 11.6 Reference Verification Agent
- Enforce artifact/schema precheck before numeric tolerance.
- Match HDF5 and Abaqus rows only by the canonical identity in Section 7.5.
- Never ignore missing/extra/nonfinite rows, synthesize S33/S13/S23, average location
mismatches, or let UR warnings change U pass/fail.