From 7ebdce373cdccaec752cc2a46b1b5a07736e6392 Mon Sep 17 00:00:00 2001 From: "KOKO\\Mimi" Date: Thu, 10 Sep 2026 01:52:49 +0900 Subject: [PATCH] fix: use residual stopping for FEAST eigenanalysis --- docs/mitc4-shell-feast-eigen2/ADR.md | 12 ++- .../FEATURED_AGENTS.md | 3 +- docs/mitc4-shell-feast-eigen2/PRD.md | 14 +++- .../formulation-eigen.md | 6 +- docs/mitc4-shell-feast-eigen2/formulation.md | 4 +- .../implementation-feast-residual-review.md | 71 ++++++++++++++++ .../implementation-verification.md | 80 +++++++++++++++++-- .../numerical-review-controls.md | 18 ++++- .../io/hdf5/eigen_hdf5_results_writer.cpp | 2 +- .../solvers/eigen/mkl_feast_eigen_solver.cpp | 2 +- .../hdf5/eigen_hdf5_results_writer_test.cpp | 12 +++ .../eigen/mkl_feast_eigen_solver_test.cpp | 2 + 12 files changed, 209 insertions(+), 17 deletions(-) create mode 100644 docs/mitc4-shell-feast-eigen2/implementation-feast-residual-review.md diff --git a/docs/mitc4-shell-feast-eigen2/ADR.md b/docs/mitc4-shell-feast-eigen2/ADR.md index 7d8db81..e26c04f 100644 --- a/docs/mitc4-shell-feast-eigen2/ADR.md +++ b/docs/mitc4-shell-feast-eigen2/ADR.md @@ -86,4 +86,14 @@ - 근거: [실행 결과](implementation-verification.md), [독립 수치 검토](implementation-numerical-review.md), [S3 검토](implementation-numerical-review-s3-static.md). - 관찰: 원본 모델은 고정 FEAST trace stopping의 실제 반환값에서 전체 c residual 기준을 넘는다. S3 public static은 rotation-only drilling의 미평형 모멘트 때문에 실패한다. - 현재 처리: r1 controls·tolerance·물리 식을 유지하고 실패를 명시한다. 요청 N 밖의 모드를 버리거나 reaction에서 torque를 제거하지 않는다. 구현 진행분은 커밋하되 기능 완료로 표시하지 않는다. -- 후속 제안: residual stopping 후보의 FEAST 제어와 S3 정식화/회복/평형 계약을 사용자 결정 후 formulation·NR에서 재검토한다. 아직 채택·승인된 변경은 없다. +- 당시 후속 제안: residual stopping 후보의 FEAST 제어와 S3 정식화/회복/평형 계약을 사용자 결정 후 formulation·NR에서 재검토한다. 이 기록 시점에는 채택·승인된 변경이 없었다. 이후 FEAST 제어만 ADR-011로 변경한다. + +## MFE2-ADR-011 — FEAST residual stopping과 S3 후속 분리 + +- 상태: 사용자 명시 승인, 2026-09-10. Owner: 메인 assistant; 수치 검토: numerical-review-agent. +- 승인 근거: “FEAST 잔차 초과 문제를 Trace 기반 종료 → residual 기반 종료로 변경”, “S3 문제는 추후에 고려”. +- 결정: C-index `fpm[5]`를 `1`에서 `0`으로 변경한다. `fpm[2]=12`, `fpm[3]=20`, count/solve 구간·capacity·seed·thread·실패 정책 및 전체 c개 독립 `1e-10` 검증은 유지한다. +- 이유: trace 변화의 수렴만으로는 원본 모델 전체 고유쌍의 독립 잔차를 충족하지 못했다. 개별 잔차를 사용하는 backend 종료를 선택하되 backend 성공을 독립 검증으로 대체하지 않는다. +- 영향: [정식화 E5](formulation-eigen.md), [수치 controls C5](numerical-review-controls.md), backend와 HDF5 writer의 control 검증을 함께 갱신한다. 기존 schema의 실제 `base_fpm[5]` 기록값이 바뀌며 field·shape·단위와 reference mapping은 유지한다. +- 검증: [실행 결과](implementation-verification.md) 및 [독립 수치 검토](implementation-feast-residual-review.md)에 새 실행을 기록한다. 기존 trace 실패 evidence는 당시 결과로 보존한다. +- 범위: S3 정식화·부분 회전 BC·reaction·평형 기준은 변경하지 않고 알려진 충돌을 후속 과제로 유지한다. S3를 해결하거나 unsupported로 재분류한 결정이 아니다. 외부 reference와 공통 tolerance도 유지한다. diff --git a/docs/mitc4-shell-feast-eigen2/FEATURED_AGENTS.md b/docs/mitc4-shell-feast-eigen2/FEATURED_AGENTS.md index 2d13bc1..bf2f74c 100644 --- a/docs/mitc4-shell-feast-eigen2/FEATURED_AGENTS.md +++ b/docs/mitc4-shell-feast-eigen2/FEATURED_AGENTS.md @@ -3,7 +3,7 @@ - Feature ID: `mitc4-shell-feast-eigen2` - Owner: 메인 assistant - Requirement baseline revision: `r1` -- 현재 작업: 확정된 requirement/formulation/NR/I/O r1을 기준으로 implementation과 필요한 실행 검증을 진행한다. +- 현재 작업: requirement/formulation/I/O r1과 [ADR-011](ADR.md#mfe2-adr-011--feast-residual-stopping과-s3-후속-분리)의 FEAST residual stopping 변경을 적용한다. C5 controls는 r2이며 S3는 후속 과제로 유지한다. - 목적: MITC4 질량행렬과 FEAST 고유진동 해석의 요구사항을 이론·수학·수치 검토·입출력 계약으로 구체화한다. - 현재 checklist: [PRD](PRD.md#현재-checklist). @@ -40,5 +40,6 @@ | [implementation-verification.md](implementation-verification.md) | 메인 assistant | 실제 구현·실행·실패·남은 evidence와 후속 결정 | | [구현 수치 검토](implementation-numerical-review.md), [검토 이력](implementation-numerical-review-history.md), [S3 정적 검토](implementation-numerical-review-s3-static.md) | numerical-review-agent | 구현의 독립 수치 대조와 계약 충돌 | | [구현 물리 검토](implementation-physics-review.md) | physics-evaluation-agent | 실제 retained 결과의 물리 evidence·범위와 기존 문제 | +| [FEAST 종료 제어 검토](implementation-feast-residual-review.md) | numerical-review-agent | 사용자 승인 residual stopping의 독립 검토와 새 실행 판정 | 반환은 결과·변경 파일·정적 확인·미해결 항목으로 충분하다. Git 경로 선택·커밋과 최종 결과 확인은 메인이 수행한다. diff --git a/docs/mitc4-shell-feast-eigen2/PRD.md b/docs/mitc4-shell-feast-eigen2/PRD.md index a2e19aa..29d6b18 100644 --- a/docs/mitc4-shell-feast-eigen2/PRD.md +++ b/docs/mitc4-shell-feast-eigen2/PRD.md @@ -29,6 +29,10 @@ solver build/test·reference 비교와 release 감사는 포함하지 않는다. 코드·테스트·실제 FEAST 및 필수 reference/회귀 검증과 작업별 커밋이다. 앞의 30분 제한은 완료된 문서 작업의 이력이다. 원본 reference 생성·변경과 push/release는 포함하지 않는다. +2026-09-10 사용자는 FEAST 종료 조건을 trace에서 residual로 변경하고 S3는 추후 고려하도록 +명시했다. [ADR-011](ADR.md#mfe2-adr-011--feast-residual-stopping과-s3-후속-분리)에 따라 backend·저장 control 검증·관련 문서를 갱신하며, +기존 독립 잔차와 외부 tolerance, 질량·drilling 수식은 유지한다. + ## 솔버 기능의 요구 범위 요약 기존 사용자 결정에 기록된 다음 의미를 새 요구사항의 출발점으로 사용한다. @@ -83,10 +87,16 @@ solver build/test·reference 비교와 release 감사는 포함하지 않는다. - [ ] 제외 예제 사용 없이 남는 static/내부 회귀·전체 build/test·필수 reference 실행. - [ ] 관련 독립 numerical/physics 확인, 결과·한계 기록과 커밋. +- [x] 승인된 FEAST residual stopping과 HDF5 control 검증을 함께 적용하고 변경 전 실패·변경 후 검사를 확인한다. +- [x] 원본 eigen의 전체 c개 독립 잔차·복구·HDF5 생성을 확인하고 종료 제어의 독립 수치 검토를 받는다. +- [ ] 원본 eigen의 외부 Value 불일치 원인을 조사한다. 현재 Mode2–10의 모드별 RMS가 1%를 초과한다. +- [ ] S3 public static 정적 평형 계약 충돌은 사용자 요청에 따라 후속 검토한다. + 현재 구현·실행은 [implementation-verification](implementation-verification.md)에 기록했다. 실제 mass/reduction/FEAST/procedure/HDF5 경로와 focused 검사가 있으며, 체크되지 않은 항목이 -전부 미구현이라는 뜻은 아니다. 원본 eigen의 전체 c residual 실패와 S3 public static -계약 충돌, 세부 case의 미완료 evidence 때문에 기능 전체 acceptance는 완료하지 않았다. +전부 미구현이라는 뜻은 아니다. 원본 eigen의 전체 c residual 실패는 residual stopping으로 +해소했다. 현재 외부 Value 불일치와 S3 public static 계약 충돌, 세부 case의 미완료 evidence가 +남으므로 기능 전체 acceptance는 완료하지 않았다. ## 이전 문서 단계의 결과와 구현 입력 diff --git a/docs/mitc4-shell-feast-eigen2/formulation-eigen.md b/docs/mitc4-shell-feast-eigen2/formulation-eigen.md index fe397d2..39bf1a9 100644 --- a/docs/mitc4-shell-feast-eigen2/formulation-eigen.md +++ b/docs/mitc4-shell-feast-eigen2/formulation-eigen.md @@ -128,8 +128,10 @@ K와 identity의 pattern이 같을 필요는 없다. Vendor types와 workspace 매 call마다 `feastinit` 후 명시 controls를 채운다. C-index `fpm[49]=1`은 CSR count를 m0로 반환하고 flag가 0으로 reset된다. Count output m0·solve requested m0·allocated capacity를 -분리한다. CSR/SPD 검사를 켜고 subspace-only를 끈다. Zero mode에도 적용할 수 있도록 -`fpm[5]=1` trace stopping을 사용하며 residual을 독립 검증한다. `epsout`은 +분리한다. CSR/SPD 검사를 켜고 subspace-only를 끈다. +[MFE2-ADR-011](ADR.md#mfe2-adr-011--feast-residual-stopping과-s3-후속-분리)의 사용자 승인으로 +`fpm[5]=0` residual stopping을 사용한다. 내부 목표 `1e-12`와 전체 c개 독립 residual +기준 `1e-10`을 유지하며 zero/mixed-zero mode에도 실제 backend 회귀를 수행한다. `epsout`은 `|trace_i-trace_previous|/max(|emin|,|emax|)`이며 eigenpair 상대오차가 아니다. `info=1`은 certified empty count가 아니다. 넓은 interval의 isolated cluster를 놓친 diff --git a/docs/mitc4-shell-feast-eigen2/formulation.md b/docs/mitc4-shell-feast-eigen2/formulation.md index 1274f8e..1139e41 100644 --- a/docs/mitc4-shell-feast-eigen2/formulation.md +++ b/docs/mitc4-shell-feast-eigen2/formulation.md @@ -39,7 +39,9 @@ Numerical scale은 초기 physical rotary diagonal 8개 trace 평균의 `10^-3` 질량 및 trace 평균은 FESA 운동학에서 유도한 선택이다. 외부 source가 이 lumping/scale을 지정한다고 주장하지 않는다. 최신 API 근거와 검토 한계는 [research](research.md)와 [research evidence](research-evidence.md)에 연결한다. FEAST count의 `fpm[49]=1`과 -trace stopping의 `fpm[5]=1`은 C-index다. 빈 count interval의 `info=0,m0=0`과 작은 +residual stopping의 `fpm[5]=0`은 C-index다. 종료 제어는 [ADR-011](ADR.md#mfe2-adr-011--feast-residual-stopping과-s3-후속-분리)과 +[controls C5](numerical-review-controls.md#c5-fixed-lower-enclosure와-bounded-upper-search)의 승인된 변경을 적용한다. +빈 count interval의 `info=0,m0=0`과 작은 scratch 허용은 보장된 vendor 계약으로 채택하지 않는다. ## 검증 의무와 미해결 항목 diff --git a/docs/mitc4-shell-feast-eigen2/implementation-feast-residual-review.md b/docs/mitc4-shell-feast-eigen2/implementation-feast-residual-review.md new file mode 100644 index 0000000..a118f3d --- /dev/null +++ b/docs/mitc4-shell-feast-eigen2/implementation-feast-residual-review.md @@ -0,0 +1,71 @@ +# 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-schema.md), [TOLERANCE](../TOLERANCE.md). + +## 판단과 필요한 확인 + +| 항목 | 독립 판단 | +| --- | --- | +| 종료 기준 | [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를 중복 실행하지 않고 메인의 실행 로그를 대조했다. + +## 새 실행 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 완료로 확장하지 않는다. + +## 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-numerical-review.md)의 별도 제한으로 남는다. diff --git a/docs/mitc4-shell-feast-eigen2/implementation-verification.md b/docs/mitc4-shell-feast-eigen2/implementation-verification.md index 850acff..ab2635b 100644 --- a/docs/mitc4-shell-feast-eigen2/implementation-verification.md +++ b/docs/mitc4-shell-feast-eigen2/implementation-verification.md @@ -1,12 +1,81 @@ # MITC4 eigen 구현 및 실행 결과 -- Feature: `mitc4-shell-feast-eigen2`; Owner: 메인 assistant; 2026-09-09 KST. -- 판정: **구현 진행분 보존, 기능 acceptance 미완료**. 시간 제한으로 중지한 작업이 아니다. +- Feature: `mitc4-shell-feast-eigen2`; Owner: 메인 assistant; 갱신 2026-09-10 KST. +- 현재 판정: **FEAST 잔차 초과 해소, 외부 Value 비교와 기능 acceptance 미완료**. + 아래 2026-09-10 결과가 최신이며 2026-09-09 trace 실행은 당시 evidence로 보존한다. - 기준: [프로젝트 지침](../../AGENTS.md), [PRD](PRD.md), [ADR](ADR.md), [정식화](formulation.md), [수치 controls](numerical-review-controls.md), [I/O](io.md). - 독립 검토: [수치](implementation-numerical-review.md), [S3 정적 계약](implementation-numerical-review-s3-static.md), - [물리](implementation-physics-review.md). + [물리](implementation-physics-review.md), [FEAST 종료 변경](implementation-feast-residual-review.md). + +## 2026-09-10 FEAST residual stopping 변경 결과 + +[ADR-011](ADR.md#mfe2-adr-011--feast-residual-stopping과-s3-후속-분리)의 사용자 승인에 따라 backend의 C-index +`fpm[5]`만 `1→0`으로 변경하고 HDF5 writer의 실제 control 검증도 `0`으로 맞췄다. +`fpm[2]=12`, `[3]=20`, seed/thread/구간/capacity/실패 정책과 모든 독립 tolerance는 유지했다. +S3, K/M·질량 축소·회복 수식, reference artifact는 변경하지 않았다. + +새 테스트는 실제 backend snapshot과 저장한 HDF5의 `[5]=0`을 확인하고 trace 값으로 +변조한 candidate를 거부하면서 기존 최종 파일을 보존하는지 검사한다. 변경 전 `[5]=1` +때문에 두 검사가 실패한 뒤 최소 source 수정으로 통과했다. + +| 실행 | 결과 | +| --- | --- | +| 변경 전 backend/HDF5 focused CTest | 2/2 실패, `[5]=1` 확인. `.harness/feast-residual-red.log` | +| MSVC x64 Debug 3개 test target build | exit0, 새 compiler warning 없음 | +| 변경 후 backend/writer/원본 reference focused CTest | 12개 중 11 통과, exit1. 영·혼합 영·반복·근접 고유값, thread 복원, control readback/변조 거부 통과. 원본은 해석 성공 후 외부 Value 비교에서 실패 | +| `python scripts/execute.py` | build 성공, runner exit1 / CTest exit8. **395개 중 394 통과**, 원본 Value reference 1개 실패. 178.42초; unit320, integration42, reference33 | +| 공식 HDF5 read-only 추출 | 전체 c개 metric과 실제 controls·backend call·10개 Value를 확인. Focused와 full 실행의 modes/vectors/eigenpair_checks/base_fpm dataset bytes 동일 | + +전체 실행은 `.harness/feast-residual-full-run.log`, 상세 CTest는 +`.harness/feast-residual-full-ctest.log`, focused는 `.harness/feast-residual-focused.log`다. +Read-only 추출 스크립트와 JSON은 최종적으로 ignored build directory에 보관했다. +재현 명령은 `uv run --with h5py python .harness/build-ninja-msvc-debug/extract_feast_residual.py`이며, +그 directory의 `feast-residual-metrics.json`과 `feast-residual-full-metrics.json`이 각 실행의 기록이다. +개인 환경·추출 스크립트·기계 생성 로그/결과는 커밋하지 않는다. 이 작업에서 Python Harness suite는 실행하지 않았다. + +원본 [결과 HDF5](../../reference/shellNL-eigen-meshfine/shellNL-eigen-meshfine_results.h5)는 +이번 실제 해석이 새로 생성한 공식 sibling output이다. 생성과 closed-file self-check는 성공했고, +기존 외부 INP/TXT의 실행 전후 bytes는 reference test에서 보존을 확인했다. + +| Metric | 새 결과 | +| --- | ---: | +| 요청 N / 계산 c / m0 | 10 / 22 / 33 | +| Count / solve calls | 25 / 1 | +| FEAST info / loop | 0 / 6 (기존 trace는 4회) | +| 전체 c 최대 rho_B | `1.605467212112365e-13` | +| 최대 original-free eta_r / whitened eta_w | `9.981033437726324e-15` / `7.315529163435965e-15` | +| eta_gram / max_eta_orth | `1.3777964580680282e-15` / `1.6958335496991244e-15` | +| 최대 backend_res | `8.280018892001454e-13` | +| epsout (trace 변화 진단량) | `2.4227135616446226e-17` | + +전체 22개는 각각 독립 `1e-10` 기준을 통과한다. 기존 실패 column20의 +`rho_B=1.48674481038207483e-10` 대비 같은 column의 잔차가 약926배 감소했다. +기존 trace 진단에서 추출한 첫10개 Value 대비 새 Value의 최대 상대 변화는 약`2.74e-14`다. +따라서 이 개선은 고유쌍의 대수적 잔차 개선이며 외부 reference와의 일치를 보장하지 않는다. + +| Mode | FESA Value (표시 반올림) | Abaqus Value | 상대오차 / singleton RMS (%) | +| --- | ---: | ---: | ---: | +| 1 | 218267.149475 | 219507 | 0.564834 | +| 2 | 873571.591115 | 885523 | 1.349644 | +| 3 | 873571.591115 | 885523 | 1.349644 | +| 4 | 1816890.360227 | 1855340 | 2.072377 | +| 5 | 2669030.373076 | 2740230 | 2.598308 | +| 6 | 2703557.194039 | 2775150 | 2.579781 | +| 7 | 4013818.213002 | 4149410 | 3.267737 | +| 8 | 4013818.213002 | 4149410 | 3.267737 | +| 9 | 6446840.913563 | 6733790 | 4.261331 | +| 10 | 6446840.913563 | 6733790 | 4.261331 | + +모드별 singleton family와 [공통 tolerance](../TOLERANCE.md)를 그대로 적용했다. +모든 행은 상대오차5% 이내지만 Mode2–10은 RMS1%를 초과하여 blocking FAIL이다. +이는 이전에는 residual 실패 때문에 도달하지 못했던 비교 결과다. 원인은 이번 변경에서 +확정하지 않았으며 질량·drilling 정식화나 tolerance를 결과에 맞춰 수정하지 않았다. +독립 수치 검토는 이번 종료 제어 변경을 PASS로 판단했으나 외부 acceptance는 FAIL로 구분했다. +S3의 알려진 실패와 아래 기존 세부 coverage 제한도 남는다. + +## 2026-09-09 trace stopping 구현 이력 ## 구현된 경로 @@ -95,11 +164,12 @@ Newton tangent/objectivity/energy/rollback와 pressure synthetic 검사는 초 full-row-sum mutation, C06 이종 section 공유 node mass assembly, C21/22의 vendor-status/ budget/allocation 실패 주입 전체, C24의 close/replace 실패 주입 전체는 추가 evidence가 필요하다. -## 사용자 결정이 필요한 후속 작업 +## 2026-09-09 당시 후속 제안 현재 요구·정식화·NR·I/O의 수치를 구현 결과에 맞춰 조용히 바꾸지 않는다. [프로젝트 지침](../../AGENTS.md)의 Physics/지원 범위/acceptance 변경 및 미해결 필수 계약 충돌 -경계에 따라 다음 재검토를 제안한다. 아래는 **미승인 제안**이다. +경계에 따라 다음 재검토를 제안했다. 당시에는 **미승인 제안**이었으며, +이후 1번의 residual stopping만 ADR-011로 승인·실행했다. 2번 S3는 사용자 요청으로 후속 검토한다. 1. `rho_B<=1e-10`과 전체 c 검증을 유지하면서 FEAST 종료 제어를 재검토한다. `fpm[5]=0` residual stopping은 검토 후보이며, actual runtime·zero/repeated/endpoint/ diff --git a/docs/mitc4-shell-feast-eigen2/numerical-review-controls.md b/docs/mitc4-shell-feast-eigen2/numerical-review-controls.md index a984e8d..b3f9210 100644 --- a/docs/mitc4-shell-feast-eigen2/numerical-review-controls.md +++ b/docs/mitc4-shell-feast-eigen2/numerical-review-controls.md @@ -1,8 +1,10 @@ # 내부 수치 기준과 FEAST controls -- Feature ID: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`; revision `r1`. +- Feature ID: `mitc4-shell-feast-eigen2`; Owner: `numerical-review-agent`; revision `r2` (2026-09-10, C5 종료 제어만 변경). - 기본 보고서: [numerical-review](numerical-review.md); 수식: [새 formulation](formulation.md). - IEEE binary64의 내부 검증 계약이며 [외부 TOLERANCE](../TOLERANCE.md)를 변경하지 않는다. +- 아래 `NOT RUN`은 r1 문서 검토 당시의 기록이다. 변경된 C5의 실제 실행 판정은 + [종료 제어 구현 검토](implementation-feast-residual-review.md)를 따른다. ## C1–C4, C6, C7의 독립 검토 후 명시 채택 @@ -46,15 +48,25 @@ Seed 변경으로 통과를 찾지 않는다. oneMKL thread-local 1을 설정하 | Index | 값 | | --- | --- | | `[0],[1],[2],[3]` | `0,16,12,20` | -| `[4],[5],[13]` | `1,1,0` | +| `[4],[5],[13]` | `1,0,0` | | `[26],[27]` | `1,1` | | `[49]` | Count `1`, solve `0` | | `[63]` | `0` | 나머지는 해당 설치의 초기값을 유지·기록한다. 이번 [Intel parameter table](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2026-0/extended-eigensolver-input-parameters.html)의 허용 contour16, -trace stopping, CSR/SPD checks와 count flag reset을 확인했다. 위 값은 FESA의 고정 +residual stopping, CSR/SPD checks와 count flag reset을 확인했다. 위 값은 FESA의 고정 제어 선택이며 어떤 matrix에서도 수렴한다는 vendor 보장이 아니다. +2026-09-10 사용자 승인으로 C-index `fpm[5]=1` trace stopping을 `0` residual stopping으로 +대체한다. Double precision의 vendor stopping epsilon은 `10^-fpm[2]=1e-12`이며 +`fpm[3]=20`을 유지한다. Count/solve 모두 같은 초기 controls를 적용하고 `[49]`만 구분한다. +전체 c개의 독립 `rho_B=||Bx-mu x||2/||x||2<=1e-10`, Gram 및 original-free 복구 검증은 +그대로다. Vendor residual의 정규화와 독립 rho_B를 동일시하지 않으며 `info=0`도 독립 검증을 +대체하지 않는다. `epsout`은 trace 변화 진단량으로 보존하고 새 residual 오차로 재해석하지 않는다. +기존 trace 실행의 pass/fail·loop·epsout은 당시 controls의 이력이다. Zero/mixed-zero/repeated +및 원본 모델의 새 실행과 미해결 위험은 [종료 제어 구현 검토](implementation-feast-residual-review.md)에 +구분한다. S3·물리 정식화·공통 외부 tolerance는 이 결정으로 변경하지 않는다. + Gershgorin off-diagonal absolute row sum은 매 합산 뒤 `nextafter(+infinity)`로 outward 누적하고 diagonal±sum도 바깥 한 ULP를 적용한다. `beta=norm(B,inf)`도 outward로 구한다. `B=0`의 algorithmic enclosure에서만 beta=1이며 physical mass/λ floor가 아니다. diff --git a/src/fesa/io/hdf5/eigen_hdf5_results_writer.cpp b/src/fesa/io/hdf5/eigen_hdf5_results_writer.cpp index 6da8782..cbcfa5b 100644 --- a/src/fesa/io/hdf5/eigen_hdf5_results_writer.cpp +++ b/src/fesa/io/hdf5/eigen_hdf5_results_writer.cpp @@ -137,7 +137,7 @@ Status Validate(const Domain& domain, const EigenAnalysisState& state, {2U, 12}, {3U, 20}, {4U, 1}, - {5U, 1}, + {5U, 0}, {13U, 0}, {26U, 1}, {27U, 1}, diff --git a/src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp b/src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp index c6c68ed..c2ece52 100644 --- a/src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp +++ b/src/fesa/solvers/eigen/mkl_feast_eigen_solver.cpp @@ -174,7 +174,7 @@ void SetControls(std::array& fpm, const bool count) { fpm[2] = 12; fpm[3] = 20; fpm[4] = 1; - fpm[5] = 1; + fpm[5] = 0; // Trace convergence alone can leave individual pairs inaccurate. fpm[13] = 0; fpm[26] = 1; fpm[27] = 1; diff --git a/tests/unit/io/hdf5/eigen_hdf5_results_writer_test.cpp b/tests/unit/io/hdf5/eigen_hdf5_results_writer_test.cpp index 2c2b255..b48152c 100644 --- a/tests/unit/io/hdf5/eigen_hdf5_results_writer_test.cpp +++ b/tests/unit/io/hdf5/eigen_hdf5_results_writer_test.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -78,6 +80,15 @@ TEST(EigenHdf5ResultsWriter, WritesModalSchemaAndRejectsTamperedState) { H5Fopen(path.string().c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); ASSERT_GE(file, 0); EXPECT_GT(H5Lexists(file, "/steps/Step-1/eigen/modes", H5P_DEFAULT), 0); + const hid_t controls = + H5Dopen2(file, "/steps/Step-1/eigen/backend/base_fpm", H5P_DEFAULT); + ASSERT_GE(controls, 0); + std::array stored_controls{}; + ASSERT_GE(H5Dread(controls, H5T_NATIVE_INT64, H5S_ALL, H5S_ALL, + H5P_DEFAULT, stored_controls.data()), + 0); + EXPECT_EQ(stored_controls[5U], 0); + EXPECT_GE(H5Dclose(controls), 0); EXPECT_GE(H5Fclose(file), 0); std::ifstream original_file{path, std::ios::binary}; const std::string original{std::istreambuf_iterator{original_file}, {}}; @@ -91,6 +102,7 @@ TEST(EigenHdf5ResultsWriter, WritesModalSchemaAndRejectsTamperedState) { [](auto& candidate) { candidate.modes[0].cluster_id = 7U; }, [](auto& candidate) { candidate.constraint_mask[0] = 1U; }, [](auto& candidate) { candidate.nodal_reduction[0].rcond_inf = 1e-15; }, + [](auto& candidate) { candidate.backend.base_fpm[5U] = 1; }, [](auto& candidate) { candidate.eta_gram = 1e-5; }}; for (const auto& mutate : mutations) { auto candidate = state; diff --git a/tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp b/tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp index 5748f6b..5581709 100644 --- a/tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp +++ b/tests/unit/solvers/eigen/mkl_feast_eigen_solver_test.cpp @@ -71,6 +71,8 @@ TEST(MklFeastEigenSolver, SolvesN1AndRetainsBackendEvidence) { EXPECT_EQ(result.Value().eigenvectors.Rows(), 1U); EXPECT_EQ(result.Value().eigenvectors.Columns(), 1U); EXPECT_EQ(result.Value().thread_count, 1U); + ASSERT_EQ(result.Value().base_fpm.size(), 128U); + EXPECT_EQ(result.Value().base_fpm[5U], 0); ASSERT_FALSE(result.Value().backend_calls.empty()); EXPECT_EQ(result.Value().backend_calls.front().purpose, "total-enclosure"); EXPECT_EQ(result.Value().backend_calls.back().kind, "solve");