docs: complete MITC4 eigen numerical review
This commit is contained in:
@@ -2,12 +2,15 @@
|
||||
|
||||
- Feature ID: `mitc4-shell-feast-eigen`
|
||||
- Owner: `numerical-review-agent`
|
||||
- Input contract revision: `r1`
|
||||
- Input contract revision: `r2`
|
||||
- 기본 보고서: [numerical-review.md](numerical-review.md)
|
||||
- 검토일 / web access date: `2026-09-06`
|
||||
|
||||
## NR-MFE-001 직접 계산 반례
|
||||
|
||||
이 절은 **r1의 실제 실패 evidence**이며 값·계산을 보존한다. r2의 독립 해소 판정은
|
||||
아래 [r2 공변성 검산](#r2-독립-공변성-검산)에 있다. 기존 실패를 통과로 소급 변경하지 않는다.
|
||||
|
||||
관련 원문은 [requirements](requirements.md)의 `002`(기존 kernel 유지),
|
||||
`008`(선택 질량의 유한 spectrum 보존), `014`(eigen 해석의 coordinate-invariance
|
||||
evidence)와 [V5](formulation-verification.md#v5-rigid-mode-coordinate-및-density-불변식)다.
|
||||
@@ -89,6 +92,10 @@ assert abs(l1-l0)>1e-6
|
||||
|
||||
## 비충돌 수학 검토
|
||||
|
||||
아래 표는 r1의 검토 기록이다. Mass·geometry·unit·BC·whitening·FEAST의 비충돌 항목은
|
||||
r2 영향 확인 후 재사용한다. E3의 scalar는 r2 S1로 바뀌며 positivity/decoupling의 재검토와
|
||||
V5의 complete K/partial-BC 해소는 아래 별도로 기록한다.
|
||||
|
||||
| 대상 | 독립 검토 결과와 한계 |
|
||||
| --- | --- |
|
||||
| M1/M2 | `S=-[d]x`이므로 `S theta=theta×d`; global DOF `[u,theta]`와 20↔24 transformation의 부호가 일치한다. Shear factor는 mass에 들어가지 않는다. |
|
||||
@@ -166,8 +173,10 @@ Known-spectrum 검증 없는 `info=0` 또는 count만으로 lowest-N를 판정
|
||||
|
||||
## 재검토 범위
|
||||
|
||||
NR-MFE-001 때문에 bounded return을 먼저 수행한다. 아래 항목은 최종 numerical gate 전에
|
||||
NR가 같은 승인 revision에서 구체적인 수치와 필수 case를 고정해야 하며 미완료로 남긴다.
|
||||
이 절은 r1의 조기 반환 당시 미완료 목록이다. r2에서는 아래 항목을
|
||||
[controls C1~C7](numerical-review-controls.md)와
|
||||
[27개 case·requirement matrix](numerical-review-cases.md)로 고정했다.
|
||||
이력 목록을 삭제하지 않으며 현재 미완료 수치 계약으로 해석하지 않는다.
|
||||
|
||||
- V1~V4의 symmetry/oracle/moment/centroid/Jensen/null/KZ/MZ/PZ/Cholesky/constraint/
|
||||
full residual/whitened residual/normalization/Gram/energy의 threshold와 zero branch.
|
||||
@@ -217,3 +226,161 @@ issues `0`이다. 문서에 보존한 반례 코드를 추출해 같은 Python
|
||||
위 kd/lambda/relative difference가 재현되었다. `git diff --check` exit `0`; 타 owner의
|
||||
`coordination.md` LF/CRLF warning만 출력되었다. 신규 owned 문서의 whitespace는 위 별도
|
||||
검사로 확인했다. `git status --short`에서 owned 신규 3개와 Coordinator 변경을 구분했다.
|
||||
|
||||
|
||||
## r2 독립 공변성 검산
|
||||
|
||||
새 [S1~S8](formulation-stabilization.md)는 초기 physical rotary block의 trace를
|
||||
사용하므로 각 node의 orthogonal tangent 기저 변화와 SO(3) 회전에 불변이다.
|
||||
Trace 평균은 PSD inventory에 zero가 있어도 같은 여덟 항을 포함하고, 기존 양의 inventory
|
||||
전제에서 strictly positive다. Positive kd와 공통 director로 E3의 Kzz>0/Kpz=0을 유지한다.
|
||||
Partial BC의 numerical contribution을 보존하므로 개선된 원 pencil의 reduction이다.
|
||||
|
||||
Nonlinear에서는 초기 scalar의 Dkd=D²kd=0이므로 기존 objective gamma의 first/second
|
||||
variations에 같은 상수를 곱한다. Positive potential가 모든 상태의 Hessian SPD를 뜻하지
|
||||
않으며 corotation coupling을 linear Td와 동일시하지 않는다. 기존 accepted branch·moment
|
||||
work·state lifecycle과 [현재 nonlinear NR](../nonlinear-static-newton-raphson/numerical-review.md)을
|
||||
대조했고 scale 개선 밖 physics 변경을 발견하지 않았다.
|
||||
|
||||
NR는 S7의 R block을 입력으로 재사용하지 않고, rectangle의 membrane/curvature/MITC
|
||||
edge shear work를 직접 적분하여 **global 24×24 physical K를 독립 구성**했다.
|
||||
기존 반례와 동일한 geometry에서 director 기반 tangent를 새로 생성해 trace scale을 계산하고
|
||||
complete K/ML를 만들었다. 회전 뒤에도 새 geometry axes로 처음부터 적분했다.
|
||||
정적 load는 d에 수직인 (5/3)b이고, 모든 full reaction을 Kq-F로 재계산했다.
|
||||
|
||||
실제 read-only command는 아래와 같으며 exit `0`, 약 `0.34 s`였다.
|
||||
Production C++ 함수, vendor solver, reference 수치를 호출하지 않았다.
|
||||
|
||||
```powershell
|
||||
@'
|
||||
from math import sqrt, fsum
|
||||
from fractions import Fraction as F
|
||||
|
||||
def dot(a,b): return fsum(x*y for x,y in zip(a,b))
|
||||
def cross(a,b): return (a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0])
|
||||
def norm(v): return sqrt(dot(v,v))
|
||||
def Rz(v): return ((v[0]-v[1])/sqrt(2),(v[0]+v[1])/sqrt(2),v[2])
|
||||
def tangent(d):
|
||||
k=min(range(3),key=lambda k:(abs(d[k]),k))
|
||||
a=tuple((1. if j==k else 0.)-d[k]*d[j] for j in range(3))
|
||||
a=tuple(v/norm(a) for v in a)
|
||||
return a,cross(d,a)
|
||||
def action(K,v): return [dot(row,v) for row in K]
|
||||
def rotate_vector(v): return [x for off in range(0,len(v),3) for x in Rz(v[off:off+3])]
|
||||
def rotate_matrix(K):
|
||||
cols=[rotate_vector(col) for col in zip(*K)]
|
||||
left=[list(row) for row in zip(*cols)]
|
||||
return [rotate_vector(row) for row in left]
|
||||
def error(a,b): return norm([x-y for x,y in zip(a,b)])/(norm(a)+norm(b))
|
||||
def matrix_error(A,B): return error(sum(A,[]),sum(B,[]))
|
||||
def matrices(ex,ey,d):
|
||||
# Independent planar polynomial work: membrane, curvature and MITC edge shear.
|
||||
signs=[(-1,-1),(1,-1),(1,1),(-1,1)]
|
||||
K=[[0.]*24 for _ in range(24)]
|
||||
for xi in [-1/sqrt(3),1/sqrt(3)]:
|
||||
for eta in [-1/sqrt(3),1/sqrt(3)]:
|
||||
fields=[]
|
||||
for sx,sy in signs:
|
||||
Nx=sx*(1+sy*eta)/8.; Ny=sy*(1+sx*xi)/4.
|
||||
tx=(1+sy*eta)/4.; ty=(1+sx*xi)/4.
|
||||
for c in range(3): fields.append(([Nx*ex[c],Ny*ey[c],Ny*ex[c]+Nx*ey[c]],[0,0,0],[Nx*d[c],Ny*d[c]]))
|
||||
for c in range(3): fields.append(([0,0,0],[Nx*ey[c],-Ny*ex[c],Ny*ey[c]-Nx*ex[c]],[tx*ey[c],-ty*ex[c]]))
|
||||
for i,(mi,bi,si) in enumerate(fields):
|
||||
for j,(mj,bj,sj) in enumerate(fields):
|
||||
K[i][j]+=2*(12*mi[0]*mj[0]+12*mi[1]*mj[1]+6*mi[2]*mj[2]+bi[0]*bj[0]+bi[1]*bj[1]+.5*bi[2]*bj[2]+5*dot(si,sj))
|
||||
ta,tb=tangent(d); diagonals=[]
|
||||
for i in range(4):
|
||||
for t in [ta,tb]:
|
||||
v=[0.]*24;v[6*i+3:6*i+6]=t
|
||||
diagonals.append(dot(v,action(K,v)))
|
||||
kd=fsum(diagonals)/8000.
|
||||
M=[[0.]*24 for _ in range(24)]
|
||||
for i in range(4):
|
||||
for a in range(3):
|
||||
M[6*i+a][6*i+a]=2.
|
||||
for b in range(3):
|
||||
K[6*i+3+a][6*i+3+b]+=kd*d[a]*d[b]
|
||||
M[6*i+3+a][6*i+3+b]=((1. if a==b else 0.)-d[a]*d[b])/6.
|
||||
return K,M,kd,diagonals
|
||||
ex=(0.,1.,0.);ey=(-.8,0.,.6);d=(.6,0.,.8)
|
||||
K,M,kd,diags=matrices(ex,ey,d)
|
||||
Kr,Mr,kdr,diagsr=matrices(Rz(ex),Rz(ey),Rz(d))
|
||||
load=[0.]*24; load[3:6]=[5*v/3 for v in ey]; loadr=rotate_vector(load)
|
||||
q=[0.]*24;qr=[0.]*24;q[5]=load[5]/K[5][5];qr[5]=loadr[5]/Kr[5][5]
|
||||
reaction=[x-y for x,y in zip(action(K,q),load)]; rr=[x-y for x,y in zip(action(Kr,qr),loadr)]
|
||||
print('independent rotary diagonals=',diags)
|
||||
print('kd=',kd,kdr,'expected=',float(F(19,4800)))
|
||||
print('Kff/Mff/lambda/thetaZ=',K[5][5],M[5][5],K[5][5]/M[5][5],q[5])
|
||||
print('rotated Kff/Mff/lambda/thetaZ=',Kr[5][5],Mr[5][5],Kr[5][5]/Mr[5][5],qr[5])
|
||||
print('complete K/M/response/reaction covariance errors=',matrix_error(Kr,rotate_matrix(K)),matrix_error(Mr,rotate_matrix(M)),error(qr,rotate_vector(q)),error(rr,rotate_vector(reaction)))
|
||||
print('load drill projection/free residual=',dot(d,load[3:6]),reaction[5],rr[5])
|
||||
assert abs(K[5][5]/M[5][5]-float(F(10369,450)))<1e-12
|
||||
assert matrix_error(Kr,rotate_matrix(K))<1e-12
|
||||
assert matrix_error(Mr,rotate_matrix(M))<1e-12
|
||||
assert error(rr,rotate_vector(reaction))<1e-12
|
||||
'@ | python -B -
|
||||
```
|
||||
|
||||
| 관찰 | 결과 |
|
||||
| --- | --- |
|
||||
| 독립 physical rotary diagonals | 각 corner 약 49/12,23/6 |
|
||||
| kd before/after | 0.003958333333333333 / 0.003958333333333332 |
|
||||
| Kff, Mff | 1.3825333333333332, 0.05999999999999998 |
|
||||
| lambda before/after | 둘 다 23.04222222222223 |
|
||||
| thetaZ per unit moment before/after | 둘 다 0.7233098659465717 |
|
||||
| Complete K covariance ratio | 7.895168813539929e-17 |
|
||||
| ML covariance ratio | 4.6611822355981756e-17 |
|
||||
| Static response covariance ratio | 0 |
|
||||
| Full reaction covariance ratio | 1.1535337419041683e-16 |
|
||||
| d dot load / both free residuals | 1.1102230246251565e-16 / 0,0 |
|
||||
|
||||
따라서 NR-MFE-001은 **r2 수학 계약에서 해소**되었다. C2/C3/C7 기준을 만족하는
|
||||
독립 계산 evidence이고 실제 C++/FEAST/기존 정적 회귀의 통과 판정은 아니다.
|
||||
|
||||
## r2 보존·변경 audit와 근거
|
||||
|
||||
`git diff c8876da --`로 r1 checkpoint와 r2 requirements/research/formulation을 대조했다.
|
||||
M1/M2/M5~M10, E6~E8, V1~V4의 식은 유지되고 변경은 scale·그 적용 대상·coordinate
|
||||
coverage와 정적 회귀다. r1 rational mass oracle와 API count/trace·reference identity는
|
||||
수식 영향이 없어 재계산 없이 재사용한다. Reference 두 SHA-256도 현재 원본에서 재확인했다.
|
||||
AGENTS, agent/documentation 계약, NR skill 및 TOLERANCE의 같은 checkpoint 대비 diff는 없다.
|
||||
|
||||
기존 linear/nonlinear numerical-review/reference-model, r2 requirements 27개와
|
||||
Research R07을 읽었고, 필요한 current nonlinear tangent test의 perturbation schedule을
|
||||
확인했다. 최초 검색의 존재하지 않는 `numerical-methods.md` 및
|
||||
`tests/fesa/elements/nonlinear_mitc4_shell_test.cpp`는 경로 오류였다.
|
||||
`rg --files`로 실제 `tests/unit/elements/nonlinear_mitc4_shell_tangent_test.cpp`를
|
||||
확인하고 scoped `rg`를 exit `0`으로 재실행했다. 이를 test 실행 실패 또는 성공으로
|
||||
취급하지 않는다. Source/test 파일은 변경하지 않았다.
|
||||
|
||||
새로 확인한 vendor 사실은 thread-local 설정/복원뿐이며
|
||||
[Intel 2026.0 공식 문서](https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2026-0/mkl-set-num-threads-local.html)를
|
||||
2026-09-06 `search_query/open/find`로 확인했다. FEAST count/trace/API는 r1의 primary
|
||||
근거를 재사용했다. 수치 기준의 선택·단위·근거·zero branch는
|
||||
[controls](numerical-review-controls.md), 요구별 falsifiable coverage는
|
||||
[cases](numerical-review-cases.md)에 있고 변경한 외부 tolerance는 없다.
|
||||
|
||||
## r2 최종 정적 검증
|
||||
|
||||
2026-09-06 workspace root에서 PowerShell here-string을 `python -B -`에 전달한
|
||||
read-only audit의 실제 exit는 `0`이다. `pathlib`의 UTF-8 읽기, Markdown 상대 링크의
|
||||
`urllib.parse.unquote`, requirement/case ID의 정규식 집합 대조, `hashlib.sha256`,
|
||||
위 r2 재현 코드의 `subprocess.run([sys.executable,'-B','-'], ...)`를 사용했다.
|
||||
문서 owner/revision·마지막 newline·trailing whitespace·표 내부 code span의 pipe escape도
|
||||
함께 검사했다. 실제 stdout은 다음과 같다.
|
||||
|
||||
```text
|
||||
AUDIT documents=5 local_links=64 requirements=27 cases=27 static_artifacts=8 all_pass
|
||||
```
|
||||
|
||||
문서에서 추출한 공변성 재현 코드의 별도 process exit도 `0`이며 위 표의 모든 수치를
|
||||
재현했다. 지정 input/TXT의 SHA-256은 reference-model의 두 값과 일치했다.
|
||||
초기 audit의 exit `1`은 Python 기본 cp949 decode와 링크의 `%20`을 실제 경로로
|
||||
해석하지 않은 audit-script 문제였다. 명시적 UTF-8과 URL decoding으로 수정해 재실행했으며
|
||||
제품·reference·수치 기준을 변경하지 않았다.
|
||||
|
||||
`git diff --check` exit `0`을 확인했다. 소유 변경은 이 evidence와 numerical-review,
|
||||
reference-model, controls, cases의 Markdown 5개이며 `coordination.md`의 동시 변경은
|
||||
Coordinator 소유다. 본 단계에서 C++ build/test, FEAST runtime, 외부 solver 실행,
|
||||
새 reference comparison은 수행하지 않았다. 이 필수 실행은 case matrix에 따라
|
||||
Implementation이 새 binary와 r2 계약으로 증명해야 한다.
|
||||
|
||||
Reference in New Issue
Block a user