15 KiB
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은 같은 모듈 구조를 사용한다.
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 Beammaterials/elastic: 등방성 선형 탄성constraints: essential BC eliminationsolvers/linear: MKL PARDISOanalysis:LinearStaticAnalysisresults: 단일 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. 핵심 객체 모델
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. 데이터 흐름
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()은 다음 생명주기를 고정한다.
initialize
buildAnalysisModel
buildDofMap
buildSparsePattern
executeProcedure
finalizeResults
Phase 1의 LinearStaticAnalysis::executeProcedure()는 다음을 수행한다.
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. 희소 조립과 병렬성
assembly의 sparse pattern builder가 요소 connectivity와DofManager의 equation mapping으로 sparsity pattern을 생성한다.- oneTBB가 요소별 local contribution을 독립적으로 계산한다.
- worker는 공유 CSR 값 배열에 무질서하게 누적하지 않고 thread-local contribution을 생성한다.
- contribution을 전역 row, column 및 안정된 tie-break key로 정렬한다.
- 고정된 순서로 합산해 대칭 CSR을 생성한다.
- essential BC를 소거해 reduced symmetric system을 만든다.
- 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
최상위 구조:
/
├── 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 matrixtests/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}브랜치 생성 또는 checkoutAGENTS.md와docs/*.mdguardrail 주입- 완료된 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 아키텍처의
요구사항으로 간주하지 않는다.