# 외부 이용 계약 ## CLI와 파일 호출은 `fesa.exe `의 한 입력뿐이다. 빈 인자·추가 인자·option·`.inp` 외 확장자는 거부한다. 확장자의 대소문자는 구별하지 않으며 `--output`은 받지 않는다. 상대 경로는 호출 cwd 기준으로 lexical normalization한다. Symlink·junction·short name을 resolve하여 출력 위치를 바꾸지 않는다. 입력의 lexical sibling에 `_results.h5`와 `_log.txt`를 만든다. 결과 경로에 `.fesa.lock`을 붙인 lease가 같은 출력의 동시 쓰기를 막는다. Lease는 handle 종료 때 삭제되며 생성 실패·점유는 저장 실패다. 정상 candidate의 기록·검사· close 뒤 최종 HDF5를 교체한다. 중간 실패에서는 이전 최종 HDF5를 보존한다. 로그는 실패 시에도 갱신될 수 있으므로 HDF5 존재만으로 이번 실행 성공을 판단하지 않는다. | Exit | 이용자에게 보이는 결과 | | ---: | --- | | 0 | 선택 해석과 최종 저장 성공. Warning이 남을 수 있다. | | 2 | 인자 또는 입력 확장자 오류. | | 3 | 읽기·문법·미지원 입력 실패. | | 4 | 모델 의미·조합·유효성 실패. | | 5 | 해법 실패. | | 6 | Lease·로그·HDF5 저장 실패. | stderr 진단은 결정적 순서의 tab 구분 `severity=...`, `code=...`, `file=...`, `line=...`, `keyword=...`, `entity_identity=...`, `message=...` 필드다. 빈 source 필드도 남긴다. Backend 고유 번호를 CLI exit로 직접 반환하지 않는다. ## 입력 파일 Physical `.inp` 하나를 읽는다. 종결자 제외 한 줄 256 ASCII bytes 이내이며 printable ASCII와 tab, LF/CRLF·빈 줄·`**` comment·keyword parameter continuation을 처리한다. Keyword·parameter·enum·name lookup은 ASCII case-insensitive지만 원문·행 번호를 보존한다. 같은 값이라도 중복 parameter는 거부하며 comma 사이의 빈 field를 지우지 않는다. 현재 identity instance의 part/assembly와 단일 step을 기본으로 한다. INCLUDE·instance transform· contact·MPC·비탄성·beam/shell 또는 shell/solid 혼합은 공개 subset 밖이다. 미지원 model-affecting keyword를 조용히 무시하지 않는다. 출력 요청의 warning no-op은 procedure별 allowlist에 한정하며 mandatory 결과를 선택·억제하는 수단으로 사용하지 않는다. | Family | 현재 입력의 요점 | 거부하는 대표 사례 | | --- | --- | --- | | B33 정적 | GENERAL section·등방 탄성·DOF1–6 BC와 CLOAD | B31·I12 비영·beam DLOAD | | MITC4 정적 | S4/S4R·centered 일정 두께·등방 탄성·DOF1–6 | Composite·offset·drill 방향 aggregate nodal moment | | MITC4 비선형 정적 | NLGEOM=YES·단일 STATIC·time period=1·고정 증분 | 자동 cutback·amplitude·restart | | Shell pressure | Assembly-level ELEMENT SURFACE의 SPOS/SNEG와 signed DSLOAD P | DLOAD·edge/body·unknown parameter·dynamic/thermal로 전용 | | Shell frequency | 양의 DENSITY·homogeneous shell·MASS normalization·양의 정수 N | 비영 BC·load·nonempty bounds/shift·preload | | Shell HHT | NLGEOM=YES·DYNAMIC DIRECT·영 BC/초기값·일정 global 병진 CLOAD | 회전 CLOAD·follower·시간변화 BC·restart | | Hex8 | Solid-only C3D8·SOLID SECTION·DOF1–3·frequency/HHT의 양의 DENSITY | 비영 회전 BC·값 0을 포함한 회전 CLOAD | | DS4 thermal | 일정 양의 두께·k/rho/c·단일 HEAT TRANSFER·온도 초기값·DOF11/15 BC와 CFLUX | 내부 station 직접 BC/CFLUX·시간변화·열구조 연성 | Shell HHT schedule은 `double(N)*h==T`, `N<=INC`를 만족하는 고정 격자이며 INC 기본값은 100이다. Hex8 HHT는 TABULAR step-time relative CLOAD amplitude의 선형 보간과 끝값 유지를 지원하지만 static/BC amplitude·TOTAL TIME·smoothing으로 확대하지 않는다. Thermal은 마지막 간격만 줄이며 `dt>T_end`면 한 증분이다. 서로 다른 시각 계약을 같은 반올림 규칙으로 통합하지 않는다. ## 결과 식별과 위치 HDF5는 feature identity·version·procedure를 조합하여 읽는다. 숫자는 fixed-width little-endian, 문자열은 UTF-8이다. Compound는 field 이름·형식·extent로 읽으며 C++ 구조체 padding에 의존하지 않는다. Source input identity는 실제 읽은 bytes에 결속된다. Node row를 source label로 보지 않고 model의 source inventory로 대응시킨다. `Step-1`은 storage slot이며 입력 step 이름이 아니다. Frequency source step은 step attribute, HHT·thermal은 metadata에서 읽는다. 기존 static에 source step 이름이 별도 저장됐다고 가정하지 않는다. | Family | 식별과 공개 결과 | | --- | --- | | Linear static | Schema0은 `analysis_procedure`가 없어도 유효하다. `/steps/Step-1/frames/0`에 nodal displacement/reaction과 요소별 복구량을 둔다. | | Nonlinear shell static | Schema1. Accepted frame과 load factor·nodal displacement/reaction·4 GP shell 복구량을 둔다. 실패 iteration은 frame이 아니다. | | Shell frequency | Schema0과 `eigen_schema_version=1`, procedure=`linear-frequency`. `/steps/Step-1/eigen/modes`는 ID·raw eigenvalue·classification·cluster를 갖고 vectors는 `[N,node,6]`이다. 검증량은 공개 N 밖을 포함한 전체 반환 pair를 대상으로 한다. | | Shell HHT | Feature/procedure=`hht-implicit-dynamics`, schema2. Metadata의 mass=`nodal-lumped-kinetic`, time integration=`reduced-coordinate-HHT-with-physical-rate-reconstruction`, acceleration=`physical-endpoint-and-auxiliary-separated`를 확인한다. | | Hex8 | Feature=`hex8-structural-analysis`, schema1, mass=`lumped-reference`. Nodal 성분은 UX/UY/UZ 3개, stress/strain은 `[E,8,6]`, eigen vectors는 `[modes,N,3]`이다. | | DS4 thermal | Feature=`shell-transient-heat-transfer`, schema1, procedure=`uncoupled-transient-heat-transfer`. Temperature `[N,5]`, reaction heat rate는 constrained inventory의 `[P]`, heat flux는 `[E,4,6,3]`이다. | Shell stress는 4 midsurface GP 각각의 bottom/middle/top S11/S22/S12이며 nodal average가 아니다. Beam endpoint action·section resultant·section point stress도 서로 다른 위치다. Hex8 stress는 global Cauchy이고 strain은 infinitesimal 또는 Green의 tensor shear다. IntPt 순서는 `---,+--,-+-,++-,--+,+-+,-++,+++`로 node 순서와 다르다. Shell HHT는 nodal `[N,6]`의 q/v/physical a/public A와 `[N,3]` spatial angular rates를 구별한다. 공개 A의 의미는 `full-chart-HHT-filter-combination-not-predictor-driver`다. Generalized force/reaction과 spatial reaction을 구별한다. 과거 full-coordinate schema1은 그 의미로 읽고 marker 보충이나 schema2 재표시로 재사용하지 않는다. Thermal 온도 성분은 NT11..NT15, zeta=`[-1,-.5,0,.5,1]`이다. Flux는 4 면내점과 `[-1+,-.5,0-,0+,.5,1-]`의 6 trace를 가진 global QX/QY/QZ다. 초기 frame은 time=delta=0이며 temperature만 있고 flux/reaction dataset은 없다. 완료 frame은 실제 양의 delta, constraint mask와 reaction inventory를 보존한다. P=0인 빈 inventory를 누락으로 취급하지 않는다. Schema·필수 field·dtype·shape·inventory·finite 불일치는 읽기나 비교 실패다. 누락을 0·NaN·기본 marker로 채워 이용하지 않는다. Mode shape는 응답 변위가 아니며 frequency와 raw lambda도 다른 양이다. 작은 음의 lambda를 abs/clamp하여 raw 값을 바꾸지 않는다. ## C++ consumer와 비교 도구 공개 interface는 `include/fesa`의 backend-neutral 값과 `Status`/`Result`를 사용한다. Domain을 빌리는 AnalysisModel과 adapter는 참조 대상의 유효 수명을 넘겨 사용하지 않는다. Procedure는 family별 completed outcome을 반환하며 로그 close와 최종 파일 공개는 호출자가 조정한다. Vendor handle이나 private header를 사용하는 consumer는 공개 경계 밖이다. Hex8/HHT Python 비교기는 입력·reference·HDF5를 읽고 지정한 JSON report만 쓴다. Solver를 기동하거나 원본을 수정하지 않는다. 입력 부재·hash 충돌·schema/identity/finite 불일치는 실패이며 합성 fixture 통과는 실제 모델 성공을 뜻하지 않는다. ## Shell HHT iteration 로그 독자 Frame0과 직접 v1 writer는 기존 `hht-log-v1` 의미를 유지한다. 양의 reduced-coordinate MITC4 HHT 증분은 `hht-log-v2`, `policy_id=abaqus2025-field-on-fesa-v1`을 기록하므로 한 파일 안의 각 record에서 schema를 읽는다. v1 숫자를 v2 field 값으로 재해석하지 않는다. V2의 고정 키 순서·분기·단위·평균·threshold는 [field 수렴 정식화](abaqus-tolerance/formulation-convergence.md#로그-소비-계약)를 따른다. `strict_` 진단은 기존 힘/모멘트 residual과 무차원 q/v/a/A correction이며 종료 기준이 아니다. UTF-8 LF 한 줄과 tab 구분 key=value를 사용한다. 첫 `=`만 구분자이며 값의 backslash, tab, LF, CR은 각각 `\\`, `\t`, `\n`, `\r`로 escape한다. 미평가 numeric/bool은 literal `not-evaluated`, 평가 bool은 `0`/`1`이다. 독자는 중복·필수키 누락·알 수 없는 branch/policy/schema·NaN/Inf를 오류로 처리한다. 숫자는 locale-independent binary64 round-trip 표현이며 step은 raw source 이름이다. 실패 전 평가된 부분값만 보존한다. `field_pass=1`은 후속 acceptance 통과를 뜻하지 않는다. `accepted=1`도 최종 HDF5 성공을 뜻하지 않으며 CLI exit와 완결 결과 identity를 함께 확인한다. 실패 증분은 accepted frame/private/flux history에 반영되지 않는다. 현재 acceptance transaction은 기존 accepted frame 전체를 가진 state를 지역 staged copy로 검증·commit한 뒤 로그 write/flush 성공 시 move로 공개한다. private/flux history도 같은 성공 경계에서만 교체한다. 이 최소 구현은 증분마다 누적 frame 수에 비례하는 copy 시간과 추가 메모리를 사용하므로 전체 실행의 복사 비용은 frame 수에 대해 이차로 증가할 수 있다. 후보의 실제 elapsed 측정에는 이 비용을 포함하며 출력 실패 안전성을 위해 이를 생략하지 않는다.