Files
FESADev/docs/mitc4-shell-feast-eigen/io-schema.md
T

220 lines
18 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.
# MITC4 eigen authoritative HDF5 schema
- Feature ID: `mitc4-shell-feast-eigen`
- Owner: `io-definition-agent`
- Input contract revision: `r2`
- 기본 보고서: [io.md](io.md)
- 수학: [E1~E8](formulation-eigen.md), [V1~V6](formulation-verification.md)
- Numerical authority: [C1~C6](numerical-review-controls.md)
## O1. Container, version과 공통 규칙
공식 결과는 input lexical sibling `<stem>_results.h5`다. 기존 linear schema0와 nonlinear
schema1은 각각의 [현행 static 계약](../shell-surface-pressure-load/io.md#71-version-and-filename-decision)을
유지한다. Eigen은 기존 shell model container에 새 procedure를 추가하며 discriminant는
`(schema_version=0, feature_id=mitc4-shell-feast-eigen, analysis_procedure=linear-frequency,
eigen_schema_version=1)`이다. `eigen_schema_version`은 새 procedure 전용 revision이다.
Static reader가 schema_version만 보고 eigen을 static으로 해석해서는 안 된다.
기존 static 파일에 새 eigen mandatory fields를 요구하거나 재작성/migration하지 않는다.
앞으로 unknown additive optional field는 무시할 수 있지만 known field의 type/의미 변경,
unknown procedure 또는 eigen_schema_version은 reader의 명시적 unsupported schema 실패다.
Float는 `H5T_IEEE_F64LE`, unsigned/signed integer는 명시된 `H5T_STD_U{8,64}LE`/
`H5T_STD_I64LE`, string은 variable-length UTF-8이다. Compound field의 byte offset/padding은
private이며 field name/type/array extent가 authoritative다. Shape의 `nn,ne,nmat`는 model
node/element/material 수, `N`은 입력 요청, `c`는 최종 solve의 전체 검증 column 수,
`Lcalls`는 모든 actual FEAST calls 수다. 모든 shape/capacity는 checked integer다.
새 numeric dataset의 required attrs는 `schema_version=0`, `eigen_schema_version=1`,
`component_names`, `component_unit_dimensions`, `coordinate_system`, `location`이다.
Compound에서 component attrs는 수치 quantity fields만 table의 명시 순서로 나열하고
identity/flag/counter는 schema 정의를 따른다. 새 modal result에는 추가로
`step_name=Step-1`, `source_step_name=<raw source>`, `domain=mode`를 기록한다.
Tokenized dimension은 아래 `mass`, `length`, `time`를 사용하며 SI label을 붙이지 않는다.
모든 mandatory physical/검증 real 값은 finite다. Optional backend diagnostic의
unavailable는 O4의 명시적 validity flag만 사용한다. NaN payload를 공개하지 않는다.
## O2. Metadata, 모델과 source 요청
`/metadata`의 아래 attributes는 mandatory다.
| Attribute | Type / 값 |
| --- | --- |
| `schema_version`, `eigen_schema_version` | uint64 `0`, `1` |
| `feature_id`, `analysis_procedure` | UTF-8 `mitc4-shell-feast-eigen`, `linear-frequency` |
| `solver_version` | 실제 실행 binary의 기존 version string |
| `source_input_identity` | 기존 `path=<absolute lexical generic path>;content_identity=fnv1a64:<16 lower hex>`; parser가 실제 읽은 원본 bytes 기준 |
| `unit_system_label` | `user-consistent-unspecified` |
| `coordinate_convention` | `global-cartesian; shell-local=initial-reference; positive-thickness=+zeta` |
| `internal_formulation` | `FESA-MITC4` |
| `integration_rule`, `mass_integration_rule` | `2x2x2-gauss; mitc4-edge-midpoint-shear`, `3x3x3-gauss` |
| `stabilization_rule` | `initial-physical-rotary-trace-mean-r2` |
| `step_name`, `source_step_name`, `frame_indexing` | `Step-1`, raw input name(현재 Step-2), `mode-rank-one-based` |
| `mass_variant`, `mass_origin`, `normalization` | `derived-lumped`, `consistent-moment-row-sum`, `mass` |
| `eigensolver_backend`, `eigensolver_routine` | `MKL FEAST`, `dfeast_scsrgv` |
| `backend_problem` | `scaled-whitened-lumped-with-identity-mass` |
| `numerical_contract` | `mitc4-shell-feast-eigen:r2` |
Source identity는 [현재 writer primitive](../../src/fesa/io/hdf5/hdf5_primitives.cpp)의 byte
identity와 동일하다. SHA-256 reference audit와 FNV source identity는 다른 목적이다.
Filename만으로 동일 input이라고 간주하지 않는다. Comparator는 실제 지정 input bytes의
content identity와 lexical input path를 metadata에 대조한다.
| Dataset | Shape/type와 fields | Identity·단위·ordering |
| --- | --- | --- |
| `/model/nodes` | `[nn]` 기존 compound: `internal_node_id:u64,instance_name:utf8,source_label:utf8,coordinates:f64[3]` | Internal ID 0..nn-1, 기존 instance expansion/declaration order; coordinates length, global-cartesian |
| `/model/elements` | `[ne]` 기존 shell compound: `internal_element_id:u64,instance_name:utf8,source_label:utf8,source_element_type:utf8,internal_formulation:utf8,node_internal_ids:u64[4],shell_section_internal_id:u64,material_internal_id:u64` | Internal ID order; source S4/S4R 구별; formulation FESA-MITC4 |
| `/model/shell/materials` | `[nmat]` 기존 compound: `internal_material_id:u64,name:utf8,E:f64,nu:f64` | Declaration order; E force/length^2, nu1. 기존 field에 rho를 끼워 넣지 않음 |
| `/model/shell/sections` | 기존 compound: `internal_section_id:u64,source_file:utf8,source_line:u64,source_elset:utf8,material_internal_id:u64,thickness:f64` | Declaration order, thickness length, centered-single-layer |
| `/model/shell/nodal_director`, `/model/shell/nodal_frame` | `[nn,3]`, `[nn,3,3]` f64 | 기존 source node rows; D components, frame axes A/B/D×global X/Y/Z, dimension1 |
| `/model/nodal_constraint_mask` | `[nn,6]` u8 | Existing DOF order UX,UY,UZ,URX,URY,URZ; free0/constrained1 |
| `/model/prescribed_displacement` | `[nn,6]` f64 | 같은 DOF order, 모든 값 exact0; units length×3,radian×3 |
| `/model/shell/densities` | `[density_count]` 새 compound: `material_internal_id:u64,rho:f64,source_file:utf8,source_line:u64` | Material ID ascending, rho mass/length^3, location model-material; declared density별 한 row, 활성 material 모두 존재 |
| `/model/eigen/source_records` | `[record_count]` compound: `ordinal:u64,source_line:u64,keyword:utf8,physical_text:utf8` | 아래 source provenance 대상의 실제 physical line 순서, ordinal0부터 |
| `/diagnostics` | `[diagnostic_count]` 기존 compound: `severity:utf8,code:utf8,file:utf8,line:u64,keyword:utf8,entity_identity:utf8,message:utf8` | 기존 SortDiagnostics 순서. 성공 파일에는 warning만 존재 |
공통 model dataset의 기존 attrs는 [linear model schema](../linear-static-mitc4-shell/io.md)와
[현재 writer](../../src/fesa/io/hdf5/hdf5_model_writer.cpp)를 따른다. Eigen-specific attrs는
새 dataset에만 필수이며 기존 static dataset type/attrs를 바꾸지 않는다.
기존 model-only midsurface_locations/section_positions를 공유 writer가 추가 저장해도 허용하나
eigen result/acceptance quantity는 아니며 eigen의 mandatory replay dataset이 아니다.
`source_records` 대상은 STEP, FREQUENCY(그 count data 포함), DENSITY(data 포함), I5
no-op keyword와 그 parameter-continuation physical lines다. Comments는 포함하지 않는다.
`keyword`는 canonical parent keyword이고 `physical_text`는 CR/LF를 제거한 원문이다.
Frequency 선언 유무·blank slot 수·raw values를 여기서 보존한다. 물리 domain의 기준은
validated semantic fields이며 output consumer가 raw text를 다시 실행하지 않는다.
`/steps/Step-1` group attrs는 아래와 같다. Canonical group명과 source name을 구분한다.
| Attribute | Type / 의미 |
| --- | --- |
| `source_step_name`, `source_step_name_canonical` | utf8 raw name / ASCII uppercase key |
| `step_source_line`, `frequency_source_line`, `frequency_data_line` | u64 실제 source1-based line |
| `source_nlgeom`, `source_perturbation_present` | u8 effective NO=0 / explicit flag 유무0 또는1 |
| `source_eigensolver`, `source_sim`, `source_acoustic_coupling`, `source_normalization` | utf8 effective `LANCZOS,YES,ON,MASS`; explicit/omitted는 source_records에서 구분 |
| `requested_mode_count`, `returned_mode_count` | u64 N,N; table row수로 입력 N을 덮어쓰지 않음 |
| `full_dof_count`, `free_dof_count`, `mass_null_dimension`, `finite_dimension` | u64 6nn,nf,nz,n, nf=n+nz |
| `validated_eigenpair_count` | u64 c, N<=c<=n; publicly returned mode 수와 구별 |
## O3. 고유치와 modal vectors
Path prefix는 `/steps/Step-1/eigen`이다. `modes`만 공개 eigenvalue row authority다.
| Relative dataset | Shape/type/fields | 의미·attrs |
| --- | --- | --- |
| `modes` | `[N]` compound `mode_id:u64,eigenvalue:f64,classification:u8,cluster_id:u64` | Row k는 mode_id=k+1; quantity=eigenvalue, component_names=Value, component_unit_dimensions=time^-2, coordinate_system=scalar, location=modal-frame |
| `frequencies` | `[Nv]` compound `mode_id:u64,frequency:f64` | 정확히 lambda>=0인 modes의 ID subset, mode ID ascending. quantity=cycle-frequency, component_names=Freq, dimension=time^-1, scalar/modal-frame; mandatory dataset이며 Nv=0도 유효 |
| `vectors` | `[N,nn,6]` f64 | mode axis는 modes와 동일, node axis는 model/nodes, component_names=UX,UY,UZ,URX,URY,URZ; global-cartesian, location=nodal-modal-vector |
`vectors.component_unit_dimensions`는 `mass^-1/2` 세 개와 `mass^-1/2*length^-1` 세 개다.
추가 attrs `normalization=mass`, `amplitude_unit_dimension=mass^1/2*length`,
`mass_variant=derived-lumped`, `interpretation=normalized-mode-not-response-displacement`를 둔다.
각 node의 세 회전 성분은 initial global infinitesimal rotation coordinates다. Constrained
component는 exact0이며 source node label을 internal/equation index로 바꾸지 않는다.
기존 `/nodal/displacement`, reaction, stress, nonlinear accepted_frames를 modal 결과로 생성하지 않는다.
Full matrices/consistent matrix/modal stress를 영속 mandatory output으로 추가하지 않는다.
Raw lambda의 오름차순 stable paired sort와 exact tie의 original FEAST column 순서를 따른다.
Sign은 [C4](numerical-review-controls.md#c4-repeated-subspace와-결정론)대로 largest absolute
scaled global component(translation/ell,rotation)의 양수, tie는 source DOF 순서다.
여기서 source DOF 순서는 model/nodes의 stable row order×정해진 component order다.
Cluster는 전체 c sorted columns에서 C4의 connected rule로 1부터 매기고 첫 N개에 같은 ID를
투영한다. Cluster ID는 진단용이며 값을 평균하거나 결과 multiplicity를 줄이지 않는다.
`operator_scale=s`는 O4에 저장한다. `mu=lambda/s`에서 `mu<-1e-9`는 성공 파일을 만들 수
없는 negative spectrum failure다. `abs(mu)<=1e-9`이면 classification=0(`near-zero`),
그 외는 classification=1(`positive`)이다. Raw lambda와 부호를 그대로 기록하며 ±boundary는
near-zero다. Frequency는 classification이 아닌 raw lambda 부호로 결정한다:
lambda>0이면 sqrt(lambda)/(2pi), lambda==0이면 exact0, lambda<0이면 row가 없다.
따라서 small positive near-zero에도 real frequency가 있고 small negative에는 없다.
Negative row의 부재 이유는 `frequencies@unavailable_rule=negative-raw-eigenvalue`로 명시한다.
Frequency overflow/양수의 underflow-to-zero도 파생 결과 실패로 처리한다. Mandatory lambda
및 mu→lambda conversion은 C3의 finite/underflow 조건을 그대로 따른다.
## O4. Backend와 검증 evidence
Prefix `/steps/Step-1/eigen/verification`의 attrs:
| Attribute | Type / 의미 |
| --- | --- |
| `characteristic_length`, `operator_scale` | positive finite f64 ell[length], s[time^-2] |
| `eta_gram`, `max_eta_orth` | finite f64, 전체 c의 V3 Gram와 pairwise 최대 metric; c=1이면 max_eta_orth=0 |
| `eta_mz`, `eta_kz`, `eta_pz`, `null_checks_applicable` | f64×3 및 u8; nz=0이면 applicable0와 storage값0, N/A이지 수행 통과로 보고하지 않음 |
| `validation_scope`, `numerical_contract` | utf8 `all-computed-c-columns`, `mitc4-shell-feast-eigen:r2` |
| Dataset | Fields / shape | 의미 |
| --- | --- | --- |
| `verification/nodal_reduction` | `[nn]` compound `free_count:u8,null_count:u8,positive_count:u8,rcond_available:u8,rcond_inf:f64` | Source node row 대응; E2 analytic counts. Nonempty positive block에 rcond_available1, C2 cutoff 통과; 빈 block은0/0 storage. nf/nz/n과 합 일치 |
| `verification/eigenpair_checks` | `[c]` compound `sorted_rank:u64,solver_column:u64,eigenvalue:f64,modal_mass:f64,rayleigh_quotient:f64,eta_r:f64,eta_w:f64,rho_b:f64,eta_norm:f64,eta_energy:f64,backend_res_available:u8,backend_res:f64` | sorted_rank1..c, solver_column은 원 FEAST column0-based unique; 실제 ML의 V3/V4/C3 metrics. 첫 N ranks의 lambda는 modes와 exact equal |
Nodal reduction의 quantity component는 `rcond_inf`, dimension1, coordinates=scalar,
location=nodal-mass-reduction이다. Eigenpair checks의 component_names는 표의 f64 fields
순서이고 dimensions는 eigenvalue와 rayleigh_quotient만 time^-2, 나머지는1이다.
Coordinates=scalar, location=eigenpair-verification이며 mandatory finite 검증량과
optional backend_res의 validity를 구분한다.
`eigenpair_checks`는 내부 count/검증 evidence다. c>N 진단행은 추가 공개 modal frame이
아니며 comparator는 여기서 Value를 추출하지 않는다. c개 vector 전부는 검사 동안 유지하고
accepted state에는 공개 N개 vector와 전체 c의 check evidence를 보존한다. 전체 c Gram의
runtime/독립 검증은 C17/18 evidence로 확인하며 N개 persistent vectors만으로 full-c Gram를
재검산했다고 주장하지 않는다. N개 원 residual/normalization은 model 데이터에서 K/ML를
독립 재구성하여 재현할 수 있다. Consistent/lumped 독립 oracle는 NR cases의 내부 테스트다.
Backend `res`가 0-eigenvalue의 상대분모 때문에 unavailable인 경우만
backend_res_available0, backend_res storage0을 사용하고 dataset attr
`unavailable_reason=zero-eigenvalue-relative-residual`를 둔다. Available 값은 finite이고,
nonzero eigenvalue의 nonfinite backend diagnostic은 failure다. Storage0을 residual evidence0으로
해석하지 않는다. mandatory eta_*는 모든 경우 자체 zero branch와 함께 finite다.
Prefix `/steps/Step-1/eigen/backend` attrs는 `runtime_version:utf8`(실제 MKL query),
`integer_abi:utf8`(`LP64|ILP64` 실제 linked ABI), `thread_count:u64=1`,
`seed:u64=0x4D495443344D4645`, `count_calls:u64`, `solve_calls:u64`,
`final_count:u64=c`, `final_solve_ordinal:u64`, `selected_ranks:utf8=1..N`,
`enclosure_lower:f64`, `enclosure_upper:f64`, `solve_lower:f64`, `solve_upper:f64`다.
Bounds는 모두 dimensionless B-space이며 physical frequency bound가 아니다.
| Relative dataset | Shape / fields | 의미 |
| --- | --- | --- |
| `calls` | `[Lcalls]` compound `ordinal:u64,kind:utf8,purpose:utf8,lower:f64,upper:f64,allocated_m0:u64,info:i64,count_available:u8,count:u64,loop_available:u8,loop:u64,epsout_available:u8,epsout:f64` | ordinal0-based 실제 call 순서; kind=count/solve, strict bounds, 실제 allocated capacity. Count의 overwritten m0와 solve의 m을 count로 구분 저장 |
| `fpm` | `[Lcalls,128]` i64 | 각 call 직전 feastinit 이후의 exact parameter snapshot; vendor type을 public core에 노출하지 않음 |
`purpose`는 `total-enclosure`, `upper-prefix`, `lower-prefix`, `endpoint-guard`,
`final-prefix`, `final-interval`, `solve` 중 하나이며 실제 C5 단계에 대응한다.
Calls의 component_names는 `lower,upper,epsout`, dimensions는 `1,1,1`,
coordinates=scalar, location=backend-call이다. Fpm은 component_names=fpm,
dimension1, coordinates=none, location=backend-parameter이며 128개 C-index 순서다.
Calls의 unavailable output은 flag0+storage0이고 원인을 info로 해석한다. Undefined vendor
output을 읽거나 garbage를 저장하지 않는다. `info=0`이면 count_available1; 성공 solve는
loop/epsout도 available1이고 epsout finite. 내부 허용 재시도의 실패 call도 삭제하지 않는다.
최종 성공과 C5 guard/prefix/total count 관계는 chronological calls/bounds로 재구성 가능해야 한다.
Allocated_m0와 input N은 독립이다. Effective fpm와 seed/budget은 C5/C6와 일치해야 한다.
Count-only res/epsout을 fabricated physical result로 사용하지 않는다.
## O5. Self-check와 compatibility tests
Writer는 candidate를 flush/close한 뒤 read-only reopen하여 type/field/shape/required attrs,
finite required values, enum/validity domains 및 다음 관계를 확인하고 검사용 handle도 닫는다.
1. Source identity·input semantic snapshot이 writer 입력과 일치한다. Node/element/material IDs,
connectivity/section/material/density links가 unique/in-range이고 모든 활성 material rho>0이다.
2. Source step은 한 개이고 canonical Step-1과 raw name의 관계가 유일하다. Input N,
requested N, returned N, modes/vector row수가 같다. mode IDs는 정확히1..N이다.
3. Modes가 raw 오름차순이며 classification/cluster는 C3/C4 규칙과 맞는다. Frequencies의
ID set은 lambda>=0 set과 exact equal이며 각 값은 candidate 파생값과 같고 finite다.
4. Vectors는 finite, source constraint component exact0, scalar/vector pair는 candidate와
일치한다. Selected vectors의 ML normalization/원 residual은 serializer 전 C3 gate에서
검증되었고 해당 metrics 및 read-back values를 대조한다. Serializer 자기복사를 독립 physics로 부르지 않는다.
5. `nf=n+nz`, node별 counts 합, N<=c<=n, 전체 c check rows와 solver-column uniqueness,
첫 N lambda exact equality, modal_mass>0, 모든 적용 C2/C3 metric 한계가 맞는다.
6. Calls/fpm row수·ordinals·strict endpoints·finite available diagnostics, fpm controls,
counts/budgets(<=512 count, <=3 solve), final solve info0/returned m=c와 selected1..N이 맞는다.
증거 없는 성공 bool 하나로 대체하지 않는다.
7. `/diagnostics`는 기존 compound `severity,code,file,line,keyword,entity_identity,message`를
유지하며 source order warnings를 저장한다. 성공 파일에 fatal error diagnostic은 없다.
이 mandatory inventory는 reader version dispatch, round-trip, 누락/extra mode/duplicate ID,
nonfinite/wrong dimension/type/mass/backend/source, close/reopen/self-check failure tests의 기준이다.
Optional unknown dataset의 존재를 extra-mode로 오인하지 않는다. Static 파일은 기존 schema
inventory로 계속 검증하고, eigen reader는 static 또는 unknown eigen revision을 명시적으로 거부한다.