# 이전 MFE 입력·결과·mapping 계약
이전 baseline의 계약 이력이다. 현재 입력·schema·controls는 [eigen2 I/O](../mitc4-shell-feast-eigen2/io.md#io)가 원본이다.
## MITC4 mass와 FEAST I/O 계약
- Feature ID: `mitc4-shell-feast-eigen`
- Input contract revision: `r2`
- 요청 outcome: `pass`; 다음 owner: `implementation-planning-agent`
- 의미: Stage 5 계약 검토 요청이며 workflow 전이·구현 완료 판정이 아니다.
지역 입력은 [FEATURED_AGENTS](FEATURED_AGENTS.md), [PRD](PRD.md), [ADR](ADR.md),
[coordination](development-notes.md#실패와-재발-방지)이다. [Requirements](requirements.md#requirements)와
[승인 evidence](requirements.md#requirements-evidence), [research](research.md#research)/[상세 근거](research.md#research-evidence),
[formulation](formulation.md#formulation), [NR](numerical-review.md#numerical-review)/[독립 evidence](numerical-review.md#numerical-review-evidence),
[controls](numerical-review.md#numerical-review-controls), [cases](numerical-review.md#numerical-review-cases),
[reference-model](reference-model.md)의 r2를 적용했다.
[프로젝트 지침](../../AGENTS.md), [ARCHITECTURE](../ARCHITECTURE.md),
[TOLERANCE](../TOLERANCE.md), [agent 계약](../SOLVER_AGENT_DESIGN.md),
[문서 관리](../FEATURE_DOCUMENTATION.md)가 공통 기준이다.
### 핵심 계약
1. [입력·validation](io.md#io-input)은 constant material density, 원형상 단일 frequency step,
입력 requested N, homogeneous global BC와 원본의 부수 옵션을 고정한다. Source
Lanczos/SIM과 actual FEAST를 구분한다. 기존 static은 density 없이 계속 동작한다.
2. [결과 schema](io.md#io-schema)는 기존 static schema를 보존하고 eigen procedure 전용
additive 계약을 정의한다. 공식 파일은 lexical sibling `_results.h5`이고,
source step과 mode 1..N, raw lambda, actual lumped mass/backend 및 내부 검증 증거를
저장한다. N개 global modal vectors는 내부 검증 재현을 위해 mandatory다.
3. [책임·failure·comparison mapping](io.md#io-mapping)은 Domain/view/DOF/별도 eigen state의
경계, candidate commit, source identity, 원본 TXT의 Value-only projection과
27개 requirement 및 I/O test obligations를 연결한다. 외부 mode-shape gate는 없다.
`consistent -> derived lumped -> MKL FEAST` 및 [mass](formulation.md#formulation-mass),
[reduction/commit](formulation.md#formulation-eigen), [verification](formulation.md#formulation-verification),
[r2 stabilization](formulation.md#formulation-stabilization)의 수학을 변경하지 않는다.
FEAST 수치 controls와 외부 10개 singleton family의 공통 판정도 그대로다.
Routine field layout·새 procedure의 additive schema를 정의했으며 기존 public 계약의
비호환 변경 또는 새 사용자 결정은 발견하지 않았다.
### Evidence와 한계
`Get-Content`, scoped `rg`로 원본 input/TXT, 기존 linear/nonlinear/pressure I/O,
실제 syntax/model mapping, HDF5 writer, source identity 및 diagnostics 경계를 대조했다.
새 keyword 의미는 공식 Abaqus 2025 공개 문서를 확인했고 locator·적용 한계를
[입력 출처](io.md#io-input--공개-근거와-적용-한계)에 기록했다. Abaqus는 외부 syntax/quantity
convention이며 내부 parser, mass, integration, stabilization 또는 ODB와 동등성을 주장하지 않는다.
정적 검증 명령·exit, owned metadata/links/coverage와 원본 inventory는
[감사 evidence](io.md#io-mapping--정적-감사-evidence)에 기록한다.
새로 작성한 문서는 이 보고서와 `io-input.md`, `io-schema.md`, `io-mapping.md`뿐이다.
Source/tests/build/phase/Hook/Git 및 upstream/reference는 수정하지 않았다.
문서 단계이므로 C++ build/test, Harness, 실제 FEAST, 외부 solver 및 FESA/reference
수치 비교는 미실행이다. Header나 계약 존재를 실행 성공으로 보고하지 않는다.
Planning은 각 test obligation을 정확한 owned paths와 RED/GREEN/focused/full VERIFY에
연결하고, Implementation/Physics는 fresh eigen 결과 및 승인된 static 회귀를 검증해야 한다.
Ill-conditioned positive mass의 명시적 실패, FEAST floating-point count/cluster 한계,
count scratch와 shifted factorization 비용은 [NR controls](numerical-review.md#numerical-review-controls)의
잔여 위험이며 I/O가 cutoff·fallback·새 tolerance로 우회하지 않는다.
## MITC4 eigen 입력 subset과 진단
- Feature ID: `mitc4-shell-feast-eigen`
- Input contract revision: `r2`
- 기본 보고서: [io.md](io.md#io)
### I1. 문법과 source identity
기존 [linear shell I/O §1](../linear-static-mitc4-shell/io.md),
[현재 pressure I/O §3](../shell-surface-pressure-load/io.md)의 공통 lexical 계약을 재사용한다.
현재 [input reader](../../src/fesa/io/abaqus/input_reader.cpp)와
[mapping context](../../src/fesa/io/abaqus/domain_mapping_context.cpp)를 읽기 전용 대조했다.
예전 nonlinear 문서의 continuation 미지원 설명보다 후속 승인된 pressure lexical 규칙이 우선한다.
- CRLF/LF를 수용한다. Physical line은 종결자를 제외해 최대 256 ASCII bytes이며 printable
ASCII와 horizontal tab만 허용한다. `**` comment와 blank line은 semantic effect가 없다.
Inline comment, data continuation, include, substitution, quoted/escaped 이름은 지원하지 않는다.
- Keyword/parameter/enum/name lookup은 ASCII case-insensitive다. Parameter 순서는 무관하지만
duplicate name은 값이 같아도 실패한다. Raw spelling, keyword physical lines, data fields와
normalized lexical input path/1-based line을 보존한다. Keyword terminal comma는 기존
parameter continuation이며 직후 comment/blank/new keyword/EOF interruption은 실패한다.
- Comma split은 빈 필드를 보존한다. 각 token 주변 space/tab만 trim한다. 아래 명시된
공란 외에 arbitrary trailing-empty 제거를 적용하지 않는다.
- Source node/element label은 positive decimal int64이고 raw digits와 numeric identity를
분리한다. Scope 내 같은 numeric label은 duplicate다. Name/target는 기존 shell의
비어 있지 않은 ASCII 이름·qualification 규칙을 재사용한다. 새 step name도 같은
name token이며 생략 시 source name은 `Step-1`이다. HDF5 path에 raw name을 삽입하지 않는다.
- 새 `rho` numeric token은 `[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[Ee][+-]?[0-9]+)?`다.
C-locale full consumption과 binary64 finite conversion을 요구한다. NaN/Inf, hex, D exponent,
overflow/underflow conversion error는 실패한다. N은 `[0-9]+`와 checked int64 범위이며
값이 양수여야 한다. 기존 keyword의 승인된 numeric parsing은 이 기능 때문에 바꾸지 않는다.
### I2. 지원 keyword와 위치
Eigen input의 문법은 `heading? preprint? part+ assembly material+ model-boundary* step EOF`다.
Comments/blank는 블록 사이에 허용한다. 기존 mesh/set nesting과 forward material/section
resolution은 유지한다. 활성 모델은 S4/S4R shell만 포함한다.
| Keyword | Eigen subset·data | 의미와 validation |
| --- | --- | --- |
| `*HEADING` | Optional 첫 keyword, parameter 없음, text rows | Heading provenance. Duplicate/nesting 오류 거부 |
| `*PART`, `*END PART` | `NAME` 하나; close parameter/data 없음 | Part-local topology. 중첩/중복/미종결 거부 |
| `*NODE` | Part scope, parameter 없음; `label,x,y,z` | Finite initial global midsurface coordinates. 중복·잘못된 arity 거부 |
| `*ELEMENT` | Part scope, `TYPE=S4` 또는 `TYPE=S4R`만; `label,n1,n2,n3,n4` | 같은 MITC4 physical/mass path와 별도 source type. 네 distinct resolved nodes 필요 |
| `*NSET`, `*ELSET` | Part/assembly scope; 해당 `NSET=name` 또는 `ELSET=name`, optional flag `GENERATE`; assembly는 `INSTANCE=name` 필수. 기존 assembly ELSET의 `INTERNAL` flag도 유지 | Explicit positive labels, 또는 `first,last,increment` inclusive generate. 기존 set row trailing comma 허용. Nonpositive/역순/도달 불가능 range·empty·duplicate definition·dangling/cyclic/mixed-instance 거부 |
| `*SHELL SECTION` | Part scope, `ELSET`, `MATERIAL` 필수; 한 row `t[,integration_points]` | Centered homogeneous layer, constant finite t>0, element별 유일 assignment. Optional second field가 있으면 positive decimal integer; 아래 예외 적용 |
| `*ASSEMBLY`, `*END ASSEMBLY` | Top-level 하나, `NAME`; close parameter/data 없음 | Assembly scope, nested/duplicate 거부 |
| `*INSTANCE`, `*END INSTANCE` | Assembly scope, `NAME`, `PART`; data 없음 | Identity instances; 같은 part의 여러 identity instance 허용. Transform/dangling/duplicate 거부 |
| `*MATERIAL` | Top-level model data, `NAME`; data 없음 | Named material 소유. Case-insensitive unique |
| `*ELASTIC` | Current material, parameter 없음; 한 row `E,nu` | 기존 finite E>0, -1
### I3. Density material mapping
`*DENSITY`는 한 material에 최대 한 번, 정확히 한 data row이며 첫 field는 rho다.
`rho` 또는 `rho,`만 허용한다. 후자는 원본 `2700.,`의 빈 temperature slot이며
temperature dependence가 없는 constant 값으로 대응한다. Nonempty temperature/field variable,
두 개 이상의 추가 comma, 추가 data row, `DEPENDENCIES`(0 포함), `PORE FLUID`, `SLURRY`,
distribution 이름과 다른 parameter는 거부한다. Elastic과 Density의 상대 선언 순서는 자유다.
Numeric rho가 finite이며 strict >0이어야 한다. Material scope 밖 Density도 실패다.
모든 활성 shell의 `element -> section -> material -> rho`가 정확히 하나로 결정되어야 한다.
Missing rho를 0이나 기본값으로 채우지 않는다. 서로 다른 material/section의 rho/t를
global 평균으로 바꾸지 않는다. 사용하지 않은 material의 Density가 존재하면 문법·양성 검증은
동일하며, rho 존재의 필수성은 활성 material에 적용한다. Material/section reference 오류는
밀도가 있는 다른 material로 fallback하지 않는다. 단위는 `mass/length^3`, 변환 없음.
Density의 새 입력 허용은 이 eigen procedure에 속한다. 기존 static parser의 Density 지원
범위를 넓히지 않고, density가 없는 기존 static input과 material 생성 경로를 보존한다.
Material의 내부 optional density를 만들더라도 static에 필수값을 요구하지 않는다.
### I4. Step와 Frequency의 exact options
`*STEP` 허용 parameter는 optional `NAME=`, optional `NLGEOM=NO`, optional
value 없는 `PERTURBATION`뿐이며 data는 없다. NLGEOM 생략은 NO다. PERTURBATION이 없어도
FREQUENCY가 원형상 linear perturbation procedure를 결정하고 source flag 유무를 보존한다.
`NLGEOM=YES`, flag NLGEOM, `PERTURBATION=...`, `INC`, 다른 option은 eigen에서 거부한다.
Frequency 외 procedure, step description data, 두 번째 procedure/step, 선행 상태는 지원하지 않는다.
| FREQUENCY parameter | 허용·기본 의미 | Observable mapping |
| --- | --- | --- |
| `EIGENSOLVER` | 생략 또는 `LANCZOS` | Source default=LANCZOS; actual=`MKL FEAST`. Explicit/omitted provenance와 backend mapping warning 기록 |
| `SIM` | 생략, value 없는 flag, `YES` | Source effective=YES. FESA SIM architecture 기능을 만들지 않음. Explicit일 때 no-op warning |
| `ACOUSTIC COUPLING` | 생략 또는 `ON` | Acoustic/ASI/TIE/coupling 정의가 전혀 없는 structural-only 모델에서만 적용 대상 없음. Explicit일 때 no-op warning |
| `NORMALIZATION` | 생략 또는 `MASS` | Source SIM=YES의 mass default를 적용. FESA 실제 ML로 phi^T ML phi=1; 값 변경 warning 없음 |
`SIM=NO`, `NORMALIZATION=DISPLACEMENT`, `AMS/SUBSPACE/FEAST` source enum,
`ACOUSTIC COUPLING=OFF|PROJECTION`, `DAMPING PROJECTION`, `RESIDUAL MODES`,
`PROPERTY EVALUATION`, `NSET` 및 다른 parameter는 지원하지 않는다.
사용자 backend 요구를 Abaqus 문법의 새 `EIGENSOLVER=FEAST` 지원으로 바꾸지 않는다.
Data는 정확히 한 physical row, comma split 후 **1~7 fields**다. 첫 field N은 mandatory
positive decimal integer이며 2~7은 존재하면 모두 empty여야 한다. 생략된 trailing fields도
unspecified다. 원본 `10, , , , ,`는 여섯 fields로 유효하다. Fields 2/3은 frequency bounds,
4는 shift, 5/6은 Lanczos controls, 7은 acoustic range factor의 source slot이다.
공란은 숫자0이 아니다. 어느 slot의 nonempty `0`도 지원하지 않으며, eighth empty field도
arity 오류다. 추가 row는 residual-mode input으로 해석하지 않고 거부한다.
이 제한은 [공식 FREQUENCY syntax](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-frequency.htm)의
선택된 부분집합이다. N은 마지막까지 input authority이고 TXT 행수/count scratch/returned m과 다르다.
`N>finite_dimension` 및 빈 finite problem은 equation 구성 뒤 명시적으로 실패한다.
### I5. Result-neutral allowlist와 warning
아래 keyword는 parameter 순서만 자유이며 duplicate/추가 parameter·data row는 거부한다.
동일 조합의 반복 output request는 각 keyword당 warning 한 개를 남기며 결과를 바꾸지 않는다.
| Keyword | 정확한 조합·위치 | Warning code |
| --- | --- | --- |
| `*PREPRINT` | Optional top-level; `ECHO=NO,MODEL=NO,HISTORY=NO,CONTACT=NO` 정확히 네 개, data 없음 | `ignored-input-keyword` |
| `*RESTART` | FREQUENCY/BC 뒤; flag WRITE와 FREQUENCY=0, data 없음 | `ignored-input-keyword` |
| `*OUTPUT` | FREQUENCY/BC 뒤; FIELD 또는 HISTORY flag 하나; optional VARIABLE=PRESELECT; data 없음 | `ignored-input-keyword` |
| `*NODE OUTPUT` | 활성 OUTPUT FIELD 아래; VARIABLE=PRESELECT 하나, data 없음 | `ignored-input-keyword` |
| `*ENERGY OUTPUT` | 활성 OUTPUT HISTORY 아래; VARIABLE=ALL 하나, data 없음 | `ignored-input-keyword` |
새 OUTPUT root는 앞의 output scope를 닫고, RESTART/END STEP도 닫는다. Child scope mismatch는
거부한다. Restart READ/nonzero write frequency, output variables data, element/contact output,
node history request 등 표 밖 조합은 eigen에서는 fail-closed다. 기존 static allowlist를 축소하지 않는다.
Warning message는 raw keyword와 `mandatory-eigen-output-unchanged` 이유를 포함한다.
RESTART frequency0은 write 중단 옵션이고 출력 요청들은 model equations를 바꾸지 않는
output selection이다. FESA는 이 selection을 구현하지 않는다는 차이를 알린다.
FREQUENCY에는 `source-eigensolver-mapped-to-feast` warning을 항상 하나 기록한다.
Explicit SIM에는 `source-sim-option-not-applied`, explicit acoustic ON에는
`acoustic-option-inapplicable-structural-only`를 기록한다.
위 세 code를 포함한 출력 순서는 기존 source tuple의 code 정렬을 따른다. Invalid model은
이 warning을 근거로 acoustic/coupling semantics를 버려서는 안 된다.
### I6. Fail-closed validation과 diagnostics
표 밖 model/history keyword는 eigen analysis 전에 거부한다. 특히 어떤 위치의
`CLOAD/DLOAD/DSLOAD`, initial condition/stress/temperature, damping, acoustic/ASI elements,
TIE/contact/MPC, transform/orientation/explicit director, surface/beam/solid/mixed model,
concentrated/nonstructural mass, composite/offset/variable thickness, amplitudes, restart read와
다중 step은 지원하지 않는다. Zero-valued load/damping 입력도 지원되는 무하중 모델로 바꾸지 않는다.
진단 record는 기존 `severity,code,file,line,keyword,entity_identity,message`를 사용한다.
file은 lexical normalized path, line은 source 1-based다. Material/section/node/element/step,
DOF 또는 invalid parameter/field ordinal을 가능한 한 entity/message에 포함한다.
Numerical scale·threshold·observed value는 binary64 round-trip 가능한 decimal로 보고한다.
Source location 없는 backend failure도 sole Frequency location과 step을 연결한다.
기존 SortDiagnostics 순서와 same-key discovery order를 유지한다.
| Condition | Stable code | CLI exit |
| --- | --- | --- |
| Lexical/arity/duplicate parameter/name/unresolved source | 기존 `invalid-input-character`, `input-line-too-long`, `invalid-data-arity`, `invalid-keyword-parameter`, `unresolved-reference` 등 해당 기존 code | 3 |
| Density scope/data/dependency/duplicate | `invalid-density-data` / `unsupported-density-option` / `duplicate-density` | 3 |
| Active rho missing / numeric nonfinite 또는 nonpositive | `missing-material-density` / `invalid-material-density` | 4 |
| New rho malformed numeric token | `invalid-density-data` | 3 |
| Frequency parameter/count/data mismatch | `unsupported-frequency-option` / `invalid-frequency-data` | 3 |
| Multiple/preload/unsupported procedure | `unsupported-analysis-procedure` | 3 |
| Nonzero base/prescribed BC | `unsupported-eigen-boundary` | 3 |
| Model-affecting exclusion / unsupported element | `unsupported-keyword` / `unsupported-element-formulation` / `unsupported-mixed-element-model` | 3 |
| Invalid geometry/section/material | 기존 model code; mass27-point invalid는 `invalid-shell-mass-geometry` | 4 |
| Global finite n=0 / N>n | `empty-eigenproblem` / `insufficient-finite-modes` | 4 |
| Analytic/null/positive mass or conditioning 실패 | `invalid-eigen-mass-space` / `eigen-mass-conditioning` | 5 |
| Index/storage/allocation/FEAST/count/budget/negative/validation 실패 | [M2 diagnostic mapping](io.md#io-mapping--m2-backend와-failure-lifecycle) | 5 |
| Candidate/write/close/self-check/replace/log/lock 실패 | 기존 output category와 [M2](io.md#io-mapping--m2-backend와-failure-lifecycle) | 6 |
`NaN/Inf` rho는 nonfinite model value(4)로 분류하고 그 외 malformed token은 syntax(3)다.
같은 실패를 여러 code로 중복 보고하지 않고 첫 발견 원인을 유지한다. Fatal 뒤 solve/commit을
실행하지 않는다. CLI usage2/success0과 stderr format은 기존 공통 계약을 유지한다.
### 공개 근거와 적용 한계
2026-09-06 공식 Abaqus 2025 문서를 `web.open`으로 확인했다. 사실은 syntax/외부 의미이고,
위 exact subset/default/warning policy는 승인된 FESA 요구에 대한 I/O mapping이다.
| Source | Locator와 사용 |
| --- | --- |
| [DENSITY](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-density.htm) | Data lines 1~2와 optional dependencies; constant rho 및 ML^-3 차원. 온도·distribution 지원은 포함하지 않음 |
| [FREQUENCY](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-frequency.htm) | Optional parameters와 Lanczos data line 1~7. Source defaults·bounds/shift 공란을 구분; FESA Lanczos 내부 동작의 근거가 아님 |
| [STEP](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-step.htm) | NAME/NLGEOM/PERTURBATION. 선행 history 전달은 제외 |
| [RESTART](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-restart.htm) | WRITE/FREQUENCY=0 및 no-data. Restart 지원을 주장하지 않음 |
| [OUTPUT](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-output.htm) | Output selection root |
| [NODE OUTPUT](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-nodeoutput.htm) | FIELD와 VARIABLE=PRESELECT |
| [ENERGY OUTPUT](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEKEYRefMap/simakey-r-energyoutput.htm) | HISTORY와 VARIABLE=ALL; 새 modal energy output 요청으로 확대하지 않음 |
| [Input Syntax Rules](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEMODRefMap/simamod-c-inputsyntax.htm) | Keyword/data/256-byte/continuation convention; FESA bounded 차이와 기존 정책은 I1이 권위 |
질량 정식화·private parser/model·solution algorithm·ODB internals의 동등성을 추론하지 않는다.
## MITC4 eigen authoritative HDF5 schema
- Feature ID: `mitc4-shell-feast-eigen`
- Input contract revision: `r2`
- 기본 보고서: [io.md](io.md#io)
- 수학: [E1~E8](formulation.md#formulation-eigen), [V1~V6](formulation.md#formulation-verification)
- Numerical authority: [C1~C6](numerical-review.md#numerical-review-controls)
### O1. Container, version과 공통 규칙
공식 결과는 input lexical sibling `_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=`, `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=;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.md#numerical-review-controls--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을 명시적으로 거부한다.
## MITC4 eigen 책임·실패·비교 대응
- Feature ID: `mitc4-shell-feast-eigen`
- Input contract revision: `r2`
- 기본 보고서: [io.md](io.md#io)
- 입력 원본: [io-input.md](io.md#io-input); 영속 schema 원본: [io-schema.md](io.md#io-schema)
### M1. Input에서 equation/result까지
아래는 implementation-neutral 책임 계약이며 정확한 C++ 타입/파일 분해는 Planning 소유다.
현행 [Domain](../../include/fesa/model/domain.h),
[model records](../../include/fesa/model/model_types.h),
[syntax records](../../include/fesa/io/abaqus/input_syntax.h),
[AnalysisModel](../../include/fesa/analysis/analysis_model.h)의 수명·의존성을 따른다.
| 경계 | 소유·전달할 최소 의미 | 금지되는 의미 혼합 |
| --- | --- | --- |
| Input adapter | 원본 path/content identity, keyword/parameter/data raw text와 line; validated density/step/options/count, unresolved targets | TXT row수로 N 생성, source enum으로 actual backend 변경 |
| Domain | Topology/source instance/labels, E/nu, section/t, optional material rho, initial director/frame, 유일 frequency 정의와 resolved homogeneous BC, warnings/provenance | Mutable mode/equation/vendor handle 소유 |
| Frequency definition | Raw/canonical source step, source option presence/effective values, count data N, source locations, procedure=linear-frequency | Static increment/time/frame state를 frequency count에 재사용 |
| AnalysisModel | Domain lifetime 아래 활성 shells/materials/sections/BC/frequency 정의의 const non-owning view | Domain copy 또는 새로운 geometry/material ownership |
| DofManager | Source node×UX/UY/UZ/URX/URY/URZ, full/free/constrained injection과 stable equation indices, scatter/sparse pattern | Element/Node 내부에 equation ID 저장 |
| Element/assembly | M1~M10 consistent/moments snapshot→nodal lumped blocks, r2 K contribution, source ordered reduction. 같은 source scatter와 실제 BC | Global scalar row lumping, artificial drilling mass, source S4R의 별도 kernel |
| Eigen procedure | Candidate workspace/state, [E1~E8](formulation.md#formulation-eigen) 순서, analytic rank/positive/null projection, whitening, actual FEAST, all-c validation, N개 global 복원/결과와 commit | 기존 LinearStaticAnalysis::Run에 eigen lifecycle 누적, pretrained/preloaded state, static reaction/modal stress 복구 |
| Private backend | C5/C6 controls, checked CSR/index conversion, vendor resources/thread guard, actual values/vectors/count/status와 call history | MKL_INT/HDF5/Win32 types 또는 vendor headers를 public solver core에 노출 |
| Result/Output adapter | Validated source/global modal pair와 O1~O5 serialization/self-check/replacement | Near-zero clamp, physical 수치 또는 identity 재계산으로 실패 은폐 |
Density/property lookup은 element마다 확정된 material identity를 사용한다. Consistent 원본을
lumped 저장으로 덮어쓰지 않고 element-wise snapshot+moments로 검사 가능하게 한다.
Full dense global MC나 일반 dense Schur는 필수가 아니다. 실제 global BC를 먼저 적용하고
director null은 [E2](formulation.md#formulation-eigen--e2-nullpositive-basis를-node마다-결정)의 exact intersection으로만
결정한다. Tiny positive mass는 정식화/NR conditioning 실패이며 input 지원에서 제거하지 않는다.
Source `(instance_name, numeric label)`과 raw label spelling은 전체 경로에서 보존한다.
Internal row order는 기존 identity-instance expansion/declaration order이며 DOF order는 고정이다.
Renumbering은 geometry/connectivity/BC를 같이 대응하여 검사한다. 숫자가 우연히 같은
source label/internal ID/equation ID를 비교키로 대체하지 않는다. 새로운 source order의 결과를
행 위치끼리 비교하거나 repeated eigenspace의 특정 vector 방향을 동일하다고 요구하지 않는다.
Accepted eigen state는 input/source step identity, N개의 paired raw scalar/global vector,
source mapping 및 전체 c의 validation/call evidence만 소유한다. Domain·AnalysisModel·DOF
정의와 수명 관계를 복사로 숨기지 않는다. Persistent N vectors로 같은 입력의 K/ML를
재조립해 constraint/normalization/원 residual을 다시 검사할 수 있어 REQ-018을 충족한다.
반복군의 개별 벡터 비유일성과 외부 mode-shape 비교 제외는 유지한다.
### M2. Backend와 failure lifecycle
FEAST fpm/interval/seed/thread/storage와 내부 수치 한계의 유일 원본은
[NR C1~C6](numerical-review.md#numerical-review-controls)다. I/O나 CLI에서 parameter override를 만들지 않는다.
Source N, reduced finite dimension n, prefix count, allocated m0, returned m, validated c,
public N을 각각 유지한다. 전체 c eigenpairs의 full original free residual/ML Gram/energy 및
endpoint/count consistency 뒤 첫 N개만 선택한다. Wrong mass·count·residual을 tolerance나
다른 solver로 우회하지 않는다.
| Failure | Code / exit5 | 보존할 context |
| --- | --- | --- |
| Checked CSR/index/capacity 산술 실패 | `eigen-index-overflow` 또는 `invalid-eigen-csr` | n/nnz/N/m0, 실패한 bound와 stage |
| Allocation 실패 | `eigen-allocation-failed` | allocation 역할·checked requested bytes; N 축소 없음 |
| FEAST non-success / forbidden retry | `eigen-feast-failed` | raw info, count/solve kind, interval/m0, C5 허용 재시도 여부 |
| Count/returned m/monotonicity·endpoint mismatch | `eigen-count-inconsistent` 또는 `eigen-endpoint-separation` | actual count history와 마지막 certified bracket |
| 유한 budget 소진 | `eigen-search-budget-exhausted` | count/solve attempts·마지막 valid bracket; optimization fallback 가능 여부는 C5 그대로 |
| Significant negative spectrum | `negative-eigenvalue-spectrum` | raw lambda/mu/s, mode rank, C3 threshold |
| Nonfinite/underflow conversion 또는 invalid frequency | `invalid-eigenvalue-result` | raw scalar·stage·source step |
| Raw pair/Gram/원 free residual/energy 검증 실패 | `eigenpair-validation-failed` | metric name, observed value, C3 limit, solver column/rank; failed raw values를 accepted result에 넣지 않음 |
위 code는 기존 FailureCategory::kSolver로 전달하며 새로운 exit category를 추가하지 않는다.
Model/preflight 오류는 [I6](io.md#io-input--i6-fail-closed-validation과-diagnostics)를 따른다.
Eigen backend failure의 returned Status는 실패까지의 call history를 message에 round-trip
decimal/ordinal 순으로 포함한다. 한 leading fatal diagnostic에 history를 부속하고 성공 count
call에 fictitious error severity를 붙이지 않는다. CLI는 기존 ordered stderr diagnostic 경로로
반환하며 caller는 Status에서 evidence를 읽을 수 있다. Allocation failure 시 추가 문자열
allocation을 보장할 수 없는 한계는 기존 best-effort stderr 범위를 따른다.
Public CLI는 기존 `fesa.exe `뿐이다. Output override 부재, `.inp` lexical
stem/대소문자/여러 dot/path 규칙, same-derived-pair nonblocking exclusive lock와 usage2는
[공통 lifecycle §7.1](../nonlinear-static-newton-raphson/io.md#71-public-output-names-log-and-lifecycle)을 유지한다.
1. CLI usage validation→lexical output pair→exclusive ownership 뒤 `_log.txt`를
open/truncate한다. Non-Newton eigen은 log에 Newton iteration/FEAST 행을 만들지 않는다.
정상 log는 기존 계약대로 zero-byte다. Log open/close failure는 output exit6다.
2. Input/model/eigen solve와 all-c validation은 candidate에 수행한다. Existing accepted
state와 final HDF5는 건드리지 않는다. Controlled failure는 기존 state와 final hash를 보존한다.
3. Successful candidate를 준비하고 log close 성공을 확인한다. 같은 directory에 exclusive-create
private HDF5 candidate를 write/flush/close/reopen/self-check하고 모든 handle을 닫는다.
4. Final replacement가 성공한 뒤 **이미 준비된 state의 no-fail swap**을 수행한다.
Swap에 allocation/validation/fallible callback을 남겨 두지 않는다. 순서는 [E8](formulation.md#formulation-eigen--e8-mode-identity-normalization과-상태)다.
5. Write/flush/close/reopen/self-check/replace 실패는 exit6이며 이전 final/state를 보존한다.
Failed candidate는 authoritative가 아니다. 정리는 best effort이고 다른 run의 파일을 지우지 않는다.
Current log는 rollback하지 않는다. 잠금 실패는 log/final도 변경하지 않는다.
과거 final이 없으면 controlled failure 후 final도 생성하지 않는다. Directory collision,
nonregular destination, lock/replacement refusal는 성공으로 처리하지 않는다. Process crash나
power-loss 전체 원자성을 약속하지 않는다. Reference artifact는 읽기 전용이며 solver의
새 HDF5/log는 별도 generated output이다. Reference 원본을 덮어쓸 output path는 없다.
### M3. 원본 TXT grammar와 deterministic Value projection
Case `shellNL-eigen-meshfine`의 input/TXT 경로·hash와 logical quantity/family 원본은
[reference-model](reference-model.md)이다. TMP/CSV 변환·filename alias·추가 provenance 파일을
reference readiness 조건으로 만들지 않는다. TXT에는 source step이 없으므로 **지정 input의
유일한 source frequency step Step-2**를 연결한다. ODB storage frame index는 추정하지 않는다.
각 LF/CRLF logical line에서 공백-only 행만 생략한다. 모든 다른 행은 아래 full-match다.
`ws`는 ASCII space/tab 0개 이상, `ws1`은 1개 이상이며 literal의 대소문자는 정확하다.
```text
number := [+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[Ee][+-]?[0-9]+)?
id := [0-9]+ # positive checked decimal integer
row := ws 'Frame:' ws1 'Mode' ws1 id ':' ws1 'Value' ws '=' ws number
ws1 'Freq' ws '=' ws number ws1 '(cycles/time)' ws
```
Header/footer, BOM, comment, 잘못된 Value/Freq label·추가 token·malformed number는 schema
failure다. `Value`는 finite binary64로 full conversion하고 overflow/underflow parsing error를
거부한다. NaN/Inf spelling은 grammar부터 실패한다. `Freq`는 숫자 token 구조만 검사하고
수치 변환/물리 일치/오차 비교에 사용하지 않는다. 반올림된 Freq로 Value를 재계산하지 않는다.
같은 숫자의 다른 mode ID는 정상이며 같은 numeric ID의 재등장은 duplicate다.
다음 순서를 tolerance 전에 완료한다.
1. 지정 input/TXT와 O1 eigen HDF5의 존재·source_input_identity·procedure/schema/unit/mass/
actual backend를 검사한다. `mass_variant=derived-lumped`, `mass_origin=consistent-moment-row-sum`,
normalization mass 및 runtime FEAST metadata가 필수다. 다른 mass의 좋은 오차를 선택하지 않는다.
2. Input의 유일 source step/N=10을 직접 확인하고 HDF5 source name/요청수/공개수에 대응한다.
TXT row count에서 N을 추정하거나 HDF5 내부 c를 공개 모드 수로 사용하지 않는다.
3. TXT 모든 nonempty row를 먼저 parse하면서 duplicate를 검사한다. Dictionary overwrite
또는 malformed-row skip은 금지다. Required identity는 양쪽 모두 정확히 mode1..10이다.
4. HDF5 `modes`의 field/type/shape/단위/순서와 모든 eigenvalue의 finiteness를 확인한다.
Wrong quantity/mass/schema·missing/extra/duplicate/nonfinite를 먼저 실패시킨다.
5. 유일 source key로 join한 뒤 mode ID ascending으로 projection한다. TXT 행 재배열은
허용하지만 HDF5 sort contract 위반은 reader가 재정렬하여 숨기지 않는다.
Projection row는
`(case_id,source_step_name,mode_id,component=Value,reference_value,fesa_value)`다.
FESA value는 `/steps/Step-1/eigen/modes.eigenvalue`만 사용한다. Diagnostic all-c table,
frequencies/vectors 또는 static fields를 fallback으로 읽지 않는다. 현재 component는 scalar
eigenvalue=`omega^2`, `time^-2`, coordinates=`scalar`, impact=`blocking`이다.
### M4. 판정·보고와 기존 static의 역할
Family는 `(case,source step,modal-frame=mode_id,quantity=eigenvalue,dimension=time^-2,
coordinates=scalar,impact=blocking)`다. **10개의 singleton family**에
[common-reference-tolerance](../TOLERANCE.md)를 그대로 적용한다. 각 family의
`S=max|r|`, `B=0.01S`, near-zero inclusive row branch 또는 5% relative row branch와
1% relative RMS를 모두 계산한다. 현재 양수 singleton은 실효 mode별1%다.
S=0이면 exact-zero FESA만 성공이며 불일치는 `zero-reference-scale-nonzero-error`다.
Source modal frame이 다르면 한 table에 저장되어도 family를 합치지 않는다.
Comparator report는 input/reference/result identity와 freshness evidence, prechecks,
family/source key/component/count/S, raw r/f/error, 적용 branch·row verdict, RMS/verdict,
blocking failure와 전체 verdict를 mode order로 남긴다. Undefined zero-scale metric은 named
state로 표현하고 NaN/Inf나 absolute floor를 넣지 않는다. CSV view가 필요하면 이 projection을
HDF5에서 추출한 보조 artifact라고 표시하며 공식 output/원본 reference를 대체하지 않는다.
기존 static의 r2 재검증은 [Requirement portfolio](requirements.md#requirements-evidence--필수-회귀-포트폴리오와-identity),
[NR C7](numerical-review.md#numerical-review-controls--c7-승인된-정적-회귀-기준), [C26](numerical-review.md#numerical-review-cases)을 따른다.
기존 linear source node/static frame와 nonlinear factor-one accepted-state identity를 유지한다.
U1/U2/U3 length/global blocking, UR1/UR2/UR3 rotation warning-only는 기존 common families다.
Nonlinear RF1/RF2/RF3·physical spatial RM1/RM2는 source-key/finite/inventory/error 보고를
유지하는 review-only다. RM3/stress와 eigen vector는 새 external gate가 아니다.
Internal force/moment equilibrium은 별도의 blocking physical evidence다.
`shellnl-meshfine-02-s4-final`의 별도 post-closure 역할도 유지한다.
과거 cache/static 수치를 새 binary의 fresh solve로 표시해서는 안 된다.
### M5. 구현·test obligations와 requirement 연결
아래 표의 `nn` 등 fixture 수를 제외한 threshold는 [NR cases/controls](numerical-review.md#numerical-review-cases)의
원본을 사용한다. Parser/mapper/schema/comparator의 실제 tests는 Planning/Implementation 소유다.
| Obligation ID | 필수 positive/negative 검증 | NR cases |
| --- | --- | --- |
| IO-T01 | 원본 unchanged input의 729 nodes/676 S4, source Step-2/N10, rho2700/t0.5, source options/no-op warnings와 실제 FEAST 선택. S4R source-only 변경도 같은 semantic physical path | MFE-C23 |
| IO-T02 | 두 material·두께의 element-section-density 연결, missing/duplicate/unresolved/0/negative/NaN/Inf/temperature/dependencies/extra row·field, section/geometry/27-point invalid 거부; static density 부재 허용 | MFE-C06, MFE-C07, MFE-C23, MFE-C26 |
| IO-T03 | N의 blank/0/negative/fraction/overflow, fields2~7에 nonempty0, eighth empty field, duplicate parameter, unsupported enums/procedure/preload/load/damping/acoustic/mixed/非영 BC 거부 | MFE-C07, MFE-C13, MFE-C23 |
| IO-T04 | Source labels/instance/set renumbering·중복/모호함, partial rotations/fullfree/fullclamp/drill-only/fully constrained source mask 복원; tiny nonzero director rank 보존·conditioning 실패, n0/N>n 명시 실패 | MFE-C06, MFE-C13, MFE-C14, MFE-C24 |
| IO-T05 | O1~O5 schema round-trip, input byte identity, N/c/source step/rank/units/actual backend/mass pairing, N vectors의 원 residual·normalization 재현. Near-zero positive/negative/exact0/±threshold 및 lambda conversion 경계 | MFE-C16, MFE-C19, MFE-C24 |
| IO-T06 | Invalid index/CSR/SPD/parameter/capacity/count/endpoint/NaN/Gram/residual/budget; actual FEAST known zero/repeated/cluster cases의 all-c history와 returned-N 분리. Output diagnostic unavailable와 raw λ 보존 | MFE-C17, MFE-C18, MFE-C19, MFE-C21, MFE-C22 |
| IO-T07 | 이전 accepted state/final hash를 준비하고 solve/validation/log/lock/write/flush/close/reopen/self-check/replace 실패를 각각 주입. 처음 실행의 실패에서 final 미생성. 성공 final 후 no-fail state swap | MFE-C24 |
| IO-T08 | TXT reorder/equal Value distinct modes 허용. Missing/extra/duplicate/nonfinite/malformed/wrong field/step/quantity/units/mass/backend/schema 실패를 tolerance 전에 확인. Freq 변화가 Value 판정을 바꾸지 않음 | MFE-C25 |
| IO-T09 | 공통 policy의 inclusive 1% RMS·5% row 경계와 양옆, generic near-zero \|r\|=B 경계·zero-scale 양성/음성. Singleton이므로5% row pass라도1% RMS fail임을 확인 | MFE-C25 |
| IO-T10 | Density 없는 기존 linear/nonlinear input·model/static output reader 불변, r2 scale 영향 portfolio를 fresh binary로 재검증. Mode-shape reference 미요구 | MFE-C26, MFE-C27 |
| IO-T11 | 세 반복의 exact sparse/row/diagnostic order 및 scalar/projector C4 기준. RED→observed failure→GREEN→focused/full MSVC x64 Debug 검증·새 warning 없음·fresh reference identity/hash | MFE-C27 |
Coverage ID 접두사는 모두 `FEM-REQ-MITC4-EIGEN-`다. 아래 표는 requirement 원문을 대체하지
않고 I/O의 기여와 다른 owner evidence를 구분한다.
| Requirement suffix | I/O 연결·verification obligation |
| --- | --- |
| 001 | I2/I4/M1; IO-T01/T03 |
| 002 | I2/O2 source type와 r2 stabilization identity; IO-T01/T10; physical kernel C01/C08/C12는 해당 owner |
| 003 | I3/O2 densities; IO-T02 |
| 004 | I2/I6/M1; IO-T02; geometry oracle C01/C02는 NR 원본 |
| 005 | M1 consistent snapshot 의미, O2 mass_origin; C01~03 구현 evidence |
| 006 | M1/O4 node rank와 restored vector; IO-T04; inertia/null C01/C03/C11 |
| 007 | M1 source/DOF/reduction ordering; IO-T04/T11 |
| 008 | M1/O4 analytic counts/conditioning, M2; IO-T04/T05; C15 spectrum oracle |
| 009 | I4/O2 N·n·c/O3 rank; IO-T03/T04/T06 |
| 010 | O3 stable paired sort/cluster identity, M3 join; IO-T05/T08/T11 |
| 011 | I4/O2/M2 actual mass/backend discriminant; IO-T01/T05/T06 |
| 012 | I6/M2/O4 validity and bounded failure; IO-T06/T07 |
| 013 | O3 vectors/O4 all-c metrics; IO-T05/T06; C11/C16~18 independent evidence |
| 014 | M1 units/source transformation/O3 replay; IO-T04/T05; C01~05/C08/C11/C20 physics |
| 015 | I4/I5/O2 source_records; IO-T01/T03 |
| 016 | I2~I6/M2; IO-T02/T03/T06 |
| 017 | O1~O5/M3 authoritative additive schema; IO-T05/T08 |
| 018 | M1/O3 persistent N vectors/source replay; IO-T04/T05; external shapes 제외 |
| 019 | M2 candidate/commit/log lifecycle; IO-T07 |
| 020 | M3/M4 Value-only + 별도 static policy; IO-T08/T10 |
| 021 | O5/M3 full prechecks; IO-T08 |
| 022 | M4 공통 family/policy/report; IO-T09 |
| 023 | IO-T11; 실행 계획/RED/GREEN/full 증거는 Planning/Implementation 소유 |
| 024 | I3/M4 existing static compatibility/portfolio; IO-T10/T11 |
| 025 | M5 coverage + 동일 r2 handoff; Physics/Release closure 소유권 유지 |
| 026 | M1 consistent→lumped/O2 mass_origin; C01~05 independent mass evidence |
| 027 | O2 stabilization_rule/M4 static 역할; IO-T10; C08~12/C26 물리 검증 |
### 정적 감사 evidence
실제 조사 명령은 `Get-Content`, `rg --files`, scoped `rg -n`, `web.open`이었다.
입력 keyword inventory와 TXT 10개 행을 읽었고 numerical quantity/formulation 계산을
재실행하지 않았다. 한 번의 `rg docs/shell-surface-pressure/io*.md`는 잘못된 directory/glob로
exit1이었고 `rg --files docs`로 실제 `docs/shell-surface-pressure-load/io.md`를 확인해
읽기 전용 대조를 완료했다(exit0). 이 검색 오류는 feature numerical failure가 아니다.
최종 감사 `python -B -` here-script는 exit0으로 owned4 metadata/66개 relative links/
requirement suffix1..27, reference10 rows/full grammar/finite Value/ID1..10 및 두 원본 SHA-256
일치를 확인했다. `git diff --check -- docs/mitc4-shell-feast-eigen/io.md
docs/mitc4-shell-feast-eigen/io-input.md docs/mitc4-shell-feast-eigen/io-schema.md
docs/mitc4-shell-feast-eigen/io-mapping.md`도 exit0이었다. 아직 untracked인 owned 문서는
별도 Python whitespace/Markdown table 검사로 확인하며 diff만으로 내용 검증했다고 하지 않는다.
실제 final audit 결과와 owned hashes는 I/O handoff에 보고한다.
이는 문서·원본 inventory 검증이며 parser/comparator 구현 test 또는 실제 수치 비교가 아니다.
CMake/CTest/Harness/FEAST/외부 solver는 이 문서 단계에서 실행하지 않는다.