# MITC4 eigen authoritative HDF5 schema - Feature ID: `mitc4-shell-feast-eigen2`; Owner: `io-definition-agent`; Contract revision: `r1`. - 기본 보고서: [io.md](io.md). 수치 원본: [formulation-eigen](formulation-eigen.md), [NR controls](numerical-review-controls.md). ## Container와 compatibility 공식 결과는 input lexical sibling `_results.h5`다. Linear schema0와 nonlinear schema1의 기존 dataset/type/필수성/reader 의미를 바꾸지 않는다. 새 eigen discriminator는 `(schema_version=0,feature_id=mitc4-shell-feast-eigen2,analysis_procedure=linear-frequency, eigen_schema_version=1)`이다. 이는 공통 shell model container에 대한 additive procedure다. Reader는 schema_version만 보고 static으로 해석하지 않는다. Unknown procedure/version 또는 eigen 필수 field 누락은 명시적 unsupported/invalid schema다. Static 파일에 새 eigen fields를 요구하거나 migration하지 않는다. Unknown optional additive fields만 무시할 수 있다. File scalar는 f64=`H5T_IEEE_F64LE`, u64/u8/i64는 해당 fixed-width little-endian integer, string은 variable-length UTF-8다. Compound byte padding/offset은 private이며 field name/type/ array extent가 계약이다. 차원 product는 allocation 전에 checked integer다. 아래 nn/ne/nmat는 model node/element/material 수, N은 input 요청, n은 finite dimension, c는 최종 전체 검증 수다. ## Metadata와 model `/metadata` 필수 attributes: | 이름 | Type / 값 | | --- | --- | | schema_version, eigen_schema_version | u64 0,1 | | feature_id, analysis_procedure | utf8 mitc4-shell-feast-eigen2, linear-frequency | | solver_version | utf8 실제 binary version | | source_input_identity | utf8 기존 `path=;content_identity=fnv1a64:<16 lower hex>`; 실제 읽은 원본 bytes | | unit_system_label | utf8 user-consistent-unspecified | | coordinate_convention | utf8 global-cartesian; shell-local=initial-reference; positive-thickness=+zeta | | internal_formulation | utf8 FESA-MITC4 | | integration_rule, mass_integration_rule | utf8 2x2x2-gauss; mitc4-edge-midpoint-shear / 3x3x3-gauss | | stabilization_rule | utf8 initial-physical-rotary-trace-mean | | mass_variant, mass_origin, normalization | utf8 derived-lumped, consistent-moment-row-sum, mass | | eigensolver_backend, eigensolver_routine | utf8 MKL FEAST, dfeast_scsrgv | | backend_problem | utf8 scaled-whitened-lumped-with-identity-mass | | numerical_contract | utf8 mitc4-shell-feast-eigen2:r1 | Model compounds의 기존 physical field는 수정하지 않고 아래처럼 재사용한다. | Dataset | Shape / fields | 의미 | | --- | --- | --- | | /model/nodes | [nn] internal_node_id:u64,instance_name:utf8,source_label:utf8,coordinates:f64[3] | ID 0..nn-1, 기존 expansion/declaration order, global length | | /model/elements | [ne] 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 | ID order; S4/S4R 원형 유지; 모두 FESA-MITC4 | | /model/shell/materials | [nmat] internal_material_id:u64,name:utf8,E:f64,nu:f64 | 기존 declaration order; E force/length^2, nu1; rho를 compound에 삽입하지 않음 | | /model/shell/sections | [section_count] internal_section_id:u64,source_file:utf8,source_line:u64,source_elset:utf8,material_internal_id:u64,thickness:f64 | 기존 centered-single-layer와 thickness length | | /model/shell/nodal_director | [nn,3] f64 | 기존 global unit director D1,D2,D3 | | /model/shell/nodal_frame | [nn,3,3] f64 | 기존 A,B,D axes×global X,Y,Z, dimension1 | | /model/nodal_constraint_mask | [nn,6] u8 | UX,UY,UZ,URX,URY,URZ; free0/constrained1 | | /model/prescribed_displacement | [nn,6] f64 | 같은 component order; 전부 exact0, 기존 length/radian dimensions | | /model/shell/densities | [density_count] 새 compound material_internal_id:u64,rho:f64,source_file:utf8,source_line:u64 | Material ID ascending, 선언 density마다 한 row; 활성 material 전부 존재, rho>0 mass/length^3 | | /diagnostics | [diagnostic_count] 기존 severity:utf8,code:utf8,file:utf8,line:u64,keyword:utf8,entity_identity:utf8,message:utf8 | 기존 deterministic order, 성공 파일은 warning만 | 기존 model dataset attrs는 [현재 model writer](../../src/fesa/io/hdf5/hdf5_model_writer.cpp)의 동일 field 의미를 따른다. `/model/shell/densities` attrs는 component_names=rho, component_unit_dimensions=mass/length^3,coordinate_system=scalar,location=model-material다. 공유 writer의 midsurface_locations/section_positions 추가 저장은 허용하지만 eigen 필수량이 아니다. `/steps/Step-1`은 storage group이며 아래 attributes가 source/procedure authority다. Raw name을 HDF5 path에 넣거나 Step-1에서 source name을 역추정하지 않는다. | Attribute | Type / 의미 | | --- | --- | | source_step_name, source_step_name_canonical | utf8 원문/ASCII uppercase; 지정 입력 Step-2/STEP-2 | | step_source_line, frequency_source_line, frequency_data_line | u64 source 1-based 위치 | | source_nlgeom, source_perturbation_present | u8 effective0 / flag presence0 또는1 | | source_eigensolver, source_sim, source_acoustic_coupling, source_normalization | utf8 effective LANCZOS,YES,ON,MASS | | source_option_presence | u8[4] 위 네 option의 explicit presence 순서 | | requested_mode_count, returned_mode_count | u64 N,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 | | frame_indexing | utf8 mode-rank-one-based | 별도 raw source-record table이나 duplicate reference provenance 파일은 필수로 만들지 않는다. Raw keyword/data/blank fields는 Domain의 ParsedInput provenance와 source byte identity로 추적한다. ## 공개 modal 결과 Prefix `/steps/Step-1/eigen`. 새 result dataset의 공통 attrs는 `eigen_schema_version:u64=1,source_step_name:utf8=,domain:utf8=mode`와 아래 quantity/ component/dimension/coordinate/location이다. Numeric/physical values는 전부 finite다. | Dataset | Shape/type | Quantity·identity | | --- | --- | --- | | modes | [N] compound mode_id:u64,eigenvalue:f64,classification:u8,cluster_id:u64 | 유일 Value authority; mode_id1..N 순서, quantity=eigenvalue, component_names=Value, component_unit_dimensions=time^-2, coordinate_system=scalar, location=modal-frame | | frequencies | [Nv] compound mode_id:u64,frequency:f64 | modes 중 raw lambda>=0의 정확한 ID subset, mode order; quantity=cycle-frequency, component_names=Freq, component_unit_dimensions=time^-1, coordinate_system=scalar, location=modal-frame | | vectors | [N,nn,6] f64 | Modes와 같은 mode axis, model/nodes와 같은 node axis; component_names=UX,UY,UZ,URX,URY,URZ, global-cartesian, nodal-modal-vector | Vectors는 **mandatory 내부 검증 projection**이다. 병진 dimension `mass^-1/2` 세 개와 회전 `mass^-1/2*length^-1` 세 개를 component_unit_dimensions에 기록한다. `normalization=mass,mass_variant=derived-lumped,interpretation=normalized-mode-not-response-displacement` attrs를 둔다. 회전은 initial global infinitesimal rotation이다. Constrained component는 exact0. Static displacement/reaction/stress/accepted_frames를 modal 결과로 생성하지 않는다. [NR raw 분류](numerical-review-controls.md)대로 mu=lambda/s의 절댓값<=1e-9는 classification0=near-zero, 나머지 허용 양수는1=positive다. mu<-1e-9는 성공 파일을 만들 수 없다. Raw lambda는 작은 음수도 보존하며 절댓값/zero clamp하지 않는다. Frequency는 raw lambda>0이면 sqrt(lambda)/(2pi), exact0이면0, 음수에는 row가 없다. Mandatory frequencies dataset은 Nv=0도 허용하며 unavailable_rule=negative-raw-eigenvalue를 기록한다. Finite/range 검사는 NR 기준이며 양수의 frequency underflow-to-zero도 invalid-eigenvalue-result다. Sort는 paired raw lambda ascending, exact tie는 원 FEAST column order다. Sign은 최대 절댓값 scaled global component(translation/ell,rotation)를 양수로, tie는 model row×DOF 순서다. Cluster는 전체 c sorted pairs의 NR connected rule로 1부터 부여한 후 N개에 투영한다. Cluster label은 진단 identity이며 mode average/deduplicate/외부 shape 비교를 유발하지 않는다. ## 전체 c 검증과 실제 backend evidence Prefix `/steps/Step-1/eigen/verification`. Attributes `characteristic_length:f64=ell [length]`, `operator_scale:f64=s [time^-2]`는 positive finite다. `validation_scope=all-computed-c-columns`, `eta_gram:f64,max_eta_orth:f64`는 dimension1, c=1이면 latter0이다. Null 검사는 `null_checks_applicable:u8`와 `eta_mz,eta_kz,eta_pz:f64`로 저장한다. nz=0이면 flag0/storage0이며 N/A이지 검증 통과 metric0이 아니다. 모든 metric 식과 limit는 NR controls와 채택 V식이다. 정규화 후 최종 phi에서 modal_mass와 yf를 다시 계산하고 모든 저장 residual/Gram/Rayleigh/energy에 이 값을 사용한다. | Dataset | Shape / fields | | --- | --- | | nodal_reduction | [nn] compound free_count:u8,null_count:u8,positive_count:u8,rcond_available:u8,rcond_inf:f64 | | 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 | 두 검증 dataset attrs는 coordinate_system=scalar이며 location은 각각 nodal-mass-reduction, eigenpair-verification이다. component_names는 표의 f64 fields 순서, component_unit_dimensions는 아래 해당 field 차원 순서다. Nodal counts는 nn source row에 대응하고 합이 nf/nz/n과 일치한다. Positive block 없는 node는 rcond_available0/storage0이다. Sorted_rank1..c, solver_column0-based unique, modes의 첫 N scalar와 exact pairing한다. Eigenvalue/Rayleigh는 time^-2, 나머지는 dimension1이다. Backend relative res가 zero-mode에서 정의되지 않는 경우에만 unavailable0/storage0으로 두고 의미를 명시한다. Nonzero mode의 nonfinite res 및 모든 mandatory independent metric nonfinite는 실패다. C개 vectors는 solve/validation 동안 유지한다. Accepted state/HDF5에는 N vectors와 전체 c의 metrics를 남긴다. N vectors로 같은 input의 K/ML를 재조립해 N개의 original-free residual/ normalization을 재현할 수 있다. 전체 c Gram의 실제 검증 evidence는 runtime/test 결과로 남기며 N vectors만으로 c Gram를 재계산했다고 주장하지 않는다. Full matrices의 영속 dump는 요구하지 않는다. Prefix `/steps/Step-1/eigen/backend` attributes: `runtime_version:utf8,integer_abi:utf8=LP64|ILP64,thread_count:u64=1,seed:u64`, `enclosure_lower:f64,enclosure_upper:f64,solve_lower:f64,solve_upper:f64`, `count_calls:u64,solve_calls:u64,final_solve_ordinal:u64,final_count:u64=c`, `upper_search_termination:utf8`를 둔다. 마지막 값은 count-target/width-limit/no-midpoint/ optimization-budget/collision-exhausted/optional-status 중 실제 종료 이유다. Bounds는 dimensionless B-space이며 사용자 frequency interval이 아니다. Seed는 NR 값이다. | Dataset | Shape / fields | 의미 | | --- | --- | --- | | base_fpm | [128] i64 | feastinit 뒤 NR override한 실제 solve control snapshot; defaults 포함. Count는 동일 snapshot에서 C-index49만1, 매 call 재초기화 | | 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,outcome:utf8,decision_reason:utf8 | 실제 chronological 호출, ordinal0-based; kind=count/solve, purpose=total-enclosure/upper-guard/final-count/solve | Count의 overwritten m0 또는 solve의 returned m을 count에 담고 allocated_m0와 구분한다. Outcome은 accepted/optional-abandoned/retry이며 NR의 실제 결정에 대응한다. Decision_reason은 accepted 또는 status/count-mismatch/endpoint-separation 등의 결정 원인과 필요한 관측값을 round-trip decimal로 남긴다. 호출 없이 budget/width로 종료한 이유는 upper_search_termination에 둔다. 초기 enclosing 재시도에서만 a0가 확정 전 변경될 수 있고, 성공한 total enclosure 이후 하한은 고정이다. Guard 세 구간은 각각 call row다. 실패·fallback을 삭제하지 않는다. Undefined vendor output은 flag0/storage0으로 두고 읽지 않는다. 성공 count는 count_available1; 성공 solve는 loop/epsout available1이고 finite다. Calls와 final interval/rank/c를 통해 fixed a0, certified upper/full enclosure fallback, budget, capacity, returned count의 경로를 재구성할 수 있어야 한다. CLI live log로 이 trace를 옮기지 않는다. Calls의 f64 component_names는 lower,upper,epsout이고 component_unit_dimensions=1,1,1, coordinate_system=scalar,location=backend-call이다. Base_fpm은 component_names=fpm, component_unit_dimensions=1,coordinate_system=none,location=backend-parameter다. 128개 per-call dump 대신 공통 snapshot 한 개와 kind로 실제 controls를 재현한다. 향후 call별 control 차이를 추가하려면 이 표현과 NR 계약을 함께 재검토해야 한다. ## Closed candidate self-check 현재 [self_check](../../src/fesa/io/hdf5/hdf5_self_check.cpp)는 static schema0/1 전용이므로 별도 eigen dispatch/check가 필요하다. Candidate를 닫고 read-only reopen하여 다음을 검증한다. - Discriminator/metadata/source input bytes·step·요청수, known type/rank/shape/dimension attrs와 model source identity uniqueness/각 reference ID range, density coverage/positivity를 candidate와 대조한다. - Model mask는0/1, prescribed values exact0, modes inventory 정확히1..N, 오름차순·cluster/classification, frequencies 정확한 subset, vectors paired axis/finite/constraint zero와 validated candidate 값을 대조한다. - nf=n+nz 및 nodal count 합, N<=c<=n, c rank/solver-column uniqueness, first-N scalar pairing, independent metrics finite/NR limits, applicable/available flags를 검사한다. N/A를 pass로 계산하지 않는다. - Backend routine/ABI/runtime/base controls, actual call ordering/count/bounds/capacity/status/budget와 final certified interval·c 및 successful all-c validation 연결을 확인한다. Static result paths가 없어야 한다. - Mandatory row 누락/추가/중복/nonfinite/잘못된 quantity·units·mass는 실패한다. Writer가 sorting, averaging, 값 수정으로 candidate mismatch를 수리하지 않는다. 모든 handle close 후에만 replace한다. Self-check는 serialization과 검증된 state의 동일성을 확인한다. 독립 physics/NR 테스트를 대신하거나 저장 metric만으로 실행되지 않은 residual/Gram 계산을 통과로 인정하지 않는다.