Files
FESA/docs/ARCHITECTURE.md

472 lines
15 KiB
Markdown

# FESA Architecture
## 1. 목표
FESA의 아키텍처 목표는 Abaqus `.inp` 부분집합을 내부 semantic model로 변환하고,
유한요소 equation system을 구성해 구조해석 결과를 HDF5로 저장하며, reference
comparison과 physics sanity가 가능한 C++20/MSVC 솔버 구조를 제공하는 것이다.
핵심 품질 속성:
- FEM formulation traceability
- explicit I/O contracts
- sparse linear algebra backend isolation
- deterministic verification
- incremental feature addition
- Harness 기반 TDD와 workspace validation
## 2. 디렉터리 구조
public header와 implementation은 같은 모듈 구조를 사용한다.
```text
include/
fesa/
core/
io/
abaqus/
hdf5/
model/
fem/
elements/
materials/
assembly/
constraints/
solvers/
linear/
nonlinear/
analysis/
results/
validation/
src/
fesa/
core/
io/
abaqus/
hdf5/
model/
fem/
elements/
materials/
assembly/
constraints/
solvers/
linear/
nonlinear/
analysis/
results/
validation/
tests/
unit/
integration/
reference/
reference/
<model-id>/
model.inp
<model-id>_displacements.csv
<model-id>_reactions.csv
<model-id>_internalforces.csv
<model-id>_stresses.csv
.agents/
skills/
harness/
review/
.codex/
hooks.json
.harness/
config.example.json
config.json
docs/
scripts/
execute.py
hooks/
msvc_harness/
phases/
```
목표 구조는 장기적인 namespace와 책임 분류다. 실제 소스 디렉터리와 클래스는 해당
기능을 구현하는 phase에서만 만든다.
Phase 1에서 실체화하는 범위:
- `elements/beam`: 2절점 3D Timoshenko Beam
- `materials/elastic`: 등방성 선형 탄성
- `constraints`: essential BC elimination
- `solvers/linear`: MKL PARDISO
- `analysis`: `LinearStaticAnalysis`
- `results`: 단일 step/frame의 field와 diagnostic output
Truss, plane, solid, shell, plasticity, MPC, nonlinear, dynamic, frequency 및 heat
transfer는 목표 taxonomy로만 유지하고 빈 구현을 미리 만들지 않는다.
## 3. 모듈 경계
### `core`
ID, status, diagnostic, source location 및 작은 값 타입을 제공한다. 외부 라이브러리에
의존하지 않는다. 단위 변환 엔진은 두지 않고 일관 단위계 규약만 표현한다.
### `io/abaqus`
`.inp` lexer/parser, flat 또는 Part/Assembly/Instance scope record 및
syntax-to-semantic mapping을 담당한다. 해석 알고리즘과 equation numbering을 알지
않는다. parser의 임시 syntax 객체는 `model`에 노출하지 않는다. `*HEADING`,
`*PREPRINT`, `*RESTART`, `*OUTPUT`은 명시적인 no-op record로 처리하고 일반적인
unknown-keyword ignore 경로를 만들지 않는다.
### `io/hdf5`
HDF5 결과 writer/reader, schema versioning 및 HDF5 resource 수명을 담당한다.
HDF5 handle은 RAII wrapper 밖으로 노출하지 않는다.
### `model`
활성 Instance에서 정규화된 절점, 요소, 집합, 재료, 단면, step, 하중 및
경계조건의 solver semantic model을 소유한다. Part/Assembly keyword record나 MKL
자료구조를 저장하지 않는다.
### `fem`
DOF 정의, equation numbering 계약, quadrature, shape function, Jacobian 및
local/global mapping을 제공한다. 특정 analysis procedure에 종속되지 않는다.
### `elements`와 `materials`
요소의 local contribution과 결과 회복 계약을 제공한다. Phase 1 요소는 선형 문제에
필요한 local stiffness, equivalent load 및 section response만 계산한다.
### `assembly`
local-to-global mapping, sparse pattern 생성, contribution 정렬·병합 및 COO/CSR
변환을 담당한다. 요소 formulation이나 PARDISO handle을 소유하지 않는다.
### `constraints`
essential BC와 full/reduced vector 변환 정책을 담당한다. Phase 1에는 elimination만
구현하고 MPC, penalty 및 Lagrange multiplier는 추가하지 않는다.
### `solvers`
희소 선형계 backend 경계를 제공한다. Phase 1의 `solvers/linear`는 MKL PARDISO를
adapter로 감싸며 symbolic analysis, factorization, solve 및 release 수명을 관리한다.
### `analysis`
step data를 실행 가능한 `AnalysisModel`로 변환하고 DOF, assembly, constraint,
solver 및 result writer를 조율한다. 구체 수치 kernel이나 외부 API를 직접 구현하지
않는다.
### `results`
nodal, element, integration-point, field, history 및 diagnostic output의 semantic
표현을 담당한다. Phase 1에는 nodal/element field와 diagnostic만 실체화한다.
### `validation`
reference mapping, 비교 metric, tolerance와 physics sanity helper를 제공한다.
production parser와 solver 내부 상태를 우회하는 별도 해석 경로를 만들지 않는다.
## 4. 핵심 객체 모델
```text
ParsedDeck (io/abaqus 전용)
├── PartDefinition[]
├── AssemblyDefinition
│ └── InstanceDefinition[1]
├── MaterialDefinition[]
└── StepDefinition
Domain
├── Node
├── Element
├── Material
├── Property
├── NodeSet
├── ElementSet
├── BoundaryCondition
├── Load
└── StepDefinition
AnalysisModel
├── active elements
├── active loads
├── active boundary conditions
├── active properties/materials
└── equation system view
AnalysisState
├── displacement U
├── external force Fext
├── internal force Fint
├── residual R
├── reaction
└── element/integration-point response
DofManager
├── node dof definitions
├── constrained/free dof mapping
├── equation numbering
├── element equation adjacency view
└── full/reduced vector reconstruction
Results
└── ResultStep
└── ResultFrame
├── FieldOutput
├── HistoryOutput
└── DiagnosticOutput
```
장기 목표인 `AnalysisState`의 velocity, acceleration, temperature, increment,
iteration 및 material state는 해당 해석 기능을 구현할 때 추가한다. Phase 1 객체에
사용되지 않는 상태를 미리 할당하지 않는다.
## 5. 상태 관리
- `Domain`은 입력에서 만들어진 전체 모델 정의를 소유한다.
- syntax-to-semantic mapping과 validation이 끝난 `Domain`은 가능한 한 불변으로
취급한다.
- 계층형 입력의 외부 ID는 `(instance name, part-local label)`로 표현하고 내부
dense index와 구분한다. flat 입력은 예약된 global scope를 사용한다.
- 여러 Part를 파싱할 수 있지만 단일 Assembly의 단일 무변환 Instance가 참조하는
Part만 `Domain`에 포함한다.
- `AnalysisModel`은 현재 step에서 활성화되는 객체의 ID/참조 기반 view다. `Domain`
복제하지 않는다.
- `DofManager`는 DOF와 equation numbering을 전담한다. `Node``Element`
equation ID를 저장하지 않는다.
- `AnalysisState`는 해석 중 변하는 물리량만 소유한다.
- 결과는 `ResultStep -> ResultFrame -> FieldOutput/HistoryOutput` 구조로 관리한다.
## 6. 데이터 흐름
```text
Abaqus input file
-> lexer/parser
-> scoped syntax records
-> complete-deck reference resolution
-> flat scope 또는 단일 active Part/Instance 선택
-> set/material/section/load/BC 정규화와 validation
-> immutable Domain
-> StepDefinition
-> AnalysisModel
-> DofManager
-> sparse pattern
-> element contributions
-> deterministic Assembler
-> essential BC elimination
-> MKL PARDISO
-> full state/reaction reconstruction
-> element result recovery
-> Results
-> HDF5 writer
```
파싱, semantic validation, equation construction, solve 및 output 단계는 서로 다른
diagnostic context를 유지한다.
## 7. 해석 실행 흐름
`Analysis::run()`은 다음 생명주기를 고정한다.
```text
initialize
buildAnalysisModel
buildDofMap
buildSparsePattern
executeProcedure
finalizeResults
```
Phase 1의 `LinearStaticAnalysis::executeProcedure()`는 다음을 수행한다.
```text
assemble
applyBoundaryConditions
solve
reconstructFullState
recoverReactions
recoverElementResults
writeResults
```
미래의 비선형·동적 해석은 `executeProcedure` 내부에 각각 Newton 또는 time-step
loop를 소유한다. base class가 모든 해석 종류의 반복 변수를 미리 소유하지 않는다.
## 8. Timoshenko Beam kernel
Phase 1 kernel은 다음 입력만 받는다.
- 두 절점 좌표
- 12개 local/global DOF mapping
- \(E,\nu\)
- \(A,I_y,I_z,J,A_{sy},A_{sz}\)
- 국부 단면축 기준 방향
- 필요한 평가 위치와 회복점
kernel 책임:
- 강건한 국부 직교 기저 생성
- 자연좌표 shape function과 Jacobian 평가
- 축·굽힘·비틀림 2점 Gauss 적분
- 전단 1점 Gauss 적분
- local stiffness와 global transformation
- section strain/resultant와 \(\sigma_{xx}\) 회복
kernel은 Abaqus의 slenderness compensation을 구현하지 않는다. 명시적 전단강성이
없으면 semantic mapper가 \(A_{sy}=A_{sz}=5A/6\)과 `SCF=0`을 적용한다. 명시적
전단강성은 이 기본값을 덮어쓰며 nonzero `SCF`는 거부한다.
## 9. 희소 조립과 병렬성
1. `assembly`의 sparse pattern builder가 요소 connectivity와 `DofManager`
equation mapping으로 sparsity pattern을 생성한다.
2. oneTBB가 요소별 local contribution을 독립적으로 계산한다.
3. worker는 공유 CSR 값 배열에 무질서하게 누적하지 않고 thread-local contribution을
생성한다.
4. contribution을 전역 row, column 및 안정된 tie-break key로 정렬한다.
5. 고정된 순서로 합산해 대칭 CSR을 생성한다.
6. essential BC를 소거해 reduced symmetric system을 만든다.
7. TBB 작업이 끝난 뒤 MKL PARDISO를 호출한다.
성능보다 같은 입력·설정에서의 수치 재현성을 우선한다. 병렬·직렬 결과 비교와 thread
count 변화 테스트를 reference suite에 포함한다.
## 10. 선형해법 backend
`LinearSolver` 경계는 matrix structure, numeric values, RHS를 입력받고 solution과
진단을 반환한다. Phase 1의 유일한 구현은 `PardisoLinearSolver`다.
PARDISO adapter 책임:
- 0-based 대칭 CSR 계약 검증
- analysis, factorization, solve 및 release phase 관리
- MKL error code를 FESA diagnostic으로 변환
- matrix checker와 residual diagnostic 제공
- handle과 workspace의 RAII 수명 관리
반력은 reduced solve 결과를 full vector로 복원한 뒤 원래 시스템의
\(r=Ku-f\)에서 계산한다.
## 11. HDF5 schema
최상위 구조:
```text
/
├── metadata
├── model
│ ├── nodes
│ ├── elements
│ ├── sets
│ ├── materials
│ ├── properties
│ └── id_maps
├── analysis
│ ├── steps
│ ├── boundary_conditions
│ ├── loads
│ └── solver_settings
├── results
│ └── steps/<step-id>/frames/<frame-id>
│ ├── nodal
│ ├── element
│ └── history
└── diagnostics
```
작은 schema 정보와 설명은 attribute로, 수치 배열과 가변 크기 데이터는 dataset으로
저장한다. root metadata에는 schema version, FESA version, 입력 fingerprint,
좌표계 및 단위 정책을 기록한다. 계층형 입력은 Part/Instance 이름, part-local ID와
전단강성 값의 입력/기본값 출처를 함께 저장한다.
## 12. 오류 처리
진단은 최소한 다음 분류를 가진다.
- I/O 및 encoding 오류
- lexical/syntax 오류
- 미지원 keyword/option
- semantic reference 오류
- model validity 오류
- equation system 오류
- numerical solver 오류
- result recovery 또는 HDF5 오류
각 진단은 가능한 경우 source file, line, keyword, entity ID, analysis stage 및 원인을
포함한다.
다음 조건은 묵시적으로 보정하지 않고 실패시킨다.
- 길이가 0인 요소
- 요소축과 평행하거나 길이가 0인 단면 방향 벡터
- 존재하지 않는 절점·집합·재료·단면 참조
- 중첩 집합 순환
- 여러 Assembly/Instance 또는 Instance 평행이동·회전
- Instance가 참조하지 않는 Part entity를 Assembly 집합이 참조하는 경우
- 재료나 단면이 없거나 중복 할당된 요소
- 상충하는 경계조건
- 강체모드가 남은 singular equation system
- NaN 또는 무한대 입력·결과
## 13. 설계 패턴
- Adapter: Abaqus, MKL, TBB 및 HDF5 경계
- RAII: PARDISO handle, HDF5 object와 temporary workspace
- Strategy: 실제 교체 가능성이 있는 solver와 writer 경계
- Template Method: `Analysis::run()`의 공통 생명주기
- Factory: Phase 1에는 B31을 생성하는 명시적 factory
- Registry: 두 번째 실제 요소나 material type이 추가되는 phase에서만 도입
- Runtime polymorphism: assembly가 구체 요소 내부 상태를 알지 않게 하는 최소 계약
대규모 모델에서 virtual dispatch가 병목이라는 측정 결과가 있을 때만 타입별 batch
kernel을 추가한다.
## 14. 검증 구조
- `tests/unit`: 값 타입, parser 단위, shape function, quadrature, transformation,
element matrix
- `tests/integration`: `.inp`에서 HDF5까지 전체 경로
- `tests/reference`: CSV 골든 결과와 FESA HDF5 결과 비교
- `reference/<model-id>`: Abaqus 입력과 현재 사용할 수 있는 결과 CSV
reference comparison request가 비교할 물리량과 CSV 경로 및 물리량별 절대 scale을
명시한다. 요청한 CSV가 없으면 실패하며 요청하지 않은 결과를 통과로 표시하지
않는다. 현재 캔틸레버는 변위, 반력 및 요소 단면력을 요청하고, 단면 도심 응력
adapter는 synthetic CSV로 검증한다.
요소 내력 CSV의 `(Instance, Element Label, Node Label)` 위치에서
`SF1,SF3,SF2,SM3,SM1,SM2`를 \(N,V_y,V_z,T,M_y,M_z\)로 매핑한다. 응력 CSV의
같은 위치에 있는 `Sxx`는 단면 도심값 \(N/A\)와 비교한다. 단일 Instance에서는
Instance 열 생략을 허용하되 comparison request가 제공한 Instance 이름으로
보완한다. Abaqus와 FESA의 정식화가 다른 상관성 비교는 component별 RMSE와
Relative L2를 보고하며 관측값으로 만든 pass/fail tolerance를 적용하지 않는다.
reference helper는 반드시 public parser와 analysis 경로로 FESA 결과를 생성한다.
테스트 전용 경로로 Domain이나 matrix를 직접 주입해 전체 파이프라인 결함을 숨기지
않는다.
## 15. Harness 실행 계층
현재 저장소의 `scripts/execute.py`, `docs/HARNESS.md`
`.agents/skills/harness/SKILL.md`를 실행 계약으로 사용한다.
Executor 동작:
- `feat-{phase-name}` 브랜치 생성 또는 checkout
- `AGENTS.md``docs/*.md` guardrail 주입
- 완료된 step의 `summary`를 다음 prompt에 전달
- 실패 시 이전 오류를 포함해 최대 3회 재시도
- 코드 변경과 phase metadata를 분리해 commit
- step/phase timestamp 기록
- `--push` 사용 시에만 원격 push
Codex hook 동작:
- PreToolUse hook은 위험한 명령 패턴을 검사한다.
- Stop hook은 감지된 C/C++ 프로젝트를 MSVC로 빌드하고 테스트한다.
- `.harness/config.json`이 있으면 해당 설정과 preset을 우선한다.
현재 executor에 없는 `allowed_paths`, `validate_workspace.py`,
`codex/<phase-name>` 브랜치 및 명시적 clean-worktree 정책은 FESA 아키텍처의
요구사항으로 간주하지 않는다.