20 KiB
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
.inpkeyword subset input
프로젝트 정체성
- FESA는 유한요소법 기반 구조해석 솔버를 단계적으로 구축하는 프로젝트이다. 목표는 Abaqus를 흉내 내는 parser를 만드는 것이 아니라, 승인된 입력 범위에서 물리적으로 설명 가능하고 재현 가능한 해석 결과를 만드는 것이다.
- 새 기능은 입력 keyword만 인식하거나 element kernel만 존재한다고 완성된 것이 아니다. Semantic model, equation system, 해법, 결과 복구, HDF5 외부 계약과 독립 검증 evidence가 하나의 추적 가능한 기능을 이뤄야 한다.
- 설계·구현 전에 PRD, ARCHITECTURE, ADR에서 현재 작업에 관련된 제품 범위·소유권·데이터 흐름·결정을 확인한다. C++ naming, formatting, Doxygen와 변경 검증은 CODINGSTYLE을 따른다. 같은 문맥에서 읽은 변경 없는 자료를 다시 읽지 않는다.
- 재사용 가능한 agent, skill과 Harness는 개발 운영 인프라다. 이를 일반화해도 이 저장소가 선택한 MSVC, Abaqus 입력 subset, HDF5 출력과 승인된 수치 계약은 바뀌지 않는다.
- FESA는 Abaqus와 독립적인 솔버다. 문서와 구현은 full Abaqus compatibility뿐 아니라 Abaqus 요소 정식화, 적분, stabilization, 내부 상태 또는 결과 생성 절차의 동등성을 주장하거나 목표로 삼지 않는다. 수치 결과의 exact equality는 허용되지만 내부 동작 동등성의 evidence가 아니다.
- 기능별로 승인된 Abaqus keyword subset만 입력 형식으로 지원한다. Abaqus 결과는 승인된 비교량의 외부 수치 reference일 뿐 FESA 내부 알고리즘 계약이 아니다.
- 공식 solver output은 입력 경로의 lexical sibling인 HDF5
<stem>_results.h5이다. 파일명과 저장 계약은 PRD와 ARCHITECTURE를 따른다. - reference 결과는 FESA와 같은 Abaqus
.inp모델을 Abaqus로 해석해 생성한 CSV 파일이다. - reference case는 기능 문서가 지정한 기존
.inp와 실제 비교에 필요한 Abaqus CSV 경로를 그대로 사용한다. canonical 이름, legacy-alias 승인, bundleREADME.md,metadata.json, Abaqus version/provenance 또는 중복 unit/coordinate/step-frame/schema 기록은 readiness 조건이 아니다. - 비교기는 필요한 source row identity와 component를 결정적으로 대응시키고 누락, 추가, 중복, nonfinite 값을 tolerance 전에 거부한다. Reference artifact는 rename, rewrite 또는 보정하지 않는다.
- 모든 외부 reference comparison의 scale, near-zero/relative/RMS 판정, zero-scale 처리와 보고서는 TOLERANCE의 승인된 공통 정책을 따른다. Numerical Review는 이 정책 안에서 기능별 비교량, identity/component와 blocking/diagnostic 구분을 정의하며 고정된 수치 기준을 임의로 선택·완화하지 않는다. 정책 변경은 해당 문서의 사용자 승인과 ADR 절차를 따른다.
- B33 section-resultant reference는
(instance, element label, endpoint node label, component)로 HDF5 element endpoint와 직접 대응한다. Node-station collapse 또는 평균을 사용하지 않는다. MITC4U1/U2/U3는 blocking,UR1/UR2/UR3는 warning-only 분류를 유지하면서 같은 공통 수치 정책을 사용한다. - CSV는 FESA 공식 output이 아니며, FESA HDF5에서 추출한 deterministic CSV view는 비교 디버깅/검토용 보조 artifact로만 둔다.
문서 기준과 Feature 관리
- 현행 운영 결정은 ADR-028, 역할·인계·실패 처리는 SOLVER_AGENT_DESIGN, skill 적용은 SOLVER_SKILL_DESIGN, 문서 배치·소유권은 FEATURE_DOCUMENTATION을 따른다. 실제 절차는 필요한
SKILL.md와 관련 reference만 읽는다. - HARNESS는 설치·설정·CLI, HARNESS_WORKFLOW는 개발·검증 흐름을 설명한다. 실행 동작은 선택된 설정과 현재
scripts/에 대조하며 구현이 승인된 제품·수치 계약을 바꿀 권한은 없다. - 지속할 계약·evidence가 필요한 Feature는 메인이 안정적인 kebab-case ID와
docs/<feature-id>/를 정한다. 작은 수정에는 새 Feature 폴더나 빈 보고서를 만들지 않는다. - 일반 Feature 작업에서 프로젝트
AGENTS.md,docs/PRD.md,docs/ADR.md는 읽기 전용 기준이다. 현재 작업의 진행 링크를 누적하지 않으며 공통 지침 수정은 별도 사용자 요청 범위에서 수행한다. - 새 Feature를 초기화하면 아래 핵심 문서 3개를 실제 요구사항으로 작성한다. 각 문서는 프로젝트 AGENTS·PRD·ADR를 상대 Markdown 링크로 참조한다.
| 메인 소유 문서 | 내용과 경계 |
|---|---|
FEATURED_AGENTS.md |
Feature ID·목적·지역 지침, 할당 owner와 문서 목록. 현재 checklist는 PRD로 연결 |
PRD.md |
사용자 요구·범위·제외·acceptance와 현재 checklist. 작은 요구사항의 원본이며 복잡한 상세 계약은 필요한 경우만 분리하여 연결 |
ADR.md |
Feature 결정 ID·상태·결정·이유·영향과 owner·승인 근거 |
- 현재 checklist는 PRD 한 곳에 둔다.
requirements.md·검증 matrix는 분리가 필요할 때만 작성하고 PRD에는 요약·링크만 유지한다. Specialist는 할당된 전문 문서만 수정한다. FEATURED_AGENTS.md는 자동 로드되는AGENTS.md가 아니다. 메인은 필요한 Feature context와 관련 경로·절만 인계하며 모든 문서를 매번 재독하도록 요구하지 않는다.- 기존
coordination.md,docs/features/<feature-id>/와 phase 자료는 이력으로 보존하고 필요한 경로·계약 revision을 참조한다. 자동 이동·복제하거나 신규 coordination 상태 파일을 만들지 않는다. - 보고서는 결정·결과, 적용 계약, evidence와 미해결 항목을 간결하게 기록한다. 간단한 구현·build/test·reference 결과는 한 보고서로 모으고 긴 유도·schema는 같은 폴더의 상세 문서로 분리해 연결한다.
- 실제 계약 변경은 관련 evidence의 유효성을 다시 확인한다. 의미 변화 없는 문서 편집마다 고정 handoff·hash·gate 기록을 만들지 않는다. 미실행 검사는 이유를 남기며 승인·통과로 표시하지 않는다.
- 소스·테스트·기계 생성 로그/결과·read-only reference 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 기준으로 검증한다.
- 동작 추가·수정은 해당 동작을 확인하는 테스트로 검증한다. 버그는 가능한 경우 실패를 재현한 뒤 최소 수정한다.
- 기존 coverage가 충분한 rename·refactor나 문서 수정에는 형식적인 새 테스트를 요구하지 않는다.
- CRITICAL: Abaqus reference artifact 생성, 수정, 복원은 명시적으로 요청된 작업 범위에서만 수행한다. 문서 또는 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만 소유한다. 구체적인 state는 승인된 procedure 계약과 ARCHITECTURE를 따르며 미래 state를 미리 할당하지 않는다.
- MKL, TBB, HDF5, Win32 API와 vendor type은 public solver core에 노출하지 않는다.
LinearSolver,ParallelFor,ResultsWriter,Vector,Matrix,SparseMatrix경계 뒤에 둔다. - 해석 단계는 실패할 수 있는 candidate를 완성하고 검증한 뒤 소유 state/output에 반영한다. 실패 시 기존 state와 기존 최종 HDF5를 가능한 계약 범위에서 보존한다.
선형 정적 해석 불변식
- 해석 실행의 공통 책임은
docs/ARCHITECTURE.md를 따른다.LinearStaticAnalysis::Run()의 구체적인 단계와 객체별 책임은 해당 기능의 승인된 계약과 구현을 대조한다. - Full stiffness를 stable free/constrained 순서로
Kff/Kfc/Kcf/Kcc에 분할하고,Kfffactorization을 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를 평균으로 합치지 않는다.
개발 운영 인프라
- 일반 specialist의 기본 추론 강도는
medium, 정식화·수치·물리 검토는high다. 모델과 역할별 설정은 .codex/agents의 현재 profile을 따르고 난해한 작업에만 필요한 범위에서 높인다. - scripts/execute.py는 명시적 build/test 실행기다. 내부 LLM·phase 상태기계·자동 Git·재시도·파일명 TDD gate·대화 종료 hook을 사용하지 않는다.
- 설정·preset·명령은 검토할 실행 입력이다.
shell=False·경로 검사·timeout이 모든 side effect를 격리하는 sandbox는 아니며 실제 도구 권한과 외부 실행 승인은 별도로 따른다. - 관련 없는 사용자 변경은 보존한다. Commit을 요청받으면 작업 경로만 stage하고 push·tag·publish 등 원격 작업은 명시적으로 승인된 범위에서 수행한다. Runner는 이 권한을 부여하거나 Git 상태를 변경하지 않는다.
- 기존 phase·hook 생성 기록은 이력으로 보존하며 ignored 상태를 유지한다. 현재 검증을 위해 기록을 조작하거나 삭제된 hook을 수동 실행하지 않는다.
기능을 추가할 때의 판단 기준
- 새 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지원을 뜻하지 않는다.
개발 프로세스
- 동작 변경을 검증하는 테스트와 가능한 버그 재현을 기본으로 하며 최소 수정 후 관련 검사를 수행한다.
- CRITICAL: 빌드 경고를 새로 추가하지 말 것.
- 수식·요소·재료·적분·상태 갱신 변경은 독립 numerical review와 해당 analytical/invariant 검증을 수행한다. 필요한 물리·reference 검증도 유지한다.
- 변경 중에는 관련 검사를, 솔버 기능 완료 시에는 구성된 전체 build/test와 필수 reference 비교를 한 번 수행한다. 사용자 요청이나 넓은 변경 영향으로 전체 검증이 필요한 경우에도 실행하며 이후 변경·실패가 없으면 반복하지 않는다.
- 문서만 수정하는 작업은 링크·소스 대조·diff 정적 검토로 확인하고 build/test를 실행하지 않는다. 미실행을 통과로 보고하지 않는다.
- 기능 문서는 기본적으로 한국어 Markdown으로 작성하되 agent/skill ID, field, requirement ID, 경로와 명령은 English를 유지한다. 새 requirement ID 기본 형식은
FEM-REQ-<FEATURE>-###이다. - 커밋 메시지는 conventional commits 형식을 따른다:
feat:,fix:,docs:,refactor:,test:,chore:.
Agent/Skill Workflow
메인 assistant가 범위를 파악하고 필요한 전문 작업만 위임하며 계획·구현·검증·결과 확인을 조정한다. 작은 작업은 직접 수행하고 고정된 stage 순회나 별도 coordinator를 호출하지 않는다.
| Specialist | 호출 조건 | Skill |
|---|---|---|
requirement-agent |
복잡하거나 상충하는 scope·acceptance 정리 | fem-requirements-baseline |
research-agent |
부족한 이론·benchmark·reference 근거 조사 | fem-research-evidence |
formulation-agent |
새 수식·요소·재료·해석 알고리즘 정식화 | fem-formulation-spec |
numerical-review-agent |
정식화·주요 수치 변경·수치 불일치의 독립 검토 | fem-numerical-review |
io-definition-agent |
입력 의미·진단·결과 schema·비교 mapping 정의 | fem-io-contract |
implementation-agent |
위임할 이점이 있는 구현 묶음 | fem-implementation-tdd |
physics-evaluation-agent |
평형·물리 타당성·coverage 평가 | fem-physics-review |
- 메인도
fem-implementation-tdd로 계획·구현·일반 실패 수정을 수행할 수 있다. 전용 planning/correction profile이나 phase 파일을 요구하지 않는다. fem-release-readiness는 사용자가 별도 감사를 명시 요청할 때만 사용한다. Readiness 권고는 외부 release 권한이 아니다.- harness는 구성된 build/test의 명시 실행, review는 요청 diff의 읽기 전용 검토, fem-theory-query는 configured FEM wiki 근거·coverage gap 조회에 사용한다. Workstation vault 절대 경로를 commit하지 않는다.
- Dispatch는 작업·관련 경로/절·수정 파일·검증 기준, return은 결과·변경 파일·검사 결과·미해결 항목으로 충분하다. 지원되는 도구에서는
fork_turns="none"으로 필요한 문맥만 전달하고 연속 수정은 같은 owner에게 보낸다. - Specialist는 할당 범위를 지키고 peer를 재위임하거나 상위 계약을 결과에 맞춰 수정하지 않는다. 계약 문제는 owner·경로·근거와 함께 메인에 전달한다. 독립 검토를 자기 승인으로 대체하지 않는다.
- 일반 실패는 현재 구현 owner가 수정한다. 새 근거·변경 없이 같은 명령·agent 호출을 반복하지 않으며 고정 correction/transport 예산을 두지 않는다.
- 승인된 범위의 일반 작업과 인계에 반복 승인 gate를 추가하지 않는다. 계획 요청만으로 실행 권한을 추정하지 않는다.
- Physics·지원 범위·공개 호환성·acceptance·영속 schema 변경, 해결되지 않은 필수 계약/reference 충돌, 외부 solver 라이선스·자격증명·비용, 중대한 보안·법률 위험, destructive/remote/release 작업은 SOLVER_AGENT_DESIGN의 사용자 결정 경계를 따른다.
최소 검증 진입점
아래 명령은 해당 구현·검증 작업에만 사용한다. 현재 작업, .harness/config.json,
preset·project metadata와 프로젝트 기준을 대조하여 선택한다. 문서 수정에는 실행하지 않는다.
Harness Python 검증
Harness 구현 변경에 필요한 검사는 관련 범위부터 실행하며 전체 검사가 필요할 때는 다음을 사용한다.
uv run --with pytest python -B -m pytest -v -rs
구성된 전체 build/test
python scripts/execute.py
Phase 인자나 --push·--approve-danger-full-access를 추가하지 않는다. 이 인자들은
usage error로 거부된다. Exit 의미·설정·이전 방식 변경 안내는 HARNESS를
따른다. 필요한 수치/reference 검증을 runner 성공만으로 대체하지 않는다.
CMake/CTest 프로젝트
현재 CMakePresets.json의 MSVC x64 Debug preset 사용 예시다.
MSVC x64 developer 환경에서 FESA_GTEST_SOURCE_DIR, MKL_DIR, TBB_DIR, HDF5_DIR
환경변수를 설치된 dependency 경로로 설정한다. FESA_GTEST_SOURCE_DIR는 승인된 local
GoogleTest source checkout, 나머지는 각 package의 CMake config directory를 가리킨다.
(FESA_GTEST_SOURCE_DIR 예시: C:\git\googletest)
cmake --preset windows-msvc-ninja-debug
cmake --build --preset windows-msvc-ninja-debug
ctest --preset windows-msvc-ninja-debug --show-only=json-v1
ctest --preset windows-msvc-ninja-debug --output-on-failure
Runner에도 이 preset을 적용하려면 HARNESS의 예시에 따라 개인
.harness/config.json의 binaryDir, configurePreset, buildPreset, testPreset을
함께 맞춘다. 현재 .harness/config.example.json은 최소
CMake 설정이며 preset 필드가 없다. Preset 파일이 있다는 사실만으로 runner가 이를
선택하지 않는다. FESA 제품 검증은 solution-only MSBuild가 아니라 CMake target과 CTest를
기준으로 한다. Target graph·dependency·Windows runtime staging은 ARCHITECTURE와 실제
CMake 파일을 따른다.