From 4bb05d23ebc655820d574ff3a6b018d9f6fe955e Mon Sep 17 00:00:00 2001 From: "KOKO\\Mimi" Date: Mon, 10 Aug 2026 16:34:20 +0900 Subject: [PATCH] docs: add FESA extension guidance --- AGENTS.md | 75 +++-- docs/ADR.md | 71 ++++- docs/ARCHITECTURE.md | 261 +++++++++--------- docs/PRD.md | 30 +- ...0-core-documentation-extension-playbook.md | 158 +++++++++++ ...documentation-extension-playbook-design.md | 46 +++ 6 files changed, 487 insertions(+), 154 deletions(-) create mode 100644 docs/superpowers/plans/2026-08-10-core-documentation-extension-playbook.md create mode 100644 docs/superpowers/specs/2026-08-10-core-documentation-extension-playbook-design.md diff --git a/AGENTS.md b/AGENTS.md index 74e92a8..ea7d208 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,11 +10,12 @@ - Abaqus `.inp` keyword subset input ## 프로젝트 정체성 -- FESA는 유한요소법 기반 구조해석 솔버 개발 프로젝트이다. +- FESA는 유한요소법 기반 구조해석 솔버를 단계적으로 구축하고 검증하는 프로젝트이다. 목표는 Abaqus를 흉내 내는 parser를 만드는 것이 아니라, 승인된 입력 범위에서 물리적으로 설명 가능하고 재현 가능한 해석 결과를 만드는 것이다. +- 새 기능은 입력 keyword만 인식하거나 element kernel만 존재한다고 완성된 것이 아니다. Semantic model, equation system, 해법, 결과 복구, HDF5 외부 계약과 독립 검증 evidence가 하나의 추적 가능한 기능을 이뤄야 한다. - 프로젝트의 배경, 목적, 사용자, 범위는 `docs/PRD.md`에서 확인한다. - 전체 아키텍처와 모듈별 책임은 `docs/ARCHITECTURE.md`에서 확인한다. - 주요 아키텍처 결정과 그 이유 및 트레이드오프는 `docs/ADR.md`에서 확인한다. -- AI 에이전트는 설계나 구현 결정을 내리기 전에 위 문서 중 작업과 관련된 내용을 참조한다. +- AI 에이전트는 설계나 구현 결정을 내리기 전에 PRD에서 제품 범위를, ARCHITECTURE에서 소유권과 데이터 흐름을, ADR에서 이미 결정된 트레이드오프를 먼저 확인한다. 기능별 의미는 `docs/requirements/`, `docs/formulations/`, `docs/io-definitions/`, `docs/reference-models/`의 승인 문서를 source of truth로 삼는다. - Harness는 솔버 자체가 아니라 요구조건, TDD, phase 실행, 검증을 통제하는 개발 운영 인프라이다. 전체 실행 흐름은 `docs/HARNESS_WORKFLOW.md`, 설치와 설정은 `docs/HARNESS.md`를 따른다. - 문서와 구현은 full Abaqus compatibility를 주장하지 않는다. 기능별로 승인된 Abaqus keyword subset만 지원한다. - 공식 solver output은 HDF5 `results.h5`이다. @@ -23,18 +24,42 @@ - 승인된 B33 baseline은 예외적으로 `reference/cantilever beam/`의 기존 space-containing 파일명을 read-only legacy alias로 사용한다. - CSV는 FESA 공식 output이 아니며, FESA HDF5에서 추출한 deterministic CSV view는 비교 디버깅/검토용 보조 artifact로만 둔다. -## 아키텍처 규칙 +## FESA 개발의 핵심 원칙 + +### 물리와 수치 계약 + +- CRITICAL: 구현보다 요구조건, 정식화, 부호, 단위, 좌표계, row identity와 tolerance 계약을 먼저 고정한다. 구현 편의를 위해 승인된 의미를 조용히 바꾸지 않는다. +- CRITICAL: 해석 결과가 유한하고 선형계가 풀렸다는 사실만으로 correctness를 주장하지 않는다. Equilibrium, reaction, rigid-body mode, energy, symmetry와 reference identity를 기능에 맞게 검증한다. +- Source label/instance identity와 internal index/equation index를 구분한다. Stable source identity는 진단, 결과, reference mapping 전 구간에서 보존한다. +- 병렬 실행 여부와 관계없이 같은 입력은 같은 sparse structure, reduction order, result row order와 diagnostic order를 만들어야 한다. +- Scale-aware validation은 formulation과 I/O 계약의 기준을 사용한다. 임의의 `max(1, ...)`, zero clamp, 누락 row 무시 또는 불일치 평균으로 오류를 숨기지 않는다. + +### 소유권과 의존성 + - CRITICAL: C++ 빌드는 CMake/MSVC/x64/Debug 기준으로 검증한다. - CRITICAL: 새 기능 또는 동작 변경은 테스트를 먼저 작성하고 실패를 확인한 뒤 구현한다. - CRITICAL: C++ production file을 바꿀 때는 관련 C++ test file이 있어야 한다. - CRITICAL: Abaqus reference artifact 생성, 수정, 복원은 명시적으로 요청된 phase에서만 수행한다. -- CRITICAL: public header와 implementation 의존성 방향을 역전하지 말 것 -- CRITICAL: 사람 개발자가 검토하기 쉽도록 코드를 작성할것. 그리고 주석도 필수로 작성할 것. +- CRITICAL: public header와 implementation 의존성 방향을 역전하지 않는다. +- CRITICAL: 사람이 계약과 수치식을 대조할 수 있는 단순한 코드를 작성한다. 주석은 코드가 이미 말하는 동작보다 부호, 수명, 순서, backend 제약처럼 비자명한 이유를 설명한다. - Domain은 입력 파일에서 생성된 전체 모델 정의를 소유하고, 파싱 이후 가능한 한 불변으로 취급한다. -- AnalysisModel은 현재 step에서 활성화된 elements, loads, boundary conditions, properties/materials의 view를 제공하며 Domain을 복사하지 않는다. +- AnalysisModel은 현재 step에서 활성화된 elements, loads, boundary conditions, properties/materials의 non-owning view를 제공하며 Domain을 복사하지 않는다. 따라서 Domain은 AnalysisModel보다 오래 살아야 한다. - DofManager는 node별 자유도 정의, constrained/free mapping, equation numbering, sparse pattern ownership을 전담한다. Node 또는 Element 내부에 equation id를 분산 저장하지 않는다. -- AnalysisState는 displacement, velocity, acceleration, temperature, external/internal force, residual, time/increment/iteration, element state를 소유한다. -- MKL, TBB, HDF5 API는 solver core에 직접 노출하지 않는다. `LinearSolver`, `ParallelFor`, `ResultsWriter`, `Vector`, `Matrix`, `SparseMatrix` adapter 경계 뒤에 둔다. +- AnalysisState는 해당 procedure가 실제로 사용하는 mutable solution과 recovery row만 소유한다. V0는 full displacement/external/internal force/residual/reaction과 step/frame 및 beam recovery rows만 보관하며 미래 state를 미리 할당하지 않는다. +- MKL, TBB, HDF5, Win32 API와 vendor type은 public solver core에 노출하지 않는다. `LinearSolver`, `ParallelFor`, `ResultsWriter`, `Vector`, `Matrix`, `SparseMatrix` 경계 뒤에 둔다. +- 해석 단계는 실패할 수 있는 candidate를 완성하고 검증한 뒤 소유 state/output에 반영한다. 실패 시 기존 state와 기존 최종 HDF5를 가능한 계약 범위에서 보존한다. + +### 선형 정적 해석 불변식 + +- `Analysis::run()`의 실제 단계와 객체별 책임은 `docs/ARCHITECTURE.md`의 해석 실행 흐름을 따른다. +- Full stiffness를 stable free/constrained 순서로 `Kff/Kfc/Kcf/Kcc`에 분할하고, `Kff` factorization을 load assembly보다 먼저 수행한다. +- Effective RHS는 `Ff - Kfc * dc`이며 substitution 뒤 full displacement를 복구한다. 모든 DOF가 constrained인 유효한 모델의 `0 x 0 Kff`를 singular error로 바꾸지 않는다. +- Reaction과 free-equilibrium evidence는 조립된 full residual `K*d - F`에서 구한다. Constrained 성분은 physical reaction이고 free 성분은 residual evidence다. +- Sparse assembly는 element-local contribution과 stable COO ordering, 고정된 reduction을 사용한다. 병렬 worker가 global CSR storage를 직접 갱신하지 않는다. +- Element end action, positive-local-x section resultant, Gauss generalized result와 section-point stress는 서로 다른 identity와 부호 계약을 가진다. Station mismatch를 평균으로 합치지 않는다. + +### 개발 운영 인프라 + - Codex custom agent의 `model_reasoning_effort` 기본값은 `extra high`로 둔다. - Harness runner는 `scripts/execute.py`에 둔다. - `scripts/execute.py`는 `feat-` branch prefix를 사용한다. @@ -53,6 +78,15 @@ - B33 reference row는 component별 Abaqus scale로 `absolute_floor + 1e-6 * reference_scale`을 적용한다. Reference 값을 zero-clamp하거나 누락 row를 무시하지 않는다. - `reference/cantilever beam/` artifact는 rename, rewrite 또는 보정하지 않는다. +## 기능을 추가할 때의 판단 기준 + +- 새 element는 요구조건과 formulation을 승인한 뒤 semantic mapping, property/material 연결, DOF/scatter, local kernel, deterministic assembly, recovery, HDF5 row identity, reference/physics evidence를 함께 설계한다. +- 새 load 또는 constraint는 parser 인식만 추가하지 않는다. Source target resolution, stable application order, full-space assembly, partition/effective RHS, diagnostic과 결과 의미까지 연결한다. +- 새 analysis procedure는 기존 선형 정적 lifecycle에 조건문을 누적하지 않는다. 필요한 state, equation, solver lifecycle과 recovery contract를 별도 요구조건·ADR·formulation으로 정의한다. +- 새 backend는 기존 public interface를 유지하고 vendor lifecycle, integer/index conversion, runtime dependency와 failure translation을 adapter 내부에 격리한다. +- 새 output quantity는 계산식뿐 아니라 units, coordinate system, source/internal identity, HDF5 schema, mandatory 여부, reference projection과 tolerance를 동시에 정의한다. +- Element API에 kernel이 존재하는 것과 Abaqus keyword/CLI에서 그 기능을 노출하는 것은 별도 계약이다. 예를 들어 V0의 line-load kernel은 `*DLOAD` 지원을 뜻하지 않는다. + ## 개발 프로세스 - TDD를 기본으로 한다. 구현은 `RED -> GREEN -> VERIFY` 순서를 따른다. - CRITICAL: 빌드 경고를 새로 추가하지 말 것. @@ -88,7 +122,9 @@ AI 에이전트는 유한요소 구조해석 지식이 필요할 때 FEM wiki를 | 물리 검토 | `physics-evaluation-agent` | `fesa-physics-sanity` | `docs/physics-evaluations/-physics-evaluation.md` | | 배포 준비 | `release-agent` | `fesa-release-readiness` | `docs/releases/-release.md` | -## 명령어 +## 최소 검증 진입점 + +세부 target graph, dependency normalization과 Windows runtime staging은 `docs/ARCHITECTURE.md`와 실제 CMake 파일을 따른다. `.harness/config.json`이 존재하면 그 설정을 우선한다. ### Harness Python 검증 @@ -106,18 +142,19 @@ python scripts/execute.py --push ### CMake/CTest 프로젝트 ```powershell -cmake -S . -B .harness/build -A x64 +$gtestSource = "C:/path/to/googletest" +$mklDir = "C:/path/to/oneAPI/mkl/lib/cmake/mkl" +$tbbDir = "C:/path/to/oneAPI/tbb/lib/cmake/tbb" +$hdf5Dir = "C:/path/to/HDF5/cmake" + +cmake --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 ` + "-DFESA_GTEST_SOURCE_DIR=$gtestSource" ` + "-DMKL_DIR=$mklDir" ` + "-DTBB_DIR=$tbbDir" ` + "-DHDF5_DIR=$hdf5Dir" cmake --build .harness/build --config Debug ctest --test-dir .harness/build -C Debug --show-only=json-v1 ctest --test-dir .harness/build -C Debug --output-on-failure ``` -### Visual Studio solution 프로젝트 - -```powershell -MSBuild.exe MyProject.sln /m /p:Configuration=Debug /p:Platform=x64 -.\build\tests\Debug\MyProjectTests.exe -``` - -실제 solution, preset, 테스트 명령은 `.harness/config.json`과 프로젝트 문서를 -우선한다. +`FESA_GTEST_SOURCE_DIR`는 approved local GoogleTest source checkout을 반드시 가리켜야 한다. MKL/TBB/HDF5가 기본 package search에서 발견되지 않는 환경에서는 나머지 세 config directory도 명시한다. FESA 제품 검증은 solution-only MSBuild가 아니라 CMake target과 CTest를 기준으로 한다. diff --git a/docs/ADR.md b/docs/ADR.md index f04328a..dcf976d 100644 --- a/docs/ADR.md +++ b/docs/ADR.md @@ -39,7 +39,7 @@ solution과 test command를 명시한 직접 MSBuild 프로젝트도 검증할 **이유**: 모델 정의, step activation, equation system, transient/nonlinear state가 섞이면 parser, assembler, solver, result writer가 강하게 결합된다. 분리된 상태 모델은 선형 정적 해석에서 시작해 비선형, 동적, thermal coupling으로 확장하기 쉽다. -**트레이드오프**: 초기 class 수가 늘어난다. Phase 1에서는 interface를 얇게 유지하고 displacement 중심 state부터 구현한다. +**트레이드오프**: 초기 class 수가 늘어난다. V0에서는 interface를 얇게 유지하고 실제 선형 정적 frame에 필요한 state만 구현한다. ### ADR-005: 공식 결과 파일은 HDF5로 하고 reference 결과는 Abaqus CSV로 둔다 **결정**: FESA solver의 authoritative result output은 `results.h5` HDF5이다. Abaqus reference results는 기능별 reference model contract가 지정한 `reference//` 아래 CSV 파일로 저장하며, verification은 FESA HDF5 rows와 Abaqus reference CSV rows를 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 비교한다. 신규 reference는 canonical 파일명을 사용하고, 승인된 기존 bundle의 legacy alias는 해당 기능 계약에 정확한 경로를 기록한 경우에만 허용한다. @@ -112,3 +112,72 @@ solution과 test command를 명시한 직접 MSBuild 프로젝트도 검증할 **이유**: 자유단 moment처럼 이론적으로 0인 값에는 행별 상대오차가 정의되지 않으며 Abaqus 결과에 작은 수치 잔차가 남을 수 있다. Component scale을 사용하면 전체 물리량 크기에 비해 작은 잔차를 허용하면서 각 row를 결정적으로 판정할 수 있다. **트레이드오프**: 큰 component scale은 zero row의 허용폭을 넓힌다. 이를 완화하기 위해 quantity와 component를 섞지 않고 Abaqus 값만 scale에 사용하며, 모든 row의 absolute/normalized error와 worst row를 보고하고 누락·추가·nonfinite row를 tolerance 전에 실패시킨다. + +### ADR-015: 외부 CMake target을 FESA 경계로 정규화하고 Windows runtime closure를 명시한다 + +**결정**: MKL, TBB, HDF5 CONFIG package가 제공하는 target은 dependency module에서 +`Fesa::MKL`, `Fesa::TBB`, `Fesa::HDF5`로 정규화한다. Product target은 이 경계만 +`PRIVATE` link하고 public header에 vendor/Win32 type을 노출하지 않는다. Approved Windows +환경에서는 packaged shared HDF5 C target을 우선하며, CLI와 test executable 옆에 TBB, +MKL, OpenMP, Intel math runtime, HDF5를 포함한 실제 runtime DLL closure를 POST_BUILD로 +stage한다. + +**이유**: Package version이나 shared/static variant에 따라 imported target 이름과 숨은 +runtime dependency가 달라질 수 있다. Configure와 link 성공만 확인하면 GoogleTest +discovery 또는 배포된 CLI가 `0xc0000135`로 실패할 수 있다. FESA-owned target과 명시적 +runtime closure는 module code와 실행 환경을 package 세부사항에서 분리한다. + +**트레이드오프**: Windows staging CMake가 길어지고 새 dynamic dependency마다 runtime +audit가 필요하다. 대신 개인 설치 경로를 source에 하드코딩하거나 developer `PATH`에 +의존하지 않고 build tree executable을 재현 가능하게 실행할 수 있다. + +### ADR-016: 결정론과 failure atomicity를 correctness contract로 취급한다 + +**결정**: Parallel element 계산은 index별 독립 buffer만 쓰고, COO tuple ordering과 +floating-point sum은 join 이후 고정된 serial 순서로 수행한다. Result recovery, solver +output, HDF5 writer는 candidate를 완성·검증한 뒤 caller-owned state 또는 final file에 +commit한다. HDF5는 same-directory temporary file을 checked close/reopen한 후에만 atomic +finalization한다. + +**이유**: Reference comparison과 물리 검토는 row identity와 작은 수치 차이에 민감하다. +Thread scheduling 또는 중간 실패가 sparse bytes, result order, 이전 output을 바꾸면 같은 +입력에 대한 evidence를 신뢰할 수 없다. + +**트레이드오프**: Serial reduction과 candidate copy가 throughput과 memory를 더 사용할 수 +있다. 성능 최적화는 동일한 ordering, failure preservation, reference 결과를 증명할 때만 +대체할 수 있으며, nondeterministic global sparse write는 허용하지 않는다. + +### ADR-017: Essential constraint는 stable elimination으로 적용하고 reaction은 full residual로 정의한다 + +**결정**: V0는 DofManager의 stable free/constrained order로 full stiffness를 +`Kff/Kfc/Kcf/Kcc`로 분할하고 `Kff * df = Ff - Kfc * dc`를 푼 뒤 full displacement를 +복구한다. 모든 DOF가 constrained인 모델의 `0 x 0 Kff`는 유효한 trivial factorization과 +empty substitution이다. Recovery의 full residual `r = K*d - F`를 reaction vector로 +보존하며 constrained entry는 physical reaction, free entry는 equilibrium evidence다. + +**이유**: Equation numbering과 prescribed displacement를 한 owner가 관리하면 nonzero +constraint, no/all/mixed constraint가 같은 수식과 stable order를 사용한다. Full residual은 +element end action을 별도로 합산하는 경로보다 조립·하중·해법 전체의 equilibrium을 직접 +검증한다. + +**트레이드오프**: Full K와 네 partition을 유지하는 메모리 비용이 있고 reaction vector의 +free entry가 정확한 0이라고 가정할 수 없다. V0에는 penalty, MPC, Lagrange multiplier를 +혼합하지 않으며, 추가 constraint policy는 별도 formulation과 equation/output 계약을 +요구한다. + +### ADR-018: Kernel 존재와 제품 노출을 분리하고 계층형 검증을 요구한다 + +**결정**: Local element/load/recovery kernel이 존재해도 syntax, semantic Domain mapping, +analysis orchestration, mandatory HDF5와 diagnostic 계약이 연결되지 않으면 CLI 지원으로 +간주하지 않는다. 검증은 unit, integration, reference comparison, physics sanity를 서로 +대체할 수 없는 계층으로 유지한다. Reference가 가능하지 않은 quantity는 명시적 N/A와 +analytical/schema/physics 대체 evidence를 요구한다. + +**이유**: Unit test는 수식과 validation을, integration test는 lifetime과 호출 순서를, +reference comparison은 외부 solver와의 수치 일치를, physics sanity는 공통-mode 오류와 +model adequacy를 검출한다. 한 계층의 성공만으로 parser exposure 또는 물리 correctness를 +추론하면 지원 범위와 검증 강도가 과장된다. + +**트레이드오프**: 작은 기능도 여러 계약과 evidence를 함께 준비해야 하므로 개발 속도가 +느려진다. 대신 `*DLOAD`처럼 kernel은 있지만 입력에 노출되지 않은 기능, stress처럼 +mandatory output이지만 Abaqus reference가 N/A인 기능을 정확하게 표현할 수 있다. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 58fa43c..0c2e478 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -17,39 +17,32 @@ source of truth는 그 계약을 전체 solver architecture의 모듈과 데이터 흐름에 배치한다. 아래에 나타난 비선형, 동적, thermal 및 다른 element 계층은 장기 확장 경계이며 V0 지원 범위가 아니다. -## 디렉토리 구조 +## 현재 구현된 디렉토리 구조 ```text +include/fesa/ # backend-neutral public C++ API src/ fesa/ - core/ # ids, status, diagnostics, units, small value types + analysis/ # Analysis lifecycle, V0 LinearStaticAnalysis + app/ # CLI application and main + assembly/ # deterministic stiffness/load assembly, ParallelFor adapter + constraints/ # essential-constraint elimination and reconstruction + core/ # source identity, status, diagnostics + elements/ # V0 EulerBeam3D kernel and recovery + fem/ # DOF/equation numbering and sparse pattern io/ - abaqus/ # .inp lexer/parser, keyword subset, include policy - hdf5/ # HDF5 result writer/reader, schema versioning - model/ # semantic model: nodes, elements, sets, materials, sections, steps - fem/ # DOF space, equation numbering, quadrature, shape functions - elements/ # truss/bar, beam, plane, solid, shell element routines - materials/ # elastic/plastic material contracts and state variables - assembly/ # local-to-global mapping, sparse pattern, COO/CSR assembly - constraints/ # essential BC, MPC, penalty or elimination policies + abaqus/ # .inp syntax reader and semantic Domain mapper + hdf5/ # private HDF5 writer and atomic finalization + math/ # owning Vector, row-major Matrix, 0-based CSR SparseMatrix + model/ # concrete V0 semantic records and immutable Domain + results/ # recovery records, full residual, ResultsWriter boundary solvers/ - linear/ # MKL PARDISO backend, iterative backend boundary - nonlinear/ # Newton control, residual/tangent norms, increments - analysis/ # static, modal, dynamic, nonlinear procedure drivers - results/ # recovery, field/history output, diagnostics - validation/ # comparison metrics and tolerance helpers - math/ # owning Vector, row-major Matrix, CSR SparseMatrix adapters + linear/ # LinearSolver interface and MKL PARDISO adapter tests/ - unit/ - integration/ - reference/ + unit/ # local contracts and failure paths + integration/ # analysis orchestration and CLI contracts + reference/ # HDF5-to-Abaqus projection and comparison reference/ - / - model.inp - metadata.json - _displacements.csv - _reactions.csv - _internalforces.csv - _stresses.csv + / # approved read-only Abaqus input/CSV bundle .agents/ skills/ # Harness and review skills .codex/ @@ -64,6 +57,10 @@ scripts/ phases/ # Optional generated phase plans ``` +`materials/`, nonlinear/dynamic analysis, MPC/penalty policies, general element factories, +history output과 production validation module은 장기 확장 경계이지 현재 구현된 module이 +아니다. 새 디렉토리와 추상 계층은 승인된 기능이 실제로 필요로 할 때 추가한다. + ## Harness Execution Layer Harness는 solver core와 분리된 세 계층의 개발 운영 인프라다. @@ -74,17 +71,47 @@ Harness는 solver core와 분리된 세 계층의 개발 운영 인프라다. Runner는 `git add -A`를 사용하므로 clean worktree 또는 별도 Git worktree가 실행 전제다. 전체 동작 계약은 `docs/HARNESS_WORKFLOW.md`, 설치와 `.harness/config.json` 설정은 `docs/HARNESS.md`를 source of truth로 삼는다. +## CMake target과 dependency graph + +Root CMake project는 C++17, extension off, CMake 3.25 이상을 요구하고 +`cmake/FesaDependencies.cmake`, `src/fesa`, `tests`를 차례로 구성한다. + +```text +MKL CONFIG package ─> Fesa::MKL ─┐ +TBB CONFIG package ─> Fesa::TBB ─┼─> fesa_solver (STATIC) ─> fesa_cli +HDF5 CONFIG package ─> Fesa::HDF5 ─┘ │ + ├─> fesa_unit_tests +approved local GoogleTest source ─> GTest targets ├─> fesa_integration_tests + └─> fesa_reference_tests +``` + +- `FESA_GTEST_SOURCE_DIR`는 네트워크 fetch 대신 승인된 local GoogleTest source checkout을 가리키는 필수 cache path다. +- MKL, TBB, HDF5는 CONFIG package로 탐지한다. Package search가 설치를 찾지 못하면 `MKL_DIR`, `TBB_DIR`, `HDF5_DIR`를 configure 때 지정한다. +- Package별 imported target 이름은 `Fesa::MKL`, `Fesa::TBB`, `Fesa::HDF5`로 정규화한다. Product module은 vendor target 이름을 직접 선택하지 않는다. +- HDF5 package가 shared와 static C target을 모두 제공하면 approved Windows environment에서는 shared target을 우선한다. Static archive의 숨은 compiler-runtime 요구가 link interface 밖으로 새는 것을 피하기 위한 결정이다. +- `fesa_solver`는 외부 dependency를 `PRIVATE`으로 link하고 `/W4 /WX`를 사용한다. 따라서 public header는 MKL/TBB/HDF5/Win32 type을 포함하지 않아야 한다. +- Test executable은 unit, integration, reference 경계를 분리하며 `fesa_tests` target은 세 executable을 build하는 aggregate target이다. Reference target에만 source/build root compile definition을 제공한다. + +### Windows runtime closure + +Configure 성공은 executable이 GoogleTest discovery 또는 CLI 실행 시 필요한 DLL을 찾는다는 +뜻이 아니다. `fesa_cli`와 세 test executable의 POST_BUILD 단계는 TBB, MKL thread/core/default +dispatch, OpenMP, `libmmd.dll`, HDF5를 포함한 imported-target runtime DLL을 executable 옆에 +복사한다. 새 dynamic backend를 도입할 때는 link 성공뿐 아니라 clean environment에서의 +post-build discovery/실행까지 runtime closure로 다뤄야 한다. 개인 설치 absolute path를 +CMake source에 기록하지 말고 config package와 imported target metadata를 확장한다. + ## 모듈 경계 - `core`는 외부 라이브러리에 의존하지 않는다. - `io/abaqus`는 syntax와 semantic mapping만 담당하고 해석 알고리즘을 알지 않는다. - `model`은 Abaqus keyword 문자열이 아니라 solver semantic model을 가진다. -- `fem`은 DOF, interpolation, quadrature, local/global mapping을 제공하되 특정 analysis procedure에 종속되지 않는다. -- `elements`와 `materials`는 local residual/tangent/stress recovery 계약을 제공한다. -- `assembly`는 sparse pattern 생성과 local contribution 조립을 담당한다. -- `constraints`는 essential BC, MPC, penalty/elimination 정책을 분리한다. -- `solvers`는 MKL/TBB 세부 구현을 감추는 backend boundary를 가진다. +- `fem`의 `DofManager`는 DOF, equation ordering, scatter와 sparse pattern을 소유한다. +- `elements`는 local/global stiffness, transformation, optional load kernel과 recovery를 제공한다. V0 material/section은 concrete Domain record다. +- `assembly`는 element-local contribution과 full nodal load를 stable full-DOF space에 조립한다. +- `constraints`는 V0 essential BC elimination과 full/reduced vector 변환을 담당한다. MPC와 penalty는 현재 범위가 아니다. +- `solvers`는 `LinearSolver` 뒤에 MKL PARDISO 세부 구현을 감춘다. TBB는 `assembly/ParallelFor`, HDF5는 `results/ResultsWriter` 경계 뒤에 각각 격리된다. - `analysis`는 step/history data를 받아 procedure를 실행하고 solver backend와 result writer를 조율한다. -- `results`는 HDF5 schema를 통해 nodal, element, integration-point, diagnostic output을 분리한다. +- `results`는 full residual과 beam rows를 복구하고 backend-neutral writer contract를 제공한다. HDF5 schema 구현은 `io/hdf5`가 담당한다. - test helper는 production parser/solver 내부 상태를 우회하지 않는다. ## V0 입력 경계 @@ -139,95 +166,51 @@ CLI pipeline에서는 이 kernel을 호출하지 않는다. Stiffness와 recover 2점 Gauss rule과 부호 규약을 따른다. ## 핵심 객체 모델 + ```text Domain -├── Node -├── Element -├── Material -├── Property -├── NodeSet -├── ElementSet -├── BoundaryCondition -├── Load -└── StepDefinition +├── owns nodes, B33 elements, materials, beam sections, sets +├── owns boundary conditions, nodal loads, one static step +└── owns source path/identity and mapping warnings AnalysisModel -├── active elements -├── active loads -├── active boundary conditions -├── active properties/materials -└── equation system view +├── non-owning view into Domain +├── stable active element/BC/load indices +└── reachable material/section indices + +DofManager +├── owns node x [UX,UY,UZ,URX,URY,URZ] full-DOF numbering +├── owns stable free/constrained order and prescribed values +├── owns element scatter maps +└── owns full-space CSR structural pattern AnalysisState ├── displacement U -├── velocity V -├── acceleration A -├── temperature T ├── external force Fext ├── internal force Fint -├── residual R -├── current time / increment / iteration -└── element state / integration point state - -DofManager -├── node dof definitions -├── constrained/free dof mapping -├── equation numbering -├── sparse matrix pattern ownership -└── full/reduced vector reconstruction +├── residual R and full-index reaction +├── StepFrameIdentity +└── endpoint, Gauss and S11 recovery rows Analysis -├── LinearStaticAnalysis -├── NonlinearStaticAnalysis -├── DynamicAnalysis -├── FrequencyAnalysis -└── HeatTransferAnalysis - -Element -├── Element1D -│ ├── Truss -│ └── Beam -├── Element2D -│ ├── MITC3 -│ └── MITC4 -└── Element3D - ├── Hexahedral - ├── Tetrahedral - ├── Wedge - └── Pyramid - -BoundaryCondition -├── Fix -├── RBE2 -└── RBE3 - -Load -├── NodalLoad -├── PressureLoad -└── BodyForce - -Results -├── ResultStep -├── ResultFrame -├── FieldOutput -└── HistoryOutput +└── LinearStaticAnalysis Vector Matrix SparseMatrix ``` -이 객체 모델 중 V0 `Analysis` 구현은 `LinearStaticAnalysis` 하나이며 `AnalysisState`는 -full displacement, external/internal force, residual, constrained reaction, step/frame -identity와 element recovery rows만 할당한다. Velocity, acceleration, temperature, -iteration history와 nonlinear element state는 V0에서 할당하지 않는다. +Nonlinear/static, dynamic, frequency, heat-transfer procedure와 general element/material/load +base hierarchy는 이 구조 위의 가능한 확장 방향일 뿐 현재 public API가 아니다. 사용 사례가 +승인되기 전에 V0 concrete record를 speculative hierarchy로 감싸지 않는다. ## 상태 관리 - `Domain`은 입력 파일에서 만들어진 전체 모델 정의를 소유한다. 파싱 이후에는 가능한 한 불변으로 취급한다. -- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않고 참조 또는 id 기반 view로 구성한다. +- `LinearStaticAnalysis`가 `Domain`을 소유하고, 그 뒤에 `AnalysisModel`, `DofManager`, `AnalysisState`, stiffness/RHS를 순서대로 만든다. 재사용 시에는 역순으로 해제하여 이전 Domain을 가리키는 view를 남기지 않는다. +- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않으므로 Domain이 반드시 더 오래 살아야 한다. - `DofManager`는 자유도와 방정식 번호를 전담한다. `Node` 또는 `Element` 내부에 equation id를 분산 저장하지 않는다. -- `AnalysisState`는 해석 중 변하는 물리량과 반복 상태를 소유한다. Phase 1에서는 displacement 중심으로 최소 구현하되, 기하비선형과 thermal-stress coupling을 위해 element/internal state 확장 지점을 유지한다. -- 결과는 `ResultStep` -> `ResultFrame` -> `FieldOutput`/`HistoryOutput` 구조로 관리한다. +- `AnalysisState`는 V0 frame에 필요한 다섯 full-DOF vector와 recovery rows만 소유한다. Velocity, acceleration, temperature, iteration history, nonlinear element state는 해당 procedure가 승인될 때 별도 계약으로 추가한다. +- Result recovery는 모든 candidate vector/row를 검증한 뒤 state에 반영한다. 실패한 recovery가 앞선 유효 state를 부분적으로 덮어쓰지 않아야 한다. ## 데이터 흐름 ```text @@ -243,51 +226,47 @@ Abaqus input file -> effective RHS = Ff - Kfc * dc -> LinearSolver::solve(rhs, df) substitution -> full displacement 복구 --> reaction = K*d - F 및 element result 복구 +-> full residual/reaction = K*d - F 및 element result 복구 -> ResultsWriter로 results.h5 atomic finalization ``` 강성행렬 factorization은 하중벡터 조립보다 먼저 수행한다. 반력은 element end action의 -별도 합이 아니라 조립된 전체 residual에서 구한다. +별도 합이 아니라 조립된 전체 residual에서 구한다. Constrained component는 physical +reaction이고 free component는 equilibrium residual evidence로 full-index vector에 남긴다. ## 해석 실행 흐름 -`Analysis::run()`은 Template Method로 다음 V0 흐름을 고정한다. 해석 종류별 class는 -승인된 procedure contract 안에서 필요한 단계만 재정의한다. +`Analysis::run()`은 Template Method로 다음 여덟 hook의 순서와 fail-fast 경계를 고정한다. -```text -initialize -buildAnalysisModel -buildDofMap -buildSparsePattern -assembleStiffness -partitionConstraints -factorize -assembleLoads -formEffectiveRhs -substitute -reconstructDisplacement -recoverResults -writeResults -``` +| 순서 | Hook | 주요 작업과 생성되는 소유 객체 | 순서/실패 불변식 | +| --- | --- | --- | --- | +| 1 | `initialize(request)` | `.inp` syntax read, semantic map, owned immutable `Domain`, sorted warnings | 이전 run의 dependent object를 역순으로 제거하고 parse/map 실패를 input category로 반환한다. | +| 2 | `buildAnalysisModel()` | non-owning `AnalysisModel` view | Domain을 복사하지 않으며 Domain lifetime 안에서만 사용한다. | +| 3 | `buildDofMapAndSparsePattern()` | `DofManager`, zero-initialized `AnalysisState` | Stable full/free/constrained numbering과 structural pattern을 한 소유자에게 둔다. | +| 4 | `assembleAndPartitionStiffness()` | full CSR K와 `Kff/Kfc/Kcf/Kcc` | Element-local buffer를 deterministic하게 reduce하고 structural zero와 stable order를 보존한다. | +| 5 | `factorize()` | retained `Kff` factorization | 모든 load assembly보다 먼저 호출한다. Valid fully constrained model의 `0 x 0 Kff`는 trivial success다. | +| 6 | `assembleLoadsAndEffectiveRhs()` | full F와 `Ff-Kfc*dc` | Semantic load source order와 finite sum을 보존하며 solver를 호출하지 않는다. | +| 7 | `substituteAndReconstruct()` | free solution과 full displacement | Factorization을 재수행하지 않고 substitution한 뒤 prescribed value를 stable order로 복구한다. | +| 8 | `recoverAndWriteResults()` | full residual/reaction, beam rows, final HDF5 | Recovery candidate를 원자적으로 commit하고 writer 성공 뒤에만 최종 output을 교체한다. | 비선형 정적 및 동적 해석은 V0 범위가 아니며 별도 ADR과 formulation을 승인한 뒤 이 -lifecycle의 확장 지점을 사용한다. +lifecycle과 state/equation 계약을 확장한다. 기존 hook 사이에 조용히 반복·증분·시간 적분 +동작을 삽입하지 않는다. ## 설계 패턴 -- Strategy Pattern: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`를 교체 가능한 전략으로 둔다. +- Strategy/Adapter Pattern: 현재 교체 가능한 public 경계는 `LinearSolver`, `ParallelFor`, `ResultsWriter`다. Vendor API는 concrete adapter implementation 안에만 둔다. - Template Method Pattern: `Analysis::run()`은 공통 실행 흐름을 고정하고 세부 단계는 procedure별로 재정의한다. -- Factory + Registry Pattern: Abaqus keyword와 내부 객체 생성을 분리한다. 예: `*Element, type=S4` -> `MITC4ElementFactory`. -- Adapter Pattern: MKL, TBB, HDF5 API는 solver core에 직접 노출하지 않는다. -- Runtime Polymorphism: 요소, 재료, 하중, 경계조건은 base interface를 통해 다룬다. 대규모 모델 성능 최적화가 필요하면 assembly 내부에서 타입별 batch 처리 또는 kernel 분리를 추가한다. +- Syntax/Semantic separation: `AbaqusInputReader`는 syntax record를 만들고 `AbaqusDomainMapper`가 승인된 keyword 의미를 concrete Domain record로 변환한다. +- Runtime Polymorphism: V0에서는 backend 경계에만 사용한다. 요소/재료/하중 base hierarchy와 factory/registry는 두 번째 실제 구현이 필요해질 때 trade-off를 다시 결정한다. - RAII: MKL handle, HDF5 file/dataset, temporary solver workspace의 수명과 오류 처리를 wrapper에 묶는다. ## Sparse Matrix Policy -- assembly는 초기에는 COO triplet 수집 후 CSR finalize를 기준으로 한다. +- Assembly는 element마다 index-addressed contribution buffer를 만들고, join 뒤 COO tuple을 stable order로 정렬해 한 thread에서 순서대로 합산한 후 CSR로 finalize한다. - `SparseMatrix`는 0-based CSR 데이터를 소유하는 별도 타입이며 dense `Matrix`를 상속하지 않는다. MKL PARDISO backend는 adapter 경계에서 필요한 descriptor와 indexing을 변환한다. -- matrix symmetry, definiteness, singularity diagnostic을 구조화된 diagnostic으로 남긴다. -- deterministic assembly를 위해 TBB element loop는 thread-local contribution buffer 또는 two-pass sparse assembly를 사용한다. +- CSR row offset, sorted-unique column, dimensions, finite values를 construction boundary에서 검증하며 structural zero를 삭제하지 않는다. +- Parallel worker는 global sparse matrix나 shared reduction accumulator를 직접 갱신하지 않는다. Worker별 failure slot과 contribution만 쓰고, deterministic reduction은 join 뒤에 수행한다. +- Matrix symmetry와 factorization/substitution failure는 solver adapter가 구조화된 solver diagnostic으로 번역한다. 승인되지 않은 regularization이나 fallback으로 singularity를 숨기지 않는다. ## Dense Math Policy @@ -299,8 +278,9 @@ lifecycle의 확장 지점을 사용한다. - MKL header와 MKL-specific type은 adapter implementation 밖으로 노출하지 않는다. ## Parallel Policy -- 첫 번째 oneTBB 적용 지점은 element-local matrix/residual 계산이다. -- 전역 sparse write는 thread-local buffer 또는 deterministic reduction으로 제한한다. +- `ParallelFor`는 `[0,count)` index-addressed 독립 작업만 노출하며 `SerialParallelFor`와 `TbbParallelFor`가 같은 observable contract를 가진다. +- 첫 oneTBB 적용 지점은 element-local stiffness 계산이다. 각 callback은 자기 index의 output slot만 쓴다. +- 전역 sparse write와 부동소수 reduction은 parallel callback 밖의 deterministic 단계로 제한한다. - MKL 내부 thread와 TBB element loop가 oversubscription을 만들지 않도록 thread count와 task arena 정책을 명시한다. ## HDF5 Result Schema @@ -325,8 +305,10 @@ Schema requirements: - Abaqus reference results는 `reference//` 아래 CSV 파일이다. - Verification은 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 FESA HDF5 rows와 Abaqus reference CSV rows를 비교한다. - FESA HDF5에서 추출한 deterministic CSV view는 optional debugging/review artifact이며 공식 solver output 또는 reference artifact가 아니다. -- Writer는 임시 HDF5 파일을 완성한 뒤 최종 경로로 교체하며 실패 시 불완전한 - `results.h5`를 남기지 않는다. +- Writer는 final과 같은 directory의 임시 HDF5에 전체 schema를 쓴 뒤 flush, checked close, + read-only reopen/self-check를 수행한다. Existing final은 `ReplaceFileW`, 새 final은 + `MoveFileExW(..., MOVEFILE_WRITE_THROUGH)`로 완료하며 실패 시 temporary artifact를 + 정리하고 불완전한 파일을 정상 `results.h5`로 노출하지 않는다. ## V0 결과 복구와 reference normalization @@ -357,3 +339,20 @@ fesa.exe --output `5=factorization/substitution`, `6=HDF5 output`으로 고정한다. Diagnostic은 `severity`, `code`, `file`, `line`, `keyword`, `entity_identity`, `message`를 가지며 stderr에 deterministic한 순서로 출력한다. + +## 기능 확장 플레이북 + +다음 표는 코드 위치만이 아니라 함께 바뀌어야 하는 계약 경계를 나타낸다. 한 열만 +구현하고 다른 열을 생략하면 internal utility 또는 실험 kernel일 수는 있어도 제품 기능은 +아니다. + +| 기능 유형 | 시작 전에 고정할 것 | 주요 구현 경계 | 함께 검증할 것 | 피해야 할 shortcut | +| --- | --- | --- | --- | --- | +| 새 element/material | DOF, interpolation, constitutive law, integration, local axes/sign, invalid geometry/property | Domain record와 mapper, element kernel, DofManager scatter/pattern, SparseAssembler, ResultRecovery | rigid modes/rank/energy, patch·analytical test, rotated coordinates, reference/physics | 기존 TYPE을 비슷한 kernel에 alias, source ID와 internal index 혼용, 검증 전 범용 hierarchy 추가 | +| 새 load/constraint | Abaqus target grammar, application order, units, follower 여부, prescribed-value 의미 | Syntax/mapper, Domain target, full-space LoadAssembler 또는 constraint partition, diagnostics | set/direct target ambiguity, multi-instance identity, nonfinite sum, `Ff-Kfc*dc`, reaction | Element load kernel 존재를 parser 지원으로 간주, penalty를 elimination에 몰래 혼합 | +| 새 analysis procedure | governing equation, state variables, increment/time lifecycle, tangent/residual, convergence와 output frame | 별도 Analysis implementation, procedure-specific state/equation owner, solver interface extension | orchestration order, failure atomicity, restart/frame identity, numerical benchmark | V0 hook 사이에 조건문으로 반복/시간 적분 삽입, 사용하지 않는 future state 선할당 | +| 새 numerical backend | matrix/index contract, lifecycle, reusable state, failure taxonomy, thread/runtime policy | 기존 `LinearSolver` 또는 `ParallelFor` interface의 concrete adapter, CMake normalized target | empty/dimension/extreme-scale input, repeated call, failed-output preservation, clean runtime discovery | Vendor type을 public header에 노출, silent fallback/regularization, absolute install path 고정 | +| 새 output/reference quantity | 물리 정의, location, sign, units, coordinates, stable row identity, mandatory 여부, tolerance | Result record/recovery, AnalysisState, ResultsWriter/HDF5 schema, comparator projection | schema dtype/shape, ordering, nonfinite rejection, identity inventory, reference N/A 대체 evidence | 서로 다른 result identity 혼합, station mismatch 평균, output request로 mandatory result 제거 | + +모든 확장은 PRD의 제품 완료 정의와 요구조건→정식화→I/O→구현→reference→physics gate를 +따른다. 기존 feature contract에 없는 범위를 편의상 “Abaqus compatible”이라고 넓히지 않는다. diff --git a/docs/PRD.md b/docs/PRD.md index 596c661..9472842 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -15,13 +15,26 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기 1. Abaqus `.inp` keyword subset parser와 내부 `Domain` semantic model 생성 2. `AnalysisModel`, `DofManager`, `AnalysisState` 기반의 step별 equation system 구성 3. 선형 정적 해석을 시작점으로 하는 `Analysis` procedure 계층 -4. 요소, 재료, 경계조건, 하중의 runtime-polymorphic base interface +4. Stable source identity를 보존하는 concrete V0 node, B33 element, material, section, boundary, load record 5. sparse matrix pattern 생성, 전역 행렬/벡터 조립, 제약조건 적용 -6. `LinearSolver` adapter를 통한 MKL PARDISO backend와 향후 iterative solver 확장 +6. `LinearSolver`, `ParallelFor`, `ResultsWriter` interface를 통한 MKL PARDISO, oneTBB, HDF5 backend 격리 7. HDF5 기반 versioned step/frame field-result 저장과 향후 history-output 확장 경계 8. FESA HDF5 rows와 `reference//` 아래 Abaqus reference CSV rows의 직접 비교 9. CMake/MSVC/x64/Debug, CTest 기반 개발 검증 +Element/material 계층의 일반적인 runtime polymorphism, iterative solver, history output은 장기 확장 방향이다. 현재 제품 계약으로 간주하지 않으며, 실제 사용 사례와 성능·수명 요구가 승인되기 전에 추상 base class를 미리 추가하지 않는다. + +## 사용자 관점 제품 흐름 + +1. 사용자는 승인된 Abaqus `.inp` subset으로 모델과 단일 analysis step을 기술한다. +2. FESA는 syntax를 읽은 뒤 semantic mapping과 model validation을 수행한다. 지원하지 않는 모델 의미는 구조화된 diagnostic과 안정된 exit code로 거부한다. +3. 해석 procedure는 active model view, DOF/equation map과 sparse system을 만들고, essential constraint elimination을 적용해 선형계를 factorize하고 substitution한다. +4. FESA는 full displacement를 복구하고 equilibrium residual/reaction과 element 결과를 계산한다. +5. 성공 시 output request와 무관한 mandatory 결과, metadata와 diagnostic을 versioned `results.h5`에 기록한다. 실패 시 불완전한 최종 결과 파일을 정상 결과처럼 남기지 않는다. +6. 검증 workflow는 HDF5 row를 승인된 Abaqus reference CSV identity에 투영해 tolerance를 판정하고, 별도로 equilibrium과 물리적 타당성을 검토한다. + +Parser keyword, element kernel, solver backend 또는 output dataset 중 하나만 추가된 상태는 end-to-end 제품 기능이 아니다. 같은 기능의 입력 의미부터 외부 결과와 검증까지 연결되어야 한다. + ## V0 범위 - 선형 정적 해석 파이프라인 구현 - 승인된 첫 end-to-end 기능: 2절점 3D Euler–Bernoulli beam, Abaqus `TYPE=B33` @@ -59,6 +72,17 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기 - 승인된 `reference/cantilever beam/` B33 결과와 displacement, reaction, section resultant comparison; beam stress reference comparison은 N/A +## 신규 기능의 제품 완료 정의 + +새로운 element, load, constraint, material, analysis procedure 또는 output quantity는 다음 조건을 모두 만족할 때 FESA 제품 기능으로 취급한다. + +1. 지원 범위와 제외 범위, 실패 category, units/coordinates/identity, tolerance가 요구조건과 I/O 계약에 명시되어 있다. +2. 필요한 FEM 정식화와 recovery/sign convention이 검토되었고, 수치 위험과 검증 문제를 numerical review가 다룬다. +3. Syntax와 semantic mapping이 내부 모델에 안정된 source identity로 연결되며 잘못된 입력을 fail-closed로 거부한다. Kernel만 제공하는 기능은 parser/CLI 지원 여부를 별도로 표시한다. +4. DOF, sparse pattern, assembly, constraint, solver lifecycle과 mutable state ownership이 기존 아키텍처에 연결되거나 승인된 새 procedure 경계를 가진다. +5. Mandatory HDF5 schema와 diagnostic, CLI 실패 의미가 정의되고 failure path가 기존 state 또는 최종 output을 오염시키지 않는다. +6. Unit test가 local 수식과 validation을, integration test가 orchestration과 외부 계약을, reference comparison과 physics sanity가 수치·물리 타당성을 각각 증명한다. Reference가 N/A이면 그 이유와 대체 evidence를 명시한다. + ## 기능 요구조건 | ID | 요구조건 | Acceptance Criteria | Verification Method | | --- | --- | --- | --- | @@ -91,7 +115,7 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기 `1e-3`이며 relative coefficient는 `1e-6`이다. - parser, solver, HDF5 writer는 실패 원인을 구조화된 diagnostic으로 보고한다. - oneMKL, oneTBB, HDF5는 CMake에서 명시 탐지하고 실패 원인을 분류한다. -- 대규모 모델 성능 최적화보다 Phase 1 명확성, 테스트 가능성, 검증 traceability를 우선한다. +- 대규모 모델 성능 최적화보다 V0의 명확성, 테스트 가능성, 검증 traceability를 우선한다. ## Acceptance Gates 1. Requirements approved: 기능 범위, 제외 범위, 입력, 출력, tolerance, 검증 물리량이 정의되어 있다. diff --git a/docs/superpowers/plans/2026-08-10-core-documentation-extension-playbook.md b/docs/superpowers/plans/2026-08-10-core-documentation-extension-playbook.md new file mode 100644 index 0000000..37942ff --- /dev/null +++ b/docs/superpowers/plans/2026-08-10-core-documentation-extension-playbook.md @@ -0,0 +1,158 @@ +# FESA Core Documentation Extension Playbook Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 미래 AI Agent가 FESA에 기능을 추가할 때 실제 해석 흐름, 소유권, CMake 설정, 수치 불변식과 검증 경계를 바로 찾을 수 있도록 핵심 문서를 보강한다. + +**Architecture:** 같은 사실을 네 문서에 반복하지 않고 문서별 책임을 분리한다. AGENTS는 프로젝트 배경·목적·핵심 개발 원칙, PRD는 사용자 관점의 제품 계약, ARCHITECTURE는 구현 구조·빌드 흐름·확장 지점, ADR은 장기 의사결정을 담당한다. + +**Tech Stack:** Markdown, C++17/MSVC, CMake/CTest, Intel oneAPI MKL/TBB, HDF5, Abaqus `.inp` subset + +## Global Constraints + +- 수정 범위는 `AGENTS.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`와 이 작업의 spec/plan 문서뿐이다. +- phase 완료 이력, commit hash, 현재 테스트 총개수는 핵심 문서에 기록하지 않는다. +- 승인되지 않은 Abaqus keyword와 해석 기능을 지원하는 것처럼 서술하지 않는다. +- project hook과 Harness는 실행하지 않는다. +- production, test, CMake, reference artifact는 수정하지 않는다. +- direct 검증은 `git diff --check`와 문서·코드·CMake 사이의 정적 대조만 사용한다. + +--- + +### Task 1: 프로젝트 배경과 핵심 개발 지침 보강 + +**Files:** +- Modify: `AGENTS.md` + +**Interfaces:** +- Consumes: root CMake options, normalized dependency targets, `Analysis::run()` lifecycle, public dependency boundaries +- Produces: FESA의 목적과 개발 판단 기준, 문서 탐색 순서, 최소 검증 진입점 + +- [x] **Step 1: 프로젝트 목적과 문서 역할을 선명하게 한다** + +FESA가 검증 가능한 구조해석 솔버라는 점, full Abaqus clone이 아니라 승인된 feature contract를 누적하는 프로젝트라는 점, PRD/ARCHITECTURE/ADR와 기능별 계약의 역할을 기록한다. + +- [x] **Step 2: 개발 시 훼손하면 안 되는 핵심 원칙을 추가한다** + +물리·수치 계약 우선, stable identity, 명시적 소유권, 결정론성, backend isolation, failure atomicity, 공식 HDF5와 read-only reference 원칙을 상위 수준 지침으로 추가한다. 상세 lifecycle은 ARCHITECTURE로 연결한다. + +- [x] **Step 3: 기능 확장 판단 기준을 추가한다** + +입력 계약, semantic model, kernel/assembly, solve/recovery, HDF5/reference/physics evidence가 함께 변경되어야 함을 명시한다. + +- [x] **Step 4: 최소 검증 진입점의 부정확한 예제를 정리한다** + +`FESA_GTEST_SOURCE_DIR`가 빠진 configure와 실제 target이 아닌 `MyProject.sln` 예제를 제거한다. 상세 package/runtime 설명은 ARCHITECTURE로 연결한다. + +- [x] **Step 5: 최소 build 명칭을 실제 CMake 옵션과 대조한다** + +Run: `rg -n "FESA_GTEST_SOURCE_DIR|MKL_DIR|TBB_DIR|HDF5_DIR|Fesa::MKL|Fesa::TBB|Fesa::HDF5" CMakeLists.txt cmake/FesaDependencies.cmake src/fesa/CMakeLists.txt tests/CMakeLists.txt AGENTS.md` + +Expected: AGENTS의 변수와 target 이름이 실제 CMake 정의와 일치한다. + +### Task 2: 제품 계약과 기능 정의 보강 + +**Files:** +- Modify: `docs/PRD.md` + +**Interfaces:** +- Consumes: 승인된 V0 input/output/diagnostic 범위 +- Produces: 사용자 관점 end-to-end 흐름과 신규 기능의 완료 정의 + +- [x] **Step 1: 제품 흐름을 입력→해석→HDF5→검증으로 명확히 한다** + +Syntax parse, semantic validation, linear solve, recovery, mandatory HDF5, optional reference comparison의 사용자 관찰 가능 결과를 기록한다. + +- [x] **Step 2: 현재 구현과 장기 방향을 구분한다** + +현재 concrete V0 model과 backend polymorphism을 정확히 기술하고, runtime-polymorphic element/material 확장은 미래 방향으로 표시한다. + +- [x] **Step 3: 신규 제품 기능의 Definition of Done을 추가한다** + +입력 노출, semantic mapping, solver lifecycle, result schema, diagnostics, unit/integration/reference/physics evidence가 모두 있어야 제품 기능으로 간주한다고 명시한다. + +### Task 3: 실제 아키텍처와 확장 지점 보강 + +**Files:** +- Modify: `docs/ARCHITECTURE.md` + +**Interfaces:** +- Consumes: `src/fesa`와 `tests`의 실제 target/module graph +- Produces: ownership/lifetime, 8-stage lifecycle, CMake/runtime graph, extension playbook + +- [x] **Step 1: directory/target 설명에서 구현과 계획을 구분한다** + +현재 존재하는 static solver library, CLI, unit/integration/reference test target을 명시하고 계획된 디렉터리는 계획이라고 표시한다. + +- [x] **Step 2: 소유권과 8단계 실행 흐름을 표로 추가한다** + +각 단계의 입력, 출력, 소유 객체, 실패 범주와 순서 불변식을 기록한다. + +- [x] **Step 3: CMake dependency와 Windows runtime staging을 설명한다** + +normalized `Fesa::*` targets, shared HDF5 preference, private product linkage, CLI/test executable 옆 runtime DLL staging을 기록한다. + +- [x] **Step 4: 기능 유형별 확장 플레이북을 추가한다** + +element, load/constraint, analysis procedure, backend, output/reference quantity별 변경 지점과 금지되는 shortcut을 기록한다. + +### Task 4: 장기 아키텍처 결정을 추가한다 + +**Files:** +- Modify: `docs/ADR.md` + +**Interfaces:** +- Consumes: 실제 CMake/runtime, deterministic assembly, essential constraints, layered verification behavior +- Produces: 향후 구현이 지켜야 할 결정과 trade-off + +- [x] **Step 1: 외부 의존성 정규화와 runtime closure ADR을 추가한다** + +Vendor target 이름을 `Fesa::*`로 정규화하고 public header에는 노출하지 않으며 Windows executable runtime closure를 staging하는 결정을 기록한다. + +- [x] **Step 2: 결정론성과 failure atomicity ADR을 추가한다** + +Stable COO/reduction, state/output candidate-commit, atomic HDF5 finalization이 성능 옵션이 아니라 correctness contract임을 기록한다. + +- [x] **Step 3: 구속 제거와 full residual ADR을 추가한다** + +`Kff`, `Ff-Kfc*dc`, valid 0x0 system, reaction=`Kd-F`의 결정과 penalty/MPC 비범위를 기록한다. + +- [x] **Step 4: 계층형 검증 ADR을 추가한다** + +Kernel 존재와 parser/CLI 노출을 구분하고 unit→integration→reference→physics gate가 각기 다른 오류를 검출한다는 결정을 기록한다. + +### Task 5: 문서 전용 정적 검증 + +**Files:** +- Verify: `AGENTS.md` +- Verify: `docs/PRD.md` +- Verify: `docs/ARCHITECTURE.md` +- Verify: `docs/ADR.md` + +**Interfaces:** +- Consumes: Tasks 1–4의 문서 변경 +- Produces: 문서 범위·형식·사실 일치 evidence + +- [x] **Step 1: 변경 범위를 확인한다** + +Run: `git status --short` + +Expected: production, test, CMake, reference 경로 변경이 없다. + +- [x] **Step 2: whitespace 오류를 확인한다** + +Run: `git diff --check` + +Expected: exit 0. + +- [x] **Step 3: stale 예제와 승인되지 않은 범위 암시를 검사한다** + +Run: `rg -n "MyProject|full Abaqus compatibility|B31.*지원|현재 테스트.*[0-9]+" AGENTS.md docs/PRD.md docs/ARCHITECTURE.md docs/ADR.md` + +Expected: stale solution 예제와 지원 범위 확대 문구가 없다. Full compatibility/B31은 거부 또는 비범위 문맥에서만 나타난다. + +- [x] **Step 4: 명령·target·lifecycle 이름을 원본과 대조한다** + +Run: `rg -n "FESA_GTEST_SOURCE_DIR|Fesa::MKL|Fesa::TBB|Fesa::HDF5|assembleAndPartitionStiffness|assembleLoadsAndEffectiveRhs|recoverAndWriteResults" AGENTS.md docs/ARCHITECTURE.md cmake/FesaDependencies.cmake src/fesa/analysis/linear_static_analysis.cpp` + +Expected: 문서의 명칭과 구현/CMake 명칭이 일치한다. diff --git a/docs/superpowers/specs/2026-08-10-core-documentation-extension-playbook-design.md b/docs/superpowers/specs/2026-08-10-core-documentation-extension-playbook-design.md new file mode 100644 index 0000000..181477a --- /dev/null +++ b/docs/superpowers/specs/2026-08-10-core-documentation-extension-playbook-design.md @@ -0,0 +1,46 @@ +# FESA Core Documentation Extension Playbook Design + +## 목적 + +`AGENTS.md`, `docs/PRD.md`, `docs/ARCHITECTURE.md`, `docs/ADR.md`를 현재 구현에 맞게 보강한다. 작업 완료 이력이나 일시적인 테스트 개수 대신, 다음 기능을 추가할 AI Agent가 바로 사용할 수 있는 해석 흐름, 소유권, 빌드 설정, 수치 불변식, 확장 경계를 기록한다. + +## 문서별 책임 + +- `AGENTS.md`: FESA의 배경과 목적, 전체 프로젝트에서 훼손하면 안 되는 개발 원칙, 문서 탐색 순서와 기능 확장 시의 판단 기준을 제공한다. 상세 구현·빌드 매뉴얼의 대체물이 아니다. +- `docs/PRD.md`: 사용자가 관찰하는 제품 흐름, 구현된 V0 지원 경계, 신규 기능이 제품 기능으로 인정되기 위한 조건을 정의한다. +- `docs/ARCHITECTURE.md`: 실제 모듈과 target, 객체 소유권, 8단계 해석 수명주기, CMake dependency/runtime graph, 기능 유형별 확장 지점을 설명한다. +- `docs/ADR.md`: 정규화된 외부 의존성, 결정론적·failure-atomic 경계, 구속 제거와 full residual, 계층형 검증을 장기 결정으로 남긴다. + +## 기록할 구현 사실 + +1. 입력은 syntax parse와 semantic mapping을 거쳐 불변 `Domain`이 되고, `AnalysisModel`은 이를 복사하지 않는 view이다. +2. `Analysis::run()`은 initialize, model view, DOF/pattern, stiffness/partition, factorization, load/effective RHS, solve/reconstruct, recovery/write 순서를 고정한다. +3. `DofManager`가 full/free/constrained numbering과 0-based CSR pattern을 단독 소유하며, Node/Element에는 equation ID를 저장하지 않는다. +4. assembly는 element-local buffer, stable COO order, serial ordered reduction으로 결정론적 CSR을 만든다. global sparse storage를 병렬로 직접 갱신하지 않는다. +5. essential constraints는 full K를 `Kff/Kfc/Kcf/Kcc`로 분할하고 `Ff - Kfc*dc`를 푼다. fully constrained 0x0 `Kff`도 유효하다. +6. reaction/equilibrium evidence는 full residual `K*d - F`를 사용한다. constrained 성분은 physical reaction이고 free 성분은 equilibrium residual이다. +7. 외부 API는 `LinearSolver`, `ParallelFor`, `ResultsWriter`와 math adapter 뒤에 둔다. public header에 MKL/TBB/HDF5/Win32 type을 노출하지 않는다. +8. HDF5 writer는 같은 directory의 temporary file, checked close/reopen self-check, atomic finalization을 사용한다. +9. element end action, section resultant, generalized result, stress identity와 sign convention을 섞지 않으며 station mismatch를 평균내지 않는다. + +## 빌드 및 검증 설계 + +- direct build는 Visual Studio generator, x64, Debug를 명시한다. 상세 target graph와 runtime 설명은 `docs/ARCHITECTURE.md`에 두고, `AGENTS.md`에는 최소 검증 진입점만 둔다. +- `FESA_GTEST_SOURCE_DIR`는 필수 local source path이다. `MKL_DIR`, `TBB_DIR`, `HDF5_DIR`는 설치 환경에서 package discovery가 되지 않으면 명시한다. +- production은 `Fesa::MKL`, `Fesa::TBB`, `Fesa::HDF5` normalized target만 사용한다. +- Windows에서는 CLI와 GoogleTest discovery 전에 MKL/TBB/HDF5 및 transitive oneAPI runtime DLL이 executable 옆에 staging되어야 한다. +- 문서 작업 검증은 project hook/Harness를 실행하지 않고 `git diff --check`, 링크·경로·명령·target 이름의 정적 대조로 제한한다. + +## 기능 확장 플레이북 + +- 새 element: 요구조건/정식화/I/O mapping을 먼저 고정하고 kernel, model mapping, DOF pattern, assembly, recovery, output, reference/physics evidence를 함께 확장한다. +- 새 load/constraint: semantic target identity, stable source order, full-space vector/matrix, partition/effective RHS, diagnostics와 output을 함께 검토한다. +- 새 analysis procedure: 기존 V0 lifecycle을 조용히 변경하지 않고 별도 orchestration/state/equation 계약과 gate를 정의한다. +- 새 numerical backend: public interface를 유지하고 adapter 내부에만 vendor API, lifecycle, runtime dependency를 격리한다. +- 새 output/reference quantity: mandatory HDF5 schema, units/coordinates/identity, recovery sign, comparison projection과 tolerance를 동시에 정의한다. + +## 범위 제한 + +- phase 완료 이력, commit hash, 현재 테스트 총개수 같은 일시적 사실을 핵심 문서에 넣지 않는다. +- full Abaqus compatibility, B31 지원, transform/nested assembly, distributed-load parser exposure 등 승인되지 않은 범위를 암시하지 않는다. +- 문서 보강 외 production, test, CMake, reference artifact를 수정하지 않는다.