# Nonlinear Static Newton-Raphson I/O Definition ## 1. Metadata - feature_id: `nonlinear-static-newton-raphson` - source_requirement: `docs/nonlinear-static-newton-raphson/requirements.md` - source_requirement_sha256: `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2` - source_research: `docs/nonlinear-static-newton-raphson/research.md` - source_research_sha256: `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE` - source_formulation: `docs/nonlinear-static-newton-raphson/formulation.md` - source_formulation_sha256: `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0` - source_numerical_review: `docs/nonlinear-static-newton-raphson/numerical-review.md` - source_numerical_review_sha256: `9517E11804C45A6F3822D18821D52EA493AE20353C8FFAD61E960F4315977D01` - source_reference_model: `docs/nonlinear-static-newton-raphson/reference-model.md` - source_reference_model_sha256: `52D10B1D0C0500B295C5E48BCB3618B309D9696371B8070D4E3DCEE8D3D74CD3` - repository_policy: `AGENTS.md`, `docs/SOLVER_AGENT_DESIGN.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`, `docs/TOLERANCE.md` - status: `ready-for-coordinator-review` - owner_agent: `io-definition-agent` - date: `2026-08-23` - authoritative_output: input sibling `_results.h5` - diagnostic_log: input sibling `_log.txt` - hdf5_schema_version: `1` 이 문서는 승인된 Stage 5 I/O 계약만 정의한다. Parser, writer, comparison tool의 C++ API나 파일 소유권은 정의하지 않는다. FESA는 Abaqus와 독립적인 solver이며, 아래 `.inp` subset과 reference CSV mapping은 Abaqus full compatibility, Abaqus `S4/S4R` 내부 알고리즘, 적분, stabilization, 상태 갱신 또는 output recovery 동등성을 주장하지 않는다. FEM wiki 근거는 `Abaqus Input File Syntax`, `Abaqus Output Database and Results Files`, `Abaqus General and Linear Perturbation Steps`, `Abaqus Initial and Boundary Conditions`, `Abaqus Loads and Predefined Fields`, `Abaqus Beam and Shell Section Definitions`를 사용했다. 이 근거는 keyword/data/comment line, model/history data, output request, step/load/boundary/section 용어를 정렬하기 위한 보조 근거이며, 승인된 FESA 요구조건과 정식화가 우선한다. ## 2. Abaqus Input Scope - input_format: Abaqus input file (`.inp`) - supported Abaqus documentation source/version: 프로젝트 연구 bundle 및 local FEM wiki에 보존된 Abaqus 2024 input syntax/output vocabulary. 저장된 nonlinear reference input은 Abaqus/CAE Learning Edition 2024 생성물이다. - supported_analysis: no-prior-history baseline에서 시작하는 정확히 하나의 source `*STEP, NLGEOM=YES`와 하나의 nonlinear `*STATIC` procedure. - internal_element_formulation: source `S4`와 `S4R` 모두 materially linear, geometrically nonlinear Total Lagrangian `FESA-MITC4`에 매핑한다. - ordinary_unit_system: 사용자가 일관되게 선택한 미지정 단위계. FESA는 단위 추론이나 변환을 수행하지 않는다. - compatibility_disclaimer: 이 문서가 명시한 keyword 위치, parameter, data-line arity, validation rule, output mapping만 지원 범위다. `supported`는 syntax가 parsing되고 feature semantic model에 매핑된다는 뜻이다. `unsupported`는 명확한 diagnostic으로 거부한다. `ignored-with-warning`은 syntax와 소속 data line을 소비하고 warning을 남기지만 Domain, AnalysisModel, nonlinear procedure, mandatory HDF5 output 또는 reference comparison 의미를 바꾸지 않는다. `requires-user-decision` 항목은 없다. | keyword | policy | allowed location | required parameters and data grammar | semantic mapping | unsupported behavior | | --- | --- | --- | --- | --- | --- | | `*HEADING` | supported | optional top-level first keyword | parameter 없음; 다음 keyword 전까지 text row 0개 이상 | raw heading을 source metadata로 보존 | parameter, nested location, 두 번째 heading은 input error | | `*INCLUDE` | unsupported | anywhere | 허용 data/parameter grammar 없음 | file traversal 또는 include expansion 없음 | `unsupported-keyword`; 참조 파일을 열지 않음 | | `*PART` / `*END PART` | supported | top-level model block | `NAME=` 필수; `*END PART` data 없음 | part-local node, element, set, shell section scope | unclosed, nested, duplicate, data-bearing close는 input error | | `*NODE` | supported | part scope | 각 row `node_label,x,y,z`; parameter 없음 | 양의 source node label과 finite global Cartesian coordinate | arity 오류, duplicate label, nonfinite value, dangling later reference는 input/model error | | `*NSET` | supported | part 또는 assembly scope | `NSET=` 필수; optional `GENERATE`; assembly scope는 `INSTANCE=` 필수; explicit labels 또는 `first,last,increment` | deterministic node-set membership | mixed-instance set, invalid generate row, duplicate set name, empty set, dangling member는 input error | | `*ELEMENT` | supported | part scope | `TYPE=S4` 또는 `TYPE=S4R`; 각 row `element_label,n1,n2,n3,n4` | four-node source shell connectivity; source type 보존; internal type `FESA-MITC4` | 다른 element type은 `unsupported-element-formulation`; repeated node, arity 오류, dangling node, mixed element model은 error | | `*ELSET` | supported | part 또는 assembly scope | `ELSET=` 필수; optional `GENERATE`; assembly scope는 `INSTANCE=` 필수; `*NSET`과 같은 row rule | deterministic element-set membership | mixed-instance set, invalid generate row, duplicate set name, empty set, dangling member는 input error | | `*MATERIAL` | supported | top-level model data | `NAME=` 필수; data 없음 | 정확히 하나의 supported isotropic `*ELASTIC` 소유 | duplicate material, missing/duplicate elasticity, 다른 material behavior는 input error | | `*ELASTIC` | supported | current `*MATERIAL` scope | 정확히 한 row `E,nu`; parameter 없음 | homogeneous isotropic linear elasticity; `G=E/(2(1+nu))` 파생 | extra field/row, dependency/temperature data, nonfinite value, `E<=0`, `nu<=-1`, `nu>=0.5`는 error | | `*SHELL SECTION` | supported | part scope | `ELSET=`와 `MATERIAL=` 필수; 정확히 한 row `thickness[,integration_points]` | centered homogeneous single-layer shell section | composite/layer data, offset, orientation, controls, variable thickness, missing reference, conflicting assignment, nonpositive thickness는 error | | `*ASSEMBLY` / `*END ASSEMBLY` | supported | 정확히 하나의 top-level assembly | `NAME=` 필수; `*END ASSEMBLY` data 없음 | identity-instance scope와 assembly-level set scope | nested/duplicate assembly, instance transform data, unmatched close는 input error | | `*INSTANCE` / `*END INSTANCE` | supported | assembly scope | `NAME=`, `PART=` 필수; transform data 없음 | named identity copy; 같은 part의 multiple identity instances 허용 | duplicate/dangling instance 또는 translation/rotation data는 unsupported input | | `*BOUNDARY` | supported | top-level model data 또는 sole step의 `*STATIC` 뒤 | parameter 없음; 각 row `target,first_dof,last_dof[,value]`; omitted value는 exact zero | common load-factor path의 factor-one absolute global DOF target; DOF `1..6` | amplitude, local coordinate system, invalid range/arity, unresolved target, nonfinite value, conflicting expanded value는 error | | `*CLOAD` | supported | sole step의 `*STATIC` 뒤 | parameter 없음; 각 row `target,dof,magnitude`; DOF `1..6` | load factor로만 scale되는 fixed-global dead nodal force/moment source | amplitude/follower/local load, invalid arity/DOF, unresolved target, nonfinite magnitude, drilling-direction aggregate moment는 error | | `*DLOAD` | unsupported | anywhere | 허용 data/parameter grammar 없음 | distributed/body/pressure/edge/follower load object를 만들지 않음 | load-like usage는 `unsupported-distributed-load`; 그 외는 `unsupported-keyword` | | `*STEP` / `*END STEP` | supported for nonlinear selector | 정확히 하나의 top-level history block | optional `NAME`; `NLGEOM=YES` 필수; `*END STEP` data 없음 | canonical nonlinear step identity `Step-1` | zero/multiple/mixed/unclosed/nested step 또는 non-`YES` nonlinear selector는 nonlinear increment 전 실패 | | `*STATIC` | supported nonlinear procedure | sole step의 첫 procedure keyword | 정확히 한 row `initial_increment,time_period,minimum_increment,maximum_increment`; 네 값 모두 finite positive; `time_period`는 endpoint `1.0` identity | 첫 값은 fixed increment `h`; 세 번째/네 번째 값은 unused compatibility source; factors는 one 미만 ordinal multiple 뒤 exact factor one | missing/extra rows/fields, nonpositive/nonfinite field, endpoint가 `1.0`이 아니면 `invalid-nonlinear-static-data` | | `*OUTPUT` | ignored-with-warning | sole step의 `*STATIC` 뒤 | 정확히 `FIELD, VARIABLE=PRESELECT` 또는 `HISTORY, VARIABLE=PRESELECT`; `FIELD`/`HISTORY`는 value 없는 flag이고 둘 중 하나만 필요; `VARIABLE`은 정확히 한 번 필요; duplicate, both flags, missing `VARIABLE`, 다른 value, extra parameter는 input error | stored reference의 `*Output, field, variable=PRESELECT`와 `*Output, history, variable=PRESELECT`를 warning no-op으로 수용; FESA mandatory output을 select/suppress할 수 없음 | output request는 FESA output을 바꾸지 않음; malformed parameter set은 `invalid-keyword-parameter` | | `*NODE OUTPUT` | ignored-with-warning | active allowlisted `*OUTPUT` scope | parameter와 다음 keyword 전 variable data를 소비 | legacy nodal request `U`, `RF` 등을 수용 | HDF5 selection, history output, empty synthetic dataset을 만들지 않음 | | `*ELEMENT OUTPUT` | ignored-with-warning | active allowlisted `*OUTPUT` scope | parameter와 다음 keyword 전 variable data를 소비 | legacy element request `S` 등을 수용 | extrapolated stress, averaging, comparison projection을 만들지 않음 | | `*PREPRINT` | ignored-with-warning | top-level | parameter를 보존 후 무시; data 불필요 | generator control syntax 수용 | semantic object 없음 | | `*RESTART` | ignored-with-warning | sole step | parameter를 보존 후 무시; restart state/data 없음 | legacy restart request syntax 수용 | restart write/read/continue 없음 | | `*CONTACT OUTPUT` | ignored-with-warning | active allowlisted `*OUTPUT` scope | parameter와 다음 keyword 전 data를 소비 | legacy contact-output request syntax만 수용 | contact model/output 없음 | `*ORIENTATION`, `*TRANSFORM`, amplitudes, follower loads, pressure, gravity, body force, edge load, `*DLOAD`, composite shell definitions, shell section offsets, material nonlinearity, density, temperature dependency, contact, MPC, penalty, multiple steps, restarts, submodels, transforms, nested assemblies와 위 표에 없는 모든 model-affecting keyword는 fail-closed unsupported input이다. 저장 또는 future linear shell input의 `NLGEOM=NO`는 `docs/linear-static-mitc4-shell/io.md`가 계속 관할한다. 이 feature bundle에서 해당 linear case는 `shell-s4-linear-limit` regression reference일 뿐 nonlinear response evidence가 아니다. ## 3. Syntax Policy - Keyword line은 optional leading whitespace 뒤 `*`로 시작한다. Comment line은 `**`로 시작하며 semantic effect가 없다. - Keyword name, parameter name, supported enumerated value, named-reference lookup은 ASCII case-insensitive다. Raw source spelling은 diagnostic/report display용으로 보존한다. - Data line과 keyword parameter field는 comma-separated다. 주변 whitespace는 parsing 전에 trim한다. 필수 field가 비어 있거나, 허용되지 않은 trailing field가 있거나, numeric token이 malformed이면 input error다. - 승인된 empty data-field 의미는 `*BOUNDARY` 네 번째 value 생략뿐이며 exact zero로 매핑한다. `*SHELL SECTION`의 optional second field는 생략 가능하고, 존재하면 positive base-10 integer여야 한다. - Continuation line, physical-line continuation, multiline name, quoted case-sensitive name, parameter substitution, include file은 unsupported다. 각 logical keyword/data row는 한 physical line에 완결되어야 한다. - 이 feature는 public numeric Abaqus line-length compatibility limit를 정의하지 않는다. 승인 input은 single-line ASCII record이며, 읽을 수 없는 physical line은 implicit continuation 없이 parsing 실패다. - Keyword, parameter, set/material/part/instance name, numeric label의 input text는 ASCII로 취급한다. HDF5 string output은 UTF-8이지만 non-ASCII source label/name은 이 feature 계약 밖이다. - Node label, element label, explicit set member는 positive base-10 integer다. Source label은 text와 numeric identity로 보존한다. Stable internal index는 diagnostic 또는 comparison row에서 source identity를 대체할 수 없다. - 모든 real-valued input은 finite `double`로 parse되어야 한다. `NaN`, `Inf`, overflow, nonfinite underflow, locale-dependent numeric format은 reject한다. - Model data와 history data는 개념적으로 분리한다. Mesh, set, material, section, coordinate, initial shell frame은 model data다. Step, procedure, boundary, load, output request는 history data다. - 어떤 keyword에도 속하지 않는 standalone data 또는 active keyword block 밖의 data는 input error다. Output-request variable data는 allowlisted output keyword에 종속될 때만 no-op으로 소비한다. - 모든 parsed keyword, parameter, data row, semantic entity는 normalized file path, 1-based line, raw keyword spelling, source identity까지 추적 가능해야 한다. ## 4. Model Data Mapping ### 4.1 Stable Source Identity and Ordering Identity-instance expansion 뒤 source node와 source element의 stable identity는 다음과 같다. ```text SourceEntityId { instance_name, source_label } ``` Name lookup은 case-insensitive지만 raw spelling은 보존한다. Stable internal ID는 input part declaration order, instance declaration order, part-local entity declaration order로 부여한다. Hash iteration, thread scheduling, set spelling, CSV row order는 source identity, internal row order, diagnostic order 또는 result row order를 바꾸면 안 된다. ### 4.2 Nodes, Elements and Sets - `*NODE`는 finite global Cartesian initial midsurface coordinate `[X,Y,Z]`로 매핑하며 unit dimension은 `length`다. - `*ELEMENT, TYPE=S4/S4R`는 ordered four-node shell connectivity `[1,2,3,4]`로 매핑한다. Natural corner 순서는 `(-1,-1)`, `(+1,-1)`, `(+1,+1)`, `(-1,+1)`이며 connectivity를 조용히 reverse하지 않는다. - Source type `S4` 또는 `S4R`는 metadata로 보존한다. 두 type 모두 같은 internal `FESA-MITC4` formulation, `2 x 2 x 2` integration, nonlinear state path를 선택한다. Source `S4R`는 reduced integration, hourglass control 또는 Abaqus `S4R` internal behavior를 활성화하지 않는다. - `*NSET`과 `*ELSET`은 explicit row order를 보존한다. `GENERATE`는 inclusive `first,last,increment` 순서로 expand한다. Assembly-scope set은 하나의 `INSTANCE`만 참조할 수 있고 mixed instance는 허용하지 않는다. - Set membership은 Domain commit 전에 source identity로 resolve한다. 같은 scope의 duplicate set definition, dangling member, invalid generate range는 analysis 전 실패한다. ### 4.3 Material, Section, Coordinates and Units - `*MATERIAL`과 `*ELASTIC`은 finite `E>0`, `-10`를 갖는 centered homogeneous shell layer로 매핑한다. Optional source integration-point 값은 syntax compatibility로만 보존하며 quadrature, recovery, output, reference comparison에 영향을 주지 않는다. - Initial nodal director와 right-handed triad는 instance expansion 뒤 승인된 linear MITC4 deterministic incident-element rule로 파생한다. 이 값들은 model data이며 모든 increment의 fixed initial reference를 정의한다. - 필수 geometry check는 finite coordinate, valid four-node topology, 모든 Gauss/tying/ center/recovery location의 positive reference Jacobian, non-opposed incident normals, valid reciprocal bases, valid initial frames를 포함한다. - `.inp` 단위는 user-consistent unspecified다. HDF5는 `length`, `force`, `force*length`, `force/length`, `force/length^2`, `1` 같은 unit dimension string만 기록하고 SI를 쓰거나 추론하지 않는다. ## 5. History Data Mapping ### 5.1 Step and Procedure Nonlinear procedure는 정확히 하나의 source step이 `*STEP, NLGEOM=YES`를 포함하고 그 안에 정확히 하나의 supported `*STATIC` data row가 있을 때만 선택한다. Semantic step name은 canonical `Step-1`이다. Raw source step name은 provenance로만 보존한다. Nonlinear `*STATIC` data row의 의미는 다음과 같다. - `initial_increment`는 fixed positive load-factor increment `h`다. - `time_period`는 endpoint `1.0`과 정확히 같은 identity여야 한다. - `minimum_increment`와 `maximum_increment`는 positive finite source value여야 하지만 cutback, growth, retry, stopping, convergence, output cadence에는 사용하지 않는다. - Intended factor identity는 `1.0`보다 작은 ordinal `j*h` 값들을 만든 뒤, 마지막에 exact assigned factor `1.0` 하나를 붙여 만든다. Cumulative `lambda += h`, tolerance-based duplicate endpoint detection, growth, cutback, retry는 금지한다. - `reference/shellNL/shellNL.inp`의 성공 run에서 expected intended/accepted factor sequence는 `0.1,0.2,...,1.0`이다. Factor zero는 no-prior-history step-start committed baseline이다. Accepted frame은 committed increment와 일대일 대응해야 하므로 factor zero는 accepted HDF5 frame이 아니다. Factor zero는 다음 metadata/model dataset으로만 projection한다. - `factor_zero_is_frame=0` - `factor_zero_load_factor=0.0` - `/model/prescribed_displacement_start`와 initial state의 step-start displacement 및 rotation-vector component - `/model/shell/nodal_frame`과 `/model/shell/nodal_director`의 step-start triad/director - zero scaled `*CLOAD` contribution과 step-start boundary value ### 5.2 Boundary Conditions `*BOUNDARY` target resolution은 direct node label 또는 node set을 허용한다. Expanded row는 stable source-node identity와 DOF order `1..6`를 사용한다. | DOF | component | unit dimension | nonlinear path meaning | | ---: | --- | --- | --- | | 1 | `UX` / CSV `U1` | length | factor-one absolute global displacement target | | 2 | `UY` / CSV `U2` | length | factor-one absolute global displacement target | | 3 | `UZ` / CSV `U3` | length | factor-one absolute global displacement target | | 4 | `URX` / CSV `UR1` | dimensionless rotation | factor-one absolute fixed-initial global rotation-vector target | | 5 | `URY` / CSV `UR2` | dimensionless rotation | factor-one absolute fixed-initial global rotation-vector target | | 6 | `URZ` / CSV `UR3` | dimensionless rotation | factor-one absolute fixed-initial global rotation-vector target | Step 앞 row와 sole step 내부 row는 모두 같은 semantic step의 factor-one target으로 매핑한다. Cross-step propagation은 없다. Load factor `lambda`에서 current constrained value는 `q_start + lambda * (q_target - q_start)`다. Current release에는 prior history가 없으므로 ordinary start value는 승인된 start-state dataset에 명시된 값을 제외하고 zero다. Constrained Newton correction component는 exact zero다. ### 5.3 Concentrated Loads `*CLOAD` target resolution은 boundary와 같다. 같은 node/DOF로 resolve되는 여러 row는 source order로 factor-one global load coefficient에 누적한다. Factor `lambda`에서 magnitude는 `lambda`만 곱한다. | DOF | source component | unit dimension | nonlinear meaning | | ---: | --- | --- | --- | | 1 | `F1` | force | fixed-global dead nodal force | | 2 | `F2` | force | fixed-global dead nodal force | | 3 | `F3` | force | fixed-global dead nodal force | | 4 | `M1` | force*length | fixed-global source nodal moment admitted only through physical director-tangent work | | 5 | `M2` | force*length | fixed-global source nodal moment admitted only through physical director-tangent work | | 6 | `M3` | force*length | fixed-global source nodal moment admitted only through physical director-tangent work | Nonzero aggregated nodal moment `M_src`마다 preprocessing과 모든 entered trial state에서 `abs(dot(d,M_src))/norm(M_src) <= 1e-12`를 denominator clamping 없이 만족해야 한다. 실패하면 `unsupported-drilling-load`다. Source moment vector는 fixed global coordinate에 남으며 FESA는 rejected moment component를 회전, 축소, 변형하거나 numerical drilling channel로 보내지 않는다. ### 5.4 Output Requests Abaqus output request keyword는 `ignored-with-warning` compatibility syntax로만 수용한다. 이 keyword들은 history output을 켜지 않고, frame cadence를 제어하지 않으며, mandatory FESA HDF5 dataset을 select, suppress, rename할 수 없다. Trial Newton state는 HDF5 field/history output이 아니다. Per-iteration evidence는 `_log.txt`에 diagnostic text로만 기록한다. ## 6. Internal Model Contract 이 section은 semantic field를 정의하며 C++ API를 정의하지 않는다. - Node record: stable internal node ID, `SourceEntityId`, finite global coordinate, initial director, initial right-handed triad, source location. - Element record: stable internal element ID, `SourceEntityId`, preserved source type `S4` 또는 `S4R`, internal formulation `FESA-MITC4`, ordered four-node connectivity, resolved section/material identity, source location. - Set record: case-insensitive set name, source scope, optional source instance, deterministic expanded source members, stable internal member IDs. - Material record: case-insensitive material name, finite `E`, finite `nu`, derived `G`, source location, homogeneous isotropic materially linear identity. - Section record: source `ELSET`, resolved material, positive thickness, optional ignored source integration-point field, centered single-layer identity. - Boundary record: source target, expanded node identities, DOF range, finite factor-one absolute target values, step-start values, source location, conflict status. - Load record: source target, expanded node identities, DOF, finite factor-one source magnitude, deterministic aggregate value, dead fixed-global load identity. - Step record: raw source name, canonical `Step-1`, `NLGEOM=YES` nonlinear procedure identity, fixed increment `h`, endpoint `1.0`, unused third/fourth `*STATIC` values, intended factor sequence, output-request no-op inventory. - State contract: committed state와 trial state는 alias될 수 없다. 완전하게 수렴한 candidate만 displacement, rotation vector, `Q`, director, load factor, frame identity, internal/external force, residual/reaction, physical recovery row를 commit한다. Failed trial, nonconvergence, nonfinite data, solve failure, recovery failure 또는 output failure는 prior committed state와 prior authoritative final result를 보존한다. - Output request record: keyword, parameter, variable row, source location은 warning diagnostic용으로만 보존한다. Solver 또는 HDF5 selection effect는 없다. Source identity와 internal index identity는 diagnostics, HDF5 row order, reference comparison 전체에서 구분해야 한다. CSV의 element-label order는 solver identity가 아니며 `(instance, source_label)` key를 대체하지 않는다. ## 7. Output HDF5 Schema ### 7.1 Public Output Names, Log and Lifecycle 승인된 public CLI shape는 다음 하나뿐이다. ```powershell fesa.exe ``` CLI는 input path 해석보다 먼저 argv token을 왼쪽에서 오른쪽으로 scan한다. 어떤 token이든 case-sensitive exact literal substring `--output`을 포함하면, `--output`, `--output=...`, `--output-path`, prefix/suffix form을 모두 포함해 usage failure다. 이 failure는 input path resolution, parsing, Analysis construction, derived-result path ownership, HDF5 candidate, log creation/truncation, output finalization 전 exit code `2`로 끝난다. Stderr에는 ordered diagnostic 하나만 쓴다. ```text severity=error code=cli-usage argument_index= argument= message=literal --output is not supported ``` 여러 token이 `--output`을 포함해도 첫 matching token만 보고 위 diagnostic 하나만 낸다. Literal `--output`에 대한 compatibility alias나 deprecation window는 없다. `--output`을 포함하지 않는 다른 unknown option은 별도 `unrecognized-option` usage diagnostic을 유지할 수 있다. Input/output lexical identity는 다음 순서로 정의한다. 1. 단일 input path token이 relative path이면 invocation CWD를 lexical base로 붙인다. 2. `.`와 `..` component만 lexically normalize한다. Symlink, junction, short-name, case-preserving target path는 resolve하지 않는다. 3. Normalized user-addressed final filename의 마지막 extension이 case-insensitive `.inp`가 아니면 input usage failure다. 4. ``은 마지막 extension 하나만 제거한 basename이다. 앞선 dot과 basename case는 보존한다. 예: `Beam.Model.INP` -> `Beam.Model_results.h5`, `Beam.Model_log.txt`. 5. Derived outputs는 normalized user-addressed input path의 sibling이다. - result final: `/_results.h5` - log final/live file: `/_log.txt` File-vs-directory collision과 same-derived-pair concurrency는 output ownership 문제다. `_log.txt`가 directory 또는 truncate 불가능한 non-regular path이면 log create/open/ truncate failure다. `_results.h5`가 directory이면 HDF5 output collision으로 fail-closed 한다. 같은 derived pair를 목표로 하는 concurrent invocation은 same-directory implementation-private lock을 nonblocking exclusive ownership으로 먼저 획득해야 한다. Lock 획득 실패 또는 lock path의 directory collision은 exit code `6`의 output-busy failure이며 best-effort fatal stderr diagnostic 하나를 시도하고 log/HDF5를 변경하지 않는다. Lock holder 하나만 log truncate, HDF5 candidate, final replace를 시도한다. Candidate filename은 public contract가 아니지만 반드시 same-directory, implementation-private, exclusive-create collision-safe여야 하며 실패한 candidate는 authoritative output이 아니다. HDF5 result lifecycle과 log lifecycle은 의도적으로 비대칭이다. - `_log.txt`는 CLI usage validation, lexical output derivation, single-writer lock 획득 뒤 replace/truncate된다. Create/open/truncate failure는 Analysis 전 exit code `6`으로 abort하며, best-effort fatal stderr diagnostic 하나를 시도한다. - Log write/flush failure는 즉시 abort한다. Solver는 retry, fallback, continue 또는 result commit을 하지 않는다. Prior authoritative HDF5는 보존하고, 이미 flush된 live-log prefix는 rollback하지 않는다. Failed write 뒤 남은 partial trailing line은 authoritative iteration record가 아니며 tooling은 LF-terminated complete record만 parsing한다. - Log close는 successful analysis/recovery 뒤, 그리고 HDF5 candidate open/write/final replace 전 수행한다. Close failure는 result commit을 block하고 exit code `6`으로 끝낸다. - `_results.h5`는 sibling candidate가 완전히 write, flush, close, reopen, schema-check된 뒤 atomic move/replace에 성공한 경우에만 authoritative다. - HDF5 failure는 exit code `6`을 반환하고 가능한 경우 prior valid final을 보존하며 current-run log를 rollback하지 않는다. HDF5 failure는 log close 성공 뒤 발생하므로 current log는 닫힌 current-run audit으로 남는다. Newton iteration log는 UTF-8 no BOM, LF-terminated text file이다. Header, trailer, BOM, CRLF는 없다. Entered Newton iteration마다 physical line 하나만 기록하고, 각 line은 fixed field order의 TAB-separated `label=value` record다. Per-iteration stderr duplication은 정확히 0개다. 각 iteration record는 다음 iteration 진입 전 또는 return 전 flush되어야 한다. Non-Newton procedure 또는 Newton iteration에 진입하기 전 끝난 controlled failure는 iteration record를 fabricate하지 않는다. 같은 open/truncate/failure lifecycle을 적용하되 successful non-Newton run의 `_log.txt` content는 zero-byte empty file이다. Pre-Newton controlled failure도 entered iteration이 없으면 iteration record가 없는 log file만 남긴다. 고정 field order는 다음과 같다. | order | label | value contract | | ---: | --- | --- | | 1 | `record` | literal `newton-iteration` | | 2 | `schema` | literal `nsnr-log-v1` | | 3 | `increment` | entered increment identity, `uint64` | | 4 | `target_factor` | finite round-trip numeric load factor | | 5 | `iteration` | entered Newton iteration identity `1..100` | | 6 | `last_completed_stage` | enum stage completed before outcome; `none` allowed | | 7 | `failing_stage` | `none` for completed gate records, otherwise failing stage enum | | 8 | `residual_force_channel` | literal `residual_force` or `not-evaluated(reason)` | | 9 | `residual_force_numerator_norm` | `||r_f^u||_inf` or `not-evaluated(reason)` | | 10 | `residual_force_denominator_scale` | `max(||f_int,f^u||_inf,||f_ext,f^u||_inf)` or `not-evaluated(reason)` | | 11 | `residual_force_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` | | 12 | `residual_force_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` | | 13 | `residual_force_threshold_unit` | `1`, `force`, or `not-evaluated(reason)` | | 14 | `residual_force_pass` | `0`, `1`, or `not-evaluated(reason)` | | 15 | `residual_moment_channel` | literal `residual_moment` or `not-evaluated(reason)` | | 16 | `residual_moment_numerator_norm` | `||r_f^phi||_inf` or `not-evaluated(reason)` | | 17 | `residual_moment_denominator_scale` | `max(||f_int,f^phi||_inf,||f_ext,f^phi||_inf)` or `not-evaluated(reason)` | | 18 | `residual_moment_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` | | 19 | `residual_moment_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` | | 20 | `residual_moment_threshold_unit` | `1`, `force*length`, or `not-evaluated(reason)` | | 21 | `residual_moment_pass` | `0`, `1`, or `not-evaluated(reason)` | | 22 | `correction_translation_channel` | literal `correction_translation` or `not-evaluated(reason)` | | 23 | `correction_translation_numerator_norm` | `||Delta u_f||_inf` fresh correction or `not-evaluated(reason)` | | 24 | `correction_translation_denominator_scale` | `||Delta u_inc,f||_inf` from current trial relative to step start or `not-evaluated(reason)` | | 25 | `correction_translation_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` | | 26 | `correction_translation_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` | | 27 | `correction_translation_threshold_unit` | `1`, `length`, or `not-evaluated(reason)` | | 28 | `correction_translation_pass` | `0`, `1`, or `not-evaluated(reason)` | | 29 | `correction_rotation_channel` | literal `correction_rotation` or `not-evaluated(reason)` | | 30 | `correction_rotation_numerator_norm` | `||Delta phi_f||_inf` fresh correction or `not-evaluated(reason)` | | 31 | `correction_rotation_denominator_scale` | `||Delta phi_inc,f||_inf` from current trial relative to step start or `not-evaluated(reason)` | | 32 | `correction_rotation_branch` | `relative`, `zero-scale`, or `not-evaluated(reason)` | | 33 | `correction_rotation_threshold` | `1e-2` for `relative`, `1e-3` for `zero-scale`, or `not-evaluated(reason)` | | 34 | `correction_rotation_threshold_unit` | `1`, `1`, or `not-evaluated(reason)` | | 35 | `correction_rotation_pass` | `0`, `1`, or `not-evaluated(reason)` | | 36 | `combined_pass` | logical AND of four pass fields, or `not-evaluated(reason)` | | 37 | `transition` | `accept`, `update`, `fail`, or `not-evaluated(reason)` | | 38 | `outcome` | `accepted`, `continue`, `nonconverged`, or `failed` | | 39 | `diagnostic_code` | `none` or approved diagnostic code | Completed gate record는 `failing_stage=none`이고 네 channel의 identity, numerator/norm, denominator/scale, branch, typed threshold, pass를 모두 finite 또는 enum value로 노출한다. Denominator가 exact zero이면 branch는 `zero-scale`이고 typed threshold는 residual force `1e-3 force`, residual moment `1e-3 force*length`, correction translation `1e-3 length`, correction rotation `1e-3 dimensionless`다. Denominator가 nonzero이면 branch는 `relative`이고 threshold는 dimensionless `1e-2`다. Empty free channel은 numerator와 denominator가 exact zero인 `zero-scale` branch로 평가한다. Early failure record는 entered iteration 하나에 대응한다. 이미 계산된 earlier fields는 실제 finite value를 기록하고, 실패 stage 뒤의 모든 later field는 `not-evaluated(reason)`을 기록한다. Not-evaluated field에 zero, pass `0`, pass `1`, fabricated denominator 또는 fabricated threshold를 쓰면 안 된다. `last_completed_stage`와 `failing_stage`는 stage enum을 사용하며 recommended enum은 `iteration-entered`, `trial-state`, `load-boundary`, `residual`, `tangent`, `factorization`, `correction`, `convergence-gates`, `update`, `recovery`, `commit`, `log-write`, `log-flush`, `none`이다. Numeric value는 locale-independent C-locale decimal point를 사용하고 finite IEEE-754 `double` round-trip이 가능해야 한다. `NaN`, `Inf`, localized comma, thousands separator, raw whitespace는 금지한다. String value는 raw TAB/LF/CR/control byte/backslash를 포함할 수 없으며 `\\`, `\t`, `\n`, `\r`, `\0`, `\xHH` escape를 사용한다. Record order는 increment, target factor, iteration 순서로 deterministic해야 한다. Schema version `1`의 모든 mandatory HDF5 dataset은 contiguous, uncompressed dataset이다. Chunking, compression filter, extendible dataset, trial-history group은 이 release 계약에 없다. ### 7.2 Metadata and Common Dataset Attribute Rules `results.h5` schema가 authoritative solver output이다. 실제 final filename은 Section 7.1의 `_results.h5`다. 모든 string은 UTF-8이다. 모든 physical real dataset은 IEEE-754 float64를 사용한다. Stable ID는 별도 명시가 없으면 unsigned 64-bit integer다. `/metadata` group의 required attributes는 다음과 같다. | attribute | required value or meaning | | --- | --- | | `schema_version` | `1` | | `feature_id` | `nonlinear-static-newton-raphson` | | `solver_version` | executing solver version string | | `source_input_identity` | lexical normalized user-addressed input path and content identity string; symlink/junction target resolution 없음 | | `unit_system_label` | `user-consistent-unspecified` | | `coordinate_convention` | `global-cartesian; shell-local=fixed-initial-reference; positive-thickness=+zeta` | | `analysis_procedure` | `nonlinear-static-full-newton` | | `internal_formulation` | `FESA-MITC4-total-lagrangian` | | `integration_rule` | `2x2x2-gauss; mitc4-edge-midpoint-shear` | | `step_name` | `Step-1` | | `frame_indexing` | `accepted-increment-order-zero-based` | | `factor_zero_is_frame` | `0` | | `factor_zero_load_factor` | `0.0` | 모든 numeric model/result dataset은 다음 required attributes를 가진다. - `schema_version=1` - `component_names` - `component_unit_dimensions` - `coordinate_system` - `location` Accepted-frame result dataset은 추가로 다음 attributes를 가진다. - `step_name=Step-1` - `frame_index=` - `increment_index=` - `load_factor=` - `is_factor_one=<0|1>` ### 7.3 Model Datasets | dataset path | shape and dtype | row identity / fields | required attributes and ordering | | --- | --- | --- | --- | | `/model/nodes` | `[node_count]` compound | `internal_node_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `coordinates:float64[3]` | internal ID ascending; `coordinate_system=global-cartesian`, `component_unit_dimensions=length,length,length`, `location=nodal-reference` | | `/model/elements` | `[element_count]` compound | `internal_element_id:uint64`, `instance_name:utf8`, `source_label:utf8`, `source_element_type:utf8`, `internal_formulation:utf8`, `node_internal_ids:uint64[4]`, `shell_section_internal_id:uint64`, `material_internal_id:uint64` | internal element ID ascending; `formulation=FESA-MITC4-total-lagrangian` | | `/model/shell/materials` | `[material_count]` compound | `internal_material_id:uint64`, `name:utf8`, `E:float64`, `nu:float64` | declaration order; `component_unit_dimensions=force/length^2,1`, `location=model-material` | | `/model/shell/sections` | `[section_count]` compound | `internal_section_id:uint64`, `source_file:utf8`, `source_line:uint64`, `source_elset:utf8`, `material_internal_id:uint64`, `thickness:float64` | declaration order; `component_unit_dimensions=length`, `location=model-shell-section`, `layering=centered-single-layer` | | `/model/shell/nodal_director` | `[node_count,3]` float64 | `/model/nodes` row; `[D1,D2,D3]` | initial director; `coordinate_system=global-cartesian`, `location=nodal-initial-director`, units `1,1,1` | | `/model/shell/nodal_frame` | `[node_count,3,3]` float64 | `/model/nodes` row; axis row `[A,B,D]`, global component column `[X,Y,Z]` | initial right-handed triad; `coordinate_system=global-cartesian`, `location=nodal-initial-frame`, units `1,1,1` | | `/model/nodal_constraint_mask` | `[node_count,6]` uint8 | `/model/nodes` row; DOF `[UX,UY,UZ,URX,URY,URZ]` | `0=free`, `1=constrained`; constrained reaction comparison identity의 authority | | `/model/prescribed_displacement_start` | `[node_count,6]` float64 | same row/DOF order | factor-zero start values; units `[length x3,1 x3]`, `load_factor=0.0` | | `/model/prescribed_displacement_target` | `[node_count,6]` float64 | same row/DOF order | factor-one absolute target values; units `[length x3,1 x3]`, `load_factor=1.0` | | `/model/shell/midsurface_locations` | `[4,2]` float64 | location rows `GP1..GP4`; columns `[XI,ETA]` | `coordinate_system=shell-natural`; `(-g,-g),(+g,-g),(+g,+g),(-g,+g)`, `g=1/sqrt(3)` | | `/model/shell/section_positions` | `[3]` float64 | rows `[BOTTOM,MIDDLE,TOP]`; values `[-1,0,+1]` | `coordinate_system=shell-natural`; physical `z=t*zeta/2`; Abaqus section-point identity가 아님 | ### 7.4 Accepted Frame Table Successful nonlinear run 뒤 `/steps/Step-1/accepted_frames`는 mandatory다. | path | shape and dtype | fields | required meaning | | --- | --- | --- | --- | | `/steps/Step-1/accepted_frames` | `[frame_count]` compound | `frame_index:uint64`, `increment_index:uint64`, `load_factor:float64`, `iteration_count:uint64`, `is_factor_one:uint8` | committed increment마다 한 row; `frame_index`는 `` group name과 같음; load factor는 strictly increasing; 마지막 row는 `load_factor=1.0`, `is_factor_one=1` | `frame_count`는 committed increment 수이며 successful run에서는 하나 이상이다. Factor-one row는 정확히 하나다. Factor zero는 이 dataset에 row를 갖지 않고 `/frames/0` 특별 의미도 갖지 않는다. ### 7.5 Accepted Frame Result Datasets `/steps/Step-1/accepted_frames.frame_index = `마다 아래 dataset들이 `/steps/Step-1/frames//` 아래 mandatory다. | quantity | exact dataset path | shape | row identity and component order | units / coordinates / location | | --- | --- | --- | --- | --- | | committed displacement and rotation vector | `/steps/Step-1/frames//nodal/displacement` | `[node_count,6]` float64 | `/model/nodes` row; `[UX,UY,UZ,URX,URY,URZ]` | `[length,length,length,1,1,1]`; global Cartesian translations and fixed-initial global rotation-vector components; nodal | | committed triad | `/steps/Step-1/frames//nodal/triad` | `[node_count,3,3]` float64 | node row; axis row `[A,B,D]`, global component column `[X,Y,Z]` | dimensionless; global Cartesian; committed `Q`; director는 row `D` | | committed director | `/steps/Step-1/frames//nodal/director` | `[node_count,3]` float64 | node row; `[D1,D2,D3]` | dimensionless; global Cartesian; triad axis `D`와 같아야 함 | | generalized internal force | `/steps/Step-1/frames//nodal/generalized_internal_force` | `[node_count,6]` float64 | node row; `[FI1,FI2,FI3,MI_PHI1,MI_PHI2,MI_PHI3]` | `[force x3,force*length x3]`; work-conjugate to `[u,phi]`; nodal | | generalized external force | `/steps/Step-1/frames//nodal/generalized_external_force` | `[node_count,6]` float64 | node row; `[FE1,FE2,FE3,ME_PHI1,ME_PHI2,ME_PHI3]` | `[force x3,force*length x3]`; work-conjugate to `[u,phi]`; approved physical moment projection 후 fixed-global dead loads; nodal | | generalized residual | `/steps/Step-1/frames//nodal/generalized_residual` | `[node_count,6]` float64 | node row; `[RU1,RU2,RU3,RPHI1,RPHI2,RPHI3]` | `[force x3,force*length x3]`; nonlinear solution coordinate의 full assembled `f_int-f_ext`; nodal | | reaction / physical residual projection | `/steps/Step-1/frames//nodal/reaction` | `[node_count,6]` float64 | node row; `[RF1,RF2,RF3,RM1,RM2,RM3]` | `[force x3,force*length x3]`; global; constrained entry는 physical reaction, free entry는 same-state equilibrium evidence; rotational columns는 `J_l(phi)^(-T)` spatial moment conversion | | shell local frame | `/steps/Step-1/frames//element/shell/local_frame` | `[element_count,4,3,3]` float64 | element row, midsurface location row `GP1..GP4`, axis row `[E1,E2,E3]`, global component column `[X,Y,Z]` | dimensionless; physical recovery용 fixed-initial shell local frame; rotating Abaqus output frame이 아님 | | generalized strain | `/steps/Step-1/frames//element/shell/generalized_strain` | `[element_count,4,8]` float64 | element row, `GP1..GP4`; `[E11,E22,G12,K11,K22,K12,G13,G23]` | `[1,1,1,1/length,1/length,1/length,1,1]`; fixed-reference shell local; midsurface | | section resultant | `/steps/Step-1/frames//element/shell/section_resultant` | `[element_count,4,8]` float64 | element row, `GP1..GP4`; `[N11,N22,N12,M11,M22,M12,Q13,Q23]` | `[force/length x3,force x3,force/length x2]`; fixed-reference shell local; midsurface | | in-plane stress | `/steps/Step-1/frames//element/shell/stress` | `[element_count,4,3,3]` float64 | element row, `GP1..GP4`, section position `[BOTTOM,MIDDLE,TOP]`, component `[S11,S22,S12]` | `force/length^2`; fixed-reference shell local; direct bottom/middle/top evaluation | | physical strain energy | `/steps/Step-1/frames//global/energy` | `[1]` float64 | `[PHYSICAL_STRAIN_ENERGY]` | `force*length`; deterministic element reduction; numerical drilling stabilization 제외 | | global equilibrium | `/steps/Step-1/frames//global/equilibrium` | `[6]` float64 | `[FORCE_1,FORCE_2,FORCE_3,MOMENT_1,MOMENT_2,MOMENT_3]` | `[force x3,force*length x3]`; global Cartesian; moment about global origin `[0,0,0]`, current force arms와 spatial physical nodal moments 사용 | Trial Newton state, iteration history, line search, cutback attempt, damping, automatic stabilization, numerical drilling stress, drilling energy ratio, `S33`, `S13`, `S23`, nodal stress extrapolation, element-corner stress, averaged stress, Abaqus integration-point number에 대한 HDF5 dataset은 만들지 않는다. ### 7.6 Diagnostics Dataset `/diagnostics`는 mandatory이며 row가 0개일 수 있다. | path | shape and dtype | fields | required meaning | | --- | --- | --- | --- | | `/diagnostics` | `[diagnostic_count]` compound | `severity:utf8`, `code:utf8`, `file:utf8`, `line:uint64`, `keyword:utf8`, `entity_identity:utf8`, `message:utf8` | CLI/input/model/solver/output deterministic diagnostics; ignored keyword warning도 success file에 보존 | Diagnostic order는 source file declaration order, 1-based line, stable entity identity, diagnostic code, discovery order를 순서대로 사용한다. Source가 없는 CLI/solver/output diagnostic은 explicit empty source field를 사용한다. ### 7.7 Output Failure and Atomic Finalization Writer는 log close 성공 뒤에만 final file과 같은 directory에 implementation-private temporary HDF5 candidate를 만든다. Candidate는 metadata, model datasets, accepted-frame table, 모든 accepted-frame dataset, diagnostics를 모두 쓰고, shape, attribute, finite value, source identity, row order를 검증한다. Checked HDF5 close와 read-only reopen/self-check가 성공한 뒤에만 final `_results.h5`를 replace/create한다. 실패한 candidate는 제거하거나 non-authoritative implementation-private artifact로만 남긴다. Controlled failure는 incomplete final result를 노출하면 안 된다. HDF5 failure는 이미 닫힌 current-run log를 rollback하지 않는다. ## 8. FESA HDF5 to Reference CSV Comparison Mapping Comparison tooling은 FESA `results.h5` schema와 exact read-only Abaqus CSV artifact만 읽는다. CSV는 FESA output이 아니다. HDF5에서 추출한 deterministic CSV view는 debugging/reporting 보조물로만 둘 수 있다. ### 8.1 Declared Cases and Artifacts | case id | role | exact path | comparison disposition | | --- | --- | --- | --- | | `shellnl-s4-final` | nonlinear input | `reference/shellNL/shellNL.inp` | required source input | | `shellnl-s4-final` | displacement CSV | `reference/shellNL/shellNL displacements.csv` | required comparison | | `shellnl-s4-final` | reaction CSV | `reference/shellNL/shellNL reactions.csv` | constrained nodes/components only required comparison | | `shellnl-s4-final` | stress CSV | `reference/shellNL/shellNL stresses.csv` | optional read-only inspection/order evidence only | | `shell-s4-linear-limit` | linear control input | `reference/shell/shell.inp` | existing linear MITC4 contract의 required regression input | | `shell-s4-linear-limit` | displacement CSV | `reference/shell/shell displacements.csv` | required regression comparison | | `shell-s4-linear-limit` | reaction CSV | `reference/shell/shell reactions.csv` | optional read-only inspection only | | `shell-s4-linear-limit` | stress CSV | `reference/shell/shell stresses.csv` | optional read-only inspection/order evidence only | Reference artifact file은 workflow에서 rename, rewrite, normalize, zero-clamp, repair, regenerate하지 않는다. ### 8.2 Accepted-State and Frame Mapping - `shellnl-s4-final`은 accepted factor-one HDF5 frame만 비교한다. 해당 frame은 `/steps/Step-1/accepted_frames`에서 `is_factor_one=1`이고 `load_factor=1.0`인 unique row다. 그 `frame_index`가 `/steps/Step-1/frames/`를 선택한다. - Required `shellNL` CSV row는 exact `Frame` value `Increment 10: Step Time = 1.000`만 가져야 하며, 이는 accepted factor-one state로 논리 매핑한다. Required row에 다른 `Frame` 값이 있으면 schema mismatch다. - `shell-s4-linear-limit` CSV에는 `Frame` column이 없으며 `docs/linear-static-mitc4-shell/io.md`의 existing linear MITC4 final frame `/steps/Step-1/frames/0`에 매핑한다. - Trial Newton state, iteration log line, optional stress inventory row는 reference row가 아니다. ### 8.3 Nodal Displacement Projection Required logical key는 다음과 같다. ```text (case_id, accepted_state, canonical_instance_name, source_node_label, component) ``` 두 case 모두 instance `PART-1-1`에서 node label `1..49`가 정확히 한 번씩 필요하다. Instance matching은 case-insensitive로 수행하되 report에는 raw spelling을 보존한다. | CSV column | comparison component | nonlinear HDF5 source | linear regression HDF5 source | | --- | --- | --- | --- | | `U-U1` | `U1` | `nodal/displacement` column `UX` | `nodal/displacement` column `UX` | | `U-U2` | `U2` | `nodal/displacement` column `UY` | `nodal/displacement` column `UY` | | `U-U3` | `U3` | `nodal/displacement` column `UZ` | `nodal/displacement` column `UZ` | | `UR-UR1` | `UR1` | `nodal/displacement` column `URX` | `nodal/displacement` column `URX` | | `UR-UR2` | `UR2` | `nodal/displacement` column `URY` | `nodal/displacement` column `URY` | | `UR-UR3` | `UR3` | `nodal/displacement` column `URZ` | `nodal/displacement` column `URZ` | `U1/U2/U3`는 blocking이다. `UR1/UR2/UR3`는 두 case 모두 warning-only다. UR warning exceedance는 blocking verdict를 바꾸지 않는다. ### 8.4 Nonlinear Constrained Reaction Projection Reaction comparison은 `shellnl-s4-final`에만 적용하며 input boundary mask의 constrained node 중 아래 24개 node에만 적용한다. ```text 1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33 ``` 승인 input에서 이 24개 node는 여섯 global DOF가 모두 constrained다. Comparator는 required HDF5 reaction row eligibility를 CSV zero value가 아니라 `/model/nodal_constraint_mask`와 source node identity에서 도출한다. | CSV columns | logical family | HDF5 source | disposition | | --- | --- | --- | --- | | `RF-RF1`, `RF-RF2` | `nonlinear.reaction_inplane_force` | factor-one `/nodal/reaction` columns `RF1,RF2` | blocking | | `RF-RF3` | `nonlinear.reaction_transverse_force` | factor-one `/nodal/reaction` column `RF3` | blocking | | `RM-RM1`, `RM-RM2` | `nonlinear.reaction_physical_moment` | factor-one `/nodal/reaction` columns `RM1,RM2`; `J_l(phi)^(-T)` 변환 뒤 spatial physical moment | blocking | | `RM-RM3` | excluded | comparison projection 없음 | blocking 및 warning-only family에서 제외 | Raw generalized rotation-coordinate residual column은 Abaqus `RM` CSV column과 직접 비교하지 않는다. ### 8.5 Comparison Families External tolerance source는 정확히 `docs/TOLERANCE.md`다. 별도 absolute floor, `max(1,S)` clamp, row averaging, source-order matching, component calibration, zero clamp는 허용하지 않는다. | family id | case | components | required row count | units / coordinates | disposition | | --- | --- | --- | ---: | --- | --- | | `linear.translation` | `shell-s4-linear-limit` | `U1,U2,U3` on nodes `1..49` | 147 | length / global | blocking regression | | `linear.rotation` | `shell-s4-linear-limit` | `UR1,UR2,UR3` on nodes `1..49` | 147 | dimensionless / fixed-initial global | warning-only | | `nonlinear.translation` | `shellnl-s4-final` | `U1,U2,U3` on nodes `1..49` | 147 | length / global | blocking | | `nonlinear.rotation` | `shellnl-s4-final` | `UR1,UR2,UR3` on nodes `1..49` | 147 | dimensionless / fixed-initial global | warning-only | | `nonlinear.reaction_inplane_force` | `shellnl-s4-final` | `RF1,RF2` on constrained nodes | 48 | force / fixed-initial global plane | blocking | | `nonlinear.reaction_transverse_force` | `shellnl-s4-final` | `RF3` on constrained nodes | 24 | force / fixed-initial global transverse | blocking | | `nonlinear.reaction_physical_moment` | `shellnl-s4-final` | `RM1,RM2` on constrained nodes | 48 | force*length / global spatial | blocking | Reference-model read-only scale audit value는 다음과 같다. | family id | `S=max(abs(reference))` | `0.01*S` | | --- | ---: | ---: | | `linear.translation` | `2.37408203e-5` | `2.37408203e-7` | | `linear.rotation` | `7.60725743e-6` | `7.60725743e-8` | | `nonlinear.translation` | `2.37408203e-5` | `2.37408203e-7` | | `nonlinear.rotation` | `7.60725743e-6` | `7.60725743e-8` | | `nonlinear.reaction_inplane_force` | `1.91663182` | `1.91663182e-2` | | `nonlinear.reaction_transverse_force` | `1.17769805e4` | `1.17769805e2` | | `nonlinear.reaction_physical_moment` | `1.95418418e4` | `1.95418418e2` | ### 8.6 Row Prechecks 아래 조건 중 하나라도 거짓이면 comparator는 tolerance 계산 전에 실패한다. 1. Exact declared input path와 required CSV path가 존재하고 readable이다. 2. Reference CSV header는 surrounding whitespace trim 뒤 필요한 column을 가진다. 3. `shellnl-s4-final` required row는 exact approved `Frame` value만 포함한다. 4. HDF5 metadata, model rows, accepted-frame table, factor-one frame, required result dataset이 문서화된 shape, component name, finite value를 가진다. 5. Wide CSV row는 이 문서의 component mapping으로 component row로 expand한다. 6. Required source wide key와 expanded component key는 unique하다. Duplicate reference 또는 HDF5 key는 실패다. 7. 각 declared family에서 FESA와 reference projected key set은 정확히 같아야 한다. Missing row와 extra row는 모두 실패다. 8. 모든 required numeric value는 finite다. Nonfinite HDF5 또는 CSV value는 tolerance 전 실패다. 9. `shellNL` reaction row는 constrained mask와 exact 24-node list에서 선택한다. Free-node CSV row는 inventory only이며 zero reaction target으로 해석하지 않는다. 10. Required row를 omit, synthesize, average, substitute identity로 sort, normalize, zero-clamp, repair하지 않는다. ### 8.7 Stress CSV Disposition Optional stress CSV identity는 다음과 같다. ```text (case_id, accepted_state, instance, element_label, element_corner_node_label, section_surface, component) ``` 현재 stress CSV는 element-corner node row와 `SPOS/SNEG` section surface에서 `S-S11`, `S-S22`, `S-S33`, `S-S12`를 포함하며, 저장된 ascending element-label block `1..36` 순서를 갖는다. FESA HDF5는 `GP1..GP4`와 `BOTTOM/MIDDLE/TOP`에서 direct `[S11,S22,S12]`만 emit한다. 따라서 두 case의 stress CSV는 optional read-only inspection 및 order evidence only다. HDF5 comparison projection, `S33` synthesis, nodal extrapolation, corner averaging, Gauss-to-corner matching, element-label-order identity는 없다. ## 9. Validation Rules | validation area | required pass condition | failure class | | --- | --- | --- | | CLI usage | input path 정확히 하나; 어떤 argv token에도 exact literal substring `--output` 없음; matching 시 path resolution/parsing/Analysis/log/HDF5 전 `cli-usage` stderr diagnostic 정확히 1개 | usage, exit `2` | | keyword inventory | keyword가 supported, explicit diagnostic의 unsupported, 또는 exact ignored-with-warning allowlist 중 하나 | input, exit `3` | | syntax | ASCII keyword/data grammar, comma fields, finite numeric tokens, continuation/include 없음 | input, exit `3` | | nesting/cardinality | part/assembly/instance/step이 닫힘; nonlinear procedure는 정확히 하나의 `NLGEOM=YES` step | input, exit `3` | | source identity | scope 내 duplicate name/label 없음; 모든 reference resolved; instance identity unique | input, exit `3` | | set expansion | explicit/generated set이 deterministic expand되고 하나의 supported scope/instance에 머묾 | input, exit `3` | | shell element | only `S4/S4R`; 네 개의 distinct resolved nodes; mixed element model 없음; source type metadata 보존 | input/model, exit `3` 또는 `4` | | material and section | single isotropic elastic material, centered homogeneous positive-thickness shell section, element마다 정확히 하나의 assignment | input/model, exit `3` 또는 `4` | | geometry and coordinates | finite global coordinates, positive reference/current validity checks, required location마다 valid directors/triads/branches | model 또는 solver trial failure, exit `4` 또는 `5` | | boundary | DOF `1..6`, resolved finite targets, factor-one absolute meaning, conflicting expanded value 없음 | input, exit `3` | | load | resolved finite `CLOAD`, stable aggregation, fixed-global dead path, unsupported `DLOAD`/follower/distributed load 없음 | input/model, exit `3` 또는 `4` | | aggregate moment | exact-zero case 또는 preprocessing 및 모든 entered trial에서 `rho_M<=1e-12` | model/solver, exit `4` 또는 `5` | | nonlinear static data | 네 positive finite values, endpoint `1.0`, fixed increment sequence with final exact factor one | input, exit `3` | | Newton iteration | iteration identity `1..100`; iteration `100` acceptance 가능; iteration `101` 없음; line search/cutback/retry/fallback 없음 | solver, exit `5` | | convergence channels | residual force, residual moment, correction translation, correction rotation이 모두 inclusive `<=` rule 또는 typed zero-scale threshold 통과 | solver, exit `5` | | nonfinite data | required residual, tangent, correction, state, load, recovery, output value가 acceptance 전 finite | solver/output, exit `5` 또는 `6` | | commit/rollback | complete converged candidate만 commit; failure는 prior committed state와 prior authoritative final HDF5 보존 | solver/output, exit `5` 또는 `6` | | HDF5 schema | exact paths, shapes, attributes, schema version, row identities, finite values, accepted-frame table, diagnostics; final replace는 log close success 뒤에만 허용 | output, exit `6` | | log | UTF-8 no BOM, LF, TAB-separated fixed `label=value` schema; entered Newton iteration마다 record 하나; no per-iteration stderr duplication; no-Newton procedure는 zero-byte empty log; open/write/flush/close fail-closed | output, exit `6` | | reference rows | exact required artifacts, headers, row keys, component keys, finite values, factor-one frame mapping | reference precheck | | tolerance | exact `docs/TOLERANCE.md` family-scale row/RMS policy; blocking/warning disposition 보존 | reference verification | Downstream test가 다뤄야 하는 approved diagnostic code는 다음을 포함한다. | code | class | meaning | | --- | --- | --- | | `cli-usage` | usage/2 | argv token이 exact literal substring `--output`을 포함하며 pre-input/pre-log/pre-output failure 하나를 stderr에 기록 | | `unrecognized-option` | usage/2 | `--output` substring을 포함하지 않는 다른 unsupported option | | `malformed-keyword` | input/3 | keyword 또는 parameter grammar invalid | | `invalid-keyword-location` | input/3 | keyword가 approved scope 밖에 위치 | | `invalid-keyword-parameter` | input/3 | parameter missing, duplicate, empty 또는 subset 밖 | | `unsupported-keyword` | input/3 | `*INCLUDE` 포함 approved subset 밖 keyword | | `unsupported-distributed-load` | input/3 | `*DLOAD`, pressure, gravity, body, edge, follower load 요청 | | `duplicate-entity` | input/3 | source identity가 scope 안에서 duplicate | | `unresolved-reference` | input/3 | connectivity, set, instance, section, material, load, boundary target dangling | | `unsupported-element-formulation` | input/3 | shell feature에서 source element type이 `S4` 또는 `S4R`가 아님 | | `unsupported-mixed-element-model` | input/3 | shell과 non-shell product semantics 혼합 | | `invalid-shell-connectivity` | input/3 | shell connectivity arity, duplicate node 또는 resolved node identity invalid | | `unsupported-shell-section-option` | input/3 | composite/layer/offset/orientation/variable-thickness section 의미 등장 | | `invalid-shell-material` | model/4 | material value가 finite `E,nu` bound 위반 | | `invalid-shell-thickness` | model/4 | shell thickness nonfinite 또는 nonpositive | | `invalid-shell-geometry` | model/4 | shell geometry, reference Jacobian 또는 topology invalid | | `opposed-incident-normal` | model/4 | averaging 전 incident normal pair가 nonpositive | | `invalid-shell-director` | model/4 | nodal/interpolated director, triad 또는 branch validity 실패 | | `invalid-shell-jacobian` | model/4 | required Gauss/tying/center/recovery point의 basis/Jacobian invalid | | `unsupported-drilling-load` | model/4 또는 solver/5 | aggregate nodal moment가 current-director admissibility 위반 | | `invalid-nonlinear-static-data` | input/3 | `*STATIC` row arity, finite/positive check 또는 endpoint-one identity 실패 | | `unsupported-analysis-procedure` | input/3 | supported nonlinear static source step으로 매핑되지 않음 | | `nonfinite-newton-data` | solver/5 | required residual, tangent, correction 또는 trial state nonfinite | | `tangent-factorization-failed` | solver/5 | entered iteration의 fresh tangent factorization 실패 | | `correction-solve-failed` | solver/5 | fresh Newton correction solve 실패 | | `nonlinear-nonconvergence` | solver/5 | iteration `100` 완료 후 네 convergence channel이 모두 통과하지 않음 | | `invalid-accepted-state` | solver/5 | converged candidate recovery/state identity가 commit 전 실패 | | `log-output-failure` | output/6 | required live log create/open/truncate, write, flush 또는 close 실패 | | `output-busy` | output/6 | same derived pair single-writer lock을 획득하지 못했거나 lock path collision 발생 | | `hdf5-output-failure` | output/6 | candidate HDF5 write, schema validation 또는 atomic finalization 실패 | ## 10. Open Issues and Downstream Handoff Open issues blocking Implementation Planning: 없음. Downstream handoff to Implementation Planning Agent through Coordinator: - Public CLI/output naming migration을 보존한다: `fesa.exe `, lexical sibling `_results.h5`, `_log.txt`, 그리고 exact literal substring `--output`을 포함하는 모든 argv token의 pre-input/pre-log/pre-output exit `2`와 정확히 하나의 `cli-usage` stderr diagnostic. - Supported/unsupported/ignored keyword row와 nonlinear `*STATIC` rule을 parser acceptance/rejection test로 변환한다. - Stored reference grammar인 `*Output, field, variable=PRESELECT`와 `*Output, history, variable=PRESELECT`를 duplicate/extra parameter 없이 `ignored-with-warning`으로 수용하고, output request가 FESA output을 바꾸지 못함을 test한다. - `NLGEOM=YES`가 nonlinear procedure를 선택하고 `shell` `NLGEOM=NO` case가 기존 linear MITC4 contract의 regression으로 남는지 test한다. - HDF5 schema version `1`을 위 accepted-frame schema 그대로 구현한다. Factor-zero non-frame handling, unique factor-one frame selection, triad/director projection, no compression/chunking, no trial-state HDF5 history를 포함한다. - 비대칭 lifecycle을 보존한다. Log는 usage validation, lexical path derivation, single-writer lock 뒤 live current-run audit이고, log create/open/truncate는 Analysis 전 abort, write/flush는 즉시 abort, close failure는 HDF5 commit을 block한다. HDF5 final은 log close와 candidate self-check 성공 뒤에만 replace하며 failure는 prior valid final과 current log를 손상하지 않는다. - Newton log parser/schema test는 UTF-8 no BOM, LF, physical TAB-separated fixed `label=value` field order, finite round-trip numerics, escaping, completed-gate four-channel metrics, early-failure `not-evaluated(reason)`, no-Newton zero-byte log, zero per-iteration stderr duplication, flush-before-next/return을 포함한다. - Exact CSV paths, trimmed headers, exact `shellNL` `Frame` value, source node/component identity, constrained reaction mask, missing/extra/duplicate rows, nonfinite values를 tolerance 전에 precheck한다. - Declared family에는 `docs/TOLERANCE.md`만 적용한다. `U`는 blocking, `UR`은 warning-only, `RF1/RF2`, `RF3`, physical spatial `RM1/RM2`는 blocking으로 유지하고 `RM3`와 모든 stress CSV value는 제외한다. - Optional stress CSV는 read-only inventory/order evidence only로 유지한다. Nodal stress extrapolation, corner averaging, `S33` synthesis, element-label-order matching을 추가하지 않는다. - Final HDF5 projection, parser diagnostics, schema tests, reference comparison tests, log lifecycle tests는 Coordinator를 통해 전달한다. 이 문서만으로 parser, C++ API, reference artifact, comparison-result, physics, release 변경을 승인하지 않는다.