feat(result-contract-completion): step 2 — self-contained-hdf5

This commit is contained in:
KOKO\Mimi
2026-08-02 01:51:24 +09:00
parent 9d37465d92
commit 4d04f3dbbe
9 changed files with 1942 additions and 242 deletions
+150 -76
View File
@@ -1,90 +1,164 @@
# FESA HDF5 Schema 1.0.0
# FESA HDF5 Schema 2.0.0
## 1. 범위
## 1. Scope and version compatibility
Schema `1.0.0``results-and-pipeline` Phase의 최소 수직 슬라이스를 정의한다.
파일은 활성 `Domain`의 절점, Beam 연결성, 적용된 전단면적과 그 출처, 그리고 전역
좌표계 절점 변위·회전 및 반력·반력모멘트를 저장한다. 단위 변환은 수행하지 않는다.
Schema `2.0.0` is the self-contained Phase 1 result contract. One file contains
the active normalized model, its single linear-static analysis definition and
solver settings, and every nodal and Beam result needed without the source
`.inp` file. FESA performs no unit conversion.
이 버전에는 재료 전체 속성, 집합, 하중·경계조건, solver 설정, 요소 결과, history,
reference CSV 및 진단 dataset을 저장하지 않는다. 이후 같은 major version에서
dataset을 추가할 수 있지만 아래 required object의 의미, 형상 또는 datatype을
변경해서는 안 된다.
Schema `1.0.0` was the earlier minimal vertical slice. Version `2.0.0` changes
the required model and result objects, so it is a new major version rather than
an in-place change to `1.0.0`. The current writer and reader accept exactly
`2.0.0`; every other version fails with `hdf5.unsupported_schema`. A future
reader may explicitly add support for compatible minor versions, but must not
infer compatibility from a version prefix.
## 2. 공통 규칙
## 2. Common rules
- root attribute `schema_version`은 UTF-8 문자열 `1.0.0`이다.
- 정수 dataset은 명시한 little-endian 고정폭 타입을 사용한다.
- 실수 dataset은 IEEE 754 little-endian 64-bit 타입을 사용한다.
- 문자열 dataset과 attribute는 UTF-8 variable-length string을 사용한다.
- `dense_index`는 해당 dataset 행의 0-based index이며 연속적이다.
- `internal_id`와 결과의 `node_ids`는 FESA semantic model의 nonnegative ID다.
- flat/orphan mesh의 `part_name``instance_name`은 빈 문자열이다.
- 결과의 6개 component 순서는
`(Ux, Uy, Uz, Rx, Ry, Rz)``(RFx, RFy, RFz, RMx, RMy, RMz)`.
- Step과 frame group 이름은 각각 0부터 연속된 decimal index다. 원래 Step 이름은
Step group의 `name` attribute에 저장한다.
- Root attributes are variable-length UTF-8 strings:
`schema_version="2.0.0"`, `fesa_version`, and
`unit_policy="consistent_input_units_no_conversion"`.
- Integer datasets use the stated little-endian fixed-width type. Floating
datasets use IEEE 754 little-endian `float64`. Strings are variable-length
UTF-8.
- `dense_index` is a contiguous 0-based row index. Semantic `internal_id`
values are nonnegative and are not assumed to be dense or ordered.
- Flat/orphan mesh `part_name` and `instance_name` values are empty strings.
- Ragged arrays use an offset dataset of length `row_count + 1`. Offsets start
at zero, are nondecreasing, and the final offset equals the flattened row
count. Input order is preserved.
- Numeric field datasets carry UTF-8 `coordinate_system` and `components`
attributes where listed. `components` is a comma-separated ordered list.
- Step and frame group names are contiguous decimal indices beginning at zero.
Phase 1 requires exactly one analysis step and one result step with the same
name.
## 3. Required objects
```text
/
├── @schema_version UTF-8 = "1.0.0"
├── model
│ ├── nodes
│ │ ├── dense_index uint64 [node_count]
│ │ ├── internal_id int64 [node_count]
│ │ ├── part_name UTF-8 [node_count]
│ │ ├── instance_name UTF-8 [node_count]
│ │ ├── local_label int64 [node_count]
│ │ └── coordinates float64[node_count, 3]
│ ├── elements
│ │ ├── dense_index uint64 [element_count]
│ │ ├── internal_id int64 [element_count]
│ │ ├── connectivity uint64 [element_count, 2]
│ │ └── section_id int64 [element_count]
│ └── sections
│ ├── internal_id int64 [section_count]
│ ├── shear_area_y float64[section_count]
│ ├── shear_area_z float64[section_count]
│ └── shear_source uint8 [section_count]
└── results
└── steps
└── <step_index>
├── @name UTF-8
└── frames
└── <frame_index>
├── @step_time float64
└── nodal
├── node_ids int64 [result_node_count]
├── displacement float64[result_node_count, 6]
└── reaction float64[result_node_count, 6]
```
### 3.1 Model
`model/elements/connectivity``model/nodes/dense_index`를 참조한다. 따라서
`internal_id`가 연속적이거나 Domain 저장 순서와 같다고 가정하지 않는다.
`section_id``model/sections/internal_id`를 참조한다.
Let `N`, `E`, `M`, `S`, `NS`, and `ES` be the node, Beam element, material,
section, node-set, and element-set counts. Let `P` be the total number of
section recovery points, `NM` the total node-set membership count, and `EM` the
total element-set membership count.
`shear_source` 값은 다음과 같다.
| Path | Type | Rank and shape | Attributes / meaning |
|---|---|---|---|
| `/model/nodes/dense_index` | `uint64` | 1, `[N]` | contiguous row index |
| `/model/nodes/internal_id` | `int64` | 1, `[N]` | `NodeId` |
| `/model/nodes/part_name` | UTF-8 | 1, `[N]` | entity provenance |
| `/model/nodes/instance_name` | UTF-8 | 1, `[N]` | entity provenance |
| `/model/nodes/local_label` | `int64` | 1, `[N]` | external local label |
| `/model/nodes/coordinates` | `float64` | 2, `[N,3]` | `coordinate_system="global"`, `components="X,Y,Z"` |
| `/model/elements/dense_index` | `uint64` | 1, `[E]` | contiguous row index |
| `/model/elements/internal_id` | `int64` | 1, `[E]` | `ElementId` |
| `/model/elements/part_name` | UTF-8 | 1, `[E]` | entity provenance |
| `/model/elements/instance_name` | UTF-8 | 1, `[E]` | entity provenance |
| `/model/elements/local_label` | `int64` | 1, `[E]` | external local label |
| `/model/elements/connectivity` | `uint64` | 2, `[E,2]` | node `dense_index`, ordered end `-1,+1` |
| `/model/elements/material_id` | `int64` | 1, `[E]` | references material `internal_id` |
| `/model/elements/section_id` | `int64` | 1, `[E]` | references section `internal_id` |
| `/model/materials/internal_id` | `int64` | 1, `[M]` | `MaterialId` |
| `/model/materials/name` | UTF-8 | 1, `[M]` | material name |
| `/model/materials/young_modulus` | `float64` | 1, `[M]` | finite, positive |
| `/model/materials/poisson_ratio` | `float64` | 1, `[M]` | finite, `-1 < nu < 0.5` |
| `/model/sections/internal_id` | `int64` | 1, `[S]` | `SectionId` |
| `/model/sections/name` | UTF-8 | 1, `[S]` | section name |
| `/model/sections/area` | `float64` | 1, `[S]` | `A` |
| `/model/sections/moment_y` | `float64` | 1, `[S]` | `Iy` |
| `/model/sections/moment_z` | `float64` | 1, `[S]` | `Iz` |
| `/model/sections/torsion_constant` | `float64` | 1, `[S]` | `J` |
| `/model/sections/shear_area_y` | `float64` | 1, `[S]` | applied `Asy` |
| `/model/sections/shear_area_z` | `float64` | 1, `[S]` | applied `Asz` |
| `/model/sections/shear_source` | `uint8` | 1, `[S]` | `0=input`, `1=phase1_default` |
| `/model/sections/orientation` | `float64` | 2, `[S,3]` | `coordinate_system="global"`, `components="X,Y,Z"` |
| `/model/sections/recovery_point_offsets` | `uint64` | 1, `[S+1]` | offsets into `recovery_points` |
| `/model/sections/recovery_points` | `float64` | 2, `[P,2]` | `coordinate_system="element_local"`, `components="y,z"` |
| `/model/sets/node/names` | UTF-8 | 1, `[NS]` | exact node-set names |
| `/model/sets/node/member_offsets` | `uint64` | 1, `[NS+1]` | offsets into `members` |
| `/model/sets/node/members` | `int64` | 1, `[NM]` | `NodeId`, input set/member order |
| `/model/sets/element/names` | UTF-8 | 1, `[ES]` | exact element-set names |
| `/model/sets/element/member_offsets` | `uint64` | 1, `[ES+1]` | offsets into `members` |
| `/model/sets/element/members` | `int64` | 1, `[EM]` | `ElementId`, input set/member order |
| 값 | 의미 |
### 3.2 Analysis
`/analysis/steps/0` has UTF-8 attribute `name`. Let `B` be the prescribed-DOF
count and `L` the nodal-load count.
| Path | Type | Rank and shape | Attributes / meaning |
|---|---|---|---|
| `/analysis/steps/0/boundary_conditions/node_ids` | `int64` | 1, `[B]` | target `NodeId` |
| `/analysis/steps/0/boundary_conditions/dofs` | `uint8` | 1, `[B]` | Abaqus/FESA DOF number 1 through 6 |
| `/analysis/steps/0/boundary_conditions/values` | `float64` | 1, `[B]` | prescribed value |
| `/analysis/steps/0/nodal_loads/node_ids` | `int64` | 1, `[L]` | target `NodeId` |
| `/analysis/steps/0/nodal_loads/values` | `float64` | 2, `[L,6]` | `coordinate_system="global"`, `components="Fx,Fy,Fz,Mx,My,Mz"` |
`/analysis/solver_settings` has the exact UTF-8 attributes used by the Phase 1
pipeline: `backend="mkl_pardiso"`,
`matrix_storage="symmetric_upper_csr"`,
`matrix_type="symmetric_positive_definite"`,
`constraint_method="essential_dof_elimination"`, and
`assembly="deterministic_serial"`. No unused future settings are stored.
### 3.3 Results
`/results/steps/0` has UTF-8 attribute `name`; frame group `0` has scalar
`float64` attribute `step_time`. Let `RN`, `RE`, `RP`, and `D` be the nodal
result, Beam result, flattened Beam recovery-point, and diagnostic counts.
| Path below `/results/steps/0/frames/0` | Type | Rank and shape | Attributes / meaning |
|---|---|---|---|
| `nodal/node_ids` | `int64` | 1, `[RN]` | `NodeId`; provenance is joined from `/model/nodes` |
| `nodal/displacement` | `float64` | 2, `[RN,6]` | `coordinate_system="global"`, `components="Ux,Uy,Uz,Rx,Ry,Rz"` |
| `nodal/reaction` | `float64` | 2, `[RN,6]` | `coordinate_system="global"`, `components="RFx,RFy,RFz,RMx,RMy,RMz"` |
| `element/beam/element_ids` | `int64` | 1, `[RE]` | `ElementId` |
| `element/beam/part_name` | UTF-8 | 1, `[RE]` | result provenance |
| `element/beam/instance_name` | UTF-8 | 1, `[RE]` | result provenance |
| `element/beam/local_label` | `int64` | 1, `[RE]` | result provenance |
| `element/beam/local_frame` | `float64` | 3, `[RE,3,3]` | `coordinate_system="global"`, `components="ex,ey,ez"`; last dimension is `X,Y,Z` |
| `element/beam/end_node_ids` | `int64` | 2, `[RE,2]` | ordered ends `-1,+1` |
| `element/beam/xi` | `float64` | 2, `[RE,2]` | `components="end_minus,end_plus"` |
| `element/beam/section_strain` | `float64` | 3, `[RE,2,6]` | `coordinate_system="element_local"`, `components="epsilon,gamma_y,gamma_z,kappa_x,kappa_y,kappa_z"` |
| `element/beam/section_force` | `float64` | 3, `[RE,2,6]` | `coordinate_system="element_local"`, `components="N,Vy,Vz,T,My,Mz"` |
| `element/beam/centroid_sigma_xx` | `float64` | 2, `[RE,2]` | `coordinate_system="element_local"`, `components="end_minus,end_plus"`, `quantity="sigma_xx"` |
| `element/beam/recovery_point_offsets` | `uint64` | 1, `[RE+1]` | offsets into recovery-point rows |
| `element/beam/recovery_point_sigma_xx` | `float64` | 2, `[RP,2]` | `coordinate_system="element_local"`, `components="end_minus,end_plus"`, `quantity="sigma_xx"`; point order comes from the referenced section |
| `diagnostics/stage` | `uint8` | 1, `[D]` | enum table below |
| `diagnostics/severity` | `uint8` | 1, `[D]` | `0=warning`, `1=error` |
| `diagnostics/code` | UTF-8 | 1, `[D]` | exact diagnostic code |
| `diagnostics/message` | UTF-8 | 1, `[D]` | exact diagnostic message |
| `diagnostics/has_source` | `uint8` | 1, `[D]` | `0=no source`, `1=source present` |
| `diagnostics/source_file` | UTF-8 | 1, `[D]` | empty when source is absent |
| `diagnostics/source_line` | `uint64` | 1, `[D]` | zero when source is absent |
| `diagnostics/source_column` | `uint64` | 1, `[D]` | zero when source is absent |
Diagnostic stage encoding follows the declaration order:
| Value | Stage |
|---:|---|
| `0` | 입력에서 명시된 전단강성으로부터 구성한 값 (`input`) |
| `1` | Phase 1 기본값 `Asy=Asz=5A/6`, `SCF=0` (`phase1_default`) |
| 0 | `io` |
| 1 | `syntax` |
| 2 | `semantic` |
| 3 | `model` |
| 4 | `equation` |
| 5 | `solver` |
| 6 | `results` |
| 7 | `validation` |
## 4. Writer reader 계약
## 4. Writer and reader contract
- writer는 쓰기 전에 `ResultDatabase` 유효성과 schema version을 검사한다.
- schema `1.0.0`이 표현하지 않는 non-empty frame diagnostics는 파일을 만들기 전에
`hdf5.unsupported_result_diagnostics`로 거부한다.
- required object 생성·쓰기·flush·close 중 HDF5 오류가 발생하면 성공으로 반환하지
않고 `DiagnosticStage::results` 오류로 변환한다.
- reader는 schema version, required object, datatype, rank와 shape를 검사한다.
- reader는 model internal ID의 uniqueness, finite coordinates 및 finite positive
shear area를 검사한다.
- writer와 reader는 모든 nodal result ID가 `model/nodes/internal_id`에 존재하는지
검사하며, 없는 ID를 성공 결과로 반환하지 않는다.
- reader는 nodal result를 `ResultDatabase`로, model dataset을 HDF5 adapter 전용
read-only inspection model로 반환한다. `Domain``ResultDatabase`에는 HDF5
저장 계약을 추가하지 않는다.
- malformed 또는 지원하지 않는 파일은 부분 database를 반환하지 않는다.
- The writer validates `ResultDatabase`, exact schema version, model/result ID
and provenance joins, Beam connectivity, recovery-point counts, and the
single-step name before creating the file.
- Required-object creation, write, flush, and close failures become
`DiagnosticStage::results` errors. A failed write is never reported as
success.
- The reader validates the exact version, required datatypes, ranks, shapes,
offsets, finite values, uniqueness, references, field metadata, and result
contracts. It does not return a partial database or partial snapshots.
- The public reader returns adapter-owned, read-only metadata, model, and
analysis snapshots plus the semantic `ResultDatabase`. No HDF5 object or
handle escapes the adapter, and the snapshots contain enough information to
reconstruct the Phase 1 model and run definition without the source deck.