Compare commits

...

2 Commits

Author SHA1 Message Date
KOKO\Mimi b7b5fc3835 Merge branch 'feat-linear-static-3d-euler-beam' into dev 2026-08-10 16:34:31 +09:00
KOKO\Mimi 4bb05d23eb docs: add FESA extension guidance 2026-08-10 16:34:20 +09:00
6 changed files with 487 additions and 154 deletions
+56 -19
View File
@@ -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-<phase-name>` 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/<feature-id>-physics-evaluation.md` |
| 배포 준비 | `release-agent` | `fesa-release-readiness` | `docs/releases/<feature-id>-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 <phase-name> --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를 기준으로 한다.
+70 -1
View File
@@ -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/<model-id>/` 아래 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인 기능을 정확하게 표현할 수 있다.
+130 -131
View File
@@ -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-id>/
model.inp
metadata.json
<model-id>_displacements.csv
<model-id>_reactions.csv
<model-id>_internalforces.csv
<model-id>_stresses.csv
<model-id>/ # 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/<model-id>/` 아래 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 <model.inp> --output <results.h5>
`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”이라고 넓히지 않는다.
+27 -3
View File
@@ -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/<model-id>/` 아래 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 EulerBernoulli 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, 검증 물리량이 정의되어 있다.
@@ -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 14의 문서 변경
- 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 명칭이 일치한다.
@@ -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를 수정하지 않는다.