From 43867d0b3d33d5969f1b68bc79d0966005d9c991 Mon Sep 17 00:00:00 2001 From: "KOKO\\Mimi" Date: Sun, 18 Oct 2026 15:06:44 +0900 Subject: [PATCH] add documents --- AGENTS.md | 34 +++- CLAUDE.md | 34 +++- docs/architecture.md | 48 ++++++ docs/business-rules.md | 80 ++++++++++ docs/contracts.md | 107 +++++++++++++ docs/engineering-notes.md | 58 +++++++ docs/operations.md | 150 ++++++++++++++++++ docs/security.md | 37 +++++ docs/standards.md | 55 +++++++ docs/tracking/decisions/0001-input-subset.md | 17 ++ .../decisions/0002-typed-ownership.md | 18 +++ .../decisions/0003-ordered-reduction.md | 17 ++ .../decisions/0004-candidate-output.md | 19 +++ .../decisions/0005-eigen-comparison.md | 18 +++ .../decisions/0006-thermal-diagnostic.md | 17 ++ .../decisions/0007-local-build-paths.md | 18 +++ docs/tracking/decisions/0008-shell-inertia.md | 20 +++ docs/tracking/decisions/0009-hex8-numerics.md | 21 +++ .../decisions/0010-thermal-discretization.md | 19 +++ docs/tracking/decisions/index.md | 14 ++ docs/tracking/findings.md | 59 +++++++ docs/tracking/status.md | 63 ++++++++ 22 files changed, 913 insertions(+), 10 deletions(-) create mode 100644 docs/architecture.md create mode 100644 docs/business-rules.md create mode 100644 docs/contracts.md create mode 100644 docs/engineering-notes.md create mode 100644 docs/operations.md create mode 100644 docs/security.md create mode 100644 docs/standards.md create mode 100644 docs/tracking/decisions/0001-input-subset.md create mode 100644 docs/tracking/decisions/0002-typed-ownership.md create mode 100644 docs/tracking/decisions/0003-ordered-reduction.md create mode 100644 docs/tracking/decisions/0004-candidate-output.md create mode 100644 docs/tracking/decisions/0005-eigen-comparison.md create mode 100644 docs/tracking/decisions/0006-thermal-diagnostic.md create mode 100644 docs/tracking/decisions/0007-local-build-paths.md create mode 100644 docs/tracking/decisions/0008-shell-inertia.md create mode 100644 docs/tracking/decisions/0009-hex8-numerics.md create mode 100644 docs/tracking/decisions/0010-thermal-discretization.md create mode 100644 docs/tracking/decisions/index.md create mode 100644 docs/tracking/findings.md create mode 100644 docs/tracking/status.md diff --git a/AGENTS.md b/AGENTS.md index e9a15d3..4d092d7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # FESA Structural Solver -FESA는 개인 연구를 위해 개발하는 유한요소 구조해석 솔버이며 외부 사용자 배포를 장기 +FESA는 로컬에서 실행하는 개인 연구용 유한요소 구조해석 솔버이며 외부 사용자 배포를 장기 목표로 한다. C++17 이상·Windows MSVC·직접 MSBuild와 CMake/CTest를 사용하고 승인된 Abaqus 입력 subset에서 재현 가능한 해석과 HDF5 결과를 제공한다. 코드 존재와 기능 검증 완료는 다르다. @@ -12,6 +12,28 @@ subset에서 재현 가능한 해석과 HDF5 결과를 제공한다. 코드 존 ├── CLAUDE.md → 같은 내용의 작업 진입점 ├── docs/ │ ├── README.md → 기능별 기술 요약 색인 +│ ├── architecture.md → 구성 요소·의존 방향·실행 흐름 +│ ├── business-rules.md → 물리량·상태 전이·수치 판정 규칙 +│ ├── security.md → 로컬 실행·파일 보호·권한 경계 +│ ├── standards.md → 개발·의존성·검증의 필수 기준 +│ ├── engineering-notes.md → 재현된 함정과 대응 방법 +│ ├── operations.md → 환경 준비·빌드·실행·검사 절차 +│ ├── contracts.md → CLI·입력·결과·실패의 외부 계약 +│ ├── tracking/ +│ │ ├── status.md → 구현과 실제 검증 상태 +│ │ ├── decisions/ → 대안·선택 이유·영향 +│ │ │ ├── index.md → 결정 기록 목록 +│ │ │ ├── 0001-input-subset.md → 입력 표기와 알고리즘 구분 +│ │ │ ├── 0002-typed-ownership.md → 정의와 실행 상태 소유권 +│ │ │ ├── 0003-ordered-reduction.md → 병렬 누적 순서 +│ │ │ ├── 0004-candidate-output.md → 검증 뒤 최종 파일 공개 +│ │ │ ├── 0005-eigen-comparison.md → 한정된 고유치 비교 예외 +│ │ │ ├── 0006-thermal-diagnostic.md → NT11 진단 분류 +│ │ │ ├── 0007-local-build-paths.md → 두 빌드 경로와 로컬 의존성 +│ │ │ ├── 0008-shell-inertia.md → Shell 질량 영공간 +│ │ │ ├── 0009-hex8-numerics.md → Hex8 강성·질량·정밀도 +│ │ │ └── 0010-thermal-discretization.md → 두께 온도와 시간적분 +│ │ └── findings.md → 재현 조건과 해결하지 못한 문제 │ ├── development-context.md → 읽기 범위와 컨텍스트 예상량 │ ├── solver-core/README.md → 공통 구조·I/O·수치 기준·빌드 방법 │ └── / → 기능 요약과 formulation 원문 @@ -64,6 +86,8 @@ subset에서 재현 가능한 해석과 HDF5 결과를 제공한다. 코드 존 ## 작업 전 확인 먼저 [기능 색인](docs/README.md), 변경할 기능의 README와 해당 영역의 AGENTS.md를 확인한다. +공통 개발 기준은 [standards](docs/standards.md), 재현된 함정은 +[engineering-notes](docs/engineering-notes.md)에서 확인한다. [솔버 공통 요약](docs/solver-core/README.md)은 아래 변경 성격에 해당하는 절을 읽는다. 색인의 다른 기능·연구 이력·대형 이관 자료를 일괄 필독으로 확장하지 않는다. 같은 문맥에서 읽고 바뀌지 않은 자료는 다시 읽지 않는다. @@ -72,6 +96,7 @@ Public header 변경은 대응하는 src 영역의 책임과 consumer까지 확 - 범위·physics·절차 변경: 기능 요약의 채택 범위·구현 한계와 관련 formulation 절의 유도·가정·검증 요구를 함께 확인한다. - 입력·결과·비교 변경: 공통 I/O·수치 기준과 해당 기능의 identity·reference mapping을 확인한다. + 외부 호출·schema 변경은 contracts, 로컬 파일 권한·공유 변경은 security도 확인한다. - C++ 구현: 공통 요약의 코딩 규약, 해당 영역 지침과 행동을 검증할 검사를 확인한다. - 빌드 변경: 실제 preset·target graph·dependency와 명령의 side effect를 실행 전에 확인한다. - 기능 재개: 해당 기능 요약의 현재 구현·검증·미해결 범위를 대조한다. @@ -89,7 +114,8 @@ Public header 변경은 대응하는 src 영역의 책임과 consumer까지 확 근거와 영향을 알린다. 자동으로 tolerance를 완화하거나 데이터를 복구·보정하지 않는다. 나머지 문제는 현재 owner가 관련 범위에서 해결한다. 지금 해결할 수 없는 문제는 재현 조건, -영향, 해결하지 못하는 이유와 다음 접근을 해당 기능 요약의 미해결 항목에 기록한다. +영향, 해결하지 못하는 이유와 다음 접근을 docs/tracking/findings.md에 기록한다. +기능별 요약의 기존 기술적 한계도 함께 일치시킨다. 새 근거나 변경 없이 같은 명령·agent 호출을 반복하지 않는다. 문서만 변경하면 정적 검토를 하고 build/test를 실행하지 않는다. 동작 변경은 관련 검사부터, @@ -98,7 +124,5 @@ Public header 변경은 대응하는 src 영역의 책임과 consumer까지 확 직접 MSBuild가 주 개발 빌드이며 CMake/Ninja는 같은 제품·검사 source를 사용하는 보조 경로다. 실제 명령·환경·`.build/native/Debug` 및 `.build/cmake-debug` 출력은 solver-core를 따른다. 두 경로의 전체 검사 등록과 실제 실행 범위를 구분하고 별도 Python·reference 결과를 기록한다. -2026-10-18 병합의 한정 검증 결과와 미검증 범위는 -[병합 현황](docs/cpp-object-oriented-modular-refactoring/README.md#병합-결과와-검증-범위)을 따른다. -당시 한정 실행으로 이후 일반 솔버 기능의 전체 검증 의무를 대체하지 않는다. +과거 작업의 한정 실행으로 이후 일반 솔버 기능의 전체 검증 의무를 대체하지 않는다. `reference/temp`는 검증에 사용하지 않는다. 정식 자료 누락은 미완료로 기록하고 통과로 바꾸지 않는다. diff --git a/CLAUDE.md b/CLAUDE.md index e9a15d3..4d092d7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # FESA Structural Solver -FESA는 개인 연구를 위해 개발하는 유한요소 구조해석 솔버이며 외부 사용자 배포를 장기 +FESA는 로컬에서 실행하는 개인 연구용 유한요소 구조해석 솔버이며 외부 사용자 배포를 장기 목표로 한다. C++17 이상·Windows MSVC·직접 MSBuild와 CMake/CTest를 사용하고 승인된 Abaqus 입력 subset에서 재현 가능한 해석과 HDF5 결과를 제공한다. 코드 존재와 기능 검증 완료는 다르다. @@ -12,6 +12,28 @@ subset에서 재현 가능한 해석과 HDF5 결과를 제공한다. 코드 존 ├── CLAUDE.md → 같은 내용의 작업 진입점 ├── docs/ │ ├── README.md → 기능별 기술 요약 색인 +│ ├── architecture.md → 구성 요소·의존 방향·실행 흐름 +│ ├── business-rules.md → 물리량·상태 전이·수치 판정 규칙 +│ ├── security.md → 로컬 실행·파일 보호·권한 경계 +│ ├── standards.md → 개발·의존성·검증의 필수 기준 +│ ├── engineering-notes.md → 재현된 함정과 대응 방법 +│ ├── operations.md → 환경 준비·빌드·실행·검사 절차 +│ ├── contracts.md → CLI·입력·결과·실패의 외부 계약 +│ ├── tracking/ +│ │ ├── status.md → 구현과 실제 검증 상태 +│ │ ├── decisions/ → 대안·선택 이유·영향 +│ │ │ ├── index.md → 결정 기록 목록 +│ │ │ ├── 0001-input-subset.md → 입력 표기와 알고리즘 구분 +│ │ │ ├── 0002-typed-ownership.md → 정의와 실행 상태 소유권 +│ │ │ ├── 0003-ordered-reduction.md → 병렬 누적 순서 +│ │ │ ├── 0004-candidate-output.md → 검증 뒤 최종 파일 공개 +│ │ │ ├── 0005-eigen-comparison.md → 한정된 고유치 비교 예외 +│ │ │ ├── 0006-thermal-diagnostic.md → NT11 진단 분류 +│ │ │ ├── 0007-local-build-paths.md → 두 빌드 경로와 로컬 의존성 +│ │ │ ├── 0008-shell-inertia.md → Shell 질량 영공간 +│ │ │ ├── 0009-hex8-numerics.md → Hex8 강성·질량·정밀도 +│ │ │ └── 0010-thermal-discretization.md → 두께 온도와 시간적분 +│ │ └── findings.md → 재현 조건과 해결하지 못한 문제 │ ├── development-context.md → 읽기 범위와 컨텍스트 예상량 │ ├── solver-core/README.md → 공통 구조·I/O·수치 기준·빌드 방법 │ └── / → 기능 요약과 formulation 원문 @@ -64,6 +86,8 @@ subset에서 재현 가능한 해석과 HDF5 결과를 제공한다. 코드 존 ## 작업 전 확인 먼저 [기능 색인](docs/README.md), 변경할 기능의 README와 해당 영역의 AGENTS.md를 확인한다. +공통 개발 기준은 [standards](docs/standards.md), 재현된 함정은 +[engineering-notes](docs/engineering-notes.md)에서 확인한다. [솔버 공통 요약](docs/solver-core/README.md)은 아래 변경 성격에 해당하는 절을 읽는다. 색인의 다른 기능·연구 이력·대형 이관 자료를 일괄 필독으로 확장하지 않는다. 같은 문맥에서 읽고 바뀌지 않은 자료는 다시 읽지 않는다. @@ -72,6 +96,7 @@ Public header 변경은 대응하는 src 영역의 책임과 consumer까지 확 - 범위·physics·절차 변경: 기능 요약의 채택 범위·구현 한계와 관련 formulation 절의 유도·가정·검증 요구를 함께 확인한다. - 입력·결과·비교 변경: 공통 I/O·수치 기준과 해당 기능의 identity·reference mapping을 확인한다. + 외부 호출·schema 변경은 contracts, 로컬 파일 권한·공유 변경은 security도 확인한다. - C++ 구현: 공통 요약의 코딩 규약, 해당 영역 지침과 행동을 검증할 검사를 확인한다. - 빌드 변경: 실제 preset·target graph·dependency와 명령의 side effect를 실행 전에 확인한다. - 기능 재개: 해당 기능 요약의 현재 구현·검증·미해결 범위를 대조한다. @@ -89,7 +114,8 @@ Public header 변경은 대응하는 src 영역의 책임과 consumer까지 확 근거와 영향을 알린다. 자동으로 tolerance를 완화하거나 데이터를 복구·보정하지 않는다. 나머지 문제는 현재 owner가 관련 범위에서 해결한다. 지금 해결할 수 없는 문제는 재현 조건, -영향, 해결하지 못하는 이유와 다음 접근을 해당 기능 요약의 미해결 항목에 기록한다. +영향, 해결하지 못하는 이유와 다음 접근을 docs/tracking/findings.md에 기록한다. +기능별 요약의 기존 기술적 한계도 함께 일치시킨다. 새 근거나 변경 없이 같은 명령·agent 호출을 반복하지 않는다. 문서만 변경하면 정적 검토를 하고 build/test를 실행하지 않는다. 동작 변경은 관련 검사부터, @@ -98,7 +124,5 @@ Public header 변경은 대응하는 src 영역의 책임과 consumer까지 확 직접 MSBuild가 주 개발 빌드이며 CMake/Ninja는 같은 제품·검사 source를 사용하는 보조 경로다. 실제 명령·환경·`.build/native/Debug` 및 `.build/cmake-debug` 출력은 solver-core를 따른다. 두 경로의 전체 검사 등록과 실제 실행 범위를 구분하고 별도 Python·reference 결과를 기록한다. -2026-10-18 병합의 한정 검증 결과와 미검증 범위는 -[병합 현황](docs/cpp-object-oriented-modular-refactoring/README.md#병합-결과와-검증-범위)을 따른다. -당시 한정 실행으로 이후 일반 솔버 기능의 전체 검증 의무를 대체하지 않는다. +과거 작업의 한정 실행으로 이후 일반 솔버 기능의 전체 검증 의무를 대체하지 않는다. `reference/temp`는 검증에 사용하지 않는다. 정식 자료 누락은 미완료로 기록하고 통과로 바꾸지 않는다. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..4cd646b --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,48 @@ +# 구성과 실행 흐름 + +FESA는 로컬 파일을 읽어 구조·열 해석을 수행하고 결과 파일을 쓰는 단일 프로세스 솔버다. +사용자 계정 서버·원격 저장소·외부 해석 서비스가 실행 경로에 끼어 있지 않다. +Abaqus 입력 표기는 의미 모델로 변환하는 경계이며 Abaqus의 요소·적분·알고리즘을 +내부 구현으로 가져오는 경계가 아니다. + +## 구성 요소와 의존 방향 + +| 영역 | 소유하는 것 | 의존 방향과 넘기지 않는 것 | +| --- | --- | --- | +| app | 인자·출력 경로·파일 점유·객체 수명·진단 출력 | 입력 준비 → 해석 선택 → 완료 결과 저장을 조합한다. 물리식을 결정하지 않는다. | +| io/abaqus | 원문·문법·모델 의미 변환 | source identity를 가진 Domain을 만든다. equation·해·vendor resource를 만들지 않는다. | +| core | source identity·ASCII 처리·공통 실패 값 | 다른 계층의 공통 값이다. procedure별 입력 의미를 default로 넣지 않는다. | +| model | node·element·set·step·geometry 정의 | properties·materials·loads의 의미 정의를 연결한다. 실행 중 해와 equation을 저장하지 않는다. | +| properties·materials·loads | 단면·구성 관계·하중 의미 | 요소에 필요한 정의와 local 응답을 제공한다. 전역 누적과 수렴을 소유하지 않는다. | +| elements | local 강성·내력·관성·열전도·복구용 응답 | 정의와 trial 값을 받아 typed 응답을 반환한다. 전역 sparse matrix와 파일을 쓰지 않는다. | +| fem·constraints | DOF·equation·pattern·partition·지정값 적용 | local 응답과 전역 방정식 사이의 mapping을 소유한다. node나 backend가 번호를 따로 발급하지 않는다. | +| assembly | local contribution의 전역 누적 | worker별 계산을 모은 뒤 정해진 순서로 reduction한다. equation 소유권을 가져오지 않는다. | +| analysis | procedure·trial·수렴·accepted history | model view·assembly·solver·recovery를 조정한다. 영속 schema와 vendor handle을 공개 state에 넣지 않는다. | +| math·solvers | 수치 storage·분해·선형해·고유치 | MKL PARDISO·FEAST·BLAS는 private adapter로 연결한다. 모델을 수정해 수치 실패를 덮지 않는다. | +| results | 위치·좌표·단위·부호를 가진 복구 결과 | 검증된 typed 결과를 만든다. 비교 원본이나 HDF5 layout에 맞춘 보정을 하지 않는다. | +| io/hdf5 | 직렬화·재개방 검사·최종 파일 교체 | HDF5 C handle을 격리한다. 완료되지 않은 trial을 정상 결과로 공개하지 않는다. | + +공개 선언은 `include/fesa`, 구현은 `src/fesa`에 있다. 공개 값과 실패 계약은 +vendor-neutral이다. TBB 병렬 실행과 Windows 파일 연산도 구현 경계에 머문다. +시험 실행기와 Python 비교기는 제품 실행 흐름 바깥의 consumer다. + +## 입력 한 건의 수명 + +1. App이 입력의 lexical 경로에서 결과·로그 경로를 만들고 출력 쌍의 lease를 얻는다. +2. 입력을 한 번 읽고 문법과 의미를 검사하여 source identity를 보존한 Domain을 만든다. +3. 준비된 Domain에서 해석 family 하나를 선택한다. AnalysisModel은 Domain을 빌려 보는 + view이므로 Domain과 주입된 solver·parallel·log adapter가 실행보다 오래 살아야 한다. +4. DofManager가 방정식과 pattern을 만들고 local 계산 결과를 안정된 순서로 조립한다. + Procedure가 해법과 trial을 조정하고 검증을 마친 candidate만 accepted state로 반영한다. +5. 완료된 family의 typed outcome을 반환한다. App이 로그 close 성공을 확인한 뒤 해당 + 결과 writer를 선택한다. Writer 누락을 다른 family로 변환하여 처리하지 않는다. +6. Writer가 별도 candidate 파일을 기록·close·재개방 검사한다. 모든 검사가 끝난 뒤 + 최종 경로를 교체한다. Accepted state의 commit과 최종 파일 공개는 별도 실패 경계다. + +## 빌드와 외부 의존 + +직접 관리하는 MSVC solution이 주 개발 경로이고 CMake/Ninja는 같은 제품·검사 source를 +사용하는 보조 경로다. 두 경로 모두 같은 solver library를 CLI와 세 검사 실행기에 연결한다. +MKL은 ILP64·dynamic·Intel threading, TBB는 local 병렬 실행, HDF5는 결과 저장을 담당한다. +GoogleTest는 승인된 로컬 source checkout을 사용한다. 의존성 탐색과 runtime DLL 배치는 +별도 책임이므로 link 성공만으로 실행 환경이 완성되지 않는다. diff --git a/docs/business-rules.md b/docs/business-rules.md new file mode 100644 index 0000000..db73b5d --- /dev/null +++ b/docs/business-rules.md @@ -0,0 +1,80 @@ +# 물리와 판정 규칙 + +## 식별과 해석 범위 + +Source의 instance·label·step·point는 내부 배열 index나 equation 번호와 다르다. +다른 instance의 같은 label을 합치거나 결과 위치가 가깝다는 이유로 대응시키지 않는다. +입력 표기 `S4/S4R`은 내부 MITC4로 연결되며 Abaqus 적분법 선택을 뜻하지 않는다. +`LANCZOS` 표기를 수용해도 실제 고유치 계산은 MKL FEAST다. + +현재 구조해석은 B33 beam, MITC4 shell, C3D8 solid의 승인된 procedure별 subset이다. +열해석은 DS4 shell의 단일 비연성 과도 열전달이다. 지원하지 않는 조합은 명시적으로 +실패하며 가장 비슷한 요소·하중·물성으로 바꾸지 않는다. 현재 subset 밖이라는 사실은 +향후 기능 추가를 영구적으로 금지하는 물리 법칙이 아니다. +사용자가 일관된 단위를 제공한다. 입력 숫자에서 SI 단위를 추정하거나 자동 변환하지 않는다. + +## 평형과 상태 전이 + +선형 정적은 지정값 기여를 포함한 `Kff*df=Ff-Kfc*dc`를 풀고 전체 해를 복원한다. +반력은 같은 full residual `K*d-F`의 constrained 성분이다. Free residual은 평형 검증량이며 +이를 반력으로 비교하지 않는다. 모든 DOF가 지정된 유효 모델의 빈 free system은 허용한다. +자유 방정식의 특이성을 penalty나 임의 대각 성분으로 없애지 않는다. + +비선형·동해석에서 같은 trial의 geometry·힘·접선을 사용한다. 수렴·finite·복구·해당 +procedure의 검증을 모두 통과한 candidate만 accepted state와 history를 갱신한다. +실패한 trial은 accepted frame이 아니며 일부 cache·chart·rate만 다음 증분에 남기지 않는다. +전체 해석 또는 결과 저장이 실패하면 기존 최종 HDF5를 보존한다. + +## 요소·하중별 구분 + +- B33는 작은 변형·회전의 직선 Euler beam이다. Endpoint outward action과 + positive-local-x 단면력은 부호·위치가 다르며 공유 node에서 평균하지 않는다. +- MITC4의 physical 응답과 numerical drilling 안정화는 별도다. Drilling energy를 + physical stress로 복구하지 않고 artificial inertia로 질량 영공간을 없애지 않는다. + Centered shell의 막력 계수는 두께에, 굽힘 계수는 두께 세제곱에 비례한다. +- Shell 정적 압력은 `SPOS=+1`, `SNEG=-1`일 때 oriented area vector `a`에 대해 + `-lambda*p*s*a`다. 양의 압력은 선택한 면의 외향 법선 반대 방향이다. 선형은 reference, + 비선형은 current geometry를 쓰고 Newton tangent는 `Kint-dFext/dq`다. 비대칭 항을 버리지 않는다. + 같은 side의 중복 facet은 경고 후 하나로 처리하고 양쪽 side 충돌은 실패한다. + 중복 DSLOAD 행은 각각 더한다. +- Hex8은 점별 deviatoric energy와 volume-weighted mean volumetric energy를 사용한다. + 이를 center 값·unweighted mean·Fbar로 대체하지 않는다. 질량은 BC 축소 전 reference + consistent matrix의 row-sum이며 warped 요소의 node별 값을 `rho*V/8`로 통일하지 않는다. +- Shell 고유치의 finite 공간은 실제 BC를 적용한 뒤 analytic mass null과 free 공간의 + 교집합을 제거하여 만든다. Partial rotational BC를 full clamp로 바꾸지 않는다. + Interval 안의 전체 반환 고유쌍을 검증한 뒤 요청한 lowest N만 공개한다. N 밖의 실패를 버리지 않는다. +- 현재 shell HHT는 nodal-lumped-kinetic 질량과 reduced-coordinate 적분을 사용한다. + Physical acceleration, 공개 auxiliary acceleration, private 적분 이력은 서로 다르다. + 공개 결과의 rate 조합만으로 private history나 restart를 재구성하지 않는다. +- Hex8 HHT의 high+low 상태는 다음 accepted state까지 보존한다. 저장되는 F64는 전체 값의 + 반올림 관측값이며 이것을 내부 전체 상태와 같다고 가정하지 않는다. +- DS4는 node당 다섯 두께 온도점을 결합한다. Consistent capacity와 Backward Euler를 + 사용하며 음수 온도를 clamp하지 않는다. Raw 초기 온도를 보존하고 지정온도는 첫 양의 + 시점부터 적용한다. 반력은 열저장까지 포함한 full residual의 constrained projection이다. + 중앙면 양쪽 flux trace는 서로 다른 위치이며 평균하지 않는다. + +## 외부 수치 비교 + +먼저 source identity·row 집합·component·schema·단위·좌표·위치와 finite 여부를 검사한다. +Missing·extra·duplicate·NaN·Inf는 허용치 계산 전 실패다. Warning-only 비교에도 이 검사는 필수다. + +Family는 같은 case·step/frame·논리 물리량·단위 차원·좌표계·판정 영향으로 묶는다. +Reference만으로 `S=max(abs(r_i))`, `B=0.01*S`를 구한다. +`abs(r_i)<=B`인 행은 `abs(f_i-r_i)<=B`, 나머지는 상대오차 `<=0.05`를 요구한다. +모든 행 조건과 `sqrt(mean((f-r)^2))/S<=0.01`을 함께 만족해야 한다. +`S=0`이면 FESA 값도 모두 exact zero여야 한다. 별도 absolute floor나 `max(1,S)`는 없다. + +MITC4 정적·비선형·shell HHT의 U는 blocking, UR의 수치 차이는 warning-only다. +Review-only RF/RM이나 외부 비교 대상이 아닌 stress를 통과로 집계하지 않는다. +Hex8 정적 U·constrained RF·점별 S는 각각 blocking이며 free RF를 residual과 비교하지 않는다. + +2026-09-10 승인된 `mitc4-eigen-first-implementation`만 source modal frame별 singleton +Value의 행 상대오차와 RMS를 각각 5%로 검사한다. Near-zero·zero-scale·사전검사와 내부 +고유쌍 residual·정규화·직교성 `1e-10`은 유지한다. 이 예외를 Hex8 고유치에 확대하지 않는다. +기존 thermal NT11 비교는 불일치를 보존하는 diagnostic/nonblocking이며 외부 수치 PASS가 아니다. + +내부 평형 허용치를 하나로 통합하지 않는다. 선형 정적 normalized free residual과 +force/moment balance는 `1e-10`이다. 비선형 shell 정적 accepted free residual은 matching +external scale이 nonzero면 상대 `1e-2`, exact-zero면 force 또는 force-length 차원의 +absolute `1e-3`이고 factor-one 전역 force/moment balance는 각각 normalized `1e-8`이다. +HHT의 잔차·시간수렴, thermal 잔차 인증은 해당 물리량과 산술 의미를 보존하여 별도로 판정한다. diff --git a/docs/contracts.md b/docs/contracts.md new file mode 100644 index 0000000..b8b2a0c --- /dev/null +++ b/docs/contracts.md @@ -0,0 +1,107 @@ +# 외부 이용 계약 + +## CLI와 파일 + +호출은 `fesa.exe `의 한 입력뿐이다. 빈 인자·추가 인자·option·`.inp` 외 확장자는 +거부한다. 확장자의 대소문자는 구별하지 않으며 `--output`은 받지 않는다. +상대 경로는 호출 cwd 기준으로 lexical normalization한다. Symlink·junction·short name을 +resolve하여 출력 위치를 바꾸지 않는다. + +입력의 lexical sibling에 `_results.h5`와 `_log.txt`를 만든다. +결과 경로에 `.fesa.lock`을 붙인 lease가 같은 출력의 동시 쓰기를 막는다. +Lease는 handle 종료 때 삭제되며 생성 실패·점유는 저장 실패다. 정상 candidate의 기록·검사· +close 뒤 최종 HDF5를 교체한다. 중간 실패에서는 이전 최종 HDF5를 보존한다. +로그는 실패 시에도 갱신될 수 있으므로 HDF5 존재만으로 이번 실행 성공을 판단하지 않는다. + +| Exit | 이용자에게 보이는 결과 | +| ---: | --- | +| 0 | 선택 해석과 최종 저장 성공. Warning이 남을 수 있다. | +| 2 | 인자 또는 입력 확장자 오류. | +| 3 | 읽기·문법·미지원 입력 실패. | +| 4 | 모델 의미·조합·유효성 실패. | +| 5 | 해법 실패. | +| 6 | Lease·로그·HDF5 저장 실패. | + +stderr 진단은 결정적 순서의 tab 구분 `severity=...`, `code=...`, `file=...`, `line=...`, +`keyword=...`, `entity_identity=...`, `message=...` 필드다. 빈 source 필드도 남긴다. +Backend 고유 번호를 CLI exit로 직접 반환하지 않는다. + +## 입력 파일 + +Physical `.inp` 하나를 읽는다. 종결자 제외 한 줄 256 ASCII bytes 이내이며 printable ASCII와 +tab, LF/CRLF·빈 줄·`**` comment·keyword parameter continuation을 처리한다. +Keyword·parameter·enum·name lookup은 ASCII case-insensitive지만 원문·행 번호를 보존한다. +같은 값이라도 중복 parameter는 거부하며 comma 사이의 빈 field를 지우지 않는다. + +현재 identity instance의 part/assembly와 단일 step을 기본으로 한다. INCLUDE·instance transform· +contact·MPC·비탄성·beam/shell 또는 shell/solid 혼합은 공개 subset 밖이다. +미지원 model-affecting keyword를 조용히 무시하지 않는다. 출력 요청의 warning no-op은 +procedure별 allowlist에 한정하며 mandatory 결과를 선택·억제하는 수단으로 사용하지 않는다. + +| Family | 현재 입력의 요점 | 거부하는 대표 사례 | +| --- | --- | --- | +| B33 정적 | GENERAL section·등방 탄성·DOF1–6 BC와 CLOAD | B31·I12 비영·beam DLOAD | +| MITC4 정적 | S4/S4R·centered 일정 두께·등방 탄성·DOF1–6 | Composite·offset·drill 방향 aggregate nodal moment | +| MITC4 비선형 정적 | NLGEOM=YES·단일 STATIC·time period=1·고정 증분 | 자동 cutback·amplitude·restart | +| Shell pressure | Assembly-level ELEMENT SURFACE의 SPOS/SNEG와 signed DSLOAD P | DLOAD·edge/body·unknown parameter·dynamic/thermal로 전용 | +| Shell frequency | 양의 DENSITY·homogeneous shell·MASS normalization·양의 정수 N | 비영 BC·load·nonempty bounds/shift·preload | +| Shell HHT | NLGEOM=YES·DYNAMIC DIRECT·영 BC/초기값·일정 global 병진 CLOAD | 회전 CLOAD·follower·시간변화 BC·restart | +| Hex8 | Solid-only C3D8·SOLID SECTION·DOF1–3·frequency/HHT의 양의 DENSITY | 비영 회전 BC·값 0을 포함한 회전 CLOAD | +| DS4 thermal | 일정 양의 두께·k/rho/c·단일 HEAT TRANSFER·온도 초기값·DOF11/15 BC와 CFLUX | 내부 station 직접 BC/CFLUX·시간변화·열구조 연성 | + +Shell HHT schedule은 `double(N)*h==T`, `N<=INC`를 만족하는 고정 격자이며 INC 기본값은 +100이다. Hex8 HHT는 TABULAR step-time relative CLOAD amplitude의 선형 보간과 끝값 유지를 +지원하지만 static/BC amplitude·TOTAL TIME·smoothing으로 확대하지 않는다. +Thermal은 마지막 간격만 줄이며 `dt>T_end`면 한 증분이다. 서로 다른 시각 계약을 같은 +반올림 규칙으로 통합하지 않는다. + +## 결과 식별과 위치 + +HDF5는 feature identity·version·procedure를 조합하여 읽는다. 숫자는 fixed-width +little-endian, 문자열은 UTF-8이다. Compound는 field 이름·형식·extent로 읽으며 C++ +구조체 padding에 의존하지 않는다. Source input identity는 실제 읽은 bytes에 결속된다. +Node row를 source label로 보지 않고 model의 source inventory로 대응시킨다. + +`Step-1`은 storage slot이며 입력 step 이름이 아니다. Frequency source step은 step +attribute, HHT·thermal은 metadata에서 읽는다. 기존 static에 source step 이름이 별도 +저장됐다고 가정하지 않는다. + +| Family | 식별과 공개 결과 | +| --- | --- | +| Linear static | Schema0은 `analysis_procedure`가 없어도 유효하다. `/steps/Step-1/frames/0`에 nodal displacement/reaction과 요소별 복구량을 둔다. | +| Nonlinear shell static | Schema1. Accepted frame과 load factor·nodal displacement/reaction·4 GP shell 복구량을 둔다. 실패 iteration은 frame이 아니다. | +| Shell frequency | Schema0과 `eigen_schema_version=1`, procedure=`linear-frequency`. `/steps/Step-1/eigen/modes`는 ID·raw eigenvalue·classification·cluster를 갖고 vectors는 `[N,node,6]`이다. 검증량은 공개 N 밖을 포함한 전체 반환 pair를 대상으로 한다. | +| Shell HHT | Feature/procedure=`hht-implicit-dynamics`, schema2. Metadata의 mass=`nodal-lumped-kinetic`, time integration=`reduced-coordinate-HHT-with-physical-rate-reconstruction`, acceleration=`physical-endpoint-and-auxiliary-separated`를 확인한다. | +| Hex8 | Feature=`hex8-structural-analysis`, schema1, mass=`lumped-reference`. Nodal 성분은 UX/UY/UZ 3개, stress/strain은 `[E,8,6]`, eigen vectors는 `[modes,N,3]`이다. | +| DS4 thermal | Feature=`shell-transient-heat-transfer`, schema1, procedure=`uncoupled-transient-heat-transfer`. Temperature `[N,5]`, reaction heat rate는 constrained inventory의 `[P]`, heat flux는 `[E,4,6,3]`이다. | + +Shell stress는 4 midsurface GP 각각의 bottom/middle/top S11/S22/S12이며 nodal average가 +아니다. Beam endpoint action·section resultant·section point stress도 서로 다른 위치다. +Hex8 stress는 global Cauchy이고 strain은 infinitesimal 또는 Green의 tensor shear다. +IntPt 순서는 `---,+--,-+-,++-,--+,+-+,-++,+++`로 node 순서와 다르다. + +Shell HHT는 nodal `[N,6]`의 q/v/physical a/public A와 `[N,3]` spatial angular rates를 +구별한다. 공개 A의 의미는 `full-chart-HHT-filter-combination-not-predictor-driver`다. +Generalized force/reaction과 spatial reaction을 구별한다. 과거 full-coordinate schema1은 +그 의미로 읽고 marker 보충이나 schema2 재표시로 재사용하지 않는다. + +Thermal 온도 성분은 NT11..NT15, zeta=`[-1,-.5,0,.5,1]`이다. Flux는 4 면내점과 +`[-1+,-.5,0-,0+,.5,1-]`의 6 trace를 가진 global QX/QY/QZ다. +초기 frame은 time=delta=0이며 temperature만 있고 flux/reaction dataset은 없다. +완료 frame은 실제 양의 delta, constraint mask와 reaction inventory를 보존한다. +P=0인 빈 inventory를 누락으로 취급하지 않는다. + +Schema·필수 field·dtype·shape·inventory·finite 불일치는 읽기나 비교 실패다. +누락을 0·NaN·기본 marker로 채워 이용하지 않는다. Mode shape는 응답 변위가 아니며 +frequency와 raw lambda도 다른 양이다. 작은 음의 lambda를 abs/clamp하여 raw 값을 바꾸지 않는다. + +## C++ consumer와 비교 도구 + +공개 interface는 `include/fesa`의 backend-neutral 값과 `Status`/`Result`를 사용한다. +Domain을 빌리는 AnalysisModel과 adapter는 참조 대상의 유효 수명을 넘겨 사용하지 않는다. +Procedure는 family별 completed outcome을 반환하며 로그 close와 최종 파일 공개는 호출자가 +조정한다. Vendor handle이나 private header를 사용하는 consumer는 공개 경계 밖이다. + +Hex8/HHT Python 비교기는 입력·reference·HDF5를 읽고 지정한 JSON report만 쓴다. +Solver를 기동하거나 원본을 수정하지 않는다. 입력 부재·hash 충돌·schema/identity/finite +불일치는 실패이며 합성 fixture 통과는 실제 모델 성공을 뜻하지 않는다. diff --git a/docs/engineering-notes.md b/docs/engineering-notes.md new file mode 100644 index 0000000..cd5bc26 --- /dev/null +++ b/docs/engineering-notes.md @@ -0,0 +1,58 @@ +# 재현된 함정과 대응 + +## 긴 임시 경로가 출력 충돌처럼 보인 경우 + +Integration 검증에서 TMP 아래 lease 경로가 260/261자가 되어 `output-busy`가 발생했다. +같은 실행물과 검사 identity에서 긴 TMP는 exit 1, 짧은 TMP는 exit 0이었다. +짧고 고유한 TMP/TEMP로 해당 integration 전체를 다시 실행해 확인했다. +재현 시 실제 점유와 경로 길이를 구분하고 원실패 로그를 남긴다. Lock을 삭제하거나 +제품의 실패 조건을 완화하는 방식으로 이 환경 문제를 해결하지 않는다. + +## 실행 환경 때문에 검사 범위가 달라진 경우 + +상속된 GoogleTest filter·sharding과 다른 compiler/build tree는 발견 목록과 실제 실행을 +다르게 만들 수 있다. 실행 전 관련 환경을 비우고 discovery identity를 XML·raw 출력과 +대조한다. `No tests were found`나 빌드 실패 뒤의 빈 실행을 통과로 기록하지 않는다. +한국어 MSVC의 Ninja include 추적은 configure/build 모두 code page 65001로 맞춘다. + +## Link 성공 뒤 DLL에 의존한 경우 + +개발자의 PATH에 있는 oneAPI/HDF5 runtime으로만 실행되면 link 성공과 배포 가능성을 +혼동한다. 실행 파일 옆에 배치된 TBB·MKL·OpenMP·Intel runtime·HDF5 DLL을 확인한다. +Native와 CMake의 설정별 runtime을 따로 확인하며 Debug DLL과 Release DLL을 섞지 않는다. + +## 작은 PARDISO 문제의 heap failure + +기존 1×1 SPD 반복에서 heap failure가 SpMV 없는 baseline에서도 재현됐다. +Vendor 원인은 확정되지 않았다. 현재 회피는 기본 정책의 해당 크기에만 local 1-thread를 +적용하고 TLS 설정을 복원하는 것이다. 보조 100회 성공을 모든 크기·vendor heap 문제의 +해결로 확대하지 않는다. 재발하면 matrix 크기·thread 정책·factor/solve/release 수명을 분리해 재현한다. + +## 열 RHS 재배치가 상쇄 오류를 숨긴 경우 + +열 RHS를 두 행곱의 차로 재배치한 후보는 cancellation oracle를 깨뜨려 폐기됐다. +현재 entry association `(c/delta)*(old-g)-k*g`와 row 순서를 보존한다. +Reduced-system scale 대신 큰 constrained 온도가 포함된 full scale로 잔차를 정규화하면 +같은 오류를 숨길 수 있다. 독립 signed residual enclosure와 실제 free system의 backward +error를 확인하며 enclosure가 0을 포함한다는 사실만으로 exact-zero를 증명하지 않는다. + +## 값의 bit 일치로 충분하지 않았던 최적화 + +Hex8 paired 연산의 Release ordered-overflow 사례는 값의 bit가 같아도 INVALID FE/MXCSR가 +달라 실패했다. Nonfinite 첫 sum에서 기존 checked scalar bridge로 돌아가 원래 실패 계산을 +보존한 뒤 관련 검사를 다시 수행했다. Flags clear나 기대값 완화는 해결이 아니다. +연산 순서·예외 상태·오류 전파가 바뀌는지까지 확인한다. + +## 중단 로그와 최종 결과를 혼동하는 경우 + +Accepted increment 로그가 있어도 해석이 끝나지 않으면 writer가 정상 HDF5를 공개하지 않는다. +History는 실행 중 메모리에 있으므로 강제 종료 로그만으로 복구되지 않는다. +이전 최종 HDF5가 남아 있을 수 있어 native exit·새 결과 identity·최종 교체를 함께 확인한다. +Wrapper의 exit와 실제 solver·comparator의 exit도 구분한다. 자식의 정상 종료 후 wrapper가 +시간 정보 처리에서 실패했던 사례는 solver 수치 실패와 다르다. + +## 외부 비교의 범위를 넓혀 해석하는 경우 + +변위 CSV에는 속도·가속도·energy가 없을 수 있다. 변위 일치로 이 물리량의 시간 정확도나 +관성 일관성을 증명하지 않는다. Warning UR·review RF/RM·diagnostic NT11은 각각의 원래 +판정 영향을 보존한다. 합성 HDF5 비교기 검사와 실제 solver의 물리 결과를 구분한다. diff --git a/docs/operations.md b/docs/operations.md new file mode 100644 index 0000000..20ffee6 --- /dev/null +++ b/docs/operations.md @@ -0,0 +1,150 @@ +# 환경 준비와 실행 + +## 준비 순서 + +저장소 root에서 VS x64 개발 환경을 사용한다. 직접 프로젝트는 v145 toolset과 Windows SDK를 +요구한다. 필요한 로컬 설치는 MKL·TBB·HDF5·OpenMP/Intel runtime과 승인된 GoogleTest +source checkout이다. CMake 경로에는 추가로 CMake 3.25 이상과 Ninja가 필요하다. +Dependency 설치·다운로드·외부 source 수정은 아래 명령에 포함되지 않는다. + +직접 MSBuild 설정은 다음 환경변수 또는 ignored `msvc/Fesa.Local.props`로 주입한다. + +| 변수 | 값의 의미 | +| --- | --- | +| `FESA_GTEST_SOURCE_DIR` | `googletest/include`와 source를 포함한 승인된 checkout root | +| `FESA_MKL_ROOT` | MKL의 include·lib·runtime을 포함한 설치 root | +| `FESA_TBB_ROOT` | TBB 설치 root; Debug와 Release runtime을 구분한다. | +| `FESA_HDF5_ROOT` | HDF5 C library의 include·lib·runtime 설치 root | +| `FESA_OMP_ROOT` | Intel OpenMP library와 runtime 설치 root | +| `MKL_DIR`·`TBB_DIR`·`HDF5_DIR` | CMake에서만 사용하는 각 CONFIG package 디렉터리; 설치 root와 혼동하지 않는다. | + +VS x64 Developer PowerShell에서 다음을 확인한다. 누락되면 해당 로컬 설치 경로를 설정한 +뒤 다시 확인한다. 개인 경로를 repository의 추적 파일에 기록하지 않는다. + +```powershell +Get-Command cl.exe, MSBuild.exe +$required_roots = 'FESA_GTEST_SOURCE_DIR','FESA_MKL_ROOT','FESA_TBB_ROOT','FESA_HDF5_ROOT','FESA_OMP_ROOT' +foreach ($root_name in $required_roots) { + $root_path = [Environment]::GetEnvironmentVariable($root_name) + if (-not $root_path -or -not (Test-Path -LiteralPath $root_path -PathType Container)) { + throw "Missing local dependency root: $root_name" + } +} +``` + +위 확인은 환경변수 방식의 준비 절차다. `Fesa.Local.props`를 사용하는 경우에는 그 파일의 +동일 MSBuild property 값을 확인한다. CMake는 `Fesa.Local.props`를 읽지 않는다. + +## 주 개발 빌드와 직접 검사 + +저장소 root의 VS x64 개발 환경에서 실행한다. 앞 명령이 실패하면 뒤 명령으로 진행하지 않는다. + +```powershell +MSBuild FESA.sln /m:2 /p:Configuration=Debug /p:Platform=x64 +if ($LASTEXITCODE -ne 0) { throw 'MSBuild failed' } +``` + +출력은 `.build/native/Debug`다. Solver CLI는 `src/fesa/fesa.exe`, 세 검사 실행기는 +`tests/fesa_unit_tests.exe`, `tests/fesa_integration_tests.exe`, +`tests/fesa_reference_tests.exe`에 있다. Release는 별도의 `Release` 디렉터리를 사용한다. +직접 MSBuild는 CMake·Ninja·Doxygen을 선행 실행하지 않는다. + +다음은 한 번의 전체 직접 검사 예시다. 각 실행기는 새 process이므로 직렬로 실행한다. +고유 디렉터리의 raw 출력·XML과 discovery를 보관한다. 이 예시는 현재 PowerShell +process의 TMP/TEMP와 GoogleTest 선택 환경을 변경한다. + +```powershell +$verify_run = Join-Path $env:LOCALAPPDATA ('fv-' + [guid]::NewGuid().ToString('N').Substring(0,8)) +New-Item -ItemType Directory -Path $verify_run -ErrorAction Stop | Out-Null +$env:TMP = $verify_run +$env:TEMP = $verify_run +foreach ($filter_name in 'GTEST_FILTER','GTEST_TOTAL_SHARDS','GTEST_SHARD_INDEX','GTEST_SHARD_STATUS_FILE','GTEST_OUTPUT') { + Remove-Item -LiteralPath ('Env:' + $filter_name) -ErrorAction SilentlyContinue +} +foreach ($test_name in 'fesa_unit_tests','fesa_integration_tests','fesa_reference_tests') { + $test_exe = Join-Path '.build/native/Debug/tests' ($test_name + '.exe') + & $test_exe --gtest_list_tests > (Join-Path $verify_run ($test_name + '-discovery.txt')) + if ($LASTEXITCODE -ne 0) { throw "Discovery failed: $test_name" } + & $test_exe ('--gtest_output=xml:' + (Join-Path $verify_run ($test_name + '.xml'))) *> (Join-Path $verify_run ($test_name + '-raw.txt')) + if ($LASTEXITCODE -ne 0) { throw "Tests failed: $test_name; records: $verify_run" } +} +``` + +생성된 경로에서도 실제 최장 lease 경로를 확인한다. 너무 길면 승인된 짧은 작업 위치를 사용한다. + +## CMake 보조 빌드 + +같은 VS x64 환경에서 로컬 CONFIG package 환경변수를 설정한 뒤 실행한다. +한국어 MSVC의 include 추적을 위해 configure/build의 code page를 65001로 맞춘다. +직접 검사와 별개의 짧고 고유한 TMP/TEMP를 만들고 상속된 필터·sharding을 제거한다. + +```powershell +Get-Command cmake.exe, ninja.exe +chcp 65001 +$cmake_verify_run = Join-Path $env:LOCALAPPDATA ('fc-' + [guid]::NewGuid().ToString('N').Substring(0,8)) +New-Item -ItemType Directory -Path $cmake_verify_run -ErrorAction Stop | Out-Null +$env:TMP = $cmake_verify_run +$env:TEMP = $cmake_verify_run +foreach ($filter_name in 'GTEST_FILTER','GTEST_TOTAL_SHARDS','GTEST_SHARD_INDEX','GTEST_SHARD_STATUS_FILE','GTEST_OUTPUT') { + Remove-Item -LiteralPath ('Env:' + $filter_name) -ErrorAction SilentlyContinue +} +cmake --preset windows-msvc-ninja-debug +if ($LASTEXITCODE -ne 0) { throw 'Configure failed' } +cmake --build --preset windows-msvc-ninja-debug --parallel 2 +if ($LASTEXITCODE -ne 0) { throw 'Build failed' } +ctest --preset windows-msvc-ninja-debug --show-only=json-v1 +if ($LASTEXITCODE -ne 0) { throw 'Discovery failed' } +ctest --preset windows-msvc-ninja-debug --output-on-failure -j 1 +if ($LASTEXITCODE -ne 0) { throw 'CTest failed' } +``` + +Debug tree는 `.build/cmake-debug`, Release tree는 `.build/cmake-release`다. +CLI는 각각의 tree에서 `src/fesa/fesa.exe`에 있다. Native와 CMake의 실행 기록을 분리하고 +discovery가 0건이 아닌지, 전체 identity가 일치하는지 확인한다. CTest label만으로 +물리 기능을 선별하지 않는다. 현재 공통 label에는 beam 이름이 들어 있으며 전체 검사의 procedure 분류가 아니다. +`fesa_docs`는 Doxygen을 검출했을 때만 존재하는 선택적 target이다. + +## Python 비교기와 실제 모델 + +Python suite는 pytest·NumPy·h5py를 사용한다. 설치된 환경에서 다음을 실행한다. + +```powershell +python -c "import pytest, numpy, h5py" +if ($LASTEXITCODE -ne 0) { throw 'Python dependencies are missing' } +python -m pytest tests -q +if ($LASTEXITCODE -ne 0) { throw 'Python tests failed' } +``` + +`scripts/verification/compare_hex8.py`와 `compare_hht_dynamic.py`는 입력·reference·HDF5를 +읽고 지정한 JSON report를 쓴다. Solver는 실행하지 않는다. 실행 전에 각 script의 `--help`로 +필수 인자와 덮어쓰기 방지 조건을 확인하고 기존 report와 다른 출력 위치를 사용한다. + +실제 모델은 원본 INP hash를 확인해 새 작업 디렉터리로 복사한 뒤 +`fesa.exe <작업복사본.inp>`로 실행한다. 출력은 해당 입력의 sibling이다. +Exit·로그·새 HDF5의 identity를 확인한 뒤 대응하는 정식 reference와 비교한다. +`reference/temp`는 사용하지 않는다. 원본 폴더 안에서 solver를 실행하지 않는다. + +다음은 Debug 빌드 뒤 정식 beam 입력을 새 위치에서 실행하는 예시다. 원본 폴더에 쓰지 않으며 +비교 CSV는 복사·수정하지 않는다. 실행 성공은 후속 reference 비교를 대신하지 않는다. + +```powershell +$model_source = 'reference/cantilever beam/cantilever beam.inp' +$model_run = Join-Path $env:LOCALAPPDATA ('fm-' + [guid]::NewGuid().ToString('N').Substring(0,8)) +New-Item -ItemType Directory -Path $model_run -ErrorAction Stop | Out-Null +$model_copy = Join-Path $model_run 'beam.inp' +Copy-Item -LiteralPath $model_source -Destination $model_copy -ErrorAction Stop +if ((Get-FileHash -LiteralPath $model_source).Hash -ne (Get-FileHash -LiteralPath $model_copy).Hash) { + throw 'Input copy hash mismatch' +} +& '.build/native/Debug/src/fesa/fesa.exe' $model_copy +if ($LASTEXITCODE -ne 0) { throw "Solver failed; records: $model_run" } +Get-Item -LiteralPath (Join-Path $model_run 'beam_results.h5'), (Join-Path $model_run 'beam_log.txt') +``` + +## 시간 측정과 배포의 경계 + +성능 판정은 Ryzen 7 5800H의 Windows/MSVC x64 최적화 Release가 기준이다. +같은 thread·runtime·전원·compiler 조건에서 워밍업 없이 모델별 process를 한 번 측정한다. +Process 시작 요청 직전부터 종료 직후까지 입력·계산·복구·로그·HDF5 최종화를 포함한다. +빌드·복사·VTune·비교는 측정 구간 밖이다. Debug 시간이나 반복 최솟값으로 대체하지 않는다. +배포 형식·installer·dependency 재배포 조건은 미확정이며 개발 빌드 절차를 배포 절차로 간주하지 않는다. diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 0000000..8bea676 --- /dev/null +++ b/docs/security.md @@ -0,0 +1,37 @@ +# 로컬 실행과 자료 보호 + +## 실행 주체와 권한 + +사용자는 FESA를 로컬에서 실행한다. 현재 제품에 계정·로그인·원격 API·서비스 인증은 없다. +실행 권한과 파일 접근 권한은 실행 중인 Windows 계정의 권한을 따른다. 제품 내부의 +사용자별 권한 분리나 비신뢰 입력을 격리하는 sandbox가 있다고 가정하지 않는다. +실행에 사용하는 API key·서비스 token은 없으므로 발급·회전·폐기 절차도 현재 적용되지 않는다. + +| 주체 | 허용되는 동작 | 조건과 금지되는 동작 | +| --- | --- | --- | +| 로컬 실행 사용자 | 입력 파일 읽기·해석·결과 저장 | 입력 읽기와 sibling 출력 위치의 OS 권한이 필요하다. 읽기 전용 입력 폴더에 대한 저장 성공을 보장하지 않는다. | +| 같은 결과 쌍을 쓰는 다른 실행 | lease 취득 후 실행 | 이미 점유된 쌍에는 쓰지 않는다. 점유 해제 목적으로 다른 프로세스의 lock을 임의 삭제하지 않는다. | +| 개발·검증 작업 | 승인된 입력의 작업 복사본에서 실행 | 기준자료 원본을 실행 위치로 사용하여 로그·결과를 만들거나 원본 값을 보정하지 않는다. | +| 자동화된 변경 작업 | 요청 범위의 코드·문서·검사 수정 | 원격 전송·외부 solver·비용 발생·release·파괴 작업은 명시적으로 승인된 범위에 한정한다. | + +## 파일 실패와 기록 + +입력 읽기 실패·잘못된 문법·미지원 의미를 정상 빈 모델로 바꾸지 않는다. +출력 lease 생성 실패나 점유 충돌은 저장 실패다. Lease 취득 전에 공개 파일을 truncate하지 않는다. +해석·로그 close·candidate write·self-check·close·최종 교체 중 실패가 나면 정상 최종 결과를 +새로 공개하지 않는다. 기존 최종 HDF5는 보존하지만 로그는 실패 진단으로 갱신될 수 있다. + +기록 대상은 입력·모델·해법·저장 오류, source 위치·keyword·entity identity, +지원 의미의 warning과 해당 procedure의 증분·반복 기록이다. 로그는 운영 진단이며 +변조 방지 감사 저장소가 아니다. 이전 HDF5의 존재를 이번 실행 성공의 증거로 사용하지 않는다. + +## 자료 취급의 경계 + +기준 INP·CSV·TXT는 읽기 전용 검증 자산으로 취급한다. 원본 hash·identity를 보존하며 +누락·충돌·불일치를 복원이나 zero-clamp로 숨기지 않는다. +로그와 결과에는 입력 경로·source 이름·물리 값이 들어갈 수 있다. 로컬 실행 승인은 +이 자료의 외부 전송 승인까지 포함하지 않는다. + +외부 배포 대상·dependency 재배포 조건·지원 환경은 아직 확정되지 않았다. +외부 입력의 격리나 자료 공유·보관 기간에 대한 별도 정책도 정해진 것으로 기록하지 않는다. +이 범위를 도입하는 작업에서는 적용할 사용 주체·공유 범위·파일 권한을 사용자와 정한다. diff --git a/docs/standards.md b/docs/standards.md new file mode 100644 index 0000000..824fb79 --- /dev/null +++ b/docs/standards.md @@ -0,0 +1,55 @@ +# 개발과 검증 기준 + +## 소유권과 의존성 + +- 공개 header는 단독 include가 가능해야 하며 `src`의 private header와 + MKL·TBB·HDF5·Win32 타입을 노출하지 않는다. Concrete adapter 선언과 vendor resource는 구분한다. +- Domain 정의·DOF와 equation·local 응답·accepted state·backend resource의 소유권을 + 섞지 않는다. Non-owning view와 borrowed adapter는 참조 대상의 수명·주소 안정성을 지킨다. +- 새 procedure는 typed state와 completed outcome을 사용한다. Static state의 미사용 field나 + 무타입 buffer로 다른 family를 위장하지 않는다. Element가 equation이나 accepted history를 소유하지 않는다. +- Expected failure는 `Status`/`Result`로 전달한다. Adapter의 vendor 오류를 정상 빈 값이나 + CLI exit 번호로 직접 흘리지 않는다. 결과 family에 필수 writer가 없으면 실패한다. +- 병렬 worker는 자기 index의 buffer만 쓴다. 공유 CSR 누적·진단 선택·결과 ordering이 + hash 순서나 worker 완료 시각에 의존하면 위반이다. + +## 변경 범위와 코드 규약 + +승인된 물리·입력·영속 schema·판정 기준을 구현 편의로 바꾸지 않는다. 필요한 변경이 +이 계약과 충돌하면 근거와 영향을 사용자에게 알린다. 무관한 사용자 변경·기준자료 원본을 보존한다. +수식·적분·reduction 순서·cache 수명 변경도 수치 변경으로 분류한다. + +C++17 이상, `.h`와 repository 경로 기반 include guard, self-contained header를 사용한다. +파일·namespace는 snake_case, 타입·함수는 PascalCase, 변수는 snake_case, +class member는 trailing `_`, format은 Google 기반 2-space다. +생산 target의 MSVC `/W4 /WX`를 유지하고 외부 GoogleTest에 제품 warning 정책을 강제하지 않는다. +단독 소유 resource는 RAII로 정리하고 dense allocation의 크기 곱 overflow와 vendor integer +변환을 할당·호출 전에 검사한다. + +Source 변경은 직접 MSVC와 CMake의 명시적 source 목록에 함께 반영한다. +제품·검사 본문을 빌드 경로별로 복제하지 않는다. `/arch:AVX2`는 전용 Hex8 source에만 적용한다. +개인 설치 경로는 환경변수나 ignored local 설정으로 주입하고 추적 파일에 고정하지 않는다. +승인된 local dependency를 사용하며 자동 다운로드와 외부 source 수정을 추가하지 않는다. +직접 MSBuild의 선행 단계로 CMake·Ninja·Doxygen을 숨겨 호출하지 않는다. + +## 검증 완료의 조건 + +문서만 바꾸면 source·경로·원문 보존을 정적으로 검토하고 build/test를 실행하지 않는다. +동작 변경은 영향받은 검사부터 수행한다. 솔버 기능 완료에는 구성된 전체 MSVC x64 Debug +build/CTest와 필수 reference 비교가 필요하다. 수식 변경에는 독립 수치 검토와 필요한 +analytical/invariant·물리 검증을 함께 수행한다. + +직접 MSVC와 CMake의 compiler·구성·CRT·ISA·source·link·DLL과 전체 검사 등록 identity를 +대조한다. 실제 실행한 identity와 제외·skip·중단을 기록하며 discovery 0건을 통과로 세지 않는다. +Release 시간 측정이나 선택 검사 통과가 전체 Debug 검증을 대체하지 않는다. +C++ unit·integration·reference, 별도 Python suite, 실제 solver와 외부 비교 결과를 구분한다. +과거 revision의 통과를 현재 source의 미실행 범위에 승계하지 않는다. + +Reference 비교는 hash가 확인된 새 작업 복사본에서만 수행한다. `reference/temp`를 +검증에 사용하거나 정식 자료로 승격하지 않는다. 정식 자료 부재는 미완료다. +검사를 삭제하려면 동등한 대체 identity·실패 경계·수치 조건 또는 폐기 구조 전용임을 +입증해야 하며 자료 누락과 실행 유예만으로 삭제하지 않는다. + +사용자 지시에 따른 한정 실행은 선택·제외 identity와 이유를 기록한 해당 작업의 근거다. +그 한정 실행을 이후 일반 기능의 검증 의무 축소로 해석하지 않는다. +Commit·branch·merge·release는 해당 요청 범위를 따르며 문서 갱신만으로 자동 수행하지 않는다. diff --git a/docs/tracking/decisions/0001-input-subset.md b/docs/tracking/decisions/0001-input-subset.md new file mode 100644 index 0000000..7e10950 --- /dev/null +++ b/docs/tracking/decisions/0001-input-subset.md @@ -0,0 +1,17 @@ +# 입력 subset과 알고리즘 구분 + +## 배경 + +Abaqus의 요소·해법 이름으로 연구 모델을 읽지만 내부 요소·적분·질량·고유치 backend는 +FESA가 승인한 정식화를 사용한다. 같은 이름 수용만으로 외부 알고리즘 동등성이 성립하지 않는다. + +## 선택 + +입력은 procedure별 allowlist로 검사하고 source spelling과 identity를 보존한다. +S4/S4R은 같은 FESA MITC4로, FREQUENCY의 LANCZOS 표기는 경고와 함께 실제 FEAST로 연결한다. + +## 대안과 영향 + +Source 이름으로 Abaqus reduced integration·hourglass·LANCZOS를 선택하는 해석은 실제 구현과 +다르므로 채택하지 않는다. Unknown model keyword를 무시하는 방식도 모델 의미를 바꾸므로 쓰지 않는다. +현재 subset 밖의 입력은 실패한다. 새 기능은 별도 의미·입력·결과·검증 계약을 확정해 추가할 수 있다. diff --git a/docs/tracking/decisions/0002-typed-ownership.md b/docs/tracking/decisions/0002-typed-ownership.md new file mode 100644 index 0000000..b5cbe01 --- /dev/null +++ b/docs/tracking/decisions/0002-typed-ownership.md @@ -0,0 +1,18 @@ +# 정의와 실행 상태의 소유권 분리 + +## 배경 + +정적·고유치·동적·열 해석은 같은 모델 정의를 쓰지만 mutable state와 완료 결과의 의미가 다르다. +Static 상태에 미사용 field와 조건문을 쌓으면 잘못된 family를 직렬화하거나 실패한 trial을 노출할 수 있다. + +## 선택 + +Domain은 의미 정의를, DofManager는 equation·pattern을, 요소는 local 응답을 소유한다. +Procedure는 typed candidate·accepted history를 관리하고 typed completed outcome을 반환한다. +Vendor resource는 private adapter가 소유하며 borrowed view·kernel은 실행 중 주소와 수명을 유지한다. + +## 대안과 영향 + +Node·element가 equation과 accepted history를 나눠 저장하거나 공통 무타입 buffer로 family를 +합치는 구조는 책임 경계를 흐리므로 사용하지 않는다. Caller가 참조 대상의 수명을 보장해야 하는 +비용이 생긴다. 새 procedure는 기존 static 결과로 위장할 수 없으며 해당 state·outcome·writer가 필요하다. diff --git a/docs/tracking/decisions/0003-ordered-reduction.md b/docs/tracking/decisions/0003-ordered-reduction.md new file mode 100644 index 0000000..87f1902 --- /dev/null +++ b/docs/tracking/decisions/0003-ordered-reduction.md @@ -0,0 +1,17 @@ +# 병렬 계산과 누적 순서 + +## 배경 + +여러 요소가 같은 DOF에 기여하며 부동소수점 합산 순서와 먼저 발견되는 오류가 결과를 바꿀 수 있다. +Thread 수와 scheduling이 source identity·결과·진단의 재현성을 바꾸면 비교 근거가 흔들린다. + +## 선택 + +Worker는 자기 element/index buffer에만 local 결과를 쓴다. Join 뒤 stable COO/source 순서와 +고정 reduction으로 전역 값을 누적한다. 오류 선택도 발견 시각 대신 지정된 순서를 따른다. + +## 대안과 영향 + +공유 CSR에 직접 병렬 더하기는 완료 순서에 따른 합산을 만들므로 쓰지 않는다. +Buffer와 ordered reduction 비용을 감수하며 hash iteration과 worker 완료 순서를 결과 순서로 쓸 수 없다. +Reduction 순서를 바꾸는 최적화는 단순 refactoring이 아니라 수치 변경으로 검증한다. diff --git a/docs/tracking/decisions/0004-candidate-output.md b/docs/tracking/decisions/0004-candidate-output.md new file mode 100644 index 0000000..065b5f9 --- /dev/null +++ b/docs/tracking/decisions/0004-candidate-output.md @@ -0,0 +1,19 @@ +# 검증된 결과만 최종 공개 + +## 배경 + +Accepted 증분이 생긴 뒤에도 다음 증분·로그 close·HDF5 기록·재개방 검사에서 실패할 수 있다. +이때 기존 정상 최종 결과를 훼손하면 실패 실행과 성공 실행을 구별할 수 없다. + +## 선택 + +Trial 검증 뒤 state를 commit하고, 전체 해석 완료와 로그 close 성공 뒤 writer를 호출한다. +별도 candidate 파일을 기록·close·self-check한 뒤 최종 경로를 교체한다. +Output lease로 같은 결과 쌍을 쓰는 실행을 하나로 제한한다. + +## 대안과 영향 + +최종 파일을 먼저 truncate하거나 각 trial을 정상 결과로 직접 저장하는 방식은 실패 보존 조건과 +충돌하므로 사용하지 않는다. Candidate용 저장 공간과 재개방 비용이 필요하다. +실패 로그가 갱신되고 이전 최종 파일이 남을 수 있어 파일 존재만으로 이번 성공을 판단할 수 없다. +실행 중 accepted history는 강제 종료 로그만으로 복원하지 못한다. diff --git a/docs/tracking/decisions/0005-eigen-comparison.md b/docs/tracking/decisions/0005-eigen-comparison.md new file mode 100644 index 0000000..23c69ca --- /dev/null +++ b/docs/tracking/decisions/0005-eigen-comparison.md @@ -0,0 +1,18 @@ +# MITC4 첫 고유치 구현의 비교 예외 + +## 배경 + +첫 MITC4 lumped-mass eigen 구현은 외부 원본 Value의 공통 RMS 1% 기준을 충족하지 못했다. +2026-09-10 사용자는 첫 구현 범위에서 모드별 비교 예외를 승인했다. + +## 선택 + +`mitc4-eigen-first-implementation` 정책을 source modal frame별 blocking singleton Value에만 +적용해 행 상대오차와 RMS를 각각 5% inclusive로 검사한다. Report에 policy_id와 RMS 0.05를 남긴다. +Near-zero·zero-scale·identity/finite와 내부 전체 반환 pair의 `1e-10` 검증은 유지한다. + +## 대안과 영향 + +공통 RMS 1% 적용 결과는 당시 실패 이력으로 남긴다. 모든 기능의 RMS를 5%로 바꾸는 방식은 +승인 범위 밖이므로 사용하지 않는다. 이 예외는 Hex8 eigen·정적 U/UR/reaction에 적용할 수 없다. +외부 Value 비교의 첫 구현 수용이지 partial-BC 정적 평형 충돌이나 알고리즘 동등성의 해결이 아니다. diff --git a/docs/tracking/decisions/0006-thermal-diagnostic.md b/docs/tracking/decisions/0006-thermal-diagnostic.md new file mode 100644 index 0000000..950d96e --- /dev/null +++ b/docs/tracking/decisions/0006-thermal-diagnostic.md @@ -0,0 +1,17 @@ +# 기존 NT11 비교의 진단 분류 + +## 배경 + +기존 DS4 reference의 Step-1/t37/DOF11 NT11은 87/729행 실패와 RMS/S 약 0.0496740846을 +보였고 독립 정식화 oracle도 같은 불일치를 보였다. 공통 RMS 0.01을 넘는다. + +## 선택 + +사용자는 원 정식화와 tolerance를 유지하고 이 비교만 diagnostic/nonblocking으로 분류했다. +새 필수 모델·CSV는 별도 identity·시점·hash를 확정해 검증한다. + +## 대안과 영향 + +온도 clamp·reference 보정·허용치 완화는 승인된 물리와 원본을 바꾸므로 사용하지 않는다. +진단 분류 검사의 성공은 외부 수치 PASS가 아니다. 새 reference가 확보되기 전에는 +외부 검증 완료를 선언할 수 없으며 기존 불일치 기록도 지우지 않는다. diff --git a/docs/tracking/decisions/0007-local-build-paths.md b/docs/tracking/decisions/0007-local-build-paths.md new file mode 100644 index 0000000..71f0c9c --- /dev/null +++ b/docs/tracking/decisions/0007-local-build-paths.md @@ -0,0 +1,18 @@ +# 직접 빌드와 보조 빌드 유지 + +## 배경 + +직접 MSBuild가 주 개발 빌드이며 CMake/Ninja도 같은 제품과 검사를 구성한다. +별도 source나 우연한 PATH runtime을 사용하면 빌드 경로에 따라 제품·검증 범위가 달라진다. + +## 선택 + +직접 관리하는 solution과 CMake의 source·검사 identity·CRT·ISA·link·runtime을 함께 유지한다. +설치 경로는 환경변수나 ignored local 설정으로 받고 GoogleTest는 승인된 local source를 사용한다. + +## 대안과 영향 + +직접 프로젝트를 CMake 생성물로 교체하거나 빌드 전 CMake·Ninja를 숨겨 호출하는 방식은 +주 개발 경로의 독립성을 잃으므로 사용하지 않는다. 두 source 목록을 함께 유지하는 비용이 생긴다. +의존성 자동 다운로드와 개인 경로 고정도 현재 접근과 다르므로 추가하지 않는다. +한 경로의 link 성공은 다른 경로의 discovery·실행·runtime 검증을 대신할 수 없다. diff --git a/docs/tracking/decisions/0008-shell-inertia.md b/docs/tracking/decisions/0008-shell-inertia.md new file mode 100644 index 0000000..4cff82d --- /dev/null +++ b/docs/tracking/decisions/0008-shell-inertia.md @@ -0,0 +1,20 @@ +# Shell 질량 영공간과 동적 좌표 + +## 배경 + +MITC4의 numerical drilling은 physical inertia가 없는 방향이다. 부분 회전구속과 warped +geometry에서는 이를 단순 성분 삭제나 scalar 회전 질량으로 바꾸면 유한 공간의 의미가 달라진다. + +## 선택 + +Eigen은 consistent moment에서 유도한 nodal block lumped mass와 실제 BC 이후의 +analytic null/free 교집합 제거를 사용한다. 현재 HHT는 nodal-lumped-kinetic measure와 +초기 null의 고정 보완기저를 사용한 reduced-coordinate 적분으로 physical rate를 복원한다. +HHT 관성력·접선·energy·momentum은 같은 kinetic measure에서 계산한다. + +## 대안과 영향 + +Artificial drilling inertia와 partial BC의 full clamp 대체는 현재 질량·구속 의미를 바꾸므로 +사용하지 않는다. 과거 consistent/full-coordinate HHT 기록은 현재 경로의 검증으로 승계하지 않는다. +고정 patch 밖의 history transport가 검증되지 않으면 실패한다. 공개 auxiliary acceleration만으로 +private 적분 이력을 구성할 수 없고 현재 restart도 제공하지 않는다. diff --git a/docs/tracking/decisions/0009-hex8-numerics.md b/docs/tracking/decisions/0009-hex8-numerics.md new file mode 100644 index 0000000..177c87a --- /dev/null +++ b/docs/tracking/decisions/0009-hex8-numerics.md @@ -0,0 +1,21 @@ +# Hex8 강성·질량·정밀도 + +## 배경 + +Pointwise bulk의 과도한 강성, warped 요소의 질량 분포와 큰 병진 속 작은 변형의 소실이 +같은 모델의 정적·고유치·동적 결과에 영향을 준다. + +## 선택 + +2026-10-10 승인된 volume-weighted mean volumetric energy와 점별 deviatoric energy를 +사용한다. 2026-10-11 승인된 reference consistent matrix의 BC 축소 전 row-sum mass를 +eigen·HHT·reaction·kinetic energy·momentum에 일관되게 쓴다. +Solid HHT는 normalized high+low 상태를 다음 accepted history까지 유지하며 F64 출력은 전체 값의 RN64다. + +## 대안과 영향 + +Center/unweighted mean·Fbar·mean-J는 채택한 energy와 달라 대체하지 않는다. +Warped node 질량을 `rho*V/8`로 통일하거나 current geometry로 재계산하지 않는다. +매 증분을 rounded F64만으로 이어 가면 low가 소실되므로 내부 상태로 사용하지 않는다. +Backend에 넘기는 RN64와 full-pair acceptance를 구별해야 하며 출력만 재입력해 같은 내부 판정을 +재현하거나 restart를 제공한다고 주장할 수 없다. diff --git a/docs/tracking/decisions/0010-thermal-discretization.md b/docs/tracking/decisions/0010-thermal-discretization.md new file mode 100644 index 0000000..4e47f71 --- /dev/null +++ b/docs/tracking/decisions/0010-thermal-discretization.md @@ -0,0 +1,19 @@ +# Shell 두께 온도와 시간적분 + +## 배경 + +DS4는 shell 면내 전도뿐 아니라 두께 방향 온도 변화와 초기 지정온도의 용량 결합을 다룬다. +독립된 여러 2D 판이나 초기 온도 projection으로 바꾸면 첫 증분과 열반력의 의미가 달라진다. + +## 선택 + +Q4 면내와 두 구간 C0 P2 두께 보간으로 node당 다섯 온도점을 결합한다. +Consistent capacity와 Backward Euler를 사용한다. Raw 초기 온도를 frame0에 보존하고 +첫 양의 시점부터 지정온도를 적용하며 열저장을 포함한 full residual에서 반력을 복구한다. + +## 대안과 영향 + +다섯 독립 판·capacity lumping·인공 확산·음수 온도 clamp를 사용하지 않는다. +초기 projection으로 첫 BC jump를 없애지 않는다. 고정 다섯 점의 두께 오차 plateau와 +초기 경계층이 남으며 thin-shell product-domain은 실제 3D 접합부 전도와 동등하지 않다. +중앙면 양쪽 도함수가 다를 수 있어 flux trace를 평균할 수 없다. diff --git a/docs/tracking/decisions/index.md b/docs/tracking/decisions/index.md new file mode 100644 index 0000000..2ad9a1d --- /dev/null +++ b/docs/tracking/decisions/index.md @@ -0,0 +1,14 @@ +# 주요 설계 결정 + +| 파일 | 결정과 주요 영향 | +| --- | --- | +| `0001-input-subset.md` | 입력 표기의 수용과 외부 solver 알고리즘 동등성을 구분한다. | +| `0002-typed-ownership.md` | 모델·방정식·local 응답·procedure별 상태·backend의 소유권을 분리한다. | +| `0003-ordered-reduction.md` | 병렬 local 계산 뒤 안정된 순서로 전역 누적한다. | +| `0004-candidate-output.md` | Accepted state와 최종 파일 공개를 별도 검증 경계로 둔다. | +| `0005-eigen-comparison.md` | MITC4 첫 구현의 모드별 Value 비교만 5% RMS 예외를 둔다. | +| `0006-thermal-diagnostic.md` | 기존 NT11 불일치를 보존하고 새 필수 reference를 별도로 검증한다. | +| `0007-local-build-paths.md` | 직접 MSBuild를 주 경로로 두고 같은 source의 CMake 경로를 유지한다. | +| `0008-shell-inertia.md` | Shell eigen/HHT의 질량 영공간을 보존하고 물리 rate를 복원한다. | +| `0009-hex8-numerics.md` | Mean-volume 강성·reference row-sum mass·high+low 상태를 사용한다. | +| `0010-thermal-discretization.md` | 다섯 두께 온도점·consistent capacity·Backward Euler를 사용한다. | diff --git a/docs/tracking/findings.md b/docs/tracking/findings.md new file mode 100644 index 0000000..dcf7c06 --- /dev/null +++ b/docs/tracking/findings.md @@ -0,0 +1,59 @@ +# 해결되지 않은 문제 + +## 비정적 검증 공백 + +- 조건·관측: 2026-10-18 통합에서 장시간 HHT 검증이 사용자 요청으로 중단되고 정적·공통 + 631개만 검증됐다. 비정적 333개 등록은 보존됐으나 최신 통합본 전체 수치 실행 근거가 없다. +- 영향: Shell HHT·solid dynamics·frequency·transient thermal의 전체 검증 완료를 선언할 수 없다. +- 지금 해결하지 못한 이유: 장시간 solver·test 실행과 독립 물리 판정이 필요한 별도 검증 작업이다. +- 다음 접근: source와 환경을 고정하고 미실행 identity별 필요한 물리·시간수렴·reference를 + 묶어 검증한다. 중단된 C08b finer-grid와 기존 완료 개별 검사를 구분한다. + +## 정식 기준자료 부재와 추가 fine 비교기 부재 + +- 조건·관측: 정식 `reference/shellNL-meshfine/`, `reference/shellNL-meshfine_02/`, + `reference/shellNL-meshfine-pressure/` 자료가 없다고 통합 기록에 남아 있다. + `_02`는 전용 comparator case identity와 비교 계약 구현도 없다. +- 영향: Fine·추가 fine·pressure의 실제 외부 비교가 미완료다. 합성 fixture가 이를 대체하지 않는다. +- 지금 해결하지 않는 이유: 정식 원본 제공은 외부 의존이며 원본 생성·복원·임시 자료 승격은 승인되지 않았다. +- 다음 접근: 정식 자료를 확보해 hash·source identity·frame을 확정한다. `_02`는 comparator + 계약을 별도로 구현한다. `reference/temp`는 검증에 사용하지 않는다. + +## Thermal NT11 외부 불일치 + +- 조건·관측: 기존 676 DS4·729 node 모델의 Step-1/t37/DOF11 NT11 비교에서 + 원본 87/729행 실패, RMS/S 약 0.0496740846으로 공통 0.01 기준을 초과했다. + 독립 정식화 oracle도 같은 불일치를 보였다. +- 영향: 기존 비교는 diagnostic/nonblocking이며 외부 수치 정확도 통과가 아니다. + 다른 station·flux·반력·전체 시간 응답으로 검증 범위를 확대할 수 없다. +- 지금 해결하지 않는 이유: 사용자가 원 정식화·허용치 유지를 선택했고 새 필수 모델·NT11 CSV가 미확보다. +- 다음 접근: 새 reference의 identity·시점·hash와 blocking 계약을 확정해 별도로 검증한다. + 음수 온도 clamp·원본 보정·RMS 완화로 기존 기록을 통과로 바꾸지 않는다. + +## Eigen partial-BC 정적 평형 충돌 + +- 조건·관측: MITC4 eigen의 S3 partial rotational BC 사례와 public static 평형 사이의 + 충돌이 기능 기록에 보류 상태로 남아 있다. +- 영향: 모드별 Value 5% 승인 예외가 이 정적 평형 문제나 Abaqus 알고리즘 동등성을 해결하지 않는다. +- 지금 해결하지 않는 이유: 수식·공개 정적 평형 계약의 별도 조사이며 문서만으로 고칠 수 없다. +- 다음 접근: 동일 source BC에서 static과 eigen의 null/finite 공간·힘/모멘트 의미를 독립 대조한다. + 부분 회전구속을 full clamp로 대체하지 않는다. + +## 성능 목표 미달과 과거 회귀 + +- 조건·관측: 세 모델의 과거 baseline은 목표 2초·100초·100초를 모두 넘었다. + Hex8 동적 수정본의 단일 개발 표본도 117.7986225초였다. Refactor의 ShellNL elapsed + 회귀 기록은 Native +86.52%·CMake +120.91%이며 원인과 변산이 미확정이다. +- 영향: 최적화 구현 존재와 최종 사용자 시간 목표 달성 사이에 공백이 있다. +- 지금 해결하지 않는 이유: 최신 최종 source의 Release 측정·전체 물리 검증이 필요한 별도 작업이다. +- 다음 접근: 같은 compiler·thread·runtime·전원 조건으로 전체 process 시간을 측정하고 + 원본 결과·필수 회귀를 함께 대조한다. 과거 보류 후보와 다른 source의 표본을 섞지 않는다. + +## PARDISO 1×1 heap failure의 vendor 원인 미확정 + +- 조건·관측: 1×1 SPD 반복의 heap failure는 SpMV 없는 baseline에서도 재현됐다. + 해당 크기에만 local-thread/TLS 회피가 적용돼 있다. +- 영향: 제한된 회피의 성공이 다른 크기·thread 정책·vendor 전체 resource 안전성을 증명하지 않는다. +- 지금 해결하지 못한 이유: vendor 원인이 미확정이며 최소 재현 실행과 backend 조사가 필요하다. +- 다음 접근: 재발 시 backend version·matrix·thread·factor/solve/release 수명을 고정한 최소 재현을 + 확보한다. 적용 범위를 근거 없이 확대하지 않는다. diff --git a/docs/tracking/status.md b/docs/tracking/status.md new file mode 100644 index 0000000..c8e4245 --- /dev/null +++ b/docs/tracking/status.md @@ -0,0 +1,63 @@ +# 구현과 검증 상태 + +## 기준 시점 + +2026-10-18 저장소 HEAD `945d899` 기준이다. 아래 통과 수치는 각 검증 당시 기록의 범위이며 +후속 source에서 새로 실행한 결과로 승계하지 않는다. +현재 용도는 개인 연구용 로컬 실행이며 장기 목표는 외부 사용자 배포다. 배포 형태·지원 환경· +dependency 재배포 조건은 확정되지 않았다. + +## 구현과 실제 근거 + +| 영역 | 구현된 범위 | 확보된 검증과 한계 | +| --- | --- | --- | +| B33·MITC4 선형 정적 | 입력 → solve → 복구 → HDF5 | 2026-10-18 정식 정적 모델 실행·비교 범위에 포함. 일반 곡선 beam·광범위 distorted/curved shell 정확도를 뜻하지 않는다. | +| MITC4 비선형 정적·압력 | Full Newton·trial/commit·정적 follower pressure | ShellNL 정식 기본 모델의 U blocking·UR warning·내부 평형 통과 기록. RF/RM은 review-only. Fine·추가 fine·pressure의 정식 자료가 없고 추가 fine 비교기 연결도 없다. | +| Shell frequency | Lumped mass·실제 FEAST·null/finite 공간·전체 반환 pair 검증 | 2026-09-10 첫 구현의 417개 통과와 Value 10개 모드별 5% 기록. 최신 통합본의 frequency 수치 실행을 완료한 근거로 승계하지 않는다. | +| Shell HHT | Nodal-lumped-kinetic·reduced-coordinate·fixed-null·schema2 | 과거 C09와 C08a 7-grid, baseline 원본 U 비교 기록. 최신 전체 회귀·C08b finer-grid·최신 원본 비교·전체 물리 판정은 미완료. 중단을 수치 실패나 통과로 세지 않는다. | +| Hex8 | Mean-volume 강성·reference row-sum mass·정적/고유치/HHT·high+low | 2026-10-13 관련 C++ 91개·Python 96개와 보존 결과 5개 비교 기록. 2026-10-18에는 정적 2개를 재실행. 최신 고유치·동적 전체 검증은 별도다. | +| DS4 thermal | 5 온도점·consistent capacity·BE·flux/reaction·원자적 출력 | 당시 추가 139개 검사 기록. 기존 NT11은 diagnostic 불일치이며 새 필수 외부 reference 검증은 미완료. 최신 통합본의 전체 열 수치 실행도 미완료다. | +| 공통 구조·빌드 | Typed procedure/capability/outcome·private backend·Native/CMake | 2026-10-18 두 경로 전체 target build·공개 header 111개 독립 compile·runtime DLL 7개 대조 기록. 물리 기능 전체 검증과 구분한다. | +| 성능 | MKL 행렬 연산·제한된 불변 cache·Hex8 SIMD·shell 산술 최적화 | 세 모델의 목표 달성은 미완료. 단일 개발 표본과 복원된 후보의 통과를 최종 성능으로 승계하지 않는다. | + +2026-10-18 통합 기록은 두 빌드 경로에서 unit 849·integration 72·reference 43, 총 964개 +등록 identity가 일치한다고 보고한다. 사용자 지시로 정적·공통 631개(unit 555·integration 35· +reference 41)만 직접 실행과 CTest에서 검증했으며 failure/error/skip은 0이었다. +Python 합성·정책 145개도 통과했다. 보존된 비정적 333개는 당시 미검증이다. + +정식 정적 5모델은 beam·shell·shellNL·Hex8 linear/nonlinear static이다. +Fresh Refactor·통합 Native·통합 CMake 실행물에서 같은 scratch 입력과 경로로 15회 실행했고 +등록 비교·보고서 검증·schema/identity/field parity를 포함한 50단계가 exit 0이었다. +이는 선택된 정적 근거이며 source 전체의 수치 동등성이나 전체 green 선언이 아니다. +근거 보관 위치는 `.build/merge-verification/refactor-integration-final-20261018-01/`다. +해당 보관물이 없는 checkout에서는 실행물을 확보한 것으로 간주하지 않는다. + +## 남은 작업과 의존 순서 + +사용자가 확인한 후속 범위는 남은 동해석·고유치·열해석 검증, 성능 개선과 미해결 이슈 처리다. +이 목록은 특정 기능의 자동 실행 지시나 장시간 작업·외부 solver 실행 승인으로 해석하지 않는다. + +1. 정식 fine·추가 fine·pressure·새 thermal 기준자료의 제공 여부와 source/frame/hash 계약을 + 확정한다. 추가 fine는 자료뿐 아니라 전용 case identity와 comparator 연결이 필요하다. +2. 현재 source·compiler·build tree를 묶어 비정적 수치 검증을 수행한다. Shell HHT 시간수렴· + 원본 비교, solid dynamics, frequency, transient thermal을 선택된 정적 근거와 구분한다. + 자료가 필요한 외부 비교는 정식 자료 확보 뒤 수행한다. +3. Eigen partial-BC 정적 평형 충돌과 thermal 외부 불일치의 영향을 각각 판정한다. + 기준 완화·질량 변경·원본 보정으로 해결하지 않는다. +4. 같은 물리·허용치·출력·정밀도를 보존한 상태에서 성능 회귀 원인을 조사하고 최종 source의 + Release 시간과 수치 결과를 다시 측정한다. 검증되지 않은 가속을 완료로 기록하지 않는다. + +위 순서는 자료·물리 판정·측정의 의존 관계다. 동해석·고유치·열해석 사이의 상세 우선순위와 +새 기능 추가 순서는 사용자가 별도로 정하지 않았다. + +## 성능 목표 + +| 모델 | 목표 초 | 과거 단일 baseline 초 | +| --- | ---: | ---: | +| hexa_nonlinearstatic | 2 | 10.914924 | +| hexa_dynnonlinear | 100 | 402.069447 | +| shellNL-dyn-meshfine | 100 | 6372.325621 | + +Hex8 동적 개발 표본 117.7986225초는 native 0과 U 비교 통과였으나 100초 목표를 넘었다. +Refactor 당시 ShellNL elapsed 회귀 Native +86.52%·CMake +120.91%는 과거 단일 기록이며 +원인·변산이 미확정이다. 최종 통합 source의 새 Release 성능 측정은 미완료다.