Files
FESADev/docs/mitc4-shell-feast-eigen2/implementation-review.md
T
2026-10-04 03:32:59 +09:00

520 lines
54 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MITC4 eigen 구현 독립 검토와 수정 이력
수정 전 finding·수정 확인·S3 보류·물리 한계·종료 제어·첫 구현 acceptance를 구분한다. 아래 각 문서의 날짜·검토 source와 미실행 범위를 유지하며 새로운 검토를 수행한 것은 아니다.
<a id="implementation-numerical-review-history"></a>
<a id="implementation-numerical-review-history--수정-전-구현-수치-검토-기록"></a>
## 수정 전 구현 수치 검토 기록
아래는 최초 검토 당시 관찰이다. 현재 판정·수정 상태는 [현재 보고서](implementation-review.md#implementation-numerical-review)를 따른다.
<a id="implementation-numerical-review-history--구현-독립-수치-검토"></a>
## 구현 독립 수치 검토
- Feature: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`.
- 검토일: `2026-09-09`; 대상: 질량·선형 stabilization·constraint-first reduction의 현재 작업본.
- 판정: **correction-required / verification-incomplete**. 최초 질량/축소 검토에 이어 메인의 추가 할당으로 FEAST backend를 검토했다. Procedure는 메인이 수정 중이므로 검토하지 않았다.
- 기준: [formulation](formulation.md), [mass/stabilization](formulation-mass-stabilization.md), [eigen](formulation-eigen.md), [controls](numerical-review-controls.md), [cases](numerical-review-cases.md), [requirements](requirements.md#requirements), [공통 tolerance](../TOLERANCE.md).
<a id="implementation-numerical-review-history--수정-사항"></a>
### 수정 사항
<a id="implementation-numerical-review-history--nr-imp-01--p2-질량-양성-검사가-불필요한-곱의-범위에-의존한다"></a>
#### NR-IMP-01 — P2: 질량 양성 검사가 불필요한 곱의 범위에 의존한다
[mitc4_shell.cpp](../../src/fesa/elements/mitc4_shell.cpp) 819–824행은
`m*j-h*h`의 finite/positive 여부를 검사한다. 채택 C2-09의 검사는
`j-h²/m>0`이며, 전자는 유한하고 잘 조건화된 질량도 density 배율만으로 거부한다.
평판 `A=4,t=2,h=0`에서 `m=2*rho,j=(2/3)*rho`다.
| rho | m*j의 binary64 결과 | j-(h/m)*h | 현재 guard |
| ---: | ---: | ---: | --- |
| 1 | 1.3333333333333333 | 0.6666666666666666 | true |
| 1e-180 | 0 | 6.666666666666667e-181 | false |
| 1e180 | inf | 6.666666666666666e179 | false |
이는 Python 표준 `float`/`math.isfinite`로 실제 계산한 scalar 반례이며 C++ solver 재현은 미실행이다.
모든 사례의 `m,j`와 nodal block 성분은 finite positive이고 density 배율은 condition number를 바꾸지 않는다.
**수정:** 승인된 Schur variance를 불필요한 `m*j`, `h*h` 중간 곱 없이 평가하고 strict finite/positive 판정은 유지한다.
두 배율의 element mass 회귀로 실패를 재현하고, 정상 mass의 density 비례 및 잘못된 variance의 거부를 확인한다.
근거: M4/M5, C1 및 C2-09, 요구 003/014/026. 허용오차·rank·density 계약 변경은 필요하지 않다.
<a id="implementation-numerical-review-history--nr-imp-02--p2-새-oraclecovariance-검사가-승인된-metric을-사용하지-않는다"></a>
#### NR-IMP-02 — P2: 새 oracle/covariance 검사가 승인된 metric을 사용하지 않는다
[mitc4_shell_test.cpp](../../tests/unit/elements/mitc4_shell_test.cpp) 837–845, 901, 922–937행은
차원이 다른 `C0/C1/C2` 및 translation/rotation matrix entries에 동일한 absolute `1e-12`를 적용한다.
특히 `ExpectGlobalZCovariance`는 `D^T M D`, `D^T K D`와 상대 Frobenius 지표를 계산하지 않는다.
이 검사는 현재 fixture의 entry 오차를 확인하지만 C1/C2-02/03의 통과 evidence를 대신할 수 없다.
**수정:** scalar Ck 오차는 `m_e(t/2)^k`, matrix congruence는 같은 `ell`의 D congruence 후
`norm(R-S)/(norm(R)+norm(S))`로 검사한다. Finite-first와 승인된 zero branch를 유지한다.
단위변환 E2-C20을 함께 연결하여 고정 절대 단위에 의존하지 않음을 확인한다.
<a id="implementation-numerical-review-history--feast-추가-검토-수정-사항"></a>
### FEAST 추가 검토: 수정 사항
대상은 [mkl_feast_eigen_solver.cpp](../../src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp)의
2026-09-09 추가 할당 시점 작업본이다. 아래 행 번호는 후속 수정 전이며 기준은 C1/C3/C5/C6다.
| Finding | 위치·영향 | 필요한 수정·검증 |
| --- | --- | --- |
| NR-IMP-03 **P1** | 420–425행은 optional count의 **모든** 오류를 fallback으로 처리한다. Invalid/SPD/inner-solver 오류도 이후 solve 성공으로 우회될 수 있다. | `info=1,2,3,-5`만 optional search 종료로 분류하고 나머지는 즉시 실패. E2-C21 status 주입으로 각각 확인 |
| NR-IMP-04 **P1** | 429–433행은 세 guard의 서로 다른 successful count를 모두 fatal로 처리한다. Spectrum이 guard 사이에 있으면 정상적인 nondecreasing count 차이이며 endpoint collision이다. 반대로 서로 다른 interval들의 global monotonicity는 검사하지 않는다. | C5의 후보 `0,+1,-1,+2,-2,+4,-4` times delta 최대7개와 certified fallback을 구현. Successful count가 interval 포함관계에 모순될 때만 count-inconsistent. 정상 collision과 실제 역전 mock을 구분 |
| NR-IMP-05 **P1** | 451–457행의 final interior endpoint 검사는 central count 한 번뿐이다. 500–505행의 retry는 같은 b에서 capacity만 늘리며 재count하지 않는다. 542–546행의 endpoint separation 실패는 retry 경로에 들어가지 않는다. | Final interior b의 세 guard 재확인, 저장된 더 큰 certified b 선택→재count→capacity 갱신을 solve retry와 endpoint 실패에 연결. 최종 b0 및 변경 없는 입력 재호출 금지·3회/budget 한계 확인 |
| NR-IMP-06 **P2** | 360–365행은 초기 retry 때 Gershgorin padding 대신 전체 bracket 폭을 2^j배 한다. 불필요하게 넓어진 contour는 승인된 controls와 다른 수렴 동작을 만든다. | 원 gL/gU를 보존하고 **16delta padding만** 2^j배로 outward 재계산. Zero B의 ±2^j branch는 현재 정의와 일치 |
| NR-IMP-07 **P2** | 175–219행의 QR은 reflector norm의 absolute 1e-12만 검사하고 relative pivot, positive R diagonal, post-QR Gram 검사를 수행하지 않는다. | C6의 원 column scale 대비 pivot·positive R sign·Gram<=1e-12를 실제 계산. Fixed seed/n,m0별 재현성과 부적합 QR 실패 검증 |
| NR-IMP-08 **P1** | 236–238/312/459–473행은 일부 size_t product만 검사한다. n²/nm0의 byte·PTRDIFF_MAX·container max_size와 count padding arithmetic 사전검사가 없고 allocation exception 변환도 이 함수에 없다. | 모든 integer/byte operation 전에 C6 범위 검사, allocation/length 오류의 structured failure 경로를 연결. 불가능한 count m0도 cast 전 `0<=m0<=n` 검증(338–344행). E2-C22의 boundary/실패 주입 |
| NR-IMP-09 **P2** | 513–535행은 finite 검사 전에 eigenvalues를 sort한다. 565행은 physical lambda 환산의 finite/비영 underflow 검사를 하지 않는다. 492–495행은 epsout을 무조건 available로 기록하고 finite 검사하지 않는다. 571–579행은 Gram 최대 entry만 계산한다. | Raw eigenpairs finite-first 후 sort, `mu*s` overflow/비영→0 실패, epsout finite 검증, 전체 c의 `norm(G-I)F/sqrt(c)`와 pairwise 기준을 별도 적용. Public 결과의 gram_error 의미를 승인된 schema에 맞춤 |
추가 관찰: `ValidateSymmetry` 118–143행의 max-entry 기준도 C2-01의 Frobenius 지표와 다르다.
Failure 반환은 local `calls`를 버리므로 실패/fallback 이력을 상위 diagnostic/log에 남기는 연결을 확인해야 한다.
현재 [backend tests](../../tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp)는 actual n1/zero/repeated/prefix/negative/thread/request를 다루지만,
위 C5 status·collision·monotonicity·final guard·retry·512 call budget·overflow failure injection은 확인되지 않았다.
Backend를 이 검토에서 실행하지 않았으며 actual FEAST의 성공 또는 실패를 새로 주장하지 않는다.
<a id="implementation-numerical-review-history--정적-대조에서-일치한-구현"></a>
### 정적 대조에서 일치한 구현
| 경로·행 | 확인 내용 |
| --- | --- |
| [mitc4_shell.cpp](../../src/fesa/elements/mitc4_shell.cpp) 292–299, 725–805 | `S=-[d]cross`, 27점 xi→eta→zeta 적분, 각 점 geometry/J 검사, 대칭 Ck와 MC의 네 block 부호·DOF 순서가 M1/M3와 일치 |
| 같은 파일 808–850 | 보존된 Ck의 실제 row sum에서 m/h/j를 만들고 nodal tensor를 재구성한다. Full24 row sum 또는 인공 drilling mass를 사용하지 않음 |
| 같은 파일 649–716 | 초기 physical rotary 8개 전부의 trace mean, zero 포함 분모8, negative/nonfinite/allzero 거부 및 complete K 재조립이 S1과 일치 |
| [eigen_reduction.cpp](../../src/fesa/analysis/eigen_reduction.cpp) 65–112 | 실제 component BC를 먼저 적용하고 constrained director의 **정확한 비영** 성분으로 analytic null을 판정. Partial URZ의 양의 mass를 보존 |
| 같은 파일 116–200, 311–332, 359–370 | `Mp/scale`의 block Cholesky, small triangular inverse action으로 rcond_inf, `P L^-T` lift, nodal stiffness congruence 및 constrained-zero scaled mode 복원 방향이 E1–E4와 일치. Global dense inverse 없음 |
| 같은 파일 238–280, 289–349 | 원 scaled constrained MZ/KZ/PZ를 검사하고 null stiffness kappa의 strict positivity를 유지. `nz=0`의 storage0는 상위 I/O에서 N/A flag와 연결해야 함 |
<a id="implementation-numerical-review-history--아직-연결해야-하는-검증"></a>
### 아직 연결해야 하는 검증
다음은 할당된 [element tests](../../tests/unit/elements/mitc4_shell_test.cpp)와
[reduction tests](../../tests/unit/analysis/eigen_reduction_test.cpp)의 정적 coverage 확인이다.
다른 파일의 미확인 coverage를 전체 저장소의 부재로 단정하지 않는다.
- E2-C02/03/04/11: warped oracle는 현재 Ck(0,0) 및 전체 scalar sums만 확인한다.
모든 Ck/row, `sum(m_i X_i+h_i d_i)`의 독립 first spatial moment, MC/ML 각각의 직접 kinetic energy,
Jensen pairwise integral·mesh 차이, consistent rank20·nodal rank5·drill null·여섯 physical rigid mass Gram이 필요하다.
- E2-C08/09/10: 원 S3 exact scalar target은 구현되어 있다. **회전한 같은 S3 fixture**의 실제 partial BC spectrum과
admissible tangent moment `(5/3)b`의 정적 응답·full residual covariance는 아직 이 두 파일에서 확인되지 않았다.
Zero 포함 rotary inventory와 독립 tangent basis, invalid inventory 경계도 별도 evidence가 필요하다.
- E2-C13/14/15/16: 현 reduction 3개 테스트는 URZ positive, full-free aligned null/Kpz 실패, p=1e-8 conditioning 실패를 다룬다.
p=1/2000 positive 성공과 p=0 exact null, 2개 free rotations, drill-only free/all-fixed node/global n0,
nonpositive kappa·MZ 위반, **비대각 Mp** `[[2,1],[1,2]]`의 lambda `2,10/3` 및 original-mass 복원 검증이 필요하다.
- E2-C06/12/20/26: 공유 node의 section별 stable assembly·재현성, frozen nonlinear scale/미분/rollback,
density와 단위변환, retained static·pressure synthetic evidence는 이번 할당 파일 범위 밖의 후속 연결 사항이다.
<a id="implementation-numerical-review-history--실행-경계와-잔여-위험"></a>
### 실행 경계와 잔여 위험
이번에는 문서·source·test를 읽고 scalar binary64 반례만 실행했다. Build/CTest·FEAST·external reference·physics 검증은 실행하지 않았다.
메인의 focused build/test 성공 전달은 별도 실행 evidence이며 본 검토가 전체 기능 완료를 승인하지 않는다.
Reference artifact와 제외 예제는 읽거나 수정하지 않았다. 상위 계약·source·test·Git도 수정하지 않았다.
남는 위험은 거의 정렬된 partial BC의 forward accuracy, geometry 평가점 밖 injectivity,
원 free residual·전체 c개 Gram을 포함한 procedure 복원 검증과 actual FEAST의 count/cluster/runtime다.
<a id="implementation-numerical-review"></a>
<a id="implementation-numerical-review--구현-독립-수치-검토"></a>
## 구현 독립 수치 검토
- Feature: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`; 검토일: `2026-09-09`.
- 판정: **correction-required / verification-incomplete**.
- 대상: 질량·stabilization·reduction, 수정된 FEAST backend와 `linear_frequency_procedure.cpp`. Writer는 검토하지 않았다.
- 기준: [formulation](formulation.md), [mass/stabilization](formulation-mass-stabilization.md), [eigen](formulation-eigen.md), [controls](numerical-review-controls.md), [cases](numerical-review-cases.md), [requirements](requirements.md#requirements), [공통 tolerance](../TOLERANCE.md).
- 최초 finding·scalar 반례는 [이전 검토 상세](implementation-review.md#implementation-numerical-review-history)에 보존한다. 아래는 후속 수정본에 대한 현재 판정이다.
<a id="implementation-numerical-review--이전-finding의-수정-확인"></a>
### 이전 finding의 수정 확인
Central Count·안정적 QR까지 수정한 최신 저장본 `mkl_feast_eigen_solver.cpp`를 직접 대조했다.
아래 source 판정과 메인이 전달한 실제 재실행 결과를 구분한다.
| Finding | 현재 상태 | 최신 정적 evidence |
| --- | --- | --- |
| NR-IMP-01 | **addressed** | [mass source](../../src/fesa/elements/mitc4_shell.cpp)의 `j-h*(h/m)` strict finite/positive와 [density 회귀](../../tests/unit/elements/mitc4_shell_test.cpp) 확인. 메인이 실제 통과를 전달 |
| NR-IMP-02 | **open** | Mass Ck oracle/`ExpectGlobalZCovariance`의 승인된 차원별 scale·D congruence 적용 및 단위변환 coverage 미완료 |
| NR-IMP-03 | **addressed in source** | [backend](../../src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp) optional info1/2/3/-5만 fallback, 나머지는 실패 |
| NR-IMP-04 | **addressed in source** | Offsets `0,±1,±2,±4`, 21-call 예약으로 optimization384 유지, 각 Count/solve의 total512 guard 확인. Central Count 473–484행에서 동일 lower의 모든 성공 이력에 대해 upper/count 단조성과 동일 endpoint count 일치를 검사 |
| NR-IMP-05 | **addressed in source** | 최초·retry interior 3-count guard, previous/new capacity 비교와 실제 interval 변경 조건을 확인. Retry Count도 위 central history 검사를 거침 |
| NR-IMP-06 | **addressed in source** | 초기 재시도는 16delta padding만 2^j배 |
| NR-IMP-07 | **addressed in source** | 229–245행의 relative pivot·`alpha=-copysign(norm,x0)` reflector, 276–290행의 Q column sign으로 positive R diagonal 및 `norm(Q^T Q-I)_F/sqrt(m0)<=1e-12` 확인 |
| NR-IMP-08 | **production guards added; failure coverage incomplete** | n²/nm0 storage·PTRDIFF/container·padding·count[0,n] 검사, 주요 allocation 변환 및 [procedure](../../src/fesa/analysis/linear_frequency_procedure.cpp)의 bad_alloc/length_error 변환 확인. 경계/실패 주입 검증 미확인 |
| NR-IMP-09 | **addressed in source** | Successful epsout/loop 및 유효한 반환 범위의 모든 eigenvalue/vector finite 검사를 endpoint/retry 앞에 수행. Finite-first sort, physical lambda 환산, exact-zero nonfinite backend res의 unavailable 처리, all-c pairwise/Frobenius Gram acceptance 확인 |
<a id="implementation-numerical-review--최신-backend-correction과-검증-경계"></a>
### 최신 backend correction과 검증 경계
[Backend source](../../src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp)의 이전 count/QR/nonfinite-vector finding은
현재 저장본에서 수정됐다. Optional guard가 중간 실패해도 이전 성공 Count는 공통 이력에 남아 이후 대조에 사용된다.
Signed Householder는 cancellation을 피하며 Q column sign 변경은 R row sign 변경과 대응하므로 positive diagonal 규칙에 맞는다.
`ValidateSymmetry` 134–166행도 scale로 정규화한 Frobenius 비율이며, max-entry acceptance라는 이전 finding은 해소됐다.
C5 실패/status/동일 endpoint/역전/retry/budget/allocation 주입은 **실행 evidence 미완료**다.
`CallHistory`는 residual 실패에 연결됐지만 다른 early failure의 전체 이력 보존도 미확인이다.
Source correction 확인을 해당 실패 경로의 실행 통과로 확대하지 않는다. NR-IMP-02의 mass oracle 차원별 scale은 별도로 남는다.
<a id="implementation-numerical-review--frequency-procedure와-reduction의-대조-결과"></a>
### Frequency procedure와 reduction의 대조 결과
[Procedure source](../../src/fesa/analysis/linear_frequency_procedure.cpp)에서 다음 수학 계약과의 불일치는 발견하지 못했다.
- 161–185행: active shell 길이 scale과 analytic reduction 뒤 actual FEAST를 사용하고, exact-zero A의 scale 후보는 `min(E/rho/ell²)`로 만든다.
- 201–223행: K/M Frobenius norm은 실제 free/free 부분에 D congruence를 적용해 같은 단위로 계산한다.
- 235–270행: `q=D y`, scaled source maximum-component sign, actual ML mass 정규화, 최종 phi에서 g/y 재계산, 원 조립 K/ML의 모든 free DOF residual·Rayleigh·energy를 평가한다. Constrained components는 exact0이며 modal reaction을 생성하지 않는다.
- 271–305행: whitened/operator residual 및 raw lambda를 보존한 near-zero/positive·connected cluster·frequency validity를 검사한다. 전체 c를 검증하고 첫 N개만 mode/vector로 공개한다.
- 306–319행: 정규화된 physical phi와 actual mass action으로 전체 c의 Gram/각 pairwise orthogonality를 다시 계산한다. `nz=0`의 null metric은 applicable flag0와 연결된다.
- [Reduction tests](../../tests/unit/analysis/eigen_reduction_test.cpp)에 비대각 Mp의 lambda2,10/3·original mass 복원, p1/2000 positive, 2 free rotations, MZ 위반, drill-only/all-fixed empty 실패가 추가됐다.
<a id="implementation-numerical-review--원본-eigen-column20-residual-실패의-한정-재검토"></a>
### 원본 eigen column20 residual 실패의 한정 재검토
메인이 전달한 correction 후 실제 값은 `n=3125,c=22,m0=33`, backend 26 calls,
`rho_B=1.48674481038207483e-10`이다. **현재 근거로 procedure/reduction의 구현 결함이 원인이라고 판정할 수 없으며,
보고된 값에 대한 실패 처리는 승인 C3-02/C5와 일치한다.** 기준1e-10을 48.6745% 초과하고,
requested10 밖의 column20도 검증 대상인 전체 c개에 속하므로 삭제하거나 검사에서 제외할 수 없다.
FEAST 성공 status·trace stopping은 이 독립 operator residual 기준을 대신하지 않는다.
- [Procedure](../../src/fesa/analysis/linear_frequency_procedure.cpp) 184–186행은 backend 실패를 즉시 반환한다.
따라서 201행 이후의 scaled original-free norm, `q=D y`, 최종 physical normalization·Gram/energy는
이번 실패 때 실행되지 않았다. 그 계산에서 이번 backend column20 오류가 생겼다는 설명은 실행 순서와 맞지 않는다.
- 최신 [reduction](../../src/fesa/analysis/eigen_reduction.cpp) 116–206, 301–356행을 다시 대조했다.
`Mp/scale=L0 L0^T`, lift=`P L0^-T/sqrt(scale)`, `A=lift^T Khat_f lift`의 전치·양쪽 D·질량·단위는 일치한다.
실제 global BC의 exact null 처리와 원 MZ/KZ/PZ 검증에도 이 residual 실패를 설명하는 수식 오류를 발견하지 못했다.
이는 실제 큰 모델의 forward accuracy 보장이거나 모든 입력 inventory의 독립 검증 완료를 뜻하지 않는다.
- Backend가 계산하는 `norm((A/s)x-mu*x)/norm(x)`는 해당 승인 metric이다.
모드 진폭을 바꿔도 비율은 같고 물리 mass 정규화로 이 값을 낮추려는 변경은 근거가 없다.
메인이 전달한 column20의 correction 전·후 actual rerun 진단값은 다음과 같다.
| 관찰 | 이전 실행 | 최신 correction 후 실행 |
| --- | ---: | ---: |
| FEAST info / loop | 0 / 4 | 0 / 4 |
| trace epsout | 2.82730672643927457e-14 | 2.82488401287762986e-14 |
| full CSR rho_B | 1.42356735413003805e-10 | 1.48674481038207483e-10 |
| mirrored upper CSR rho_B | 1.42356735389686902e-10 | 1.48674481542089335e-10 |
| full/upper difference action norm | 1.24572423402534915e-17 | 1.38724134018909290e-17 |
**해당 실행 판정: mandatory all-c residual failure confirmed.** FEAST가 실제 받은 symmetric upper operator에서도
같은 기준을 넘으므로 full/upper symmetry roundoff는 이 실패의 원인이 아니다.
고정 `fpm[5]=1` trace stopping이 4회에서 충족된 결과이며 **최대20회 반복을 소진한 실패가 아니다**.
따라서 단순히 maximum loop를 늘리는 것을 확인된 원인 수정으로 제시할 수 없다.
작은 trace 변화나 `info=0`을 모든 eigenpair residual의 통과로 해석하지 않는다.
최신 진단은 위 central Count·안정적 QR correction **이후 실행**이다. 확인된 구현 결함을 수정한 뒤에도
승인 fixed controls로 얻은 이 모델의 결과가 mandatory all-c 기준을 충족하지 못한다.
이는 모든 잠재적 구현 결함을 배제한 증명은 아니지만, 현재 reference 성공 또는 기능 완료 판정을 막는 실제 evidence다.
전체 runner 통과가 있더라도 이 필수 residual/reference 실패를 대신 해소하지 않는다.
FEAST stopping/control·후검증 기준·실패 retry 정책을 바꾸려는 경우에는 고정 C3/C5 계약의
**사용자 결정과 관련 수치 재검토가 먼저 필요하다**. 구현 correction은 기존 계약 안에서 진행할 수 있으며,
mass·seed·N 변경, column20 제외 또는 실패 후 미승인 재시도의 근거가 되지 않는다.
이번 검토자는 actual rerun을 직접 실행하지 않았고 전달받은 진단값과 read-only 실행 경로를 대조했다.
<a id="implementation-numerical-review--남은-검증과-실행-경계"></a>
### 남은 검증과 실행 경계
- **NR-IMP-10 / upstream-contract-conflict:** S3의 public static global moment failure는 exact numerical drilling torque에서 발생한다. `norm(e_M)=95/41476`, 현재 normalized metric≈7.328771e-4다. [독립 유도와 판단](implementation-review.md#implementation-numerical-review-s3-static)을 참조한다. 메인은 수정된 E2-C09 direct pencil/full Kq-F covariance 테스트 통과와 별도 public rejection 재현을 전달했다. 수학 case의 검증은 연결됐지만 public 지원 범위의 평형 충돌은 미해결이다.
- [Procedure integration tests](../../tests/integration/analysis/linear_frequency_procedure_test.cpp)는 S3 direct pencil/full residual covariance와 free panel의 여섯 near-zero mode/all-c evidence를 다룬다. Density4 및 length1024의 물리 단위변환에서 lambda·rotation amplitude·residual/energy를 검증하는 테스트도 추가됐고 메인은 최신 focused 통과를 전달했다. Wrong-mass/vector/constraint mutation 검증은 미완료다.
- Mass의 모든 warped Ck/rows·first spatial moment·두 mass의 독립 energy/Jensen·mesh 오차·rank20/rank5·physical rigid Gram, 독립 tangent inventory 및 frozen nonlinear/retained static 검증은 최초 상세의 coverage gap이 남아 있다.
- [Actual FEAST tests](../../tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp)에 zero/positive known spectra의 lowest prefix와 Givens congruence로 회전한 close distinct spectrum/Gram 검증이 추가됐고 메인은 최신 focused 통과를 전달했다. C5 status·guard collision/역전·retry·budget·allocation 주입, repeated eigenspace projector 및 세 반복 재현성 evidence는 미확인이다.
- 메인이 전달한 최신 source checkpoint는 `22c9d44`이며 configured full runner는 **395개 중394 통과, 원본 eigen 1개 실패, 155.31초**다. Input/FEAST/procedure/writer focused41은 새 density·unit scaling을 포함해 모두 통과했다. 본 검토자는 실행 로그를 직접 재검증하거나 build/test를 실행하지 않았다. 필수 reference/physics 완료는 승인하지 않는다.
- 최초 원본 eigen 실행의 10669ms 뒤 column20 `eigenpair-validation-failed`는 위 actual rerun의 full/upper residual·loop/epsout evidence로 구체화됐다. 필수 reference/전체 기능의 성공 판정은 할 수 없다.
- 이번 후속 수정은 본 보고서뿐이며 과거 검토 상세는 보존했다. 상위 계약·source·tests·writer·Git·reference는 수정하지 않았고 reference·제외 예제는 열람하지 않았다. 잔여 위험은 mandatory residual와 public static 계약 충돌, near-aligned forward accuracy, geometry 평가점 밖 injectivity 및 필수 coverage다.
<a id="implementation-numerical-review-s3-static"></a>
<a id="implementation-numerical-review-s3-static--s3-partial-bc-정적-평형-불일치"></a>
## S3 partial-BC 정적 평형 불일치
- Feature: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`; 검토일: `2026-09-09`.
- Finding: **NR-IMP-10 / upstream-contract-conflict**. [현재 보고서](implementation-review.md#implementation-numerical-review)의 추가 검토다.
- 입력: [S3 정식화](formulation-mass-stabilization.md), [E2-C09](numerical-review-cases.md), 채택 [C7](../mitc4-shell-feast-eigen/numerical-review.md#numerical-review-controls), 기존 [linear formulation §14.1](../linear-static-mitc4-shell/formulation.md), [linear I/O §6.5](../linear-static-mitc4-shell/io.md).
<a id="implementation-numerical-review-s3-static--독립-수치-결론"></a>
### 독립 수치 결론
`d=(3/5,0,4/5)`, node1 URZ만 free, applied moment `(-4/3,0,1)=(5/3)b`,
`M0=1`인 승인 S3에서 다음은 정확하다. Moment의 단위는 `[force·length]`다.
\[
\theta_{1Z}=7500/10369,\qquad
\gamma_1=d^T\theta_1=6000/10369,\qquad k_d=19/4800.
\]
Physical stiffness의 spatial total moment는 0이지만,
`Kdrill`은 node1에 `tau_d=kd gamma1 d`를 더한다. `r=Kq-F`의 free 성분은 0이므로
applied load와 **constrained full residual**을 더한 기존 global moment evidence는
\[
e_M=\tau_d=(57/41476,\ 0,\ 19/10369),\qquad
\|e_M\|=95/41476\approx0.002290481242164143\ne0.
\]
Global Z45° 회전에서는 `e_M'=Q e_M`이며 norm은 같다. Applied moment가 tangent라는 사실은
partial global BC가 만든 `gamma1!=0`을 없애지 않는다. Load의 constrained X 성분을 추가해도
`Ff=1`과 위 nonzero torque는 그대로다. Physical rigid representative의 회전은 `P_i Omega`이고,
full spatial `Omega`와 numerical drilling energy를 혼동하면 이 불일치를 놓친다.
[기존 독립 oracle](numerical-review.md#numerical-review-evidence)의 첫 Python block을 그대로 실행한 뒤
원 `K,q,F`에서 constrained `Kq-F`, 각 node의 `X cross R+RM`을 따로 합산했다.
현재 [global recovery](../../src/fesa/results/global_equilibrium_recovery.cpp) 193–249행과 같은
정규화에서 `reaction moment scale=3.1253278233567374`,
`applied moment scale=5/3`, `eta_M=0.0007328771161369957`을 얻었다.
Fraction 산술의 위 exact torque와 일치한다. 따라서 기존 `1e-10` 검사가 실패하는 것은 예상된 결과다.
이것은 독립 수학 실행이며 C++/reference/solver 재실행이 아니다.
<a id="implementation-numerical-review-s3-static--e2-c09-검증-계층과-계약-경계"></a>
### E2-C09 검증 계층과 계약 경계
**E2-C09 자체는 public `LinearStaticProcedureExecutor::Execute`의 성공을 명시하지 않는다.**
S3, E2-C09 및 채택 C7의 해당 문장은 `thetaZ`, complete full `Kq-F`, same-BC/load 회전 공변성을 요구한다.
기존 독립 evidence도 direct1DOF partition solve로 이를 검증했고 zero global moment를 확인한 적은 없다.
따라서 production kernel의 complete K를 geometry/frame부터 재계산하여 `Kff theta=Ff`를 풀고,
전체 `r=Kq-F`와 원/회전 결과를 비교하는 **직접 pencil 테스트는 E2-C09에 맞는 검증**이다.
Constrained residual이 0이어야 한다는 의미로 complete residual 기준을 적용하지 않는다.
이는 case의 test layer를 바로잡는 것이며 threshold·물리·reaction 계약을 바꾸지 않는다.
동시에 **public static 실패는 별개의 실제 계약 충돌로 남는다.** 기존
[linear requirements](../linear-static-mitc4-shell/requirements.md)의 017–019는 이 global component BC와
tangent CLOAD를 지원하고, 029/046/057 및 기존 I/O는 full residual reaction과 spatial global balance를 유지한다.
새 요구 024/027은 그 의미를 보존한다. 승인된 M2의 rotation-only drill penalty와 이 조합은
S3에서 exact algebra상 동시에 public 성공 조건을 만족할 수 없다.
직접 테스트 통과만으로 public static 회귀가 해소되었다거나 이 입력이 새로 unsupported라고 선언하면 안 된다.
**처리:** E2-C09의 algebraic 검증과 현재 public failure 재현은 따로 보존한다.
Global balance를 완화하거나 drill torque를 빼거나 reaction을 projection하거나 fixture BC/load를 바꾸어 실패를 감추지 않는다.
Public static의 해당 supported 범위까지 성공해야 하는 완료 판정을 내려면 메인이 formulation/requirements owner에게
이 exact 반례를 전달하고, physics·지원 범위·recovery/acceptance 중 어떤 계약을 바꿀지 사용자 결정을 받아야 한다.
현재 numerical reviewer에게 그 변경을 자체 승인할 권한은 없다. Eigen S3의 finite-pencil target은 이 static 충돌로 바뀌지 않는다.
후속 실행 전달: 메인은 E2-C09를 direct pencil/full `Kq-F` covariance 테스트로 수정하여 통과했고,
별도 public static 테스트는 현재 global-equilibrium rejection을 재현한다고 보고했다.
이는 수학 case와 public 실패를 분리해 검증한 evidence이며, 지원 범위의 상위 계약 충돌을 해결하거나
public failure를 승인된 unsupported-input 진단으로 바꾼 결정은 아니다.
<a id="implementation-physics-review"></a>
> 이 절은 2026-09-10 residual stopping·후속 recovery 수정 이전의 발견 기록이다.
> Eigen all-c 잔차는 후속 수정으로 해소했고, 굽힘 단면력은 HHT 후속 작업에서 수정했다.
> 원래 실패 수치와 coverage 한계는 그대로 보존하며 S3는 보류다.
<a id="implementation-physics-review--구현-결과-물리-검토"></a>
## 구현 결과 물리 검토
- Feature: `mitc4-shell-feast-eigen2`; Owner: `physics-evaluation-agent`; 검토일: `2026-09-09`.
- 결론: **유지 대상 변위·평형 evidence는 타당하나 feature 완료 판정 불가**. 원본 eigen 필수 residual 실패, S3 public static 계약 충돌이 남는다. 별도로 기존 nonlinear 굽힘 단면력 복구 결함을 확인했다.
- 기준: [cases E2-C08/09/11/12/26](numerical-review-cases.md), [mass/stabilization S1–S3](formulation-mass-stabilization.md), [controls C3/C7](numerical-review-controls.md), [공통 tolerance](../TOLERANCE.md), [nonlinear I/O §7.5/8.5](../nonlinear-static-newton-raphson/io.md). 새 acceptance나 release 승인을 만들지 않는다.
<a id="implementation-physics-review--직접-확인한-evidence"></a>
### 직접 확인한 evidence
아래 `A/B/C`는 이번 검토 시 허용된 각 경로에서 `LastWriteTime`으로 선택한 최신 결과다. HDF5를 `h5py.File(path, 'r')`로 읽어 계산했으며 solver/build/test는 재실행하지 않았다. 이후 구현 수정·재실행 결과로 자동 승계하지 않는다.
| ID | Artifact |
| --- | --- |
| A | [.harness/build-ninja-msvc-debug/reference/mitc4-shell-s4-comparison/shell_results.h5](../../.harness/build-ninja-msvc-debug/reference/mitc4-shell-s4-comparison/shell_results.h5), 같은 폴더 [comparison.json](../../.harness/build-ninja-msvc-debug/reference/mitc4-shell-s4-comparison/comparison.json) |
| B | .harness/build-ninja-msvc-debug/reference/nonlinear-static-reference/shellNL/shellnl-s4-final-798076888102900-0/shellNL_results.h5(당시 경로: `../../.harness/build-ninja-msvc-debug/reference/nonlinear-static-reference/shellNL/shellnl-s4-final-798076888102900-0/shellNL_results.h5`, 현재 checkout에 없음), 같은 폴더 `shellNL_log.txt` |
| C | .harness/build-ninja-msvc-debug/reference/nonlinear-static-reference/shell/shell-s4-linear-limit-798054727288300-1/shell_results.h5(당시 경로: `../../.harness/build-ninja-msvc-debug/reference/nonlinear-static-reference/shell/shell-s4-linear-limit-798054727288300-1/shell_results.h5`, 현재 checkout에 없음) |
| Model/reference | [shell.inp](../../reference/shell/shell.inp), [shell displacements.csv](<../../reference/shell/shell displacements.csv>), [shellNL.inp](../../reference/shellNL/shellNL.inp), [shellNL displacements.csv](<../../reference/shellNL/shellNL displacements.csv>), [shellNL reactions.csv](<../../reference/shellNL/shellNL reactions.csv>) |
두 모델은 `36 S4 / 49 nodes`, `[-5,5]×[-5,5]` 평판, `t=0.5`, `E=2.1e11`, `nu=0.3`, 외곽 24 node의 6 DOF 고정, 중앙 `(Part-1-1, node 2)`의 `FZ=-100000`이다. A/C는 linear, B는 `nlgeom=YES`, factor `0.1..1.0`의 10 accepted frames다. 단위계는 입력의 일관된 미지정 단위: 변위 `length`, 힘 `force`, 모멘트·에너지 `force*length`, 응력 `force/length²`, 굽힘 단면력 `force`다. SI로 추정하지 않는다. 제외된 원본·복사·cache 모델과 stress reference CSV는 열거나 사용하지 않았다.
<a id="implementation-physics-review--변위-대칭-평형과-에너지"></a>
### 변위, 대칭, 평형과 에너지
| 관찰 | 직접 계산/저장 결과 | 해석 |
| --- | --- | --- |
| A/C 하중 방향·크기 | 중앙 `UZ=-2.3550441765084857e-5`; `UX=UY=URZ=0`; `max|URX/Y|=7.55060026636933e-6` | 음의 Z 하중에 음의 처짐. `|UZ|/t=4.71009e-5`로 작은 변형 영역 |
| A 대칭 | X/Y 반사 node 대응의 `max|ΔUZ|=3.21873e-20 length` | 중앙하중·고정 외곽의 대칭과 일치. 이 수치는 별도 새 판정 기준이 아닌 관찰 |
| A 평형 | HDF5 `global/verification_metrics`: free residual `1.07747756e-14`, force `1.12049747e-14`, moment `2.35981342e-15` | 각각 기존 `1e-10` 이내 |
| A 에너지 | physical energy `1.1775220882542212`; `Fᵀu/2=1.1775220882542428`; 상대차 `1.82912e-14` | 양의 선형 변형에너지와 일치, 기존 energy `1e-12` 이내 |
| B 최종 변위 | 중앙 `UZ=-2.355044174560645e-5`; `max|UX/UY|≈8.79961e-12`; 반사 `max|ΔUZ|=7.41128e-17` | 작은 면내 응답과 대칭 유지. 큰 변형의 외부 검증으로 확대할 수 없음 |
| B 선형극한 | C 대비 중앙 UZ 상대차 `8.27093e-10`; 전체 translation 최대차/최대 linear translation `3.73649e-7` | 작은 하중의 nonlinear displacement가 linear에 접근. 단면력 일치까지 뜻하지 않음 |
| B 에너지·증분 | factor0.1 energy `0.011775220886841211`, factor1 energy `1.1775220868030056`; 모든 10 frame 양수·증가, 각 2 Newton iterations | 거의 factor² 에너지와 factor 비례 처짐. Nonlinear에서 `Fᵀu/2`를 일반 항등식으로 요구하지 않음 |
B frame9의 `generalized_residual`에 **먼저 constraint mask**를 적용한 뒤 회전만 `J_l(phi)^(-T)`로 spatial 변환하고 current arm `X+u`를 사용했다. `|phi|<1.1e-5`에서 inverse-Jacobian의 안정적 소각 전개를 사용했다. 독립 합산은 저장된 `/global/equilibrium`과 roundoff 범위에서 일치한다.
- Constrained resultant force: `(-5.88263e-12, 6.25300e-12, 100000.00000082512) force`. Applied force `(0,0,-100000)`을 상쇄한다. Reference CSV 전체 RF 합의 Z는 `99999.99959279996 force`; 이는 review-only 관찰이다.
- Constrained resultant moment about origin: `(-5.63887e-11, 3.63798e-11, -4.17886618386e-5) force*length`. 중앙 applied force arm은 사실상 0이다.
- I/O §8.5의 nodal norm-sum scale은 force `100000.00439300563`, moment `780242.2734309232`. 독립 normalized force `8.25134e-12`, moment `5.35586e-11`로 각각 기존 factor-one `1e-8` 이내다. 저장 balance Z-force `8.25122697279e-7`, Z-moment `-4.17886618392e-5`를 zero-clamp하지 않았다.
- Accepted free residual: force infinity norm `0.031462885121074535 force`, matching external scale `100000`, internal-inclusive scale `100000.00000106206` → relative `3.14629e-7 <= 1e-2`. Moment infinity norm `3.3292018315478344e-6 force*length`, matching external scale exact0 → 기존 typed absolute `1e-3` 이내. 이 accepted residual과 global balance는 서로 다른 관찰이다.
<a id="implementation-physics-review--외부-변위-비교와-복구-결함"></a>
### 외부 변위 비교와 복구 결함
A comparison JSON은 49 nodes × 6 components의 294행, blocking U와 warning-only UR 각각 147행, 실패행·warning 0이다. U relative RMS `0.0010332756650397166`, UR `0.0029771372973060382`로 기존 `0.01` 이내다.
B는 실제 CSV/HDF5의 `(case-insensitive instance, source node label, component)`를 직접 대응했다. 49개의 유일 node identity가 일치하고 값이 모두 유한하다. 같은 공통 tolerance로 U relative RMS `0.0010332757195474177`, UR `0.0029771373238648216`, 각 family 실패행 0이다. Reaction CSV를 blocking 비교로 승격하지 않는다. 변위 수치 일치는 아래 복구 결함을 검출하지 않는다.
**PE-IMP-01 — 기존 nonlinear 굽힘 단면력 복구 결함, 구현 owner 인계.** B frame9 `(Part-1-1, element 3, midsurface GP2)`의 `S11` bottom/middle/top은 `[313254.63790344447, 3.694293034163272, -313246.91989287396] force/length²`이다. [nonlinear formulation §13.3](../nonlinear-static-newton-raphson/formulation.md)의 `M11=∫z S11 dz`, `z∈[-t/2,t/2]`와 평판의 두께 stress polynomial에서:
`M11 = t²/12 * (S11_top-S11_bottom) = -13052.1157874233 force`.
그러나 HDF5 `section_resultant[...,3]`는 `-26104.23157284045 force`, 비율 `1.999999999846297`이다. A의 같은 적분은 저장 M과 최대차 `9.09495e-12 force`로 일치한다. B의 모든 row/component 중 최대 굽힘 오차는 `13052.11578541715 force`다.
메인의 추가 읽기 허가로 [nonlinear recovery source](../../src/fesa/elements/nonlinear_mitc4_shell.cpp#L1243)를 확인했다. 두께 Gauss moment 가중치가 `0.25*t*zeta*stress`이므로 `z dz`가 요구하는 `0.25*t²*zeta*stress`의 thickness 한 개가 빠져 있다. `t=0.5`의 2배 차이와 직접 연결되며 차원도 맞지 않는다. 해당 파일의 `git diff HEAD -- <path>`는 비어 있다. 따라서 **현재 eigen 변경이 도입한 결함이라는 근거는 없고 HEAD에도 존재하는 복구 결함**이다. 코드 수정이나 새 gate를 수행하지 않았다. Finite stress/strain, 양의 에너지, U/UR 통과만으로 nonlinear section-resultant 물리 타당성을 주장할 수 없다.
<a id="implementation-physics-review--eigens3와-남은-범위"></a>
### Eigen/S3와 남은 범위
- **원본 eigen 미해결:** 메인의 최신 actual FEAST 전달값은 `676 shells / 729 nodes`, `nf=3750,nz=625,n=3125,N=10`, `c=22,m0=33,loop=4`, column20 `rho_B=1.48674481038207483e-10 > 1e-10`이다. Symmetric upper operator에서도 `1.48674481542089335e-10`이다. 요청 10개 밖이어도 all-c 검증 대상이므로 버릴 수 없다. Accepted modal HDF5와 Value reference comparison이 없으므로 원본 modal energy·mass normalization·mode shape 물리 검증은 **미실시**다. 최신 실패값은 메인 실행 전달이며 이 검토자가 eigen artifact를 직접 읽은 값이 아니다.
- **S3 public static 충돌:** [독립 수치 검토](implementation-review.md#implementation-numerical-review-s3-static)의 `thetaZ=7500/10369`, `lambda=10369/450`과 complete `Kq-F` 회전 공변성은 direct pencil 검증이다. `gamma1=6000/10369`에서 미상쇄 drilling torque `(57/41476,0,19/10369) force*length`, norm `95/41476≈0.002290481242164143`, normalized spatial moment `0.0007328771161369957 > 1e-10`가 남는다. 메인은 direct 검증 통과와 별도 public rejection 재현을 전달했다. 지원되는 static 성공을 의미하지 않으며 기존 reaction/global-balance 의미와의 계약 충돌 해결은 formulation/requirements owner와 사용자 결정 사항이다.
- **전달받은 synthetic 통과의 한계:** 작은 S3 eigen, free panel 여섯 rigid near-zero modes 및 all-c Gram, nonlinear tangent/objectivity/force/moment/free residual/energy/rollback 통과는 메인 실행 전달이다. 이번 검토자는 해당 test output을 직접 열지 않았다. Massless drill null과 양의 질량을 가진 physical rigid modes를 구분하는 근거이지만 큰 원본 모델 성공을 대신하지 않는다.
- Retained 외부 모델은 같은 평판의 매우 작은 변형이다. Arbitrary curved/director, 큰 회전·큰 변형의 외부 정확도, pressure external fresh comparison, modal stress/reaction, 일반 mesh 수렴은 여기서 검증하지 않았다. Synthetic pressure 통과가 외부 pressure coverage를 채우지 않는다.
검토 변경은 이 보고서뿐이다. 계약·허용오차·source·test·output·reference는 수정하지 않았다. 후속 action은 원본 eigen 실패와 S3 계약 충돌의 owner 처리, PE-IMP-01의 기존 recovery 결함 분리 추적이다.
<a id="implementation-feast-residual-review"></a>
<a id="implementation-feast-residual-review--feast-residual-stopping-독립-검토"></a>
## FEAST residual stopping 독립 검토
- Feature: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`; 2026-09-10.
- 범위: 사용자 승인 `fpm[5]:1→0`, `[2]=12`, `[3]=20` 유지. S3는 보류 상태를 유지한다.
- 판정: **`PASS` — 승인된 종료 제어 변경**, **`FAIL` — 원본 외부 Value acceptance**.
전체 기능 완료 판정이 아니다.
- 기준: [PRD](PRD.md), [ADR](ADR.md), [E4–E7](formulation-eigen.md),
[C3/C5](numerical-review-controls.md), [I/O](io.md#io-schema), [TOLERANCE](../TOLERANCE.md).
<a id="implementation-feast-residual-review--판단과-필요한-확인"></a>
### 판단과 필요한 확인
| 항목 | 독립 판단 |
| --- | --- |
| 종료 기준 | [Intel C parameter 표](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2026-0/extended-eigensolver-input-parameters.html)는 `[5]=0` residual, `1` trace이며 double epsilon은 `10^-fpm[2]`임을 명시한다. `1e-12` vendor stopping과 독립 all-c `1e-10`은 서로 다른 metric이다 |
| 불변 수식 | `B=A/s`, `mu=lambda/s`는 무차원이고 `rho_B=norm2(Bx-mu x)/norm2(x)`도 무차원이다. 종료 시점만 바뀌며 K/M, 부호·단위·DOF 순서, 적분, whitening, raw sort, 복구·state commit 식은 그대로다 |
| 전체 c | 요청 N 밖을 포함한 c개 residual과 pairwise/Frobenius Gram 검증 후 첫 N개를 공개해야 한다. FEAST 성공이나 작은 epsout으로 생략할 수 없다 |
| Zero·반복군 | 정확한 zero의 backend residual이 비유한이면 기존 available=false 표현을 유지한다. 독립 zero identity와 nonzero vector·Gram은 검증한다. Residual stopping에서 zero/mixed-zero의 실제 성공 여부는 실행으로 확인해야 하며 trace fallback을 추가하지 않는다. 반복군은 multiplicity·공간·Gram으로 판단하고 개별 벡터 방향의 유일성을 요구하지 않는다 |
| 상태·metadata | `SetControls`를 count/solve마다 재초기화하며 count의 `[49]=1` reset을 다음 solve에 전파하지 않는다. `base_fpm[5]=0,[2]=12,[3]=20`은 실제 새 HDF5에서 확인한다. `epsout`은 기존 trace 변화 진단량이며 residual stopping 지표로 이름·의미를 바꾸지 않는다 |
| 실패·안정성 | Refinement 최대20, bounded interval/capacity retry와 독립 검증 실패 즉시 종료를 유지한다. 새 종료 조건에서도 모든 conditioning의 수렴을 보장하지 않는다. Source의 미수렴/status/budget/allocation 전체 실패 주입 coverage는 기존 미완료 위험으로 남는다 |
검토 source: [backend](../../src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp),
[기존 backend tests](../../tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp).
추가로 [writer 검증](../../src/fesa/io/hdf5/eigen_hdf5_results_writer.cpp)의 `[5]=0` 제한과
[실제 HDF5 readback·변조 거부 검사](../../tests/unit/io/hdf5/eigen_hdf5_results_writer_test.cpp)를
대조했다. Schema의 field/type/layout 변경 없이 승인된 control 값만 일치시킨다.
본 검토자는 source/tests를 변경하거나 build/test를 중복 실행하지 않고 메인의 실행 로그를 대조했다.
<a id="implementation-feast-residual-review--새-실행-evidence"></a>
### 새 실행 evidence
개인 `.harness/config.json`과 preset의 MSVC x64 Debug·oneMKL 2026.1 설정을 확인했다.
| Evidence 경로 | 확인 결과 |
| --- | --- |
| `.harness/feast-residual-red.log` | 변경 전 backend와 실제 HDF5에서 `[5]=1`을 읽어 새 `[5]=0` 검사 두 개가 실패함 |
| `.harness/feast-residual-focused.log` | 12개 중 11 통과. Backend 10개는 n1/all-zero/mixed-zero/repeated40 prefix/close distinct·Givens/negative/invalid/thread 복원 포함. Writer 한 개는 실제 control readback·trace로 변조한 candidate 거부 포함 |
| 같은 focused log의 원본 reference | Application 성공 후 Value 비교까지 진행했으나 10 singleton 중 9개 실패. 기존 독립 residual 차단과 다른 외부 acceptance 실패이며 전체 검사가 통과한 것은 아님 |
| `.harness/feast-residual-full-run.log` | 구성된 전체 build/test에서 CTest 395개 중 394 통과, 원본 Value reference 한 개 실패, CTest exit8, 실행178.42초. 전체 통과 아님 |
| `.harness/build-ninja-msvc-debug/feast-residual-metrics.json` | `.harness/build-ninja-msvc-debug/extract_feast_residual.py`가 공식 원본 sibling HDF5를 read-only 추출한 값. 스크립트의 실제 dataset·mode_id 대응과 JSON을 대조함 |
원본 새 HDF5에서 `c=22,m0=33,info=0,loop=6`, controls `[2]=12,[3]=20,[5]=0`,
`epsout=2.4227135616446226e-17`을 확인했다. 전체 c개의 최대값은 다음과 같다.
| Metric | 실제 최대값 | 판정 기준 |
| --- | ---: | ---: |
| 독립 rho_B | `1.605467212112365e-13` | `<=1e-10`, PASS |
| Original-free eta_r / whitened eta_w | `9.981033437726324e-15` / `7.315529163435965e-15` | 각각 `<=1e-10`, PASS |
| Gram eta_gram / max_eta_orth | `1.3777964580680282e-15` / `1.6958335496991244e-15` | 각각 `<=1e-10`, PASS |
| Backend res | `8.280018892001454e-13` | vendor 진단량, 독립 rho_B 대체 아님 |
Value 행별 상대오차는 전부 5% 이내지만 Mode2–10의 singleton RMS는 1%를 초과한다.
Mode1은 `0.5648341627%`로 PASS, Mode2–10은 `1.3496440956%`–`4.2613310845%`로 FAIL이다.
양의 singleton은 RMS가 relative error와 같다는 [승인된 family 계약](reference-model.md)을
그대로 적용했다. 행 5%만으로 전체 PASS를 선언하거나 frame을 합쳐 RMS를 완화할 수 없다.
**필요한 후속 correction:** 메인이 이 외부 불일치의 원인·모델 가정을 별도 조사해야 한다.
현재 evidence만으로 질량·stabilization 등 특정 물리 식이 원인이라고 단정할 수 없다.
반복군 검사 통과를 모든 projector·3회 결정론·vendor 실패 주입 coverage 완료로 확장하지 않는다.
<a id="implementation-feast-residual-review--trace-stopping-이력과-잔여-위험"></a>
### Trace stopping 이력과 잔여 위험
[기존 실행 기록](implementation-verification.md)의 trace stopping 실패는
`n=3125,N=10,c=22,m0=33,info=0,loop=4`, raw solver column20의
`rho_B=1.48674481038207483e-10>1e-10`, `epsout=2.82488401287762986e-14`다.
Full/upper action 차이 `1.38724134018909290e-17`은 해당 실패 크기를 설명하지 못한다.
이 관찰은 trace 수렴이 각 vector residual 통과를 보장하지 않는 실제 반례이며,
새 제어의 개선 정도·통과 여부를 선취하지 않는다.
공통 외부 정책은 필요한 row의 누락·추가·중복·비유한을 tolerance 전에 거부하고 승인된
Value family에 적용한다. 독립 modal 허용오차를 외부 reference tolerance로 대체하지 않는다.
S3 정적 계약 충돌과 기존 nonlinear recovery 문제, 27개 case 전체 세부 coverage 미완료는
[기존 독립 검토](implementation-review.md#implementation-numerical-review)의 별도 제한으로 남는다.
<a id="implementation-first-version-review"></a>
<a id="implementation-first-version-review--첫-구현-acceptance-독립-검토"></a>
## 첫 구현 acceptance 독립 검토
- Feature: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`; 2026-09-10.
- 판정: **`PASS` — 사용자 승인 첫 구현 범위**. S3와 후속 정확도 개선은 보류 상태다.
- 적용: 사용자 승인 외부 Value 5%, [PRD](PRD.md), [ADR](ADR.md),
[TOLERANCE](../TOLERANCE.md), [reference-model](reference-model.md),
[필수 cases](numerical-review-cases.md), [내부 controls](numerical-review-controls.md).
<a id="implementation-first-version-review--승인-경계와-수치-판단"></a>
### 승인 경계와 수치 판단
원본 Mode1–10은 source `Step-2`의 독립 modal-frame singleton이다. 첫 구현 profile
`mitc4-eigen-first-implementation`은 각 `Value`의 reference-only relative error와 RMS를
각각 .05로 검사한다. 경계 포함이며 family를 합치거나 mode를 평균하지 않는다.
다른 공통 comparison의 RMS .01, missing/extra/duplicate/nonfinite 거부, zero-scale exact-zero,
내부 전체 c개의 residual/Gram `1e-10`은 유지한다.
[종료 제어 검토](implementation-review.md#implementation-feast-residual-review)의 원본 최대 Value 오차
`4.2613310845%`는 승인된 새 5% 범위 안이다. 새 comparator의 실제 focused 실행에서
원본 10개 family가 통과했다. 기존 1% FAIL 기록은 당시 판정으로 보존한다. 수식·DOF·단위·적분·
mass·whitening·복구·state update는 이번 외부 정책으로 바뀌지 않는다.
<a id="implementation-first-version-review--필수-보강과-추가-검증-한계"></a>
### 필수 보강과 추가 검증 한계
| 분류 | 요구·현재 evidence·필요한 보강 |
| --- | --- |
| 확인 — backend 실패 | REQ012/019, C21/C22. Fatal count·optional info1 fallback, final count 불일치·변경 없는 solve 반복 금지, info2의 더 큰 구간 retry, 요청 N 밖 고유벡터의 실제 residual 초과 및 nonfinite/Gram 거부 통과. Production이 사용하는 동일 budget helper의 511/512·363/364, size product·PTRDIFF/container 경계, 실제 count/solve workspace bad_alloc·thread 복원 및 초기 count3회 한계를 검사 |
| 확인 — raw·순위·반복군 | C18/C19/C21. 증가 upper의 감소 count 거부, raw -1e-12와 -1e-9 보존 및 -1e-9 바로 아래 실패 통과. 작은 isolated repeated군을 세 번 실제 FEAST로 풀어 순서·history와 승인된 Frobenius projector/sqrt(2r) metric을 비교 |
| 확인 — mass oracle·단위 | REQ005/014/026, C02/C03/C05. 48개 rational Ck/각 row·first spatial moment, theta×d 부호의 C1 cross-block·C2 rotary block과 두24×24 질량, pairwise Jensen의1/2 및2*C1 항을 대조. Scalar는 m_e(t/2)^k, matrix는 D Frobenius norm합, Jensen 차이는 qMLq+qMCq로 정규화. Proper Q+shift를 geometry/director부터 재계산하여 두 mass의 공변성 통과 |
| 확인 — 공유 node assembly | REQ003/004/007, C06. rho2/t.5와 rho5/t1의 공유 node URX만 free인 patch에서 mass7/64, local K합/m와 modal amplitude²*mass1, element source order 변화의 결과를 확인. Model-level BC로 fixture를 바로잡은 뒤 통과; parser 지원 범위를 넓히지 않음 |
| 확인 — final 보존 | REQ019, C24. Eigen candidate 변조·empty pencil 보존 및 실제 valid HDF5에 Win32 delete-sharing lock을 걸어 close/self-check 뒤 replace 실패·원본 bytes 보존 통과. 공통 AtomicFinalizeValidatedCandidate의 실패 경로와 연결 |
| 확인 — 5% 한정 정책 | C25. ±5% 경계와 바로 밖, zero/nonfinite·identity 거부, common RMS1% 보존, actual profile metadata와 원본 10 family fresh 비교 통과. 아래 focused evidence와 source 대조 |
| 사용자 명시 보류 | S3의 public static moment 충돌. Direct pencil/covariance 검사의 성공과 구별하고 지원 정적 사례의 성공으로 표시하지 않는다 |
| 추가 검증의 한계 | 모든 조건수·geometry injectivity·mesh spectrum 수렴차수·vendor/OS 오류 조합·임의 반복군 방향은 보장하지 않는다. H5Fclose 오류 자체와512회 actual vendor 호출은 미실행이다. CloseChecked 실패는 RequireHdf5→catch/cleanup→replace전 종료를 정적으로 대조했고 budget은 실제 사용 helper의 경계 검사다. 대표 분기 검증을 모든 오류 조합 전수 검사로 확대하지 않는다 |
검토 대상 tests: [mass contract](../../tests/unit/elements/mitc4_shell_mass_contract_test.cpp),
[mass/kernel](../../tests/unit/elements/mitc4_shell_test.cpp),
[공유 node assembly](../../tests/unit/analysis/eigen_mass_assembly_test.cpp),
[reduction](../../tests/unit/analysis/eigen_reduction_test.cpp),
[backend](../../tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp),
[procedure](../../tests/integration/analysis/linear_frequency_procedure_test.cpp),
[writer](../../tests/unit/io/hdf5/eigen_hdf5_results_writer_test.cpp),
[common finalize](../../tests/unit/io/hdf5/hdf5_writer_components_test.cpp).
Source의 guard 존재와 실제 실패 주입 통과를 구분한다. 검토자는 source/tests·상위 계약·reference를
수정하지 않고 메인의 fresh 결과를 대조한다.
<a id="implementation-first-version-review--실행-evidence"></a>
### 실행 evidence
- `.harness/eigen-first-implementation-focused.log`: comparator/policy 10/10 PASS,
원본 실제 해석→HDF5→10개 family 비교 포함. 정책 코드의 공통 Evaluate는 RMS .01을
유지하고 named entry는 blocking singleton `Value`만 허용한다.
- 독립 재계산: [기존 rational coefficient 적분](numerical-review.md#numerical-review-evidence)의 Python을
표준 라이브러리로 새 실행하고 mass test의 48개 rational 상수를 Fraction으로 대조하여
전부 exact 일치를 확인했다. 이종 두 요소 공유 node의 rotary mass도
`2*(1/2)^3/48+5/48=7/64 [M L²]`로 독립 확인했다. 이는 C++ 실행 대체가 아니다.
- `.harness/eigen-first-implementation-coverage.log`: 31개 중30 PASS. Backend24개·writer
통과, C06 fixture의 BC 위치만 실패했다. `.harness/eigen-first-implementation-mass.log`에서
fixture와 정규화 보강 뒤 mass6/6 PASS를 직접 확인했다.
- `.harness/eigen-first-implementation-boundaries.log`: raw negative와 count monotonicity 경계2/2 PASS.
- `.harness/eigen-first-implementation-full-run.log`: MSVC x64 Debug의 configure/build/
discovery/CTest 모두 exit0, **417/417 PASS**, 166.86초. Unit339/integration42/reference36.
같은 build의 `Testing/Temporary/LastTest.log`에서도 Passed417/Failed0와 원본 reference
실행을 직접 확인했다. 과거 C06 실패를 담은 `LastTestsFailed.log`는 최신 판정 근거로 사용하지 않는다.
이번 검토에서 추가 numerical correction은 필요하지 않다. 독립 내부 기준과 새 외부
정책의 실행 연결을 확인했으며, 모든 vendor·OS 실패 조합이나 S3 해결·Abaqus 내부 절차
동등성을 승인한 판정은 아니다. [이전 물리 검토](implementation-review.md#implementation-physics-review)의 기존
nonlinear recovery 제한도 이 변경으로 해소됐다고 주장하지 않는다.