# FESA Phase 1 검증 보고서

## 1. 검증 기준과 실행 증거

이 보고서는 2026-08-03에 `feat-beam-reference-qualification`에서 새 Debug 빌드와
테스트를 실행해 수집한 결과다. FESA Beam 검증은 다음 두 gate를 독립적으로
운영한다.

- Gate A — FESA 정식화 적합성: FESA가 채택한 선택적 감차적분 Timoshenko
  정식화를 해석해, 에너지, 강체 mode와 평형으로 검증한다.
- Gate B — Abaqus 결과 상관성: Abaqus B31과 FESA의 정식화 차이를 인정하고
  요청된 결과의 component별 RMSE와 Relative L2를 보고한다.

실행 결과는 다음과 같다.

| 명령 | 결과 |
|------|------|
| `cmake --build --preset windows-debug` | MSVC v145 Debug x64 빌드 성공, 새 경고 없음 |
| `ctest --preset windows-debug --output-on-failure` | 68/68 통과 |
| `uv run --with pytest python -m pytest -v -rs` | 20/20 통과 |
| `fesa solve` 후 `fesa-reference-compare` | 42개 요청 위치와 18개 component metric 생성, exit code 0 |

Harness child의 관리형 WindowsApps PowerShell은 `CreateProcessAsUserW` 오류로 명령을
시작하지 못했다. 위 명령은 동일 저장소와 preset에서 현재 세션이 직접 실행했으며,
executor 환경 문제를 테스트 성공으로 간주하지 않았다.

## 2. Gate A — FESA 정식화 적합성

### 2.1 요소 정식화와 회복

`tests/unit/elements/beam3d2_test.cpp`의 다음 검증이 모두 통과했다.

| 검증 | 증거 | 판정 기준 |
|------|------|-----------|
| 행렬 유한성·대칭성 | `Beam3D2.ProducesFiniteSymmetricLocalAndGlobalStiffness` | local/global 12×12 전 항 유한, 대칭 항 bitwise equality |
| 강체 mode | `RigidBody.SixIndependentModesHaveZeroStrainEnergy` | 3개 병진과 3개 회전 mode의 energy가 roundoff bound 이내 |
| 축·비틀림 | `Timoshenko.ReproducesAnalyticalAxialSubmatrix`, `ReproducesAnalyticalTorsionalSubmatrix` | 해석 stiffness 대비 `512*epsilon` 상대 규모 |
| 굽힘 y/z | `Timoshenko.ReproducesConstantCurvatureEnergyAboutLocalY/LocalZ` | 해석 strain energy 대비 `512*epsilon` 상대 규모 |
| 전단 y/z | `Timoshenko.ReproducesConstantShearEnergyInLocalY/LocalZ` | 해석 strain energy 대비 `512*epsilon` 상대 규모 |
| 세장비 | `Timoshenko.AvoidsShearLockingAcrossSlendernessSweep` | `L/h={2,10,100,1000}`, `4096*epsilon*(L/h)^2` 상대 규모 |
| 회전 불변성 | `Beam3D2.PreservesGlobalEnergyUnderRigidCoordinateRotation` | 회전 전후 global energy가 `4096*epsilon` 상대 규모 이내 |
| 단면력 회복 | `BeamRecovery.*`, `SectionForce.*` | 축력, 비틀림, 전단, My, Mz와 biaxial 부호를 양 끝에서 검증 |

### 2.2 Physics sanity와 결정성

| 검증 | 증거 | 결과 |
|------|------|------|
| full-system 평형 | `StaticEquilibrium.ReturnedFieldsSatisfyOriginalFullEquation` | `Ku-f-r` 각 DOF가 `1e-12` 이내 |
| 비영 지정 DOF | `ConstraintElimination.ShiftsNonzeroPrescribedValueAndPreservesOriginalSystem` 및 `LinearStaticAnalysis.SolvesAllConstrainedSystemWithoutPardiso` | reduced RHS 이동, full displacement와 reaction 검증 |
| 반력 | `Reaction.UsesOriginalFullEquilibriumEquation` | 원래 full equation에서 회복 |
| production pipeline | `MinimalCantileverPipeline.WritesReadableFiniteEquilibratedResults` | parser→solver→HDF5 결과 유한, 전역 반력 평형 `1e-12` 이내 |
| reference 평형 | `CantileverReference.CorrelatesAllAvailableAbaqusResults` | 절대 `1e-12`와 적용 하중 대비 상대 `2e-13` 중 큰 허용치 이내 |
| 병렬 결정성 | `ThreadCountDeterminism.AssemblyAndLinearStateAreBitwiseStable` | thread `{1,2,16}`에서 10회 반복, matrix/displacement/reaction bitwise 동일 |

