diff --git a/AGENTS.md b/AGENTS.md index 33eb424..74e92a8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,8 @@ - 문서와 구현은 full Abaqus compatibility를 주장하지 않는다. 기능별로 승인된 Abaqus keyword subset만 지원한다. - 공식 solver output은 HDF5 `results.h5`이다. - reference 결과는 FESA와 같은 Abaqus `.inp` 모델을 Abaqus로 해석해 생성한 CSV 파일이다. -- reference comparison은 FESA `results.h5`의 변위, 반력, 내력, 응력 dataset을 `reference//_*.csv` 파일과 비교한다. +- reference artifact의 정확한 경로와 파일명은 기능별 reference model contract를 따른다. 신규 모델은 `reference//_*.csv` canonical 이름을 사용한다. +- 승인된 B33 baseline은 예외적으로 `reference/cantilever beam/`의 기존 space-containing 파일명을 read-only legacy alias로 사용한다. - CSV는 FESA 공식 output이 아니며, FESA HDF5에서 추출한 deterministic CSV view는 비교 디버깅/검토용 보조 artifact로만 둔다. ## 아키텍처 규칙 @@ -43,6 +44,15 @@ - Stop은 `.harness/config.json` 또는 자동 감지 결과에 따라 MSVC build와 test를 모두 검증한다. - Generated phase execution outputs remain ignored under `phases/**/step*-output.json`. +## 현재 승인된 V0 기능 계약 +- `linear-static-3d-euler-beam`의 source of truth는 `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`이다. 관련 문서를 변경하거나 구현할 때 이 계약의 의미를 임의로 넓히지 않는다. +- 입력 파일당 하나의 `*STEP, *STATIC`과 `TYPE=B33`만 지원한다. B31을 Euler 요소로 매핑하지 않고 `unsupported-element-formulation`으로 거부한다. +- `*PART/*ASSEMBLY/*INSTANCE`는 identity instance와 stable source identity만 지원한다. instance transform과 nested assembly는 거부한다. +- 선형 정적 실행 순서는 stiffness assembly와 constrained partition 뒤 `Kff`를 factorize하고, 그 다음 load vector와 effective RHS를 조립해 substitution하는 순서를 유지한다. +- FESA는 output request와 무관하게 displacement, reaction, equilibrium end action, section resultant, generalized strain/resultant, axial `S11`을 HDF5에 기록한다. Beam stress의 Abaqus reference comparison은 N/A다. +- B33 reference row는 component별 Abaqus scale로 `absolute_floor + 1e-6 * reference_scale`을 적용한다. Reference 값을 zero-clamp하거나 누락 row를 무시하지 않는다. +- `reference/cantilever beam/` artifact는 rename, rewrite 또는 보정하지 않는다. + ## 개발 프로세스 - TDD를 기본으로 한다. 구현은 `RED -> GREEN -> VERIFY` 순서를 따른다. - CRITICAL: 빌드 경고를 새로 추가하지 말 것. diff --git a/docs/ADR.md b/docs/ADR.md index e25f630..9408512 100644 --- a/docs/ADR.md +++ b/docs/ADR.md @@ -34,23 +34,23 @@ FESA의 architecture decision은 solver correctness, verification traceability, **트레이드오프**: 초기 class 수가 늘어난다. Phase 1에서는 interface를 얇게 유지하고 displacement 중심 state부터 구현한다. ### ADR-005: 공식 결과 파일은 HDF5로 하고 reference 결과는 Abaqus CSV로 둔다 -**결정**: FESA solver의 authoritative result output은 `results.h5` HDF5이다. Abaqus reference results는 `reference//` 아래 CSV 파일로 저장하며, verification은 FESA HDF5 rows와 Abaqus reference CSV rows를 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 비교한다. +**결정**: FESA solver의 authoritative result output은 `results.h5` HDF5이다. Abaqus reference results는 기능별 reference model contract가 지정한 `reference//` 아래 CSV 파일로 저장하며, verification은 FESA HDF5 rows와 Abaqus reference CSV rows를 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 비교한다. 신규 reference는 canonical 파일명을 사용하고, 승인된 기존 bundle의 legacy alias는 해당 기능 계약에 정확한 경로를 기록한 경우에만 허용한다. **이유**: 구조해석 결과는 step/frame, field/history, node/element/integration point location, units, coordinate system, schema version을 함께 가져야 한다. HDF5는 이 계층 구조와 metadata를 안정적으로 표현한다. **트레이드오프**: reference comparison은 FESA HDF5 dataset identity와 Abaqus CSV row identity를 모두 관리해야 한다. FESA HDF5에서 추출한 deterministic CSV view는 디버깅/검토용 보조 artifact로 허용하지만, 공식 solver output이나 reference artifact로 취급하지 않는다. ### ADR-006: 해석 알고리즘과 수치 backend는 Strategy와 Adapter 경계 뒤에 둔다 -**결정**: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`는 Strategy로 구성하고, MKL, TBB, HDF5 API는 adapter 계층 뒤에 둔다. +**결정**: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`는 Strategy로 구성하고, MKL, TBB, HDF5 API는 adapter 계층 뒤에 둔다. `Vector`는 contiguous `double`, `Matrix`는 row-major contiguous `double`을 소유하고 dense 연산은 MKL CBLAS를 사용한다. `SparseMatrix`는 이들과 상속 관계가 없는 0-based CSR 전용 타입이며, PARDISO factorization과 substitution은 `LinearSolver` 경계 뒤에서 분리한다. **이유**: 선형 정적, 비선형 정적, 동적, frequency, heat transfer 해석은 공통 흐름을 공유하지만 알고리즘과 backend가 다르다. 외부 API를 core에 노출하면 테스트 double, backend 교체, dependency review가 어려워진다. -**트레이드오프**: 단일 기능만 구현할 때는 adapter가 다소 장황해 보일 수 있다. 하지만 solver backend와 result writer는 장기적으로 교체 가능해야 한다. +**트레이드오프**: 단일 기능만 구현할 때는 adapter가 다소 장황해 보일 수 있다. Row-major dense storage와 CSR sparse storage를 따로 유지해야 하지만 backend 의존성과 dense/sparse 의미가 core 모델에 섞이지 않는다. ### ADR-007: Analysis 실행 흐름은 Template Method로 고정한다 -**결정**: `Analysis::run()`은 `initialize -> buildAnalysisModel -> buildDofMap -> buildSparsePattern -> assemble -> applyBoundaryConditions -> solve -> updateState -> writeResults` 흐름을 고정한다. +**결정**: `Analysis::run()`은 공통 lifecycle을 고정한다. 선형 정적 V0의 순서는 `parse input -> initialize Domain -> build AnalysisModel -> build DOF map/sparse pattern -> assemble stiffness -> partition constraints -> factorize Kff -> assemble load -> form effective RHS -> substitute -> reconstruct displacement -> recover results -> write HDF5`다. 강성행렬 factorization은 하중벡터 조립보다 먼저 수행하고, factorization과 substitution을 하나의 불투명한 solve 호출로 합치지 않는다. -**이유**: 해석 procedure가 늘어나도 공통 실행 순서가 유지되어야 검증, logging, result writing, failure classification이 일관된다. +**이유**: 해석 procedure가 늘어나도 공통 실행 순서가 유지되어야 검증, logging, result writing, failure classification이 일관된다. Factorization과 substitution을 분리하면 동일 강성행렬에 여러 RHS를 적용할 수 있고 각 실패 단계를 구조화된 diagnostic으로 분류할 수 있다. **트레이드오프**: 특수 해석 절차가 공통 흐름에 맞지 않는 경우 hook point가 필요하다. 초기에는 선형 정적 해석을 기준으로 최소 hook만 둔다. @@ -69,11 +69,11 @@ FESA의 architecture decision은 solver correctness, verification traceability, **트레이드오프**: 초기 병렬화 범위가 제한된다. MKL 내부 thread와 TBB task arena의 oversubscription 정책을 별도로 문서화해야 한다. ### ADR-010: Abaqus reference artifact는 사람이 생성하거나 명시 승인된 절차로만 갱신한다 -**결정**: Agent는 Abaqus, Nastran 또는 reference solver를 직접 실행하지 않는다. reference artifact 생성, 수정, 복원은 명시 승인된 phase에서만 수행하고 provenance를 `metadata.json`에 기록한다. +**결정**: Agent는 Abaqus, Nastran 또는 reference solver를 직접 실행하지 않는다. reference artifact 생성, 수정, 복원은 명시 승인된 phase에서만 수행한다. 신규 bundle의 provenance는 `metadata.json`에 기록한다. 승인된 `cantilever-beam-b33` legacy baseline은 source commit과 generator, units, coordinate system, schema, tolerance를 설계 및 Reference Model Contract가 대신 기록하므로 이 baseline에 한해서 `metadata.json`과 `README.md`가 N/A다. **이유**: reference 결과는 solver correctness의 기준이다. 생성 절차가 불명확하면 구현 결함과 reference artifact 오류를 구분할 수 없다. -**트레이드오프**: reference 준비가 느려질 수 있다. 대신 검증 기준의 신뢰도와 감사 가능성이 높아진다. +**트레이드오프**: reference 준비가 느려질 수 있다. Legacy 예외는 일반 artifact 규칙을 복잡하게 하지만 exact path와 source commit을 고정하고 read-only로 취급해 감사 가능성을 유지한다. ### ADR-011: 구형 단일 검증 진입점 계약을 폐기한다 @@ -88,3 +88,19 @@ FESA의 architecture decision은 solver correctness, verification traceability, **이유**: 테스트 파일 존재 검사, TDD 실행 증거, 전체 build/test는 서로 다른 책임이다. 이를 분리하면 Hook이 보장하는 범위를 과장하지 않으면서 Step 종료 시 green 상태를 강제할 수 있다. **트레이드오프**: PreToolUse만으로 구현 전 RED 실행을 증명할 수 없으므로 Implementation report에 RED/GREEN 명령과 결과를 기록해야 한다. C/C++가 없는 저장소는 Stop이 통과하므로 Harness Python 검증은 별도 acceptance command로 유지한다. + +### ADR-013: V0 선형 정적 해석은 단일 step B33 Euler beam으로 제한한다 + +**결정**: 첫 end-to-end 제품 기능은 입력 파일당 하나의 `*STEP, *STATIC`을 해석하는 2절점 3D Euler–Bernoulli beam이다. Abaqus `TYPE=B33`만 이 요소로 매핑하고 B31은 `unsupported-element-formulation`으로 거부한다. `*PART/*ASSEMBLY/*INSTANCE`는 여러 identity instance와 stable source identity를 지원하지만 instance transform, nested assembly, 다중 step은 지원하지 않는다. Output-request keyword는 승인 allowlist에서 warning 후 no-op 처리하고 FESA 기본 HDF5 결과는 항상 생성한다. + +**이유**: B31은 transverse shear deformation을 포함하므로 Euler–Bernoulli 정식화와 의미가 다르다. 단일 step과 identity instance로 범위를 제한하면 parser wrapper, source identity, assembly, 해법 및 결과 복구를 end-to-end로 검증하면서 의미를 왜곡하지 않는다. + +**트레이드오프**: 기존 Abaqus 모델 중 B31, instance transform, 다중 step 또는 `*DLOAD`를 사용하는 입력은 거부된다. 이후 기능은 별도 요구조건과 formulation/reference gate를 거쳐 추가한다. + +### ADR-014: B33 cantilever baseline은 component-scale 혼합 tolerance로 비교한다 + +**결정**: `reference/cantilever beam/`의 B33 input, displacement CSV, reaction CSV, elemental-force CSV를 V0 reference baseline으로 사용한다. Displacement와 reaction은 node identity로, section resultant는 CSV node station과 정규화된 FESA element endpoint로 비교한다. 같은 model, step/frame, quantity, component에 대해 `reference_scale = max(abs(reference rows))`를 계산하고 모든 row에 `absolute_floor + 1e-6 * reference_scale`을 적용한다. SI displacement/rotation absolute floor는 `1e-9`, force/moment floor는 `1e-3`이다. Beam stress는 출력하되 Abaqus stress reference comparison은 N/A다. + +**이유**: 자유단 moment처럼 이론적으로 0인 값에는 행별 상대오차가 정의되지 않으며 Abaqus 결과에 작은 수치 잔차가 남을 수 있다. Component scale을 사용하면 전체 물리량 크기에 비해 작은 잔차를 허용하면서 각 row를 결정적으로 판정할 수 있다. + +**트레이드오프**: 큰 component scale은 zero row의 허용폭을 넓힌다. 이를 완화하기 위해 quantity와 component를 섞지 않고 Abaqus 값만 scale에 사용하며, 모든 row의 absolute/normalized error와 worst row를 보고하고 누락·추가·nonfinite row를 tolerance 전에 실패시킨다. diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 2d32271..58fa43c 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -11,6 +11,12 @@ FESA의 아키텍처 목표는 Abaqus `.inp` subset을 내부 semantic model로 - incremental feature addition - Harness 기반 TDD +현재 승인된 V0 end-to-end 기능은 `linear-static-3d-euler-beam`이다. 상세 계약의 +source of truth는 +`docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`이며, 이 문서는 +그 계약을 전체 solver architecture의 모듈과 데이터 흐름에 배치한다. 아래에 나타난 +비선형, 동적, thermal 및 다른 element 계층은 장기 확장 경계이며 V0 지원 범위가 아니다. + ## 디렉토리 구조 ```text src/ @@ -31,9 +37,7 @@ src/ analysis/ # static, modal, dynamic, nonlinear procedure drivers results/ # recovery, field/history output, diagnostics validation/ # comparison metrics and tolerance helpers - math/ - Vector/ # managing double array including vector operation, vector operation must use BLAS from MKL - Matrix/ # managing double array including matrix operation, matrix operation must use BLAS from MKL + math/ # owning Vector, row-major Matrix, CSR SparseMatrix adapters tests/ unit/ integration/ @@ -83,6 +87,57 @@ Runner는 `git add -A`를 사용하므로 clean worktree 또는 별도 Git workt - `results`는 HDF5 schema를 통해 nodal, element, integration-point, diagnostic output을 분리한다. - test helper는 production parser/solver 내부 상태를 우회하지 않는다. +## V0 입력 경계 + +V0 parser는 keyword와 parameter를 case-insensitive하게 해석하되 source label의 원문을 +보존한다. 지원하는 model/procedure keyword는 다음과 같다. + +- `*HEADING` +- `*PART`, `*END PART` +- `*NODE` +- `*ELEMENT, TYPE=B33` +- `*NSET`, `*ELSET`, including `GENERATE` +- `*MATERIAL`, `*ELASTIC` +- `*BEAM GENERAL SECTION, SECTION=GENERAL` +- `*SECTION POINTS` +- `*ASSEMBLY`, `*END ASSEMBLY` +- `*INSTANCE`, `*END INSTANCE` +- `*BOUNDARY`, `*CLOAD` +- `*STEP`, `*STATIC`, `*END STEP` + +Part 내부 label은 `SourceEntityId { instance_name, source_label }`로 보존하고 Domain은 +별도 stable internal index를 부여한다. 같은 part의 여러 identity instance는 허용하지만 +translation/rotation data와 nested assembly는 구조화된 unsupported diagnostic으로 +거부한다. 입력 파일당 하나의 static step만 허용하고 두 번째 step은 오류다. + +`*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`, +`*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT` 및 그에 속한 +미지원 output variable data는 warning 후 no-op 처리한다. 이 allowlist 밖의 미지원 +model-affecting keyword는 오류다. FESA output은 Abaqus output request에 좌우되지 않는다. + +## V0 beam과 section 계약 + +`EulerBeam3D`는 2절점과 절점당 `[UX, UY, UZ, URX, URY, URZ]` 6 DOF를 사용하며 축, +두 방향 Euler–Bernoulli 굽힘과 Saint-Venant 비틀림을 제공한다. Beam tangent를 local +`x`, Abaqus first section axis `n1`을 local `y`, `t x n1`을 local `z`로 둔다. +`*BEAM GENERAL SECTION`의 `A, I11, I12, I22, J`는 `Iy=I11`, `Iz=I22`로 매핑하고 +V0는 `I12=0`만 허용한다. `E`, `G`, `A`, `Iy`, `Iz`, `J`는 양수여야 하며 zero-length +element와 tangent에 평행한 guide vector를 scale-aware tolerance로 거부한다. + +요소 API는 stiffness, transformation, load와 recovery 책임을 분리한다. + +```cpp +Matrix localStiffness() const; +Matrix globalStiffness() const; +Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const; +BeamRecovery recover(const Vector& globalElementDisplacement) const; +``` + +`localEquivalentLoad`는 formulation의 constant local line-load kernel을 unit test하기 +위한 계약이다. V0 parser는 `*DLOAD`나 distributed-load Domain object를 생성하지 않으므로 +CLI pipeline에서는 이 kernel을 호출하지 않는다. Stiffness와 recovery는 formulation의 +2점 Gauss rule과 부호 규약을 따른다. + ## 핵심 객체 모델 ```text Domain @@ -159,8 +214,14 @@ Results 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에서 할당하지 않는다. + ## 상태 관리 - `Domain`은 입력 파일에서 만들어진 전체 모델 정의를 소유한다. 파싱 이후에는 가능한 한 불변으로 취급한다. - `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않고 참조 또는 id 기반 view로 구성한다. @@ -171,37 +232,46 @@ Matrix ## 데이터 흐름 ```text Abaqus input file --> InputParser --> Domain 생성 --> StepDefinition 루프 --> AnalysisModel 생성 --> DofManager로 자유도/방정식 번호 생성 --> sparse pattern 생성 --> Analysis 실행 --> Assembler로 전역 행렬/벡터 조립 --> BoundaryCondition 적용 --> LinearSolver 또는 nonlinear/time integration loop --> AnalysisState 갱신 --> ResultsWriter로 step/frame/history 저장 --> 다음 step 진행 +-> syntax parse and semantic mapping +-> immutable Domain 생성 +-> 단일 step AnalysisModel view 생성 +-> DofManager DOF/scatter map/sparse pattern 생성 +-> element stiffness 계산과 deterministic COO-to-CSR 조립 +-> free/constrained partition 생성 +-> LinearSolver::factorize(Kff) +-> full nodal load vector 조립 +-> effective RHS = Ff - Kfc * dc +-> LinearSolver::solve(rhs, df) substitution +-> full displacement 복구 +-> reaction = K*d - F 및 element result 복구 +-> ResultsWriter로 results.h5 atomic finalization ``` +강성행렬 factorization은 하중벡터 조립보다 먼저 수행한다. 반력은 element end action의 +별도 합이 아니라 조립된 전체 residual에서 구한다. + ## 해석 실행 흐름 -`Analysis::run()`은 Template Method로 다음 큰 흐름을 고정한다. 해석 종류별 class는 필요한 단계만 재정의한다. +`Analysis::run()`은 Template Method로 다음 V0 흐름을 고정한다. 해석 종류별 class는 +승인된 procedure contract 안에서 필요한 단계만 재정의한다. ```text initialize buildAnalysisModel buildDofMap buildSparsePattern -assemble -applyBoundaryConditions -solve -updateState +assembleStiffness +partitionConstraints +factorize +assembleLoads +formEffectiveRhs +substitute +reconstructDisplacement +recoverResults writeResults ``` -비선형 정적해석은 이 흐름을 Newton-Raphson 반복 루프 안에서 사용하고, 동적해석은 time step/frame 루프 안에서 사용한다. +비선형 정적 및 동적 해석은 V0 범위가 아니며 별도 ADR과 formulation을 승인한 뒤 이 +lifecycle의 확장 지점을 사용한다. ## 설계 패턴 - Strategy Pattern: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`를 교체 가능한 전략으로 둔다. @@ -213,10 +283,21 @@ writeResults ## Sparse Matrix Policy - assembly는 초기에는 COO triplet 수집 후 CSR finalize를 기준으로 한다. -- `SparseMatrix`는 solver core가 사용하는 추상 contract이고 MKL PARDISO backend는 CSR input contract만 받는다. +- `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를 사용한다. +## Dense Math Policy + +- `Vector`는 contiguous `double` 데이터와 크기를 소유하고 copy, dot, Euclidean norm, + scale, axpy를 MKL CBLAS adapter로 수행한다. +- `Matrix`는 row-major contiguous `double` 데이터와 dimensions를 소유하고 + matrix-vector 및 matrix-matrix 연산에 `CBLAS_ROW_MAJOR`를 사용한다. +- 두 타입은 copy/move semantics와 bounds-checked access를 제공한다. +- MKL header와 MKL-specific type은 adapter implementation 밖으로 노출하지 않는다. + ## Parallel Policy - 첫 번째 oneTBB 적용 지점은 element-local matrix/residual 계산이다. - 전역 sparse write는 thread-local buffer 또는 deterministic reduction으로 제한한다. @@ -227,10 +308,12 @@ writeResults /metadata /model/nodes /model/elements -/steps//frames//nodal/displacement -/steps//frames//nodal/reaction -/steps//frames//element/stress -/steps//frames//element/strain +/steps//frames/0/nodal/displacement +/steps//frames/0/nodal/reaction +/steps//frames/0/element/end_force_local +/steps//frames/0/element/section_resultant +/steps//frames/0/element/generalized_strain +/steps//frames/0/element/stress_s11 /diagnostics ``` @@ -242,3 +325,35 @@ Schema requirements: - Abaqus reference results는 `reference//` 아래 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`를 남기지 않는다. + +## V0 결과 복구와 reference normalization + +- Nodal displacement와 reaction은 global `[UX, UY, UZ, URX, URY, URZ]` 순서다. +- Equilibrium end action은 local `[FX,FY,FZ,MX,MY,MZ]`, endpoint section resultant는 + `[N,T,My,Mz]`, generalized strain/resultant는 두 Gauss point에 기록한다. +- General beam section stress는 section point의 axial `S11`만 복구한다. Section point가 + 없으면 centroid `(0,0)`을 `source=fesa-default`로 기록한다. +- 승인된 `reference/cantilever beam/cantilever beam elemental forces.csv`는 node station + 기준 `SF1/SM1/SM2/SM3`을 제공한다. FESA endpoint를 동일한 section-cut 부호로 + 정규화하고 interior node의 두 endpoint가 tolerance 안에서 일치하는지 먼저 확인한 뒤 + `SF1 -> N`, `SM1 -> My`, `SM2 -> Mz`, `SM3 -> T`로 비교한다. +- Reference tolerance는 같은 model, step/frame, quantity, component의 Abaqus rows에서 + `reference_scale = max(abs(reference_value))`를 구하고 각 row에 + `absolute_floor + 1e-6 * reference_scale`을 적용한다. SI displacement/rotation floor는 + `1e-9`, force/moment floor는 `1e-3`이다. +- Beam stress는 HDF5 schema와 unit/analytical test로 검증하지만 Abaqus reference + comparison은 N/A다. + +## CLI와 diagnostics + +```powershell +fesa.exe --output +``` + +`--output`을 생략하면 현재 작업 디렉터리의 `results.h5`를 사용한다. Exit code는 +`0=success`, `2=usage`, `3=input syntax/semantic mapping`, `4=model validation`, +`5=factorization/substitution`, `6=HDF5 output`으로 고정한다. Diagnostic은 `severity`, +`code`, `file`, `line`, `keyword`, `entity_identity`, `message`를 가지며 stderr에 +deterministic한 순서로 출력한다. diff --git a/docs/PRD.md b/docs/PRD.md index af57755..596c661 100644 --- a/docs/PRD.md +++ b/docs/PRD.md @@ -18,31 +18,46 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기 4. 요소, 재료, 경계조건, 하중의 runtime-polymorphic base interface 5. sparse matrix pattern 생성, 전역 행렬/벡터 조립, 제약조건 적용 6. `LinearSolver` adapter를 통한 MKL PARDISO backend와 향후 iterative solver 확장 -7. HDF5 기반 `ResultStep` -> `ResultFrame` -> `FieldOutput`/`HistoryOutput` 저장 +7. HDF5 기반 versioned step/frame field-result 저장과 향후 history-output 확장 경계 8. FESA HDF5 rows와 `reference//` 아래 Abaqus reference CSV rows의 직접 비교 9. CMake/MSVC/x64/Debug, CTest 기반 개발 검증 ## V0 범위 - 선형 정적 해석 파이프라인 구현 -- 첫 end-to-end 기능 후보: Isoparametric 3D Euler beam element +- 승인된 첫 end-to-end 기능: 2절점 3D Euler–Bernoulli beam, Abaqus `TYPE=B33` +- 입력 파일당 하나의 `*STEP, *STATIC` +- 절점당 자유도 `[UX, UY, UZ, URX, URY, URZ]` +- 축, 두 방향 굽힘, Saint-Venant 비틀림 및 선형 등방 탄성 - 최소 Abaqus keyword subset: - `*HEADING` - - `*NODE` - - `*ELEMENT` - - `*NSET` - - `*ELSET` + - `*PART`, `*END PART` + - `*NODE`, `*ELEMENT, TYPE=B33` + - `*NSET`, `*ELSET`, including `GENERATE` - `*MATERIAL` - `*ELASTIC` - - `*Beam General Section` + - `*BEAM GENERAL SECTION, SECTION=GENERAL` + - `*SECTION POINTS` + - `*ASSEMBLY`, `*END ASSEMBLY` + - `*INSTANCE`, `*END INSTANCE` - `*BOUNDARY` - `*CLOAD` - - `*STEP` - - `*STATIC` - - output request subset + - `*STEP`, `*STATIC`, `*END STEP` +- `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`, + `*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT`과 그에 속한 + 미지원 variable data는 warning 후 no-op 처리 +- 같은 part의 여러 identity instance와 stable source label mapping +- nonzero prescribed displacement를 포함한 free/constrained partition +- formulation의 constant local line-load equivalent nodal vector kernel. V0 parser와 CLI는 + `*DLOAD`를 지원하거나 이 kernel을 호출하지 않음 +- deterministic COO-to-CSR stiffness assembly - MKL PARDISO 기반 sparse direct solver -- displacements, reactions, elemental forces 중심의 verification +- stiffness factorization과 load-vector substitution 분리 +- displacements, reactions, equilibrium end actions, section resultants, generalized results, + axial `S11` output - HDF5 result schema v0 -- FESA HDF5 to Abaqus reference CSV comparison 계약 +- `fesa.exe --output ` CLI +- 승인된 `reference/cantilever beam/` B33 결과와 displacement, reaction, section resultant + comparison; beam stress reference comparison은 N/A ## 기능 요구조건 | ID | 요구조건 | Acceptance Criteria | Verification Method | @@ -51,18 +66,29 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기 | FESA-PRD-002 | FESA는 입력 모델을 `Domain`으로 변환해야 한다. | nodes, elements, materials, properties, sets, loads, boundary conditions, step definitions가 semantic model에 보존된다. | parser integration test | | FESA-PRD-003 | FESA는 현재 step의 실행 view를 `AnalysisModel`로 구성해야 한다. | active elements, loads, boundary conditions, properties/materials가 Domain 복사 없이 참조 또는 id view로 연결된다. | analysis model unit test | | FESA-PRD-004 | FESA는 equation numbering과 constraint/free mapping을 `DofManager`에 집중해야 한다. | Node/Element 내부에 equation id를 분산 저장하지 않는다. | code review, DofManager unit test | -| FESA-PRD-005 | FESA는 해석 중 변하는 물리량을 `AnalysisState`에 저장해야 한다. | displacement, force, residual, increment/iteration 상태가 step/frame 출력과 연결된다. | state unit test, integration test | -| FESA-PRD-006 | FESA는 solver 결과를 HDF5 authoritative output `results.h5`로 저장해야 한다. | step/frame, field/history, metadata, diagnostics가 schema version과 함께 저장된다. | HDF5 schema test | -| FESA-PRD-007 | FESA는 Abaqus reference CSV rows와 비교 가능한 deterministic row mapping을 제공해야 한다. | displacement, reaction, internal force, stress 등 검증 물리량의 row identity와 tolerance source가 명확하다. | reference comparison report | +| FESA-PRD-005 | FESA는 해석 중 변하는 물리량을 `AnalysisState`에 저장해야 한다. | V0 displacement, external/internal force, residual, constrained reaction, step/frame identity와 element recovery rows가 출력에 연결되고 velocity, acceleration, temperature, iteration history는 할당하지 않는다. | state unit test, integration test | +| FESA-PRD-006 | FESA는 solver 결과를 HDF5 authoritative output `results.h5`로 저장해야 한다. | V0 step/frame field results, metadata, diagnostics가 schema version과 함께 저장된다. | HDF5 schema test | +| FESA-PRD-007 | FESA는 Abaqus reference CSV rows와 비교 가능한 deterministic row mapping을 제공해야 한다. | displacement와 reaction은 node identity, B33 section resultant는 정규화된 node station identity로 비교하고 stress reference comparison은 N/A로 기록한다. | reference comparison report | | FESA-PRD-008 | FESA의 production C++ 변경은 테스트를 먼저 작성하고 실패를 확인한 뒤 구현해야 한다. | 관련 C++ test file, RED 실패와 후속 GREEN 성공 증거가 있고 Stop의 전체 MSVC build/test가 통과한다. | implementation report, Hook guardrail, CTest | | FESA-PRD-009 | FESA는 외부 라이브러리 API를 solver core에 직접 노출하지 않아야 한다. | MKL, TBB, HDF5 의존은 adapter module에 제한된다. | architecture review, dependency review | | FESA-PRD-010 | FESA 기능 완료는 reference comparison과 physics sanity 통과를 요구해야 한다. | 수치 tolerance와 물리 검토가 모두 pass이고 known limitation이 기록된다. | verification report, physics evaluation report | +| FESA-PRD-011 | V0는 입력 파일당 하나의 linear static step과 Abaqus B33 3D Euler beam만 해석해야 한다. | 단일 B33 model은 해석되고, B31과 두 번째 step은 구조화된 unsupported diagnostic으로 거부된다. | parser/semantic unit test, CLI integration test | +| FESA-PRD-012 | V0는 Part/Assembly/Instance wrapper와 source identity를 보존해야 한다. | 여러 identity instance의 node/element/set label이 stable internal ID로 deterministic하게 매핑되고 transform 또는 nested assembly는 거부된다. | semantic mapping unit test | +| FESA-PRD-013 | Output-request allowlist는 해석 의미를 변경하지 않아야 한다. | 승인 keyword와 variable data는 warning 후 no-op이고, allowlist 밖 model-affecting keyword는 오류이며 기본 결과는 output request와 무관하게 생성된다. | parser diagnostic test, HDF5 integration test | +| FESA-PRD-014 | 선형 정적 pipeline은 stiffness factorization과 load substitution을 분리해야 한다. | `Kff` factorization이 load vector assembly보다 먼저 수행되고, `rhs=Ff-Kfc*dc` substitution으로 full displacement를 복구한다. | orchestration test, solver-adapter test | +| FESA-PRD-015 | FESA는 V0 결과와 diagnostic을 안정된 외부 계약으로 출력해야 한다. | CLI가 `0=success`, `2=usage`, `3=input`, `4=model`, `5=solver`, `6=HDF5` exit code를 사용하고 diagnostic field가 계약과 일치하며 HDF5가 displacement, reaction, end force, section resultant, generalized strain/resultant, axial `S11`을 포함하고 실패 시 불완전한 최종 파일을 남기지 않는다. | CLI integration test, HDF5 schema/atomicity test | +| FESA-PRD-016 | Dense와 sparse math storage 및 backend 경계를 분리해야 한다. | `Vector`는 contiguous, `Matrix`는 row-major contiguous storage와 MKL CBLAS를 사용하고 `SparseMatrix`는 별도 0-based CSR 타입이며 MKL 타입이 public core API에 노출되지 않는다. | math unit test, dependency review | +| FESA-PRD-017 | B33 reference comparison은 component-scale 혼합 tolerance를 사용해야 한다. | 모든 matched row가 `abs_error <= absolute_floor + 1e-6 * reference_scale`을 만족하고 missing/extra/nonfinite row는 comparison 전에 실패한다. | reference comparison unit/integration test, verification report | +| FESA-PRD-018 | 승인된 B33 reference artifact는 read-only baseline으로 유지해야 한다. | `reference/cantilever beam/` 파일을 rename, rewrite, 보정하지 않고 exact legacy path로 읽으며 B33 element type과 expected headers를 artifact check에서 확인한다. | artifact inventory, Git diff review | +| FESA-PRD-019 | B33 beam section과 local axis를 Abaqus 의미에 맞게 매핑해야 한다. | `n1 -> local y`, `t x n1 -> local z`, `Iy=I11`, `Iz=I22`, `I12=0`을 적용하고 nonpositive property, zero-length element, tangent-parallel guide vector를 구조화된 model diagnostic으로 거부한다. | section-mapping unit test, element geometry test | ## 비기능 요구조건 - MSVC x64 Debug 환경에서 configure, build, CTest를 검증한다. - reference test 결과는 deterministic해야 한다. - HDF5 schema는 versioned contract로 관리한다. -- tolerance policy는 absolute, relative, norm-based 기준을 구분한다. +- B33 reference tolerance는 model, step/frame, quantity, component별 Abaqus scale만 사용한다. +- 승인된 SI B33 bundle의 absolute floor는 displacement/rotation `1e-9`, force/moment + `1e-3`이며 relative coefficient는 `1e-6`이다. - parser, solver, HDF5 writer는 실패 원인을 구조화된 diagnostic으로 보고한다. - oneMKL, oneTBB, HDF5는 CMake에서 명시 탐지하고 실패 원인을 분류한다. - 대규모 모델 성능 최적화보다 Phase 1 명확성, 테스트 가능성, 검증 traceability를 우선한다. @@ -74,14 +100,22 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기 4. I/O contract approved: Abaqus keyword subset, internal model mapping, HDF5 result contract, reference CSV comparison row contract가 승인되어 있다. 5. Tests fail before implementation: C++/integration/reference test를 제품 코드보다 먼저 작성하고 같은 Step 안에서 RED 실패와 후속 GREEN 성공을 확인한다. 6. CMake/CTest pass: MSVC/x64/Debug 기준 configure, build, test가 통과한다. -7. Reference comparison pass: FESA `results.h5` rows와 Abaqus reference CSV rows가 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준 안에 있다. -8. Physics sanity pass: equilibrium, reaction consistency, displacement direction, symmetry, stress sanity가 검토되어 있다. +7. Reference comparison pass: FESA `results.h5`의 displacement, reaction, section resultant rows가 승인된 B33 CSV와 documented identity 및 component-scale 혼합 tolerance 안에 있다. Beam stress comparison은 명시적 N/A다. +8. Physics sanity pass: equilibrium, reaction consistency, displacement direction, symmetry, section-force consistency와 normalized residual이 검토되어 있다. 9. Release readiness pass: acceptance traceability, known limitations, release notes draft가 준비되어 있다. ## 제외 사항 - Abaqus full parser 호환 +- Abaqus B31/Timoshenko beam +- 다중 analysis step과 step 간 load/BC propagation +- instance translation/rotation, nested assembly 및 dependent/independent mesh semantics +- `I12 != 0`, taper, offset, release, curved beam, warping +- Abaqus `*DLOAD` 입력과 Domain distributed-load object +- 기하·재료비선형, dynamics, contact, thermal effects +- transverse shear stress와 torsional shear stress recovery +- beam stress에 대한 Abaqus reference comparison - Abaqus, Nastran 또는 reference solver 직접 실행 자동화 - Agent가 Abaqus reference CSV 파일을 임의 생성 또는 수정하는 작업 - GUI 또는 postprocessor - Visual Studio `.sln`/`.vcxproj` 전용 MSBuild workflow -- Explicit dynamics, contact, plasticity, shell end-to-end 구현 +- plasticity와 shell end-to-end 구현 diff --git a/docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md b/docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md new file mode 100644 index 0000000..b770913 --- /dev/null +++ b/docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md @@ -0,0 +1,282 @@ +# Linear Static 3D Euler Beam Harness Phase Construction 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:** Create the approved 29-step Harness phase that drives the FESA V0 single-step B33 linear-static solver from upstream contracts through release readiness. + +**Architecture:** The phase is a sequence of seven document gates, eighteen TDD implementation steps, and four final verification gates. Each `stepN.md` is self-contained, names its role/skill and owned paths, preserves the approved design as the source of truth, and delegates per-step commits and timestamps to `scripts/execute.py`. + +**Tech Stack:** Markdown and JSON phase descriptors; C++17; MSVC x64 Debug; CMake/CTest; GoogleTest from `C:/git/googletest`; Intel oneMKL/oneTBB; HDF5; Python 3 Harness runner. + +## Global Constraints + +- The approved source of truth is `docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md`; phase steps must not silently broaden or reinterpret it. +- The solver scope is one `*STEP, *STATIC` using Abaqus `TYPE=B33`; `TYPE=B31`, multiple steps, instance transforms, nested assemblies, and `*DLOAD` input remain unsupported. +- Runtime order keeps `Kff` factorization before load-vector assembly and separates factorization from substitution. +- Production C++ changes use `RED -> GREEN -> VERIFY`; every production file has a related GoogleTest file. +- Validation uses MSVC x64 Debug and the exact dependency cache variables in the approved design; production CMake must not hardcode the local GoogleTest path. +- `reference/cantilever beam/` is read-only and must not be renamed, rewritten, regenerated, or repaired by the phase. +- Beam stress is written and tested, but Abaqus stress reference comparison is explicitly N/A. +- Harness owns per-step commits and timestamps; a step must update only its phase status and must not invoke `git commit`. +- Before `python scripts/execute.py linear-static-3d-euler-beam`, use a clean worktree or a separate worktree because the current executor stages with `git add -A`. + +--- + +### Task 1: Create Phase Indexes + +**Files:** +- Create: `phases/index.json` +- Create: `phases/linear-static-3d-euler-beam/index.json` + +**Interfaces:** +- Consumes: approved phase name and 29-step table from the design specification. +- Produces: top-level pending phase registration and contiguous step numbers `0..28` with kebab-case names. + +- [ ] **Step 1: Register the phase** + +```json +{ + "phases": [ + { "dir": "linear-static-3d-euler-beam", "status": "pending" } + ] +} +``` + +- [ ] **Step 2: Create the task index** + +Use `project: "FESA Structural Solver"`, `phase: "linear-static-3d-euler-beam"`, and the exact step names from specification section 3. Do not add timestamps; the executor owns them. + +- [ ] **Step 3: Validate both JSON files** + +```powershell +Get-Content -Raw phases/index.json | ConvertFrom-Json | Out-Null +$phase = Get-Content -Raw phases/linear-static-3d-euler-beam/index.json | ConvertFrom-Json +if ($phase.steps.Count -ne 29) { throw 'Expected 29 steps' } +if (($phase.steps.step -join ',') -ne ((0..28) -join ',')) { throw 'Step numbers are not contiguous' } +``` + +- [ ] **Step 4: Executor commit checkpoint** + +Do not run `git commit`; `scripts/execute.py` commits phase execution results. The phase-construction changes remain for the user to review and commit. + +### Task 2: Create Upstream Contract Gate Steps + +**Files:** +- Create: `phases/linear-static-3d-euler-beam/step0.md` through `step6.md` + +**Interfaces:** +- Consumes: approved design, formulation, root project documents, gate-specific README files, and exact FESA skill contracts. +- Produces: requirements, research, formulation alignment, numerical review, I/O, reference-model, and implementation-plan documents. + +- [ ] **Step 1: Define role and skill ownership** + +```text +0 requirement-agent / fesa-requirements-baseline +1 research-agent / fesa-research-evidence + fem-theory-query +2 formulation-agent / fesa-formulation-spec +3 numerical-review-agent / fesa-numerical-review +4 io-definition-agent / fesa-io-contract +5 reference-model-agent / fesa-reference-models +6 implementation-planning-agent / fesa-cpp-msvc-tdd +``` + +- [ ] **Step 2: Make each document gate self-contained** + +Each step names required input paths, the exact output path, mandatory sections/status, immutable decisions, executable PowerShell checks, status-update rules, and prohibited changes. Step 2 aligns the existing formulation without changing its approved mathematical meaning; Step 5 documents the approved legacy bundle exception without modifying `reference/`. + +- [ ] **Step 3: Verify gate file structure** + +```powershell +0..6 | ForEach-Object { + $path = "phases/linear-static-3d-euler-beam/step$_.md" + if (-not (Test-Path $path)) { throw "Missing $path" } + foreach ($section in @('## 읽어야 할 파일','## 작업','## Acceptance Criteria','## 검증 절차','## 금지사항')) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $section -Quiet)) { + throw "$path missing $section" + } + } +} +``` + +- [ ] **Step 4: Executor commit checkpoint** + +Do not commit manually; the executor will commit each completed gate. + +### Task 3: Create C++ TDD Implementation Steps + +**Files:** +- Create: `phases/linear-static-3d-euler-beam/step7.md` through `step24.md` + +**Interfaces:** +- Consumes: approved upstream documents produced by Steps 0–6. +- Produces: build foundation, core/model/parser/FEM/math/solver/result modules, tests, and `fesa.exe`. + +- [ ] **Step 1: Lock module order and interfaces** + +```cpp +Matrix EulerBeam3D::localStiffness() const; +Matrix EulerBeam3D::globalStiffness() const; +Vector EulerBeam3D::localEquivalentLoad(const ConstantLocalLineLoad&) const; +BeamRecovery EulerBeam3D::recover(const Vector& globalElementDisplacement) const; + +class LinearSolver { +public: + virtual ~LinearSolver() = default; + virtual Status factorize(const SparseMatrix& matrix) = 0; + virtual Status solve(const Vector& rhs, Vector& solution) const = 0; +}; +``` + +The remaining steps define signatures for diagnostics, semantic mapping, active views, DOF numbering, state, deterministic parallel assembly, constraints, load assembly, result recovery, HDF5 writing, and orchestration without exposing MKL/TBB/HDF5 types across adapter boundaries. + +- [ ] **Step 2: Encode test-first execution in every production step** + +Each Step 8–24 contains these independently verifiable actions: + +```text +1. Add the named GoogleTest cases before production edits. +2. Build and run the targeted CTest regex; record the expected missing-behavior RED failure. +3. Add only the production behavior owned by the step. +4. Rebuild and run the targeted test to GREEN. +5. Run CTest discovery and the full CTest suite for VERIFY. +``` + +Step 7 creates the build/test foundation and proves at least one discovered test. Step 24 also provides the end-to-end CLI and test-only B33 reference comparison command used read-only by Step 26. + +- [ ] **Step 3: Use the approved dependency configure command** + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +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 +``` + +- [ ] **Step 4: Verify all implementation step descriptors** + +```powershell +7..24 | ForEach-Object { + $path = "phases/linear-static-3d-euler-beam/step$_.md" + if (-not (Test-Path $path)) { throw "Missing $path" } + foreach ($text in @('MSVC x64 Debug','## Acceptance Criteria','## 금지사항')) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "$path missing $text" + } + } +} +``` + +- [ ] **Step 5: Executor commit checkpoint** + +Do not commit manually; the executor creates one feature commit and one metadata commit per completed step. + +### Task 4: Create Final Verification Gate Steps + +**Files:** +- Create: `phases/linear-static-3d-euler-beam/step25.md` through `step28.md` + +**Interfaces:** +- Consumes: completed solver, generated HDF5 result, approved read-only reference CSVs, and all upstream reports. +- Produces: build/test, reference-verification, physics-evaluation, and release-readiness reports. + +- [ ] **Step 1: Define strict gate transitions** + +```text +25 pass-for-reference-verification + -> 26 pass-for-physics-evaluation + -> 27 pass-for-release-agent + -> 28 ready-for-release +``` + +Each later step must block or emit the appropriate `needs-*` status when its required predecessor is not passing. Step 26 applies the exact component-scale mixed tolerance, Step 27 checks physical equilibrium and signs, and Step 28 audits traceability and limitations without publishing anything. + +- [ ] **Step 2: Enforce read-only boundaries** + +Steps 26–28 must not edit source, tests, CMake, upstream contracts, reference artifacts, or tolerance policy. Step 26 must state stress comparison is N/A while requiring the stress output schema/test evidence. + +- [ ] **Step 3: Verify the final gate descriptors** + +```powershell +25..28 | ForEach-Object { + $path = "phases/linear-static-3d-euler-beam/step$_.md" + if (-not (Test-Path $path)) { throw "Missing $path" } + foreach ($text in @('## Acceptance Criteria','reference')) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "$path missing $text" + } + } +} +``` + +- [ ] **Step 4: Executor commit checkpoint** + +Do not commit manually; Harness owns execution commits and timestamps. + +### Task 5: Validate the Generated Phase + +**Files:** +- Read: `docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md` +- Read: `phases/index.json` +- Read: `phases/linear-static-3d-euler-beam/index.json` +- Read: `phases/linear-static-3d-euler-beam/step0.md` through `step28.md` + +**Interfaces:** +- Consumes: all generated planning artifacts. +- Produces: structural and source-contract verification evidence; no solver execution. + +- [ ] **Step 1: Parse and cross-check JSON** + +```powershell +$top = Get-Content -Raw phases/index.json | ConvertFrom-Json +$task = Get-Content -Raw phases/linear-static-3d-euler-beam/index.json | ConvertFrom-Json +if (($top.phases | Where-Object dir -eq 'linear-static-3d-euler-beam').status -ne 'pending') { throw 'Top-level phase registration is invalid' } +if ($task.project -ne 'FESA Structural Solver') { throw 'Project name mismatch' } +if ($task.phase -ne 'linear-static-3d-euler-beam') { throw 'Phase name mismatch' } +if ($task.steps.Count -ne 29) { throw 'Step count mismatch' } +``` + +- [ ] **Step 2: Check step/file correspondence and required sections** + +```powershell +$task.steps | ForEach-Object { + $path = "phases/linear-static-3d-euler-beam/step$($_.step).md" + if (-not (Test-Path $path)) { throw "Missing $path" } + if ($_.status -ne 'pending') { throw "Non-pending step $($_.step)" } +} +``` + +- [ ] **Step 3: Scan for placeholders and whitespace errors** + +```powershell +$markers = @(('T' + 'BD'), ('T' + 'ODO'), ('FIX' + 'ME'), ('PLACE' + 'HOLDER'), + ('implement' + ' later'), ('Similar' + ' to Task')) +$unfinished = rg -n ($markers -join '|') ` + docs/superpowers/plans/2026-08-09-linear-static-3d-euler-beam-harness-phase.md ` + phases/linear-static-3d-euler-beam +if ($LASTEXITCODE -eq 0) { throw "Unfinished marker found:`n$unfinished" } +git diff --check +``` + +Expected: no placeholder matches and no whitespace errors. CRLF conversion warnings without whitespace error lines are acceptable. + +- [ ] **Step 4: Confirm reference artifacts are untouched** + +```powershell +git diff --name-only -- reference/ +``` + +Expected: no output. + +- [ ] **Step 5: Execution handoff** + +After the phase-construction files and existing documentation edits are reviewed and committed, execute from a clean worktree: + +```powershell +python scripts/execute.py linear-static-3d-euler-beam +``` + +Use `--push` only when remote publication is explicitly desired. diff --git a/phases/index.json b/phases/index.json new file mode 100644 index 0000000..6b4570a --- /dev/null +++ b/phases/index.json @@ -0,0 +1,8 @@ +{ + "phases": [ + { + "dir": "linear-static-3d-euler-beam", + "status": "pending" + } + ] +} diff --git a/phases/linear-static-3d-euler-beam/index.json b/phases/linear-static-3d-euler-beam/index.json new file mode 100644 index 0000000..c900f76 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/index.json @@ -0,0 +1,35 @@ +{ + "project": "FESA Structural Solver", + "phase": "linear-static-3d-euler-beam", + "steps": [ + { "step": 0, "name": "requirements-baseline", "status": "pending" }, + { "step": 1, "name": "research-evidence", "status": "pending" }, + { "step": 2, "name": "formulation-alignment", "status": "pending" }, + { "step": 3, "name": "numerical-review", "status": "pending" }, + { "step": 4, "name": "io-contract", "status": "pending" }, + { "step": 5, "name": "reference-model-contract", "status": "pending" }, + { "step": 6, "name": "implementation-plan", "status": "pending" }, + { "step": 7, "name": "cmake-test-foundation", "status": "pending" }, + { "step": 8, "name": "core-diagnostics", "status": "pending" }, + { "step": 9, "name": "dense-math-adapters", "status": "pending" }, + { "step": 10, "name": "domain-model", "status": "pending" }, + { "step": 11, "name": "inp-syntax-parser", "status": "pending" }, + { "step": 12, "name": "inp-domain-mapping", "status": "pending" }, + { "step": 13, "name": "analysis-model", "status": "pending" }, + { "step": 14, "name": "dof-manager", "status": "pending" }, + { "step": 15, "name": "analysis-state", "status": "pending" }, + { "step": 16, "name": "euler-beam-element", "status": "pending" }, + { "step": 17, "name": "parallel-for-tbb", "status": "pending" }, + { "step": 18, "name": "sparse-assembly", "status": "pending" }, + { "step": 19, "name": "essential-constraints", "status": "pending" }, + { "step": 20, "name": "mkl-pardiso-solver", "status": "pending" }, + { "step": 21, "name": "load-assembly", "status": "pending" }, + { "step": 22, "name": "result-recovery", "status": "pending" }, + { "step": 23, "name": "hdf5-results-writer", "status": "pending" }, + { "step": 24, "name": "linear-static-cli", "status": "pending" }, + { "step": 25, "name": "build-test-verification", "status": "pending" }, + { "step": 26, "name": "reference-verification", "status": "pending" }, + { "step": 27, "name": "physics-sanity", "status": "pending" }, + { "step": 28, "name": "release-readiness", "status": "pending" } + ] +} diff --git a/phases/linear-static-3d-euler-beam/step0.md b/phases/linear-static-3d-euler-beam/step0.md new file mode 100644 index 0000000..2fc0497 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step0.md @@ -0,0 +1,101 @@ +# Step 0: Requirements Baseline + +## 담당 역할과 필수 스킬 + +- 담당 역할: `requirement-agent` +- 필수 스킬: `fesa-requirements-baseline` +- 작업을 시작하기 전에 위 스킬의 `SKILL.md`를 끝까지 읽고 경계를 준수하라. + +## 읽어야 할 파일 + +먼저 아래 파일을 읽고 승인된 범위와 프로젝트 규칙을 파악하라. + +- `/AGENTS.md` +- `/docs/PRD.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/requirements/README.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/reference/cantilever beam/cantilever beam.inp` + +승인된 설계 문서의 `status: approved`와 2026-08-09 amendment를 이 step의 사용자 승인 +근거로 사용한다. + +## 작업 + +`docs/requirements/linear-static-3d-euler-beam.md`를 생성하라. 문서는 다음 계약을 +downstream agent가 추측 없이 사용할 수 있는 `shall` 요구조건과 검증 행렬로 바꿔야 한다. + +- Metadata: `feature_id: linear-static-3d-euler-beam`, `status: approved`, + `owner_agent: requirement-agent`, 현재 날짜, 승인된 설계 경로를 기록한다. +- 목적, In Scope, Out Of Scope, Analysis Definition, Input Requirements, Output + Requirements, Verification Quantities, Tolerance Policy, Reference Artifact + Requirements, Requirement Verification Matrix, Downstream Handoff를 포함한다. +- 한 입력당 단일 `*STEP, *STATIC`, 2절점 3D Euler–Bernoulli, node당 6 DOF, + `TYPE=B33`만 지원하고 B31은 오류로 거부하는 요구조건을 분리한다. +- `*PART/*ASSEMBLY/*INSTANCE` identity wrapper, stable source identity, 여러 identity + instance 허용, transform/nested assembly 거부를 요구조건으로 만든다. +- 지원 keyword와 warning no-op allowlist를 정확히 열거하고 allowlist 밖 model-affecting + keyword는 오류로 요구한다. +- factorization-before-load 순서, nonzero prescribed displacement, deterministic + COO-to-CSR, MKL/TBB/HDF5 adapter 경계, CLI exit code, HDF5 schema/output을 요구한다. +- B33 legacy reference bundle은 read-only이며 exact filename을 보존하고 stress reference + comparison은 N/A지만 `S11` output과 test는 필수임을 명시한다. +- reference tolerance는 같은 model/step/frame/quantity/component의 read-only Abaqus + scale만 사용해 `absolute_floor + 1e-6 * reference_scale`을 모든 row에 적용한다. + SI floor는 displacement/rotation `1e-9`, force/moment `1e-3`이다. +- 모든 `must` 요구조건에 acceptance criterion, verification method, tolerance 또는 N/A, + downstream agent, status를 매핑한다. 숫자 ID는 + `FESA-REQ-LS3DEB-001`부터 중복 없이 연속 부여한다. + +설계가 이미 승인했으므로 새 정책 결정을 만들지 말고, 충돌을 발견하면 문서를 승인 +상태로 꾸미지 말고 phase step을 `blocked`로 기록하라. + +## Acceptance Criteria + +```powershell +$path = 'docs/requirements/linear-static-3d-euler-beam.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @( + 'feature_id: `linear-static-3d-euler-beam`', + 'status: `approved`', + '## In Scope', + '## Out Of Scope', + '## Requirement Verification Matrix', + 'TYPE=B33', + 'TYPE=B31', + 'absolute_floor + 1e-6 * reference_scale', + 'reference/cantilever beam/' +) +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing contract text: $text" + } +} +$ids = Select-String -LiteralPath $path -Pattern 'FESA-REQ-LS3DEB-\d{3}' -AllMatches | + ForEach-Object { $_.Matches.Value } +if (($ids | Sort-Object -Unique).Count -lt 1) { throw 'No requirement ids found' } +git diff --check -- $path +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. 설계 문서 2절, 6절, 9절, 10절, 11절, 12절의 각 필수 계약이 최소 한 요구조건과 + verification matrix row에 추적되는지 점검한다. +3. 수치값, 단위, 좌표계, artifact path가 설계와 정확히 일치하는지 확인한다. +4. `/phases/linear-static-3d-euler-beam/index.json`의 Step 0을 갱신한다. + - 성공: `status`를 `completed`로 바꾸고 생성 파일과 승인 baseline을 `summary` 한 줄에 기록한다. + - 수정 3회 후 실패: `status: error`와 `error_message`를 기록한다. + - 승인 설계와 프로젝트 문서가 충돌해 사용자 결정이 필요하면 `status: blocked`와 + `blocked_reason`을 기록하고 중단한다. + +## 금지사항 + +- C++ API나 파일 구조를 설계하지 마라. 이유: Requirement Agent의 책임 범위를 넘는다. +- formulation 수식을 수정하지 마라. 이유: 수학 계약은 후속 gate가 담당한다. +- Abaqus 또는 reference solver를 실행하지 마라. 이유: 승인된 read-only artifact만 사용한다. +- `/reference/` 파일을 생성·수정·rename하지 마라. 이유: correctness baseline을 오염시킨다. +- 직접 commit하지 마라. 이유: Harness executor가 commit과 timestamp를 관리한다. diff --git a/phases/linear-static-3d-euler-beam/step1.md b/phases/linear-static-3d-euler-beam/step1.md new file mode 100644 index 0000000..3ab72e4 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step1.md @@ -0,0 +1,80 @@ +# Step 1: Research Evidence + +## 담당 역할과 필수 스킬 + +- 담당 역할: `research-agent` +- 필수 스킬: `fesa-research-evidence`, `fem-theory-query` +- 두 스킬의 `SKILL.md`를 끝까지 읽고, FEM wiki query를 우선 사용하라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/research/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` + +Step 0 산출물과 phase index의 완료 summary를 확인한 뒤 작업하라. + +## 작업 + +FEM wiki에서 다음 연구 질문을 query하고 +`docs/research/linear-static-3d-euler-beam-research.md`를 생성하라. + +- Abaqus B31과 B33의 formulation 차이 및 B33을 Euler–Bernoulli 의미로 사용하는 근거 +- 2절점 spatial Euler beam의 cubic Hermite interpolation, 6 rigid modes, rank 6, + two-point Gauss exactness, local/global transformation과 end-force sign +- Abaqus general beam section의 `A, I11, I12, I22, J`, first axis `n1`, section + resultant `SF*`/`SM*`, axial `S11` 의미 +- analytical cantilever axial/torsion/two-plane bending benchmark와 검증 가능한 물리량 +- PARDISO SPD factorization, deterministic sparse assembly, reference comparison에 필요한 + 기술 근거와 적용 한계 + +문서는 Metadata(`status: ready-for-formulation`), Research Questions, Source Inventory, +Extracted Facts, Candidate Benchmarks, Verification Relevance, Applicability Limits, +Open Issues, Downstream Handoff를 포함해야 한다. Source Inventory에는 문서명, 제공 기관, +wiki page identity, 원 출처/매뉴얼 identity, reliability tier와 적용 범위를 기록한다. +확인된 사실과 설계에서 도출한 inference를 구분한다. 기존 정식화 식을 최종 승인하거나 +새 tolerance를 만들지 않는다. + +## Acceptance Criteria + +```powershell +$path = 'docs/research/linear-static-3d-euler-beam-research.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @( + 'status: `ready-for-formulation`', + '## Research Questions', + '## Source Inventory', + '## Extracted Facts', + '## Candidate Benchmarks', + '## Applicability Limits', + 'B31', + 'B33', + 'Hermite', + 'general beam section' +) +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing research evidence: $text" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. 주요 claim마다 source tier 또는 inference 표시가 있는지 확인한다. +3. benchmark마다 target quantity와 검증할 수 없는 범위를 함께 기록했는지 확인한다. +4. Step 1을 `completed`와 한 줄 `summary`로 갱신한다. 반복 실패는 `error`, 실제 source + 부재나 상충으로 사용자 판단이 필요하면 `blocked`로 기록한다. + +## 금지사항 + +- 웹 검색 결과나 LLM 기억만을 source로 쓰지 마라. 이유: 사용자가 FEM wiki manual을 허용했다. +- formulation을 최종화하거나 C++ API를 설계하지 마라. 이유: downstream 책임이다. +- tolerance나 reference 값을 발명하지 마라. 이유: 승인 설계 값을 그대로 사용해야 한다. +- Abaqus 실행 및 `/reference/` 변경을 하지 마라. 이유: artifact는 read-only다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step10.md b/phases/linear-static-3d-euler-beam/step10.md new file mode 100644 index 0000000..453e216 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step10.md @@ -0,0 +1,102 @@ +# Step 10: Domain Model + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/core/source_identity.hpp` +- `/include/fesa/core/status.hpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` + +## 소유 파일 + +- Create: `/include/fesa/model/model_types.hpp` +- Create: `/include/fesa/model/domain.hpp` +- Create: `/src/fesa/model/domain.cpp` +- Create: `/tests/unit/model/model_types_test.cpp` +- Create: `/tests/unit/model/domain_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +parser와 analysis가 공유할 immutable semantic model을 위 exact paths에 구현하라. +최소 model types는 다음을 포함한다. + +```cpp +using EntityIndex = std::uint32_t; +struct Node { SourceEntityId sourceId; std::array coordinates; }; +struct LinearElasticMaterial { std::string name; double youngsModulus; double poissonRatio; }; +struct GeneralBeamSection { + std::string name; double area; double i11; double i12; double i22; double torsionalConstant; + std::array firstAxis; std::vector> sectionPoints; +}; +struct EulerBeam3DDefinition { + SourceEntityId sourceId; std::array nodeIndices; + EntityIndex materialIndex; EntityIndex sectionIndex; +}; +struct BoundaryCondition { std::string target; int firstDof; int lastDof; double value; }; +struct NodalLoad { std::string target; int dof; double magnitude; }; +struct StaticStepDefinition { std::string name; std::vector boundaries; + std::vector loads; }; +``` + +`PartDefinition`과 `InstanceDefinition`은 source name, referenced part, identity-instance +restriction과 source-to-internal mapping을 보존한다. `NodeSet`, `ElementSet`, +part/instance/source label mapping을 포함한다. `Domain`은 vectors와 +stable lookup을 소유하고 construction 완료 후 const access만 제공한다. 필요한 builder는 +construction 경계에만 두고 Domain을 복사하지 않아도 view를 만들 수 있는 stable index를 +보장한다. Node/element에는 equation ID를 저장하지 않는다. + +Tests는 source identity equality/order, same-part multiple-instance distinction, stable +insertion order/index, deep ownership, const access, one static step storage, equation-ID 부재를 +검증하고 `DomainModel` regex로 등록한다. + +## Acceptance Criteria + +RED targeted command 후 최소 구현으로 GREEN을 만든다. + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R DomainModel --output-on-failure +``` + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R DomainModel --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. Domain tests를 먼저 추가하고 compile/test RED를 확인한다. +2. 최소 semantic types와 immutable Domain ownership으로 GREEN을 만든다. +3. full VERIFY와 public dependency direction을 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 10 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 10을 `completed`로 갱신하고 model types/stable identity를 summary에 기록한다. + +## 금지사항 + +- Abaqus keyword string을 Domain의 핵심 의미로 저장하지 마라. 이유: syntax/model 경계를 깨뜨린다. +- Domain에 equation numbering이나 mutable analysis vector를 넣지 마라. 이유: DofManager/AnalysisState 책임이다. +- parser를 이 step에서 구현하지 마라. 이유: Step 11–12 범위다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step11.md b/phases/linear-static-3d-euler-beam/step11.md new file mode 100644 index 0000000..d6986c1 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step11.md @@ -0,0 +1,102 @@ +# Step 11: Abaqus INP Syntax Parser + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/core/diagnostic.hpp` +- `/include/fesa/core/status.hpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` +- `/reference/cantilever beam/cantilever beam.inp` + +## 소유 파일 + +- Create: `/include/fesa/io/abaqus/input_syntax.hpp` +- Create: `/include/fesa/io/abaqus/input_reader.hpp` +- Create: `/src/fesa/io/abaqus/input_reader.cpp` +- Create: `/tests/unit/io/abaqus/input_syntax_test.cpp` +- Create: `/tests/unit/io/abaqus/input_reader_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +keyword/data/comment lexical 및 syntax parsing만 위 exact paths에 구현하라. Semantic +Domain mapping은 Step 12에 남긴다. 최소 계약은 다음과 같다. + +```cpp +struct KeywordParameter { std::string name; std::optional value; }; +struct DataLine { std::vector fields; SourceLocation location; }; +struct KeywordBlock { + std::string canonicalName; + std::string originalLine; + std::vector parameters; + std::vector data; + SourceLocation location; +}; +struct ParsedInput { std::vector blocks; }; +class AbaqusInputReader { +public: + Result read(const std::filesystem::path& inputPath) const; +}; +``` + +Keyword와 parameter name은 uppercase canonical form으로 비교하되 parameter value와 +data label 원문을 보존한다. `**` comment line은 무시하고 blank line, comma-separated +field, valueless parameter, line number와 file identity를 처리한다. Keyword/data 구분, +malformed keyword, keyword 전 data line, unreadable file은 structured diagnostic으로 +반환한다. Wrapper 의미, keyword allowlist, numeric conversion은 구현하지 않는다. + +Tests는 mixed case, comments, blank/empty trailing fields, parameters, source locations, +malformed syntax, legacy cantilever syntax parse를 포함하고 `InpSyntax` regex로 등록한다. + +## Acceptance Criteria + +RED targeted command: + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R InpSyntax --output-on-failure +``` + +GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R InpSyntax --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. syntax tests를 먼저 추가하고 reader 부재 RED를 확인한다. +2. semantic 판단이 없는 최소 reader로 GREEN을 만든다. +3. legacy input을 read-only fixture로 읽고 전체 VERIFY를 수행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 11 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 11을 `completed`로 갱신하고 parsed syntax/source-location evidence를 summary에 기록한다. + +## 금지사항 + +- B33/B31 또는 supported keyword 정책을 syntax reader에 넣지 마라. 이유: semantic mapper 책임이다. +- source label/value case를 canonicalize하지 마라. 이유: stable source identity를 보존해야 한다. +- `*INCLUDE` 같은 미승인 기능을 추가하지 마라. 이유: scope 밖이다. +- reference input을 수정하지 마라. 이유: read-only fixture다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step12.md b/phases/linear-static-3d-euler-beam/step12.md new file mode 100644 index 0000000..7bd7d59 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step12.md @@ -0,0 +1,117 @@ +# Step 12: INP to Domain Mapping + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/model/model_types.hpp` +- `/include/fesa/model/domain.hpp` +- `/src/fesa/model/domain.cpp` +- `/tests/unit/model/domain_test.cpp` +- `/include/fesa/io/abaqus/input_syntax.hpp` +- `/include/fesa/io/abaqus/input_reader.hpp` +- `/src/fesa/io/abaqus/input_reader.cpp` +- `/tests/unit/io/abaqus/input_reader_test.cpp` +- `/reference/cantilever beam/cantilever beam.inp` + +## 소유 파일 + +- Create: `/include/fesa/io/abaqus/domain_mapper.hpp` +- Create: `/src/fesa/io/abaqus/domain_mapper.cpp` +- Create: `/tests/unit/io/abaqus/domain_mapper_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +ParsedInput을 검증된 immutable Domain으로 바꾸는 semantic mapper를 구현하라. + +```cpp +class AbaqusDomainMapper { +public: + Result map(const ParsedInput& input) const; +}; +``` + +지원 범위는 승인 I/O contract와 정확히 같아야 한다. + +- `*HEADING`, `*PART`/`*END PART`, `*NODE`, `*ELEMENT, TYPE=B33`, + `*NSET`/`*ELSET` 및 `GENERATE`, `*MATERIAL`/`*ELASTIC`, + `*BEAM GENERAL SECTION, SECTION=GENERAL`, `*SECTION POINTS`, + `*ASSEMBLY`/`*END ASSEMBLY`, `*INSTANCE`/`*END INSTANCE`, + `*BOUNDARY`, `*CLOAD`, `*STEP`/`*STATIC`/`*END STEP`를 mapping한다. +- 같은 part의 여러 identity instance를 deterministic stable internal IDs로 expand하고 + `SourceEntityId {instance_name, source_label}`를 보존한다. +- assembly set의 `INSTANCE` parameter와 node/set target을 해석한다. +- `A,I11,I12,I22,J`, `E,nu`, `G=E/(2*(1+nu))`, `Iy=I11`, `Iz=I22`, + `n1 -> local y`를 mapping한다. `E>0`, `-10`과 section + properties의 positivity를 검증한다. +- `*STEP`의 `NLGEOM`은 absent/`NO`만 accept하고 `YES`는 model diagnostic으로 거부한다. + `*STATIC`의 1개 또는 2–4개 time-control data field를 finite positive 값으로 읽되 V0는 + 하나의 final frame 0만 만든다. Step 앞의 model-level `*BOUNDARY`는 sole static step에 + 활성화하고 step 안 `*CLOAD`와 함께 `StaticStepDefinition`에 연결한다. +- B31은 `unsupported-element-formulation`, instance translation/rotation data는 + `unsupported-instance-transform` diagnostic으로 거부한다. Second step, nested assembly, + `I12!=0`, invalid DOF, duplicate label, dangling target/reference, nonpositive properties, + invalid geometry에도 설계/I/O contract가 정한 structured diagnostic code를 반환한다. +- `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`, + `*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT`와 그 + output-variable data는 warning으로 보존하고 무시한다. 이 allowlist 밖 unknown keyword는 + error다. FESA default outputs를 output request로 필터링하지 않는다. + +Tests는 모든 supported keyword의 positive path, mixed case, Generate, multiple identity +instances, allowlist warning, unknown keyword, B31 rejection, transform/nested/multi-step, +duplicate/dangling/invalid numeric와 approved legacy input mapping을 포함하고 +`InpDomainMapping` regex로 등록한다. + +## Acceptance Criteria + +RED targeted command: + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R InpDomainMapping --output-on-failure +``` + +GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R InpDomainMapping --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. semantic positive/negative tests를 production mapper보다 먼저 작성하고 RED를 확인한다. +2. 승인 subset에 필요한 최소 mapping/validation만 구현해 GREEN을 만든다. +3. diagnostic field/order와 Domain non-mutation을 점검하고 전체 VERIFY를 수행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 12 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 12를 `completed`로 갱신하고 supported mapping/negative diagnostics를 summary에 기록한다. + +## 금지사항 + +- B31을 Euler element로 alias하지 마라. 이유: 물리 formulation 의미가 다르다. +- transform을 무시하거나 fallback local axis를 선택하지 마라. 이유: 입력 의미를 왜곡한다. +- `*DLOAD` 또는 multiple-step propagation을 구현하지 마라. 이유: 승인 범위 밖이다. +- reference input/CSV를 수정하지 마라. 이유: read-only baseline이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step13.md b/phases/linear-static-3d-euler-beam/step13.md new file mode 100644 index 0000000..9c0b60e --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step13.md @@ -0,0 +1,97 @@ +# Step 13: AnalysisModel Active View + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/model/model_types.hpp` +- `/include/fesa/model/domain.hpp` +- `/src/fesa/model/domain.cpp` +- `/include/fesa/io/abaqus/domain_mapper.hpp` +- `/src/fesa/io/abaqus/domain_mapper.cpp` +- `/tests/unit/io/abaqus/domain_mapper_test.cpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` + +## 소유 파일 + +- Create: `/include/fesa/analysis/analysis_model.hpp` +- Create: `/src/fesa/analysis/analysis_model.cpp` +- Create: `/tests/unit/analysis/analysis_model_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +단일 static step에서 활성 entity를 stable index/reference view로 분류하는 +`AnalysisModel`만 구현하라. + +```cpp +class AnalysisModel { +public: + static Result create(const Domain& domain); + const Domain& domain() const noexcept; + const StaticStepDefinition& step() const noexcept; + const std::vector& activeElements() const noexcept; + const std::vector& activeMaterials() const noexcept; + const std::vector& activeSections() const noexcept; + const std::vector& activeBoundaryConditions() const noexcept; + const std::vector& activeLoads() const noexcept; +}; +``` + +AnalysisModel은 Domain 객체나 semantic entity를 복사·수정하지 않고, 자체 소유가 필요한 +경우 stable ID 목록만 가진다. Element에서 reachable material/section을 deterministic한 +internal index 순으로 deduplicate한다. 정확히 하나의 static step만 허용하며 missing 또는 +multiple step은 structured diagnostic이다. + +Tests는 active classification, stable ordering/deduplication, reference address identity, +Domain 불변성, missing/multiple step rejection을 포함하고 `AnalysisModel` regex로 등록한다. + +## Acceptance Criteria + +RED targeted command: + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R AnalysisModel --output-on-failure +``` + +GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R AnalysisModel --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. active-view tests를 먼저 작성하고 missing class/behavior RED를 확인한다. +2. stable ID view의 최소 구현으로 GREEN을 만든다. +3. Domain address/state 불변성과 전체 MSVC x64 Debug VERIFY를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 13 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 13을 `completed`로 바꾸고 active view/non-copy evidence를 summary에 기록한다. + +## 금지사항 + +- Domain entity를 AnalysisModel에 복제하지 마라. 이유: source of truth가 분산된다. +- load/BC propagation이나 multi-step activation을 추가하지 마라. 이유: V0는 single step이다. +- equation number나 numeric state를 저장하지 마라. 이유: DofManager/AnalysisState 책임이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step14.md b/phases/linear-static-3d-euler-beam/step14.md new file mode 100644 index 0000000..89fb39c --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step14.md @@ -0,0 +1,104 @@ +# Step 14: DofManager + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/model/domain.hpp` +- `/include/fesa/analysis/analysis_model.hpp` +- `/src/fesa/analysis/analysis_model.cpp` +- `/tests/unit/analysis/analysis_model_test.cpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` + +## 소유 파일 + +- Create: `/include/fesa/fem/dof_manager.hpp` +- Create: `/src/fesa/fem/dof_manager.cpp` +- Create: `/tests/unit/fem/dof_manager_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +node별 여섯 DOF, prescribed constraints, full/free numbering, element scatter map와 sparse +pattern을 단독 소유하는 `DofManager`를 구현하라. + +```cpp +enum class DofComponent : std::uint8_t { ux, uy, uz, urx, ury, urz }; +struct SparsePattern { std::vector rowOffsets; + std::vector columnIndices; }; +class DofManager { +public: + static Result create(const AnalysisModel& model); + std::size_t fullDofCount() const noexcept; + std::size_t freeDofCount() const noexcept; + std::size_t constrainedDofCount() const noexcept; + std::size_t fullDof(EntityIndex node, DofComponent component) const; + std::optional freeEquation(std::size_t fullDof) const; + const std::array& elementScatter(EntityIndex element) const; + const std::vector& freeDofs() const noexcept; + const std::vector& constrainedDofs() const noexcept; + const Vector& prescribedValues() const noexcept; + const SparsePattern& sparsePattern() const noexcept; +}; +``` + +Node internal index와 fixed component 순서로 full DOF를 부여하고, free/constrained mapping도 +stable하게 만든다. Boundary target expansion과 overlapping equal prescriptions를 처리하고, +서로 다른 prescribed value conflict는 diagnostic으로 거부한다. Sparse pattern은 active +element scatter에서 생성하고 각 row column을 sorted unique로 유지한다. Node/Element model +objects를 수정하지 않는다. `prescribedValues()`는 `constrainedDofCount()` 크기이며 +`constrainedDofs()`와 동일 순서의 `dc`를 반환한다. + +Tests는 6-DOF numbering, set expansion, zero/nonzero constraints, overlapping/conflicting BC, +free equation mapping, 12-DOF element scatter, CSR pattern sorted uniqueness, full/reduced +round-trip를 포함하고 `DofManager` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R DofManager --output-on-failure +``` + +위 command의 RED를 확인한 뒤 구현하고 다음 GREEN/VERIFY를 실행한다. + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R DofManager --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. numbering/constraint/pattern tests를 먼저 작성하고 RED를 확인한다. +2. deterministic mapping에 필요한 최소 구현으로 GREEN을 만든다. +3. model objects에 equation ID가 추가되지 않았는지 review하고 full VERIFY를 수행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 14 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 14를 `completed`로 갱신하고 numbering/pattern evidence를 summary에 기록한다. + +## 금지사항 + +- equation ID를 Node나 Element에 저장하지 마라. 이유: DofManager 단독 ownership 계약이다. +- penalty method, MPC, RBE를 추가하지 마라. 이유: V0 essential elimination 범위 밖이다. +- sparse numeric values를 저장하지 마라. 이유: assembly step 책임이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step15.md b/phases/linear-static-3d-euler-beam/step15.md new file mode 100644 index 0000000..bfdab0b --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step15.md @@ -0,0 +1,103 @@ +# Step 15: AnalysisState + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/math/vector.hpp` +- `/include/fesa/analysis/analysis_model.hpp` +- `/include/fesa/fem/dof_manager.hpp` +- `/src/fesa/fem/dof_manager.cpp` + +## 소유 파일 + +- Create: `/include/fesa/results/result_records.hpp` +- Create: `/include/fesa/analysis/analysis_state.hpp` +- Create: `/src/fesa/analysis/analysis_state.cpp` +- Create: `/tests/unit/results/result_records_test.cpp` +- Create: `/tests/unit/analysis/analysis_state_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +V0에서 실제 할당하는 mutable analysis quantities와 output row identity를 소유하는 +`AnalysisState`를 위 exact paths에 구현하라. 최소 계약은 다음 의미를 가진다. + +```cpp +struct StepFrameIdentity { std::string stepName; std::size_t frameIndex; }; +struct EndpointResultRow { EntityIndex element; int endpoint; SourceEntityId node; + std::array endAction; + std::array sectionResultant; }; +struct GaussResultRow { EntityIndex element; int gaussPoint; + std::array generalizedStrain; + std::array generalizedResultant; }; +struct StressS11Row { EntityIndex element; int gaussPoint; std::size_t sectionPoint; + double x1; double x2; double s11; std::string source; }; +class AnalysisState { +public: + static AnalysisState create(const DofManager& dofs, StepFrameIdentity identity); + Vector& displacement() noexcept; + Vector& externalForce() noexcept; + Vector& internalForce() noexcept; + Vector& residual() noexcept; + Vector& reaction() noexcept; + // const overloads and owned element-recovery row accessors +}; +``` + +각 full vector 크기는 `fullDofCount()`이고 zero-initialized다. Reaction은 constrained value를 +동일 full-index space에 두며 free component는 residual sanity에 사용할 수 있어야 한다. +Endpoint/Gauss/stress row는 stable element/point order로 저장한다. Velocity, acceleration, +temperature, iteration history, nonlinear state storage를 만들지 않는다. + +Tests는 allocation/zero initialization, independent ownership, step/frame identity, row ordering, +copy/move policy, forbidden-state API 부재 review를 포함하고 `AnalysisState` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R AnalysisState --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R AnalysisState --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. state ownership tests를 먼저 작성하고 RED를 확인한다. +2. V0에서 필요한 field만 최소 구현해 GREEN을 만든다. +3. 전체 VERIFY와 output row identity/order를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 15 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 15를 `completed`로 갱신하고 allocated fields/omitted fields를 summary에 기록한다. + +## 금지사항 + +- velocity, acceleration, temperature, nonlinear iteration history를 할당하지 마라. 이유: V0 범위 밖이다. +- Domain 정의를 state에 복사하지 마라. 이유: model/state ownership을 분리해야 한다. +- HDF5 API를 state에 노출하지 마라. 이유: ResultsWriter adapter 책임이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step16.md b/phases/linear-static-3d-euler-beam/step16.md new file mode 100644 index 0000000..5c55249 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step16.md @@ -0,0 +1,113 @@ +# Step 16: 3D Euler Beam Element + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/math/vector.hpp` +- `/include/fesa/math/matrix.hpp` +- `/include/fesa/model/model_types.hpp` +- `/include/fesa/results/result_records.hpp` +- `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md` + +## 소유 파일 + +- Create: `/include/fesa/elements/euler_beam_3d.hpp` +- Create: `/src/fesa/elements/euler_beam_3d.cpp` +- Create: `/tests/unit/elements/euler_beam_3d_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +승인 formulation을 그대로 구현하는 2-node `EulerBeam3D` kernel을 작성하라. + +```cpp +struct ConstantLocalLineLoad { double px; double py; double pz; double mx; }; +struct BeamStressPoint { int gaussPoint; std::size_t sectionPoint; double x1; double x2; + double s11; std::string source; }; +struct BeamRecovery { + std::array, 2> equilibriumEndActions; + std::array, 2> endpointSectionResultants; + std::array, 2> gaussGeneralizedStrains; + std::array, 2> gaussGeneralizedResultants; + std::vector stressPoints; +}; +class EulerBeam3D { +public: + static Result create(/* two nodes, guide, E, G, A, Iy, Iz, J, section points */); + Matrix localStiffness() const; + Matrix globalStiffness() const; + Vector localEquivalentLoad(const ConstantLocalLineLoad& load) const; + BeamRecovery recover(const Vector& globalElementDisplacement) const; +}; +``` + +- Local DOF order와 부호는 formulation의 12-component order를 그대로 쓴다. +- `R` rows는 `(ex,ey,ez)`, `T=diag(R,R,R,R)`, `dl=T*dg`, `Kg=T^T*Kl*T`다. +- `Kl`은 두 Gauss point로 `B^T D B`를 적분하고 closed-form과 normalized `1e-12`로 + 검증한다. Production에서 1-point reduced integration을 사용하지 않는다. +- `coordinate_scale=max(1,norm(X1),norm(X2))`에 대해 + `L>1e-12*coordinate_scale`, `norm(a_perp)>1e-12*max(1,norm(a))`를 요구한다. + `E,G,A,Iy,Iz,J>0`을 검증하고 fallback axis를 쓰지 않는다. +- line-load kernel은 constant `[px,py,pz,mx]` consistent vector만 제공한다. Parser/CLI load + object로 연결하지 않는다. +- Recovery는 equilibrium end action과 section resultants를 구분하고 two Gauss generalized + values 및 section point `S11=E(epsilon0+x2*kappa_y-x1*kappa_z)`를 생성한다. Element + identity가 없는 kernel-level `BeamStressPoint`를 Step 22가 `StressS11Row`로 감싼다. + Section point가 없으면 `(0,0), source=fesa-default` 하나를 사용한다. + +Tests는 Hermite endpoint/derivative, B matrix, Gauss/closed stiffness, symmetry, six rigid +modes/rank 6, positive deformation energy, transform orthogonality/determinant/energy invariance, +line-load signs, axial/torsion/y-z bending analytical displacement/recovery, invalid geometry와 +stress formula를 포함하고 `EulerBeam3D` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R EulerBeam3D --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R EulerBeam3D --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. formulation invariant/analytical tests를 먼저 작성해 RED를 확인한다. +2. 가장 작은 kernel 구현으로 GREEN을 만들고 normalized tolerance를 그대로 적용한다. +3. 수식/코드 component ordering을 대조하고 전체 MSVC x64 Debug VERIFY를 수행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 16 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 16을 `completed`로 갱신하고 element/recovery test evidence를 summary에 기록한다. + +## 금지사항 + +- B31/Timoshenko shear deformation을 섞지 마라. 이유: 승인 formulation이 아니다. +- 1-point bending integration이나 fallback orientation을 쓰지 마라. 이유: spurious mode/의미 왜곡 위험이다. +- transverse/torsional shear stress를 만들어내지 마라. 이유: section 정보가 부족하고 범위 밖이다. +- `*DLOAD` parser/CLI 지원을 추가하지 마라. 이유: kernel test만 승인됐다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step17.md b/phases/linear-static-3d-euler-beam/step17.md new file mode 100644 index 0000000..33dfa44 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step17.md @@ -0,0 +1,96 @@ +# Step 17: oneTBB ParallelFor Adapter + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/core/status.hpp` +- `/include/fesa/elements/euler_beam_3d.hpp` +- `/src/fesa/elements/euler_beam_3d.cpp` +- `/tests/unit/elements/euler_beam_3d_test.cpp` +- `/cmake/FesaDependencies.cmake` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` + +## 소유 파일 + +- Create: `/include/fesa/assembly/parallel_for.hpp` +- Create: `/src/fesa/assembly/parallel_for.cpp` +- Create: `/tests/unit/assembly/parallel_for_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +solver core에서 oneTBB header/type을 숨기는 element-local loop adapter를 구현하라. + +```cpp +class ParallelFor { +public: + virtual ~ParallelFor() = default; + virtual void execute(std::size_t count, + const std::function& body) const = 0; +}; +class SerialParallelFor final : public ParallelFor { /* same contract */ }; +class TbbParallelFor final : public ParallelFor { /* oneTBB implementation in .cpp */ }; +``` + +각 index는 정확히 한 번 처리하고 `count==0`은 no-op이다. Element-local 결과는 호출자가 +index-addressed storage에 기록해 scheduling과 무관한 ordering을 갖게 한다. Adapter는 +전역 sparse matrix write나 reduction을 수행하지 않는다. Oversubscription 정책은 +implementation comment와 test/implementation report에 남기고, 이 step에서 임의 global +thread setting을 바꾸지 않는다. + +Tests는 zero/one/many counts, exact-once, serial/TBB semantic equivalence, stable +index-addressed output, exception propagation policy를 검증하고 `ParallelFor` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R ParallelFor --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R ParallelFor --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +$leaks = rg -n "oneapi/tbb|tbb/" include/fesa +if ($LASTEXITCODE -eq 0) { throw "oneTBB API leaked into public headers:`n$leaks" } +if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' } +``` + +마지막 scan은 public header에서 no-match여야 한다. + +## 검증 절차 + +1. adapter conformance tests를 먼저 작성하고 RED를 확인한다. +2. Serial과 oneTBB 최소 구현으로 GREEN을 만든다. +3. public boundary scan과 전체 VERIFY를 실행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 17 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 17을 `completed`로 갱신하고 deterministic-use contract를 summary에 기록한다. + +## 금지사항 + +- 전역 sparse storage에 병렬 write하지 마라. 이유: ordering/race는 Step 18이 통제한다. +- TBB type/header를 public API에 노출하지 마라. 이유: adapter boundary 계약이다. +- process-wide thread count를 임의 변경하지 마라. 이유: MKL/TBB policy가 불명확해진다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step18.md b/phases/linear-static-3d-euler-beam/step18.md new file mode 100644 index 0000000..fad2020 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step18.md @@ -0,0 +1,109 @@ +# Step 18: Deterministic Sparse Assembly + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/math/vector.hpp` +- `/include/fesa/math/matrix.hpp` +- `/include/fesa/fem/dof_manager.hpp` +- `/include/fesa/elements/euler_beam_3d.hpp` +- `/include/fesa/assembly/parallel_for.hpp` +- `/src/fesa/assembly/parallel_for.cpp` + +## 소유 파일 + +- Create: `/include/fesa/math/sparse_matrix.hpp` +- Create: `/src/fesa/math/sparse_matrix.cpp` +- Create: `/include/fesa/assembly/sparse_assembler.hpp` +- Create: `/src/fesa/assembly/sparse_assembler.cpp` +- Create: `/tests/unit/math/sparse_matrix_test.cpp` +- Create: `/tests/unit/assembly/sparse_assembler_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +element-local stiffness contributions를 deterministic하게 COO로 수집하고 0-based CSR로 +finalize하는 별도 sparse module을 구현하라. + +```cpp +struct CooContribution { + std::size_t row; + std::size_t column; + double value; + std::size_t elementOrder; + std::size_t localOrder; +}; +class SparseMatrix { +public: + static Result fromCoo(std::size_t rows, std::size_t columns, + std::vector contributions, + const SparsePattern& expectedPattern); + std::size_t rows() const noexcept; + std::size_t columns() const noexcept; + const std::vector& rowOffsets() const noexcept; + const std::vector& columnIndices() const noexcept; + const std::vector& values() const noexcept; + Vector multiply(const Vector& rhs) const; + Status validate() const; +}; +``` + +`SparseMatrix`는 `Matrix`를 상속하지 않는다. COO는 `(row,column,elementOrder,localOrder)`로 +stable sort한 후 duplicate를 고정 순서로 합산한다. Zero value 보존/제거 policy는 +implementation plan과 I/O-independent math contract에 맞춰 하나로 고정하고 test한다. +Row offsets/column indices는 0-based, columns sorted unique, sizes/ranges consistent해야 한다. +Element stiffness 계산은 ParallelFor로 index-addressed buffer에 넣고 global reduction은 +element internal index 순서로 수행한다. + +Tests는 known matrix CSR/matrix-vector product, duplicate sum, invalid index/pattern, empty row, symmetry, +serial-vs-TBB byte-identical row/column/value vectors, repeated runs를 포함하고 +`SparseAssembly` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R SparseAssembly --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R SparseAssembly --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. CSR invariant/determinism tests를 먼저 작성하고 RED를 확인한다. +2. ordered COO reduction과 CSR ownership의 최소 구현으로 GREEN을 만든다. +3. repeated serial/TBB equivalence와 전체 VERIFY를 수행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 18 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 18을 `completed`로 갱신하고 CSR/determinism evidence를 summary에 기록한다. + +## 금지사항 + +- `SparseMatrix`를 dense `Matrix`에서 상속하지 마라. 이유: storage/backend 의미가 다르다. +- TBB worker가 shared CSR value에 직접 쓰게 하지 마라. 이유: race와 nondeterminism이 생긴다. +- PARDISO-specific descriptor/index type을 public sparse API에 넣지 마라. 이유: Step 20 adapter 책임이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step19.md b/phases/linear-static-3d-euler-beam/step19.md new file mode 100644 index 0000000..6980d0e --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step19.md @@ -0,0 +1,99 @@ +# Step 19: Essential Constraints and Matrix Partition + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/math/vector.hpp` +- `/include/fesa/math/sparse_matrix.hpp` +- `/include/fesa/fem/dof_manager.hpp` +- `/include/fesa/assembly/sparse_assembler.hpp` +- `/src/fesa/assembly/sparse_assembler.cpp` + +## 소유 파일 + +- Create: `/include/fesa/constraints/essential_constraints.hpp` +- Create: `/src/fesa/constraints/essential_constraints.cpp` +- Create: `/tests/unit/constraints/essential_constraints_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +조립된 full CSR matrix를 DofManager의 stable free/constrained ordering으로 partition하고 +full/reduced vector를 mapping하는 essential-constraint module을 구현하라. + +```cpp +struct PartitionedStiffness { + SparseMatrix kff; + SparseMatrix kfc; + SparseMatrix kcf; + SparseMatrix kcc; +}; +class EssentialConstraints { +public: + static Result partition(const SparseMatrix& full, + const DofManager& dofs); + static Vector gatherFree(const Vector& full, const DofManager& dofs); + static Vector gatherConstrained(const Vector& full, const DofManager& dofs); + static Vector reconstructFull(const Vector& freeValues, + const Vector& constrainedValues, + const DofManager& dofs); +}; +``` + +Partition은 numeric value와 row/column order를 보존하고 0-based CSR invariants를 다시 +검증한다. `dc`는 DofManager prescribed values에서 가져오며 zero로 가정하지 않는다. +이 step은 load vector나 RHS를 조립하지 않고 matrix/vector mapping만 소유한다. + +Tests는 hand-computed block extraction, no/all/mixed constraints, nonzero prescribed values, +full-free-constrained round trip, invalid dimensions/order를 검증하고 +`EssentialConstraints` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R EssentialConstraints --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R EssentialConstraints --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. partition/mapping tests를 먼저 추가하고 RED를 확인한다. +2. elimination에 필요한 최소 block extraction으로 GREEN을 만든다. +3. nonzero `dc`와 전체 VERIFY를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 19 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 19를 `completed`로 갱신하고 partition/reconstruction evidence를 summary에 기록한다. + +## 금지사항 + +- prescribed displacement를 zero로 덮어쓰지 마라. 이유: 승인된 nonzero BC를 깨뜨린다. +- penalty/MPC solver를 추가하지 마라. 이유: V0는 essential partition만 지원한다. +- RHS/load assembly를 이 step에 섞지 마라. 이유: factorization-before-load 순서를 검증해야 한다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step2.md b/phases/linear-static-3d-euler-beam/step2.md new file mode 100644 index 0000000..a16595e --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step2.md @@ -0,0 +1,83 @@ +# Step 2: Formulation Alignment + +## 담당 역할과 필수 스킬 + +- 담당 역할: `formulation-agent` +- 필수 스킬: `fesa-formulation-spec` +- 스킬의 `SKILL.md`를 끝까지 읽고 수학 계약과 구현 계약의 경계를 지켜라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/formulations/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/research/linear-static-3d-euler-beam-research.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` + +Step 0–1 산출물과 완료 summary를 확인하라. + +## 작업 + +기존 `docs/formulations/3d-isoparametric-euler-beam-formulation.md`를 승인된 V0 요구조건과 +연구 근거에 맞춰 정렬하라. 기존 정식화의 정확한 수학적 의미를 유지해야 하며, 이 +step은 새 요소를 다시 설계하는 작업이 아니다. + +- Metadata의 source requirement/research 경로와 status를 실제 산출물에 맞게 바꾸고 + `feature_id: 3d-isoparametric-euler-beam`, `status: ready-for-numerical-review`를 기록한다. +- 기존 strong/weak form, DOF 순서, `theta_y=-w'`, B matrix, constitutive matrix, + 2-point Gauss, 12x12 stiffness, transformation, line-load vector, recovery 식을 유지한다. +- 승인된 입력 의미를 수학 계약에 연결한다: `n1 -> local y`, `t x n1 -> local z`, + `Iy=I11`, `Iz=I22`, `I12=0`, scale-aware geometry validation. +- equilibrium end action, endpoint section resultant, Gauss generalized values, section-point + axial `S11`을 구분하고 stress reference comparison은 N/A임을 분명히 한다. +- 기존 Open Issues 중 승인 설계에서 해결된 tolerance, orientation, HDF5 distinction, + requirement/research 부재 항목을 제거하거나 resolved decision으로 바꾼다. +- Euler–Bernoulli slenderness 적용 범위는 limitation으로 유지하되 승인되지 않은 임의 + warning/error threshold를 추가하지 않는다. + +수식 결함을 발견해 정확한 의미를 보존하면서 정렬할 수 없으면 문서를 조용히 수정하지 +말고 Step 2를 `blocked`로 기록한다. + +## Acceptance Criteria + +```powershell +$path = 'docs/formulations/3d-isoparametric-euler-beam-formulation.md' +$required = @( + 'status: `ready-for-numerical-review`', + 'docs/requirements/linear-static-3d-euler-beam.md', + 'docs/research/linear-static-3d-euler-beam-research.md', + 'theta_y=-', + '2점 Gauss', + 'equilibrium end action', + 'section resultant', + 'S11', + 'n1' +) +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing aligned formulation contract: $text" + } +} +if (Select-String -LiteralPath $path -SimpleMatch 'status: `needs-research`' -Quiet) { + throw 'Stale formulation status remains' +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. 기존 수식의 DOF/component 순서와 부호가 승인 전 문서 의미와 동일한지 diff로 검토한다. +3. requirement/research의 모든 math handoff가 정식화 section 또는 limitation에 연결되는지 확인한다. +4. Step 2를 `completed`와 변경 요약으로 갱신한다. 수학 결함이나 upstream 충돌은 + `blocked`, 반복 편집 실패는 `error`로 기록한다. + +## 금지사항 + +- C++ class, header, storage API를 설계하지 마라. 이유: formulation은 수학 계약이다. +- 승인된 부호·DOF·적분 규칙을 편의상 바꾸지 마라. 이유: reference 의미가 달라진다. +- B31/Timoshenko 또는 `*DLOAD` parser 지원을 추가하지 마라. 이유: V0 범위 밖이다. +- Abaqus 실행 및 reference artifact 변경을 하지 마라. 이유: 이 gate는 문서 정렬만 담당한다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step20.md b/phases/linear-static-3d-euler-beam/step20.md new file mode 100644 index 0000000..3c86701 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step20.md @@ -0,0 +1,110 @@ +# Step 20: MKL PARDISO Linear Solver + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/core/status.hpp` +- `/include/fesa/core/diagnostic.hpp` +- `/include/fesa/math/vector.hpp` +- `/include/fesa/math/sparse_matrix.hpp` +- `/src/fesa/math/sparse_matrix.cpp` +- `/cmake/FesaDependencies.cmake` + +## 소유 파일 + +- Create: `/include/fesa/solvers/linear/linear_solver.hpp` +- Create: `/include/fesa/solvers/linear/mkl_pardiso_solver.hpp` +- Create: `/src/fesa/solvers/linear/mkl_pardiso_solver.cpp` +- Create: `/tests/unit/solvers/linear/linear_solver_test.cpp` +- Create: `/tests/unit/solvers/linear/mkl_pardiso_solver_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +MKL PARDISO를 solver core에서 숨기며 SPD `Kff` factorization과 RHS substitution을 분리하는 +adapter를 구현하라. Public interface는 승인된 계약과 동일해야 한다. + +```cpp +class LinearSolver { +public: + virtual ~LinearSolver() = default; + virtual Status factorize(const SparseMatrix& matrix) = 0; + virtual Status solve(const Vector& rhs, Vector& solution) const = 0; +}; + +class MklPardisoSolver final : public LinearSolver { +public: + MklPardisoSolver(); + ~MklPardisoSolver() override; + Status factorize(const SparseMatrix& matrix) override; + Status solve(const Vector& rhs, Vector& solution) const override; +private: + class Impl; + std::unique_ptr impl_; +}; +``` + +Adapter는 0-based CSR을 명시적으로 처리하고 real symmetric positive definite matrix +descriptor를 사용한다. Factorization state/workspace를 RAII로 소유하고 destructor와 +re-factorization에서 누수 없이 해제한다. 동일 factorization에 여러 RHS를 substitution할 +수 있어야 한다. invalid CSR, solve-before-factorize, dimension mismatch, nonfinite RHS, +PARDISO singular/positive-definite failure를 deterministic structured diagnostic으로 반환한다. +MKL header/type은 `.cpp`/private Impl 밖에 노출하지 않는다. + +Tests는 known SPD solution/residual `1e-10`, repeated RHS, re-factorization, invalid CSR, +singular/indefinite matrix, solve-before-factorize, dimension mismatch를 포함하고 +`MklPardisoSolver` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R MklPardisoSolver --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R MklPardisoSolver --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +$leaks = rg -n "mkl\.h|MKL_INT|pardiso" include/fesa +if ($LASTEXITCODE -eq 0) { throw "PARDISO API leaked into public headers:`n$leaks" } +if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' } +``` + +마지막 scan은 public header에서 no-match여야 한다. + +## 검증 절차 + +1. adapter tests를 먼저 작성하고 missing solver RED를 확인한다. +2. factorize/solve phase를 분리한 최소 PARDISO adapter로 GREEN을 만든다. +3. repeated RHS, RAII, residual, public boundary와 전체 VERIFY를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 20 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 20을 `completed`로 갱신하고 factorization/substitution evidence를 summary에 기록한다. + +## 금지사항 + +- factorization과 solve를 하나의 opaque method로 합치지 마라. 이유: 승인 runtime order를 깨뜨린다. +- MKL type/header를 public interface에 노출하지 마라. 이유: adapter boundary 계약이다. +- singularity에 임의 regularization을 적용하지 마라. 이유: invalid model을 숨긴다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step21.md b/phases/linear-static-3d-euler-beam/step21.md new file mode 100644 index 0000000..f622fb6 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step21.md @@ -0,0 +1,94 @@ +# Step 21: Nodal Load Assembly and Effective RHS + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/analysis/analysis_model.hpp` +- `/include/fesa/fem/dof_manager.hpp` +- `/include/fesa/constraints/essential_constraints.hpp` +- `/src/fesa/constraints/essential_constraints.cpp` + +## 소유 파일 + +- Create: `/include/fesa/assembly/load_assembler.hpp` +- Create: `/src/fesa/assembly/load_assembler.cpp` +- Create: `/tests/unit/assembly/load_assembler_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +single-step `*CLOAD`를 full external force vector에 deterministic하게 조립하고 effective +free RHS를 만드는 module을 구현하라. + +```cpp +class LoadAssembler { +public: + static Result assembleFullNodalLoad(const AnalysisModel& model, + const DofManager& dofs); + static Result effectiveFreeRhs(const Vector& fullLoad, + const SparseMatrix& kfc, + const Vector& prescribedValues, + const DofManager& dofs); +}; +``` + +Node label/node set target은 semantic Domain의 expanded stable identity를 사용한다. 같은 +full DOF의 multiple CLOAD는 source order로 합산하고 output vector ordering은 full DOF +ordering과 같다. `rhs=Ff-Kfc*dc`를 정확히 구현하며 `dc`는 constrained ordering으로 gather한다. +Nonfinite load와 dimension mismatch는 diagnostic이다. 이 module은 element line load나 +`*DLOAD` object를 만들지 않는다. + +Tests는 single node/set loads, multiple accumulation, six components, negative magnitude, +nonfinite rejection, constrained load partition, nonzero prescribed `Kfc*dc` hand calculation, +zero loads를 포함하고 `LoadAssembly` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R LoadAssembly --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R LoadAssembly --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. nodal load/effective RHS tests를 먼저 작성하고 RED를 확인한다. +2. nodal-only deterministic assembly와 RHS 최소 구현으로 GREEN을 만든다. +3. nonzero prescribed displacement와 전체 VERIFY를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 21 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 21을 `completed`로 갱신하고 load/RHS evidence를 summary에 기록한다. + +## 금지사항 + +- factorization을 이 module에서 호출하지 마라. 이유: orchestration order는 Step 24가 소유한다. +- `*DLOAD` 또는 Domain distributed-load object를 추가하지 마라. 이유: V0 입력 범위 밖이다. +- prescribed displacement contribution을 생략하지 마라. 이유: `rhs=Ff-Kfc*dc` 계약이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step22.md b/phases/linear-static-3d-euler-beam/step22.md new file mode 100644 index 0000000..f0d0a38 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step22.md @@ -0,0 +1,101 @@ +# Step 22: Result Recovery + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/analysis/analysis_model.hpp` +- `/include/fesa/analysis/analysis_state.hpp` +- `/include/fesa/fem/dof_manager.hpp` +- `/include/fesa/elements/euler_beam_3d.hpp` +- `/include/fesa/math/sparse_matrix.hpp` +- `/include/fesa/constraints/essential_constraints.hpp` +- `/include/fesa/assembly/load_assembler.hpp` + +## 소유 파일 + +- Create: `/include/fesa/results/result_recovery.hpp` +- Create: `/src/fesa/results/result_recovery.cpp` +- Create: `/tests/unit/results/result_recovery_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +full displacement로 전체 residual 반력과 element outputs를 복구해 AnalysisState에 채우는 +module을 구현하라. + +```cpp +class ResultRecovery { +public: + static Status recover(const AnalysisModel& model, + const DofManager& dofs, + const SparseMatrix& fullStiffness, + AnalysisState& state); +}; +``` + +- `internalForce=K*d`, `residual=internalForce-externalForce`를 full space에서 계산하고 + constrained DOF reaction을 residual에서 복구한다. Element end action을 별도 합산해 + reaction을 만들지 않는다. +- Free residual normalized criterion은 `1e-10`이고 nonfinite를 실패시킨다. +- Active element internal index 순서로 global 12-DOF vector를 gather하고 `EulerBeam3D::recover` + 결과를 endpoint/Gauss/stress rows에 안정적으로 저장한다. +- Equilibrium end action `[FX,FY,FZ,MX,MY,MZ]`, endpoint section resultant `[N,T,My,Mz]`, + Gauss generalized strain/resultant, section-point `S11`을 서로 다른 row/data로 유지한다. +- Reference용 node-station normalization helper는 동일 section-cut sign으로 endpoint를 + 변환하고 interior endpoint 불일치를 평균으로 숨기지 않으며, 일치한 경우 작은 stable + element ID를 대표 row로 선택한다. + +Tests는 hand matrix reaction, nonzero prescribed displacement, free residual, axial/torsion/ +y-z bending signs, end action vs section resultant distinction, stress point order/default centroid, +interior endpoint match/mismatch와 stable representative를 포함하고 `ResultRecovery` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R ResultRecovery --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R ResultRecovery --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +## 검증 절차 + +1. reaction/recovery/sign/normalization tests를 먼저 작성하고 RED를 확인한다. +2. residual 기반 최소 recovery 구현으로 GREEN을 만든다. +3. formulation component ordering과 full VERIFY를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 22 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 22를 `completed`로 갱신하고 recovered quantities/residual evidence를 summary에 기록한다. + +## 금지사항 + +- reaction을 element endpoint 합산 경로로 계산하지 마라. 이유: nodal load와 nonzero BC를 놓친다. +- interior endpoint mismatch를 average로 숨기지 마라. 이유: tolerance failure evidence다. +- shear stress나 nodal stress averaging을 추가하지 마라. 이유: V0 recovery 범위 밖이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step23.md b/phases/linear-static-3d-euler-beam/step23.md new file mode 100644 index 0000000..91dfd5c --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step23.md @@ -0,0 +1,127 @@ +# Step 23: HDF5 Results Writer + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/core/diagnostic.hpp` +- `/include/fesa/model/domain.hpp` +- `/include/fesa/analysis/analysis_state.hpp` +- `/include/fesa/results/result_records.hpp` +- `/cmake/FesaDependencies.cmake` + +## 소유 파일 + +- Create: `/include/fesa/results/results_writer.hpp` +- Create: `/include/fesa/io/hdf5/hdf5_results_writer.hpp` +- Create: `/src/fesa/io/hdf5/hdf5_results_writer.cpp` +- Create: `/tests/unit/results/results_writer_test.cpp` +- Create: `/tests/unit/io/hdf5/hdf5_results_writer_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +HDF5 API를 adapter 안에 숨기고 schema v0를 임시 파일에 완성한 후 final path로 교체하는 +ResultsWriter를 구현하라. + +```cpp +class ResultsWriter { +public: + virtual ~ResultsWriter() = default; + virtual Status write(const std::filesystem::path& outputPath, + const Domain& domain, + const AnalysisState& state, + const std::vector& diagnostics) = 0; +}; +class Hdf5ResultsWriter final : public ResultsWriter { +public: + Status write(const std::filesystem::path& outputPath, + const Domain& domain, + const AnalysisState& state, + const std::vector& diagnostics) override; +}; +``` + +다음 group/dataset을 exact path와 승인 shape/component order로 기록한다. + +```text +/metadata +/model/nodes +/model/elements +/steps//frames/0/nodal/displacement +/steps//frames/0/nodal/reaction +/steps//frames/0/element/end_force_local +/steps//frames/0/element/section_resultant +/steps//frames/0/element/generalized_strain +/steps//frames/0/element/generalized_resultant +/steps//frames/0/element/stress_s11 +/diagnostics +``` + +승인 설계의 schema 목록은 minimum contract이며, 별도 `generalized_resultant` dataset은 +설계가 요구한 Gauss-point generalized resultant를 손실 없이 기록하기 위한 필수 sibling이다. +Metadata는 schema/solver version, source input identity, `user-consistent-unspecified` unit +label, coordinate convention, `B33 Euler-Bernoulli` formulation을 가진다. Model rows는 stable +internal ID와 instance/source label을 함께 쓴다. 모든 field에는 component/output-location +identity를 기록한다. HDF5 handle은 RAII로 닫고 failure 시 incomplete final `results.h5`를 +남기지 않는다. Existing final 교체도 Windows에서 실패 중간 상태를 만들지 않는 adapter +내 정책과 test를 제공한다. HDF5/Windows API type은 public header에 노출하지 않는다. + +Tests는 complete schema/shape/metadata/identity/component, diagnostics warning, no section +points centroid, failed path/no partial final, successful replacement을 포함하고 +`Hdf5ResultsWriter` regex로 등록한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure +``` + +RED 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R Hdf5ResultsWriter --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +$leaks = rg -n "H5[A-Z_a-z0-9]*|hid_t" include/fesa +if ($LASTEXITCODE -eq 0) { throw "HDF5 API leaked into public headers:`n$leaks" } +if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' } +``` + +마지막 scan은 public header에서 no-match여야 한다. + +## 검증 절차 + +1. schema/atomicity tests를 먼저 작성하고 writer 부재 RED를 확인한다. +2. exact schema와 RAII/temporary finalization의 최소 구현으로 GREEN을 만든다. +3. HDF5 inspection, failure cleanup, public boundary와 전체 VERIFY를 확인한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 23 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 23을 `completed`로 갱신하고 schema/atomicity evidence를 summary에 기록한다. + +## 금지사항 + +- CSV를 공식 solver output으로 추가하지 마라. 이유: authoritative output은 HDF5 하나다. +- Abaqus output request로 dataset을 생략하지 마라. 이유: FESA default output은 항상 생성된다. +- HDF5 type/header를 public API에 노출하지 마라. 이유: adapter boundary 계약이다. +- 실패 후 incomplete final file을 남기지 마라. 이유: output integrity 계약이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step24.md b/phases/linear-static-3d-euler-beam/step24.md new file mode 100644 index 0000000..a7c0227 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step24.md @@ -0,0 +1,167 @@ +# Step 24: Linear Static Orchestration and CLI + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/io/abaqus/input_reader.hpp` +- `/include/fesa/io/abaqus/domain_mapper.hpp` +- `/include/fesa/analysis/analysis_model.hpp` +- `/include/fesa/analysis/analysis_state.hpp` +- `/include/fesa/fem/dof_manager.hpp` +- `/include/fesa/assembly/parallel_for.hpp` +- `/include/fesa/assembly/sparse_assembler.hpp` +- `/include/fesa/constraints/essential_constraints.hpp` +- `/include/fesa/solvers/linear/linear_solver.hpp` +- `/include/fesa/assembly/load_assembler.hpp` +- `/include/fesa/results/result_recovery.hpp` +- `/include/fesa/results/results_writer.hpp` +- `/include/fesa/io/hdf5/hdf5_results_writer.hpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` +- `/reference/cantilever beam/`의 승인된 네 파일 + +## 소유 파일 + +- Create: `/include/fesa/analysis/linear_static_analysis.hpp` +- Create: `/src/fesa/analysis/linear_static_analysis.cpp` +- Create: `/include/fesa/app/fesa_application.hpp` +- Create: `/src/fesa/app/fesa_application.cpp` +- Create: `/src/fesa/app/main.cpp` +- Create: `/tests/integration/analysis/linear_static_analysis_test.cpp` +- Create: `/tests/integration/app/fesa_application_test.cpp` +- Create: `/tests/reference/reference_comparison.hpp` +- Create: `/tests/reference/reference_comparison.cpp` +- Create: `/tests/reference/reference_comparison_test.cpp` +- Create: `/tests/reference/b33_reference_comparison_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +전체 single-step lifecycle과 `fesa.exe` CLI를 구현하고 Step 26이 재사용할 read-only +reference comparison test utility를 완성하라. + +```cpp +struct AnalysisRequest { std::filesystem::path inputPath; std::filesystem::path outputPath; }; +class Analysis { +public: + virtual ~Analysis() = default; + Status run(const AnalysisRequest& request); +protected: + virtual Status initialize(const AnalysisRequest& request) = 0; + virtual Status buildAnalysisModel() = 0; + virtual Status buildDofMapAndSparsePattern() = 0; + virtual Status assembleAndPartitionStiffness() = 0; + virtual Status factorize() = 0; + virtual Status assembleLoadsAndEffectiveRhs() = 0; + virtual Status substituteAndReconstruct() = 0; + virtual Status recoverAndWriteResults() = 0; +}; +class LinearStaticAnalysis final : public Analysis { /* V0 hook implementations */ }; +class FesaApplication { +public: + int run(const std::vector& arguments); +}; +``` + +`LinearStaticAnalysis::run`은 다음 event order를 exact하게 고정하고 각 실패를 diagnostic/ +exit category에 연결한다. + +```text +parse input -> Domain -> AnalysisModel -> DofManager/sparse pattern +-> parallel element stiffness -> deterministic COO-to-CSR +-> free/constrained partition -> factorize(Kff) +-> assemble full nodal load -> rhs=Ff-Kfc*dc +-> solve substitution -> reconstruct full displacement +-> residual/reaction/element recovery -> atomic HDF5 write +``` + +Spy/fake adapters를 사용한 orchestration test는 `factorize` event가 load assembly보다 먼저고 +`solve`가 factorization을 재수행하지 않음을 검증한다. 실제 production default는 +TbbParallelFor, MklPardisoSolver, Hdf5ResultsWriter를 사용한다. + +CLI는 `fesa.exe --output `와 output 생략 시 current directory +`results.h5`를 지원한다. Exit code는 `0 success`, `2 usage`, `3 input syntax/semantic`, +`4 model validation`, `5 factorization/substitution`, `6 HDF5 output`이다. Error diagnostics는 +stderr에 deterministic order로 쓰고 warning은 output diagnostics에도 보존한다. CMake +executable target은 내부 이름이 다르더라도 `OUTPUT_NAME fesa`를 설정해 Debug output이 +실제로 `fesa.exe`가 되게 한다. + +Test-only reference support를 `tests/reference/` 아래 구현하라. + +- approved input으로 `.harness/build/reference/cantilever-beam-b33/results.h5`를 생성한다. +- legacy displacement/reaction/elemental-force CSV를 read-only로 parse하고 실제 CAE header + `U-U*`, `UR-UR*`, `RF-RF*`, `RM-RM*`, `SF-SF1`, `SM-SM*`을 canonical component로 normalize한다. +- row matching 전에 expected header, B33 input, unique identity, missing/extra/nonfinite를 검사한다. +- same model/step/frame/quantity/component의 Abaqus-only scale과 + `absolute_floor + 1e-6*reference_scale`로 모든 row를 판정한다. +- section resultants는 node station과 `SF1->N`, `SM1->My`, `SM2->Mz`, `SM3->T`로 비교한다. +- Stress comparison은 N/A로 기록하되 HDF5 stress dataset/test 통과를 요구한다. +- max absolute, component-scale normalized, RMS, norm, worst row/component를 + `.harness/build/reference/cantilever-beam-b33/comparison.json`에 결정적으로 기록한다. +- 같은 JSON에 matched FESA/reference rows, full free residual norm, applied/reaction force와 + origin 기준 moment 합, endpoint consistency를 `physics_evidence`로 기록해 Step 27이 + source/test 변경 없이 물리 sanity를 독립 검토할 수 있게 한다. + +Tests는 orchestration order, CLI default/explicit output, all exit codes, output-request no-op, +approved input end-to-end, reference tolerance zero/near-zero/failure cases를 포함한다. +CTest regex/label은 `LinearStaticCli`, `ReferenceComparisonContract`, +`B33ReferenceComparison`으로 실행 가능하게 한다. + +## Acceptance Criteria + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R "LinearStaticCli|ReferenceComparisonContract|B33ReferenceComparison" --output-on-failure +``` + +위 command에서 missing orchestration/CLI/reference utility RED를 확인한 후 구현한다. + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R "LinearStaticCli|ReferenceComparisonContract|B33ReferenceComparison" --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +if (-not (Test-Path '.harness/build/reference/cantilever-beam-b33/results.h5')) { throw 'Missing reference-run HDF5' } +if (-not (Test-Path '.harness/build/reference/cantilever-beam-b33/comparison.json')) { throw 'Missing comparison metrics' } +git diff --exit-code -- reference/ +``` + +## 검증 절차 + +1. orchestration/CLI/reference contract tests를 먼저 작성하고 targeted RED를 확인한다. +2. exact lifecycle과 minimal CLI/test utility로 targeted GREEN을 만든다. +3. approved input end-to-end, comparison metrics, CTest discovery/full VERIFY를 실행한다. +4. reference artifacts가 unchanged인지 확인한다. +5. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 24 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output, 변경 파일과 generated HDF5/comparison evidence를 기록한다. +6. Step 24를 `completed`로 갱신하고 CLI path, exit codes, generated HDF5/metrics와 + RED/GREEN/VERIFY evidence를 summary에 기록한다. + +## 금지사항 + +- load assembly를 factorization 앞으로 옮기지 마라. 이유: 승인 runtime order와 반대다. +- factorize와 substitution을 합치지 마라. 이유: solver contract와 repeated RHS 검증을 깨뜨린다. +- B31/multiple-step/transform/`*DLOAD`를 지원하지 마라. 이유: V0 범위 밖이다. +- reference CSV를 보정·rename·rewrite하지 마라. 이유: comparison baseline을 오염시킨다. +- stress reference comparison을 만들어내지 마라. 이유: 승인 범위에서 명시적 N/A다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step25.md b/phases/linear-static-3d-euler-beam/step25.md new file mode 100644 index 0000000..579aa46 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step25.md @@ -0,0 +1,85 @@ +# Step 25: Build and Test Verification + +## 담당 역할과 필수 스킬 + +- 담당 역할: `build-test-executor-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 이 step은 검증과 보고만 수행한다. 실패를 production 변경으로 덮지 않는다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/build-test-reports/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` +- `/CMakeLists.txt`와 모든 CMake/test registration +- `/phases/linear-static-3d-euler-beam/index.json`의 Step 7–24 summary + +## 작업 + +fresh MSVC x64 Debug configure/build/test evidence를 수집해 +`docs/build-test-reports/linear-static-3d-euler-beam.md`를 생성하라. + +- Metadata status는 모든 gate 통과 시 `pass-for-reference-verification`이다. +- Environment/dependency revision과 config-resolved command를 기록한다. +- Configure, build, targeted feature tests, CTest discovery, full CTest 각각에 command, + start/end 또는 duration, exit code, stdout/stderr tail, verdict를 기록한다. +- CTest discovery가 하나 이상의 test를 포함하고 compiler metadata가 MSVC인지 확인한다. +- `/W4 /WX`로 새 product warning이 없는지 build output/CMake setting으로 확인한다. +- implementation report의 Step 7–24 RED/GREEN/VERIFY evidence가 모두 present인지 감사한다. +- 실패는 `configure | compile | link | test | reference-comparison | harness | environment | + upstream-contract` 중 하나로 분류하고 correction handoff를 기록한다. + +## Acceptance Criteria + +아래 명령을 fresh evidence로 실행한다. + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +$discovery = ctest --test-dir .harness/build -C Debug --show-only=json-v1 | ConvertFrom-Json +if ($discovery.tests.Count -lt 1) { throw 'CTest discovered zero tests' } +ctest --test-dir .harness/build -C Debug -L linear-static-3d-euler-beam --output-on-failure +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +Report structural check: + +```powershell +$path = 'docs/build-test-reports/linear-static-3d-euler-beam.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @('status: `pass-for-reference-verification`', 'MSVC', 'x64', 'Debug', + 'configure', 'build', 'show-only=json-v1', 'output-on-failure', 'exit code', 'duration') +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing build/test evidence: $text" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. 모든 command를 새로 실행하고 실제 exit code/duration/output tail을 기록한다. +2. implementation evidence와 CTest discovered tests를 대조한다. +3. 모두 성공한 경우에만 report와 Step 25를 pass/completed로 갱신한다. +4. 실패 시 report에 정확한 classification과 correction handoff를 기록하고 Step 25를 + `error`로 둔다. 환경/사용자 조치가 필수인 경우만 `blocked`로 둔다. + +## 금지사항 + +- source, tests, CMake를 수정하지 마라. 이유: independent build/test gate다. +- 실패 test를 disable/filter-out하지 마라. 이유: 회귀를 숨긴다. +- reference artifact나 tolerance를 수정하지 마라. 이유: 이 gate의 책임 밖이다. +- command 결과를 추정하거나 이전 summary를 fresh evidence로 대체하지 마라. 이유: gate 신뢰성을 잃는다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step26.md b/phases/linear-static-3d-euler-beam/step26.md new file mode 100644 index 0000000..2bf5f92 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step26.md @@ -0,0 +1,104 @@ +# Step 26: Abaqus B33 Reference Verification + +## 담당 역할과 필수 스킬 + +- 담당 역할: `reference-verification-agent` +- 필수 스킬: `fesa-reference-comparison` +- `ARTIFACT CHECK -> COMPARE -> CLASSIFY -> REPORT` 순서를 지켜라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/reference-verifications/README.md` +- `/docs/build-test-reports/linear-static-3d-euler-beam.md` +- `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md` +- `/reference/cantilever beam/cantilever beam.inp` +- `/reference/cantilever beam/cantilever beam displacements.csv` +- `/reference/cantilever beam/cantilever beam reactions.csv` +- `/reference/cantilever beam/cantilever beam elemental forces.csv` +- Step 24가 생성한 reference comparison test/command 계약과 build-directory result/metrics + +## 작업 + +Build/Test report status가 `pass-for-reference-verification`인지 먼저 확인한다. 통과했다면 +승인 input으로 solver output을 재생성하고, test-only comparison utility가 기록한 raw +normalized rows/metrics를 독립 검토해 +`docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md`를 작성하라. + +Artifact check: + +- exact legacy 네 파일 존재, input `TYPE=B33`, expected CAE CSV headers, unique row keys, + finite values를 검사한다. +- 이 bundle은 승인된 예외이므로 `metadata.json`, `README.md`, stress CSV 부재만으로 + 차단하지 않는다. Contract에서 provenance/units/schema/stress N/A를 확인한다. +- generated HDF5 schema/version/units/coordinate/step-frame/source identity를 검사한다. + +Comparison: + +- displacement CSV `U-U1/U-U2/U-U3/UR-UR1/UR-UR2/UR-UR3`, reaction CSV + `RF-RF1/RF-RF2/RF-RF3/RM-RM1/RM-RM2/RM-RM3`, section-resultant CSV + `SF-SF1/SM-SM1/SM-SM2/SM-SM3`을 canonical component로 normalize한 뒤 exact + identity/component mapping으로 비교한다. +- CSV increment 1/time 1.0을 `(Step-1, frame 0)`으로 normalize한다. +- interior endpoint consistency를 먼저 검사하고 평균으로 숨기지 않는다. +- 같은 model/step/frame/quantity/component의 read-only reference rows에서만 + `reference_scale=max(abs(reference_value_i))`를 계산한다. +- 모든 row에 `absolute_floor + 1e-6*reference_scale`을 적용한다. SI displacement/rotation + floor `1e-9`, force/moment floor `1e-3`; scale zero면 floor만 적용한다. +- Missing/extra/nonfinite/schema/identity mismatch는 tolerance 전에 fail한다. +- max absolute error, component-scale normalized error, RMS, norm, worst row/component를 기록한다. +- Stress reference comparison은 N/A라고 명시하고 HDF5 stress schema/unit test evidence를 연결한다. + +모든 비교 통과 시 Metadata status는 `pass-for-physics-evaluation`이다. No-Change Assertion에 +source/test/CMake/reference/tolerance가 모두 unchanged임을 기록한다. + +## Acceptance Criteria + +```powershell +if (-not (Select-String -LiteralPath 'docs/build-test-reports/linear-static-3d-euler-beam.md' ` + -SimpleMatch 'status: `pass-for-reference-verification`' -Quiet)) { + throw 'Build/test gate is not passing' +} +ctest --test-dir .harness/build -C Debug -R B33ReferenceComparison -V --output-on-failure +$metricsPath = '.harness/build/reference/cantilever-beam-b33/comparison.json' +if (-not (Test-Path $metricsPath)) { throw 'Missing comparison metrics' } +$metrics = Get-Content -Raw $metricsPath | ConvertFrom-Json +if ($metrics.status -ne 'pass') { throw "Reference comparison failed: $($metrics.status)" } +git diff --exit-code -- reference/ +``` + +```powershell +$path = 'docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @('status: `pass-for-physics-evaluation`', '## Artifact Inventory', + '## Comparison Contract', '## Quantity Results', '## No-Change Assertion', + 'cantilever-beam-b33', 'absolute_floor + 1e-6 * reference_scale', 'stress', 'N/A') +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing reference verification evidence: $text" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Artifact check를 comparison보다 먼저 완료한다. +2. B33ReferenceComparison을 fresh 실행하고 comparison JSON과 HDF5를 직접 확인한다. +3. 모든 row/metric/tolerance가 통과한 경우에만 report와 Step 26을 pass/completed로 갱신한다. +4. 실패는 정해진 classification과 handoff를 report에 기록하고 Step 26을 `error`로 둔다. + 사용자/외부 artifact 조치가 필수인 경우만 `blocked`로 둔다. + +## 금지사항 + +- source, tests, CMake, upstream contract를 수정하지 마라. 이유: independent comparison gate다. +- FESA 결과나 reference value로 scale/tolerance를 조정하지 마라. 이유: acceptance를 오염시킨다. +- row를 zero-clamp, 삭제, 평균 처리하지 마라. 이유: mismatch를 숨긴다. +- reference artifact를 생성·수정·rename하지 마라. 이유: read-only baseline이다. +- Abaqus를 실행하지 마라. 이유: 저장된 CSV만 authoritative reference다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step27.md b/phases/linear-static-3d-euler-beam/step27.md new file mode 100644 index 0000000..1cc94ec --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step27.md @@ -0,0 +1,91 @@ +# Step 27: Physics Sanity + +## 담당 역할과 필수 스킬 + +- 담당 역할: `physics-evaluation-agent` +- 필수 스킬: `fesa-physics-sanity` +- reference tolerance를 다시 판정하지 말고 documented physical expectation만 평가하라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/physics-evaluations/README.md` +- `/docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md` +- `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/.harness/build/reference/cantilever-beam-b33/results.h5` +- `/.harness/build/reference/cantilever-beam-b33/comparison.json` +- `/reference/cantilever beam/`의 승인된 read-only artifact + +## 작업 + +Reference Verification status가 `pass-for-physics-evaluation`인지 먼저 확인하고 +`docs/physics-evaluations/linear-static-3d-euler-beam-physics-evaluation.md`를 생성하라. + +다음 physical check를 documented expectation과 observed HDF5/comparison evidence로 각각 +판정한다. + +- global applied force + reaction force equilibrium +- origin 기준 applied/reaction force moment와 reaction moment equilibrium +- constrained DOF reaction consistency와 free residual normalized `1e-10` +- load 방향에 대한 displacement/rotation direction과 sign +- expected zero/symmetry components +- adjacent element endpoint section resultant consistency와 boundary end action balance +- local/global component mapping, section-force signs, `S11` location/sign sanity +- nonfinite, rigid-body-mode, 비정상 magnitude/energy 징후 +- B33 cantilever가 검증하는 범위와 line-load/rotated/analytical unit test가 보완하는 coverage + +각 check에 식, unit, coordinate system, observed value/norm, criterion, verdict를 기록한다. +Stress는 Abaqus reference comparison 없이 schema/unit/analytical evidence로만 sanity를 +평가한다고 명시한다. 모든 documented check가 통과하면 Metadata와 Evaluation Verdict를 +`pass-for-release-agent`로 둔다. No-Change Assertion을 포함한다. + +## Acceptance Criteria + +```powershell +$referenceReport = 'docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md' +if (-not (Select-String -LiteralPath $referenceReport ` + -SimpleMatch 'status: `pass-for-physics-evaluation`' -Quiet)) { + throw 'Reference verification gate is not passing' +} +ctest --test-dir .harness/build -C Debug -R "EulerBeam3D|ResultRecovery|B33ReferenceComparison" --output-on-failure +if (-not (Test-Path '.harness/build/reference/cantilever-beam-b33/results.h5')) { throw 'Missing solver HDF5 evidence' } +if (-not (Test-Path '.harness/build/reference/cantilever-beam-b33/comparison.json')) { throw 'Missing normalized comparison/physics evidence' } +git diff --exit-code -- reference/ +``` + +```powershell +$path = 'docs/physics-evaluations/linear-static-3d-euler-beam-physics-evaluation.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @('status: `pass-for-release-agent`', '## Input Evidence', '## Physics Checks', + 'global equilibrium', 'reaction consistency', 'displacement direction', + 'element force', 'stress', '## No-Change Assertion') +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing physics evidence: $text" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Passing reference report와 exact solver artifact identity를 확인한다. +2. 각 physical expectation을 HDF5/metrics/test evidence로 계산·검토한다. +3. 모두 통과한 경우에만 report와 Step 27을 pass/completed로 갱신한다. +4. 실패는 physics classification과 owning agent handoff를 기록하고 Step 27을 `error`로 둔다. + 추가 reference model/사용자 결정이 필수이면 `blocked`로 둔다. + +## 금지사항 + +- source, tests, CMake, upstream reports/contracts를 수정하지 마라. 이유: independent physics gate다. +- reference tolerance 성공을 다시 판정하거나 완화하지 마라. 이유: Step 26 책임이다. +- undocumented expectation으로 pass를 만들지 마라. 이유: 검토 traceability가 사라진다. +- Abaqus 실행 또는 reference artifact 변경을 하지 마라. 이유: read-only evidence다. +- release readiness를 승인하지 마라. 이유: Step 28 책임이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step28.md b/phases/linear-static-3d-euler-beam/step28.md new file mode 100644 index 0000000..23e8ed1 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step28.md @@ -0,0 +1,100 @@ +# Step 28: Release Readiness + +## 담당 역할과 필수 스킬 + +- 담당 역할: `release-agent` +- 필수 스킬: `fesa-release-readiness` +- `GATE AUDIT -> TRACEABILITY CHECK -> RELEASE DOCUMENTATION -> RELEASE VERDICT` 순서를 지켜라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/PRD.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/releases/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/research/linear-static-3d-euler-beam-research.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md` +- `/docs/build-test-reports/linear-static-3d-euler-beam.md` +- `/docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md` +- `/docs/physics-evaluations/linear-static-3d-euler-beam-physics-evaluation.md` +- `/phases/linear-static-3d-euler-beam/index.json`의 모든 completed summary + +## 작업 + +모든 gate evidence를 감사하고 +`docs/releases/linear-static-3d-euler-beam-release.md`를 생성하라. + +- 같은 feature ID, source design revision, implementation scope와 artifact identity가 모든 + 문서에서 일치하는지 확인한다. +- Build/Test `pass-for-reference-verification`, Reference Verification + `pass-for-physics-evaluation`, Physics Evaluation `pass-for-release-agent`를 필수로 요구한다. +- 모든 `FESA-REQ-LS3DEB-*` must requirement를 acceptance criterion, test ID, reference/ + analytical evidence, final disposition에 연결한다. +- Release Scope, Gate Evidence Inventory, Acceptance Traceability, Validation Evidence, + Known Limitations, Release Notes Draft, Release Verdict, Handoff, No-Change Assertion을 작성한다. +- Known Limitations에는 B31, multiple steps, transforms/nested assembly, `I12!=0`, `*DLOAD`, + nonlinear/dynamic/contact/thermal, shear/warping stress, beam stress reference N/A, legacy + artifact exception을 포함한다. +- 모든 evidence가 present/passing이고 unresolved blocker가 없을 때만 + `status: ready-for-release`와 같은 verdict를 발행한다. + +이 verdict는 내부 feature readiness이며 publish, package, tag, push 또는 external release를 +수행하는 권한이 아니다. + +## Acceptance Criteria + +```powershell +$gates = @{ + 'docs/build-test-reports/linear-static-3d-euler-beam.md' = 'status: `pass-for-reference-verification`' + 'docs/reference-verifications/linear-static-3d-euler-beam-reference-verification.md' = 'status: `pass-for-physics-evaluation`' + 'docs/physics-evaluations/linear-static-3d-euler-beam-physics-evaluation.md' = 'status: `pass-for-release-agent`' +} +foreach ($entry in $gates.GetEnumerator()) { + if (-not (Select-String -LiteralPath $entry.Key -SimpleMatch $entry.Value -Quiet)) { + throw "Gate is not passing: $($entry.Key)" + } +} +$phase = Get-Content -Raw 'phases/linear-static-3d-euler-beam/index.json' | ConvertFrom-Json +if (($phase.steps | Where-Object { $_.step -lt 28 -and $_.status -ne 'completed' }).Count -ne 0) { + throw 'One or more prerequisite phase steps are incomplete' +} +``` + +```powershell +$path = 'docs/releases/linear-static-3d-euler-beam-release.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @('status: `ready-for-release`', '## Release Scope', '## Gate Evidence Inventory', + '## Acceptance Traceability', '## Validation Evidence', '## Known Limitations', + '## Release Notes Draft', '## Release Verdict', '## No-Change Assertion', + 'TYPE=B33', 'TYPE=B31', 'stress reference', 'N/A') +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing release evidence: $text" + } +} +git diff --check -- $path +git diff --exit-code -- reference/ +``` + +## 검증 절차 + +1. Gate status와 feature/source identity를 먼저 감사한다. +2. 모든 must requirement의 test/reference/final disposition trace를 확인한다. +3. limitations와 N/A가 Release Notes Draft에 누락되지 않았는지 확인한다. +4. 모든 조건을 만족한 경우에만 report와 Step 28을 ready/completed로 갱신한다. +5. evidence가 missing/failing/contradictory면 적절한 `needs-*` verdict와 handoff를 report에 + 기록하고 Step 28을 `error`로 둔다. 사용자 결정이 필수인 경우만 `blocked`로 둔다. + +## 금지사항 + +- source, tests, CMake, upstream gate report, reference artifact, tolerance를 수정하지 마라. 이유: audit 독립성이다. +- failed/missing gate를 override하지 마라. 이유: release verdict 신뢰성을 깨뜨린다. +- publish, deploy, package, tag, push를 수행하지 마라. 이유: 사용자 명시 권한이 없다. +- 직접 commit하지 마라. 이유: Harness executor가 phase metadata commit을 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step3.md b/phases/linear-static-3d-euler-beam/step3.md new file mode 100644 index 0000000..ec053d5 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step3.md @@ -0,0 +1,79 @@ +# Step 3: Numerical Review + +## 담당 역할과 필수 스킬 + +- 담당 역할: `numerical-review-agent` +- 필수 스킬: `fesa-numerical-review` +- 스킬을 끝까지 읽고 formulation 작성자와 독립된 reviewer 관점으로 작업하라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/numerical-reviews/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/research/linear-static-3d-euler-beam-research.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` + +## 작업 + +`docs/numerical-reviews/linear-static-3d-euler-beam-review.md`를 생성해 구현 전 수치 +검토를 수행하라. + +- Metadata와 `Review Verdict`를 포함하고 통과 시 + `status: pass-for-implementation-planning`을 사용한다. +- `[u,v,w,theta_x,theta_y,theta_z]` DOF 순서, `theta_y=-w'`, `My=-EIy*w''`, natural + boundary/end-action 부호를 독립 재유도한다. +- 4x12 B matrix와 12x12 closed-form stiffness의 대응, 2-point Gauss exactness, + symmetry, rank 6, six rigid modes, positive deformation energy를 검토한다. +- `R`, `T` orthogonality/right-handedness와 energy invariance를 검토한다. +- consistent constant line-load vector의 component와 부호를 검토하되 `*DLOAD` input은 + 범위 밖임을 유지한다. +- free/constrained partition, nonzero prescribed displacement, residual reaction, + SPD factorization 가정과 singularity/conditioning 위험을 검토한다. +- 구현 테스트 권고를 구체적 test id/criterion으로 제시하고 confirmed defect, risk, + open issue를 분리한다. + +확인된 수학 결함이 하나라도 있으면 `pass-for-implementation-planning`을 발행하지 말고 +`needs-formulation-revision`으로 보고한 뒤 phase step을 `blocked`로 기록한다. + +## Acceptance Criteria + +```powershell +$path = 'docs/numerical-reviews/linear-static-3d-euler-beam-review.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @( + 'status: `pass-for-implementation-planning`', + '## Review Verdict', + '## Critical Findings', + '## Numerical Risk Assessment', + '## Consistency Checks', + '## Verification Readiness', + 'rank 6', + 'rigid', + '2-point' +) +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing numerical review evidence: $text" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. review가 formulation을 직접 수정하지 않았는지 확인한다. +3. 모든 numerical risk가 test recommendation 또는 explicit limitation으로 연결되는지 확인한다. +4. 통과 시 Step 3을 `completed`와 verdict summary로 갱신한다. 수학 revision이 필요하면 + `blocked`, 문서 생성 자체가 반복 실패하면 `error`로 기록한다. + +## 금지사항 + +- formulation 문서를 직접 편집하지 마라. 이유: 독립 review evidence를 보존해야 한다. +- C++ API/file ownership을 설계하거나 구현하지 마라. 이유: 다음 gate 책임이다. +- reference comparison 성공을 판정하지 마라. 이유: solver 결과가 아직 없다. +- Abaqus 실행과 `/reference/` 변경을 하지 마라. 이유: read-only baseline이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step4.md b/phases/linear-static-3d-euler-beam/step4.md new file mode 100644 index 0000000..ff35e5e --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step4.md @@ -0,0 +1,96 @@ +# Step 4: I/O Contract + +## 담당 역할과 필수 스킬 + +- 담당 역할: `io-definition-agent` +- 필수 스킬: `fesa-io-contract` +- 스킬을 끝까지 읽고 semantic contract만 정의하라. C++ API는 다음 gate가 담당한다. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/io-definitions/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` +- `/reference/cantilever beam/cantilever beam.inp` +- `/reference/cantilever beam/cantilever beam displacements.csv` +- `/reference/cantilever beam/cantilever beam reactions.csv` +- `/reference/cantilever beam/cantilever beam elemental forces.csv` + +## 작업 + +`docs/io-definitions/linear-static-3d-euler-beam-io.md`를 생성하라. Metadata status는 +`ready-for-implementation-planning`으로 둔다. + +- 지원 keyword별 위치, parameter, data grammar, case policy, source-location 보존, + duplicate/dangling reference validation을 표로 정의한다. +- `*PART/*ASSEMBLY/*INSTANCE` nesting grammar, 여러 identity instance, stable + `SourceEntityId`, assembly set의 `INSTANCE` parameter를 정의한다. +- B33 acceptance, B31 rejection, transform/nested assembly/multiple-step rejection code를 + 포함한다. +- `*STEP`의 `NLGEOM`은 absent 또는 `NO`만 허용하고 `YES`는 거부한다. `*STATIC`의 승인 + legacy data `initial increment, time period, minimum increment, maximum increment` 네 값을 + accept하되 V0 결과 identity는 `(Step-1, frame 0)`으로 고정한다. +- `*BOUNDARY target, first_dof, last_dof[, value]`와 + `*CLOAD target, dof, magnitude`, DOF 1..6 의미를 정확히 정의한다. +- General section의 `A,I11,I12,I22,J`, material `E,nu`, `G`, guide vector/geometry + validation과 local axis mapping을 정의한다. +- `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`, + `*OUTPUT, HISTORY`, `*NODE OUTPUT`, `*ELEMENT OUTPUT`, `*CONTACT OUTPUT` 및 그 output + variable data의 warning no-op allowlist와 unknown model-affecting keyword error를 분리한다. +- HDF5 schema v0의 exact dataset path, shape, row identity, component order, units label, + metadata, diagnostics, atomic finalization을 정의한다. +- legacy CSV header의 `U-U1/U-U2/U-U3`, `UR-UR1/UR-UR2/UR-UR3`, + `RF-RF1/RF-RF2/RF-RF3`, `RM-RM1/RM-RM2/RM-RM3`, `SF-SF1`, + `SM-SM1/SM-SM2/SM-SM3`을 canonical component로 바꾸는 규칙과 + frame/instance/node-station normalization 및 + `SF1->N`, `SM1->My`, `SM2->Mz`, `SM3->T`, interior endpoint consistency를 정의한다. +- 일반 end-action/section mapping은 `SF1->FX/N`, `SF3->FY`, `SF2->FZ`, + `SM3->MX/T`, `SM1->MY`, `SM2->MZ`로 정의한다. 승인 legacy comparison에는 CSV에 + 존재하는 `SF1/SM1/SM2/SM3`만 사용하고 `SF2/SF3`를 reference row로 만들어내지 않는다. +- component-scale tolerance와 missing/extra/nonfinite precheck를 정의한다. +- CLI syntax와 exit code `0,2,3,4,5,6`을 포함한다. + +## Acceptance Criteria + +```powershell +$path = 'docs/io-definitions/linear-static-3d-euler-beam-io.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @( + 'status: `ready-for-implementation-planning`', + '## Abaqus Input Scope', + '## Syntax Policy', + '## Model Data Mapping', + '## Output HDF5 Schema', + '## FESA HDF5 to Reference CSV Comparison Schema', + '*OUTPUT, FIELD', + 'SF1', + '/steps//frames/0/nodal/displacement', + 'absolute_floor + 1e-6 * reference_scale' +) +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing I/O contract: $text" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. 지원 keyword마다 purpose, required data, unsupported behavior가 있는지 확인한다. +3. HDF5 dataset과 reference CSV component/identity가 양방향으로 추적되는지 확인한다. +4. Step 4를 `completed`와 schema summary로 갱신한다. upstream 충돌은 `blocked`, 반복 + 생성 실패는 `error`로 기록한다. + +## 금지사항 + +- parser나 HDF5 writer를 구현하지 마라. 이유: 이 step은 I/O 계약만 소유한다. +- full Abaqus compatibility를 주장하지 마라. 이유: 승인 subset만 지원한다. +- output request가 FESA 기본 output을 끄도록 정의하지 마라. 이유: 승인 의미와 반대다. +- reference CSV를 rewrite하거나 tolerance를 변경하지 마라. 이유: 승인 baseline이다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step5.md b/phases/linear-static-3d-euler-beam/step5.md new file mode 100644 index 0000000..0e1512b --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step5.md @@ -0,0 +1,88 @@ +# Step 5: Reference Model Contract + +## 담당 역할과 필수 스킬 + +- 담당 역할: `reference-model-agent` +- 필수 스킬: `fesa-reference-models` +- 스킬을 끝까지 읽고 artifact 설계와 artifact 생성의 경계를 준수하라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/reference-models/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/research/linear-static-3d-euler-beam-research.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` +- `/reference/cantilever beam/cantilever beam.inp` +- `/reference/cantilever beam/cantilever beam displacements.csv` +- `/reference/cantilever beam/cantilever beam reactions.csv` +- `/reference/cantilever beam/cantilever beam elemental forces.csv` + +## 작업 + +`docs/reference-models/linear-static-3d-euler-beam-reference-models.md`를 생성하라. +Metadata status는 `ready-for-implementation-planning`으로 둔다. + +- code verification, analytical solution verification, B33 reference comparison을 분리한다. +- analytical inventory에 axial, torsion, local y/z bending, rotated beam, nonzero prescribed + displacement, invalid input cases를 포함하고 각 target quantity/test를 연결한다. +- 승인 reference record는 `model_id: cantilever-beam-b33`, logical schema + `abaqus-cae-report-csv-v0`, source commit `2b34d0b`, generator + `Abaqus/CAE Learning Edition 2024`, SI, `Step-1`, increment 1/time 1.0을 기록한다. +- exact legacy paths 네 개를 inventory에 기록하고 B33 element type, expected header, + unique row key, finite value artifact check를 요구한다. +- 이 legacy bundle에 한해서 `metadata.json`, `README.md`, stress CSV가 N/A이며 설계와 + 이 contract가 provenance/schema/tolerance/stress 사유를 대신 기록한다고 명시한다. +- 이후 reference model에는 canonical file names, metadata.json, README.md를 요구한다. +- displacement, reaction, section resultant coverage와 HDF5 dataset/CSV/component/tolerance를 + 연결하는 Coverage Matrix를 작성한다. Stress comparison은 N/A지만 output unit/analytical + verification을 연결한다. +- artifact 상태를 실제 파일 inventory에 따라 기록하되 reference 값을 재계산하지 않는다. + +## Acceptance Criteria + +```powershell +$path = 'docs/reference-models/linear-static-3d-euler-beam-reference-models.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$artifacts = @( + 'reference/cantilever beam/cantilever beam.inp', + 'reference/cantilever beam/cantilever beam displacements.csv', + 'reference/cantilever beam/cantilever beam reactions.csv', + 'reference/cantilever beam/cantilever beam elemental forces.csv' +) +foreach ($artifact in $artifacts) { + if (-not (Test-Path $artifact)) { throw "Missing approved artifact: $artifact" } + if (-not (Select-String -LiteralPath $path -SimpleMatch $artifact -Quiet)) { + throw "Artifact is not inventoried: $artifact" + } +} +$required = @('status: `ready-for-implementation-planning`', 'cantilever-beam-b33', + '2b34d0b', 'abaqus-cae-report-csv-v0', 'stress', 'N/A', '## Coverage Matrix') +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing reference contract: $text" + } +} +git diff --check -- $path +git diff --exit-code -- reference/ +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. 네 legacy artifact가 exact path로만 참조되고 rename 제안이 없는지 확인한다. +3. 모든 must requirement가 model/test/quantity 또는 명시적 N/A에 연결되는지 확인한다. +4. Step 5를 `completed`와 inventory summary로 갱신한다. artifact 필수 조건 불충족은 + 승인된 legacy 예외를 먼저 적용한 뒤 실제 결함만 `blocked`로 기록한다. + +## 금지사항 + +- Abaqus나 다른 reference solver를 실행하지 마라. 이유: 이 step은 계약만 준비한다. +- `/reference/` 아래 어떤 파일도 생성·수정·rename하지 마라. 이유: baseline은 read-only다. +- legacy bundle에 metadata/README/stress CSV를 요구해 차단하지 마라. 이유: 승인된 예외다. +- reference comparison을 수행하거나 pass를 선언하지 마라. 이유: solver result가 아직 없다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step6.md b/phases/linear-static-3d-euler-beam/step6.md new file mode 100644 index 0000000..60c1355 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step6.md @@ -0,0 +1,97 @@ +# Step 6: Implementation Plan + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-planning-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 스킬의 planning workflow를 끝까지 읽고 코드나 테스트를 작성하지 않은 채 계획만 작성하라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/SOLVER_AGENT_DESIGN.md` +- `/docs/implementation-plans/README.md` +- `/docs/build-test-reports/README.md` +- `/docs/corrections/README.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/research/linear-static-3d-euler-beam-research.md` +- `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` +- `/docs/numerical-reviews/linear-static-3d-euler-beam-review.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` +- `/phases/linear-static-3d-euler-beam/step7.md`부터 `/step24.md`까지 + +## 작업 + +`docs/implementation-plans/linear-static-3d-euler-beam.md`를 생성하라. 승인 설계가 이 +경로를 명시하므로 README의 기본 suffix보다 이 경로를 우선한다. + +- Metadata와 Readiness Check를 작성하고 upstream status가 모두 준비된 경우 + `status: ready-for-implementation`을 사용한다. +- Implementation Scope와 Non-goals를 승인 설계와 동일하게 기록한다. +- Step 7–24 각각을 독립 Work Breakdown task로 매핑하고 exact candidate source/header, + test, CMake file을 제시한다. 한 file은 한 책임을 가져야 한다. +- 각 task에 consumes/produces signature를 정의한다. 특히 `Vector`, row-major `Matrix`, + CSR `SparseMatrix`, `Domain`, `AnalysisModel`, `DofManager`, `AnalysisState`, + `EulerBeam3D`, `ParallelFor`, `LinearSolver`, `ResultsWriter`, orchestration API를 일관되게 쓴다. +- 각 production task에 GoogleTest test ID, RED condition, GREEN condition, targeted CTest + regex, full VERIFY command를 연결한다. +- parser negative cases, beam invariants/analytical cases, deterministic CSR, nonzero + prescribed displacement, PARDISO repeated RHS/singular diagnostics, HDF5 atomicity, + CLI/reference integration을 빠짐없이 배치한다. +- Requirement-to-task/test/reference Acceptance Traceability Matrix와 implementation report + evidence 형식을 포함한다. +- Step 24에서 test-only reference comparison executable/test를 완성해 Step 26이 source/test + 변경 없이 다시 실행하고 report를 작성할 수 있게 계획한다. +- reference artifact, upstream contract, tolerance를 변경하는 correction을 금지한다. + +## Acceptance Criteria + +```powershell +$path = 'docs/implementation-plans/linear-static-3d-euler-beam.md' +if (-not (Test-Path $path)) { throw "Missing $path" } +$required = @( + 'status: `ready-for-implementation`', + '## Readiness Check', + '## Work Breakdown', + '## TDD Test Plan', + '## CMake and CTest Plan', + '## Acceptance Traceability Matrix', + 'cmake -S . -B .harness/build -A x64', + 'ctest --test-dir .harness/build -C Debug --output-on-failure', + 'reference/cantilever beam/' +) +foreach ($text in $required) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $text -Quiet)) { + throw "Missing implementation-plan contract: $text" + } +} +$modules = @('cmake-test-foundation','core-diagnostics','dense-math-adapters','domain-model', + 'inp-syntax-parser','inp-domain-mapping','analysis-model','dof-manager','analysis-state', + 'euler-beam-element','parallel-for-tbb','sparse-assembly','essential-constraints', + 'mkl-pardiso-solver','load-assembly','result-recovery','hdf5-results-writer','linear-static-cli') +foreach ($module in $modules) { + if (-not (Select-String -LiteralPath $path -SimpleMatch $module -Quiet)) { + throw "Missing work-breakdown module: $module" + } +} +git diff --check -- $path +``` + +## 검증 절차 + +1. Acceptance Criteria 명령을 실행한다. +2. 모든 must requirement가 최소 한 task와 test에 연결되는지 확인한다. +3. later task가 사용하는 type/signature가 earlier task 정의와 정확히 같은지 대조한다. +4. 각 production task에 RED/GREEN/VERIFY command가 있고 reference step이 read-only인지 확인한다. +5. Step 6을 `completed`와 plan readiness summary로 갱신한다. upstream gate 미통과는 + `blocked`, 반복 작성 실패는 `error`로 기록한다. + +## 금지사항 + +- C++ source, test, CMake를 작성하거나 실행하지 마라. 이유: 이 step은 계획만 소유한다. +- upstream 요구조건·정식화·I/O·tolerance를 바꾸지 마라. 이유: 이미 승인된 계약이다. +- reference artifact를 생성·수정하지 마라. 이유: read-only baseline이다. +- API를 승인 문서와 모순되게 확정하지 마라. 이유: downstream task 간 계약이 깨진다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step7.md b/phases/linear-static-3d-euler-beam/step7.md new file mode 100644 index 0000000..8760372 --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step7.md @@ -0,0 +1,103 @@ +# Step 7: CMake and GoogleTest Foundation + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` +- 구현 전에 스킬과 Step 6 implementation plan을 끝까지 읽어라. + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/docs/superpowers/specs/2026-08-08-linear-static-3d-euler-beam-design.md` +- `/docs/HARNESS_WORKFLOW.md` +- `/docs/HARNESS.md` +- `/CMakeLists.txt`가 이미 생겼다면 그 파일 + +## 소유 파일 + +- Create: `/CMakeLists.txt` +- Create: `/cmake/FesaDependencies.cmake` +- Create: `/include/fesa/build_info.hpp` +- Create: `/src/fesa/build_info.cpp` +- Create: `/src/fesa/CMakeLists.txt` +- Create: `/tests/CMakeLists.txt` +- Create: `/tests/unit/build_info_test.cpp` +- Create: `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md` + +## 작업 + +MSVC x64 Debug에서 이후 모든 C++ step을 TDD로 실행할 최소 build/test foundation을 +구현하라. Step 6이 정한 exact file layout을 우선하되 최소 책임은 다음과 같다. + +- `CMakeLists.txt`: C++17, `enable_testing()`, FESA target 구성과 하위 CMake 진입점. +- `cmake/FesaDependencies.cmake`: cache variable `FESA_GTEST_SOURCE_DIR`을 검증하고 + `C:/git/googletest`를 source tree로 받을 수 있게 한다. 이 절대경로를 default나 + production source에 하드코딩하지 않는다. oneMKL, oneTBB, HDF5 CONFIG package를 찾고 + dependency target 차이는 이 파일 안에서 정규화한다. +- `include/fesa/build_info.hpp`, `src/fesa/build_info.cpp`: HDF5 metadata가 재사용할 + `std::string_view solverVersion() noexcept`의 최소 안정 API. +- `src/fesa/CMakeLists.txt`: `fesa_solver` static library와 FESA에만 `/W4 /WX` 적용. +- `tests/CMakeLists.txt`, `tests/unit/build_info_test.cpp`: GoogleTest 연결, + `gtest_discover_tests`, `BuildInfo` regex와 공통 `linear-static-3d-euler-beam` label을 가진 + 최소 제품 test. 이후 이 phase의 모든 CTest는 같은 공통 label을 상속한다. +- `docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`: + feature metadata, dependency/configure evidence와 Step 7–24별 RED/GREEN/VERIFY command, + exit code, 핵심 output, 변경 파일, requirement/test trace를 누적할 implementation report. + +GoogleTest external target에는 `/W4 /WX`를 전파하지 않는다. MKL/TBB/HDF5 header나 type을 +`build_info.hpp` 또는 다른 public header에 노출하지 않는다. 외부 checkout을 수정하거나 +network fetch를 하지 않는다. + +## Acceptance Criteria + +먼저 `C:/git/googletest`의 revision을 read-only로 확인하라. + +```powershell +if (-not (Test-Path 'C:/git/googletest/CMakeLists.txt')) { throw 'GoogleTest checkout is missing' } +$gtestRevision = git -C C:/git/googletest rev-parse HEAD +if ($gtestRevision -ne '04ee1b4f2aefdffb0135d7cf2a2c519fe50dabe4') { + throw "Unexpected GoogleTest revision: $gtestRevision" +} +``` + +구성·build·discovery·test를 실행한다. + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R BuildInfo --output-on-failure +$discovery = ctest --test-dir .harness/build -C Debug --show-only=json-v1 | ConvertFrom-Json +if ($discovery.tests.Count -lt 1) { throw 'CTest discovered zero tests' } +ctest --test-dir .harness/build -C Debug --output-on-failure +if (-not (Test-Path 'docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md')) { + throw 'Missing implementation evidence report' +} +``` + +## 검증 절차 + +1. build_info test를 먼저 작성하고 API가 없어 compile RED가 발생하는지 확인한 뒤 + `build_info` production 파일을 추가한다. +2. 위 명령을 실행해 GREEN과 전체 VERIFY를 확인한다. +3. MSVC compiler metadata와 FESA target `/W4 /WX`, third-party warning 격리를 확인한다. +4. implementation report에 Step 7 RED/GREEN/VERIFY의 실제 command, exit code와 핵심 + output을 기록한다. +5. Step 7을 `completed`로 바꾸고 build files, target names, dependency resolution을 + `summary`에 기록한다. 설치 경로/환경이 실제로 없으면 `blocked`, 반복 구현 실패는 + `error`로 기록한다. + +## 금지사항 + +- dependency source를 vendor하거나 download하지 마라. 이유: 승인된 local install을 사용한다. +- GoogleTest 절대경로를 CMake default로 하드코딩하지 마라. 이유: cache variable 계약이다. +- FESA warning option을 third-party target에 적용하지 마라. 이유: 외부 코드 경고는 제품 책임이 아니다. +- 이후 solver module을 미리 만들지 마라. 이유: 이 step은 build/test foundation만 소유한다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step8.md b/phases/linear-static-3d-euler-beam/step8.md new file mode 100644 index 0000000..a24cdbd --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step8.md @@ -0,0 +1,109 @@ +# Step 8: Core Diagnostics + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/io-definitions/linear-static-3d-euler-beam-io.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/build_info.hpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` + +## 소유 파일 + +- Create: `/include/fesa/core/source_identity.hpp` +- Create: `/include/fesa/core/diagnostic.hpp` +- Create: `/include/fesa/core/status.hpp` +- Create: `/src/fesa/core/diagnostic.cpp` +- Create: `/src/fesa/core/status.cpp` +- Create: `/tests/unit/core/source_identity_test.cpp` +- Create: `/tests/unit/core/diagnostic_test.cpp` +- Create: `/tests/unit/core/status_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +Step 6의 file plan을 따르며 core ID, source location, diagnostic, status/result type만 구현하라. +최소 public 계약은 아래 의미를 제공해야 한다. + +```cpp +struct SourceLocation { std::filesystem::path file; std::size_t line; }; +struct SourceEntityId { std::string instanceName; std::int64_t sourceLabel; }; +enum class Severity { warning, error }; +struct Diagnostic { + Severity severity; + std::string code; + SourceLocation location; + std::string keyword; + std::string entityIdentity; + std::string message; +}; +class Status { +public: + static Status ok(); + static Status failure(std::vector diagnostics); + bool isOk() const noexcept; + const std::vector& diagnostics() const noexcept; +}; +template class Result; +``` + +`Result`는 성공 value 또는 실패 `Status`를 소유하고 실패 value access를 거부한다. +Diagnostic ordering helper는 file, line, keyword, entity identity, code 순으로 stable하게 +정렬한다. `core` public header는 MKL/TBB/HDF5에 의존하지 않는다. + +위 exact 파일을 생성하고 각 production stem에 대응하는 test를 먼저 작성하라. +Test suite label/regex는 +`CoreDiagnostics`로 식별 가능해야 한다. + +## Acceptance Criteria + +RED에서는 production 파일을 만들기 전에 다음 targeted command가 missing header/symbol로 +실패하는 것을 확인하고 구현 report 또는 step summary용 evidence를 남긴다. + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R CoreDiagnostics --output-on-failure +``` + +구현 후 GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R CoreDiagnostics --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +``` + +Tests는 value/error exclusivity, move/copy, failed access, exact diagnostic fields와 +deterministic ordering을 검증해야 한다. + +## 검증 절차 + +1. GoogleTest를 먼저 추가하고 targeted RED를 관찰한다. +2. 최소 production 구현으로 targeted GREEN을 만든다. +3. 전체 MSVC x64 Debug build/CTest VERIFY를 실행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 8 section에 실제 RED/GREEN/VERIFY command, exit code, 핵심 output과 변경 파일을 기록한다. +5. public header dependency를 검토하고 Step 8에 `completed`와 RED/GREEN/VERIFY 요약을 기록한다. + +## 금지사항 + +- parser-specific keyword policy를 core에 넣지 마라. 이유: layer dependency를 역전시킨다. +- exception text에 backend-specific detail을 노출하지 마라. 이유: structured diagnostic이 계약이다. +- 기존 build/test 동작을 재구성하지 마라. 이유: Step 7 범위다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다. diff --git a/phases/linear-static-3d-euler-beam/step9.md b/phases/linear-static-3d-euler-beam/step9.md new file mode 100644 index 0000000..be18e8b --- /dev/null +++ b/phases/linear-static-3d-euler-beam/step9.md @@ -0,0 +1,113 @@ +# Step 9: Dense Math Adapters + +## 담당 역할과 필수 스킬 + +- 담당 역할: `implementation-agent` +- 필수 스킬: `fesa-cpp-msvc-tdd` + +## 읽어야 할 파일 + +- `/AGENTS.md` +- `/docs/ARCHITECTURE.md` +- `/docs/ADR.md` +- `/docs/requirements/linear-static-3d-euler-beam.md` +- `/docs/implementation-plans/linear-static-3d-euler-beam.md` +- `/include/fesa/core/status.hpp` +- `/src/fesa/CMakeLists.txt` +- `/tests/CMakeLists.txt` + +## 소유 파일 + +- Create: `/include/fesa/math/vector.hpp` +- Create: `/include/fesa/math/matrix.hpp` +- Create: `/src/fesa/math/vector.cpp` +- Create: `/src/fesa/math/matrix.cpp` +- Create: `/tests/unit/math/vector_test.cpp` +- Create: `/tests/unit/math/matrix_test.cpp` +- Modify: `/src/fesa/CMakeLists.txt` +- Modify: `/tests/CMakeLists.txt` + +## 작업 + +연속 `double` storage를 소유하는 `Vector`와 row-major `Matrix`를 위 exact paths에 +구현하라. Public 의미는 다음과 같아야 한다. + +```cpp +class Vector { +public: + explicit Vector(std::size_t size, double value = 0.0); + std::size_t size() const noexcept; + double* data() noexcept; + const double* data() const noexcept; + double& operator[](std::size_t index); + const double& operator[](std::size_t index) const; + double dot(const Vector& rhs) const; + double norm() const; + void scale(double alpha); + void axpy(double alpha, const Vector& x); +}; + +class Matrix { +public: + Matrix(std::size_t rows, std::size_t columns, double value = 0.0); + std::size_t rows() const noexcept; + std::size_t columns() const noexcept; + double& operator()(std::size_t row, std::size_t column); + const double& operator()(std::size_t row, std::size_t column) const; + Vector multiply(const Vector& rhs) const; + Matrix multiply(const Matrix& rhs) const; +}; +``` + +copy/move semantics를 검증하고 모든 index access는 bounds-checked여야 한다. dimension +mismatch는 `std::invalid_argument`, bounds 위반은 `std::out_of_range`로 일관되게 처리한다. +copy, dot, Euclidean norm, scale, axpy, GEMV, GEMM은 `.cpp` 내부 MKL CBLAS adapter를 +사용한다. `mkl.h`, `MKL_INT`, `CBLAS_*`가 public header에 나타나면 안 된다. + +Tests는 zero-size policy, ownership/deep-copy, move safety, bounds, mismatch, non-square +row-major GEMV/GEMM과 known BLAS values를 검증하고 `DenseMath` regex로 실행 가능하게 한다. + +## Acceptance Criteria + +RED targeted command: + +```powershell +cmake --build .harness/build --config Debug --target fesa_tests +ctest --test-dir .harness/build -C Debug -R DenseMath --output-on-failure +``` + +GREEN/VERIFY: + +```powershell +cmake -S . -B .harness/build -A x64 ` + -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` + "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` + "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` + "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" +cmake --build .harness/build --config Debug +ctest --test-dir .harness/build -C Debug -R DenseMath --output-on-failure +ctest --test-dir .harness/build -C Debug --show-only=json-v1 +ctest --test-dir .harness/build -C Debug --output-on-failure +$leaks = rg -n "mkl\.h|MKL_INT|CBLAS_" include/fesa +if ($LASTEXITCODE -eq 0) { throw "MKL API leaked into public headers:`n$leaks" } +if ($LASTEXITCODE -ne 1) { throw 'Public-header dependency scan failed' } +``` + +마지막 `rg`는 no-match여야 한다. + +## 검증 절차 + +1. `vector_test.cpp`, `matrix_test.cpp`를 먼저 작성하고 missing behavior RED를 확인한다. +2. 최소 adapter/ownership 구현으로 GREEN을 만든다. +3. 전체 MSVC x64 Debug VERIFY와 public-header dependency scan을 실행한다. +4. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 + Step 9 section에 실제 RED/GREEN/VERIFY command, exit code, + 핵심 output과 변경 파일을 기록한다. +5. Step 9를 `completed`로 바꾸고 operations/test evidence를 summary에 기록한다. + +## 금지사항 + +- `Matrix`를 sparse storage로 재사용하지 마라. 이유: CSR은 별도 타입이다. +- MKL type/header를 public API에 노출하지 마라. 이유: adapter boundary 계약이다. +- expression template이나 lazy evaluation을 추가하지 마라. 이유: 승인되지 않은 일반화다. +- 직접 commit하지 마라. 이유: Harness executor가 담당한다.