chore: remove retired workflow and historical material
This commit is contained in:
@@ -1,158 +0,0 @@
|
||||
# Shell Transient Heat Transfer 결정 기록
|
||||
|
||||
- Feature ID: `shell-transient-heat-transfer`
|
||||
- Owner: 메인 assistant
|
||||
- 상태: Accepted (구현 검증 완료와 구별)
|
||||
- 승인 근거: ready 인터뷰의 개별 선택, 최종 “네 승인합니다”, 후속 `dryforge:go` 요청.
|
||||
|
||||
기준: [프로젝트 지침](../../AGENTS.md), [프로젝트 PRD](../PRD.md),
|
||||
[공통 ADR](../ADR.md#adr-028). 요구사항과 현재 checklist는 [PRD](PRD.md),
|
||||
지역 소유권은 [FEATURED_AGENTS](FEATURED_AGENTS.md)를 따른다.
|
||||
아래 결정은 이전 Proposed 상태를 대체하며 실제 계산 결과의 정확도 승인을 의미하지 않는다.
|
||||
수식 원본은 [formulation](formulation.md), 독립 판정은 [numerical-review](numerical-review.md)다.
|
||||
|
||||
## STH-ADR-001: Uncoupled transient 범위
|
||||
|
||||
- 상태: Accepted
|
||||
- 결정: 구조해석과 분리된 단일 Shell 과도 열전달 procedure를 구현한다.
|
||||
- 이유: 사용자가 “지금은 uncoupled heat transfer를 구현합니다”라고 명시했다.
|
||||
- 영향: 열응력·변형 피드백·양방향 연성은 장기 목표이며 이번 acceptance에서 제외한다.
|
||||
|
||||
## STH-ADR-002: 다섯 두께 온도점
|
||||
|
||||
- 상태: Accepted; 초기 두께 등온 선택을 대체
|
||||
- 결정: 균질 centered section의 온도점은 항상 다섯 개다. 면내 및 두께 전도를 계산한다.
|
||||
Source DOF 11/13/15는 bottom/midsurface/top이다.
|
||||
- 이유: 기존 DS4 reference와 사용자가 선택한 두께 방향 범위를 유지한다.
|
||||
- 영향: 적층·사용자 선택 온도점 수·삼각형은 제외하며 Abaqus 내부 정식화 동등성을 주장하지 않는다.
|
||||
|
||||
## STH-ADR-003: 상수 물성과 제한된 열입력
|
||||
|
||||
- 상태: Accepted; edge 부분은 STH-ADR-012로 대체
|
||||
- 결정: 양의 유한 상수 k/rho/c와 요소 집합별 재료·일정 두께를 사용한다.
|
||||
초기 온도는 node/Nset별로 지정하되 한 절점의 두께 전체에 동일하다.
|
||||
지정 온도와 집중 열입력은 source DOF 11/15에만 허용하며 step 중 일정하다.
|
||||
- 이유: 사용자 선택 범위에서 독립 검증 가능한 첫 열해석 기능을 구성한다.
|
||||
- 영향: 온도 의존·이방성·표면 분포 flux·대류·복사·내부 발열·내부 station 직접 입력은 제외한다.
|
||||
Concentrated P는 signed power이며 h나 면적을 곱하지 않는다. 중복 하중은 source 순서로 합한다.
|
||||
|
||||
## STH-ADR-004: 모든 완료 증분과 초기 온도 저장
|
||||
|
||||
- 상태: Accepted
|
||||
- 결정: 초기 raw 온도와 모든 완료 증분의 온도·flux·반력 열률을 공식 HDF5에 저장한다.
|
||||
- 이유: 한 시점의 reference 외에도 전체 과도응답을 검증해야 한다.
|
||||
- 영향: Output no-op 요청이 필수 저장량을 줄이지 않는다. 초기 flux/reaction dataset은 없다.
|
||||
종료 규칙은 009, 영속 schema는 013을 따른다.
|
||||
|
||||
## STH-ADR-005: NT11 외부 비교와 독립 물리 검증
|
||||
|
||||
- 상태: Superseded by STH-ADR-015 (원본 비교의 blocking 분류에 한함)
|
||||
- 결정: 기존 CSV의 Step-1, t=37, NT11을 필수 비교하고 나머지는 해석해·수지·수렴으로 검증한다.
|
||||
- 이유: Reference의 실제 coverage는 단일 시점의 아랫면 온도 729행이다.
|
||||
- 영향: 공통 TOLERANCE의 row/family 기준을 유지한다. 추가 Abaqus CSV나 Abaqus 실행은 필수가 아니다.
|
||||
원본 음수·단위·시간을 보정하지 않는다. Source identity 오류는 tolerance 전에 거부한다.
|
||||
|
||||
## STH-ADR-006: 단일 step
|
||||
|
||||
- 상태: Accepted
|
||||
- 결정: 초기 온도에서 일정한 지정 온도·열입력으로 하나의 transient step을 수행한다.
|
||||
- 이유: 사용자의 명시 범위 선택이다.
|
||||
- 영향: 여러 step, restart, 시간 변화 amplitude와 자동 시간 증분을 제외한다.
|
||||
|
||||
## STH-ADR-007: Q4×P2 두 구간과 consistent K/C
|
||||
|
||||
- 상태: Accepted; 이전 수치 방법 Proposed 상태를 대체
|
||||
- 결정: 요소당 20 DOF, Q4 면내 보간과 C0 두 구간 P2 두께 보간을 사용한다.
|
||||
K=integral(B^T k B), C=integral(rho c H^T H), 면내 3×3 Gauss와 두께 exact Z를 채택한다.
|
||||
- 이유: 전도·열저장·반력·에너지를 같은 Galerkin 보간으로 연결하며 직접 54점 적분으로 검산할 수 있다.
|
||||
- 대안·영향: Lumped C, reduced integration, hourglass, 인공 확산과 온도 clamp는 추가하지 않는다.
|
||||
Consistent C는 급변 경계에서 positivity를 보장하지 않으며 일반 warped patch의 3×3은 exact가 아니다.
|
||||
Reference 실패에 맞춰 방법을 변경하지 않는다. 수치 상세 기준은 구현 전 독립 검토한다.
|
||||
|
||||
## STH-ADR-008: 실제 midsurface metric과 normalized station 접속
|
||||
|
||||
- 상태: Accepted; 이전 물리 범위 검토 대기를 대체
|
||||
- 결정: 실제 bilinear 3D midsurface의 metric/법선을 사용하고 두께 offset 곡률 보정을 생략한다.
|
||||
공유 source node의 같은 normalized station을 접속하며 fold와 두께 단차도 같은 규칙을 사용한다.
|
||||
- 이유: 승인한 4절점 Shell과 다섯 온도점을 일관된 product-domain으로 표현한다.
|
||||
- 영향: 접합부의 상세 3D 전도·접촉 저항·추가 부피/용량을 해상하지 않는다.
|
||||
방향이 일관된 manifold mesh만 허용하며 T-edge/vertex-only 접합을 거부한다.
|
||||
전체 patch validity를 검증하고 수치적으로 증명할 수 없는 geometry는 진단한다.
|
||||
임의 warp/aspect cutoff나 자동 normal flip·node weld로 지원 의미를 바꾸지 않는다.
|
||||
|
||||
## STH-ADR-009: Backward Euler와 마지막 짧은 증분
|
||||
|
||||
- 상태: Accepted; 이전 정수 배수 종료 제한 제안을 대체
|
||||
- 결정: A=C/delta+K를 사용하고 동일 계수 factorization을 재사용한다.
|
||||
기본 dt로 진행하고 종료까지 남은 구간만 단축한다. dt>T_end이면 한 증분이다.
|
||||
- 이유: 사용자의 시간 제어 선택을 유지하며 정확한 종료 시점을 저장한다.
|
||||
- 영향: 마지막 delta가 실제로 달라지면 재분해하고 RHS·반력·수지 모두 같은 delta를 사용한다.
|
||||
n*dt 기반 시간격자의 표현오차와 INC 사전검사를 고정한다. 무구속 transient도 유효하다.
|
||||
Generic all-constrained 처리는 algebra 검증이며 공개 내부 station BC 지원이 아니다.
|
||||
|
||||
## STH-ADR-010: Raw 초기값과 step BC override
|
||||
|
||||
- 상태: Accepted; 이전 초기 상태·default 검토 대기를 대체
|
||||
- 결정: t=0은 raw 초기 온도이며 미지정 값은 0이다. 첫 양의 증분에서 g를 적용한다.
|
||||
첫 RHS의 C_fc*T_c_old/delta를 보존한다. Model BC를 상속하고 같은 target의 step BC가 덮어쓴다.
|
||||
- 이유: 원래 초기 상태와 첫 증분의 열저장·반력·에너지 변화를 보존한다.
|
||||
- 영향: 각 단계 안의 동일 BC 중복은 허용하고 상충은 거부한다. Thermal override를 구조 절차에 전파하지 않는다.
|
||||
생략 BC 값은 0이며 초기값을 g로 projection하지 않는다. 순간 impulse를 별도 해상하지 않는다.
|
||||
|
||||
## STH-ADR-011: 직접 flux와 full residual 반력
|
||||
|
||||
- 상태: Accepted; 이전 recovery 검토 대기를 대체
|
||||
- 결정: q_global=-k B T를 면내 네 점×두께 여섯 trace에서 직접 복구한다.
|
||||
Global q와 local frame을 저장하며 local q를 중복 필수 저장하지 않는다.
|
||||
반력 열률은 C*DeltaT/delta+K*T-Q의 constrained 성분이고 양수는 모델로 공급되는 열이다.
|
||||
- 이유: 온도 기울기와 열저장을 포함한 반력을 서로 다른 observable로 검증한다.
|
||||
- 영향: 0-/0+와 요소 경계 값을 평균하지 않는다. Free residual·열에너지는 내부 검증 evidence다.
|
||||
Fourier flux 경계 적분으로 FE 반력을 대체하지 않는다. 초기 반력을 0이나 NaN으로 저장하지 않는다.
|
||||
|
||||
## STH-ADR-012: Edge 분포 열입력 연기
|
||||
|
||||
- 상태: Deferred; 이전 edge kernel·syntax 제안을 대체
|
||||
- 결정: FEM-REQ-SHELL-THERMAL-011을 이번 구현에서 제외한다. Edge kernel·keyword·공개 테스트를 추가하지 않는다.
|
||||
- 이유: Ready에서 사용자가 집중 열입력만 먼저 구현하는 범위를 승인했다.
|
||||
- 영향: 이전 q_in*h*L와 edge weighting 유도는 이번 제품 계약이 아니다.
|
||||
후속 지원에는 별도 단위·부호·대상·중복 의미 및 수치 검증이 필요하다.
|
||||
|
||||
## STH-ADR-013: 입력 subset과 영속 thermal schema
|
||||
|
||||
- 상태: Accepted
|
||||
- 결정: [PRD STH-C02](PRD.md#sth-c02--공개-입력-충돌과-부가-keyword)의 입력과
|
||||
[STH-C05](PRD.md#sth-c05--hdf5-외부-계약)의 schema version 1을 구현한다.
|
||||
- 이유: Domain/source identity에서 결과 row까지 재현 가능한 외부 계약을 고정한다.
|
||||
- 영향: Temperature N×5, global flux E×4×6×3, constrained reaction P를 저장한다.
|
||||
P=0도 빈 dataset을 유지하며 t=0 flux/reaction은 dataset 자체가 없다.
|
||||
지정된 no-op만 warning과 함께 허용하고 unknown keyword는 오류다.
|
||||
초기/완료 frame, mapping·units·finite 값을 atomic finalize 전에 self-check한다.
|
||||
|
||||
## STH-ADR-014: Candidate 보존과 검증 evidence
|
||||
|
||||
- 상태: Accepted
|
||||
- 결정: Domain 정의, non-owning AnalysisModel, DofManager numbering, thermal mutable state를 분리한다.
|
||||
Solve/recovery/검증을 마친 candidate만 반영하고 전체 성공 후 최종 HDF5를 원자 교체한다.
|
||||
- 이유: 실패가 이전 accepted state와 기존 최종 결과를 오염시키지 않도록 한다.
|
||||
- 영향: Deterministic COO reduction과 기존 CLI/lease/exit 분류를 유지한다.
|
||||
전체 baseline을 먼저 재현하고 완료 시 전체 검사를 다시 실행한다.
|
||||
재현된 무관한 HHT temporal 실패만 별도 미해결로 둘 수 있으며 새 실패·악화를 허용하지 않는다.
|
||||
이를 전체 CTest green으로 보고하지 않는다. 열해석 필수 검증 실패는 면제되지 않는다.
|
||||
|
||||
## STH-ADR-015: 원본 reference 진단 전환과 새 모델 비교
|
||||
|
||||
- 상태: Accepted; 사용자 선택 “A, reference 모델을 변경하겠습니다.”
|
||||
- 결정: 승인된 Q4×P2, consistent C, raw 초기값 및 Backward Euler 정식화를 유지한다.
|
||||
기존 `reference/shell-thermal` Step-1/time 37/NT11 family는 진단으로 분류하고
|
||||
공통 tolerance로 계산한 row/family 실패 수치를 그대로 남긴다. 사용자는 새 reference
|
||||
모델과 CSV를 기존 원본과 분리된 경로에 두기로 결정했다. 새 파일이 확정되면 별도의
|
||||
필수 family로 비교한다.
|
||||
- 이유: 원본 729행 중 87행 실패와 RMS/S=0.04967408461567323 초과가 있었고,
|
||||
FESA와 독립적으로 승인 식을 계산한 oracle도 같은 차이를 재현했다.
|
||||
[충돌 evidence](reference-comparison-conflict.md)는 원본의 blocking 조건과 승인 방법을
|
||||
동시에 만족하지 못함을 보여준다.
|
||||
- 영향: 원본 artifact와 공통 tolerance는 수정하지 않는다. 진단 실패를 PASS로 바꾸지
|
||||
않고 row identity·오차를 보고한다. 새 모델의 경로, 원본 hash, 비교 시점·성분·identity가
|
||||
아직 제공되지 않았으므로 새 필수 비교의 실행·통과는 미완료다. 독립 해석해·수지·수렴성,
|
||||
전체 회귀 및 physics 검토를 완료 조건으로 유지한다. 이는 Abaqus 내부 알고리즘의
|
||||
동등성이나 기존 reference가 잘못되었다는 판정이 아니다.
|
||||
@@ -1,24 +0,0 @@
|
||||
# shell-transient-heat-transfer 문서·작업 지침
|
||||
|
||||
- Feature ID: `shell-transient-heat-transfer`
|
||||
- 문서 진입점·목적·사용법·Handoff: [README](README.md).
|
||||
- 현재 범위·checklist: [PRD](PRD.md); 결정·승인·대체 이력: [ADR](ADR.md).
|
||||
- 적용 범위: 해당 기능의 문서. 자동 로드되는 코드 영역 `AGENTS.md`가 아니다.
|
||||
|
||||
기준: [프로젝트 지침](../../AGENTS.md), [ARCHITECTURE](../ARCHITECTURE.md),
|
||||
[Feature 문서 관리](../FEATURE_DOCUMENTATION.md), [공통 tolerance](../TOLERANCE.md).
|
||||
|
||||
## 보존할 계약과 인계
|
||||
|
||||
수식·I/O·수치 기준의 원본은 README에서 연결한 전문 문서를 따른다. 기능을 재개할 때
|
||||
관련 계약과 실제 실행 revision·미해결 항목을 함께 읽는다. 과거 stage pass나 현재 문서
|
||||
정리를 solver 검증 통과로 계산하지 않는다. 요구사항·ADR ID와 승인 이력을 유지한다.
|
||||
메인은 PRD·ADR·진입점·문서 참조를 관리하고 전문 작업자는 할당한 본문과 관련 범위만 수정한다.
|
||||
기존 개인 설정·reference·다른 작업자의 변경을 보존하며 실패를 tolerance 완화로 숨기지 않는다.
|
||||
문서만 수정하면 정적 검토를 수행하고, 동작 변경에는 관련 검사와 필요한 독립 검토를 수행한다.
|
||||
|
||||
Uncoupled Q4×two-P2·consistent C·Backward Euler가 현재 범위다. DOF11/13/15는 bottom/mid/top이고
|
||||
공개 지정온도·열률은11/15만 지원한다. 중립면의 양쪽 flux trace를 평균하지 않는다.
|
||||
원본 NT11은 수치 FAIL을 보존한 diagnostic이며 새 필수 reference는 준비 중이다.
|
||||
Edge 열입력·내부 station BC·열-구조 연성을 확대하지 않는다. Private full-end fixture를
|
||||
공개 입력 지원이나 접합부의 실제3D 전도 검증으로 해석하지 않는다.
|
||||
@@ -1,458 +0,0 @@
|
||||
# Shell Transient Heat Transfer 요구사항과 승인 계약
|
||||
|
||||
- Feature ID: `shell-transient-heat-transfer`
|
||||
- Owner: 메인 assistant
|
||||
- 상태: 사용자 승인 계약; 구현·검증 진행 중
|
||||
- 승인 근거: ready 인터뷰의 명시 선택, 최종 “네 승인합니다”, 후속 `dryforge:go` 실행 요청.
|
||||
|
||||
기준: [프로젝트 지침](../../AGENTS.md), [프로젝트 PRD](../PRD.md),
|
||||
[공통 ADR](../ADR.md#adr-028), [ARCHITECTURE](../ARCHITECTURE.md),
|
||||
[CODINGSTYLE](../CODINGSTYLE.md), [TOLERANCE](../TOLERANCE.md).
|
||||
지역 지침은 [FEATURED_AGENTS](FEATURED_AGENTS.md), 결정 근거는 [ADR](ADR.md),
|
||||
수식은 [formulation](formulation.md), 구현 순서는 [design-plan](design.md#design-plan),
|
||||
독립 수치 판정은 [numerical-review](numerical-review.md)를 따른다.
|
||||
|
||||
개인 연구용 솔버가 일차 목적이며 외부 배포와 양방향 열–구조 연성은 장기 목표다.
|
||||
현재 목표는 3차원 공간의 4절점 shell에 대한 단일 step uncoupled transient heat transfer다.
|
||||
입력 의미, 열 방정식, 시간 적분, 결과 복구, HDF5 저장과 독립 검증을 함께 구현한다.
|
||||
채택 승인은 정확도 통과 evidence가 아니다. 아래는 승인된 실행 명세를 영속 문서에 반영한 계약이다.
|
||||
초기 제안 중 edge 입력 지원과 정수 배수 종료 제한은 아래 계약으로 대체한다.
|
||||
|
||||
## 요구사항과 경계
|
||||
|
||||
`FEM-REQ-SHELL-THERMAL-`를 아래 표의 ID prefix로 사용한다. 기존 ID를 재번호화하지 않는다.
|
||||
|
||||
| ID | 구현할 동작 |
|
||||
| --- | --- |
|
||||
| 001 | 구조해석과 분리된 과도 열전달 procedure |
|
||||
| 002 | 3차원 공간의 DS4 4절점 shell; 평판·유효한 warped patch·곡면 mesh·접힌 판 |
|
||||
| 003 | 절점마다 두께 온도점 5개, 면내와 두께 방향 전도 |
|
||||
| 004 | 단면 전체가 같은 재료인 centered homogeneous shell |
|
||||
| 005 | 상수 등방성 양의 유한 열전도율 k, 밀도 rho, 비열 c |
|
||||
| 006 | 요소 집합별 서로 다른 재료 |
|
||||
| 007 | 요소 집합별 양의 유한 두께 h; 요소 내부에서는 일정 |
|
||||
| 008 | 절점/절점 집합의 초기 온도; 동일 절점의 5점에는 같은 값 |
|
||||
| 009 | 아랫면·윗면의 독립적인 지정 온도 |
|
||||
| 010 | 아랫면·윗면의 독립적인 절점 집중 열입력 |
|
||||
| 011 | **이번 구현에서 연기:** 모서리 분포 열입력. Kernel·keyword·공개 테스트 지원을 추가하지 않음 |
|
||||
| 012 | 지정 온도와 열입력은 step 중 일정 |
|
||||
| 013 | 사용자 지정 총 시간과 기본 시간 간격; 마지막 증분만 필요 시 단축 |
|
||||
| 014 | 온도·요소 전역 열유속·지정 온도점의 반력 열률 |
|
||||
| 015 | 초기 온도와 모든 완료 증분을 공식 HDF5에 저장 |
|
||||
| 016 | 원본 reference Step-1, t=37, NT11의 진단 외부 비교와 새 reference 모델의 필수 비교 |
|
||||
| 017 | 전체 온도·flux·반력에 대한 해석해·수지·시간 및 공간 수렴 검증 |
|
||||
| 018 | 하나의 transient step만 지원 |
|
||||
|
||||
추가 상세 계약은 이 문서의 `STH-C01`–`STH-C08`이다. 위 요구사항의 구체화이며 별도 기능을
|
||||
추가하지 않는다. 제외: 열–구조 연성, 삼각형, 적층, 이방성·온도 의존 물성, 잠열,
|
||||
대류·복사·내부 발열, 윗면/아랫면 분포 열유속, 모서리 분포 입력, 두께 비균일 초기 온도,
|
||||
내부 온도점 직접 BC/CFLUX, 절점별 두께, 사용자 선택 온도점 수, 시간 이력·amplitude,
|
||||
적응 시간 간격, 여러 step, restart, Abaqus 내부 정식화 동등성.
|
||||
|
||||
## STH-C01 — 모델, geometry와 자유도
|
||||
|
||||
### Source 의미
|
||||
|
||||
- Shell geometry 절점은 midsurface에 있다. Source DOF `[11,12,13,14,15]`는 각각
|
||||
`zeta=[-1,-1/2,0,1/2,1]`이며 11은 bottom, 13은 midsurface, 15는 top이다.
|
||||
- 요소 절점 순서는 자연좌표 `(-1,-1),(1,-1),(1,1),(-1,1)`이다. 요소 로컬 DOF는
|
||||
node-major `p=5*(i-1)+a`, i=1..4, a=1..5의 20개다.
|
||||
- Source instance/label, Domain index, full DOF, equation index는 서로 다른 identity다.
|
||||
집합을 전개해도 source row와 target identity를 진단까지 보존한다.
|
||||
- 모든 열 방정식은 활성 DS4에 연결된 온도 DOF에 대해 구성한다. 비활성/미연결 절점을
|
||||
열 방정식에 넣어 0 용량 행을 만들지 않는다. 그런 절점을 명시적으로 대상으로 하는 열
|
||||
initial/BC/load는 유효한 열 target이 아니므로 모델 오류다. 일반 source model의 미사용
|
||||
절점은 보존할 수 있으며 결과의 활성 절점 mapping으로 구분한다.
|
||||
- 한 열해석 모델에 structural B33/S4/S4R 또는 coupled 요소를 혼합하지 않는다.
|
||||
각 DS4에는 정확히 하나의 shell section과 thermal material이 연결되어야 한다.
|
||||
Section 중복 지정은 값이 같아도 오류이며, set 내부의 동일 member는 한 번만 전개한다.
|
||||
|
||||
### Geometry와 접속
|
||||
|
||||
`r=sum(N_i*x_i)`, `a1=r_,xi`, `a2=r_,eta`, `g=A^T A`, `A=[a1,a2]`,
|
||||
`Js=|a1 cross a2|`, `n=(a1 cross a2)/Js`를 평가점별로 사용한다.
|
||||
Warped 요소를 중심 평면에 투영하지 않는다.
|
||||
|
||||
`grad_s(N_i)=A*g^-1*[N_i,xi,N_i,eta]^T`,
|
||||
`grad_*T=grad_s(T)+n*(2/h)*T_,zeta`, `dV*=Js*(h/2)*dxi*deta*dzeta`다.
|
||||
실제 offset surface의 곡률에 따른 metric·면적 변화는 포함하지 않는다.
|
||||
이는 두께 방향 등온 가정이 아니다. 얇은 shell product-domain 모델의 한계를 문서화하며,
|
||||
큰 h/곡률 또는 초기 두께 경계층에 대한 정량 정확도를 검증 없이 보장하지 않는다.
|
||||
|
||||
공유 source node의 같은 normalized zeta 온도는 공유한다. 서로 다른 두께에서도 같으며,
|
||||
실제 물리 z 좌표 일치, 접촉 열저항, 접합부의 유한 부피·추가 용량을 의미하지 않는다.
|
||||
접힌 판·두께 단차의 국소 3D 전도장은 이번 모델의 해상 대상이 아니다.
|
||||
|
||||
Topology는 방향이 일관된 manifold shell 표면이다. 하나의 edge에 최대 두 요소가 접속하고
|
||||
공유 edge를 따라 절점 순서는 반대여야 한다. 불일치는 오류이며 자동으로 뒤집지 않는다.
|
||||
T자 분기 edge, vertex-only 접합과 nonmanifold vertex fan은 거부한다.
|
||||
분리된 여러 shell 영역은 허용하며 좌표만 같은 서로 다른 source node를 자동 병합하지 않는다.
|
||||
서로 다른 instance도 명시적인 공유 source identity가 없으면 연결되지 않는다.
|
||||
|
||||
유한 좌표, 서로 다른 4절점, 양의 Js와 비특이 metric, 자기 교차 없는 patch를 요구한다.
|
||||
적분점 몇 곳의 검사만으로 전체 patch 유효성을 증명했다고 하지 않는다.
|
||||
Roundoff를 고려한 전체 patch의 유효성 판정과 geometry 오차 분리는 STH-C07의 선행
|
||||
수치 계약 작업에서 고정한다. 양의 작은 Jacobian을 clamp하거나 구조 shell의 drilling/
|
||||
director/두께 비율 제한을 검토 없이 전용하지 않는다.
|
||||
|
||||
## STH-C02 — 공개 입력, 충돌과 부가 keyword
|
||||
|
||||
공통 ASCII·대소문자·source ordering·single physical file·part/identity-instance·set 규칙은
|
||||
[공통 입력 계약](../contracts.md)의 기존 계약을 따른다. 열 입력의 추가 subset은 다음과 같다.
|
||||
|
||||
| 입력 | 허용 형식과 의미 |
|
||||
| --- | --- |
|
||||
| `*ELEMENT, TYPE=DS4` | 4절점; 기존 선택적 ELSET 및 topology 구문 사용 |
|
||||
| `*SHELL SECTION, ELSET=..., MATERIAL=...` | 단일 row `h` 또는 `h,5`; 온도점 수 생략은 5. 명시 값은 5만 허용; offset/composite/nodal thickness 제외 |
|
||||
| `*CONDUCTIVITY` | parameter 없는 상수 k 한 row; 선택적 마지막 빈 field 하나 허용 |
|
||||
| `*DENSITY` | 기존 상수 rho 구문; 양의 유한 값 |
|
||||
| `*SPECIFIC HEAT` | parameter 없는 상수 c 한 row; 선택적 마지막 빈 field 하나 허용 |
|
||||
| `*INITIAL CONDITIONS, TYPE=TEMPERATURE` | model-level, `node-or-nset,T`; 각 target의 5점에 같은 유한 T |
|
||||
| `*BOUNDARY` | model 또는 step, `target,dof,dof[,T]`; dof는 11 또는 15, T 생략은 0 |
|
||||
| `*CFLUX` | step-level, parameter 없이 `target,dof,P`; dof 11 또는 15, 유한한 signed P |
|
||||
| `*STEP` | 기존 NAME, INC; NLGEOM은 생략 또는 NO, PERTURBATION 제외 |
|
||||
| `*HEAT TRANSFER` | END 생략 또는 PERIOD; 한 row `dt,T_end` 뒤 최대 3개의 빈 field 허용 |
|
||||
| `*END STEP` | 단일 step 종료 |
|
||||
|
||||
추가 material temperature/field columns, ANISOTROPIC/ORTHOTROPIC, STEADY STATE,
|
||||
DELTMX, 시간증분 최소/최대의 명시 숫자, OP/AMPLITUDE 등 미지원 option은 거부한다.
|
||||
`*BOUNDARY`의 11..15 범위 표기는 내부 station을 포함하므로 거부한다.
|
||||
물성·두께·시간은 양의 유한 값이며 온도는 signed finite scalar다. 섭씨/절대온도 단위를
|
||||
숫자로 추정하지 않는다. Reference 파일의 상수 값을 변환하지 않는다.
|
||||
|
||||
미지정 초기 온도는 0이다. 같은 초기 선언에서 집합이 겹치면 동일 값은 허용하고 다른
|
||||
값은 오류다. BC는 model 단계와 step 단계 각각에서 target을 완전히 전개하여 충돌을
|
||||
확인한 뒤 step의 값이 동일 node/DOF에 대한 model 값을 덮어쓴다. 각 단계 안의 동일
|
||||
값 중복은 허용하며 다른 값은 오류다. 이 override는 thermal에만 적용한다.
|
||||
|
||||
집중 입력은 source row 순서로 더한다. 양수 P는 모델 안으로 공급되는 열률이며 음수는
|
||||
열 제거다. P에 h·면적·shape weight를 곱하지 않는다. 지정 온도와 겹치는 입력도 full Q에
|
||||
유지하여 반력에 반영한다. 온도 또는 열입력이 지정되지 않은 외부 경계는 자연 단열이다.
|
||||
|
||||
Reference에 있는 다음 부가 구문만 열 procedure의 no-op으로 허용한다. Data row가
|
||||
필요 없는 구문에 data를 추가하거나 미지원 option을 붙이면 오류다. 허용한 각 no-op
|
||||
block에 source 위치를 갖는 warning을 하나씩 남기며 필수 결과를 줄이지 않는다.
|
||||
|
||||
- `*PREPRINT, ECHO=NO, MODEL=NO, HISTORY=NO, CONTACT=NO`.
|
||||
- `*RESTART, WRITE, FREQUENCY=0`: restart 파일을 생성하지 않는다.
|
||||
- `*OUTPUT, FIELD, VARIABLE=PRESELECT` 및 `*OUTPUT, HISTORY, FREQUENCY=0`.
|
||||
Child NODE/ELEMENT OUTPUT 및 그 밖의 output 설정은 제외한다.
|
||||
- 하중이 참조하지 않는 assembly `*SURFACE, TYPE=ELEMENT, NAME=...`:
|
||||
기존 target 및 SPOS/SNEG facet 의미를 검증하고 보존하되 열하중으로 사용하지 않는다.
|
||||
- Model-level `*PHYSICAL CONSTANTS, ABSOLUTE ZERO=<finite>`:
|
||||
이번 상수 물성·비복사 모델에서 온도 변환이나 에너지 영점 이동에 쓰지 않는다.
|
||||
|
||||
Unknown/unsupported keyword를 일반적으로 무시하는 fallback은 없다.
|
||||
|
||||
## STH-C03 — 행렬과 시간 적분
|
||||
|
||||
두께는 `[-1,0]`, `[0,1]`의 C0 quadratic 구간 둘로 구성한다. 각 구간에서
|
||||
`s=2*zeta+1` 또는 `s=2*zeta-1`로 두고
|
||||
`l=[s(s-1)/2, 1-s*s, s(s+1)/2]`를 각각 station `(1,2,3)`과 `(3,4,5)`에 놓는다.
|
||||
`dL/dzeta=2*dl/ds`이며 중립면의 온도는 하나지만 미분의 두 trace는 별도다.
|
||||
|
||||
`H_ia=N_i*L_a`, `B_ia=L_a*grad_s(N_i)+n*N_i*(2/h)*L_a,zeta`다.
|
||||
|
||||
```text
|
||||
M_ij = integral_surface N_i N_j dA
|
||||
S_ij = integral_surface grad_s(N_i) dot grad_s(N_j) dA
|
||||
Z0_ab = integral_-1^1 L_a L_b dzeta
|
||||
Z1_ab = integral_-1^1 L_a,zeta L_b,zeta dzeta
|
||||
C_e = rho*c*(h/2) * (M tensor Z0)
|
||||
K_e = k * [(h/2)*(S tensor Z0) + (2/h)*(M tensor Z1)]
|
||||
Z0_segment = [[4,2,-1],[2,16,2],[-1,2,4]] / 30
|
||||
Z1_segment = [[7,-8,1],[-8,16,-8],[1,-8,7]] / 3
|
||||
```
|
||||
|
||||
각 segment의 3×3 행렬을 공유 station 3에 조립한다. 면내 production 적분은 3×3
|
||||
Gauss, 두께는 위 exact Z다. 동일 보간의 직접 54점 적분과 교차 검산한다.
|
||||
Affine 평판의 exact 면내 2×2 검산과 production 규칙을 혼동하지 않는다.
|
||||
Structural 질량을 C로 재사용하지 않으며 lumping, reduced integration, hourglass,
|
||||
인공 확산·온도 clamp를 추가하지 않는다. Consistent C는 급변 BC에서 undershoot를
|
||||
만들 수 있으므로 온도 범위 초과만으로 성공/실패를 결정하지 않는다.
|
||||
|
||||
기본 dt>0, 총 시간 T_end>0에서 종료까지의 증분을 구성한다. 마지막 구간이 남으면 그
|
||||
길이 delta로 단축한다. dt>T_end이면 delta=T_end인 한 증분이다. 적응 제어는 없다.
|
||||
일반 시점은 누적 덧셈 대신 n*dt로 만들고 마지막 저장 시점은 입력 T_end다.
|
||||
정수 배수의 부동소수점 표현 오차 때문에 거의 0인 가짜 증분을 만들지 않는다.
|
||||
시간 비교의 roundoff bound는 입력·곱셈·나눗셈 연산을 근거로 STH-C07에서 고정한다.
|
||||
정상 간격과 표현 오차 수준에서 같은 마지막 간격에는 같은 계수를 사용하며, 실제로
|
||||
단축된 마지막 간격은 모든 방정식·반력·에너지에 동일한 delta를 사용한다.
|
||||
시점이 유한하고 엄격히 증가해야 하며 표현할 수 없는 격자는 진단으로 거부한다.
|
||||
INC는 기존 STEP 기본 100 또는 명시 양의 uint32다. 필요한 완료 증분 수가 INC를
|
||||
넘으면 실행 전에 오류로 처리하며 중간 결과를 성공 결과로 저장하지 않는다.
|
||||
|
||||
각 증분의 Backward Euler 식은 다음과 같다.
|
||||
|
||||
```text
|
||||
A = C/delta + K
|
||||
A_ff*T_f_new = Q_f + C_ff*T_f_old/delta + C_fc*T_c_old/delta - A_fc*g_new
|
||||
T_c_new = g_new
|
||||
```
|
||||
|
||||
입력 초기 T_raw를 t=0에 보존하며 첫 old state로 그대로 쓴다. t=0에 g로 projection하지
|
||||
않는다. 따라서 첫 증분의 `C_fc*(T_c_old-g_new)/delta`는 생략할 수 없다.
|
||||
이 정책은 초기 불연속을 첫 유한 증분에 반영하며 순간 impulse를 해상한다는 뜻은 아니다.
|
||||
동일 계수의 A_ff factorization은 재사용하고 마지막 delta가 바뀌면 다시 구성·분해한다.
|
||||
무구속 단열 모델도 C가 양정치여서 transient A는 양정치다. 연결 component별 K의 상수
|
||||
null mode를 과도계의 singular error로 오인하지 않는다. Generic 0×0 free partition은
|
||||
solve 없이 처리하되 공개 입력은 내부 station을 구속하지 못하므로 all-constrained는
|
||||
algebra fixture로만 검증한다.
|
||||
|
||||
## STH-C04 — 열유속, 반력과 수지
|
||||
|
||||
각 완료 온도장으로 `q_global=-k*B*T_e`를 직접 평가한다. 단위 차원은 power/area다.
|
||||
`e1=a1/|a1|`, `e2=n cross e1`, `R=[e1,e2,n]`이고 후처리 local 성분은 `R^T*q_global`다.
|
||||
Local q3는 bottom에서 top으로 흐를 때 양수다. Local 성분을 중복 필수 저장하지 않는다.
|
||||
|
||||
면내 점 순서는 `(-g,-g),(g,-g),(g,g),(-g,g)`, g=1/sqrt(3)이다.
|
||||
각 점에서 두께 순서는 `(-1,+),(-1/2,interior),(0,-),(0,+),(1/2,interior),(1,-)`로
|
||||
고정한다. 총 24개/요소다. 부호는 해당 두께 위치로 접근하는 쪽이며 바깥 법선 부호가 아니다.
|
||||
중립면 양쪽, 재료 경계와 인접 요소의 값을 평균하지 않는다. Nodal smoothing/extrapolation을
|
||||
공식 flux로 추가하지 않는다. Point source 부근의 mesh 독립적인 유한 flux를 보장하지 않는다.
|
||||
|
||||
```text
|
||||
r = C*(T_new-T_old)/delta + K*T_new - Q
|
||||
reaction = r의 constrained 성분 [power, 양수: 모델에 공급]
|
||||
free residual = r의 free 성분 [내부 검증 evidence]
|
||||
DeltaE = 1^T*C*(T_new-T_old) [energy]
|
||||
DeltaE = delta*(sum(Q)+sum(reaction)+sum(free residual))
|
||||
```
|
||||
|
||||
물리 수지 defect와 free residual 크기를 별도로 검사한다. 위 등식이 대수적으로 맞는다는
|
||||
사실만으로 free equation 정확도를 주장하지 않는다. 에너지 영점을 자동 추정하지 않으며
|
||||
온도 기준 이동에 대한 에너지 변화의 불변성을 검사한다. Fourier flux의 경계 적분은
|
||||
일반적으로 FE 반력과 같지 않으며 반력 대신 사용하지 않는다. BE의 C-norm 소산도
|
||||
실제 열에너지 보존과 별도 검증한다. t=0 반력은 미정의다.
|
||||
|
||||
## STH-C05 — HDF5 외부 계약
|
||||
|
||||
CLI는 기존 `fesa.exe <model.inp>`이고 output은 lexical sibling `<stem>_results.h5`다.
|
||||
새 thermal 형식은 기존 structural 형식을 변경하지 않는다. 아래 모든 필드는 mandatory다.
|
||||
F64/U64/U8/I8은 고정 폭 little-endian, 문자열은 UTF-8다. Compound는 field/type/extent로
|
||||
읽으며 메모리 padding을 계약으로 삼지 않는다. Float 결과는 모두 finite다.
|
||||
|
||||
### Metadata와 model
|
||||
|
||||
`/metadata` scalar attributes:
|
||||
|
||||
| 이름 | 값/형식 |
|
||||
| --- | --- |
|
||||
| schema_version | U64, 1 |
|
||||
| feature_id | `shell-transient-heat-transfer` |
|
||||
| analysis_procedure | `uncoupled-transient-heat-transfer` |
|
||||
| source_step_name | 입력의 원문 step 이름, 생략 시 Step-1 |
|
||||
| solver_version | 기존 build version |
|
||||
| source_input_identity | 실제 읽은 입력 byte의 기존 identity 계약 |
|
||||
| unit_system_label | `user-consistent-unspecified` |
|
||||
| internal_formulation | `FESA-Q4-P2x2-thermal-shell` |
|
||||
| integration_rule | `surface-3x3-gauss; thickness-exact-P2x2` |
|
||||
| time_integration | `backward-euler` |
|
||||
| nominal_time_increment | F64, 입력 dt |
|
||||
| time_period | F64, 입력 T_end |
|
||||
|
||||
Model의 기본 row 순서는 기존 Domain의 stable source declaration/instance expansion 순서다.
|
||||
|
||||
| Dataset | Shape/field와 의미 |
|
||||
| --- | --- |
|
||||
| `/model/nodes` | 기존 node compound: internal_node_id U64, instance_name/string, source_label/string, coordinates F64[3] |
|
||||
| `/model/elements` | thermal DS4 row: internal_element_id U64, instance_name/string, source_label/string, source_element_type=`DS4`, internal_formulation/string, node_internal_ids U64[4], shell_section_internal_id U64, material_internal_id U64 |
|
||||
| `/model/thermal_materials` | internal_material_id U64, name/string, conductivity F64, density F64, specific_heat F64 |
|
||||
| `/model/shell_sections` | internal_section_id U64, source_file/string, source_line U64, source_elset/string, material_internal_id U64, thickness F64 |
|
||||
| `/model/thermal_node_ids` | U64[N], 활성 온도 절점의 internal_node_id, 원래 node 순서를 유지 |
|
||||
| `/model/thermal_element_ids` | U64[E], flux 요소 행에 대응하는 internal_element_id, 원래 element 순서 유지 |
|
||||
| `/model/temperature_dofs` | U64[5]=[11,12,13,14,15] |
|
||||
| `/model/temperature_zeta` | F64[5]=[-1,-0.5,0,0.5,1] |
|
||||
| `/model/thermal_constraint_mask` | U8[N,5], free=0/constrained=1 |
|
||||
| `/model/thermal_reaction_dofs` | compound[P]: internal_node_id U64, source_dof U64; mask의 1인 항목을 thermal node 행/DOF 순서로 나열 |
|
||||
| `/model/thermal_flux_inplane_coordinates` | F64[4,2], 위 xi/eta 순서 |
|
||||
| `/model/thermal_flux_zeta` | F64[6]=[-1,-0.5,0,0,0.5,1] |
|
||||
| `/model/thermal_flux_trace_side` | I8[6]=[1,0,-1,1,0,-1]; 0=interior, +/-1=위의 접근 방향 |
|
||||
| `/model/thermal_flux_local_frames` | F64[E,4,3,3], 마지막 두 축은 global component와 local axis; R의 열이 e1,e2,n |
|
||||
|
||||
ID는 해당 model table에 존재해야 하며 중복·누락 mapping은 self-check 실패다.
|
||||
Reaction mapping은 source DOF 11/15만 포함한다. P=0이면 길이 0인 dataset을 유지한다.
|
||||
Material/section의 source provenance는 기존 모델 writer convention을 보존한다.
|
||||
Structural elastic E/nu나 displacement mask를 thermal material/DOF 대신 기록하지 않는다.
|
||||
|
||||
### Frames
|
||||
|
||||
Storage slot은 `/steps/Step-1`로 고정하며 실제 step 이름은 metadata로 구별한다.
|
||||
`/steps/Step-1/accepted_frames`는 compound[N_step+1]이고 field는
|
||||
`frame_index U64`, `increment_index U64`, `time F64`, `time_increment F64`, `is_initial U8`다.
|
||||
Frame/index는 0..N_step이고 서로 같다. 초기 행은 time=0, time_increment=0, is_initial=1,
|
||||
나머지는 완료 시간과 해당 방정식에 사용한 양의 delta, is_initial=0이다.
|
||||
각 `/steps/Step-1/frames/<decimal-index>` group에도 위 다섯 scalar attribute를 저장한다.
|
||||
|
||||
| Frame 상대 경로 | Shape | 초기 frame | 완료 frame |
|
||||
| --- | --- | --- | --- |
|
||||
| `nodal/temperature` | F64[N,5] | raw 초기 온도 | 완료 온도 |
|
||||
| `nodal/reaction_heat_rate` | F64[P] | **dataset 없음** | constrained full residual, reaction mapping 순서 |
|
||||
| `element/heat_flux` | F64[E,4,6,3] | **dataset 없음** | global qx,qy,qz |
|
||||
|
||||
Temperature attributes는 `component_order=NT11,NT12,NT13,NT14,NT15`,
|
||||
`units_label=temperature`, `coordinate_system=scalar`, `location=nodal-thickness-stations`다.
|
||||
Reaction은 `component_order=RFL`, `units_label=power`, `coordinate_system=scalar`,
|
||||
`location=prescribed-temperature-dofs`, `positive_direction=into-model`이다.
|
||||
Flux는 `component_order=QX,QY,QZ`, `units_label=power/area`,
|
||||
`coordinate_system=global-cartesian`, `location=element-inplane-thickness-traces`다.
|
||||
Model geometry의 좌표·두께는 length, normalized coordinates/frames/masks/IDs는
|
||||
dimensionless다. `/model/nodes`는 `units_label=length`,
|
||||
`/model/shell_sections`는 `thickness_units_label=length`를 가진다.
|
||||
`/model/thermal_materials`의 세 attribute는
|
||||
`conductivity_units_label=power/(length*temperature)`,
|
||||
`density_units_label=mass/volume`, `specific_heat_units_label=energy/(mass*temperature)`다.
|
||||
`/steps/Step-1/accepted_frames`에는 `time_units_label=time`을 저장하며 time과
|
||||
time_increment 모두에 적용한다. 서로 다른 단위의 compound field를 하나의
|
||||
모호한 units_label로 합치지 않는다.
|
||||
|
||||
초기 frame의 누락 flux/reaction은 정해진 schema이며 NaN이나 계산된 0으로 대체하지 않는다.
|
||||
Free residual·열에너지는 검증 보고서의 evidence로 유지하고 필수 공개 dataset을 추가하지 않는다.
|
||||
Warnings는 기존 `/diagnostics` compound convention의 source/severity/code/message를 유지한다.
|
||||
형식 discriminator, schema, mandatory field·shape·identity·finite value·frame 완전성을
|
||||
atomic finalization 이전에 self-check한다. Unknown optional additive field를 무시할 수
|
||||
있으나 잘못된 mandatory schema를 허용하지 않는다.
|
||||
|
||||
## STH-C06 — 런타임 소유권과 실패
|
||||
|
||||
Domain은 thermal material/section/initial/BC/load/step 정의를 소유하며 parsing 이후
|
||||
불변이다. AnalysisModel은 non-owning active view, DofManager는 열 5개와 구조 6개의
|
||||
layout, numbering, scatter, constraint 및 sparse pattern을 전담한다. Equation ID를
|
||||
Node/Element에 분산시키지 않는다. Thermal kernel/procedure/state/recovery를 구분하고
|
||||
구조 displacement API에 temperature를 위장하거나 structural mass로 C를 취급하지 않는다.
|
||||
미래 coupling state를 미리 할당하지 않는다. Vendor type은 기존 adapter 경계 안에 둔다.
|
||||
|
||||
Assembly는 element-local contribution, stable COO ordering/reduction을 사용한다.
|
||||
병렬 worker가 global CSR를 직접 갱신하지 않는다. 같은 입력은 같은 sparse structure,
|
||||
축약 순서, diagnostic order와 result row order를 만든다.
|
||||
|
||||
증분마다 solve, full temperature 복구, residual/flux/finite/수지 검증을 끝낸 candidate만
|
||||
accepted state에 반영한다. 실패 시 마지막 accepted state를 오염시키지 않는다.
|
||||
최종 output은 전체 해석 성공과 writer self-check·close 후 원자적으로 교체한다.
|
||||
실패 시 기존 최종 HDF5를 보존하며 로그는 실패 진단으로 갱신될 수 있다.
|
||||
Output lease와 CLI exit 2/3/4/5/6의 기존 분류를 유지한다. 초기 해석 성공이나 이전
|
||||
파일 존재만으로 이번 실행 성공을 표시하지 않는다. Failed trial을 accepted_frames에 넣지 않는다.
|
||||
|
||||
## STH-C07 — 독립 검증과 수치 계약의 선행 조건
|
||||
|
||||
채택된 수식의 일관성에 관한 기존 독립 검토와 실제 solver 정확도 검증을 구별한다.
|
||||
수치 전문 작업은 kernel 구현 전에 [정식화](formulation.md)와 [독립 수치 검토](numerical-review.md)에 아래 세부 계약을 문서화하고 독립 numerical review를
|
||||
통과해야 한다. 이는 기존 PRD가 numerical owner에게 맡긴 상세 설계 작업이다.
|
||||
|
||||
1. 전체 bilinear patch 유효성·orientation 판정, 비다양체 판정, scale-aware degeneracy
|
||||
bound와 검증할 geometry군. 전역 자기 교차 검출이나 contact 기능을 추가하지 않는다.
|
||||
2. Roundoff metric: 행렬 norm·연산 수·machine epsilon·conditioning을 근거로 exact
|
||||
fixture 및 free residual의 bound를 도출한다. 예: backward error의 분모는
|
||||
`||A_ff||*||T_f||+||b_f||`; 분모 0은 별도 처리한다. `max(1,scale)` floor 금지.
|
||||
3. 에너지 defect는 저장·외력·반력 항의 절댓값 합을 기준으로 정의하고 free residual
|
||||
평가와 분리한다. 이산 수지와 BE 소산 각각의 roundoff 전파를 문서화한다.
|
||||
4. 3×3/5×5/7×7 quadrature 비교, 시간/공간 convergence의 norm·mesh·시간·series
|
||||
절단 오차·판정 구간을 독립 oracle와 예상 asymptotic order에서 도출한다.
|
||||
5. 고정 5점의 slab 오차 plateau와 초기 열침투 깊이 sqrt(alpha*t)를 보고하는 기준,
|
||||
비교 시점과 각 물리량의 허용 이산 오차를 테스트 실행 전에 고정한다.
|
||||
6. 시간격자 roundoff 동등성·increment count·overflow와 representability 판정을 고정한다.
|
||||
|
||||
이 수치 기준을 구현 결과에 맞춰 완화하거나 외부 reference 5%/1%를 내부 검사에
|
||||
전용하지 않는다. 검토에서 3×3 방법 변경, 지원 geometry 축소, 추가 물리 또는 accuracy
|
||||
acceptance 변경이 필요하면 구체적 근거를 제시하고 사용자 결정으로 돌아간다.
|
||||
수치 상세 기준의 독립 검토가 끝나기 전 production kernel 착수를 통과로 표시하지 않는다.
|
||||
|
||||
필수 검증은 다음과 같다. 별도 허용을 뜻하는 fixture와 공개 CLI 사례를 구별한다.
|
||||
|
||||
| 검증 | 독립 oracle와 실패 검출 |
|
||||
| --- | --- |
|
||||
| Shape/K/C | sum(H)=1, sum(B)=0, 정확 M/S/Z, C SPD, K rank19/상수 null, symmetry, 양의 에너지, h 및 1/h scaling, 분리식/직접54점 일치 |
|
||||
| 방향/flux | constant/면내선형/두께선형 patch, global rotation covariance, normal 반전과 station 재매핑, R 직교성 |
|
||||
| 중립면 trace | kernel state (0,0,0,1,2)에서 q3(0-)=0, q3(0+)=-4k/h; 공개 초기조건 사례로 오인하지 않음 |
|
||||
| 초기 jump | C=[[2,1],[1,2]], K=[[1,-1],[-1,1]], delta=1/2, old=(0,0), 두 번째 g=1: 첫 free=-1/5, 다음=1/25, 반력24/5와36/25 |
|
||||
| 시간격자 | 정수배, 10/3 마지막1, dt>T, decimal roundoff, INC 초과, 비표현 가능 시간, 마지막 factorization 변경 및 실제delta 반력/수지 |
|
||||
| 열저장/하중 | 단열 균일 온도 유지, no-BC transient, P 및 -P, overlapping source load 합산, constrained DOF에 P 유지, disconnected component별 보존 |
|
||||
| Partition | 0×0 all-constrained generic algebra; 공개 내부 station BC 금지 유지 |
|
||||
| 면내 해석해 | 단열 직사각형 T=T0+A*cos(pi*x/L)*exp(-alpha*(pi/L)^2*t), alpha=k/(rho*c); 온도와 미분 flux, 면내 L2 온도2차/gradient1차 |
|
||||
| 시간 해석해 | 같은 고정 spatial discretization의 독립 eigenpair Kv=lambda Cv 및 exp(-lambda*t), BE 증폭률; dt refinement의 1차 오차 |
|
||||
| 두께 slab | 균일 초기온도, bottom step 온도/top 단열 Fourier series; 5점 온도·flux·열에너지·반력, series 절단 bound 및 두께 오차 plateau |
|
||||
| 재료/두께/접속 | full-end prescribed strip의 sum L/(k*h*w) 저항은 assembly fixture; 실제 bottom/top-only CLI는 해당 조건의 독립 oracle 사용. Fold 등온 및 조립 열률 수지 |
|
||||
| Geometry | 왜곡/warped patch 적분 비교, scaling/translation, zero/negative/uncertain metric, 자기 교차, 방향 충돌, T edge와 vertex-only junction 음성 사례 |
|
||||
| IO/실패 | 모든 양성/음성 subset, source identity, HDF5 round trip, 초기 dataset 부재, P=0 반력, 마지막delta, no-op warnings, candidate/lease/write/self-check/close 실패 시 기존결과 보존 |
|
||||
|
||||
구현 단계에는 열해석 관련 검사를 먼저 수행하고 전체 MSVC x64 Debug build/CTest와
|
||||
확정된 새 reference의 필수 비교를 수행한다. 기존 reference의 진단 비교도 실패 수치까지
|
||||
보고한다. 새 compiler warning을 추가하지 않는다.
|
||||
구현 전 전체 검사를 실행하여 기존 HHT 시간수렴 실패 2건의 실제 재현·이름·metric을
|
||||
기록한다. 기록만으로 현재 실패를 가정하지 않는다. 구현 후 전체 검사에서 제외하지 않고,
|
||||
새 실패·기존 실패 악화를 허용하지 않는다. 재현된 기존의 무관한 HHT 실패만 별도
|
||||
미해결로 유지할 수 있으며 전체 CTest green이라고 보고하지 않는다.
|
||||
예상하지 못한 baseline failure는 자동 면제하지 않고 원인과 영향 범위를 확인한다.
|
||||
열해석의 필수 검증 실패는 이 예외에 포함되지 않는다.
|
||||
|
||||
## STH-C08 — Reference 원본과 완료 evidence
|
||||
|
||||
대상 경로는 다음 두 개다.
|
||||
|
||||
- `reference/shell-thermal/shell-thermal.inp`
|
||||
- `reference/shell-thermal/shell-thermal NodalTemperature.csv`
|
||||
|
||||
구현 preflight에서 동일 저장소의 기존 dev worktree에 있는
|
||||
동일 상대 경로에서 byte 그대로 복사한다. `git worktree list --porcelain`으로 dev
|
||||
worktree를 찾고 파일별 SHA256을 아래와 대조한다. 이 방식은 머신 절대경로를 계약에
|
||||
고정하지 않는다. 원본이 달라졌거나 없으면 임의 생성·보정·대체하지 않는다.
|
||||
|
||||
| 파일 | 확인한 SHA256 |
|
||||
| --- | --- |
|
||||
| shell-thermal.inp | 955C8BEEC35CE53DA5F5DD48785CF8C12FCE726EBFDE7EAE40CF69DBF00D6EA4 |
|
||||
| shell-thermal NodalTemperature.csv | 765B0D0F64C24CDE6D033D6EF80E0267275A496C97E28D932466EB877810D3E5 |
|
||||
|
||||
목적 파일이 이미 있으면 hash 일치를 확인해 재사용하고 다르면 덮어쓰지 않는다.
|
||||
복사 전후 hash와 사용한 경로를 evidence에 남긴다. Abaqus를 실행하거나 원본 파일명,
|
||||
내용, metadata를 수정하는 권한은 포함하지 않는다. FESA HDF5/log는 복사한 입력 옆에
|
||||
생성한다. 보조 deterministic CSV view는 공식 결과가 아니다.
|
||||
|
||||
기존 외부 family는 `(shell-thermal, source step Step-1, time 37, bottom temperature NT11,
|
||||
scalar, user-consistent temperature units, diagnostic)`이다. 원본은 단일 Part-1-1,
|
||||
676 DS4, 729 node이며 CSV의 `Step,Frame,Node Label,NT11`에서 instance 열 부재는
|
||||
입력의 단일 instance 및 label 집합 검증으로만 복원한다. HDF5의 source_step_name,
|
||||
정확한 t=37 accepted frame, source DOF11을 일대일 대응한다. Nearest-time matching,
|
||||
station 평균, 행 순서 추정, 잘못된 instance 추정은 금지한다.
|
||||
|
||||
Missing/extra/duplicate/nonfinite/identity 오류는 tolerance 전에 실패다.
|
||||
[공통 tolerance](../TOLERANCE.md)의 S=max|reference|, B=0.01S, near-zero absolute<=B,
|
||||
그 밖의 relative<=0.05, family RMS/S<=0.01, S=0 exact-zero 규칙을 그대로 적용한다.
|
||||
관찰된 min=-15.5742216, max=1000은 정적 관찰이며 solver 통과 evidence가 아니다.
|
||||
음수·미소값을 clamp하거나 온도 기준·단위를 조정해 비교를 통과시키지 않는다.
|
||||
이 원본 비교의 tolerance 초과는 진단 실패로 남긴다. Row identity 오류와 metric을
|
||||
숨기거나 원본 비교를 통과로 표시하지 않는다. 독립 계산과 실제 실패 evidence는
|
||||
[충돌 보고서](reference-comparison-conflict.md)에 보존한다. 사용자가 새 reference 모델과
|
||||
CSV를 기존 `reference/shell-thermal`과 분리된 경로에 두기로 결정했다. 해당 입력·CSV
|
||||
경로, source row identity, 비교 시점·성분과 새 파일의 hash가 확정되면
|
||||
이를 별도의 필수 family로 지정하여 실제 비교한다. 새 artifact가 아직 제공되지 않았으므로
|
||||
새 family의 통과를 주장하지 않는다. 공통 tolerance 수치는 변경하지 않는다.
|
||||
|
||||
완료 보고서는 구현 diff, 실제 검증 명령/환경·결과, 독립 numerical/physics 검토,
|
||||
외부 비교 row/family 판정, 기존 HHT 실패, 남은 물리 한계를 구분한다.
|
||||
새 reference 모델과 그 결과 CSV가 확정되어야 새 필수 family를 실행할 수 있다.
|
||||
이는 다른 물리량의 해석해·수지·수렴성 검증을 생략하는 근거가 아니다.
|
||||
|
||||
## 현재 checklist
|
||||
|
||||
- [x] 요구사항 인터뷰와 단일 uncoupled step 범위 확정
|
||||
- [x] Q4×P2 두 구간, consistent C, 3×3/exact Z, BE 채택 승인
|
||||
- [x] Geometry 접속 이상화, raw 초기값, 마지막 짧은 증분, 입력·HDF5 계약 승인
|
||||
- [x] 모서리 분포 입력 011 연기 및 reference 복사 승인
|
||||
- [x] 실행 계획 승인 및 구현 요청
|
||||
- [x] 정식화 정합과 상세 수치 기준의 [독립 검토](numerical-review.md) 완료
|
||||
- [x] Production 변경 전 전체 baseline과 reference hash evidence 기록
|
||||
- [x] Thermal semantic model·DOF·geometry·K/C·flux 구현 및 [독립·통합 검증](implementation-verification.md#요소-kernel과-형상-검증)
|
||||
- [x] Thermal 입력 subset·진단·결정적 조립·시간 적분 구현 및 [범위별 검증](implementation-verification.md#backward-euler-procedure와-candidate-검증)
|
||||
- [x] HDF5·CLI·candidate와 기존 결과 보존 [검증](implementation-verification.md#application과-실제-cli)
|
||||
- [x] 승인 정식화와 원본 reference 통과 조건의 [실측 충돌](reference-comparison-conflict.md)에 대한 사용자 결정: 기존 비교는 진단, 정식화 유지, 새 reference 모델 사용
|
||||
- [x] [해석해·수지·수렴성 검증](implementation-verification.md#t10-해석해수지수렴성과-원본-진단-비교)과 원본 NT11 진단 비교의 실패 metric 보존
|
||||
- [ ] 새 reference 모델·CSV·identity 확정 및 필수 외부 비교 통과
|
||||
- [x] 전체 MSVC Debug build/CTest 및 [기존 실패 대비 확인](implementation-verification.md#통합-전체-회귀와-남은-완료-조건): 614 PASS·기존 2 FAIL·1 SKIP, 추가 139개 모두 PASS
|
||||
- [x] [독립 physics 검토](physics-evaluation.md)와 [구현·검증 evidence 기록](implementation-verification.md#통합-전체-회귀와-남은-완료-조건)
|
||||
|
||||
새 필수 reference 모델·CSV는 사용자 답변에 따라 아직 준비 중이다. 위 실행·검토 완료는
|
||||
그 외부 비교의 통과를 뜻하지 않으며, 파일·identity 확정과 실제 필수 비교가 완료되어야
|
||||
기능 검증 완료로 판단한다.
|
||||
|
||||
미실행 검사를 통과로 표시하지 않는다. 전문 문서의 수치 유도·검산, 실제 solver 검사,
|
||||
외부 reference 비교와 physics 검토는 서로 다른 evidence다.
|
||||
@@ -1,252 +0,0 @@
|
||||
# 구현 방법과 재사용 Handoff
|
||||
|
||||
현재 구현·검증 상태는 [PRD](PRD.md)와 [구현 검증](implementation-verification.md)을 따른다. 아래는 채택 방법론이며 새 실행 계획이 아니다.
|
||||
|
||||
<a id="design-plan"></a>
|
||||
|
||||
<a id="design-plan--shell-transient-heat-transfer-상세-설계구현-계획안"></a>
|
||||
## Shell Transient Heat Transfer 상세 설계·구현 계획안
|
||||
|
||||
- 상태: 사용자 승인 실행 계획. 구현·검증 진행 중이며 수치 통과 evidence와 구별한다.
|
||||
- 기준: [Feature PRD](PRD.md), [프로젝트 지침](../../AGENTS.md), [ARCHITECTURE](../ARCHITECTURE.md),
|
||||
[CODINGSTYLE](../CODINGSTYLE.md), [TOLERANCE](../TOLERANCE.md)
|
||||
- 수식의 상세 원본: [정식화](formulation.md). 현재 checklist는 [PRD](PRD.md#현재-checklist)에만 둔다.
|
||||
- 독립 검토: [numerical-review.md](numerical-review.md). 수식의 일관성 검토이며 구현·정확도 통과 판정은 아니다.
|
||||
|
||||
<a id="design-plan--1-구현할-해석과-채택-방법"></a>
|
||||
### 1. 구현할 해석과 채택 방법
|
||||
|
||||
입력의 4절점 Shell mesh에서 온도만 풀며, 한 절점에 두께 방향 온도 5개를 둔다.
|
||||
요소당 20개 온도 자유도로 면내·두께 방향 전도와 열저장을 함께 계산한다.
|
||||
기존 MITC4의 변위·회전 강성행렬을 열행렬로 전용하지 않는다.
|
||||
|
||||
| 항목 | 채택 방법 | 선택 이유와 한계 |
|
||||
| --- | --- | --- |
|
||||
| 면내 보간 | Bilinear Q4 | 승인된 4절점 topology와 연결되며 상수 온도·평판 선형 온도장을 재현 |
|
||||
| 두께 보간 | 2개 구간의 C0 2차 Lagrange 보간 | 5개 온도점을 사용하고 중앙 온도점을 공유. 전체 두께 단일 4차 보간보다 구간별 gradient와 적분을 분리하기 쉬움 |
|
||||
| geometry | 실제 3차원 midsurface의 metric과 법선을 이용하는 thin-shell product-domain | 접힌 판·곡면을 같은 scalar 열전도 문제로 구성. 두께 offset에 따른 곡률 보정은 생략하는 모델임을 명시 |
|
||||
| 열용량 | Consistent heat-capacity matrix | Galerkin 약형에서 직접 유도하고 열저장·반력·에너지 계산에 같은 행렬 사용. Lumping·인공 확산·온도 clamp는 승인 범위 밖 |
|
||||
| 적분 | 면내 3×3 Gauss, 두께의 두 P2 구간은 정확 적분한 Z 행렬 사용 | 직접 54점 적분과 대조. Affine 평판은 2×2 면내 적분도 정확하며 곡면·왜곡은 고차 적분 대조로 오차 확인 |
|
||||
| 시간 적분 | Backward Euler, 고정 Δt | 일정 계수 선형 문제에서 factorization을 재사용할 수 있고 첫 구현의 시간 수렴 검증이 명확 |
|
||||
| 열유속 | 보간 온도의 기울기에서 직접 복구 | 요소별·위치별 Fourier 열유속과 전체 residual 반력을 구별하여 검증 |
|
||||
|
||||
이 표는 사용자가 채택한 FESA 방법이며 Abaqus 내부 알고리즘 동등성의 약속이 아니다.
|
||||
특히 consistent C가 현재 reference의 과도응답을 공통 tolerance 안에서 재현하는지는
|
||||
아직 검증하지 않았다. 시간 적분의 안정성이 양의 온도 보존이나 정확도를 보장하지도 않는다.
|
||||
|
||||
<a id="design-plan--2-온도-자유도와-보간"></a>
|
||||
### 2. 온도 자유도와 보간
|
||||
|
||||
온도점의 무차원 두께 좌표는 `ζ = [-1, -1/2, 0, 1/2, 1]`, 실제 좌표는 `z=hζ/2`다.
|
||||
요소 vector는 node-major 순서로 정의한다.
|
||||
|
||||
\[
|
||||
\mathbf T_e=[T_{1,1},\ldots,T_{1,5},T_{2,1},\ldots,T_{4,5}]^T.
|
||||
\]
|
||||
|
||||
Source 자유도 11~15와 위 온도점 1~5를 명시적으로 대응시킨다. 내부 equation 번호와
|
||||
source 자유도를 같은 정수로 취급하지 않는다. 현재 reference의 NT11은 아랫면 값이다.
|
||||
|
||||
\[
|
||||
T_h(\xi,\eta,\zeta)=\sum_{a=1}^4\sum_{s=1}^5
|
||||
N_a(\xi,\eta)L_s(\zeta)T_{a,s}=\mathbf H\mathbf T_e.
|
||||
\]
|
||||
|
||||
Q4의 `N_a`와 두께의 `L_s` 및 도함수는 [정식화](formulation.md)에 명시한다.
|
||||
5개의 서로 독립적인 2D 판을 만드는 것이 아니라, 두께 도함수 항으로 온도점 사이를 결합한다.
|
||||
|
||||
<a id="design-plan--3-3차원-geometry와-열전도행렬-k"></a>
|
||||
### 3. 3차원 geometry와 열전도행렬 K
|
||||
|
||||
Midsurface를 `r(ξ,η)=Σ N_a x_a`로 나타낸다. 접선 행렬 `A=[r_,ξ r_,η]`, metric
|
||||
`G=AᵀA`, 면적 Jacobian `J_s=|r_,ξ×r_,η|`, 단위 법선 `n`을 계산한다.
|
||||
면내 gradient와 전체 gradient의 각 열은 다음과 같다.
|
||||
|
||||
\[
|
||||
\nabla_sN_a=A G^{-1}\begin{bmatrix}N_{a,\xi}\\N_{a,\eta}\end{bmatrix},
|
||||
\qquad
|
||||
\mathbf B_{a,s}=L_s\nabla_sN_a+
|
||||
\mathbf n N_a\frac{2}{h}L'_s.
|
||||
\]
|
||||
|
||||
`B`는 3×20이며 `∇T=B T_e`다. 등방성 전도율 `k>0`에 대해
|
||||
|
||||
\[
|
||||
\boxed{\mathbf K_e=\frac h2\int_{-1}^1\!\int_{-1}^1\!\int_{-1}^1
|
||||
\mathbf B^T(k\mathbf I)\mathbf B\,J_s\,d\zeta\,d\eta\,d\xi}
|
||||
\]
|
||||
|
||||
를 20×20 행렬로 계산한다. `L_s L_t ∇_sN_a·∇_sN_b`는 면내 전도,
|
||||
`N_aN_b(2/h)^2 L'_sL'_t`는 두께 전도다. 법선과 면내 접선의 직교성 때문에 이
|
||||
product-domain 모델의 교차항은 0이다. 평판에서 각각 대략 `kh`, `k/h`의 두께 scaling을 갖는다.
|
||||
|
||||
`G`의 퇴화, 뒤집히거나 자기 교차하는 요소, 불일치하는 surface side는 입력 geometry
|
||||
진단으로 처리한다. `|det J|`로 invalid 요소를 정상화하거나 임의의 최소 두께를 대입하지 않는다.
|
||||
중앙면 접속은 같은 normalized thickness station을 공유하는 이상화다.
|
||||
두께가 다른 요소의 단차·급한 fold의 실제 3D 접합부 열장은 이 모델의 해상 범위 밖이다.
|
||||
이 접속 의미와 얇은 Shell 곡률 근사는 사용자가 채택한 물리 모델이며 상세 3D 전도를 보장하지 않는다.
|
||||
|
||||
<a id="design-plan--4-열용량행렬-c와-적분-절차"></a>
|
||||
### 4. 열용량행렬 C와 적분 절차
|
||||
|
||||
밀도 `ρ>0`, 비열 `c>0`에 대해
|
||||
|
||||
\[
|
||||
\boxed{\mathbf C_e=\frac h2\int\rho c\,\mathbf H^T\mathbf H\,J_s
|
||||
\,d\zeta\,d\eta\,d\xi}
|
||||
\]
|
||||
|
||||
를 계산한다. K의 단위는 `power/temperature`, C는 `energy/temperature`다.
|
||||
사용자가 일관된 단위계를 제공하며 코드가 입력 숫자를 보고 SI 단위로 추정하지 않는다.
|
||||
|
||||
계산 순서는 다음과 같다.
|
||||
|
||||
1. 면내 9개 Gauss 위치에서 `N`, 도함수, `J_s`, `G`, 법선을 계산한다.
|
||||
2. `M_ij=∫N_iN_j dA`, `S_ij=∫∇_sN_i·∇_sN_j dA`의 4×4 행렬을 누적한다.
|
||||
3. 정확히 적분한 `Z0_ab=∫L_aL_b dζ`, `Z1_ab=∫L'_aL'_b dζ`의 5×5 행렬을 사용한다.
|
||||
4. Node-major 순서에서 `C=ρc(h/2)(M⊗Z0)`, `K=k[(h/2)(S⊗Z0)+(2/h)(M⊗Z1)]`를 구성한다.
|
||||
5. finite·대칭성·차원과 상수 온도 null mode를 확인한 element candidate를 반환한다.
|
||||
|
||||
Z의 명시 행렬은 [정식화](formulation.md)에 있다. 별도의 직접 적분 검산은 면내 9점 ×
|
||||
두께 2구간 × 구간당 3점, 총 54개 위치에서 H/B를 구성해 같은 K/C를 얻는지 확인한다.
|
||||
Affine 평판은 면내 2×2 × 두께 6점, 총 24점으로도 정확하다. 5개 온도점, 6개 두께 적분
|
||||
위치, 아래의 flux trace 위치는 서로 다른 개념이다. 곡면은 면내 3×3→5×5→7×7 대조로
|
||||
적분 오차를 평가하며 reduced integration이나 hourglass 안정화항을 추가하지 않는다.
|
||||
|
||||
<a id="design-plan--5-열입력과-지정-온도"></a>
|
||||
### 5. 열입력과 지정 온도
|
||||
|
||||
공개 입력은 source DOF 11/15에 대한 일정한 절점 집중 power P만 지원한다.
|
||||
양수는 모델로 공급되는 열이며 h·면적·shape weight를 곱하지 않는다. Source row 순서로
|
||||
더하고 constrained DOF의 입력도 full Q에 유지한다. Edge 분포 입력 011은 연기되었으며
|
||||
이번에 kernel이나 keyword를 추가하지 않는다. 지정되지 않은 외부 경계는 자연 단열이다.
|
||||
|
||||
초기 온도는 node/Nset별 signed finite 값으로 5점에 동일 적용하고 미지정 값은 0이다.
|
||||
BC 생략값은 0이며 model 단계와 step 단계 각각에서 중복 충돌을 검사한 뒤 step이
|
||||
동일 target의 model 값을 덮어쓴다. 동일 값 중복은 허용하고 다른 값은 오류다.
|
||||
정확한 subset·미지원 옵션·no-op warning은 [PRD STH-C02](PRD.md#sth-c02--공개-입력-충돌과-부가-keyword)를 따른다.
|
||||
|
||||
<a id="design-plan--6-transient-equation과-해법"></a>
|
||||
### 6. Transient equation과 해법
|
||||
|
||||
\[
|
||||
\mathbf C\dot{\mathbf T}+\mathbf K\mathbf T=\mathbf Q+\mathbf R.
|
||||
\]
|
||||
|
||||
Backward Euler로 다음을 구성한다.
|
||||
|
||||
\[
|
||||
\mathbf A=\mathbf C/\Delta t+\mathbf K,\qquad
|
||||
\mathbf b^{n+1}=\mathbf Q^{n+1}+\mathbf C\mathbf T^n/\Delta t.
|
||||
\]
|
||||
|
||||
free/constrained partition에서
|
||||
|
||||
\[
|
||||
\boxed{\mathbf A_{ff}\mathbf T_f^{n+1}=
|
||||
\mathbf Q_f^{n+1}+\mathbf C_{ff}\mathbf T_f^n/\Delta t+
|
||||
\mathbf C_{fc}\mathbf T_c^n/\Delta t-\mathbf A_{fc}\mathbf g^{n+1}}
|
||||
\]
|
||||
|
||||
를 푼다. 초기 구속점 온도와 step 지정 온도가 다르면 첫 증분의
|
||||
`C_fc(T_c^0−g)/Δt` 항을 빠뜨리면 안 된다. 입력 초기 상태를 `t=0`에 보존하고
|
||||
첫 양의 시점부터 step 지정 온도를 부과하는 것이다. 초기 값을 덮어쓴 다른 해석과
|
||||
에너지·reference 결과가 달라지므로 raw 초기값을 조용히 projection하지 않는다.
|
||||
|
||||
고정 물성·geometry·구속 집합·Δt에서는 A_ff를 한 번 factorize하고 매 증분 RHS만 갱신한다.
|
||||
전체 시간이 Δt로 나누어떨어지지 않으면 마지막 증분만 종료까지 단축한다. Δt가 전체 시간보다
|
||||
크면 한 증분이다. 시간은 n*Δt로 생성하고 마지막 저장 시점은 입력 종료 시간이다. 표현 오차
|
||||
수준으로 같은 마지막 간격은 같은 계수를 사용하고 실제로 짧은 간격만 재분해한다.
|
||||
시간격자·INC·표현 가능성의 상세 판정은 정식화와 독립 numerical review에서 고정한다.
|
||||
|
||||
절연체의 K는 상수 온도 null mode를 가지지만 양의 C 때문에 A는 양정치다.
|
||||
정적 solver처럼 “온도 구속이 없으므로 singular”로 판정하지 않는다. 일반 partition 연산은
|
||||
전체 구속 시 0×0 free solve를 건너뛰도록 검산한다. 다만 이번 공개 입력은 bottom/top만
|
||||
구속하므로 내부 3개 온도점까지 모두 구속한 사례는 CLI 지원 모델이 아닌 algebra fixture다.
|
||||
|
||||
<a id="design-plan--7-heat-flux와-reaction-heat-rate-복구"></a>
|
||||
### 7. Heat flux와 reaction heat rate 복구
|
||||
|
||||
각 완료 증분에 element scatter로 `T_e`를 모아, 동일한 B로
|
||||
|
||||
\[
|
||||
\boxed{\mathbf q^{global}=-k\mathbf B\mathbf T_e}
|
||||
\]
|
||||
|
||||
를 계산한다. 단위는 `power/area`이며 고온에서 저온 방향이 양의 흐름이다.
|
||||
local 직교 frame `R=[e_1,e_2,n]`이면 `q_local=Rᵀq_global`이고,
|
||||
앞 두 성분은 면내, 세 번째는 두께 방향 열유속이다.
|
||||
|
||||
- 기본 authoritative flux는 면내 2×2 Gauss 위치와 두께 trace
|
||||
`[-1+, -1/2, 0−, 0+, 1/2, 1−]`의 곱인 24개 위치에서 복구한다. 두께 trace는 구간
|
||||
안쪽에서 평가하는 위치/접근 방향이다. Global 성분과 local frame을 저장하고 local 성분은 Rᵀq로 후처리한다.
|
||||
- 위 trace 위치에서 B를 직접 평가한다. C0 보간의 중앙면에서 두께 도함수는 한쪽 극한
|
||||
두 개일 수 있으므로 `0−`와 `0+`를 평균으로 합치지 않는다. 행렬의 적분 위치와 복구 위치는 독립이다.
|
||||
- 재료 경계와 요소 경계를 넘어 nodal averaging한 값을 공식 heat flux로 사용하지 않는다.
|
||||
- 부호를 비교할 때 아랫면의 외향 법선은 `−n`, 윗면은 `+n`임을 구별한다.
|
||||
|
||||
반력 열률은 gradient flux를 절점으로 평균하여 만들지 않고 full residual에서 계산한다.
|
||||
|
||||
\[
|
||||
\boxed{\mathbf r^{n+1}=\mathbf C(\mathbf T^{n+1}-\mathbf T^n)/\Delta t
|
||||
+\mathbf K\mathbf T^{n+1}-\mathbf Q^{n+1}}
|
||||
\]
|
||||
|
||||
free 성분은 평형 잔차, constrained 성분은 지정 온도 유지에 필요한 반력 열률이다.
|
||||
양의 반력은 모델에 추가로 공급한 열이다. transient 반력에는 열저장 항이 포함되어야 한다.
|
||||
초기 온도는 저장하지만 `t=0` flux와 reaction dataset은 생성하지 않는다. 반력을 계산된 0이나 NaN으로 대체하지 않는다.
|
||||
|
||||
<a id="design-plan--8-기존-코드와-연결할-책임파일"></a>
|
||||
### 8. 기존 코드와 연결할 책임·파일
|
||||
|
||||
현재 `Element::Recover`는 displacement를 소비하고 `DofManager`는 `kDofsPerNode=6`을
|
||||
전제로 한다. 따라서 parser에 DS4만 추가해서 완료할 수 없다. 다음은 실제 저장소 경로와
|
||||
신규 파일 배치다. 세부 C++ signature는 승인된 I/O·정식화 계약과 기존 객체 책임을 따른다.
|
||||
|
||||
| 작업 경계 | 기존 수정 대상 | 신규 파일과 책임 |
|
||||
| --- | --- | --- |
|
||||
| Semantic model | `include/fesa/model/domain.h`, `src/fesa/model/domain.cpp`, `include/fesa/model/model_types.h`, `include/fesa/materials/material.h` | `include/fesa/materials/isotropic_thermal_material.h`, `src/fesa/materials/isotropic_thermal_material.cpp`: 양의 k·ρ·c와 source identity |
|
||||
| Thermal element | `include/fesa/elements/element_definition.h`, `src/fesa/elements/element_factory.cpp`의 definition/runtime 생성 경계 | `include/fesa/elements/thermal_shell.h`, `src/fesa/elements/thermal_shell.cpp`: 20×20 K/C와 직접 flux 복구. 열 kernel을 구조 Element의 displacement 계약에 억지로 넣지 않음 |
|
||||
| Geometry | 기존 `model/shell_geometry`의 MITC4 definition/director 의존성 확인 | `src/fesa/elements/thermal_shell_geometry.h`, `.cpp`: Q4 metric·법선·geometry 검증. 구조 shear tying·drilling 정보 불필요 |
|
||||
| DOF | `include/fesa/elements/element.h`, `include/fesa/fem/dof_manager.h`, `src/fesa/fem/dof_manager.cpp` | Explicit layout/constraint 입력 경계를 추가하여 DofManager 안에서 구조 6개·열 5개 profile을 구별. 기존 구조 numbering/scatter 계약 보존 |
|
||||
| Thermal assembly | `SparseMatrix::FromCoo`, `ParallelFor` 재사용 | `include/fesa/assembly/thermal_assembler.h`, `src/fesa/assembly/thermal_assembler.cpp`: 동일 scatter의 K/C, stable COO reduction과 source-ordered Q |
|
||||
| Procedure/state | `analysis_model.h/.cpp`, `prepared_analysis.h/.cpp`, `src/fesa/app/fesa_application.cpp` | `include/fesa/analysis/transient_heat_procedure.h`, `src/fesa/analysis/transient_heat_procedure.cpp`, `include/fesa/analysis/thermal_analysis_state.h`: factorize/step/recover/candidate commit |
|
||||
| Abaqus mapping | `src/fesa/io/abaqus/domain_mapping_context.cpp`, `domain_builder.cpp`, `topology_mapper.cpp`, `material_property_mapper.cpp`, `step_definition_mapper.cpp` | 책임별 thermal block mapping 추가. 기존 structural validation의 제한을 온도에 그대로 적용하지 않음 |
|
||||
| Results | 기존 HDF5 atomic file·primitives와 prepared outcome dispatch | `include/fesa/results/thermal_results_writer.h`, `include/fesa/io/hdf5/thermal_hdf5_results_writer.h`, `src/fesa/io/hdf5/thermal_hdf5_results_writer.cpp`: 온도/flux/reaction/history identity와 atomic finalize |
|
||||
|
||||
Domain이 정의를 소유하고 AnalysisModel이 non-owning view를 제공하는 기존 책임을 유지한다.
|
||||
새 thermal state만 temperature/history를 소유한다. Node/Element에 equation 번호를 저장하지 않는다.
|
||||
열용량 C를 structural mass field에 저장하지 않으며 vendor API는 기존 backend 경계에 둔다.
|
||||
|
||||
<a id="design-plan--10-방법론을-반증할-검증-사례"></a>
|
||||
### 10. 방법론을 반증할 검증 사례
|
||||
|
||||
필수 사례의 원본은 [PRD STH-C07](PRD.md#sth-c07--독립-검증과-수치-계약의-선행-조건)이다.
|
||||
정확 fixture·norm·시간/mesh 목록·oracle 절단 및 order 판정은 [독립 수치 검토](numerical-review.md)가 소유한다.
|
||||
|
||||
- Shape partition, affine exact K/C, constant null mode, C SPD, 양의 에너지와 회전 변환.
|
||||
- 일정 온도·면내 선형·두께 선형 flux 및 중앙면 0-/0+를 구별하는 직접 미분.
|
||||
- 두 자유도 C=[[2,1],[1,2]], K=[[1,-1],[-1,1]], delta=.5, old=0, 두 번째 g=1에서
|
||||
첫 free=-.2, 두 번째 .04, reaction=4.8와1.44. 첫 C_fc 이전 상태 항을 검출한다.
|
||||
- No-BC 균일 보존, P/-P·constrained P·source 중복과 component별 에너지 수지.
|
||||
- Semidiscrete 독립 eigenmode로 시간1차, Fourier 직사각형의 L2 온도2차·gradient1차.
|
||||
- Bottom step/top 단열 slab series의 온도·flux·에너지·반력; 고정5점 두께 오차 plateau와 초기 침투 깊이 보고.
|
||||
- 다중 재료/두께 strip 저항은 full-end assembly fixture로 확인한다. 내부 station BC를 CLI로 확대하지 않는다.
|
||||
- 원본 Step-1 t37 NT11 729행의 identity precheck와 공통 tolerance 진단 비교;
|
||||
새 reference 모델이 확정되면 별도 필수 비교. [STH-ADR-015](ADR.md#sth-adr-015-원본-reference-진단-전환과-새-모델-비교)를 따른다.
|
||||
|
||||
에너지 defect의 scale은 저장·외력·반력 항의 절댓값 합이며 free residual을 별도로 검사한다.
|
||||
E=1ᵀCT의 기준 온도 이동에 대한 DeltaE 불변성과 BE C-norm 소산은 서로 다른 검사다.
|
||||
외부 5%/1% 기준으로 내부 수지를 판정하거나 max(1,scale)로 작은 모델의 오류를 숨기지 않는다.
|
||||
|
||||
<a id="design-plan--12-채택-모델의-한계"></a>
|
||||
### 12. 채택 모델의 한계
|
||||
|
||||
Product-domain은 실제 offset 곡률과 상세 접합부를 해상하지 않는다. 고정5점은 초기 두께
|
||||
경계층을 충분히 해상하지 못할 수 있고 면내 refinement가 두께 오차를 제거하지 않는다.
|
||||
Consistent C/BE의 안정성은 positivity나 정확도를 보장하지 않는다. Point source 부근의
|
||||
mesh 독립적인 유한 flux는 보장하지 않는다. 이 한계를 임의 clamp나 tolerance 완화로 숨기지 않는다.
|
||||
|
||||
Reference의 NT11 최소값 -15.5742216은 S=1000, B=10의 near-zero 범위 밖이다.
|
||||
공통 상대오차 검사를 유지하고 초기 jump·공간 이산·열용량의 영향을 독립적으로 평가한다.
|
||||
현재 채택 계약을 바꾸어야 하는 충돌이 확인되면 근거를 제시하고 사용자 결정으로 돌린다.
|
||||
@@ -1,513 +0,0 @@
|
||||
# Shell 과도 열전달 구현·검증 기록
|
||||
|
||||
- Feature ID: `shell-transient-heat-transfer`
|
||||
- Owner: 메인 assistant
|
||||
- 상태: 열해석 구현·전체 회귀·독립 검토 완료. 새 필수 reference 비교는 미실행이며 제품 검증 완료가 아니다.
|
||||
- 기준: [PRD](PRD.md), [ADR](ADR.md), [정식화](formulation.md),
|
||||
[독립 수치 검토](numerical-review.md), [공통 tolerance](../TOLERANCE.md).
|
||||
|
||||
## Production 변경 전 baseline
|
||||
|
||||
검사 대상 source revision은 `a3502c9b974bc17698d57438274408f29317ced4`다.
|
||||
검사 도중 reference 두 파일만 `e6fd9e9`에 추가했으며 production source와 테스트는 변경하지 않았다.
|
||||
정식화·계약 문서 편집은 별도 task checkout에서 수행했다.
|
||||
|
||||
Windows MSVC x64 Debug, CMake/Ninja와 기존 설치된 의존성을 사용했다.
|
||||
MSVC toolset 14.51.36231, oneAPI MKL 2026.1, TBB 2023.1, HDF5 2.1.1 및
|
||||
승인 local GoogleTest checkout을 사용했다. 머신별 절대 경로는 개인 실행 환경에만 둔다.
|
||||
저장소에 `.harness/config.json`이 없어 직접 preset을 실행했다.
|
||||
|
||||
| 실행 | Captured exit | 관찰 |
|
||||
| --- | --- | --- |
|
||||
| `cmake --preset windows-msvc-ninja-debug -DCMAKE_PROJECT_FESA_INCLUDE=` | 0 | Configure 완료; 추가 task source overlay 없음 |
|
||||
| `cmake --build --preset windows-msvc-ninja-debug --parallel 4` | 0 | 전체 baseline build 완료; compiler warning 검색 결과 없음 |
|
||||
| `ctest --preset windows-msvc-ninja-debug --show-only=json-v1` | 0 | 478개 검사 발견 |
|
||||
| `ctest --preset windows-msvc-ninja-debug --output-on-failure` | 8 | 478개: 475 PASS, 2 FAIL, 1 SKIP. 3480.67초; 전체 검사 제외 없음 |
|
||||
|
||||
실제 로그·argv·revision·exit·완료 시각은 로컬 `.dryforge/evidence/baseline-*.log`와
|
||||
각 `.log.json`에 보존한다. 전체 CTest 로그도 `.dryforge/evidence/baseline-LastTest.log`에
|
||||
복사해 후속 실행으로 덮어쓰이지 않도록 보존했다. Native CTest exit은 8이고 외부
|
||||
PowerShell 실행 도구는 실패 exit 1을 반환했다. 아래 표는 실제 로그의 값을 요약한다.
|
||||
|
||||
### 기존 HHT 실패
|
||||
|
||||
`HhtShellPhysics.C08aRigidManufacturedOrbitFullCoordinateTimeConvergence`는
|
||||
828.34초 실행 후 실패했다. 여섯 channel의 정의와 원래 판정은
|
||||
`tests/unit/analysis/hht_shell_physics_test.cpp`의 해당 검사 그대로다.
|
||||
|
||||
| 실패 metric | 실제 값 | 기존 기준 |
|
||||
| --- | --- | --- |
|
||||
| Channel 3 최종 refinement error / noise floor | `1.178006582488537e-6` / `1.664587376115457e-6` | error > noise floor |
|
||||
| Channel 5 마지막 시간격자의 최대 error | `5.675659240050177e-4` | <= `1e-4` |
|
||||
| Channel 5 두 refinement order | `1.0286686694389584`, `1.0289692381730642` | 각각 >= `1.8` |
|
||||
| Channel 5 error / noise floor | `5.675659240050177e-4` / `8.1556816896757325e-4` | error > noise floor |
|
||||
|
||||
`HhtShellPhysics.C08bFreeFiniteRotationPlateSelfConvergenceAndPhysicalInvariants`는
|
||||
2382.81초 실행 후 실패했다. 마지막 공통시간 차이는 다음과 같다.
|
||||
|
||||
| Channel | 마지막 self-difference | 기존 기준 |
|
||||
| --- | --- | --- |
|
||||
| q_u | `5.5474274071377627e-6` | <= `1e-4` (이 항목은 통과) |
|
||||
| q_phi | `1.3870090193204238e-4` | <= `1e-4` |
|
||||
| v_u | `1.7761250930811503e-4` | <= `1e-4` |
|
||||
| v_phi | `1.15434079805253e-2` | <= `1e-4` |
|
||||
| a_u | `1.1979645042237048e-2` | <= `1e-4` |
|
||||
| a_phi | `8.6893881162834119e-1` | <= `1e-4` |
|
||||
|
||||
q_phi/v_phi/a_u/a_phi의 마지막 두 관측 차수는 각각
|
||||
`(-.1538334889569796,.17869938751647654)`,
|
||||
`(-.084636748464689021,.057860368459572473)`,
|
||||
`(.4062904963410236,.20093674620022031)`,
|
||||
`(-.15578672026532631,.17674898422982255)`로 기존 `>=1.8`에 미달했다.
|
||||
v_u의 마지막 차수도 `.85658192310858094`로 미달했다.
|
||||
Linear momentum drift의 마지막 세 값은
|
||||
`3.8504721819452428e-14`, `4.8249991985258491e-14`, `2.004031863681472e-13`으로,
|
||||
원래 strict decrease와 마지막 비율 `<=.6` 검사도 실패했다. 작은 값이라는 이유로 면제하지 않는다.
|
||||
최종 energy/L drift는 `9.5590394502167011e-7` / `4.2974921804532845e-7`이었다.
|
||||
이 실패 양상은 [기존 HHT physics 검토](../hht-implicit-dynamics/physics-evaluation.md)의
|
||||
미해결 C08 범위와 일치하며 열해석 변경 이전에 재현했다.
|
||||
|
||||
### 기존 HHT N7 inconclusive
|
||||
|
||||
`HhtTemporalVerification.C04aFinestReductionComparisonIsNumericallyResolved`는
|
||||
기존 테스트의 명시 `GTEST_SKIP()` 분기로 SKIP이었다. Full/reduced acceleration defect
|
||||
`3.0790209097630861e-10`이 기존 비교 기준 `1e-10`보다 크지만 arithmetic/solve resolution
|
||||
`6.2961354117696263e-10` 이하인 경우를 N7 INCONCLUSIVE로 표시하는 원래 검사다.
|
||||
원인과 범위를 `tests/unit/analysis/hht_temporal_verification_test.cpp:478` 및 실제 출력으로
|
||||
대조했다. 환경 누락이나 열 기능의 미실행이 아니며, 이 항목을 PASS로 세지 않는다.
|
||||
최종 전체 검사에서도 이 분류와 metric을 대조하고 새 skip으로 검증을 회피하지 않는다.
|
||||
|
||||
승인된 예외는 재현된 무관한 기존 HHT 실패의 별도 보존뿐이다. 마지막 전체 검사에서
|
||||
동일 metric을 대조하여 새 실패·악화 여부를 확인한다. 기존 실패를 PASS/SKIP으로 바꾸거나
|
||||
전체 CTest green으로 보고하지 않는다. 예상하지 못한 실패와 열해석 필수 실패는 자동 면제하지 않는다.
|
||||
|
||||
## Reference 복사와 원본 보존
|
||||
|
||||
`git worktree list --porcelain`으로 확인한 동일 저장소 `dev` checkout의
|
||||
`reference/shell-thermal/`에서 다음 두 파일을 같은 상대 경로로 byte 그대로 복사했다.
|
||||
원본과 복사본의 SHA256이 각각 일치했고, 복사본을 `e6fd9e9`에 기록했다.
|
||||
|
||||
| 파일 | 원본과 복사본의 SHA256 |
|
||||
| --- | --- |
|
||||
| `shell-thermal.inp` | `955C8BEEC35CE53DA5F5DD48785CF8C12FCE726EBFDE7EAE40CF69DBF00D6EA4` |
|
||||
| `shell-thermal NodalTemperature.csv` | `765B0D0F64C24CDE6D033D6EF80E0267275A496C97E28D932466EB877810D3E5` |
|
||||
|
||||
Abaqus 실행·reference 재생성·이름 변경·내용 보정은 수행하지 않았다.
|
||||
이 hash 확인은 FESA/reference 수치 비교 통과 evidence가 아니다.
|
||||
|
||||
## 구현 및 최종 검증
|
||||
|
||||
### 구현 전 수치 계약
|
||||
|
||||
정식화와 승인 범위의 정합, 전체 patch certificate, source 접속, 시간격자·오차·수렴·slab
|
||||
검증 기준을 작성하고 독립 수치 검토를 마쳤다. 검토 대상 정식화의 마지막 수식 변경은
|
||||
`dd409b5`, 독립 보고서의 최종 보완은 `6df5a17`이다. 설계상 blocking 지적은 해결했다.
|
||||
소스 구현의 정확도 통과 판정은 아니다.
|
||||
|
||||
- 전역 T-edge 좌표 검사를 source endpoint를 공유하는 후보로 제한하여 disconnected 접촉을 구별했다.
|
||||
- 입력 rounding-cell을 놓치는 시간격자 반례를 발견하고 정확한 cell overlap으로 보완했다.
|
||||
Production은 최대 122비트의 고정 폭 연산이며 새 임의정밀도 의존성을 요구하지 않는다.
|
||||
- 공간수렴 검증은 8/16/32/64 정사각 mesh, `T=.001`, 32증분으로 고정했다.
|
||||
기존 관찰 차수 기준을 유지하고 시간오차/공간오차 비율의 최대값 `.006864`를 확인했다.
|
||||
가장 큰 mesh의 온도·flux 원시 이력은 약 77.3MiB다.
|
||||
- 고정5점의 초기 slab 오차·warped 3×3 적분 오차는 별도로 정량화했다.
|
||||
|
||||
통합된 문서의 [독립 oracle 부록](verification-oracles.md#독립-oracle와-재현)의 Python block 5개를
|
||||
메인이 다시 추출 실행했다. Captured Python exit 0,
|
||||
`ALL SCRATCH BLOCKS COMPLETED`를 확인했고 출력은
|
||||
`.dryforge/evidence/t1-oracle-replay.log`에 보존했다.
|
||||
기능 문서의 링크·anchor·요구사항 ID 및 `git diff --check`도 통과했다.
|
||||
문서 변경을 이유로 solver build/CTest를 반복하지 않았다.
|
||||
|
||||
### Thermal semantic model
|
||||
|
||||
열물성·Domain·AnalysisModel semantic 구현을 `254247e`, `283628e`로 작성하고,
|
||||
독립 코드 검토에서 해당 범위의 잔여 차단 항목이 없음을 확인했다.
|
||||
BC/CFLUX는 source DOF 11·15만 허용한다. 열 재료·단면의 local index와 전체 Domain
|
||||
material index를 구분하며, 구조 step 접근을 열 모델에 잘못 호출하면 명시적으로 실패한다.
|
||||
두 단계 BC는 원본 수준별 정의를 보존하며 최종 상속·override는 후속 입력/실행 연결의 책임이다.
|
||||
|
||||
Endpoint 제한의 행동 재현 검사에서 기존 구현이 12·13·14를 수용하여 CTest exit 8을
|
||||
확인했고 수정 후 통과했다. 이전 API 누락에 의한 compile 실패는 행동 재현 evidence로
|
||||
계산하지 않는다. 잘못된 물성·두께, 비활성 target, 초기값·BC 충돌, constrained CFlux
|
||||
중복·순서 보존, 이동 후 소유 데이터 접근과 다중 재료 인덱스를 검사했다.
|
||||
|
||||
작업 checkout의 clean MSVC x64 Debug build와 최종 fixture 추가 후 incremental build는
|
||||
각각 exit 0이다. 최종 관련 CTest는 **21/21 PASS**, exit 0이며 compiler warning은
|
||||
검색되지 않았다. 실제 evidence는 `t2-correction-clean-build-build.log`,
|
||||
`t2-correction-final-build-build.log`, `t2-correction-final-regression-test.log` 및 각
|
||||
명령·cwd·native exit JSON에 보존했다. 실행 당시 HEAD는 commit 전 `254247e`이고,
|
||||
최종 검사 09:47:06 UTC 후 동일 수정분을 `283628e`로 기록했다.
|
||||
|
||||
검증 중 한국어 MSVC `/showIncludes` prefix가 CMake에서 잘못 decode되어 Ninja가
|
||||
header dependency를 0개로 기록하는 환경 문제를 발견했다. Header 변경 후 이전 객체를
|
||||
재사용하여 AnalysisModel 접근 오류가 발생했다. 개인 검증 환경에서 실제 UTF-8 prefix를
|
||||
지정하고 clean build한 뒤 같은 객체의 dependency가 47개이며 관련 header를 포함함을
|
||||
확인했다. 잘못된 추적 상태의 중간 incremental 결과는 최종 evidence로 사용하지 않는다.
|
||||
Production 변경 전 baseline은 175개 build action을 처음부터 실행한 결과로 유지한다.
|
||||
|
||||
공통 CMake source/test 등록 후 통합 checkout에서도 clean build exit 0, CTest inventory
|
||||
**487개**, 관련 semantic·기존 structural DOF 검사를 포함한 **29/29 PASS**를 확인했다.
|
||||
Evidence는 `.dryforge/evidence/semantic-integrated-{configure,build,test}.log`와
|
||||
`semantic-integrated-serial-inventory.log`다. 최초 inventory와 test를 동시에 시작했을 때
|
||||
GoogleTest discovery의 공용 JSON 생성이 경합하여 inventory exit 8이 발생했다.
|
||||
직렬 inventory 재실행은 exit 0이며, 이후 같은 build tree의 discovery/test는 직렬 실행한다.
|
||||
|
||||
### Thermal DOF 매핑
|
||||
|
||||
`e71f3ad`, `17a2355`의 열 5성분 profile, 활성 절점 번호, 20-entry scatter, partition과
|
||||
CSR 매핑을 독립 검토했다. Canonical 11..15 순서, 비연속 반복 절점, 잘못된 enum 범위,
|
||||
구조/열 profile 오용을 거부한다. 미사용 절점이 중간에 있는 경우와 공유 edge·분리 영역,
|
||||
BC 상속·override, 실패 후 전체 mapping 보존을 확인했다.
|
||||
|
||||
`t4-final3-build.log`는 native exit 0, `t4-final3-test.log`는 **13/13 PASS**, exit 0이다.
|
||||
이 중 기존 structural DofManager 검사는 8개다. `t4-final2-inventory.log`의 491개는
|
||||
discovery 수이며 전체 실행 수가 아니다. 검사 후 마지막 수정은 줄바꿈·들여쓰기뿐임을
|
||||
독립 reviewer가 확인했고, 범위 내 잔여 차단 항목 없이 `7b9a36c`로 통합했다.
|
||||
요소 kernel과 결합한 통합 검사는 kernel 완료 후 수행한다.
|
||||
|
||||
PATH 밖의 설치된 clang-format을 확인한 뒤 새 semantic 파일의 서식을 적용했다.
|
||||
`8ba4d18`은 세 신규 파일의 서식 수정이며 관련 신규 header/source/test의 dry-run 검사는
|
||||
exit 0이다. 앞선 수동 서식 확인을 formatter 실행으로 대신 주장하지 않는다.
|
||||
|
||||
### 시간격자 독립 실행 확인
|
||||
|
||||
요소 kernel과 분리된 시간격자 checkpoint `e33ee6a`를 독립 검토자가 별도 실행기로
|
||||
컴파일했다. Production의 binary64 입력 cell 판정을 exact Fraction oracle의
|
||||
**11,043개 사례**에 대조했고, 유효 11,030개와 입력·INC 거부 13개에서 불일치가 없었다.
|
||||
**66,023개 Frame 표본**의 저장 시각·실제 delta가 비트 단위로 일치했다.
|
||||
기본 INC=100, 범위 밖 Frame 거부와 진단도 확인했다.
|
||||
|
||||
MSVC `/Od /W4 /WX /fp:precise` standalone build, runner 및 비교기는 각각 native exit 0이다.
|
||||
원래 subnormal 간격, open/closed midpoint, 최대 finite, 실제 shortened 마지막 증분과
|
||||
거대한 count의 O(1) 사전검사를 포함한다. Evidence는 작업 checkout의
|
||||
`.dryforge/review/time_grid_e33ee6a/`에 committed source manifest, 실제 출력,
|
||||
`comparison.json` 및 실행 명령으로 보존했다. 이는 시간격자에 한정한 evidence이며
|
||||
kernel·procedure·physics의 최종 판정을 대신하지 않는다.
|
||||
|
||||
### 요소 kernel과 형상 검증
|
||||
|
||||
요소 구현 checkpoint `32f0c16`의 독립 행동 계약 검토에서 잔여 차단 항목이 없었다.
|
||||
Domain의 node/section 범위 검사 뒤 전체 patch와 source 접속을 검사하며, 분리 영역의
|
||||
좌표 접촉을 자동 연결하지 않는다. Recovery는 4×6 위치, 중립면의 별도 두 trace와
|
||||
열벡터 `e1/e2/n`을 유지한다. 생성·복구 실패는 기존 kernel을 변경하지 않는다.
|
||||
|
||||
작업 checkout의 `t3-ready-build.log`, `t3-ready-test.log`는 native exit 0이며
|
||||
**32/32 PASS**다: kernel 10, geometry 9, time 7, semantic 6개다.
|
||||
`t3-ready-inventory.log`의 513개는 discovery 수이며 전체 실행 수가 아니다.
|
||||
실행 metadata의 HEAD는 commit 전 `e33ee6a`이고, 검사한 수정분을 이후 `32f0c16`에
|
||||
기록했다. Build warning은 검색되지 않았고 formatter와 `git diff --check`도 통과했다.
|
||||
`32f0c16`의 독립 수치 검토도 잔여 차단 항목 없이 통과했다. Commit에서 추출한 실제
|
||||
kernel/geometry를 MSVC로 별도 컴파일하여 고정밀 oracle와 대조했다.
|
||||
|
||||
- 유효 fixture 22개의 C/K 계수 17,600개와 평가점 198개의 면적·gradient enclosure
|
||||
2,574개에서 production 반올림 오차 경계 위반이 없었다.
|
||||
- 직접 54점 적분과 절댓값 contribution 기준, C 양정치·K rank 19·상수 모드,
|
||||
두께 변화·별도 중립면 trace·source topology 14개 사례를 확인했다.
|
||||
- 고정 affine/distorted/saddle 사례의 3/5/7 적분 진단과 production C/K를 이용한
|
||||
독립 BE 대수 응답, 실제 `Recover`의 온도 응답 5개를 확인했다. 전역 procedure를
|
||||
실행한 결과는 아니다.
|
||||
|
||||
실제 명령·native exit와 계산 결과는 작업 checkout의
|
||||
`.dryforge/review/kernel_32f0c16/`에 보존했다. 최종 compile/runner/checker는 모두 exit 0이다.
|
||||
최초 surface oracle는 이동된 평판의 정확한 영 성분에 남은 고정밀 cancellation 폭으로
|
||||
exit 1이었다. 입력 좌표 차를 exact Fraction으로 계산하여 oracle의 translation을
|
||||
제거한 뒤 같은 포함 검사가 통과했다. Production 변경이나 tolerance 완화는 없었다.
|
||||
공통 CMake 등록 commit `85b5daa`에서 MSVC x64 Debug clean build exit 0,
|
||||
inventory **517개**, 열·기존 Domain·자유도 관련 **89/89 PASS**, exit 0을 확인했다.
|
||||
Evidence는 `.dryforge/evidence/thermal-kernel-final-{configure,build,inventory,test}.log`와
|
||||
각 native exit JSON이다. 전체 CTest 실행은 아니며 최종 회귀는 별도로 남는다.
|
||||
|
||||
최초 통합 build는 exit 0이었지만 Windows PowerShell 5가 UTF-8 BOM 없는 개인 helper의
|
||||
한국어 prefix를 잘못 읽어 header 의존성 추적이 손상됐다. Helper에 BOM을 추가하고
|
||||
`pwsh`로 configure 및 clean build를 다시 수행했다. 최종 Ninja prefix와 실제 header
|
||||
dependency를 확인했으며, 중간 `thermal-kernel-integrated-build.log`는 최종 근거를
|
||||
대신하지 않는다. 이 보완은 개인 검증 환경에 한정하며 제품 소스 변경은 없다.
|
||||
|
||||
### 결정적 조립과 accepted state
|
||||
|
||||
`54154bee`의 full K/C/Q 조립과 결과 state를 독립 검토하여 잔여 차단 항목이 없음을
|
||||
확인했다. Local kernel 오차와 순서가 고정된 합산 오차를 포함한 경계를 제공하며,
|
||||
constrained Q도 보존한다. State는 생성 뒤 Domain 수명에 의존하지 않고 raw 초기
|
||||
프레임, immutable row mapping, 정확한 schedule 및 완료 프레임을 소유한다.
|
||||
|
||||
작업 checkout의 `t6-final-{build,inventory,test}.log`는 각각 native exit 0이다.
|
||||
Inventory 528개 중 관련 **11/11 PASS**이며 24종류의 candidate 손상에 대한 전체
|
||||
이력 보존과 UINT32_MAX schedule의 선할당 방지도 검사했다. 실행 당시 HEAD는
|
||||
commit 전 `85b5daa`였고, 같은 수정분을 `54154bee`에 기록했다.
|
||||
|
||||
독립 실행기는 committed assembler/state를 별도 컴파일하여 4요소·9활성절점의
|
||||
서로 다른 물성·두께 및 global material offset 모델을 검산했다. Exact Fraction
|
||||
oracle의 C/K **4,050항**과 **40개 하중 사례**를 대조했고, 유효 39개와 overflow
|
||||
거부 1개가 기대와 일치했다. Serial/actual TBB의 값·오차 경계·flux는 비트 단위로
|
||||
일치했다. State의 초기값·완료 여부·잘못된 uint64 frame 거부·복사 독립성도 확인했다.
|
||||
|
||||
Evidence는 작업 checkout의 `.dryforge/review/t6_54154bee/`에 보존했다.
|
||||
최초 reviewer runner의 정수 narrowing compile 실패를 구별해 기록했으며,
|
||||
수정 후 compile/runner/Fraction checker/source audit는 모두 실제 exit 0이다.
|
||||
입력 파서와 합친 통합 검사 결과는 아래에 기록한다.
|
||||
|
||||
### Thermal 입력 subset과 진단
|
||||
|
||||
입력 구현 `203d068`을 독립 검토하여 T5 범위의 잔여 차단 항목이 없음을 확인했다.
|
||||
DS4 inline ELSET, 상수 물성·5점 단면, raw 초기값, model/step 경계조건,
|
||||
source 순서 CFLUX와 정확한 시간격자를 연결한다. 부가 keyword는 승인된 형식만
|
||||
허용하며 source warning을 남긴다. 미사용 surface도 target을 검증하고 보존한다.
|
||||
|
||||
검토에서 strict output/restart, surface resolution, source 진단 및 mixed procedure
|
||||
문제를 보완했다. 마지막 DS4 inline ELSET 거부와 beam section 무시 문제는 실제
|
||||
반례 4개의 실패(native exit 8)를 확인한 뒤 수정했다. 같은 집합 내부의 member는
|
||||
STH-C01에 따라 한 번 전개하고, 별도 CFLUX source row는 가산 대상으로 유지한다.
|
||||
|
||||
작업 checkout의 `t5-inline-green-{build,test,inventory}.log`와 JSON에서 각각
|
||||
native exit 0을 확인했다. 관련 **82/82 PASS**는 thermal 입력 32개와 기존 structural
|
||||
입력 50개이며 inventory **549개**는 전체 실행 수가 아니다. 검사 당시 HEAD는
|
||||
수정 전 `360f8df`였고, `t5-inline-manifest.json`의 소스·테스트 hash가 최종 commit과
|
||||
일치함을 독립 확인했다. 원본 reference 두 파일의 hash는 변경되지 않았다.
|
||||
공통 CMake 등록 commit `983e2fe`에서 configure/build/inventory/test가 각각
|
||||
native exit 0이었다. 실제 inventory는 **560개**, 열·기존 입력·Domain·자유도 관련
|
||||
**152/152 PASS**다. 새 compiler warning이 없고 Ninja의 실제 header dependency도
|
||||
정상임을 확인했다. Evidence는
|
||||
`.dryforge/evidence/thermal-input-state-integrated-{configure,build,inventory,test}.log`
|
||||
및 native exit JSON이다. 전체 회귀 검사는 아니며 시간 적분·HDF5·CLI 이후에 수행한다.
|
||||
|
||||
### 시간 적분 구현 전 residual 해석 확인
|
||||
|
||||
정식화의 reduced 분모 `D_f=||A_ff||∞||T_f||∞+||b_f||∞`를 reduced 및
|
||||
full-free residual certificate 모두에 유지한다. Reduced 검사는 승인된 식 그대로 수행한다.
|
||||
Full residual은 직접 평가 interval과 reduced residual에 독립적인 signed construction
|
||||
interval을 더한 interval의 교집합으로 인증할 수 있다. 두 interval은 같은 stored-data
|
||||
정확 잔차를 포함해야 하며 빈 교집합은 실패다. 이는 허용치를 늘리지 않고 포함 구간을
|
||||
좁히는 방법이다. 방정식 구성 오차를 residual 허용치나 에너지 bound에 더하지 않는다.
|
||||
|
||||
독립 Fraction 반례에서 2-DOF fixture의 큰 constrained 온도에 의해 계산된 우변이
|
||||
0으로 소실되지만 정확 우변은 4인 경우를 확인했다. Full BE scale로 정규화하면
|
||||
이 오류가 통과할 수 있으므로 이를 blocking 분모로 대체하지 않는다.
|
||||
`.dryforge/review/t7_residual_normalization/`의 script·실제 출력·실행 JSON은
|
||||
native exit 0이며, 이는 승인 계약 해석의 evidence다. 최초 검토에서 direct-full의
|
||||
느슨한 상계를 그대로 별도 gate로 요구한 해석은 필수 첫 jump에서 `29.4u > 20u`로
|
||||
충돌하여 정정했다. `refinement-interpretation.txt`와 실제 Fraction 검산은 교집합
|
||||
인증에서 같은 사례가 약 `4u`로 통과하고, 앞의 우변 소실 반례는 여전히 실패함을
|
||||
보인다. `D_f=0`은 물리 잔차의 exact zero 증명이 필요하며 단순히 interval이 0을
|
||||
포함한다고 통과시키지 않는다. Procedure 구현의 실제 interval 검증은 별도로 남는다.
|
||||
|
||||
### Backward Euler procedure와 candidate 검증
|
||||
|
||||
`ef8ec473`의 시간 적분 구현은 독립 행동 계약 검토와 별도 exact 산술 검산에서
|
||||
잔여 차단 항목이 없었다. Raw 초기값, 첫 증분의 old constrained 용량 항,
|
||||
실제 delta가 같을 때의 factorization 재사용, full 반력·flux 복구와 실패 전 commit
|
||||
방지를 구현했다. 공개 API는 `Result<ThermalExecutionResult>`이며 내부 검산용
|
||||
partition이나 recovery 주입을 공개 경계조건 기능으로 노출하지 않는다.
|
||||
|
||||
작업 checkout의 `t7-final-{build,inventory,test}.log` 및 native exit JSON은 모두 0이다.
|
||||
Inventory **570개**, 관련 **91/91 PASS**이며 새 10개 tests는 두 증분 exact fixture,
|
||||
all-constrained, 상쇄와 잘못된 solve 거부, 실제 시간격자·factorization 횟수,
|
||||
실제 MKL affine mode/flux, 이력 보존, signed power·분리 영역, subnormal 경계,
|
||||
잘못된 입력과 Serial/TBB 이력 일치를 검사한다. `t7-tested-source-hashes.json`은
|
||||
실행한 6개 소스·테스트가 최종 commit과 동일함을 식별한다.
|
||||
|
||||
메인의 독립 실행기는 committed algebra와 bounds를 별도 MSVC target으로 호출하고
|
||||
Python Fraction oracle와 비교했다. **31,668개 산술 enclosure**, 인증된 **502개 증분**의
|
||||
**737개 free residual**, **502개 열수지**, **108개 단열 소산**에서 경계 위반이 없었다.
|
||||
추가 무작위 algebra 사례 1개는 full-free 인증 불가로 거부됐으며 통과 수에 포함하지
|
||||
않았다. 허용치나 production을 결과에 맞춰 변경하지 않았다. Evidence와 적용 한계는
|
||||
작업 checkout의 `.dryforge/review/t7_ef8ec473/review.md`, `comparison.json`, 실제
|
||||
runner/checker 출력·native exit 기록에 보존했다. 최종 독립 build/runner/checker는 exit 0이다.
|
||||
HDF5 구현과 합친 통합 검사는 writer의 독립 검토 후 수행한다.
|
||||
|
||||
### Thermal HDF5 저장과 publication
|
||||
|
||||
`7f11d533`의 writer와 self-check를 STH-C05/C06에 대조한 독립 검토에서 차단 항목이
|
||||
없었다. 모든 필수 metadata·model·mapping·frame·diagnostic의 field/type/extent/value를
|
||||
검사하며, compound의 순서·padding에 의존하지 않고 fixed/variable UTF-8을 허용한다.
|
||||
Global material ID, 정규화한 section provenance, raw initial, 실제 delta와 회전된 R 및
|
||||
global flux의 trace/component 순서를 직접 읽어 검증했다.
|
||||
|
||||
Candidate close 이후 파일을 다시 열어 검사하고 reader close 성공 뒤에만 최종 파일을
|
||||
교체한다. 쓰기·candidate close·self-check·reader close·finalize의 다섯 실패 경계에서
|
||||
기존 결과 byte 보존과 candidate 정리를 확인했다. Domain과 이력의 활성 identity,
|
||||
시간격자, raw 초기값, constraint mask와 완료된 prescribed 온도도 대조한다.
|
||||
|
||||
작업 checkout의 `t8-final-{build,inventory,test}.log` 및 native exit JSON은 모두 0이다.
|
||||
Inventory **573개**, 관련 **31/31 PASS**이며 이 중 thermal writer 검사는 **13개**다.
|
||||
실행 당시 HEAD는 commit 전 `983e2fe`였고 `t8-tested-source-hashes.json`의 8개 파일 hash가
|
||||
최종 commit과 정확히 일치함을 독립 확인했다. 이 결과는 writer 범위이며 CLI·물리·외부
|
||||
reference 검증을 대신하지 않는다.
|
||||
|
||||
시간 적분과 writer를 실제 CMake에 등록한 `1b82707`에서 configure/build/inventory/test는
|
||||
모두 native exit 0이다. Inventory **583개** 중 `Thermal|TransientHeat|Hdf5`에 해당하는
|
||||
**134/134 PASS**, 새 compiler warning 없음이다. Evidence는 메인 checkout의
|
||||
`.dryforge/evidence/thermal-procedure-output-integrated-{configure,build,inventory,test}.log`
|
||||
및 exit JSON에 보존했다. 이는 관련 통합 검사이며 전체 회귀는 아니다.
|
||||
|
||||
### Application과 실제 CLI
|
||||
|
||||
`7cccfcd`의 독립 검토에서 application 연결 범위의 차단 항목이 없었다. Thermal step을
|
||||
구조 step 개수 검사보다 먼저 선택하며, typed outcome과 thermal writer를 연결했다.
|
||||
기존 호출의 optional adapter, output lease·log close 순서와 오류 분류를 보존한다.
|
||||
실제 executable을 사용하는 통합 테스트의 CMake 의존성도 명시했다.
|
||||
|
||||
작업 checkout의 `t9-verified-{build,test}.log`, `t9-complete-inventory.log`와 exit JSON은
|
||||
native exit 0이다. Inventory **592개**, application 관련 **28/28 PASS**이며 새 thermal
|
||||
검사 9개와 기존 static/nonlinear/eigen, 실제 HHT 경로를 포함한다. 최초 정상 thermal
|
||||
입력이 `invalid-analysis-step-count`로 거부된 실패(native test exit 8)를 기록한 후 수정했다.
|
||||
실행 시점 HEAD는 `14160dd`이고 `t9-tested-source-sha256.json`의 4개 파일은 최종 commit과
|
||||
일치한다. Lease 경합, solver overflow와 실제 Windows final-file 교체 거부에서도 기존
|
||||
결과가 보존되고 candidate가 정리됐다.
|
||||
|
||||
메인의 독립 probe는 실제 `fesa.exe`와 별도 `h5dump`를 subprocess로 실행했다.
|
||||
**29개 명령**에서 기대 exit가 일치했고, raw 초기 온도·양면 지정 온도·모든 frame의
|
||||
시간/실제 delta·source step·반력/flux shape·finite 값·초기 recovery 부재를 확인했다.
|
||||
미지원 source DOF12와 usage 오류 이후에도 기존 최종 파일 SHA256이 유지됐다.
|
||||
`.dryforge/review/t9_cli/t9-7cccfcd/`에 stdout/stderr, `execution.json`, `result.json`과
|
||||
script/binary hash를 포함한 `review-execution.json`을 보존했다. Probe 자체도 native exit 0이다.
|
||||
이는 실행 경로와 저장 계약 검증이며 실제 열해의 정확도 판단은 다음 물리 검증에 속한다.
|
||||
|
||||
### 원본 reference 비교의 실패와 진단 전환
|
||||
|
||||
NT11 외부 비교를 실제 실행했으나 **실패**했다. 원본 Step-1/time37/DOF11의 729행 중
|
||||
87행이 기준을 벗어났고 RMS/S=0.04967408461567323으로 승인 0.01을 초과한다.
|
||||
별도 C++ 공통 정책 비교도 같은 실패를 재현했다. 승인 식을 FESA 코드 없이 조립·계산한
|
||||
독립 oracle는 FESA와 최대 7.673861546209082e-12 차이로 같은 reference 불일치를 보였다.
|
||||
수치·원본 hash·재현 명령·의사결정 범위는 [충돌 보고서](reference-comparison-conflict.md)에
|
||||
기록했다. 사용자 선택 A에 따라 승인 정식화와 공통 tolerance를 유지하고 원본 비교를
|
||||
진단으로 분류했다([STH-ADR-015](ADR.md#sth-adr-015-원본-reference-진단-전환과-새-모델-비교)).
|
||||
실패 행과 family metric은 변경하지 않는다. 새 reference 모델·CSV는 아직 제공되지 않아
|
||||
그 필수 비교를 실행하거나 기능 완료로 표시하지 않는다.
|
||||
|
||||
결정 전 T10 comparator checkpoint `95ba2c5`는 별도 작업 branch에 보존하고 필수 검사가 실패한
|
||||
상태로 구현 branch에 병합하지 않았다. Configure/build/inventory는 native 0,
|
||||
inventory 599개이며, 최종 schema/identity 음성검사 **6/6 PASS**(native 0)다.
|
||||
원본 application/reference 실행의 CTest는 native 8이고, 최종 comparator 소스로 같은
|
||||
생성 HDF5를 다시 비교한 standalone 실행은 native 1로 같은 실패를 확인했다.
|
||||
`.dryforge/evidence/t10-checkpoint-{source,artifact}-sha256.json`과 실제 실행/row 보고서를
|
||||
보존했고, 4개 tested-source hash와 clean checkpoint의 일치를 메인이 확인했다.
|
||||
이 checkpoint에는 물리·수렴성 검사 구현이나 production 변경이 없다.
|
||||
|
||||
### T10 해석해·수지·수렴성과 원본 진단 비교
|
||||
|
||||
T10 고정 소스 `9e8afb9`의 8개 파일은
|
||||
`T2/.dryforge/evidence/t10-final-eigen-source-sha256.json`의 SHA256과 모두 일치한다.
|
||||
실행 JSON의 revision은 commit 전 `95ba2c5`지만 실행한 작업트리의 8개 파일 hash가
|
||||
최종 `9e8afb9`와 일치한다. 메인 checkout은 Git의 CRLF checkout 변환으로 raw byte hash가
|
||||
일부 다르며, 8개 파일의 LF 정규화 내용이 모두 일치함을 별도로 확인했다.
|
||||
작업 checkout의 MSVC Debug build·inventory는 native exit 0, inventory **617개**다.
|
||||
`t10-final-focused-test.log`와 즉시 보존한 `t10-final-focused-LastTest.log`에서
|
||||
**26/26 PASS**, native exit 0, 실제 2901.03초를 확인했다. 146개 수치 기록은
|
||||
`t10-final-metrics.json`에 있다. Test 코드의 slab 에너지/반력 인덱스 오류는 최초
|
||||
실패 로그를 보존한 뒤 수정했고, 위 최종 검사는 수정된 소스 전체를 다시 실행한 결과다.
|
||||
|
||||
단열 균일장, signed·중첩·구속점 열입력의 component별 수지, full-end 검산 fixture의
|
||||
재료/두께 단차와 90° fold 저항, 회전·법선 반전·중립면 양쪽 flux trace를 확인했다.
|
||||
Full-end fixture는 공개 입력의 내부 station BC 지원을 뜻하지 않는다. 독립 rational
|
||||
Q1×P2 조립에서 8×8 고유모드 `K v−λ_h C v`의 405행과 C-노름을 검산했다.
|
||||
실제 시간 수렴차수는 **0.981712, 0.990734, 0.995336, 0.997660**으로 승인 구간에 있다.
|
||||
전체 이력을 저장한 8/16/32/64의 2D 공간 수렴은 온도 차수
|
||||
**1.996702, 2.000769, 2.006577**, gradient 차수
|
||||
**0.997220, 0.999305, 0.999826**이다. 64 mesh의 시간/공간 오차 비는
|
||||
**0.00686327**이고 온도·flux payload는 **81,074,472 byte**였다.
|
||||
|
||||
Slab는 `t=.001,.01,.05,.1,.5,1`에서 N=4096/8192, 각 1×1/2×2 mesh의
|
||||
**24개 실제 해석·147,456증분**을 실행했다. 모든 완료 프레임의 온도·flux와
|
||||
에너지·반력을 독립 two-P2/Fourier interval 및 실제 residual 기반 오차 경계로
|
||||
판정했다. 최대 `(solver+oracle bound)/(D_space/1000)`은 **0.163432**다.
|
||||
초기 시점의 두께 오차 plateau는 관측됐으나 후기 `.5/1`의 T/E/R은 도달하지
|
||||
않은 것으로 분리해 보고한다. 이는 고정 5점의 두께 해상도 한계다.
|
||||
Warped patch의 production 3점 대 독립 3점 K/C·BE 온도/flux 검산과 3/5/7점
|
||||
진단은 기존 고정 [kernel 검토](#요소-kernel과-형상-검증)의 실제 evidence를 재사용했다.
|
||||
7점을 exact해로 취급하지 않으며 이 검토만으로 전역 warped procedure 전체를
|
||||
검증했다고 주장하지 않는다.
|
||||
|
||||
독립 수치 검토자는 Gauss header 112개 값과 slab header 654개 값을 generator로
|
||||
재생성하여 일치함을 확인했다. 수정된 에너지/반력 index, 고유모드 405행,
|
||||
C-노름 및 승인 오차 예산에서도 차단 finding이 없었다. 별도 비교기 검토는 원본
|
||||
진단 분류에도 row identity/schema·공통 tolerance 실패가 그대로 드러남을 확인했다.
|
||||
원본 CLI/reference 검사는 **테스트로는 PASS**지만 실제 비교는 **87/729행 FAIL**,
|
||||
RMS/S=**0.049674084615673214**, max abs=**245.26294650091936**,
|
||||
`blocking=false`다. 원본 INP/CSV SHA256은 실행 전후 승인 값과 같다.
|
||||
새 필수 reference는 별도 경로의 모델·CSV를 아직 받지 못하여 미실행이다.
|
||||
|
||||
메인에서 CMake 등록을 반영한 작업트리의 configure/build/inventory는 native 0이다.
|
||||
실행 JSON의 revision은 commit 전 `69fa4ca`이며 등록 변경은 `9f7fb2e`로 확정했다.
|
||||
inventory **617개**, 새 compiler warning 없음이다. 짧은 물리·비교기 통합 검사
|
||||
**10/10 PASS**도 native 0이다. 관련 로그는 메인의
|
||||
`.dryforge/evidence/t10-integrated-*`와 작업 checkout의 위 `t10-final-*`에 보존한다.
|
||||
전체 회귀의 최종 결과는 아래에 별도로 기록했다. 독립 physics 평가는
|
||||
[물리 검토 보고서](physics-evaluation.md)에 기록했다.
|
||||
|
||||
### 독립 최종 구현 검토
|
||||
|
||||
독립 검토자가 `a3502c9..926e97e`의 열해석 구현과 Feature 계약을 읽기 전용으로
|
||||
대조했다. 수정이 필요한 finding은 발견하지 못했다. Q4×P2 K/C·24개 Fourier flux trace,
|
||||
raw 초기값을 사용하는 BE RHS·실제 delta·full residual 반력, 결정적 조립과 accepted
|
||||
history의 소유권, 입력의 fail-closed 처리, candidate close/readback/atomic finalize,
|
||||
reference identity와 공통 tolerance를 확인했다. 검토자는 파일을 변경하거나 검사를
|
||||
실행하지 않았으며, 이 검토를 build/CTest의 실행 evidence로 취급하지 않는다.
|
||||
새 필수 reference의 미제공과 physics 보고서의 두께 경계층·곡면·접합부 검증 한계는
|
||||
그대로 남는다.
|
||||
|
||||
### 통합 전체 회귀와 남은 완료 조건
|
||||
|
||||
Production/test/CMake 소스가 `9f7fb2e`인 통합 구현에서
|
||||
`ctest --preset windows-msvc-ninja-debug --output-on-failure`를 필터 없이 실행했다.
|
||||
후속 commit은 문서만 변경했으며 최종 검토 revision `926e97e`와 해당 소스의 diff가 없다.
|
||||
전체 **617개: 614 PASS, 2 FAIL, 1 SKIP**, native CTest exit **8**이다.
|
||||
Baseline의 478개 검사 이름이 모두 포함되며 추가된 **139개는 모두 PASS**다.
|
||||
전체 CTest green이라고 보고하지 않는다.
|
||||
|
||||
| 기존 비통과 항목 | 최종 판정 | 실행 시간 | Baseline과 수치 기록 대조 |
|
||||
| --- | --- | --- | --- |
|
||||
| `HhtShellPhysics.C08aRigidManufacturedOrbitFullCoordinateTimeConvergence` | FAIL | 928.48초 | status와 GTest metric body 정확히 일치 |
|
||||
| `HhtShellPhysics.C08bFreeFiniteRotationPlateSelfConvergenceAndPhysicalInvariants` | FAIL | 2478.99초 | status와 GTest metric body 정확히 일치 |
|
||||
| `HhtTemporalVerification.C04aFinestReductionComparisonIsNumericallyResolved` | SKIP | 0.07초 | status와 판정 불가 사유 정확히 일치 |
|
||||
|
||||
세 항목은 기존의 무관한 HHT 미해결로 유지한다. 시간 정보만 제외한 assertion·metric
|
||||
본문을 `compare_baseline_metrics.py`로 대조한 native exit은 0이며, 실패 기준을
|
||||
완화하거나 검사를 제외하지 않았다. 독립 최종 검토에서도 새로운 코드 finding이 없다.
|
||||
검토자가 종료 후 전체 617개 test block·집계·native exit 복구 기록·baseline 대조를
|
||||
읽기 전용으로 확인했고 기존 검토 결론을 유지했다.
|
||||
|
||||
실행 중 세션 재시작으로 stdout 수집 wrapper가 종료되어
|
||||
`t11-full-test.log`는 547번 시작까지만 기록됐다. 살아 있던 CTest PID 67836의 Windows
|
||||
process handle을 유지하고 `GetExitCodeProcess`로 최종 native exit 8을 직접 캡처했다.
|
||||
모든 617개 verdict와 `End testing`이 있는 CTest 원본 `LastTest.log`를 종료 직후 복사해
|
||||
보존했다. Wrapper의 불완전한 stdout를 전체 결과 근거로 사용하지 않는다.
|
||||
|
||||
최종 evidence는 메인 `.dryforge/evidence/`의 다음 파일이다.
|
||||
|
||||
- `t11-full-test-recovered-exit.json`: native exit·argv·대상 source revision·복구 방법.
|
||||
- `t11-full-LastTest.log`: 전체 검사별 실제 결과와 수치 출력.
|
||||
- `t11-full-outcomes.json`: 617개 최종 verdict, baseline 포함 여부와 추가 139개 판정.
|
||||
- `t11-hht-baseline-comparison.json`: 기존 2 FAIL·1 SKIP의 정확한 metric body 대조.
|
||||
|
||||
최종 원본 NT11 비교는 **87/729행 FAIL**, RMS/S=**0.049674084615673214**,
|
||||
max abs=**245.26294650091845**, `numerical_passed=0`, `blocking=0`이다.
|
||||
진단 분류 검사는 PASS지만 외부 수치 일치가 PASS라는 뜻이 아니다. 원본 INP/CSV의
|
||||
SHA256은 전체 실행 후에도 STH-C08 값과 일치한다.
|
||||
|
||||
사용자가 새 reference 모델·NT11 CSV는 **아직 준비 중**이라고 답했다. 별도 경로의
|
||||
파일·identity가 제공되면 승인 공통 tolerance로 새 필수 family를 실제 실행해야 한다.
|
||||
그 전까지 기능의 외부 검증 완료·release 준비를 주장하지 않는다.
|
||||
|
||||
### 사용자 요청에 따른 dev 병합과 worktree 정리
|
||||
|
||||
2026-10-04 사용자가 작업 내용을 dev에 병합하고 나머지 worktree를 정리하도록
|
||||
명시적으로 요청했다. 이는 구현 통합·작업 공간 정리 승인이고 새 필수 reference의
|
||||
검증 통과 승인이 아니다. 해당 미실행 상태와 기존 HHT 미해결은 유지한다.
|
||||
|
||||
작업 checkout을 제거하기 전에 dev checkout 기준
|
||||
`.dryforge/retained/shell-transient-heat-transfer-20261004/`에 검증 자료를 보존한다.
|
||||
원래 경로와 보존 경로의 대응은 다음과 같다.
|
||||
|
||||
| 원래 작업 checkout의 상대 경로 | 보존 디렉터리의 상대 경로 |
|
||||
| --- | --- |
|
||||
| 메인 `.dryforge/`의 실행 계획·evidence·review·개인 실행 script | `root-dryforge/` |
|
||||
| T1 `.dryforge/`의 kernel·procedure 검산과 실행 evidence | `T1-dryforge/` |
|
||||
| T2 `.dryforge/`의 T10 oracle·검사·검토 evidence | `T2-dryforge/` |
|
||||
| 메인 reference 옆 생성 HDF5 | `generated-results/` |
|
||||
| 병합 전 dev의 미추적 원본 INP/CSV | `dev-reference-before-merge/` |
|
||||
|
||||
`manifest.json`에 보존한 각 파일의 source·destination·길이·SHA256을 기록하고
|
||||
복사본을 source hash와 대조한다. 빌드 cache는 검증 evidence로 취급하지 않는다.
|
||||
기존 reference 두 파일의 byte는 유지하고, 기능 기록과 구현 이력은 dev에서 보존한다.
|
||||
새 필수 reference를 위한 활성 계획도 위 보존 디렉터리에 남긴다.
|
||||
@@ -1,589 +0,0 @@
|
||||
# Shell 과도 열전달 독립 수치 검토
|
||||
|
||||
- 검토일: 2026-09-29. **정식화 일관성 및 구현 전 수치 검증 설계 PASS /
|
||||
solver 구현·정확도·reference·physics 검증 미실행**.
|
||||
- 독립 검토 대상: formulation commit e052b6e, source 접속 범위 보완 efa5403,
|
||||
입력 rounding-cell 보완 dd409b5의 실제 diff 및 §7.1–7.2.
|
||||
[PRD STH-C07](PRD.md#sth-c07--독립-검증과-수치-계약의-선행-조건)의 위임 범위에서
|
||||
아래 식·상수·fixture·판정 기준을 production kernel 구현 전에 고정한다.
|
||||
- 상태: **DONE_WITH_CONCERNS**. 고정 5점의 초기 침투층 및 warped 3×3 적분 오차를
|
||||
정량 기록했다. 지원 방법·geometry·외부 tolerance 변경을 제안하거나 승인하지 않는다.
|
||||
- 기준: [정식화](formulation.md), [승인 ADR](ADR.md), [공통 수치 기준](../TOLERANCE.md),
|
||||
[개발 규칙](../standards.md), [수치 주의점](../engineering-notes.md).
|
||||
재현 계산은 [scratch appendix](verification-oracles.md#독립-oracle와-재현)에 있다.
|
||||
Reviewer는 정식화 작성자가 아니며 production·test·reference를 수정하지 않았다.
|
||||
|
||||
## 1. 판정과 이전 검토의 정리
|
||||
|
||||
2026-09-28 Proposed 검토는 당시 evidence다. NR-01의 product-domain 및 normalized
|
||||
station 접속, NR-02의 raw 초기값과 BC 상속/override는 현재 승인 계약으로 해결되었다.
|
||||
NR-03의 edge 입력 제안은 **011 전체 연기**로 대체된다. 과거 edge weight는 이번
|
||||
구현·검증 요구가 아니다. 종료 시간의 정수배 제한 제안도 폐기되었다.
|
||||
|
||||
| 항목 | 독립 판단 / 현재 경계 |
|
||||
| --- | --- |
|
||||
| 약형·분리 행렬·부호 | Q4×두 C0 P2, 실제 midsurface metric, exact Z, consistent C와 BE는 일관된다. 단위·node-major 순서·법선 방향을 확인했다. |
|
||||
| Whole patch | affine normal image의 separating vector certificate 및 bilinear midpoint identity의 injectivity 유도가 성립한다. 적분점만 검사하는 것은 불충분하다. |
|
||||
| Source 접속 | 전역 node-edge scan은 disconnected/contact 범위를 침범할 수 있었다. efa5403의 source endpoint를 공유하는 coarse/partial edge 후보 제한을 독립 확인했다. |
|
||||
| 초기 jump | raw t=0 보존 및 첫 RHS의 C_fc T_c_old 항이 필요하다. Slab의 δ→0 자유 초기 극한은 분석용 oracle이며 raw 초기 dataset을 바꾸는 projection 절차가 아니다. |
|
||||
| 시간 | 표현오차 수준 endpoint-close와 실제 shortened δ를 구별하는 predicate를 검산했다. 저장 시각의 subtraction과 연산 δ를 혼동하지 않는다. |
|
||||
| Recovery | 4 면내점×6 두께 trace의 global q와 R=[e1,n×e1,n], 0−/0+ 분리, full residual 반력 부호가 일관된다. t=0 flux/reaction은 없다. |
|
||||
| 남는 위험 | consistent C의 초기 undershoot, 고정 두께 해상도, metric conditioning, 3×3 유한 적분 오차. Clamp/lumping/차수 변경/지원 축소로 숨길 수 없다. |
|
||||
|
||||
PASS는 **설계의 수학적 일관성과 독립 사전 oracle**에 한정한다.
|
||||
실제 MSVC solver·HDF5·외부 reference 결과가 통과했다는 뜻은 아니다.
|
||||
|
||||
## 2. Geometry와 mesh 판정
|
||||
|
||||
### 2.1 Whole-patch certificate와 uncertainty
|
||||
|
||||
정식화 §2.1의 r=a+bξ+cη+dξη, w=w0+uξ+vη를 사용한다.
|
||||
Convex set W={w(ξ,η)}의 원점에 가장 가까운 w*는 w*·w≥||w*||²를 만족한다.
|
||||
따라서 네 corner에 대한 **같은** 고정 double 벡터 s의 양의 interval dot product가
|
||||
전체 patch를 증명한다. 후보 최소점 계산이 부정확해도 최종 certificate가 양수이면
|
||||
안전하다. 후보 탐색 실패를 수학적 퇴화의 증명으로 보고하면 안 된다.
|
||||
r(p)−r(q)=Dr((p+q)/2)(p−q)이므로 전체 patch에서 rank(Dr)=2이면 단사다.
|
||||
이 증명은 bilinear map 전용이며 일반 고차 curved element로 확대하지 않는다.
|
||||
|
||||
**고정 규칙:** binary64, u=2^-53, epsilon=2^-52, round-to-nearest,
|
||||
gradual underflow; 입력 double은 singleton interval이다. 각 사칙연산 endpoint를
|
||||
양쪽 nextafter로 한 번씩 넓힌다. 0을 포함한 divisor는 사용하지 않는다.
|
||||
sqrt는 비음수 endpoint를 계산한 뒤 같은 방식으로 넓힌다. 재척도는 exact
|
||||
power-of-two이며 손실된 subnormal도 enclosure에 포함한다. Fast-math/FTZ와
|
||||
증명되지 않은 재결합은 이 bound의 전제가 아니다.
|
||||
|
||||
모든 lower(s·w_corner)>0이면
|
||||
J_lower=min lower(s·w_corner)/upper(sqrt(s·s))>0를 보존한다.
|
||||
증명되지 않으면 다른 유한 candidate를 시도하고 모두 실패하면 uncertain geometry로
|
||||
fail closed한다. 정확히 중복된 좌표·source node, 비유한 값, 증명된 w=0은 invalid다.
|
||||
고정 Jacobian epsilon·warp/aspect cutoff는 **0개**다. Certificate 뒤에도 각 사용점의
|
||||
metric inverse/gradient가 유한하고 interval에서 0 divisor가 배제되는지 확인한다.
|
||||
κ(g)는 진단과 오차 전파에 쓰며 지원 cutoff가 아니다.
|
||||
|
||||
### 2.2 Source topology와 T-edge uncertainty
|
||||
|
||||
Edge incidence는 1 또는 반대 순서의 2; 3 이상·같은 방향·중복 patch는 거부한다.
|
||||
각 vertex link는 하나의 path 또는 cycle이며 끊어진 fan·branch·중복 link는 거부한다.
|
||||
|
||||
T-edge 후보는 **같은 instance에서 source endpoint를 공유한**
|
||||
(p,q)와 (p,v) 또는 (v,q)이고 p,q,v는 서로 다른 node다. Coarse 방향을 양쪽으로
|
||||
시도한다. a=q−p, b=v−p의 interval에서 |a_j| lower가 가장 큰 성분 j를 택하고
|
||||
λ=b_j/a_j, 잔여 성분 b_i−λa_i를 계산한다.
|
||||
|
||||
- 잔여 성분 interval 하나가 0을 제외하거나 λ가 [0,1] 밖이면 비접합이다.
|
||||
- 공선 및 0<λ<1이 증명되면 nonconforming T-edge다.
|
||||
- 공선/열린 구간 포함이 불확실하면 uncertain 접속으로 실패한다. 정확한 끝점 일치는
|
||||
별도 중복 좌표 진단이며 열린 구간으로 clamp하지 않는다.
|
||||
- Interval이 0을 포함한다고 exact 공선을 주장하지 않는다. Exact double-rational
|
||||
검산은 선택 사항이며 새 arbitrary-precision runtime dependency를 요구하지 않는다.
|
||||
Interval fail-closed만으로 계약을 충족한다.
|
||||
|
||||
모든 node 대 모든 edge scan, 좌표 welding, source 후보가 없는 component 접촉 검출은
|
||||
하지 않는다. 같은 component의 멀리 떨어진 부분끼리의 접촉도 대상이 아니다.
|
||||
이는 global contact 검증을 완료했다는 뜻이 아니다.
|
||||
|
||||
### 2.3 고정 geometry fixture군
|
||||
|
||||
| 군 | 좌표/변환과 필수 판정 |
|
||||
| --- | --- |
|
||||
| Affine | (0,0,0),(1,0,0),(1,1,0),(0,1,0); 평행사변형 (0,0,0),(2,0,0),(3,1,0),(1,1,0). Certificate PASS. |
|
||||
| 평면 왜곡 | (0,0,0),(2,0,0),(1.5,1,0),(0,1,0). J>0; M exact, S의 3×3 exactness 주장 금지. |
|
||||
| Saddle | r=(ξ,η,aξη), a=.1,.5,2; 자연 corner를 node로 사용. w=(-aη,-aξ,1), s=(0,0,1), J_lower=1의 exact 근거. 모두 지원. |
|
||||
| 긴 aspect | rectangle 1×2^-40; 유효 certificate 필요. 조건수와 metric 계산을 별도 기록하며 aspect만으로 거부 금지. |
|
||||
| Scale/이동/회전 | 유효군의 2^-200,1,2^200배; unit patch에 (2^20,-2^20,2^20) 이동. Signed axis permutation 및 z축 3-4-5 회전. 입력 반올림을 oracle interval에 포함. |
|
||||
| 적분점 검사의 반례 | r=(ξ,(ξ−1/4)η,0). 3×3 모든 점의 J는 비영이지만 ξ=1/4에서 J=0. Whole-patch 거부. |
|
||||
| Invalid | bow-tie 순서, 반복 source/좌표, collinear 네 node, NaN/Inf. 자동 재순서/normal flip 금지. |
|
||||
| Uncertain | affine b=(1,1,0),c=(1,1+2^-52,0): cancellation interval이 0을 포함할 수 있다. 증명된 certificate 또는 uncertain 실패만 허용; 임의 epsilon/형상 보정 금지. |
|
||||
| 접속 양성 | 반대 순서 edge 공유 Q4 두 개, 90도 fold, h=1/2 두께 단차, k=1/10 재료 접속; disconnected 두 patch. |
|
||||
| 음성/대조 | edge 3 incidence, 동일 directed edge, node 하나만 공유한 두 fan; coarse(p,q)/partial(p,v),v=(p+q)/2. 각 음성의 별도 source identity/instance 좌표 접촉 대조군은 자동접속·T-edge 거부가 없어야 함. |
|
||||
|
||||
## 3. 내부 roundoff, 행렬 및 solve 기준
|
||||
|
||||
### 3.1 공통 오차 언어
|
||||
|
||||
외부 5%/1%와 무관하게 γ_m=mu/(1−mu),u=2^-53이며 mu<1을 요구한다.
|
||||
행렬/shape는 Frobenius norm, solve는 ∞ norm, 물리 integral은 아래 L2 norm이다.
|
||||
분모가 0이면 numerator도 정확히 0일 때만 통과한다. max(1,scale)은 금지다.
|
||||
|
||||
P_ij는 계산한 signed 합의 절댓값이 아니라 **각 quadrature/분리 항의 절댓값 합**이다.
|
||||
Cancellation 때문에 P와 |X|를 바꿔 쓰지 않는다. 단위 affine fixture의 closed-form
|
||||
rational oracle에 대한 고정 roundoff bound는 다음과 같다.
|
||||
|
||||
| 검사 | 고정 bound / 연산 수 근거 |
|
||||
| --- | --- |
|
||||
| M,S,Z 및 분리 C,K | \|\|X_hat−X_exact\|\|F ≤γ_4096\|\|P_X\|\|F. 점당 shape·metric·gradient·weight·entry scalar path128 이하×9+분리/scatter64 이하를 포괄한다. |
|
||||
| 직접54점 대 분리 | \|\|X_54−X_sep\|\|F ≤γ_8192\|\|P_54\|\|F+γ_4096\|\|P_sep\|\|F. 54×128+reduction<8192. |
|
||||
| Affine gradient·H·R | component 절댓값 전파 scale P에 error norm≤γ_2048\|\|P\|\|. Partition sum은 P=Σ\|H\|, gradient sum은 P=Σ\|\|B_p\|\|; 비영 patch는 exact gradient 크기도 포함. |
|
||||
| Symmetry | \|\|X−Xᵀ\|\|F≤2E_X. E_X는 위 bound. 강제 대칭화로 검사를 통과시키지 않는다. |
|
||||
| 상수 null | \|\|K1\|\|2≤sqrt(20)E_K; \|1ᵀC1−2\|≤20E_C. Fraction 검산은 exact equality. |
|
||||
| h scaling | h=1/2,1,2, k/rho/c=1; C와 면내 K는 h, normal K는 1/h. 두 계산의 E를 해당 배율로 더한다. |
|
||||
|
||||
Operation budget은 단순 loop의 최장 path 상한이다. 실제 경로가 이보다 길면 결과에 맞춰
|
||||
상수를 늘리지 않고 경로/interval을 다시 검토한다. 일반 warped/translated geometry에는
|
||||
affine bound를 그대로 쓰지 않는다. §2 interval을 같은 quadrature에 전파하여 X^I를
|
||||
얻고 E_X=||max(|lower(X^I)−X_mid|,|upper(X^I)−X_mid|)||F를 사용한다.
|
||||
각 point의 κ2(g)와 κ2(g)γ_64를 기록한다. Inverse perturbation 상대 증폭은
|
||||
κ2(g)γ_64/(1−κ2(g)γ_64)이고 분모가 양수가 아니면 이 상계는 불확실하다.
|
||||
직접 interval inverse가 유한 enclosure를 증명하면 사용하고 아니면 uncertain이다.
|
||||
κ를 geometry 지원 조건으로 바꾸지 않는다. Roundoff와 quadrature 절단 차이는 별개다.
|
||||
|
||||
### 3.2 Exact fixture와 rank
|
||||
|
||||
단위 square,h=2,k=rho=c=1:
|
||||
M=1/36 [[4,2,1,2],[2,4,2,1],[1,2,4,2],[2,1,2,4]],
|
||||
S=1/6 [[4,-1,-2,-1],[-1,4,-1,-2],[-2,-1,4,-1],[-1,-2,-1,4]].
|
||||
|
||||
길이1 ζ 구간의 Z0=1/30 [[4,2,-1],[2,16,2],[-1,2,4]],
|
||||
Z1=1/3 [[7,-8,1],[-8,16,-8],[1,-8,7]]을 station(1,2,3),(3,4,5)에
|
||||
조립한다. C=M⊗Z0,K=S⊗Z0+M⊗Z1, node-major 순서다.
|
||||
정확 유리수 LDL에서 C의20 pivot>0,K의 leading19 pivot>0,K1=0,1ᵀC1=2를
|
||||
확인했다. C SPD,K PSD/rank19가 독립 증명된다.
|
||||
|
||||
Floating 결과는 matrix bound 외에 C의 λ_min>E_C, K를 1⊥에 제한한
|
||||
λ_min>E_K와 null eigenvalue 크기≤E_K를 확인한다. Eigen 연산 자체의 backward
|
||||
error enclosure도 더한다. Separation이 불가능하면 rank는 inconclusive이며
|
||||
clamp로 PASS를 만들지 않는다. 전역 K는 component마다 null mode 하나다.
|
||||
|
||||
Gradient fixture는 단위 affine 평판의 접선 b에 대해 T=A+b·r+cz,
|
||||
A=2,b=(3,-2,0),c=4로 q=−k(b+cn)이다. Warped patch의 임의 global b에
|
||||
같은 식을 강제하지 않으며 그 경우 실제 reciprocal tangent의 projection을 사용한다.
|
||||
Constant T=2, 면내/두께선형도 각각 검사한다. 회전 후 q는 같은 회전,
|
||||
normal 반전 후 station a↔6−a와 조건까지 재매핑한다. RᵀR=I,detR=+1.
|
||||
Trace state(0,0,0,1,2)는 q3(0−)=0,q3(0+)=−4k/h이며 평균하지 않는다.
|
||||
|
||||
### 3.3 Free solve, certified residual과 forward 전파
|
||||
|
||||
n=free DOF 수,A=A_ff,b=같은 δ와 full old state로 만든 RHS다.
|
||||
Full residual의 free 성분 및 독립 A T_f−b를 확인한다.
|
||||
|
||||
β_limit=nγ_(n+1)+γ_(2n+4)+γ_(4n+8).
|
||||
|
||||
첫 항은 Cholesky의 |L||L|ᵀ bound와 || |L||L|ᵀ ||∞≤n||A||∞에서,
|
||||
나머지는 triangular solves 및 residual 평가의 dot-product bound에서 나온 보수적인
|
||||
**허용 상한**이다. Backend가 전제를 충족하지 못하면 더 엄밀한 backward-error
|
||||
evidence가 필요하며 이 상한을 늘리지 않는다. n=0은 free 검사 대신 full reaction·수지를
|
||||
검사한다. 큰 n의 상한을 실제 오차로 가정하여 forward budget에 넣지 않는다.
|
||||
|
||||
실제 sparse 행 i의 nonzero 수 ν_i로 독립 r_tilde=fl(A T_f−b)를 평가하고
|
||||
|
||||
E_r,i=γ_(2ν_i+2)(Σ_j|A_ij||T_f,j|+|b_i|),
|
||||
R_cert=upper(|| |r_tilde|+E_r ||∞),
|
||||
D_lower=lower(||A||∞||T_f||∞+||b||∞),
|
||||
β_cert=upper(R_cert/D_lower).
|
||||
|
||||
모든 scale sum/norm은 outward interval로 계산하며 underflow 항도 §2 enclosure로
|
||||
보존한다. D_lower=0은 exact-zero numerator/denominator를 별도 확인한다.
|
||||
**β_cert≤β_limit**가 residual 판정이다. Full C dT/δ+KT−Q 평가에도 자신의 실제
|
||||
row count·signed term absolute scale로 같은 의미를 검산한다. 구체적으로
|
||||
E_r,full,i=γ_(2ν_C,i+2ν_K,i+6)(Σ|C_ij||dT_j|/δ+Σ|K_ij||Tnew_j|+|Q_i|)
|
||||
+γ_1Σ|C_ij|(|Tnew_j|+|Told_j|)/δ로 둔다.
|
||||
관측 residual에 roundoff enclosure를 더하므로 우연히 작은 computed residual을 그대로
|
||||
정확한 잔차라고 가정하지 않는다.
|
||||
|
||||
n≤100의 소형 fixture는 독립 dense inverse로 Z≈A^-1를 구하고
|
||||
θ=upper(||I−ZA||∞)<1을 확인한다. 그러면
|
||||
upper(||A^-1||∞)≤upper(||Z||∞)/(1−θ)가 rigorous inverse-norm bound다.
|
||||
κ∞(A)β_cert<1일 때 relative forward bound는
|
||||
2κ∞(A)β_cert/(1−κ∞(A)β_cert).
|
||||
정확 coefficient의 E_A/E_b도 numerator에 E_A||T_f||∞+E_b로 더한다.
|
||||
이때 stored A의 inverse 상계를 J라 하면 J E_A<1을 확인하고 정확 A*의 inverse는
|
||||
J/(1−J E_A)로 넓힌다. 따라서 absolute forward bound는
|
||||
`[J/(1−J E_A)](R_cert+E_A||T_f||∞+E_b)`다(E_A/E_b는 ∞ norm bound).
|
||||
이 denominator의 조건을 증명하지 못하면 inconclusive이며 clamp/상한 확대는 금지다.
|
||||
|
||||
큰 **구조화된 convergence fixture**는 inverse나 최악 β_limit 없이 다음 C-norm
|
||||
전파를 사용한다. 정확 oracle C*,K*에 대한 증분 residual의 component enclosure를
|
||||
|
||||
R_n=|r_tilde|+E_r+E_C|dT|/δ+E_K|Tnew|+E_Q
|
||||
|
||||
로 둔다(E_C/E_K는 성분별 절댓값 오차 상계). 단열 homogeneous error의
|
||||
(C*+δK*)^-1C*는 C* norm에서 contraction이므로
|
||||
|
||||
B_T^n=B_T^(n−1)+δ||R_n||2/sqrt(λ_lower(C*))
|
||||
|
||||
가 온도 C-norm error의 사전 고정된 누적 상계다. 초기 nodal cos의 interval 오차를
|
||||
B_T^0에 포함한다. Normalized k=rho=c=h=1 fixture에서는 이 C-norm이 실제
|
||||
product-volume temperature L2다. Sampling/오차 norm 적분의 interval도 더한다.
|
||||
|
||||
n×n unit square의 tensor mass는 Mx⊗My⊗Cz다.
|
||||
Uniform Q1 1D mass의 Gershgorin lower는 1/(6n), 두 길이1/2 P2 segment의
|
||||
Cz lower는 1/60이므로 **λ_lower(C*)=1/(2160n²)**.
|
||||
K generalized upper는 면내 12n²+12n² 및 thickness
|
||||
||Kz||∞/λ_lower(Cz)=(64/3)/(1/60)=1280으로
|
||||
**λ_upper(K*,C*)=24n²+1280**.
|
||||
따라서 gradient L2 solver budget은 sqrt(24n²+1280) B_T^n이다.
|
||||
이 analytic bounds는 §6의 unit affine tensor fixture 전용이며 일반 mesh의 condition
|
||||
보증으로 확대하지 않는다. 큰 fixture에 production sparse inverse를 요구하지 않는다.
|
||||
§4 에너지 roundoff 상계의 β_limit는 보수적인 acceptance로 유지할 수 있지만,
|
||||
§6–7의 oracle 차이/관찰 order budget에는 β_cert 또는 위 R_n 전파를 사용한다.
|
||||
|
||||
## 4. 에너지, 반력과 BE 소산
|
||||
|
||||
C=[[2,1],[1,2]],K=[[1,-1],[-1,1]],δ=1/2,Q=0,rawT0=(0,0),g2=1에서
|
||||
T_f=(-1/5,1/25),Rc=(24/5,36/25)를 exact 확인했다. Raw constrained 항을 빼거나
|
||||
먼저 g로 projection하면 실패한다. Signed undershoot를 삭제하면 안 된다.
|
||||
이 fixture와 all-constrained 검사는 algebra다. Full-end strip ΣL/(khw)도 assembly
|
||||
전용이며 공개 내부 station BC 지원을 뜻하지 않는다.
|
||||
|
||||
dT=Tnew−Told,ΔE=1ᵀC dT,Rc=(C dT/δ+K Tnew−Q)_c.
|
||||
온도 영점을 뺀 두 큰 U를 차분하는 대신 ΔE를 직접 계산해도 같은 물리량이다.
|
||||
|
||||
**물리 수지 defect**
|
||||
D_E=|ΔE−δ(ΣQ+ΣRc)|,
|
||||
S_E=Σ_ij|C_ij dT_j|+δΣ_i|Q_i|+δΣ_c|Rc_i|.
|
||||
|
||||
m=전체 DOF 수,D_f=||A_ff||∞||T_f||∞+||b_f||∞라 하면
|
||||
|
||||
B_E=δnβ_limit D_f+δ||1ᵀK||1||Tnew||∞+γ_(4m+12)S_E
|
||||
+δγ_(2m+6)(|| |C||dT| ||1/δ+|| |K||Tnew| ||1+||Q||1)
|
||||
+γ_1Σ_ij|C_ij|(|Tnew_j|+|Told_j|).
|
||||
|
||||
두 번째 줄은 full residual 평가의 dot-product/division/subtraction 오차이며,
|
||||
마지막 항은 온도 subtraction 오차다. D_E≤B_E와 free β≤β_limit를 **각각**
|
||||
만족해야 한다. K 상수 mode 항은 §3 null bound도 만족해야 하므로 K 오류를 면제하지
|
||||
않는다. 보고 metric D_E/S_E에서 S_E=0이면 exact-zero 분기다. Actual free residual을
|
||||
수지에 다시 넣어 0을 만드는 대수 항등식은 물리 평형 판정을 대신하지 않는다.
|
||||
|
||||
단열·무입력·무구속의 별도 C-norm 소산 defect는
|
||||
|
||||
D_C=|0.5(TnewᵀCTnew−ToldᵀCTold+dTᵀCdT)+δTnewᵀKTnew|.
|
||||
|
||||
S_C는 앞의 세 C quadratic form의 **성분별 절댓값 합**에 각각 0.5를 곱하고,
|
||||
마지막 K quadratic form의 성분별 절댓값 합에 δ를 곱하여 모두 더한 값이다.
|
||||
B_C=δ||Tnew||1β_limit D_f+γ_(6m+20)S_C
|
||||
+0.5||dT||2||C−Cᵀ||2||Told||2
|
||||
+γ_1(|Tnew|+|Told|)ᵀ|C||dT|.
|
||||
|
||||
Residual work, 합/subtraction, symmetry defect, dT 오차 전파를 구분한 식이다.
|
||||
D_C≤B_C,||Tnew||C²≤||Told||C²+2B_C를 검사하고 S_C=0은 exact-zero다.
|
||||
이 제곱 norm은 실제 열에너지와 단위가 다르다.
|
||||
|
||||
P/−P,constrained DOF의 P,disconnected component를 별도 실행한다. 집중 입력은
|
||||
signed power 그대로 Q에 가산한다. 단열 균일 T=2 보존,no-BC transient,component별
|
||||
수지,정상상태 ΣQ+ΣRc=0을 검사한다. Raw flux 경계 적분과 FE 반력의 exact equality를
|
||||
강제하지 않는다.
|
||||
|
||||
## 5. Warped quadrature의 사전 진단
|
||||
|
||||
§2 affine/distorted/saddle a=.1,.5,2에서 k=rho=c=h=1.
|
||||
각 3/5/7 surface rule과 exact Z로 C_r,K_r를 독립 계산한다.
|
||||
대표 응답은 old=0,Q=e_(node1,station11),δ=.1,noBC의 한 BE 증분이다.
|
||||
|
||||
d_X(r,s)=||X_r−X_s||F/||X_s||F(X=C,K),
|
||||
d_T=||T_r−T_s||2/||T_s||2,
|
||||
d_q=max_trace||q_r−q_s||2/max_trace||q_s||2.
|
||||
|
||||
| fixture | d_C(3,5)/(5,7) | d_K(3,5)/(5,7) | d_T(3,5)/(5,7) | d_q(3,5)/(5,7) |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| distorted | roundoff/roundoff | 2.189065e-7/5.970737e-12 | 2.385149e-6/6.505495e-11 | 1.070060e-6/2.918586e-11 |
|
||||
| saddle .1 | 3.944257e-7/7.758135e-13 | 3.862043e-7/7.500898e-13 | 7.916236e-7/1.286406e-12 | 9.283663e-7/1.601583e-12 |
|
||||
| saddle .5 | 1.667355e-4/1.431780e-7 | 1.643476e-4/1.408553e-7 | 3.301794e-4/2.150240e-7 | 3.703751e-4/2.649276e-7 |
|
||||
| saddle 2 | 5.631484e-3/2.213607e-4 | 5.618988e-3/2.217451e-4 | 6.690109e-3/1.033767e-4 | 5.483294e-3/8.641481e-5 |
|
||||
|
||||
표의 반올림 값을 tolerance로 쓰지 않는다. 판정은 (1) production3점이 독립3점
|
||||
oracle와 §3 bound로 일치,(2) 각 fixture d(5,7)≤d(3,5)+양쪽 roundoff bound,
|
||||
(3) affine 모든 차이는 roundoff 이내다. Appendix에서 재계산한 metric과 interval을
|
||||
함께 보고한다. d가 roundoff 이하이면 ratio/order를 만들지 않는다. 독립54점/분리
|
||||
C,K의 scratch 상대 norm 차이는 최대7.73e-16이었다.
|
||||
|
||||
이는 **선정 fixture의 적분 수렴 진단**이다. 7점을 exact해로 보거나 모든 허용
|
||||
geometry에 같은 d 상한을 요구하지 않는다. 일반 모델의 진단이 비단조이면 조사·보고하며
|
||||
지원 geometry cutoff,production 차수 변경/adaptive quadrature로 자동 교체하지 않는다.
|
||||
|
||||
## 6. 시간·면내 수렴
|
||||
|
||||
### 6.1 고정 spatial eigen oracle의 시간1차
|
||||
|
||||
Affine 단열 unit square,균일8×8 mesh,h=1,k=rho=c=1,
|
||||
station 동일 v_ij=cos(πi/8)를 쓴다. Consistent Q1의 정확한 discrete eigenvector이며
|
||||
λ_h=6(1−cos(π/8))/[(1/8)²(2+cos(π/8))].
|
||||
독립 assembly로 Kv−λCv 및 C normalization을 §3 bound로 확인한다.
|
||||
τ=1/λ_h,δ=τ/N,N=16,32,64,128,256,INC≥256.
|
||||
|
||||
T_exact=e^-1v,T_BE=(1+1/N)^-Nv,
|
||||
e_N=||T_BE−T_exact||C/||v||C,p=log2(e_N/e_2N).
|
||||
모든 pair의 p 허용구간은 **[.97,1.02]**.
|
||||
독립 기대값은 .9817124,.9907338,.9953356,.9976599.
|
||||
log(1+x)의 전개에서 e_N=e^-1/(2N)+O(N^-2)이며 N≥16의 독립 값으로 구간을
|
||||
고정했다. Roundoff propagation이 e_N/1000을 넘으면 order는 inconclusive다.
|
||||
공간오차와 시간오차를 분리하는 고정 spatial oracle다.
|
||||
|
||||
### 6.2 Fourier rectangle의 면내2차/gradient1차
|
||||
|
||||
Unit square,h=1,k=rho=c=1,noBC/noQ,T0=cos(πx)를 모든 station에 동일하게 둔다.
|
||||
**τ=.001,N=32,δ=τ/32,INC=32**로 고정한다. 연속해는
|
||||
T=cos(πx)exp(−π²t),∇T=(-πsin(πx)exp(−π²t),0,0).
|
||||
Affine n×n,n=8,16,32,64를 모두 유지한다. Norm은 product-volume temperature와
|
||||
global gradient L2다. 평가 적분은 cell별12×12 Gauss×exact thickness이며
|
||||
12→16점 oracle 변화≤해당 오차의1e-8을 확인한다.
|
||||
|
||||
독립 exp(-λ_hτ) spatial oracle와 finite-N modal BE oracle를 동시에 사용한다.
|
||||
BE-exponential 온도 L2 차이는 continuum semidiscrete 오차의 **1/32 이하**여야 한다.
|
||||
작은 시간과 bounded N은 이 시간오차 분리를 유지하면서 모든 accepted frame을 저장한다.
|
||||
별도 시간1차 검사는 §6.1에 그대로 남긴다.
|
||||
|
||||
| n | Semidiscrete T L2 | BE T L2 | BE gradient L2 | Time/spatial ratio |
|
||||
| ---: | ---: | ---: | ---: | ---: |
|
||||
| 8 | 9.903629946e-3 | 9.902647628e-3 | 2.487150504e-1 | .0001089543 |
|
||||
| 16 | 2.482303232e-3 | 2.481327028e-3 | 1.245973612e-1 | .0004305809 |
|
||||
| 32 | 6.209759342e-4 | 6.200013808e-4 | 6.232870148e-2 | .0017171164 |
|
||||
| 64 | 1.552689976e-4 | 1.542952827e-4 | 3.116810477e-2 | .0068632659 |
|
||||
|
||||
모든 pair의 기존 허용구간을 유지한다: T p **[1.95,2.05]**,gradient p **[.98,1.03]**.
|
||||
독립 finite-N 기대값은 T=(1.9967024,2.0007686,2.0065775),
|
||||
gradient=(.9972203,.9993050,.9998262).
|
||||
Q1 smooth interpolation O(h²)/O(h),λ_h=π²+O(h²)와 위 독립 계산에 근거한다.
|
||||
12/16점 변화 최대1.30e-13이며 criterion1e-8보다 작다.
|
||||
§3의 실제 residual 기반 B_T 및 gradient budget이 측정 오차의1/1000 이하여야
|
||||
order 판정을 사용한다. 집중 source의 특이 해에 이 smooth order를 요구하지 않는다.
|
||||
|
||||
**실행 예산:** n=64에서도 sparse solve32회다. Mandatory flux와 initial 포함
|
||||
temperature raw doubles는
|
||||
4096×24×3×32×8 + 4225×5×33×8 = **81,074,472 bytes(약77.3MiB)**.
|
||||
모든4개 mesh의 같은 payload 합은107,772,960 bytes(약102.8MiB), solve총128회다.
|
||||
Model의 local frames는 시간마다 중복하지 않는 승인 schema이므로 largest mesh에서
|
||||
추가4096×4×9×8=1,179,648 bytes다. Identity/HDF5 overhead와 실제 peak memory를
|
||||
evidence에 별도 기록한다. 이 예산은 history/flux 생략이나 제품 출력 변경을 전제하지 않는다.
|
||||
|
||||
초기 문서의 τ=.1,N=16n²는 n64에서 flux만 약154.6GB인 과도한 fixture였으므로
|
||||
**kernel 구현 전** 독립 계산으로 위 설계로 대체했다. Production 결과에 맞춘 tolerance
|
||||
완화가 아니며 기존 공간 order·시간오차 분리·모든 frame 계약을 그대로 유지한다.
|
||||
|
||||
## 7. 고정5점 slab: 허용 이산 오차와 plateau
|
||||
|
||||
Unit area,h=1,k=rho=c=1,Ti=0,Ts=1,bottom step/top 단열이며 면내 node 조건은 같다.
|
||||
x=(0,1/4,1/2,3/4,1) T,six trace x=(0,1/4,1/2−,1/2+,3/4,1)의 q3,
|
||||
E=1ᵀCT,bottom 전체 Rc를 비교한다. Unit square1요소 및2×2 mesh다.
|
||||
t=0은 rawTi이며 flux/reaction을 생성하지 않는다.
|
||||
|
||||
무차원 시간 t*=αt/h²,T/ΔT,q/(kΔT/h),E/(ρc area hΔT),R/(k areaΔT/h).
|
||||
이 fixture의 척도는 모두1이다. T/flux는 위 위치의 max absolute error,
|
||||
E/R은 absolute error다. Station 상대오차나 near-zero floor를 만들지 않는다.
|
||||
|
||||
### 7.1 Fourier 및 독립 P2 spectral oracle
|
||||
|
||||
정식화 §10 series에서 M=80,최소 t*=.001.
|
||||
β=π²t*/4,r=exp[-8β(M+1)]이면 온도 tail≤
|
||||
4exp[-β(2M+1)²]/[π(2M+1)(1-r)],flux/reaction tail≤
|
||||
2exp[-β(2M+1)²]/(1-r),energy tail≤temperature tail.
|
||||
최소 시간에서도 모든 무차원 tail은 **1e-27 미만**이다.
|
||||
1−r는 -expm1 표현과 수학적으로 동등한 exact interval subtraction으로 평가한다.
|
||||
**Oracle 산술은 다음 방식으로 고정**하며 C++17 libm의 막연한 1ULP 보장을 가정하지 않는다.
|
||||
Appendix E가 실제 실행 가능한 표준 라이브러리 generator다.
|
||||
|
||||
1. π=16 atan(1/5)−4 atan(1/239), 각 alternating arctan을 j=0…63까지 exact
|
||||
유리수로 합한다. 첫 생략항 q^129/129로 양쪽 enclosure를 만든다.
|
||||
2. 이후 모든 interval endpoint는 격자 2^-320으로 floor/ceil하여 outward 보존한다.
|
||||
원래 π enclosure 폭은2^-295 미만이다.
|
||||
3. Slab station의 phase는 정수 kπ/8이다. 정수 quadrant reduction으로 |r|≤π/4에
|
||||
옮긴 뒤 sin/cos Taylor 각각32항을 쓴다. Remainder는 보수적으로1/65!,1/64!다.
|
||||
4. exp(-x),0≤x≤512는 y=x/1024의64차 Taylor,
|
||||
remainder≤(1/2)^65/65!를 더하고 interval squaring10회로 복구한다.
|
||||
x≥512이면 0≤exp(-x)≤2^-512(e>2)을 사용한다.
|
||||
5. M=80 series를 위 interval로 합한다. Tail을 더하기 전 각 quantity enclosure 폭은
|
||||
**2^-270 미만**이어야 한다. 여기에 앞의 analytic Fourier tail을 더한다.
|
||||
필요한 binary64 fixture는 lower를 float 변환 후 nextafter(-∞),upper를 변환 후
|
||||
nextafter(+∞)하여 export한다. 이 endpoint 차이가 B_oracle이며 별도 floor가 없다.
|
||||
|
||||
실제 generator에서 최소 시간의 tailT=1.658661e-30,tailq=4.194724e-28,
|
||||
최종 enclosure 최대 폭8.389448e-28이었다. 나머지 시각의 폭은8.93e-89 이하였다.
|
||||
이 방식은 테스트 oracle generator 전용이며 production arbitrary-precision dependency가
|
||||
아니다. Spectral oracle의 exp도 동일 enclosure를 적용하고 eigenpair/coefficients의
|
||||
backward-error interval을 함께 전파한다. Appendix A의 통상 math 계산은 표 수치의
|
||||
간단한 재현용이며 interval E가 transcendental correctness의 근거다.
|
||||
|
||||
T10은 generator의 T/q/E/R interval을 outward binary64 fixture로 고정하여 사용할 수
|
||||
있다. 또는 binary64 outward Taylor가 동일한 최종 B_oracle 및 §6–7의 오차 budget을
|
||||
증명하면 그 경로도 가능하다. 2^-270은 고정 고정밀 generator의 내부 검사이며 production
|
||||
정밀도 요구가 아니다. 무차원 interval error를 실제 단위로 옮길 때 T는 |ΔT|,
|
||||
q는 k|ΔT|/h,E는 rho c area h|ΔT|,R은 k area|ΔT|/h를 곱한다.
|
||||
온도 기준 이동은 interval 폭을 바꾸지 않는다. 선형 sampling/trace/energy/reaction row L은
|
||||
성분별 |L| times input error로 전파하며 signed 값 자체를 절댓값으로 바꾸지 않는다.
|
||||
|
||||
독립1D P2 FE는 길이1/2인 두 segment를 조립한다.
|
||||
C_seg=(1/2)/30 [[4,2,-1],[2,16,2],[-1,2,4]],
|
||||
K_seg=2/3 [[7,-8,1],[-8,16,-8],[1,-8,7]].
|
||||
Bottom elimination 뒤4×4 generalized eigenproblem의 Cholesky+Jacobi 계산은
|
||||
3D product kernel을 호출하지 않는다.
|
||||
|
||||
Raw 초기 정책에서 δ→0 자유 초기 극한은
|
||||
T_f(0+)=-C_ff^-1C_fc=(-5/34,3/17,-1/34,1/17).
|
||||
y0=T_f(0+)−1,C-orthonormal v_j의 a_j=v_jᵀC_ff y0로
|
||||
T_f(t)=1+Σa_jv_j exp(-λ_jt).
|
||||
이는 첫 finite-step RHS의 극한이며 FESA t=0 state/dataset을 변경하지 않는다.
|
||||
|
||||
λ=(2.4686647564,22.9461660098,77.0631371712,198.6985026508).
|
||||
Scratch eigen residual3.994e-16,C-orthogonality8.069e-16.
|
||||
Solver 허용치는 이 숫자 자체가 아니라 §3의 coefficient/eigen/residual enclosure다.
|
||||
BE oracle는 exp(-λt)를 (1+λt/N)^-N으로 대체한다.
|
||||
N>1의 마지막 반력은 modal derivative -λ×final amplitude로 구할 수 있어
|
||||
작은 δ의 subtraction cancellation을 피한다.
|
||||
|
||||
### 7.2 사전 고정 물리 오차와 허용치
|
||||
|
||||
각 t*마다 별도 N=4096,8192,δ=t*/N,INC=N run.
|
||||
아래 첫 값은 **δ→0 P2 공간오차**, 괄호는 위로 반올림한 **D_space**다.
|
||||
초기의 큰 허용치는 method의 제한이며 제품 전 범위 정확도 보증이 아니다.
|
||||
|
||||
| t*/sqrt(t*) | T∞ | q∞ | E | Rc |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| .001/.03162 | .1399996(.141) | 10.64818(10.7) | .03031345(.0304) | 10.86927(10.9) |
|
||||
| .01/.10000 | .01524952(.0153) | 1.274464(1.28) | .00467600(.00468) | .823687(.824) |
|
||||
| .05/.22361 | .00597851(.00598) | .252470(.253) | .00129690(.00130) | .00631488(.00632) |
|
||||
| .1/.31623 | .001387325(.00139) | .135427(.136) | .000665986(.000666) | .009524106(.00953) |
|
||||
| .5/.70711 | .000141091(.000142) | .0283969(.0284) | .0000944866(.0000945) | .000525742(.000526) |
|
||||
| 1/1 | .0000413942(.0000414) | .00815759(.00816) | .0000158234(.0000159) | .0000478014(.0000479) |
|
||||
|
||||
Continuum 오차 허용치는 **D_space+D_time(N)+B_oracle+B_solver**다.
|
||||
D_time은 독립 modal 차이의 max/absolute norm이다. 온도/flux sampling L,
|
||||
energy row1ᵀC,reaction row K_cf−C_cf C_ff^-1K_ff 각각에 대해
|
||||
LΣa_jv_j[(1+λ_jt/N)^-N−exp(-λ_jt)]를 계산한다.
|
||||
Cancellation이 불확실하면 Σ|La_jv_j|×|amplitude차이|로 enclosure한다.
|
||||
B_oracle은 series tail+summation/eigen interval,B_solver는 §3 행렬/solve 오차를
|
||||
L에 전파한 값이다. **B_oracle+B_solver>D_space/1000이면 plateau 판정은
|
||||
inconclusive**다. 이 조건은 geometry 지원 cutoff가 아니다.
|
||||
|
||||
N=4096의 독립 D_time은 아래와 같다. N=8192에서는 대략 절반이며 appendix가 재현한다.
|
||||
|
||||
| t* | T∞ | q∞ | E | Rc |
|
||||
| ---: | ---: | ---: | ---: | ---: |
|
||||
| .001 | 7.5820e-7 | 8.7770e-6 | 4.6839e-8 | 6.0181e-6 |
|
||||
| .01 | 1.6648e-5 | 1.9198e-4 | 1.8013e-6 | 1.5383e-4 |
|
||||
| .05 | 2.9817e-5 | 2.2173e-4 | 7.3403e-6 | 1.9484e-4 |
|
||||
| .1 | 3.0985e-5 | 1.9790e-4 | 1.1177e-5 | 1.6441e-4 |
|
||||
| .5 | 6.8903e-5 | 1.1406e-4 | 4.3931e-5 | 1.0879e-4 |
|
||||
| 1 | 8.0305e-5 | 1.3224e-4 | 5.1125e-5 | 1.2621e-4 |
|
||||
|
||||
물리 오차 허용치 외에 **동시에** FESA와 finite-N BE oracle가
|
||||
B_oracle+B_solver 내에서 일치해야 한다. 큰 초기 공간오차가 잘못 구현된 방법까지
|
||||
허용하지 않도록 분리했다. Table rounding은 production 결과와 무관하게 고정했다.
|
||||
|
||||
### 7.3 Plateau 정량 보고
|
||||
|
||||
E_space=||oracle_P2−Fourier||와 FESA error e_N에 대해
|
||||
|e_N−E_space|≤D_time+B_oracle+B_solver를 확인한다.
|
||||
면내1×1과2×2의 slab 차이는 §3 roundoff 이내여야 한다.
|
||||
두께 지배 해가 면내 refinement로 좋아진다고 판정하면 실패다.
|
||||
|
||||
관측 plateau의 기준은 D_time+B_oracle+B_solver≤E_space/10.
|
||||
N=8192에서 .001/.01/.05/.1의 네 quantity는 충족한다. 뒤 시각에서 미충족하는
|
||||
T/E/R은 **미도달**로 보고하고 δ→0 spectral 공간오차를 따로 제시한다.
|
||||
예컨대 t*=1의 E는 시간오차가 공간오차보다 커서 두 N만으로 plateau가 관측되었다고
|
||||
할 수 없다. 침투 깊이 sqrt(αt),station 간격 h/4,segment 길이 h/2,E_space,D_time을
|
||||
함께 보고한다. 초기 큰 flux/reaction 오차는 음수 온도 제거로 고칠 수 없다.
|
||||
|
||||
## 8. 시간격자 predicate, count와 재분해
|
||||
|
||||
### 8.1 독립 반증과 수정 범위
|
||||
|
||||
Arithmetic-only D≤d rad(q)+rad(p)는 입력 표현오차를 모두 포함하지 않았다.
|
||||
τ=5.351455173733616,d=.17262758624947144,m=31에서
|
||||
exact |τ−md|=8.326672684688674e-16 > 기존 Bhat=7.507374033534679e-16인데,
|
||||
입력 rounding-cell I(τ)와 mI(d)는 겹친다. 이 반례를 blocking으로 보고했고
|
||||
승인된 입력 표현오차 의미에 맞춰 **input-cell overlap**으로 보완했다.
|
||||
이전 predicate의 실행 성공을 의미 정합 승인으로 대체하지 않았다.
|
||||
Appendix D는 이 실패 이력을 보존하며 현재 판정은 C를 따른다.
|
||||
|
||||
### 8.2 현재 고정 predicate
|
||||
|
||||
입력 double x의 원래 rounding-cell은
|
||||
L_x=(prev(x)+x)/2,U_x=(x+next(x))/2다. Significand LSB가 짝수면 두 endpoint
|
||||
포함, 홀수면 두 endpoint 제외(nearest-even). 최대 finite의 U_x는 next=Inf를
|
||||
평균하지 않고 x+(x−prev(x))/2라는 유한 real dyadic threshold다.
|
||||
최소 subnormal의 half-ULP도 binary64로 먼저 반올림하지 않는다.
|
||||
|
||||
τ,d를 공통 power-of-two로 τ∈[1/2,1)에 옮겨 q=fl(τ/d),
|
||||
m=nearest-even integer(q)를 만든다. **원래 입력의 cell도 동일 scale로 옮긴다.**
|
||||
Normal화된 값의 이웃으로 cell을 다시 만들면 subnormal 입력의 표현오차를 축소하므로
|
||||
잘못이다. Endpoint-close는 I(τ)와 mI(d)의 exact 교집합이 비어 있지 않은 경우다.
|
||||
두 구간이 한 점에서만 닿으면 그 점이 양쪽에 모두 포함되는지도 확인한다.
|
||||
|
||||
INC≤2^32−1,q≤INC+1 및 위 scale에서 cell endpoint는 고정 dyadic 격자 2^-88에
|
||||
정확히 놓인다. Endpoint 정수와 m곱의 보수적 최대122bit는 두 uint64 또는 네 uint32
|
||||
limb 안에 들어간다. Carry/shift를 검사하는 bounded 정수 산술이며 새 arbitrary-precision
|
||||
runtime dependency가 아니다. Reviewer의 Fraction은 이 bounded 비교의 독립 oracle다.
|
||||
나눗셈·곱셈 roundoff는 후보/연산 bound 설명에 쓰고 cell을 더 넓히는 별도 epsilon으로
|
||||
중복 가산하지 않는다.
|
||||
|
||||
q overflow 또는 INC+1 초과는 preflight 실패; close면 N=m이다. Nonclose에서는
|
||||
X=τs2^88,Y=ds2^88,f=floor(q)로 fY≤X<(f+1)Y를 exact 비교하고 필요하면 f를
|
||||
한 번 ±1 교정한다. X=fY이면 N=f, 아니면 N=f+1이다. Division 오차를 count에
|
||||
그대로 전달하지 않는다. d≥τ는 한 증분 δ=τ의 선행 분기다.
|
||||
INC 기본100,양의 uint32,N≤INC. 정상 stored time=fl(jd),마지막=입력τ,
|
||||
strict increase/finite를 검사한다. Close의 마지막 δ는 **d 그대로**다.
|
||||
실제 shortened만 fma(-(N−1),d,τ)를 쓰며 A/RHS/reaction/energy/dissipation은 같은 δ다.
|
||||
|
||||
| fixture | 필수 결과 |
|
||||
| --- | --- |
|
||||
| τ=10,d=3 | N=4,stored3,6,9,10;δ=3,3,3,1;마지막 refactor |
|
||||
| τ=2,d=3 및 d=τ | 한 증분 δ=τ |
|
||||
| τ=.9,d=.3 | N=3,stored 마지막 .9;세 δ=.3,factorization 재사용 |
|
||||
| τ=1,d=.1 | N=10;stored .30000000000000004 등을 보존,δ=.1 유지 |
|
||||
| nextafter(.9,-∞),d=.3 | .8999999999999999:close,N=3,δ=.3 |
|
||||
| 두 ULP 아래 τ,d=.3 | .8999999999999998:nonclose,N=3,finalδ=.2999999999999998 |
|
||||
| nextafter(.9,+∞),d=.3 | .9000000000000001:nonclose,N=4,finalδ=1.6653345369377348e-16 |
|
||||
| 기존 반례 τ=5.351455173733616,d=.17262758624947144 | input cells overlap,N=31,모든 δ=d;가짜 tiny 증분 제거 |
|
||||
| Subnormal midpoint | a=최소 positive subnormal:τ=20a,d=6a는 even/even 닫힌 접촉,N=3;τ=17a,d=5a는 odd/odd 열린 접촉,N=4,마지막δ=2a |
|
||||
| Scale/최대값 | (.9,.3)×2^-1000 및×2^1000은 같은 count/close;τ=1e-323,d=5e-324는 N=2;τ=maxfinite,d=fl(maxfinite/3)는 N=3 |
|
||||
| INC | N/N−1 경계,생략100;0,-1,1.5,4294967296 실패;τ=2^32,d=1,INC=2^32−1은 사전 count 실패 |
|
||||
| 비유한/비표현 | Inf/NaN/0/음수,binary64에서0으로 underflow하는 token 거부;거대한 τ/d는 cast/allocation 전 실패 |
|
||||
| 저장 가능성 | finite-positive/uint32 count 제한 아래 정상 간격 d는 ulp(jd)보다 충분히 크다. Generator의 finite/strict-increase 보호 분기는 중복/Inf 시간을 주입한 내부 fixture로 검사;불가능한 정상 공개 입력을 만들지 않음. |
|
||||
|
||||
특히 nextafter(.9,+∞)/.3의 tiny remainder를 유지하는 근거는 단순 predicate 결과가
|
||||
아니다. exact |τ−3d|=1.6653345369377348e-16이고 두 입력 cell 반폭 합은
|
||||
1.3877787807814457e-16이므로 **실제 rounding cells가 분리된다**. 이를 가짜 표현오차
|
||||
증분으로 흡수하면 입력 표현오차 범위를 넘는다. 반면 위 m=31 반례는 cells가 겹치므로
|
||||
추가 tiny 증분을 만들면 안 된다. 작은 실제 δ의 나쁜 conditioning은 §3과 candidate
|
||||
보존으로 처리하며 nominal δ로 바꾸지 않는다.
|
||||
|
||||
현재 predicate의 independent seed901 10,000쌍은 원래 cell Fraction overlap과
|
||||
2^-88 정수 비교가 모두 일치했고 최대122bit를 넘지 않았다. 원래 subnormal,maxfinite,
|
||||
열린/닫힌 접촉,반례 및 scale 경계를 따로 검산했다. FMA oracle는 exact Fraction
|
||||
product-sum을 한 번 float로 반올림한다. Production dependency 요구가 아니다.
|
||||
|
||||
## 9. 외부 reference와 evidence 경계
|
||||
|
||||
필수 원본은 reference/shell-thermal/shell-thermal.inp와
|
||||
reference/shell-thermal/shell-thermal NodalTemperature.csv다.
|
||||
이 검토는 원본 복사·수정·생성 또는 Abaqus 실행을 하지 않았다.
|
||||
2026-09-28 read-only snapshot(729row,min=-15.5742216,max=1000)은 과거 관찰이며
|
||||
이번 solver comparison을 대신하지 않는다.
|
||||
|
||||
Family=(shell-thermal,source Step-1,exact t=37,NT11 bottom,scalar,
|
||||
사용자 일관 온도 단위,blocking),identity=(Part-1-1,source node label,DOF11).
|
||||
CSV instance 생략은 입력 단일 instance와 label 집합 검증으로만 복원한다.
|
||||
Missing/extra/duplicate/nonfinite/frame/instance/station 오류는 tolerance 전에 실패한다.
|
||||
|
||||
공통 TOLERANCE 그대로 S=max|reference|=1000,B=.01S=10;
|
||||
|r|≤B이면 |f−r|≤B,그 밖에는 |f−r|/|r|≤.05,
|
||||
모든729row RMS/S≤.01을 동시에 만족한다. S=0이면 모든 값 exact0이다.
|
||||
−15.5742216은 relative 대상이며 clamp/온도 영점 이동 금지.
|
||||
추가 Abaqus CSV는 필수가 아니다. 한 frame으로 내부 station/flux/reaction/시간 이력을
|
||||
검증했다고 할 수 없다.
|
||||
|
||||
## 10. 실행 기록과 완료 경계
|
||||
|
||||
git rev-parse --show-toplevel로 T1 worktree를 확인했다(exit0).
|
||||
NumPy/SciPy import 환경 probe는 NumPy 부재로 exit1;설치 없이 표준 라이브러리
|
||||
scratch로 전환했다. [Appendix](verification-oracles.md#독립-oracle와-재현)의 명령은 Python blocks를
|
||||
지정 순서로 메모리에서 실행한다. 실제 scratch exit0의 핵심 출력:
|
||||
|
||||
- Fraction:C positive pivot20,K positive leading pivot19/K1=0,1ᵀC1=2;
|
||||
jump−1/5,1/25 및 reaction24/5,36/25.
|
||||
- 직접54점/분리식:다섯 geometry 상대 norm 차이 최대7.73e-16.
|
||||
- Slab eigen residual3.994e-16/C-orthogonality8.069e-16,§7 공간/시간 오차.
|
||||
- §5 quadrature,§6 예상 차수,§8 time predicate/INC assertions.
|
||||
|
||||
최종 재현 명령은 appendix 첫 PowerShell block이며 exit 0,
|
||||
마지막 출력은 ALL SCRATCH BLOCKS COMPLETED였다. Input-cell 독립 비교는
|
||||
10,000/10,000 및 CURRENT TIME GRID ASSERTIONS PASSED를 출력했다.
|
||||
실행 예산 보완 뒤 five-block 재검산도 exit 0이었다. Bounded-space order/time ratio,
|
||||
FOURIER INTERVAL ASSERTIONS PASSED 및 최종 완료 출력을 확인했다.
|
||||
상대 링크 파일 존재/Markdown 표 열 수 정적 검사도 exit 0(8 links,2 files),
|
||||
두 소유 파일만 대상으로 한 git diff --check는 exit 0이었다.
|
||||
|
||||
수학 scratch는 production correctness를 증명하지 않는다. **미실행:**MSVC build/CTest,
|
||||
구현 단위·통합 검사,FESA 결과 생성,NT11 comparison,실제 solver convergence/energy/
|
||||
physics 검토. 필요한 수치 기준은 고정되었으며 구현 결과 뒤에 선택할 미정 tolerance는
|
||||
없다. 필수 실패 시 구현·conditioning·oracle 전제를 조사하고 physics/method/acceptance
|
||||
충돌은 메인에 보고한다.
|
||||
@@ -1,55 +0,0 @@
|
||||
# Shell transient heat transfer — T10 물리 결과 평가
|
||||
|
||||
평가 대상은 T10 소스 `9e8afb9`의 실제 MSVC focused 실행이다. 메인 병합 후 HEAD는
|
||||
`9f7fb2e`다. [승인 계약](PRD.md) STH-C03/C04/C07/C08,
|
||||
[수치 기준](numerical-review.md), [reference 결정](ADR.md#sth-adr-015-원본-reference-진단-전환과-새-모델-비교)을
|
||||
적용했다. 이 평가는 T10 결과의 물리 개연성 검토이며 기능 완료 또는 release 승인이 아니다.
|
||||
|
||||
실행 근거는 작업 checkout의
|
||||
`.dryforge/worktrees/T2/.dryforge/evidence/t10-final-focused-test.log`,
|
||||
`t10-final-focused-LastTest.log`, `t10-final-metrics.json`,
|
||||
`t10-final-eigen-source-sha256.json`, `t10-final-reference-after-sha256.json`이다.
|
||||
소스 manifest는 실행한 physics/oracle/comparator 파일 8개를 식별하고 metrics의
|
||||
`source_hashes_match=true`다. Focused CTest는 **26/26 PASS, native exit 0**이다.
|
||||
실행 JSON은 commit 전 revision `95ba2c5`를 기록하지만 T2 작업트리의 8개 raw hash는
|
||||
최종 commit `9e8afb9`와 일치한다. 메인 checkout의 일부 raw byte 차이는 CRLF 변환이며
|
||||
LF 정규화 내용은 8개 모두 같다.
|
||||
이 숫자에는 원본 reference가 수치 실패로 남았는지를 확인하는 진단 테스트의 PASS가
|
||||
포함된다. 따라서 26/26을 원본 수치 비교의 통과로 읽을 수 없다.
|
||||
|
||||
| 물리 항목 | 실제 결과와 계산 | 판정 범위 |
|
||||
| --- | --- | --- |
|
||||
| 단열·잔차·에너지 | 0, +2, -2 균일 온도 8증분에서 시작값 유지; 0장은 수지/소산 defect가 정확히 0. 실제 38개 `THERMAL_PHYSICS` run의 최대 free `beta=1.0613e-14`, full `physical_beta=1.1041e-14`, 최대 `energy_defect=7.2165e-16`; 각 run의 최대 `energy_defect/energy_bound=0.001161`. 단열에서 최대 `dissipation_defect/dissipation_bound=6.194e-5`. | 기록된 승인 roundoff bound 안. `beta`·수지·소산 defect 자체는 production 증분 evidence이며, 테스트는 이를 bound와 대조한다. 독립적인 40-DOF 두 component 수지 계산은 아래 항목이다. C-norm 소산은 실제 열에너지 수지와 구별한다. |
|
||||
| 부호·component 수지·반력 | 두 분리 영역의 signed 입력에서 첫 영역 `+3`의 constrained 입력을 제거해도 온도 이력은 동일하고 반력은 `-3`만큼 변한다: `R_with-R_without=-3` [power]. 두 번째 영역의 `+2+3-5=0`이며 독립 용량 적분에서 `ΔE₂≈0`; 첫 영역은 `ΔE₁-dt·R≈0`을 승인 bound로 확인한다. | 외력 `Q`가 full residual에 남고 reaction 양수가 모델 공급이라는 STH-C04 부호와 일치한다. 검사는 상태/반력 벡터를 읽는다. |
|
||||
| 두께·재료·접힘 | 길이 1씩, `k₁h₁=1`, `k₂h₂=5`, 폭 1의 전단면 strip 저항 `R=1+1/5=1.2`, `ΔT=1`이므로 `P=1/R=5/6=0.8333333333333333`. 평판·90° 접힘 모두 출력 반력 `0.8333333333333877`, 차이 약 `5.44e-14`, 서로 같은 반력. Flux는 첫 요소 `-5/6` x, 두 번째 요소 평판 `-5/3` x / 접힘 `-5/3` z 방향이다. | 길이·두께·물성에 맞는 열률 및 전역 방향이다. **모든 두께 station을 양 끝에서 구속하고 C=0으로 둔 내부 assembly fixture**이므로 공개 bottom/top-only CLI 사례의 검증으로 확대할 수 없다. 접힘의 실제 3D 접합장도 해상하지 않는다. |
|
||||
| Flux 방향·trace | `T=2+3x-2y+4(hζ/2)`의 직접 복구에서 `q=(-3k,+2k,-4k)` [power/area]. 회전 후 벡터도 함께 회전하고 법선 반전에는 station이 재매핑된다. `T_station=(0,0,0,1,2)`에서는 중립면 `q₃(0-)=0`, `q₃(0+)=-4k/h`; 평균하지 않는다. Frame은 직교·right-handed 조건을 검사한다. | Fourier 부호와 한쪽 trace 의미에 부합한다. 이 affine/trace 검사는 내부 all-constrained partition fixture이며 공개 BC 허용 범위를 넓히지 않는다. |
|
||||
| 시간·면내 수렴 | 고정 8×8 eigenmode의 N=16→256에서 N=32/64/128/256 오차 `0.00567442, 0.00285549, 0.00143237, 0.000717347`; 관측 차수 `0.981712, 0.990734, 0.995336, 0.997660`, 승인 `[.97,1.02]`. 8/16/32/64 면내 mesh의 T L2 차수 `1.99670, 2.00077, 2.00658` 및 gradient L2 차수 `0.997220, 0.999305, 0.999826`, 승인 `[1.95,2.05]`/`[.98,1.03]`. 최대 time/spatial ratio `0.0068633<1/32`. | 실제 전체 node×5 station 온도 벡터와 독립 eigen/Fourier oracle를 비교한다. 단위 k=1 fixture에서는 gradient 차수가 flux의 공간차수를 대표한다. 일반 점열원·곡면에 이 smooth 수렴차수를 주장하지 않는다. |
|
||||
| 두께 slab 응답 | 단위 면적, `h=k=rho=c=1`, 초기 0, bottom 1, top 단열의 1×1/2×2 mesh, 시간 `.001,.01,.05,.1,.5,1`, N=4096/8192에서 실제 온도·global q₃·용량 적분 E·반력 합을 각각 독립 finite-N P2 및 Fourier oracle와 대조한다. 96개 quantity-group 결과 중 최대 finite-BE gap/bound `0.01871`, 최대 물리오차/(D_space+D_time+B_oracle+B_solver) `0.999979`; 1×1/2×2 차이는 각 승인 roundoff 안이다. | 두꺼운 layer의 같은 두께 오차가 면내 refinement로 사라지지 않는 결과와 일치. `.001≤t*≤.1`, N=8192의 네 물리량은 모두 plateau 조건 성립. `.5,1`에서는 flux만 plateau이고 T/E/R은 미도달로 표기한다. |
|
||||
|
||||
초기 slab에서 `sqrt(alpha·t)=0.03162h` (`t*=.001`)는 station 간격 `0.25h`,
|
||||
P2 segment 길이 `0.5h`보다 훨씬 작다. 따라서 N=8192에서도 Fourier 대비 최대
|
||||
무차원 오차는 T `0.13999998`, q `10.64818068`, E `0.03031342`, bottom 반력
|
||||
`10.86926883`이다. 각각 승인된 `D_space=0.141,10.7,0.0304,10.9`와
|
||||
시간/roundoff 예산 안이지만, **초기 경계층의 국소 flux 및 반력 정확도는 낮다**.
|
||||
이 수치 일치는 5점 모델의 의도한 제한을 드러내며 일반 shell의 정확도 보증은 아니다.
|
||||
`t*=1`의 E는 `E_space=1.58234e-5`, `D_time=2.55629e-5`로 시간오차가 더 커서
|
||||
plateau 관측을 주장하지 않는다. Slab의 q, E, 반력 계산은 solver 결과를 별도로
|
||||
집계하지만 Fourier/P2 목표값과 bound는 테스트 oracle가 제공한다.
|
||||
|
||||
원본 `reference/shell-thermal/` 입력/CSV SHA256은 계약의
|
||||
`955C8BEE…00D6EA4` / `765B0D0F…10D3E5`와 일치한다. 실제 HDF5와 비교한
|
||||
Step-1, `t=37`, NT11 729행에서 **87행 실패**, `RMS/S=0.049674084615673214`
|
||||
(`S=1000`, `B=10`, 승인 family 한계 `0.01`), 최대 절대차 `245.26294650091936`이다.
|
||||
STH-ADR-015에 따라 이는 **수치 FAIL인 진단 family**로 유지한다. 독립 승인식 oracle도
|
||||
같은 불일치를 보였다는 [충돌 기록](reference-comparison-conflict.md)은 원인 범위를
|
||||
좁히지만 Abaqus 내부 정식화의 옳고 그름을 판정하지 않는다. 분리 경로의 새 필수
|
||||
reference 모델/CSV가 없어 해당 비교는 **미실행이며 완료 차단**이다.
|
||||
|
||||
검증 범위의 경계: T10 물리 검사는 `Domain → Assembly → MKL 증분 → accepted state`
|
||||
결과를 주로 평가하며 공개 CLI/HDF5의 모든 물리량을 각 증분마다 별도 재적분하지는
|
||||
않는다. 원본 reference는 실제 HDF5 경로를 사용하나 NT11 한 성분·한 시점뿐이다.
|
||||
Warped/곡면 전도 응답, 접힘·두께 단차의 국소 3D 전도, 큰 `h/곡률`, 초기 두께
|
||||
경계층, 점열원 근처 mesh-independent flux는 이 evidence로 검증되지 않는다.
|
||||
`STH-C01`의 normalized station 공유도 실제 물리 z 일치 또는 접촉 전도를 뜻하지
|
||||
않는다. T10 focused 26개는 전체 회귀 결과가 아니다. 물리적으로 확인된 범위는
|
||||
위 균일·affine·strip·smooth 면내·slab fixture에 한정한다.
|
||||
@@ -1,113 +0,0 @@
|
||||
# 승인 정식화와 원본 NT11 reference 비교의 충돌
|
||||
|
||||
상태: **비교 분류 결정 완료; 원본 수치 불일치 유지**. 작성일: 2026-09-29.
|
||||
사용자는 정식화를 유지하고 기존 비교를 진단으로 전환하며 reference 모델을 변경하는
|
||||
선택 A를 승인했다([STH-ADR-015](ADR.md#sth-adr-015-원본-reference-진단-전환과-새-모델-비교)).
|
||||
이 문서는 결정 전의 실패 evidence를 그대로 보존한다. 정식화·초기화·공통 허용치는 변경하지 않는다.
|
||||
기준은 [PRD STH-C03/C04/C08](PRD.md), [formulation](formulation.md),
|
||||
[numerical review](numerical-review.md), [공통 tolerance](../TOLERANCE.md)다.
|
||||
|
||||
## 1. 실제 실행과 비교
|
||||
|
||||
구현 `7cccfcd`의 실제 CLI로 원본 `reference/shell-thermal/shell-thermal.inp`를 실행했다.
|
||||
100개 증분과 초기 프레임을 저장하고 exit 0으로 종료했다(153.5초).
|
||||
원본 INP와 CSV의 SHA256은 실행 전후 PRD의 승인 값과 일치했다.
|
||||
FESA가 생성한 HDF5는 입력의 lexical sibling이다.
|
||||
|
||||
별도 `h5dump`로 source step, 정확한 time=37/increment=37, DOF11,
|
||||
`Part-1-1`/node label과 thermal row mapping을 확인했다. 729행 모두 중복·누락 없이
|
||||
대응했고 값은 finite였다. Source DOF13이나 nearest frame으로 대체하지 않았다.
|
||||
|
||||
| 판정량 | 실제 결과 | 승인 기준 |
|
||||
| --- | ---: | ---: |
|
||||
| 비교 행 | 729 | 모든 source 행의 일대일 대응 |
|
||||
| Reference scale S / near-zero B | 1000 / 10 | 공통 정책 |
|
||||
| 행별 실패 수 | 87 | 0 |
|
||||
| RMS/S | 0.04967408461567323 | ≤0.01 |
|
||||
| 최대 절대 차이 | 245.26294650091884 | 해당 행 기준으로 판정 |
|
||||
| FESA 최솟값 / 최댓값 | -258.91081180091885 / 1000 | clamp 금지 |
|
||||
|
||||
대표 source node 22에서 reference=-13.6478653, FESA=-258.91081180091885이며,
|
||||
행별 5% 기준은 0.682393265다. 근소한 반올림 차이가 아니다.
|
||||
|
||||
별도 C++ comparator도 기존 `ReferenceTolerancePolicy::Evaluate`를 그대로 사용하여
|
||||
동일 실패를 확인했다. `ThermalReference.OriginalAbaqusNt11AtExactTime37`의 실제 결과는
|
||||
729행, 87개 실패, RMS/S=0.049674084615673214, max_abs=245.26294650091862다.
|
||||
결정 전 해당 CTest 실행은 native exit 8이었고, 비교를 통과로 표시하지 않았다.
|
||||
|
||||
## 2. FESA 코드를 사용하지 않은 독립 계산
|
||||
|
||||
독립 Python/SciPy 실행기는 원본 텍스트에서 729개 좌표, 676개 사각형 connectivity,
|
||||
Set-10의 196개 node를 읽었다. 모든 요소가 평면 직사각형임을 확인한 뒤,
|
||||
직사각형 Q1의 닫힌형 M/S와 두 P2 구간의 정확한 Z0/Z1을 조립했다.
|
||||
FESA parser·kernel·assembler·시간 적분 코드는 호출하지 않았다.
|
||||
|
||||
입력 물성 k=54, rho=7850, c=460, h=0.5를 사용하고 승인된 식
|
||||
`C=rho*c*(h/2)*M⊗Z0`, `K=k*((h/2)*S⊗Z0+(2/h)*M⊗Z1)`을 적용했다.
|
||||
전체 raw T0=0, Set-10의 source DOF11만 g=1000, dt=1인 BE를 37회 계산했다.
|
||||
3449 free / 196 constrained DOF를 별도 SciPy sparse LU로 풀었다.
|
||||
|
||||
| 독립 계산량 | 결과 |
|
||||
| --- | ---: |
|
||||
| FESA NT11과 최대 절대 차이 | 7.673861546209082e-12 |
|
||||
| 최대 정규화 선형 잔차 | 3.599964225668404e-16 |
|
||||
| Reference 행별 실패 수 | 87 |
|
||||
| Reference RMS/S | 0.04967408461567341 |
|
||||
| 독립 NT11 최솟값 | -258.9108118009203 |
|
||||
|
||||
이 수치는 새 tolerance가 아니다. 승인 식의 독립 계산도 같은 큰 reference 차이를
|
||||
재현한다는 관측이다. 이 사례의 차이를 단순한 source mapping이나 production 행렬
|
||||
계산 버그로 설명할 근거는 발견하지 못했다. 전체 물리 검증의 통과를 뜻하지는 않는다.
|
||||
|
||||
별도 read-only 검토자는 원본 hash·수치 상수·경계조건, oracle의 tensor 식/BE 우변,
|
||||
HDF/CSV identity join과 공통 tolerance 계산을 대조하여 이 충돌 evidence의 차단 오류를
|
||||
발견하지 못했다. Oracle는 범용 입력기가 아니며 물성·두께·시간·g는 이 사례의 확인된
|
||||
상수를 사용한다. 다른 입력에 대한 정확도나 Abaqus의 내부 동작을 입증하는 검사는 아니다.
|
||||
|
||||
## 3. 공개 문서 확인과 해석 한계
|
||||
|
||||
공개 [Choosing a Shell Element](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEELMRefMap/simaelm-c-shellelem.htm)의
|
||||
Heat Transfer Shell Elements 절은 다중 온도점을 갖는 shell의 DOF11을 아랫면 온도로
|
||||
설명한다. [Uncoupled Heat Transfer Analysis](https://docs.software.vt.edu/abaqusv2025/English/SIMACAEANLRefMap/simaanl-c-heattransfer.htm)의
|
||||
Initial Conditions 절은 생략된 초기 온도의 기본값을 0으로 설명한다.
|
||||
이 관측 가능한 의미는 현재 reference mapping을 DOF13으로 바꿀 근거를 주지 않는다.
|
||||
|
||||
확인 가능한 문서는 2025판이며 2024 URL은 접근 거부였다. 공개 문서와 한 시점의 CSV만으로
|
||||
reference 생성기의 내부 행렬·적분·초기 처리 방식이나 그 동등성을 단정하지 않는다.
|
||||
다른 방법의 수치 결과가 비슷하다는 이유만으로 FESA의 승인 방법을 교체하지 않는다.
|
||||
|
||||
## 4. 승인된 결정과 남은 비교
|
||||
|
||||
원본 모델에서는 다음 두 조건을 동시에 충족하지 못했다.
|
||||
|
||||
1. 승인된 consistent C, Q4×P2 두 구간, exact thickness 적분과 raw 초기값 BE를 유지한다.
|
||||
2. 이 원본 NT11 비교를 현재 공통 tolerance의 필수 blocking 검사로 통과한다.
|
||||
|
||||
사용자는 첫 조건을 유지하고 기존 원본 비교를 **진단**으로 전환하는 선택 A를 승인했다.
|
||||
공통 tolerance 계산과 87행 실패, RMS/S 초과를 그대로 기록한다. 비교기의 새 진단
|
||||
테스트가 통과하더라도 이는 열해가 원본 CSV tolerance를 만족한다는 뜻이 아니다.
|
||||
독립 해석해·수지·수렴성 검증과 새 reference 모델의 필수 비교가 완료 조건이다.
|
||||
새 모델과 결과 CSV는 기존 원본과 분리된 경로에 두기로 했다. 구체적인 경로·hash·비교
|
||||
시점·성분·row identity는 아직 확정되지 않았다.
|
||||
원본을 변경하거나 새 모델의 결과를 추정하여 통과로 표시하지 않는다.
|
||||
|
||||
T1–T9 구현·검증은 유지한다. T10은 원본 비교의 실제 FAIL metric을 보존한 진단
|
||||
분류와 독립 slab/시간·공간 수렴 검증을 마쳤다. 자세한 실제 실행은
|
||||
[구현 검증 보고서](implementation-verification.md#t10-해석해수지수렴성과-원본-진단-비교)에
|
||||
기록했다. 전체 회귀와 독립 physics·최종 구현 검토도 완료했고 그 결과는
|
||||
[구현 검증 보고서](implementation-verification.md#통합-전체-회귀와-남은-완료-조건)에
|
||||
기록했다. 새 필수 reference 비교는 별도 모델·CSV 제공 전까지 미실행이다.
|
||||
|
||||
## 5. 보존 evidence
|
||||
|
||||
- 메인 `.dryforge/review/t10_reference/`: `run.py`, `execution.json`, stdout/stderr,
|
||||
생성 log, `compare.py`, 실제 dump/exit 기록, `comparison.json`, `comparison-rows.json`.
|
||||
- 같은 경로의 `independent.py`, `independent-execution.json`,
|
||||
`independent-comparison.json`, `independent-rows.json`: native exit 0,
|
||||
NumPy 2.4.6 / SciPy 1.17.1, 사용 script hash 포함.
|
||||
- 작업 checkout T2 `.dryforge/evidence/t10-reference-test.log` 및 native exit JSON:
|
||||
공통 정책을 사용한 C++ 비교의 실제 실패. Checkpoint `95ba2c5`의 최종 schema/identity
|
||||
음성검사는 6/6 PASS이며, 동일 출력의 최종 comparator는 native 1로 비교 실패를 유지했다.
|
||||
세부 source/artifact hash와 보존 상태는 [구현 검증 보고서](implementation-verification.md)에 기록했다.
|
||||
- 원본 reference INP/CSV는 변경하지 않았다. 생성 HDF5와 CSV row view는 외부 reference
|
||||
artifact를 교체하는 자료가 아니다.
|
||||
@@ -1,508 +0,0 @@
|
||||
# 독립 oracle와 재현
|
||||
|
||||
수치 검토에 사용한 exact/rational·spectral·Gauss 검산 코드를 보존한다. 코드의 결과는 당시 정식화 검산이며 실제 solver의 전체 검증을 대신하지 않는다. 실제 실행·소스·한계는 [구현 검증](implementation-verification.md)과 [수치 검토](numerical-review.md)를 따른다.
|
||||
|
||||
# 독립 numerical oracle scratch
|
||||
|
||||
이 파일은 numerical-review.md의 사전 계산을 재현하는 문서 부록이다. Solver 또는
|
||||
production test가 아니며 외부 package·reference·출력 파일을 사용하지 않는다.
|
||||
Python 표준 라이브러리만 사용한다. Fraction은 oracle에서 입력 double의 exact 산술을
|
||||
확인하는 용도이며 production arbitrary-precision dependency를 요구하지 않는다.
|
||||
|
||||
T1 root에서 다음 명령은 각 Python block을 순서대로 메모리에서 실행한다.
|
||||
|
||||
```powershell
|
||||
@'
|
||||
from pathlib import Path
|
||||
import re
|
||||
p = Path('docs/shell-transient-heat-transfer/numerical-oracle-scratch.md')
|
||||
blocks = re.findall(r'```python\n(.*?)```', p.read_text(encoding='utf-8-sig'), re.S)
|
||||
assert len(blocks) == 5
|
||||
scope = {}
|
||||
for block in blocks:
|
||||
exec(compile(block, str(p), 'exec'), scope)
|
||||
print('ALL SCRATCH BLOCKS COMPLETED')
|
||||
'@ | python -
|
||||
```
|
||||
|
||||
실행 exit는 0이어야 한다. Assertion 범위는 exact algebra와 독립 oracle 자체에 한정된다.
|
||||
수렴/이산 오차의 출력 숫자 자체를 production tolerance로 사용하지 않고 본 보고서의
|
||||
roundoff·conditioning·오차 전파 기준을 적용한다. NumPy 부재 probe exit1은 실행 실패
|
||||
이력으로 보고서에 남겼으며 아래 코드에는 NumPy를 쓰지 않는다.
|
||||
|
||||
## A. Slab spectral·quadrature·공간/시간 oracle
|
||||
|
||||
```python
|
||||
import math,json
|
||||
def zeros(n,m=None): return [[0.0]*(n if m is None else m) for _ in range(n)]
|
||||
def tr(A):return list(map(list,zip(*A)))
|
||||
def mm(A,B):return [[sum(a*b for a,b in zip(row,col)) for col in zip(*B)]for row in A]
|
||||
def mv(A,x):return [sum(a*b for a,b in zip(row,x)) for row in A]
|
||||
def solve(A,b):
|
||||
a=[list(r)+[v]for r,v in zip(A,b)];n=len(b)
|
||||
for k in range(n):
|
||||
p=max(range(k,n),key=lambda i:abs(a[i][k]));a[k],a[p]=a[p],a[k]
|
||||
d=a[k][k]
|
||||
for j in range(k,n+1):a[k][j]/=d
|
||||
for i in range(n):
|
||||
if i!=k:
|
||||
d=a[i][k]
|
||||
for j in range(k,n+1):a[i][j]-=d*a[k][j]
|
||||
return [r[-1]for r in a]
|
||||
def chol(A):
|
||||
n=len(A);L=zeros(n)
|
||||
for i in range(n):
|
||||
for j in range(i+1):
|
||||
v=A[i][j]-sum(L[i][k]*L[j][k]for k in range(j))
|
||||
L[i][j]=math.sqrt(v)if i==j else v/L[j][j]
|
||||
return L
|
||||
def eig(A):
|
||||
a=[r[:]for r in A];n=len(a);v=[[float(i==j)for j in range(n)]for i in range(n)]
|
||||
for z in range(100*n*n):
|
||||
p,q=max(((i,j)for i in range(n)for j in range(i+1,n)),key=lambda ij:abs(a[ij[0]][ij[1]]))
|
||||
if abs(a[p][q])<1e-15*sum(abs(a[i][i])for i in range(n)):break
|
||||
phi=.5*math.atan2(2*a[p][q],a[q][q]-a[p][p]);c=math.cos(phi);s=math.sin(phi)
|
||||
J=[[float(i==j)for j in range(n)]for i in range(n)]
|
||||
J[p][p]=J[q][q]=c;J[p][q]=s;J[q][p]=-s
|
||||
a=mm(mm(tr(J),a),J);v=mm(v,J)
|
||||
ix=sorted(range(n),key=lambda i:a[i][i])
|
||||
return [a[i][i]for i in ix],[[v[j][i]for i in ix]for j in range(n)]
|
||||
def slabmat(ne):
|
||||
n=2*ne+1;C=zeros(n);K=zeros(n);l=1/ne
|
||||
for e in range(ne):
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
C[2*e+i][2*e+j]+=l/30*[[4,2,-1],[2,16,2],[-1,2,4]][i][j]
|
||||
K[2*e+i][2*e+j]+=[[7,-8,1],[-8,16,-8],[1,-8,7]][i][j]/(3*l)
|
||||
return C,K
|
||||
C,K=slabmat(2);Cf=[r[1:]for r in C[1:]];Kf=[r[1:]for r in K[1:]]
|
||||
L=chol(Cf);Li=tr([solve(L,[float(i==j)for i in range(4)])for j in range(4)])
|
||||
lam,V=eig(mm(mm(Li,Kf),tr(Li)));W=mm(tr(Li),V)
|
||||
yp=[-1-x for x in solve(Cf,[r[0]for r in C[1:]])]
|
||||
coef=mv(tr(W),mv(Cf,yp))
|
||||
def spectral(t,n=None):
|
||||
amp=[a*(math.exp(-l*t)if n is None else math.exp(-n*math.log1p(l*t/n)))for a,l in zip(coef,lam)]
|
||||
T=[1]+[1+x for x in mv(W,amp)]
|
||||
if n is None:dT=[0]+mv(W,[-l*x for l,x in zip(lam,amp)])
|
||||
else:
|
||||
oldamp=[x*(1+l*t/n)for l,x in zip(lam,amp)]
|
||||
old=[1]+[1+x for x in mv(W,oldamp)]
|
||||
dT=[(a-b)/(t/n)for a,b in zip(T,old)]
|
||||
E=sum(mv(C,T));R=mv(C,dT)[0]+mv(K,T)[0]
|
||||
q=[]
|
||||
for e,ss in [(0,-1),(0,0),(0,1),(1,-1),(1,0),(1,1)]:
|
||||
q.append(-4*sum(a*b for a,b in zip([ss-.5,-2*ss,ss+.5],T[2*e:2*e+3])))
|
||||
return T,q,E,R
|
||||
def exact(t):
|
||||
M=80
|
||||
T=[1-sum(4/((2*m+1)*math.pi)*math.sin((2*m+1)*math.pi*x/2)*math.exp(-((2*m+1)*math.pi/2)**2*t)for m in range(M))for x in [0,.25,.5,.75,1]]
|
||||
q=[sum(2*math.cos((2*m+1)*math.pi*x/2)*math.exp(-((2*m+1)*math.pi/2)**2*t)for m in range(M))for x in [0,.25,.5,.5,.75,1]]
|
||||
E=1-sum(8/((2*m+1)*math.pi)**2*math.exp(-((2*m+1)*math.pi/2)**2*t)for m in range(M))
|
||||
return T,q,E,q[0]
|
||||
def errors(a,b):return [max(abs(x-y)for x,y in zip(a[0],b[0])),max(abs(x-y)for x,y in zip(a[1],b[1])),abs(a[2]-b[2]),abs(a[3]-b[3])]
|
||||
out={"lambda":lam,"projected_initial_free":[1+x for x in yp],"slab":[]}
|
||||
for t in [.001,.01,.05,.1,.5,1]:
|
||||
s=spectral(t);x=exact(t)
|
||||
out["slab"].append({"t":t,"penetration":math.sqrt(t),"spatial_error":errors(s,x),"BE4096_temporal":errors(spectral(t,4096),s),"BE8192_temporal":errors(spectral(t,8192),s),"spectral":s})
|
||||
print(json.dumps(out,indent=2))
|
||||
|
||||
def gauss(n):
|
||||
x=[];w=[]
|
||||
for i in range(1,n+1):
|
||||
z=math.cos(math.pi*(i-.25)/(n+.5))
|
||||
for _ in range(30):
|
||||
p0,p1=1.,z
|
||||
for j in range(2,n+1):p0,p1=p1,((2*j-1)*z*p1-(j-1)*p0)/j
|
||||
dp=n*(z*p1-p0)/(z*z-1);nz=z-p1/dp
|
||||
if abs(nz-z)<2e-16: z=nz;break
|
||||
z=nz
|
||||
x.append(z);w.append(2/((1-z*z)*dp*dp))
|
||||
return list(zip(x,w))
|
||||
def dot(x,y):return sum(a*b for a,b in zip(x,y))
|
||||
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 geometry(X,xi,eta):
|
||||
signs=[(-1,-1),(1,-1),(1,1),(-1,1)]
|
||||
N=[(1+s*xi)*(1+t*eta)/4 for s,t in signs]
|
||||
D=[[s*(1+t*eta)/4,t*(1+s*xi)/4]for s,t in signs]
|
||||
a=[sum(D[i][0]*X[i][j]for i in range(4))for j in range(3)]
|
||||
b=[sum(D[i][1]*X[i][j]for i in range(4))for j in range(3)]
|
||||
W=cross(a,b);J=math.sqrt(dot(W,W));norm=[z/J for z in W]
|
||||
aa,ab,bb=dot(a,a),dot(a,b),dot(b,b);det=J*J
|
||||
ra=[(bb*x-ab*y)/det for x,y in zip(a,b)];rb=[(aa*y-ab*x)/det for x,y in zip(a,b)]
|
||||
G=[[D[i][0]*ra[j]+D[i][1]*rb[j]for j in range(3)]for i in range(4)]
|
||||
return N,G,J,norm
|
||||
def surface(X,n):
|
||||
M=zeros(4);S=zeros(4)
|
||||
for xi,wx in gauss(n):
|
||||
for eta,wy in gauss(n):
|
||||
N,G,J,no=geometry(X,xi,eta)
|
||||
for i in range(4):
|
||||
for j in range(4):
|
||||
M[i][j]+=N[i]*N[j]*J*wx*wy;S[i][j]+=dot(G[i],G[j])*J*wx*wy
|
||||
return M,S
|
||||
Z0,Z1=slabmat(2)
|
||||
# h=1: Z0 physical mass already; Z1 physical normal stiffness already.
|
||||
def mats(X,n):
|
||||
M,S=surface(X,n);C=zeros(20);K=zeros(20)
|
||||
for i in range(4):
|
||||
for j in range(4):
|
||||
for a in range(5):
|
||||
for b in range(5):
|
||||
C[5*i+a][5*j+b]=M[i][j]*Z0[a][b]
|
||||
K[5*i+a][5*j+b]=S[i][j]*Z0[a][b]+M[i][j]*Z1[a][b]
|
||||
return C,K
|
||||
def fn(A):return math.sqrt(sum(x*x for r in A for x in r))
|
||||
def rel(A,B):return fn([[a-b for a,b in zip(r,s)]for r,s in zip(A,B)])/fn(B)
|
||||
def response(X,C,K):
|
||||
A=[[c/.1+k for c,k in zip(cr,kr)]for cr,kr in zip(C,K)]
|
||||
T=solve(A,[float(i==0)for i in range(20)])
|
||||
flux=[]
|
||||
for xi,eta in [(-1/math.sqrt(3),-1/math.sqrt(3)),(1/math.sqrt(3),-1/math.sqrt(3)),(1/math.sqrt(3),1/math.sqrt(3)),(-1/math.sqrt(3),1/math.sqrt(3))]:
|
||||
N,G,J,no=geometry(X,xi,eta)
|
||||
for off,s in [(0,-1),(0,0),(0,1),(2,-1),(2,0),(2,1)]:
|
||||
Ls=[s*(s-1)/2,1-s*s,s*(s+1)/2];Ds=[4*(s-.5),-8*s,4*(s+.5)]
|
||||
flux.append([-sum((G[i][j]*Ls[a]+no[j]*N[i]*Ds[a])*T[5*i+off+a]for i in range(4)for a in range(3))for j in range(3)])
|
||||
return T,flux
|
||||
def rv(a,b):return math.sqrt(sum((x-y)**2 for x,y in zip(a,b)))/math.sqrt(sum(x*x for x in b))
|
||||
cases={"affine":[[0,0,0],[1,0,0],[1,1,0],[0,1,0]],"distorted":[[0,0,0],[2,0,0],[1.5,1,0],[0,1,0]]}
|
||||
for w in [.1,.5,2]:cases["saddle"+str(w)]=[[x,y,w*x*y]for x,y in [(-1,-1),(1,-1),(1,1),(-1,1)]]
|
||||
ans={}
|
||||
for name,X in cases.items():
|
||||
ds=[]
|
||||
for n in [3,5,7]:
|
||||
C,K=mats(X,n);T,q=response(X,C,K);ds.append((C,K,T,q))
|
||||
rows=[]
|
||||
for a,b in [(ds[0],ds[1]),(ds[1],ds[2])]:
|
||||
rows.append([rel(a[0],b[0]),rel(a[1],b[1]),rv(a[2],b[2]),max(math.sqrt(dot([x-y for x,y in zip(q,r)],[x-y for x,y in zip(q,r)]))for q,r in zip(a[3],b[3]))/max(math.sqrt(dot(r,r))for r in b[3])])
|
||||
ans[name]=rows
|
||||
print(json.dumps({"quadrature":ans},indent=2))
|
||||
def direct54(X):
|
||||
C=zeros(20);K=zeros(20)
|
||||
for xi,wx in gauss(3):
|
||||
for eta,wy in gauss(3):
|
||||
N,G,J,no=geometry(X,xi,eta)
|
||||
for off in [0,2]:
|
||||
for s,ws in gauss(3):
|
||||
ls=[s*(s-1)/2,1-s*s,s*(s+1)/2]
|
||||
ds=[4*(s-.5),-8*s,4*(s+.5)]
|
||||
H=[0.]*20;B=zeros(20,3)
|
||||
for i in range(4):
|
||||
for a in range(3):
|
||||
p=5*i+off+a;H[p]=N[i]*ls[a]
|
||||
B[p]=[G[i][j]*ls[a]+no[j]*N[i]*ds[a]for j in range(3)]
|
||||
weight=wx*wy*ws*J/4
|
||||
for i in range(20):
|
||||
for j in range(20):
|
||||
C[i][j]+=weight*H[i]*H[j];K[i][j]+=weight*dot(B[i],B[j])
|
||||
return C,K
|
||||
for name,X in cases.items():
|
||||
C,K=mats(X,3);Cd,Kd=direct54(X)
|
||||
print("54point",name,rel(C,Cd),rel(K,Kd))
|
||||
assert rel(C,Cd)<1e-12 and rel(K,Kd)<1e-12
|
||||
# Generalized eigen residual and C orthogonality, independently reassemble.
|
||||
C,K=slabmat(2);Cf=[r[1:]for r in C[1:]];Kf=[r[1:]for r in K[1:]]
|
||||
res=fn([[a-b*l for a,b,l in zip(kr,cr,lam)]for kr,cr in zip(mm(Kf,W),mm(Cf,W))])/fn(mm(Kf,W))
|
||||
orth=fn([[v-float(i==j)for j,v in enumerate(row)]for i,row in enumerate(mm(mm(tr(W),Cf),W))])
|
||||
print("slab eigen residual",res,"C orthogonality",orth)
|
||||
assert res<1e-12 and orth<1e-12
|
||||
|
||||
|
||||
def spatial_bounded(n,steps=32,t=.001,ng=12):
|
||||
h=1/n;l=6*(1-math.cos(math.pi/n))/(h*h*(2+math.cos(math.pi/n)))
|
||||
af=math.exp(-steps*math.log1p(l*t/steps));ase=math.exp(-l*t);ae=math.exp(-math.pi**2*t)
|
||||
et=eg=etime=ese=0.
|
||||
for i in range(n):
|
||||
for s,w in gauss(ng):
|
||||
x=(i+(s+1)/2)*h;measure=w*h/2
|
||||
v=((1-s)*math.cos(math.pi*i/n)+(1+s)*math.cos(math.pi*(i+1)/n))/2
|
||||
g=(math.cos(math.pi*(i+1)/n)-math.cos(math.pi*i/n))/h
|
||||
et+=(af*v-ae*math.cos(math.pi*x))**2*measure
|
||||
eg+=(af*g+math.pi*ae*math.sin(math.pi*x))**2*measure
|
||||
etime+=((af-ase)*v)**2*measure
|
||||
ese+=(ase*v-ae*math.cos(math.pi*x))**2*measure
|
||||
return math.sqrt(et),math.sqrt(eg),math.sqrt(etime),math.sqrt(ese)
|
||||
rows=[]
|
||||
for n in [8,16,32,64]:
|
||||
a=spatial_bounded(n);b=spatial_bounded(n,ng=16)
|
||||
ratio=a[2]/a[3];quad=max(abs(x-y)/abs(x)for x,y in zip(a,b))
|
||||
assert ratio<1/32 and quad<1e-8
|
||||
rows.append(a)
|
||||
fluxbytes=n*n*24*3*32*8
|
||||
tempbytes=(n+1)**2*5*33*8
|
||||
print("bounded space",n,"T,grad,time,semi",a,"time/space",ratio,"quad",quad,"historybytes",fluxbytes+tempbytes)
|
||||
for a,b in zip(rows,rows[1:]):
|
||||
pt=math.log(a[0]/b[0],2);pg=math.log(a[1]/b[1],2)
|
||||
assert 1.95<=pt<=2.05 and .98<=pg<=1.03
|
||||
print("bounded order",pt,pg)
|
||||
|
||||
time_orders=[]
|
||||
for n in [16,32,64,128]:
|
||||
e1=abs(math.exp(-n*math.log1p(1/n))-math.exp(-1))
|
||||
e2=abs(math.exp(-2*n*math.log1p(1/(2*n)))-math.exp(-1))
|
||||
order=math.log(e1/e2,2)
|
||||
assert .97<=order<=1.02
|
||||
time_orders.append(order)
|
||||
print("fixed spatial time orders",time_orders)
|
||||
|
||||
```
|
||||
|
||||
## B. Exact Fraction integration·rank·jump
|
||||
|
||||
```python
|
||||
|
||||
from fractions import Fraction as F
|
||||
def fmat(A,d):return [[F(v,d)for v in r]for r in A]
|
||||
def mul(a,b):
|
||||
c=[F(0)]*(len(a)+len(b)-1)
|
||||
for i,x in enumerate(a):
|
||||
for j,y in enumerate(b):c[i+j]+=x*y
|
||||
return c
|
||||
def der(a):return [i*a[i] for i in range(1,len(a))]
|
||||
def integ(a):return sum(F(x,i+1)for i,x in enumerate(a))
|
||||
sh=[[1,-3,2],[0,4,-4],[0,-1,2]]
|
||||
assert [[integ(mul(a,b))for b in sh]for a in sh]==fmat([[4,2,-1],[2,16,2],[-1,2,4]],30)
|
||||
assert [[integ(mul(der(a),der(b)))for b in sh]for a in sh]==fmat([[7,-8,1],[-8,16,-8],[1,-8,7]],3)
|
||||
M=fmat([[4,2,1,2],[2,4,2,1],[1,2,4,2],[2,1,2,4]],36)
|
||||
S=fmat([[4,-1,-2,-1],[-1,4,-1,-2],[-2,-1,4,-1],[-1,-2,-1,4]],6)
|
||||
fac=[([1,-1],[1,-1]),([0,1],[1,-1]),([0,1],[0,1]),([1,-1],[0,1])]
|
||||
assert [[integ(mul(a,c))*integ(mul(b,d))for c,d in fac]for a,b in fac]==M
|
||||
assert [[integ(mul(der(a),der(c)))*integ(mul(b,d))+integ(mul(a,c))*integ(mul(der(b),der(d)))for c,d in fac]for a,b in fac]==S
|
||||
Z0=[[F(0)for _ in range(5)]for _ in range(5)]
|
||||
Z1=[[F(0)for _ in range(5)]for _ in range(5)]
|
||||
for off in [0,2]:
|
||||
for i in range(3):
|
||||
for j in range(3):
|
||||
Z0[i+off][j+off]+=F([[4,2,-1],[2,16,2],[-1,2,4]][i][j],30)
|
||||
Z1[i+off][j+off]+=F([[7,-8,1],[-8,16,-8],[1,-8,7]][i][j],3)
|
||||
C=[[M[i//5][j//5]*Z0[i%5][j%5]for j in range(20)]for i in range(20)]
|
||||
K=[[S[i//5][j//5]*Z0[i%5][j%5]+M[i//5][j//5]*Z1[i%5][j%5]for j in range(20)]for i in range(20)]
|
||||
def pivots(A):
|
||||
a=[r[:]for r in A];p=[]
|
||||
for k in range(len(a)):
|
||||
d=a[k][k];p.append(d)
|
||||
for i in range(k+1,len(a)):
|
||||
for j in range(k+1,len(a)):a[i][j]-=a[i][k]*a[k][j]/d
|
||||
return p
|
||||
assert all(x>0 for x in pivots(C))
|
||||
assert all(x>0 for x in pivots([r[:19]for r in K[:19]]))
|
||||
assert all(sum(r)==0 for r in K)
|
||||
assert sum(map(sum,C))==2
|
||||
cc=[[F(2),F(1)],[F(1),F(2)]];kk=[[F(1),F(-1)],[F(-1),F(1)]]
|
||||
old=[F(0),F(0)]
|
||||
for expected,react in [(F(-1,5),F(24,5)),(F(1,25),F(36,25))]:
|
||||
new=[(2*(2*old[0]+old[1])-1)/5,F(1)]
|
||||
r=[2*sum(cc[i][j]*(new[j]-old[j])for j in range(2))+sum(kk[i][j]*new[j]for j in range(2))for i in range(2)]
|
||||
assert new[0]==expected and r==[0,react]
|
||||
assert 3*sum(new[j]-old[j]for j in range(2))==react/2
|
||||
old=new
|
||||
print("exact: C SPD 20/20; K rank19; K1=0; 1TC1=2; jump -1/5,1/25; Rc 24/5,36/25")
|
||||
|
||||
```
|
||||
|
||||
## C. Time predicate와 경계
|
||||
|
||||
```python
|
||||
|
||||
import math,random,struct
|
||||
from fractions import Fraction as F
|
||||
def input_cell(x):
|
||||
v=F(x);prev=F(math.nextafter(x,-math.inf))
|
||||
nxt=math.nextafter(x,math.inf)
|
||||
hi=(v+F(nxt))/2 if math.isfinite(nxt) else v+(v-prev)/2
|
||||
even=not(struct.unpack('>Q',struct.pack('>d',x))[0]&1)
|
||||
return (prev+v)/2,hi,even
|
||||
def cell_overlap(t,d,m):
|
||||
a,b,ca=input_cell(t);c,e,cb=input_cell(d);c*=m;e*=m
|
||||
lo=max(a,c);hi=min(b,e)
|
||||
return lo<hi or (lo==hi and (ca or (a<lo<b)) and (cb or (c<lo<e)))
|
||||
def dyadic_overlap(t,d,m):
|
||||
_,ex=math.frexp(t)
|
||||
factor=F(2)**(-ex)
|
||||
aa,bb,ca=input_cell(t);cc,ee,cb=input_cell(d)
|
||||
ints=[]
|
||||
for x in [aa,bb,cc,ee]:
|
||||
z=x*factor*2**88
|
||||
assert z.denominator==1
|
||||
ints.append(z.numerator)
|
||||
a,b,c,e=ints;c*=m;e*=m
|
||||
assert max(z.bit_length()for z in [a,b,c,e])<=122
|
||||
lo=max(a,c);hi=min(b,e)
|
||||
return lo<hi or (lo==hi and (ca or (a<lo<b)) and (cb or(c<lo<e)))
|
||||
def fm(a,b,c):return float(F(a)*F(b)+F(c))
|
||||
def grid_cell(t,d,inc=100):
|
||||
if not(math.isfinite(t)and math.isfinite(d)and t>0 and d>0 and type(inc)is int and 1<=inc<=2**32-1):return "input-error"
|
||||
if d>=t:return 1,False,t
|
||||
if F(t)/F(d)>inc+1:return "INC"
|
||||
_,e=math.frexp(t);q=math.ldexp(t,-e)/math.ldexp(d,-e);m=round(q)
|
||||
close=cell_overlap(t,d,m)
|
||||
assert close==dyadic_overlap(t,d,m)
|
||||
if close:n=m
|
||||
else:
|
||||
factor=F(2)**(-e+88);X=F(t)*factor;Y=F(d)*factor
|
||||
assert X.denominator==Y.denominator==1
|
||||
X=int(X);Y=int(Y);f=math.floor(q)
|
||||
if f*Y>X:f-=1
|
||||
elif (f+1)*Y<=X:f+=1
|
||||
assert f*Y<=X<(f+1)*Y
|
||||
n=f if X==f*Y else f+1
|
||||
if n>inc:return "INC"
|
||||
if not close:assert n==-(-F(t)//F(d))
|
||||
delta=d if close else fm(-(n-1),d,t)
|
||||
assert 0<delta<=d and math.isfinite(delta)
|
||||
assert (n-1)*d<t
|
||||
return n,close,delta
|
||||
pairs=[(10.,3.),(2.,3.),(.9,.3),(math.nextafter(.9,math.inf),.3),
|
||||
(5.351455173733616,.17262758624947144),
|
||||
(20*math.ulp(0.),6*math.ulp(0.)),(17*math.ulp(0.),5*math.ulp(0.)),
|
||||
(math.nextafter(math.inf,0.),math.nextafter(math.inf,0.)/3)]
|
||||
for t,d in pairs:print("input-cell grid",repr(t),repr(d),grid_cell(t,d))
|
||||
rng=random.Random(901)
|
||||
count=0
|
||||
for i in range(10000):
|
||||
m=rng.randint(2,2**32-1);d=math.ldexp(rng.uniform(.5,1),rng.randint(-1073,990))
|
||||
t=m*d
|
||||
if not(math.isfinite(t)and d>0):continue
|
||||
t=math.nextafter(t,math.inf if i%2 else -math.inf)
|
||||
if not math.isfinite(t):continue
|
||||
q=t/d
|
||||
if not math.isfinite(q)or q>2**32:continue
|
||||
mm=round(q)
|
||||
assert cell_overlap(t,d,mm)==dyadic_overlap(t,d,mm)
|
||||
count+=1
|
||||
print("input-cell/fixed-dyadic independent comparisons",count)
|
||||
assert grid_cell(5.351455173733616,.17262758624947144)[0]==31
|
||||
assert grid_cell(math.nextafter(.9,math.inf),.3)[0]==4
|
||||
assert grid_cell(20*math.ulp(0.),6*math.ulp(0.))[0]==3
|
||||
assert grid_cell(17*math.ulp(0.),5*math.ulp(0.))[0]==4
|
||||
print("INPUT-CELL ASSERTIONS PASSED")
|
||||
|
||||
for t,d in [(1.,.1),(math.ldexp(.9,-1000),math.ldexp(.3,-1000)),(math.ldexp(.9,1000),math.ldexp(.3,1000)),(1e-323,5e-324)]:
|
||||
print("input-cell scale",repr(t),repr(d),grid_cell(t,d))
|
||||
assert grid_cell(10.,3.,3)=="INC" and grid_cell(10.,3.,4)[0]==4
|
||||
assert grid_cell(float(2**32),1.,2**32-1)=="INC"
|
||||
for bad in [0,-1,1.5,2**32]:assert grid_cell(1.,.1,bad)=="input-error"
|
||||
for bad in [0.,-1.,math.inf,math.nan]:assert grid_cell(bad,.1)=="input-error"
|
||||
print("CURRENT TIME GRID ASSERTIONS PASSED")
|
||||
|
||||
```
|
||||
|
||||
## D. 입력 rounding-cell의 독립 반증 검색
|
||||
|
||||
고정 seed의 검색은 폐기된 arithmetic-only predicate와 입력 rounding-cell의 차이를
|
||||
검출한다. 이 출력은 predicate 실행 성공과 승인 시간 의미의 정합을 구별하기 위한
|
||||
반증 evidence다. 상세 판정은 numerical-review.md §8을 따른다.
|
||||
|
||||
```python
|
||||
|
||||
import math,random
|
||||
from fractions import Fraction as F
|
||||
def rad(x):return max(x-math.nextafter(x,-math.inf),math.nextafter(x,math.inf)-x)/2
|
||||
def pred(t,d,m):
|
||||
q=t/d;p=m*d
|
||||
B=math.nextafter(d*rad(q)+rad(p),math.inf)
|
||||
return abs(float(F(t)-m*F(d)))<=B,B
|
||||
rng=random.Random(41);found=[]
|
||||
for z in range(20000):
|
||||
d=rng.uniform(.125,.25);m=rng.randint(2,100);t=m*d
|
||||
for dr in [-1,1]:
|
||||
tt=math.nextafter(t,math.inf if dr>0 else -math.inf)
|
||||
loT=(F(tt)+F(math.nextafter(tt,-math.inf)))/2
|
||||
hiT=(F(tt)+F(math.nextafter(tt,math.inf)))/2
|
||||
loD=(F(d)+F(math.nextafter(d,-math.inf)))/2
|
||||
hiD=(F(d)+F(math.nextafter(d,math.inf)))/2
|
||||
overlap=max(loT,m*loD)<=min(hiT,m*hiD)
|
||||
ok,B=pred(tt,d,m)
|
||||
if overlap and not ok:
|
||||
found.append((tt,d,m,float(abs(F(tt)-m*F(d))),B));break
|
||||
if found:break
|
||||
print("input-cell overlap rejected by retired arithmetic predicate:",found)
|
||||
t=math.nextafter(.9,math.inf);d=.3;m=3
|
||||
print("specific .9 upper:",float(F(t)-m*F(d)),rad(t)+m*rad(d),"input-cell overlap",abs(F(t)-m*F(d))<=F(rad(t))+m*F(rad(d)))
|
||||
|
||||
```
|
||||
|
||||
## E. Library ULP 가정 없는 Fourier interval oracle
|
||||
|
||||
고정 dyadic 320-bit outward enclosure, Machin π, Taylor sin/cos/exp와 analytic
|
||||
remainder를 사용한다. Python Fraction은 검증 generator 전용이다. 출력 interval의
|
||||
outward binary64 hex endpoints를 C++ fixture에 고정할 수 있다. FESA solver와
|
||||
C++ std::sin/std::exp의 ULP 보장을 가정하지 않는다.
|
||||
|
||||
```python
|
||||
|
||||
from fractions import Fraction as F
|
||||
import math
|
||||
BITS=320;SCALE=1<<BITS
|
||||
def down(x):return F((x*SCALE).numerator//(x*SCALE).denominator,SCALE)
|
||||
def up(x):return -down(-x)
|
||||
def interval(a,b=None):return (down(F(a)),up(F(a if b is None else b)))
|
||||
def add(a,b):return down(a[0]+b[0]),up(a[1]+b[1])
|
||||
def neg(a):return -a[1],-a[0]
|
||||
def sub(a,b):return add(a,neg(b))
|
||||
def mul(a,b):
|
||||
v=[x*y for x in a for y in b];return down(min(v)),up(max(v))
|
||||
def div(a,b):
|
||||
assert b[0]>0 or b[1]<0
|
||||
return mul(a,(F(1)/b[1],F(1)/b[0]))
|
||||
def scale(a,c):return mul(a,interval(c))
|
||||
def atan_bounds(q):
|
||||
a=sum((F(-1)**j)*q**(2*j+1)/(2*j+1) for j in range(64))
|
||||
tail=q**129/129
|
||||
return a,a+tail
|
||||
a,b=atan_bounds(F(1,5)),atan_bounds(F(1,239))
|
||||
PI=interval(16*a[0]-4*b[1],16*a[1]-4*b[0])
|
||||
assert PI[1]-PI[0]<F(2)**-295
|
||||
def exneg(x):
|
||||
assert x[0]>=0
|
||||
if x[0]>=512:return interval(0,F(2)**-512)
|
||||
assert x[1]<=512
|
||||
y=scale(x,F(1,1024));term=interval(1);s=term
|
||||
for j in range(1,65):
|
||||
term=scale(mul(term,neg(y)),F(1,j));s=add(s,term)
|
||||
tail=F(1,2)**65/math.factorial(65)
|
||||
s=add(s,interval(-tail,tail))
|
||||
for _ in range(10):s=mul(s,s)
|
||||
return s
|
||||
def sincos_pi8(k):
|
||||
k%=16;quad=(k+2)//4;rem=k-4*quad
|
||||
x=scale(PI,F(rem,8));x2=mul(x,x)
|
||||
st=x;ss=x;ct=interval(1);cs=ct
|
||||
for j in range(1,32):
|
||||
st=scale(mul(st,neg(x2)),F(1,2*j*(2*j+1)));ss=add(ss,st)
|
||||
ct=scale(mul(ct,neg(x2)),F(1,(2*j-1)*2*j));cs=add(cs,ct)
|
||||
ss=add(ss,interval(-F(1,math.factorial(65)),F(1,math.factorial(65))))
|
||||
cs=add(cs,interval(-F(1,math.factorial(64)),F(1,math.factorial(64))))
|
||||
q=quad%4
|
||||
return [(ss,cs),(cs,neg(ss)),(neg(ss),neg(cs)),(neg(cs),ss)][q]
|
||||
def series_interval(t):
|
||||
Ts=[interval(1)for _ in range(5)];qs=[interval(0)for _ in range(5)];E=interval(1)
|
||||
for m in range(80):
|
||||
odd=2*m+1
|
||||
x=scale(mul(PI,PI),F(t)*odd*odd/4);dec=exneg(x)
|
||||
for j in range(5):
|
||||
si,co=sincos_pi8(odd*j)
|
||||
Ts[j]=sub(Ts[j],scale(div(mul(si,dec),PI),F(4,odd)))
|
||||
qs[j]=add(qs[j],scale(mul(co,dec),2))
|
||||
E=sub(E,scale(div(dec,mul(PI,PI)),F(8,odd*odd)))
|
||||
assert max(hi-lo for lo,hi in Ts+qs+[E])<F(2)**-270
|
||||
# Uniform analytic tail bound, using safe r upper at minimum time.
|
||||
beta=scale(mul(PI,PI),F(t)/4)
|
||||
first=exneg(scale(beta,161*161))
|
||||
rr=exneg(scale(beta,8*81))
|
||||
tailq=div(scale(first,2),sub(interval(1),rr))[1]
|
||||
tailt=div(scale(first,4),scale(mul(PI,sub(interval(1),rr)),161))[1]
|
||||
Ts=[add(v,interval(-tailt,tailt))for v in Ts]
|
||||
qs=[add(v,interval(-tailq,tailq))for v in qs]
|
||||
E=add(E,interval(-tailt,tailt))
|
||||
return Ts,qs,E,tailt,tailq
|
||||
for t in [.001,.01,.05,.1,.5,1.]:
|
||||
Ts,qs,ee,tt,tq=series_interval(t)
|
||||
assert tt<F(1,10**27) and tq<F(1,10**27)
|
||||
# Certified brackets can be exported as outward binary64 hex endpoints for C++ fixtures.
|
||||
width=max(float(hi-lo)for lo,hi in Ts+qs+[ee])
|
||||
assert width<1e-26
|
||||
print("Fourier certified",t,"max-width",width,"tailT",float(tt),"tailq",float(tq),
|
||||
"E bracket",math.nextafter(float(ee[0]),-math.inf).hex(),math.nextafter(float(ee[1]),math.inf).hex())
|
||||
print("FOURIER INTERVAL ASSERTIONS PASSED")
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user