182 lines
15 KiB
Markdown
182 lines
15 KiB
Markdown
# Project: FESA Structural Solver
|
|
|
|
## 기술 스택
|
|
- C++17 이상
|
|
- MSVC on Windows
|
|
- CMake + CTest
|
|
- Python 3 Harness scripts
|
|
- Intel oneAPI MKL, Intel oneAPI TBB
|
|
- HDF5 result storage
|
|
- Abaqus `.inp` keyword subset input
|
|
|
|
## 프로젝트 정체성
|
|
- FESA는 유한요소법 기반 구조해석 솔버를 단계적으로 구축하고 검증하는 프로젝트이다. 목표는 Abaqus를 흉내 내는 parser를 만드는 것이 아니라, 승인된 입력 범위에서 물리적으로 설명 가능하고 재현 가능한 해석 결과를 만드는 것이다.
|
|
- 새 기능은 입력 keyword만 인식하거나 element kernel만 존재한다고 완성된 것이 아니다. Semantic model, equation system, 해법, 결과 복구, HDF5 외부 계약과 독립 검증 evidence가 하나의 추적 가능한 기능을 이뤄야 한다.
|
|
- 프로젝트의 배경, 목적, 사용자, 범위는 `docs/PRD.md`에서 확인한다.
|
|
- 전체 아키텍처와 모듈별 책임은 `docs/ARCHITECTURE.md`에서 확인한다.
|
|
- 주요 아키텍처 결정과 그 이유 및 트레이드오프는 `docs/ADR.md`에서 확인한다.
|
|
- 외부 reference tolerance 값, 판정 과정, 보고서와 변경 관리는
|
|
`docs/TOLERANCE.md`를 따른다.
|
|
- AI 에이전트는 설계나 구현 결정을 내리기 전에 PRD에서 제품 범위를, ARCHITECTURE에서 소유권과 데이터 흐름을, ADR에서 이미 결정된 트레이드오프를 먼저 확인한다. 기능별 요구조건, 연구, 정식화, 수치/reference 검토, I/O, 구현, 검증, 물리 및 release 의미는 `docs/<feature-id>/`의 승인 문서를 source of truth로 삼는다.
|
|
- Harness는 솔버 자체가 아니라 요구조건, TDD, phase 실행, 검증을 통제하는 개발 운영 인프라이다. 전체 실행 흐름은 `docs/HARNESS_WORKFLOW.md`, 설치와 설정은 `docs/HARNESS.md`를 따른다.
|
|
- FESA는 Abaqus와 독립적인 솔버다. 문서와 구현은 full Abaqus compatibility뿐 아니라
|
|
Abaqus 요소 정식화, 적분, stabilization, 내부 상태 또는 결과 생성 절차의 동등성을
|
|
주장하거나 목표로 삼지 않는다. 수치 결과의 exact equality는 허용되지만 내부 동작
|
|
동등성의 evidence가 아니다.
|
|
- 기능별로 승인된 Abaqus keyword subset만 입력 형식으로 지원한다. Abaqus 결과는 승인된
|
|
비교량의 외부 수치 reference일 뿐 FESA 내부 알고리즘 계약이 아니다.
|
|
- 공식 solver output은 HDF5 `results.h5`이다.
|
|
- reference 결과는 FESA와 같은 Abaqus `.inp` 모델을 Abaqus로 해석해 생성한 CSV 파일이다.
|
|
- reference case는 기능 문서가 지정한 기존 `.inp`와 실제 비교에 필요한 Abaqus CSV 경로를
|
|
그대로 사용한다. canonical 이름, legacy-alias 승인, bundle `README.md`, `metadata.json`,
|
|
Abaqus version/provenance 또는 중복 unit/coordinate/step-frame/schema 기록은 readiness
|
|
조건이 아니다.
|
|
- 비교기는 필요한 source row identity와 component를 결정적으로 대응시키고 누락, 추가,
|
|
중복, nonfinite 값을 tolerance 전에 거부한다. Reference artifact는 rename, rewrite 또는
|
|
보정하지 않는다.
|
|
- 모든 외부 reference comparison은 `docs/TOLERANCE.md`의 공통 정책을 사용한다.
|
|
설계 근거는 `docs/superpowers/specs/2026-08-17-common-reference-tolerance-design.md`와
|
|
ADR-022에 보존한다. 동일 logical quantity, unit dimension, coordinate system과 blocking behavior의
|
|
component family에서 Abaqus-only scale `S=max(abs(reference))`를 구한다. `abs(reference)`가
|
|
`0.01*S` 이하인 행은 `abs(fesa-reference) <= 0.01*S`, 그 외 행은 상대오차 `<=0.05`로
|
|
판정하고, family scale-relative RMS `RMS(error)/S <= 0.01`도 함께 통과해야 한다. 별도
|
|
absolute-error gate는 사용하지 않으며 zero-scale family는 FESA도 exact zero일 때만
|
|
통과한다.
|
|
- B33 section-resultant reference는 `(instance, element label, endpoint node label,
|
|
component)`로 HDF5 element endpoint와 직접 대응한다. Node-station collapse 또는 평균을
|
|
사용하지 않는다. MITC4 `U1/U2/U3`는 blocking, `UR1/UR2/UR3`는 warning-only 분류를
|
|
유지하면서 같은 공통 수치 정책을 사용한다.
|
|
- 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에서만 수행한다. 문서 또는 agent가 artifact naming이나 보조 metadata를 맞추기 위해 파일 변경을 요구하지 않는다.
|
|
- CRITICAL: public header와 implementation 의존성 방향을 역전하지 않는다.
|
|
- CRITICAL: 사람이 계약과 수치식을 대조할 수 있는 단순한 코드를 작성한다. 주석은 코드가 이미 말하는 동작보다 부호, 수명, 순서, backend 제약처럼 비자명한 이유를 설명한다.
|
|
- 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는 해당 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를 사용한다.
|
|
- runner는 `git add -A`로 변경사항을 stage하므로 실행 전 clean worktree 또는 별도 Git worktree를 사용한다.
|
|
- Hook 연결은 `.codex/hooks.json`, 구현은 `scripts/hooks/`와 `scripts/msvc_harness/`에 둔다.
|
|
- PreToolUse는 위험 명령과 C++ production file의 대응 테스트 존재 여부를 검사하는 guardrail이며 RED 실행을 증명하지 않는다.
|
|
- Stop은 `.harness/config.json` 또는 자동 감지 결과에 따라 MSVC build와 test를 모두 검증한다.
|
|
- Generated phase execution outputs remain ignored under `phases/**/step*-output.json`.
|
|
|
|
## 기능을 추가할 때의 판단 기준
|
|
|
|
- 새 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: 빌드 경고를 새로 추가하지 말 것.
|
|
- 기능 개발은 다음 8단계 gate를 순서대로 통과해야 한다.
|
|
1. 요구조건
|
|
2. 연구
|
|
3. 정식화
|
|
4. 수치 검토 + reference model 계약
|
|
5. I/O 정의
|
|
6. 구현 계획 + C++ 구현 + build/test + reference comparison
|
|
7. 물리 검토
|
|
8. 배포 준비
|
|
- 커밋 메시지는 conventional commits 형식을 따른다: `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`.
|
|
|
|
## Agent/Skill Workflow
|
|
`coordinator-agent`는 유일한 main agent로서 `docs/<feature-id>/coordination.md`의 8단계
|
|
worklist, sub-agent dispatch, evidence gate와 workflow closure를 관리한다. 나머지 모든
|
|
profile은 Coordinator가 한정된 단계 작업으로 호출하는 sub-agent이며, peer agent를 직접
|
|
호출하거나 다음 gate로 진행하지 않는다. 유한요소 구조해석 지식이 필요할 때는
|
|
`.codex/skills/fem-theory-query`를 보조 skill로 사용할 수 있다.
|
|
|
|
| 단계 | 담당 sub-agent | 필수 skill | `docs/<feature-id>/` 산출물 |
|
|
| --- | --- | --- | --- |
|
|
| 1. 요구조건 | `requirement-agent` | `fesa-requirements-baseline` | `requirements.md` |
|
|
| 2. 연구 | `research-agent` | `fesa-research-evidence`, 필요 시 `fem-theory-query` | `research.md` |
|
|
| 3. 정식화 | `formulation-agent` | `fesa-formulation-spec` | `formulation.md` |
|
|
| 4. 수치 검토 + reference model 계약 | `numerical-review-agent` | `fesa-numerical-review` | `numerical-review.md`, `reference-model.md` |
|
|
| 5. I/O 정의 | `io-definition-agent` | `fesa-io-contract` | `io.md` |
|
|
| 6. 구현 계획 + C++ 구현 + build/test + reference comparison | `implementation-planning-agent`, `implementation-agent` | `fesa-cpp-msvc-tdd`, 계획 시 project-local `harness` | `implementation-plan.md`, `implementation-report.md`, `build-test.md`, `reference-comparison.md` |
|
|
| 7. 물리 검토 | `physics-evaluation-agent` | `fesa-physics-sanity` | `physics-evaluation.md` |
|
|
| 8. 배포 준비 | `release-agent` | `fesa-release-readiness` | `release.md` |
|
|
|
|
`correction-agent`는 정규 단계가 아니라 반복되거나 원인이 불명확한 구현 실패를 다루는
|
|
on-demand rework sub-agent다. Coordinator가 호출할 때만 `docs/<feature-id>/corrections.md`에
|
|
원인, 수정과 재검증 결과를 기록하고 Implementation 단계로 반환한다.
|
|
|
|
Implementation Planning Agent는 구현 계획 요청에서 `.agents/skills/harness`를 반드시
|
|
사용한다. 먼저 여러 자기완결적 Step의 초안을 제시하고 사용자 승인을 받은 뒤에만
|
|
`phases/index.json`, `phases/<task-name>/index.json`, `phases/<task-name>/stepN.md`를
|
|
생성한다. Harness 실행은 별도 사용자 요청이 있을 때만 수행한다.
|
|
|
|
## 최소 검증 진입점
|
|
|
|
세부 target graph, dependency normalization과 Windows runtime staging은 `docs/ARCHITECTURE.md`와 실제 CMake 파일을 따른다. `.harness/config.json`이 존재하면 그 설정을 우선한다.
|
|
|
|
### Harness Python 검증
|
|
|
|
```powershell
|
|
uv run --with pytest python -m pytest -v -rs
|
|
```
|
|
|
|
### Phase 실행
|
|
|
|
```powershell
|
|
python scripts/execute.py <phase-name>
|
|
python scripts/execute.py <phase-name> --push
|
|
```
|
|
|
|
### CMake/CTest 프로젝트
|
|
|
|
```powershell
|
|
$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
|
|
```
|
|
|
|
`FESA_GTEST_SOURCE_DIR`는 approved local GoogleTest source checkout을 반드시 가리켜야 한다. MKL/TBB/HDF5가 기본 package search에서 발견되지 않는 환경에서는 나머지 세 config directory도 명시한다. FESA 제품 검증은 solution-only MSBuild가 아니라 CMake target과 CTest를 기준으로 한다.
|