# 실행·입력·결과의 외부 계약 ## 호출과 파일 수명 ```text fesa.exe ``` 인자는 비어 있지 않은 입력 경로 하나다. 상대 경로는 호출 시 작업 디렉터리 기준으로 lexical normalization한다. 확장자 `.inp`는 대소문자를 구별하지 않는다. 옵션 형태 인자와 `--output`은 지원하지 않는다. Symlink·junction·short name을 resolve해 결과 위치를 바꾸지 않는다. | 산출물 | 경로와 의미 | | --- | --- | | 공식 결과 | 입력의 lexical sibling `_results.h5` | | 실행 로그 | 같은 위치의 `_log.txt`; 실패 진단을 포함할 수 있음 | | 쓰기 lease | 결과 경로에 `.fesa.lock`을 붙인 임시 소유권 파일; 정상 handle 종료 시 삭제 | 같은 output pair를 다른 실행이 점유하면 `output-busy`로 실패한다. Lease 생성 실패도 같은 output failure로 분류되므로 충돌 외에 OS 권한·디렉터리 상태도 확인해야 한다. 최종 HDF5는 완료 candidate의 기록·self-check·close 후 교체한다. 실패 시 이전 최종 HDF5를 보존하는 계약과 로그가 갱신될 수 있는 계약을 구별한다. 기존 파일의 존재가 새 실행 성공을 의미하지 않는다. | CLI exit | 의미 | | ---: | --- | | 0 | 선택된 해석과 최종 결과 저장 성공 | | 2 | 잘못된 인자·입력 확장자 등 usage 오류 | | 3 | 파일 읽기·문법·미지원 입력 오류 | | 4 | 모델 의미·구성·유효성 오류 | | 5 | 해법 실패 | | 6 | Output lease·로그·HDF5 저장 실패 | 진단은 stderr에 결정적인 순서로 출력된다. 한 줄은 탭으로 구분된 `severity=... code=... file=... line=... keyword=... entity_identity=... message=...` 필드를 갖고 빈 source 필드도 유지한다. Backend 원래 오류 번호를 새 CLI exit로 그대로 반환하지 않는다. 경고가 있는 성공도 가능하며 성공 HDF5의 진단은 warning이다. ## 공통 입력 규칙 현재 입력은 하나의 physical `.inp` 파일이다. LF·CRLF, 빈 줄, `**` comment와 keyword parameter continuation을 처리한다. Physical line은 종결자 제외 256 ASCII bytes 이내이며 printable ASCII와 tab을 사용한다. Keyword·parameter·enum·이름 lookup은 ASCII case-insensitive이고 원문 표기와 줄 번호는 보존한다. 같은 값의 중복 parameter도 실패다. Comma의 빈 field를 없애거나 data continuation으로 연결하지 않는다. 모델은 part의 node·element·set·section, identity instance를 둔 assembly, named material, 모델 경계조건과 하나의 해석 step으로 구성한다. Instance transform, `*INCLUDE`, 일반 contact·MPC·비탄성·혼합 beam/shell model은 현재 공개 subset이 아니다. | 입력 | 소비자가 지켜야 할 의미 | | --- | --- | | `*NODE` | Part 안의 `label,x,y,z`; label은 양의 정수, 좌표는 finite | | `*ELEMENT, TYPE=B33|S4|S4R, ELSET=...` | B33은 2개, shell은 서로 다른 4개 node label; source type과 내부 정식화 구별 | | `*NSET`·`*ELSET` | 허용 scope의 label 나열 또는 `GENERATE`; assembly set은 명시 instance에 결속 | | `*INSTANCE, NAME=..., PART=...` | 기존 part의 identity instance; transform data 미지원 | | `*ELASTIC` | 상수 등방 `E,nu`; `E>0`, `-1/` | | Frequency | schema 0에 `feature_id=mitc4-shell-feast-eigen2`, `analysis_procedure=linear-frequency`, `eigen_schema_version=1` 추가 | | HHT | `feature_id=hht-implicit-dynamics`, `analysis_procedure=hht-implicit-dynamics`, schema 1, 전체 accepted frame과 `/steps/Step-1/frames//` | `Step-1`은 storage slot이다. Frequency는 `/steps/Step-1`의 `source_step_name`, HHT는 `/metadata`의 `source_step_name`에서 원래 이름을 읽는다. 기존 선형·비선형 static은 canonical `step_name=Step-1`만 저장하므로 원래 source 이름이 HDF5에 별도로 있다고 가정하지 않는다. Float64와 fixed-width integer는 little-endian, 문자열은 UTF-8다. Compound는 field name/type/extent로 읽고 C++ struct padding에 의존하지 않는다. Source 입력 identity는 실제 읽은 byte의 identity를 포함한다. `/model/nodes`와 `/model/elements`의 source instance/label과 internal ID를 사용해 결과 row를 연결한다. Internal row 번호를 원본 label로 취급하지 않는다. Nodal displacement와 constraint mask의 6성분 순서는 `[UX,UY,UZ,URX,URY,URZ]`다. Reaction, 가속도 등 다른 dataset에는 각각의 component 이름이 있으므로 이 이름을 재사용하지 않고 단위·좌표·location·component attribute를 함께 읽는다. `/model/nodal_constraint_mask`의 free=0/constrained=1이 반력 해석의 기준이다. Static nodal `displacement`는 `[node_count,6]`이다. Linear nodal `reaction`의 constrained 성분은 반력, free 성분은 잔차 evidence다. Shell 결과의 기본 location 축은 면내 4점, 응력의 section 축은 bottom/middle/top 3점이다. Section resultant의 8성분은 `[N11,N22,N12,M11,M22,M12,Q13,Q23]`, 응력의 3성분은 `[S11,S22,S12]`다. 두 값의 단위와 위치를 서로 바꾸지 않는다. Beam 결과는 element endpoint와 단면 위치를 유지하며 node 평균 결과로 읽지 않는다. Frequency의 `/steps/Step-1/eigen/modes`는 N개 `mode_id,eigenvalue,classification,cluster_id` record이며 mode_id는 1부터다. `frequencies`는 raw eigenvalue가 비음수인 mode의 ID subset, `vectors`는 `[N,node_count,6]`의 mass-normalized mandatory projection이다. 이 벡터는 응답 변위가 아니다. 작은 음수 고유치를 abs/zero clamp하지 않으며 frequency 존재 여부를 eigenvalue와 구별한다. Static reaction·stress를 modal 결과에 요구하지 않는다. HHT frame은 0부터 N까지이고 `time=double(n)*h`다. `is_initial`은 n=0에만 참이다. Nodal `acceleration`과 `algorithmic_acceleration`, `angular_acceleration`, `generalized_reaction`과 공간 `reaction`은 구별된 dataset이다. Accepted frame과 source identity로 접근하고 failed trial이나 time 기반 nearest-neighbor matching을 사용하지 않는다. ## 외부 비교 Comparison은 필요한 instance·entity·location·component·step/frame을 일대일 대응한다. Missing·extra·duplicate·nonfinite는 tolerance 전에 실패한다. 같은 case/step/frame/ quantity/단위/좌표/판정 영향의 값만 한 family에 넣는다. Reference 값만으로 `S=max(abs(r_i))`, `B=0.01*S`를 정한다. `abs(r_i)<=B`이면 `abs(f_i-r_i)<=B`, 나머지는 상대오차 `<=0.05`를 요구한다. Family 전체의 `sqrt(mean((f_i-r_i)^2))/S<=0.01`도 만족해야 한다. S=0이면 모든 FESA 값도 exact 0이어야 하며 nonzero 오류는 `zero-reference-scale-nonzero-error`로 보고한다. 임의 floor는 없다. MITC4 eigen 첫 구현의 named policy `mitc4-eigen-first-implementation`에 한해 mode별 singleton Value family의 상대오차와 RMS를 모두 5%로 판정한다. 다른 family의 RMS 1%나 내부 eigen 검증 기준을 바꾸지 않는다. MITC4 U는 blocking, UR는 warning-only이며 warning도 결정적 순서로 남긴다. 사전검사 실패는 warning-only family에서도 전체 실패다. CSV view는 비교 보조 산출물이다. FESA 공식 output으로 대체하거나 reference 값을 보정하는 중간 형식으로 사용하지 않는다.