Files
FESADev/docs/io-definitions/linear-static-3d-euler-beam-io.md
T
2026-08-12 02:22:01 +09:00

474 lines
32 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Linear Static 3D Euler Beam I/O Definition
## Metadata
- feature_id: `linear-static-3d-euler-beam`
- source_requirement: `docs/requirements/linear-static-3d-euler-beam.md`
- source_formulation: `docs/formulations/3d-isoparametric-euler-beam-formulation.md`
- source_numerical_review: `docs/numerical-reviews/linear-static-3d-euler-beam-review.md`
- source_research: `docs/research/linear-static-3d-euler-beam-research.md`
- approved_design: `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`
- status: `ready-for-implementation-planning`
- owner_agent: `io-definition-agent`
- date: `2026-08-09`
- authoritative_output: `results.h5`
- reference_baseline: `reference/cantilever beam/` at source commit `2b34d0b`
이 문서는 승인된 V0의 semantic I/O contract만 정의한다. Parser, HDF5 writer,
comparison tooling의 C++ API나 구현 구조는 정의하지 않으며 Abaqus full compatibility를
주장하지 않는다.
## Abaqus Input Scope
- input_format: Abaqus input file (`.inp`)
- supported_analysis: 입력 파일당 하나의 linear-static step과 `TYPE=B33` 2절점 3D
EulerBernoulli beam
- ordinary_unit_system: user-consistent; `.inp`만 보고 SI를 추론하지 않음
- compatibility_disclaimer: 아래 표의 위치, parameter, data grammar만 지원함
`supported`는 해당 행의 정확한 subset만 의미한다. `warning no-op`은 syntax를 소비하고
구조화된 warning을 기록하지만 Domain, AnalysisModel 또는 mandatory HDF5 output을
변경하지 않는다는 뜻이다.
| keyword | status and allowed location | required parameters and data grammar | purpose and semantic mapping | unsupported behavior |
| --- | --- | --- | --- | --- |
| `*HEADING` | supported; optional top-level first keyword | parameters 없음; 다음 keyword 전까지 0개 이상의 text data line | 원문 heading을 source metadata로 보존 | 중첩 위치 또는 parameter는 input error |
| `*PART` / `*END PART` | supported; top-level model block | `NAME=<part-name>` 필수; `*END PART` data 없음 | part-local node, element, set, section 정의 범위 | 닫히지 않음, 중첩 part, duplicate part name은 error |
| `*NODE` | supported; part 내부 | parameter 없음; 각 row `node_label, x, y, z` | positive integer source label과 finite global Cartesian 좌표 | 다른 arity, duplicate label, nonfinite 좌표는 error |
| `*ELEMENT` | supported; part 내부 | `TYPE=B33` 필수; 각 row `element_label, node_1, node_2` | 2절점 straight Euler beam definition | `TYPE=B31``unsupported-element-formulation`; 다른 type/arity와 dangling connectivity는 error |
| `*NSET` | supported; part 또는 assembly 내부 | `NSET=<name>` 필수; optional `GENERATE`; assembly에서는 `INSTANCE=<instance-name>` 필수; explicit row는 하나 이상의 node label, generate row는 `first,last,increment` | part-local 또는 single-instance assembly node set | mixed-instance set, zero/negative increment, duplicate name, dangling member는 error |
| `*ELSET` | supported; part 또는 assembly 내부 | `ELSET=<name>` 필수; optional `GENERATE`; assembly에서는 `INSTANCE=<instance-name>` 필수; explicit/generate grammar는 `*NSET`과 동일 | part-local 또는 single-instance assembly element set | mixed-instance set, invalid range, duplicate name, dangling member는 error |
| `*MATERIAL` | supported; top-level model data | `NAME=<material-name>` 필수; data 없음 | 뒤따르는 단일 isotropic `*ELASTIC`을 소유 | duplicate name, missing/duplicate elasticity, 다른 material model은 error |
| `*ELASTIC` | supported; 현재 material 내부 | parameter 없음; 정확히 한 row `E, nu` | homogeneous isotropic elasticity; `G=E/(2(1+nu))` | extra field/row, nonfinite value 또는 `E<=0`/`G<=0`은 model error |
| `*BEAM GENERAL SECTION` | supported; part 내부 | `ELSET=<name>`, `MATERIAL=<name>`, `SECTION=GENERAL` 필수; 첫 row `A,I11,I12,I22,J`, 둘째 row `n1x,n1y,n1z` | section assignment, properties와 first section axis | 다른 `SECTION`, missing/dangling reference, `I12!=0`, invalid property/guide vector는 error |
| `*SECTION POINTS` | supported; 바로 앞 general beam section에 종속 | parameter 없음; 하나 이상의 row `x1,x2` | 입력 순서의 stress recovery point; `x1=y`, `x2=z` | 선행 section 없음, 다른 arity, nonfinite 또는 duplicate point는 error |
| `*ASSEMBLY` / `*END ASSEMBLY` | supported; 정확히 하나의 top-level assembly block | `NAME=<assembly-name>` 필수; `*END ASSEMBLY` data 없음 | identity instance와 assembly set 범위 | nested/duplicate assembly는 `unsupported-nested-assembly` |
| `*INSTANCE` / `*END INSTANCE` | supported; assembly 내부 | `NAME=<instance-name>`, `PART=<part-name>` 필수; 두 keyword 사이 data 없음 | named identity copy; 같은 part의 여러 identity instance 허용 | translation/rotation data는 `unsupported-instance-transform`; duplicate/dangling instance는 error |
| `*BOUNDARY` | supported; top-level model data 또는 sole step 내부 | parameter 없음; 각 row `target, first_dof, last_dof[, value]`; omitted value는 `0` | sole step의 prescribed displacement | invalid arity/range, unresolved target, conflicting expanded node/DOF value는 error |
| `*CLOAD` | supported; sole step 내부 | parameter 없음; 각 row `target, dof, magnitude` | sole step의 global nodal concentrated load | invalid arity/DOF, nonfinite magnitude 또는 unresolved target은 error |
| `*STEP` / `*END STEP` | supported; exactly one top-level history block | optional `NAME`; optional `NLGEOM=NO`; `*END STEP` data 없음 | canonical result identity `(Step-1, frame 0)` | second step은 `unsupported-multiple-step`; `NLGEOM=YES``unsupported-nonlinear-geometry` |
| `*STATIC` | supported; sole step 내부, exactly once | parameter 없음; exactly one row `initial_increment, time_period, minimum_increment, maximum_increment` | 승인 legacy row를 읽되 V0는 하나의 linear solve와 frame 0만 생성 | missing/extra/nonfinite/nonpositive field 또는 다른 procedure는 error |
| `*PREPRINT` | warning no-op; top-level | 모든 parameter를 보존 후 무시; data 없음 | legacy generator control 수용 | semantic object를 만들지 않음 |
| `*RESTART` | warning no-op; sole step | 모든 parameter를 보존 후 무시; data 없음 | legacy restart request 수용 | restart state를 만들지 않음 |
| `*TRANSVERSE SHEAR STIFFNESS` | warning no-op; beam section context | keyword와 소속 data line을 보존 후 무시 | B33 legacy deck 수용 | Euler formulation/property를 변경하지 않음 |
| `*OUTPUT, FIELD` | warning no-op; sole step | output parameter와 subordinate data를 보존 후 무시 | legacy field request root 수용 | mandatory FESA output을 선택·억제하지 않음 |
| `*OUTPUT, HISTORY` | warning no-op; sole step | output parameter와 subordinate data를 보존 후 무시 | legacy history request root 수용 | history result를 생성하지 않음 |
| `*NODE OUTPUT` | warning no-op; active output request 내부 | 모든 parameter와 다음 keyword 전 variable data를 무시 | legacy nodal variable request 수용 | requested variables로 HDF5 schema를 변경하지 않음 |
| `*ELEMENT OUTPUT` | warning no-op; active output request 내부 | 모든 parameter와 다음 keyword 전 variable data를 무시 | legacy element variable request 수용 | requested variables로 HDF5 schema를 변경하지 않음 |
| `*CONTACT OUTPUT` | warning no-op; active output request 내부 | 모든 parameter와 다음 keyword 전 variable data를 무시 | legacy contact variable request 수용 | contact model/result를 만들지 않음 |
`*DLOAD`, `*INCLUDE` 및 표에 없는 model-affecting keyword는 no-op 대상이 아니며
`unsupported-keyword` input error다. 특히 formulation-only constant local line-load
kernel은 parser나 Domain의 distributed-load 지원을 뜻하지 않는다.
### Nesting grammar
```text
input-file
:= heading? part+ assembly material+ model-boundary* step EOF
part
:= *PART
node-block+ element-block+ (nset | elset)*
general-section+ section-points*
*END PART
assembly
:= *ASSEMBLY
instance+ assembly-set*
*END ASSEMBLY
instance
:= *INSTANCE *END INSTANCE
step
:= *STEP *STATIC step-boundary* cload* allowed-no-op* *END STEP
```
Top-level material과 model boundary는 step 전에만 나타난다. Part는 assembly 전에 모두
닫혀야 하고 assembly 안에는 instance와 assembly-level set만 허용한다. Instance 안의
node/element 재정의, nested assembly, dependent/independent mesh option은 지원하지 않는다.
Sole step의 source `NAME` spelling은 metadata에 보존하지만 V0 HDF5와 comparison의
canonical identity는 항상 `Step-1`, `frame 0`이다.
## Syntax Policy
- keyword line은 첫 non-whitespace character가 `*`이고 `**`가 아니어야 한다.
- comment line은 `**`로 시작하며 의미 모델에서는 제외하되 file과 1-based line 위치를
유지한다.
- keyword, parameter name, enumerated parameter value와 named-reference lookup은 ASCII
case-insensitive다. Part, instance, material, set의 원래 spelling과 numeric label lexeme는
외부 identity를 위해 그대로 보존한다.
- keyword line은 comma-separated `KEY[=VALUE]` fields다. Data line도 comma-separated이며
field 양끝 whitespace를 제거한다. Required empty field, trailing empty optional value,
잘못된 numeric token은 input error다.
- Keyword/data continuation, quoted/multiline name, include file 및 line continuation은 V0에서
지원하지 않는다. 한 logical keyword/data row는 한 physical line에 완결되어야 한다.
- Node/element labels와 explicit set members는 positive base-10 integer다. Internal index로
바꾸어도 raw source label text를 잃지 않는다.
- 모든 numeric value는 finite `double`이어야 한다. `NaN`, positive/negative infinity는
syntax/semantic validation에서 거부한다.
- 각 parsed keyword, parameter, data row와 semantic entity는 `file`, 1-based `line`, raw
`keyword`, raw source label을 추적할 수 있어야 한다.
- Output-request subordinate variable data는 직전의 allowlisted output keyword부터 다음
keyword까지에만 warning no-op이다. 그 밖의 예상되지 않은 data line은 input error다.
### Duplicate and dangling-reference policy
- Part, assembly, instance, material, set 이름은 각 semantic scope의 case-insensitive key로
unique해야 한다. Node/element numeric source label은 part scope에서 unique해야 한다.
- 같은 part의 여러 identity instance는 duplicate가 아니다. 각 copy는 instance name으로
구분되는 별도 source identity를 가진다.
- Element connectivity, set membership, instance `PART`, section `ELSET`/`MATERIAL`, assembly
set `INSTANCE`, boundary/load target은 Domain finalization 전에 모두 resolve되어야 한다.
- Duplicate definition은 `duplicate-entity`; unresolved reference는 `unresolved-reference`
진단하고 partial Domain을 해석에 넘기지 않는다.
## Model Data Mapping
### Stable source identity and instances
Part-local node, element, set은 instance expansion 뒤 다음 identity를 갖는다.
```text
SourceEntityId { instance_name, source_label }
```
`instance_name``source_label`은 원래 spelling을 보존한다. Case-insensitive lookup key와
표시용 raw text는 별개다. Stable Domain internal index는 input declaration order,
instance declaration order, part-local entity declaration order의 결정적 순서로 부여하며
thread count나 hash iteration order에 의존하지 않는다. 같은 part의 두 identity instance는
source label이 같아도 instance name이 다르므로 서로 merge하지 않는다.
Assembly-level `*NSET`/`*ELSET``INSTANCE`는 정확히 하나의 identity instance를
지정하고 data의 label을 그 instance가 참조하는 part-local source label로 resolve한다.
따라서 assembly set member도 `(instance_name, source_label)`로 결정된다. V0는 한 set에
여러 instance의 member를 섞는 grammar를 제공하지 않는다.
### Nodes, elements, sets, material, and section
- Node는 global Cartesian coordinate `[X,Y,Z]`, stable internal node ID와 source identity를
가진다.
- B33 element는 ordered connectivity `[node_1,node_2]`, stable internal element ID,
source identity, general-section assignment를 가진다. Connectivity order가 local tangent
`t=(X2-X1)/L`의 방향을 정한다.
- Explicit set은 data order, generated set은 inclusive `first,last,increment` expansion
order를 보존한다. Membership은 internal ID에 연결되지만 source identity로 round-trip
가능해야 한다.
- Material은 정확한 입력 `E,nu`를 보존하고 `G=E/(2(1+nu))`를 유도한다.
- General section 첫 row는 정확히 `[A,I11,I12,I22,J]`다. V0는 `I12`의 exact numeric
zero만 허용하고 `Iy=I11`, `Iz=I22`로 매핑한다.
- Guide vector `a=n1`을 tangent에 직교 투영·정규화하여 local `y`로, `t x n1`을 local
`z`로 둔다. `(x,y,z)`는 right-handed다.
### Model validation
모든 값은 finite여야 하고 다음 조건을 element calculation 전에 검사한다.
```text
E > 0
G = E / (2 * (1 + nu)) > 0
A > 0, Iy > 0, Iz > 0, J > 0
L > 1e-12 * max(1, norm(X1), norm(X2))
norm(a_perp) > 1e-12 * max(1, norm(a))
```
`a_perp = a - dot(a,t)*t`다. 길이 조건 실패는 `invalid-beam-length`, zero guide vector나
projection 조건 실패는 `invalid-beam-guide-vector`, nonpositive property는
`invalid-beam-property`, `I12!=0``unsupported-coupled-section` model diagnostic이다.
Fallback axis, absolute-value 보정 또는 B31 재해석은 허용하지 않는다.
## History Data Mapping
V0는 하나의 history object, canonical `Step-1`만 만든다. `*STATIC`의 네 legacy field는
각각 `initial_increment`, `time_period`, `minimum_increment`, `maximum_increment`
보존한다. 모두 finite positive여야 하고 `minimum_increment <= maximum_increment`여야
한다. 이 값들은 입력 호환성과 provenance를 위한 값이며 V0가 increment loop나 여러
frame을 생성하게 하지 않는다. 결과는 항상 `(Step-1, frame 0)`이다.
`*BOUNDARY`의 target은 node source label 또는 node set이다. Assembly set은 그
`INSTANCE`를 포함해 source node identity로 확장한다. `first_dof <= last_dof`이고 두 값은
1..6이어야 한다. 생략된 value는 exact zero다. Model-level boundary와 step-level boundary는
sole step에 활성화되며 같은 expanded node/DOF에 서로 다른 value가 생기면 input error다.
`*CLOAD` target resolution은 boundary와 같고 각 row는 해당 target의 모든 node에 global
component load를 적용한다. 같은 node/DOF로 resolve되는 여러 load row는 input order로
결정적으로 합산한다.
| DOF | nodal kinematic component | boundary unit dimension | CLOAD component | load unit dimension |
| ---: | --- | --- | --- | --- |
| 1 | `UX` | length | `FX` | force |
| 2 | `UY` | length | `FY` | force |
| 3 | `UZ` | length | `FZ` | force |
| 4 | `URX` | radian | `MX` | force x length |
| 5 | `URY` | radian | `MY` | force x length |
| 6 | `URZ` | radian | `MZ` | force x length |
Abaqus output request는 history activation이나 output selection으로 매핑하지 않는다.
Allowlisted request의 존재 여부와 무관하게 mandatory HDF5 dataset은 모두 생성된다.
## Internal Model Contract
- Domain은 nodes, B33 elements, sets, material, section, boundary, load와 sole static step의
완전한 semantic definition을 소유하고 mapping 이후 effectively immutable하다.
- AnalysisModel은 sole step에 활성인 Domain IDs/references만 제공하며 Domain object를
복사하지 않는다.
- Node/element는 equation ID를 소유하지 않는다. DOF numbering과 constrained/free mapping은
이 I/O 계약 밖의 DofManager 책임이다.
- Boundary와 load는 expansion 전 target identity와 expansion 후 stable node identity를 모두
추적할 수 있어야 한다.
- Result identity는 source identity와 stable internal identity를 모두 보유해야 하며
parser의 raw keyword string을 solver physics object로 사용하지 않는다.
- Endpoint equilibrium action, endpoint section resultant, Gauss generalized result,
assembled residual reaction은 서로 다른 quantity/location identity다.
## Output HDF5 Schema
Authoritative output은 하나의 HDF5 file `results.h5`, schema version `0`이다. 아래의
`<step-name>`은 V0에서 literal `Step-1`이다. 모든 string은 UTF-8, 모든 물리 실수는
IEEE-754 float64, stable internal ID는 uint64다.
### Metadata and model identity
`/metadata`는 group이며 다음 scalar attributes를 반드시 가진다.
| attribute | required value or meaning |
| --- | --- |
| `schema_version` | `0` |
| `feature_id` | `linear-static-3d-euler-beam` |
| `solver_version` | 실행 solver version string |
| `source_input_identity` | normalized input path와 content identity를 추적 가능한 string |
| `unit_system_label` | ordinary run은 `user-consistent-unspecified` |
| `coordinate_convention` | `global-cartesian; beam-local=(t,n1,t-cross-n1)` |
| `element_formulation` | `B33-3D-Euler-Bernoulli` |
| `step_name` | `Step-1` |
| `frame_index` | integer `0` |
승인 legacy comparison은 `.inp`에서 SI를 추론하지 않는다. Reference Model Contract와
verification report가 model `cantilever-beam-b33`에 외부 `SI` provenance를 적용한다.
| dataset path | shape and dtype | row identity / fields | required attributes and ordering |
| --- | --- | --- | --- |
| `/model/nodes` | `[node_count]` compound | `internal_node_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `coordinates:float64[3]` | internal node ID ascending; `coordinate_system=global-cartesian`, `units_label=length` |
| `/model/elements` | `[element_count]` compound | `internal_element_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `node_internal_ids:uint64[2]`, `local_axes:float64[3,3]` | internal element ID ascending; axes row order `[x,y,z]`, `formulation=B33-3D-Euler-Bernoulli` |
### Step/frame result datasets
| quantity | exact dataset path | shape | row identity and component order | units/coordinates/location |
| --- | --- | --- | --- | --- |
| displacement | `/steps/<step-name>/frames/0/nodal/displacement` | `[node_count,6]` float64 | `/model/nodes` row; `[UX,UY,UZ,URX,URY,URZ]` | `[length,length,length,radian,radian,radian]`; global; nodal |
| reaction | `/steps/<step-name>/frames/0/nodal/reaction` | `[node_count,6]` float64 | `/model/nodes` row; `[RF1,RF2,RF3,RM1,RM2,RM3]` | `[force,force,force,force*length,force*length,force*length]`; global; nodal |
| equilibrium end action | `/steps/<step-name>/frames/0/element/end_force_local` | `[element_count,2,6]` float64 | element row, endpoint `[-1,+1]`; `[FX,FY,FZ,MX,MY,MZ]` | `[force x3, force*length x3]`; beam local; endpoint outward action |
| endpoint section resultant | `/steps/<step-name>/frames/0/element/section_resultant` | `[element_count,2,4]` float64 | element row, endpoint `[-1,+1]`; `[N,T,My,Mz]` | `[force,force*length,force*length,force*length]`; beam local; positive-local-x section cut |
| generalized strain | `/steps/<step-name>/frames/0/element/generalized_strain` | `[element_count,2,4]` float64 | element row, Gauss point `[-1/sqrt(3),+1/sqrt(3)]`; `[epsilon0,kappa_x,kappa_y,kappa_z]` | `[1,1/length,1/length,1/length]`; beam local; integration point |
| generalized resultant | `/steps/<step-name>/frames/0/element/generalized_resultant` | `[element_count,2,4]` float64 | element row, same Gauss points; `[N,T,My,Mz]` | `[force,force*length,force*length,force*length]`; beam local; integration point |
| axial stress | `/steps/<step-name>/frames/0/element/stress_s11` | `[stress_row_count]` compound | `internal_element_id`, `gauss_point_index`, `section_point_index`, `x1`, `x2`, `source`, `S11` | element/Gauss/section order; `units_label=force/length^2`, beam local section point |
| diagnostics | `/diagnostics` | `[diagnostic_count]` compound | `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, `message` | deterministic diagnostic order; empty dataset is required when count is zero |
각 numeric result dataset은 `component_names`, `component_unit_dimensions`,
`coordinate_system`, `location`, `step_name=Step-1`, `frame_index=0` attributes를 가진다.
Endpoint axis order는 `xi=-1` then `xi=+1`, Gauss axis order는 negative then positive다.
Stress row는 internal element ID, Gauss index 1..2, input section-point index 순으로 정렬한다.
입력 section point가 없으면 `(x1,x2)=(0,0)`, index `0`, `source=fesa-default`인 centroid
row 하나를 각 Gauss point에 쓴다. 입력 point는 index 1부터 원래 data order를 따른다.
Reaction은 모든 node와 여섯 component에 존재하며 free DOF의 residual도 포함한다.
Transverse/torsional shear stress dataset이나 averaged nodal stress는 만들지 않는다.
`S11`은 mandatory HDF5 output이지만 Abaqus reference comparison은 명시적 N/A다.
### Atomic finalization
Writer는 requested final path와 같은 directory에 temporary HDF5를 만들고 모든 mandatory
group/dataset/attribute 작성, flush, close, schema self-check가 성공한 뒤에만 final path를
원자적으로 교체한다. 실패하면 temporary artifact는 비권위적이며 기존 final file이
있다면 그대로 보존한다. 실패한 새 run은 불완전한 `results.h5`를 남기지 않고 exit code
`6`과 HDF5 diagnostic을 반환한다.
## FESA HDF5 to Reference CSV Comparison Schema
Authoritative 비교는 위 HDF5 rows와 read-only Abaqus CSV rows 사이에서만 수행한다.
HDF5에서 추출한 deterministic CSV view는 debugging/review 보조물이며 solver output이나
reference artifact가 아니다.
### Approved legacy artifact precheck
Comparison 전에 다음 exact files가 존재하고 변경되지 않았음을 확인한다.
- `reference/cantilever beam/cantilever beam.inp`
- `reference/cantilever beam/cantilever beam displacements.csv`
- `reference/cantilever beam/cantilever beam reactions.csv`
- `reference/cantilever beam/cantilever beam elemental forces.csv`
Input은 `TYPE=B33`이어야 하고 trim한 CSV header는 아래 mapping 표와 정확히 일치해야
한다. 각 projected row key는 unique하고 모든 numeric value는 finite여야 한다. 파일
missing/type mismatch는 `needs-reference-artifacts`, header/value/identity mismatch는
`schema-mismatch`이며 comparison은 시작하지 않는다. `metadata.json` 부재는 프로젝트
전역 정책에 따라 허용되고, `README.md`는 이 legacy bundle에서 N/A다. 파일을 rename,
rewrite, zero-clamp 또는 보정하지 않는다.
### Header and component normalization
| legacy file/header | canonical quantity/component | FESA HDF5 source |
| --- | --- | --- |
| `U-U1`, `U-U2`, `U-U3` | displacement `UX`, `UY`, `UZ` | `nodal/displacement` columns 0..2 |
| `UR-UR1`, `UR-UR2`, `UR-UR3` | displacement `URX`, `URY`, `URZ` | `nodal/displacement` columns 3..5 |
| `RF-RF1`, `RF-RF2`, `RF-RF3` | reaction `RF1`, `RF2`, `RF3` | `nodal/reaction` columns 0..2 |
| `RM-RM1`, `RM-RM2`, `RM-RM3` | reaction `RM1`, `RM2`, `RM3` | `nodal/reaction` columns 3..5 |
| `SF-SF1` | section resultant `N` | `element/section_resultant` component `N` |
| `SM-SM1` | section resultant `My` | `element/section_resultant` component `My` |
| `SM-SM2` | section resultant `Mz` | `element/section_resultant` component `Mz` |
| `SM-SM3` | section resultant `T` | `element/section_resultant` component `T` |
General Abaqus beam component meaning and FESA local mapping은 다음과 같다.
| Abaqus component | equilibrium end-action component | section-resultant component |
| --- | --- | --- |
| `SF1` | `FX` | `N` |
| `SF3` | `FY` | N/A in `[N,T,My,Mz]` |
| `SF2` | `FZ` | N/A in `[N,T,My,Mz]` |
| `SM3` | `MX` | `T` |
| `SM1` | `MY` | `My` |
| `SM2` | `MZ` | `Mz` |
이 general mapping은 component axis의 의미다. Outward equilibrium end action과
positive-local-x-face section resultant의 sign identity를 합치지 않는다. 승인 legacy
CSV는 `SF1/SM1/SM2/SM3`만 제공하고 section-cut result와 비교하므로 `SF2`/`SF3` row를
0으로 만들거나 reference row로 합성하지 않는다. HDF5의 transverse end action은
unit/analytical test와 physics sanity 대상이다.
### Frame, instance, and node-station normalization
- Legacy `Frame` value `Increment 1: Step Time = 1.000`은 canonical `(Step-1, frame 0)`으로
변환한다. 승인 bundle의 다른 increment/time string은 `schema-mismatch`다.
- `Part Instance Name`은 HDF5 `/model/nodes` 또는 `/model/elements`의 exact preserved
`instance_name`과 case-insensitive lookup 후 raw identity 일치 여부를 확인한다.
- `Node Label`은 instance 안의 preserved source node label로 resolve한다. Displacement와
reaction key는 `(model_id,Step-1,0,instance_name,source_node_label,quantity,component)`다.
- Elemental-force CSV는 element label이 없으므로 HDF5 endpoint section resultants를
source node station으로 project한다. Boundary station은 유일한 incident endpoint를 쓴다.
- Interior station collapse는 정확히 두 incident B33 endpoints, 동일 section/local-axis
orientation, 일관된 chain connectivity, 해당 node의 concentrated force/moment가 없는
경우에만 허용한다. 두 positive-face section-cut 값이 아래 승인 component tolerance
안에서 먼저 일치해야 한다.
- Interior 값이 일치하면 stable internal element ID가 작은 endpoint를 deterministic
representative로 선택한다. 두 값을 평균하지 않는다. 불일치는 `tolerance-failure`다.
- Reversed connectivity, local-axis discontinuity, section jump, branch 또는 loaded interior
station은 element label 없는 legacy schema로 collapse할 수 없다. 이 approved bundle
밖에서는 element-aware reference row가 필요하며 legacy projection은 `schema-mismatch`
중단한다.
Projected canonical comparison row는 다음 fields를 가진다.
```text
model_id, step_name, frame_index, instance_name, source_node_label,
quantity, component, value, unit_dimension, coordinate_system, hdf5_dataset_path
```
Stable ordering은 quantity inventory order, instance declaration order, stable source node
order, component order다. Approved model ID는 `cantilever-beam-b33`; nodal quantities는
global Cartesian, section resultants는 beam local이다.
### Row-set precheck and tolerance
먼저 양쪽을 legacy contract가 실제 제공하는 quantity/component projection으로 제한한다.
그 projection 안에서는 missing, extra, duplicate, nonfinite, schema-mismatched 또는
identity-mismatched row가 하나라도 있으면 tolerance 계산 전에 실패한다. HDF5에만
mandatory인 `SF2/SF3` 대응 end action, generalized results와 `S11`은 계약상 비교 대상이
아니므로 extra reference row가 아니다.
Matched rows는 같은 `model_id`, step/frame, quantity, component로 group한다.
```text
reference_scale = max(abs(reference_value_i))
row_tolerance = absolute_floor + 1e-6 * reference_scale
row_pass = abs(fesa_value_i - reference_value_i) <= row_tolerance
```
즉 exact policy는 `absolute_floor + 1e-6 * reference_scale`이다. `reference_scale`
read-only Abaqus values만 사용하고 FESA 값으로 조정하지 않는다. Scale이 zero면 relative
term은 zero다. Reference value나 작은 residue를 zero-clamp하지 않고 모든 row를 판정한다.
| approved SI component class | absolute floor |
| --- | ---: |
| displacement and rotation | `1e-9` |
| force and moment | `1e-3` |
Interior endpoint consistency도 해당 CSV quantity/component의 same Abaqus-only scale과
floor를 사용한다. Verification report는 모든 row pass/fail과 quantity별 max absolute
error, component-scale normalized error, RMS error, norm error, worst row/component를
기록한다. 이 reference tolerance는 analytical/formulation tolerance를 대체하지 않는다.
## CLI and Diagnostics Contract
```powershell
fesa.exe <model.inp> --output <results.h5>
```
`--output`을 생략하면 현재 작업 directory의 `results.h5`가 final path다. Input path는
정확히 하나이며 unknown option, missing argument, repeated `--output`은 usage error다.
| exit code | meaning |
| ---: | --- |
| `0` | success; authoritative HDF5 finalization complete |
| `2` | CLI usage error |
| `3` | input syntax or semantic mapping error, including unsupported keyword/formulation/wrapper |
| `4` | model validation error, including geometry, section or property invalidity |
| `5` | factorization or substitution error |
| `6` | HDF5 write, validation or atomic finalization error |
각 stderr diagnostic record는 exact field order `severity`, `code`, `file`, `line`,
`keyword`, `entity_identity`, `message`를 사용한다. Source-backed diagnostics는 normalized
file path와 1-based line을 가지며, source가 없는 solver/output error는 빈 source field를
명시한다. 출력 순서는 source file declaration order, line, entity stable internal ID,
diagnostic code의 tuple로 결정하고 같은 tuple에서는 discovery order를 보존한다. Warning은
성공 run에서도 `/diagnostics`에 기록되며 error가 있으면 해당 exit class를 반환한다.
## Validation Rules
| validation area | required pass condition | failure class |
| --- | --- | --- |
| keyword inventory | supported 또는 exact warning no-op allowlist에 속함 | input, exit 3 |
| nesting/cardinality | closed part/assembly/instance/step; one assembly and one static step | input, exit 3 |
| source identity | duplicate 없음; all references resolve; multi-instance identity unique | input, exit 3 |
| B33 semantics | only `TYPE=B33`; two distinct connected nodes | input/model, exit 3 or 4 |
| section/material | exact data arity/mapping, `I12=0`, all required positive properties | model, exit 4 |
| geometry/local axes | approved length/projection thresholds and right-handed axes | model, exit 4 |
| history | DOF 1..6, resolved targets, finite values, sole canonical frame | input, exit 3 |
| HDF5 | all exact paths, shapes, attributes, identities and finite result values | output, exit 6 |
| legacy artifacts | exact four files, B33, exact headers, unique finite rows | reference precheck |
| comparison | exact projected row-set, endpoint eligibility/consistency, approved tolerance | reference verification |
No parser/HDF5 implementation, reference artifact mutation, Abaqus execution, physics pass 또는
release approval을 이 status가 의미하지 않는다.
## Open Issues and Downstream Handoff
### Resolved numerical-review handoff
`NR-O03-STATION-NORMALIZATION`은 approved legacy bundle에 대해 unloaded, consistently
oriented two-endpoint interior station만 collapse하고, tolerance check 후 smaller stable
element ID를 선택하는 규칙으로 구체화했다. Reversed/branched/loaded/jumped station은
element-aware reference가 없는 한 비교하지 않는다.
### Reference Model Agent
- Exact legacy inventory, generator `Abaqus/CAE Learning Edition 2024`, source commit
`2b34d0b`, external SI provenance와 stress comparison N/A를 계약에 고정한다.
- 추가 reference model은 canonical filenames와 metadata를 사용하며 이 legacy file을
변경하지 않는다.
### Implementation Planning Agent
- Keyword별 positive/negative grammar, source location, duplicates/dangling references,
B31/transform/nested/multiple-step/NLGEOM diagnostics를 TDD cases로 만든다.
- Exact HDF5 path/shape/component/identity, mandatory-output independence와 atomic failure를
검증한다.
- C++ API는 이 semantic contract에서 파생하되 여기에 소급해 API 설계를 추가하지 않는다.
### Reference Verification Agent
- Artifact precheck 뒤 HDF5-to-legacy projection, node-station eligibility, row-set equality,
component-scale comparison 순서를 유지한다.
- Missing/extra/nonfinite row를 무시하거나 `SF2/SF3`/stress reference row를 합성하지 않는다.