Gate A disposition은 **PASS**다.

## 3. Gate B — Abaqus 2024 결과 상관성

### 3.1 모델과 비교 계약

- Abaqus provenance: `reference/cantilever beam/cantilever beam.inp`와 변위, 반력,
  요소 단면력 CSV. 원본 모델의 `SCF=0.25`는 유지한다.
- FESA projection: `reference/cantilever beam/cantilever beam fesa.inp`. 기하, 재료,
  단면, 명시적 전단강성, 경계조건과 하중은 같고 `SCF=0`만 적용한다.
- entity join: nodal 결과 11개씩은 `(Instance, Node Label)`, 요소 단면력 20개는
  `(Instance, Element Label, End Node Label)`로 매칭한다.
- absolute scale: displacement `1e-10`, reaction `1e-8`, internal force `1e-8`.
- 서로 단위가 다른 component는 하나의 norm으로 합치지 않는다.

요소력 축 순서는 다음과 같다.

| FESA | Abaqus CSV |
|------|------------|
| `N` | `SF1` |
| `Vy` | `SF3` |
| `Vz` | `SF2` |
| `T` | `SM3` |
| `My` | `SM1` |
| `Mz` | `SM2` |

component \(c\)의 표본 수를 \(n\), 오차를 \(e_i=a_i-r_i\), absolute scale을
\(s_i\)라 하면 다음을 사용한다.

\[
\operatorname{RMSE}_c=\sqrt{\frac{1}{n}\sum_i e_i^2}
\]

\[
\operatorname{RelativeL2}_c=
\frac{\sqrt{\sum_i e_i^2}}
{\max\left(\sqrt{\sum_i r_i^2},\sqrt{\sum_i s_i^2}\right)}
\]

### 3.2 수집된 correlation metric

| 물리량 | component | count | RMSE | Relative L2 |
|--------|-----------|------:|-----:|------------:|
| displacement | Ux | 11 | 0 | 0 |
| displacement | Uy | 11 | 0 | 0 |
| displacement | Uz | 11 | 2.1970445023044601e-05 | 2.2349969291714038e-03 |
| displacement | Rx | 11 | 0 | 0 |
| displacement | Ry | 11 | 2.1672945177750166e-09 | 1.0416581667076092e-06 |
| displacement | Rz | 11 | 0 | 0 |
| reaction | RFx | 11 | 0 | 0 |
| reaction | RFy | 11 | 0 | 0 |
| reaction | RFz | 11 | 1.3385150002853335e-07 | 4.4393520322089023e-13 |
| reaction | RMx | 11 | 0 | 0 |
| reaction | RMy | 11 | 7.8149308366928907e-07 | 2.591919334788851e-13 |
| reaction | RMz | 11 | 0 | 0 |
| internal force | N | 20 | 0 | 0 |
| internal force | Vy | 20 | 0 | 0 |
| internal force | Vz | 20 | 2.7107472798172421e-07 | 2.7107472798172426e-13 |
| internal force | T | 20 | 0 | 0 |
| internal force | My | 20 | 474341.64902538335 | 0.082541022764834646 |
| internal force | Mz | 20 | 0 | 0 |

모든 요청 entity/component가 유일하게 매칭됐고 metric이 유한하므로 Gate B
disposition은 **EVALUABLE**이다. 이는 Abaqus B31과 FESA의 정식화가 동일하거나
임의 정확도 threshold를 통과했다는 뜻이 아니다. 현재 가장 큰 Relative L2는
`My=0.082541022764834646`, 다음은 `Uz=0.0022349969291714038`이다. pass/fail
envelope는 mesh 또는 해석적 연구 근거 없이 이 관측값에 맞춰 설정하지 않는다.

## 4. 검증 범위와 제한

- Abaqus 단면 도심 응력 CSV는 제공되지 않았다. `StressCsv`는 synthetic CSV schema와
  `(Instance, Element, End Node)` 매핑만 검증하며, 응력은 **not yet
  Abaqus-qualified**다.
- Gate B는 solver 간 correlation이며 Gate A의 해석적 정확도 검증을 대체하지 않는다.
- Abaqus golden 갱신에는 Abaqus 2024 환경과 수동 provenance 검토가 필요하다.
- FESA는 단위 변환을 수행하지 않으므로 입력과 CSV가 일관 단위계를 사용해야 한다.

현재 이중 gate 결론은 **Gate A PASS / Gate B EVALUABLE**이다.
