docs: add linear static beam harness phase
This commit is contained in:
@@ -19,7 +19,8 @@
|
|||||||
- 문서와 구현은 full Abaqus compatibility를 주장하지 않는다. 기능별로 승인된 Abaqus keyword subset만 지원한다.
|
- 문서와 구현은 full Abaqus compatibility를 주장하지 않는다. 기능별로 승인된 Abaqus keyword subset만 지원한다.
|
||||||
- 공식 solver output은 HDF5 `results.h5`이다.
|
- 공식 solver output은 HDF5 `results.h5`이다.
|
||||||
- reference 결과는 FESA와 같은 Abaqus `.inp` 모델을 Abaqus로 해석해 생성한 CSV 파일이다.
|
- reference 결과는 FESA와 같은 Abaqus `.inp` 모델을 Abaqus로 해석해 생성한 CSV 파일이다.
|
||||||
- reference comparison은 FESA `results.h5`의 변위, 반력, 내력, 응력 dataset을 `reference/<model-id>/<model-id>_*.csv` 파일과 비교한다.
|
- reference artifact의 정확한 경로와 파일명은 기능별 reference model contract를 따른다. 신규 모델은 `reference/<model-id>/<model-id>_*.csv` canonical 이름을 사용한다.
|
||||||
|
- 승인된 B33 baseline은 예외적으로 `reference/cantilever beam/`의 기존 space-containing 파일명을 read-only legacy alias로 사용한다.
|
||||||
- CSV는 FESA 공식 output이 아니며, FESA HDF5에서 추출한 deterministic CSV view는 비교 디버깅/검토용 보조 artifact로만 둔다.
|
- CSV는 FESA 공식 output이 아니며, FESA HDF5에서 추출한 deterministic CSV view는 비교 디버깅/검토용 보조 artifact로만 둔다.
|
||||||
|
|
||||||
## 아키텍처 규칙
|
## 아키텍처 규칙
|
||||||
@@ -43,6 +44,15 @@
|
|||||||
- Stop은 `.harness/config.json` 또는 자동 감지 결과에 따라 MSVC build와 test를 모두 검증한다.
|
- Stop은 `.harness/config.json` 또는 자동 감지 결과에 따라 MSVC build와 test를 모두 검증한다.
|
||||||
- Generated phase execution outputs remain ignored under `phases/**/step*-output.json`.
|
- 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` 순서를 따른다.
|
- TDD를 기본으로 한다. 구현은 `RED -> GREEN -> VERIFY` 순서를 따른다.
|
||||||
- CRITICAL: 빌드 경고를 새로 추가하지 말 것.
|
- CRITICAL: 빌드 경고를 새로 추가하지 말 것.
|
||||||
|
|||||||
+23
-7
@@ -34,23 +34,23 @@ FESA의 architecture decision은 solver correctness, verification traceability,
|
|||||||
**트레이드오프**: 초기 class 수가 늘어난다. Phase 1에서는 interface를 얇게 유지하고 displacement 중심 state부터 구현한다.
|
**트레이드오프**: 초기 class 수가 늘어난다. Phase 1에서는 interface를 얇게 유지하고 displacement 중심 state부터 구현한다.
|
||||||
|
|
||||||
### ADR-005: 공식 결과 파일은 HDF5로 하고 reference 결과는 Abaqus CSV로 둔다
|
### ADR-005: 공식 결과 파일은 HDF5로 하고 reference 결과는 Abaqus CSV로 둔다
|
||||||
**결정**: FESA solver의 authoritative result output은 `results.h5` HDF5이다. Abaqus reference results는 `reference/<model-id>/` 아래 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/<model-id>/` 아래 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를 안정적으로 표현한다.
|
**이유**: 구조해석 결과는 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로 취급하지 않는다.
|
**트레이드오프**: 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 경계 뒤에 둔다
|
### 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가 어려워진다.
|
**이유**: 선형 정적, 비선형 정적, 동적, 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로 고정한다
|
### 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만 둔다.
|
**트레이드오프**: 특수 해석 절차가 공통 흐름에 맞지 않는 경우 hook point가 필요하다. 초기에는 선형 정적 해석을 기준으로 최소 hook만 둔다.
|
||||||
|
|
||||||
@@ -69,11 +69,11 @@ FESA의 architecture decision은 solver correctness, verification traceability,
|
|||||||
**트레이드오프**: 초기 병렬화 범위가 제한된다. MKL 내부 thread와 TBB task arena의 oversubscription 정책을 별도로 문서화해야 한다.
|
**트레이드오프**: 초기 병렬화 범위가 제한된다. MKL 내부 thread와 TBB task arena의 oversubscription 정책을 별도로 문서화해야 한다.
|
||||||
|
|
||||||
### ADR-010: Abaqus reference artifact는 사람이 생성하거나 명시 승인된 절차로만 갱신한다
|
### 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 결과는 solver correctness의 기준이다. 생성 절차가 불명확하면 구현 결함과 reference artifact 오류를 구분할 수 없다.
|
||||||
|
|
||||||
**트레이드오프**: reference 준비가 느려질 수 있다. 대신 검증 기준의 신뢰도와 감사 가능성이 높아진다.
|
**트레이드오프**: reference 준비가 느려질 수 있다. Legacy 예외는 일반 artifact 규칙을 복잡하게 하지만 exact path와 source commit을 고정하고 read-only로 취급해 감사 가능성을 유지한다.
|
||||||
|
|
||||||
### ADR-011: 구형 단일 검증 진입점 계약을 폐기한다
|
### ADR-011: 구형 단일 검증 진입점 계약을 폐기한다
|
||||||
|
|
||||||
@@ -88,3 +88,19 @@ FESA의 architecture decision은 solver correctness, verification traceability,
|
|||||||
**이유**: 테스트 파일 존재 검사, TDD 실행 증거, 전체 build/test는 서로 다른 책임이다. 이를 분리하면 Hook이 보장하는 범위를 과장하지 않으면서 Step 종료 시 green 상태를 강제할 수 있다.
|
**이유**: 테스트 파일 존재 검사, TDD 실행 증거, 전체 build/test는 서로 다른 책임이다. 이를 분리하면 Hook이 보장하는 범위를 과장하지 않으면서 Step 종료 시 green 상태를 강제할 수 있다.
|
||||||
|
|
||||||
**트레이드오프**: PreToolUse만으로 구현 전 RED 실행을 증명할 수 없으므로 Implementation report에 RED/GREEN 명령과 결과를 기록해야 한다. C/C++가 없는 저장소는 Stop이 통과하므로 Harness Python 검증은 별도 acceptance command로 유지한다.
|
**트레이드오프**: 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 전에 실패시킨다.
|
||||||
|
|||||||
+142
-27
@@ -11,6 +11,12 @@ FESA의 아키텍처 목표는 Abaqus `.inp` subset을 내부 semantic model로
|
|||||||
- incremental feature addition
|
- incremental feature addition
|
||||||
- Harness 기반 TDD
|
- 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
|
```text
|
||||||
src/
|
src/
|
||||||
@@ -31,9 +37,7 @@ src/
|
|||||||
analysis/ # static, modal, dynamic, nonlinear procedure drivers
|
analysis/ # static, modal, dynamic, nonlinear procedure drivers
|
||||||
results/ # recovery, field/history output, diagnostics
|
results/ # recovery, field/history output, diagnostics
|
||||||
validation/ # comparison metrics and tolerance helpers
|
validation/ # comparison metrics and tolerance helpers
|
||||||
math/
|
math/ # owning Vector, row-major Matrix, CSR SparseMatrix adapters
|
||||||
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
|
|
||||||
tests/
|
tests/
|
||||||
unit/
|
unit/
|
||||||
integration/
|
integration/
|
||||||
@@ -83,6 +87,57 @@ Runner는 `git add -A`를 사용하므로 clean worktree 또는 별도 Git workt
|
|||||||
- `results`는 HDF5 schema를 통해 nodal, element, integration-point, diagnostic output을 분리한다.
|
- `results`는 HDF5 schema를 통해 nodal, element, integration-point, diagnostic output을 분리한다.
|
||||||
- test helper는 production parser/solver 내부 상태를 우회하지 않는다.
|
- 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
|
```text
|
||||||
Domain
|
Domain
|
||||||
@@ -159,8 +214,14 @@ Results
|
|||||||
|
|
||||||
Vector
|
Vector
|
||||||
Matrix
|
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`은 입력 파일에서 만들어진 전체 모델 정의를 소유한다. 파싱 이후에는 가능한 한 불변으로 취급한다.
|
- `Domain`은 입력 파일에서 만들어진 전체 모델 정의를 소유한다. 파싱 이후에는 가능한 한 불변으로 취급한다.
|
||||||
- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않고 참조 또는 id 기반 view로 구성한다.
|
- `AnalysisModel`은 현재 step에서 활성화되는 해석 객체들의 실행 view이다. `Domain`을 복사하지 않고 참조 또는 id 기반 view로 구성한다.
|
||||||
@@ -171,37 +232,46 @@ Matrix
|
|||||||
## 데이터 흐름
|
## 데이터 흐름
|
||||||
```text
|
```text
|
||||||
Abaqus input file
|
Abaqus input file
|
||||||
-> InputParser
|
-> syntax parse and semantic mapping
|
||||||
-> Domain 생성
|
-> immutable Domain 생성
|
||||||
-> StepDefinition 루프
|
-> 단일 step AnalysisModel view 생성
|
||||||
-> AnalysisModel 생성
|
-> DofManager DOF/scatter map/sparse pattern 생성
|
||||||
-> DofManager로 자유도/방정식 번호 생성
|
-> element stiffness 계산과 deterministic COO-to-CSR 조립
|
||||||
-> sparse pattern 생성
|
-> free/constrained partition 생성
|
||||||
-> Analysis 실행
|
-> LinearSolver::factorize(Kff)
|
||||||
-> Assembler로 전역 행렬/벡터 조립
|
-> full nodal load vector 조립
|
||||||
-> BoundaryCondition 적용
|
-> effective RHS = Ff - Kfc * dc
|
||||||
-> LinearSolver 또는 nonlinear/time integration loop
|
-> LinearSolver::solve(rhs, df) substitution
|
||||||
-> AnalysisState 갱신
|
-> full displacement 복구
|
||||||
-> ResultsWriter로 step/frame/history 저장
|
-> reaction = K*d - F 및 element result 복구
|
||||||
-> 다음 step 진행
|
-> ResultsWriter로 results.h5 atomic finalization
|
||||||
```
|
```
|
||||||
|
|
||||||
|
강성행렬 factorization은 하중벡터 조립보다 먼저 수행한다. 반력은 element end action의
|
||||||
|
별도 합이 아니라 조립된 전체 residual에서 구한다.
|
||||||
|
|
||||||
## 해석 실행 흐름
|
## 해석 실행 흐름
|
||||||
`Analysis::run()`은 Template Method로 다음 큰 흐름을 고정한다. 해석 종류별 class는 필요한 단계만 재정의한다.
|
`Analysis::run()`은 Template Method로 다음 V0 흐름을 고정한다. 해석 종류별 class는
|
||||||
|
승인된 procedure contract 안에서 필요한 단계만 재정의한다.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
initialize
|
initialize
|
||||||
buildAnalysisModel
|
buildAnalysisModel
|
||||||
buildDofMap
|
buildDofMap
|
||||||
buildSparsePattern
|
buildSparsePattern
|
||||||
assemble
|
assembleStiffness
|
||||||
applyBoundaryConditions
|
partitionConstraints
|
||||||
solve
|
factorize
|
||||||
updateState
|
assembleLoads
|
||||||
|
formEffectiveRhs
|
||||||
|
substitute
|
||||||
|
reconstructDisplacement
|
||||||
|
recoverResults
|
||||||
writeResults
|
writeResults
|
||||||
```
|
```
|
||||||
|
|
||||||
비선형 정적해석은 이 흐름을 Newton-Raphson 반복 루프 안에서 사용하고, 동적해석은 time step/frame 루프 안에서 사용한다.
|
비선형 정적 및 동적 해석은 V0 범위가 아니며 별도 ADR과 formulation을 승인한 뒤 이
|
||||||
|
lifecycle의 확장 지점을 사용한다.
|
||||||
|
|
||||||
## 설계 패턴
|
## 설계 패턴
|
||||||
- Strategy Pattern: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`를 교체 가능한 전략으로 둔다.
|
- Strategy Pattern: `Analysis`, `LinearSolver`, `TimeIntegrator`, `ConvergenceCriteria`를 교체 가능한 전략으로 둔다.
|
||||||
@@ -213,10 +283,21 @@ writeResults
|
|||||||
|
|
||||||
## Sparse Matrix Policy
|
## Sparse Matrix Policy
|
||||||
- assembly는 초기에는 COO triplet 수집 후 CSR finalize를 기준으로 한다.
|
- 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으로 남긴다.
|
- matrix symmetry, definiteness, singularity diagnostic을 구조화된 diagnostic으로 남긴다.
|
||||||
- deterministic assembly를 위해 TBB element loop는 thread-local contribution buffer 또는 two-pass sparse assembly를 사용한다.
|
- 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
|
## Parallel Policy
|
||||||
- 첫 번째 oneTBB 적용 지점은 element-local matrix/residual 계산이다.
|
- 첫 번째 oneTBB 적용 지점은 element-local matrix/residual 계산이다.
|
||||||
- 전역 sparse write는 thread-local buffer 또는 deterministic reduction으로 제한한다.
|
- 전역 sparse write는 thread-local buffer 또는 deterministic reduction으로 제한한다.
|
||||||
@@ -227,10 +308,12 @@ writeResults
|
|||||||
/metadata
|
/metadata
|
||||||
/model/nodes
|
/model/nodes
|
||||||
/model/elements
|
/model/elements
|
||||||
/steps/<step-name>/frames/<frame-id>/nodal/displacement
|
/steps/<step-name>/frames/0/nodal/displacement
|
||||||
/steps/<step-name>/frames/<frame-id>/nodal/reaction
|
/steps/<step-name>/frames/0/nodal/reaction
|
||||||
/steps/<step-name>/frames/<frame-id>/element/stress
|
/steps/<step-name>/frames/0/element/end_force_local
|
||||||
/steps/<step-name>/frames/<frame-id>/element/strain
|
/steps/<step-name>/frames/0/element/section_resultant
|
||||||
|
/steps/<step-name>/frames/0/element/generalized_strain
|
||||||
|
/steps/<step-name>/frames/0/element/stress_s11
|
||||||
/diagnostics
|
/diagnostics
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -242,3 +325,35 @@ Schema requirements:
|
|||||||
- Abaqus reference results는 `reference/<model-id>/` 아래 CSV 파일이다.
|
- Abaqus reference results는 `reference/<model-id>/` 아래 CSV 파일이다.
|
||||||
- Verification은 documented IDs, components, units, coordinate system, step/frame identity, tolerance 기준으로 FESA HDF5 rows와 Abaqus reference CSV rows를 비교한다.
|
- 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가 아니다.
|
- 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 <model.inp> --output <results.h5>
|
||||||
|
```
|
||||||
|
|
||||||
|
`--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한 순서로 출력한다.
|
||||||
|
|||||||
+53
-19
@@ -18,31 +18,46 @@ FESA는 Abaqus `.inp` keyword subset을 입력으로 받아 유한요소법 기
|
|||||||
4. 요소, 재료, 경계조건, 하중의 runtime-polymorphic base interface
|
4. 요소, 재료, 경계조건, 하중의 runtime-polymorphic base interface
|
||||||
5. sparse matrix pattern 생성, 전역 행렬/벡터 조립, 제약조건 적용
|
5. sparse matrix pattern 생성, 전역 행렬/벡터 조립, 제약조건 적용
|
||||||
6. `LinearSolver` adapter를 통한 MKL PARDISO backend와 향후 iterative solver 확장
|
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/<model-id>/` 아래 Abaqus reference CSV rows의 직접 비교
|
8. FESA HDF5 rows와 `reference/<model-id>/` 아래 Abaqus reference CSV rows의 직접 비교
|
||||||
9. CMake/MSVC/x64/Debug, CTest 기반 개발 검증
|
9. CMake/MSVC/x64/Debug, CTest 기반 개발 검증
|
||||||
|
|
||||||
## V0 범위
|
## 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:
|
- 최소 Abaqus keyword subset:
|
||||||
- `*HEADING`
|
- `*HEADING`
|
||||||
- `*NODE`
|
- `*PART`, `*END PART`
|
||||||
- `*ELEMENT`
|
- `*NODE`, `*ELEMENT, TYPE=B33`
|
||||||
- `*NSET`
|
- `*NSET`, `*ELSET`, including `GENERATE`
|
||||||
- `*ELSET`
|
|
||||||
- `*MATERIAL`
|
- `*MATERIAL`
|
||||||
- `*ELASTIC`
|
- `*ELASTIC`
|
||||||
- `*Beam General Section`
|
- `*BEAM GENERAL SECTION, SECTION=GENERAL`
|
||||||
|
- `*SECTION POINTS`
|
||||||
|
- `*ASSEMBLY`, `*END ASSEMBLY`
|
||||||
|
- `*INSTANCE`, `*END INSTANCE`
|
||||||
- `*BOUNDARY`
|
- `*BOUNDARY`
|
||||||
- `*CLOAD`
|
- `*CLOAD`
|
||||||
- `*STEP`
|
- `*STEP`, `*STATIC`, `*END STEP`
|
||||||
- `*STATIC`
|
- `*PREPRINT`, `*RESTART`, `*TRANSVERSE SHEAR STIFFNESS`, `*OUTPUT, FIELD`,
|
||||||
- output request subset
|
`*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
|
- 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
|
- HDF5 result schema v0
|
||||||
- FESA HDF5 to Abaqus reference CSV comparison 계약
|
- `fesa.exe <model.inp> --output <results.h5>` CLI
|
||||||
|
- 승인된 `reference/cantilever beam/` B33 결과와 displacement, reaction, section resultant
|
||||||
|
comparison; beam stress reference comparison은 N/A
|
||||||
|
|
||||||
## 기능 요구조건
|
## 기능 요구조건
|
||||||
| ID | 요구조건 | Acceptance Criteria | Verification Method |
|
| 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-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-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-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-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`로 저장해야 한다. | step/frame, field/history, metadata, diagnostics가 schema version과 함께 저장된다. | HDF5 schema 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, internal force, stress 등 검증 물리량의 row identity와 tolerance source가 명확하다. | reference comparison report |
|
| 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-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-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-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를 검증한다.
|
- MSVC x64 Debug 환경에서 configure, build, CTest를 검증한다.
|
||||||
- reference test 결과는 deterministic해야 한다.
|
- reference test 결과는 deterministic해야 한다.
|
||||||
- HDF5 schema는 versioned contract로 관리한다.
|
- 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으로 보고한다.
|
- parser, solver, HDF5 writer는 실패 원인을 구조화된 diagnostic으로 보고한다.
|
||||||
- oneMKL, oneTBB, HDF5는 CMake에서 명시 탐지하고 실패 원인을 분류한다.
|
- oneMKL, oneTBB, HDF5는 CMake에서 명시 탐지하고 실패 원인을 분류한다.
|
||||||
- 대규모 모델 성능 최적화보다 Phase 1 명확성, 테스트 가능성, 검증 traceability를 우선한다.
|
- 대규모 모델 성능 최적화보다 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가 승인되어 있다.
|
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 성공을 확인한다.
|
5. Tests fail before implementation: C++/integration/reference test를 제품 코드보다 먼저 작성하고 같은 Step 안에서 RED 실패와 후속 GREEN 성공을 확인한다.
|
||||||
6. CMake/CTest pass: MSVC/x64/Debug 기준 configure, build, test가 통과한다.
|
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 기준 안에 있다.
|
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, stress sanity가 검토되어 있다.
|
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가 준비되어 있다.
|
9. Release readiness pass: acceptance traceability, known limitations, release notes draft가 준비되어 있다.
|
||||||
|
|
||||||
## 제외 사항
|
## 제외 사항
|
||||||
- Abaqus full parser 호환
|
- 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 직접 실행 자동화
|
- Abaqus, Nastran 또는 reference solver 직접 실행 자동화
|
||||||
- Agent가 Abaqus reference CSV 파일을 임의 생성 또는 수정하는 작업
|
- Agent가 Abaqus reference CSV 파일을 임의 생성 또는 수정하는 작업
|
||||||
- GUI 또는 postprocessor
|
- GUI 또는 postprocessor
|
||||||
- Visual Studio `.sln`/`.vcxproj` 전용 MSBuild workflow
|
- Visual Studio `.sln`/`.vcxproj` 전용 MSBuild workflow
|
||||||
- Explicit dynamics, contact, plasticity, shell end-to-end 구현
|
- plasticity와 shell end-to-end 구현
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"phases": [
|
||||||
|
{
|
||||||
|
"dir": "linear-static-3d-euler-beam",
|
||||||
|
"status": "pending"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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를 관리한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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<double, 3> 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<double, 3> firstAxis; std::vector<std::array<double, 2>> sectionPoints;
|
||||||
|
};
|
||||||
|
struct EulerBeam3DDefinition {
|
||||||
|
SourceEntityId sourceId; std::array<EntityIndex, 2> 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<BoundaryCondition> boundaries;
|
||||||
|
std::vector<NodalLoad> 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가 담당한다.
|
||||||
@@ -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<std::string> value; };
|
||||||
|
struct DataLine { std::vector<std::string> fields; SourceLocation location; };
|
||||||
|
struct KeywordBlock {
|
||||||
|
std::string canonicalName;
|
||||||
|
std::string originalLine;
|
||||||
|
std::vector<KeywordParameter> parameters;
|
||||||
|
std::vector<DataLine> data;
|
||||||
|
SourceLocation location;
|
||||||
|
};
|
||||||
|
struct ParsedInput { std::vector<KeywordBlock> blocks; };
|
||||||
|
class AbaqusInputReader {
|
||||||
|
public:
|
||||||
|
Result<ParsedInput> 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가 담당한다.
|
||||||
@@ -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<Domain> 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`, `-1<nu<0.5`, 계산한 `G>0`과 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가 담당한다.
|
||||||
@@ -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<AnalysisModel> create(const Domain& domain);
|
||||||
|
const Domain& domain() const noexcept;
|
||||||
|
const StaticStepDefinition& step() const noexcept;
|
||||||
|
const std::vector<EntityIndex>& activeElements() const noexcept;
|
||||||
|
const std::vector<EntityIndex>& activeMaterials() const noexcept;
|
||||||
|
const std::vector<EntityIndex>& activeSections() const noexcept;
|
||||||
|
const std::vector<EntityIndex>& activeBoundaryConditions() const noexcept;
|
||||||
|
const std::vector<EntityIndex>& 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가 담당한다.
|
||||||
@@ -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<std::size_t> rowOffsets;
|
||||||
|
std::vector<std::size_t> columnIndices; };
|
||||||
|
class DofManager {
|
||||||
|
public:
|
||||||
|
static Result<DofManager> 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<std::size_t> freeEquation(std::size_t fullDof) const;
|
||||||
|
const std::array<std::size_t, 12>& elementScatter(EntityIndex element) const;
|
||||||
|
const std::vector<std::size_t>& freeDofs() const noexcept;
|
||||||
|
const std::vector<std::size_t>& 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가 담당한다.
|
||||||
@@ -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<double, 6> endAction;
|
||||||
|
std::array<double, 4> sectionResultant; };
|
||||||
|
struct GaussResultRow { EntityIndex element; int gaussPoint;
|
||||||
|
std::array<double, 4> generalizedStrain;
|
||||||
|
std::array<double, 4> 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가 담당한다.
|
||||||
@@ -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<std::array<double, 6>, 2> equilibriumEndActions;
|
||||||
|
std::array<std::array<double, 4>, 2> endpointSectionResultants;
|
||||||
|
std::array<std::array<double, 4>, 2> gaussGeneralizedStrains;
|
||||||
|
std::array<std::array<double, 4>, 2> gaussGeneralizedResultants;
|
||||||
|
std::vector<BeamStressPoint> stressPoints;
|
||||||
|
};
|
||||||
|
class EulerBeam3D {
|
||||||
|
public:
|
||||||
|
static Result<EulerBeam3D> 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가 담당한다.
|
||||||
@@ -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<void(std::size_t)>& 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가 담당한다.
|
||||||
@@ -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<SparseMatrix> fromCoo(std::size_t rows, std::size_t columns,
|
||||||
|
std::vector<CooContribution> contributions,
|
||||||
|
const SparsePattern& expectedPattern);
|
||||||
|
std::size_t rows() const noexcept;
|
||||||
|
std::size_t columns() const noexcept;
|
||||||
|
const std::vector<std::size_t>& rowOffsets() const noexcept;
|
||||||
|
const std::vector<std::size_t>& columnIndices() const noexcept;
|
||||||
|
const std::vector<double>& 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가 담당한다.
|
||||||
@@ -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<PartitionedStiffness> 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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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> 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가 담당한다.
|
||||||
@@ -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<Vector> assembleFullNodalLoad(const AnalysisModel& model,
|
||||||
|
const DofManager& dofs);
|
||||||
|
static Result<Vector> 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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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<Diagnostic>& diagnostics) = 0;
|
||||||
|
};
|
||||||
|
class Hdf5ResultsWriter final : public ResultsWriter {
|
||||||
|
public:
|
||||||
|
Status write(const std::filesystem::path& outputPath,
|
||||||
|
const Domain& domain,
|
||||||
|
const AnalysisState& state,
|
||||||
|
const std::vector<Diagnostic>& diagnostics) override;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
다음 group/dataset을 exact path와 승인 shape/component order로 기록한다.
|
||||||
|
|
||||||
|
```text
|
||||||
|
/metadata
|
||||||
|
/model/nodes
|
||||||
|
/model/elements
|
||||||
|
/steps/<step-name>/frames/0/nodal/displacement
|
||||||
|
/steps/<step-name>/frames/0/nodal/reaction
|
||||||
|
/steps/<step-name>/frames/0/element/end_force_local
|
||||||
|
/steps/<step-name>/frames/0/element/section_resultant
|
||||||
|
/steps/<step-name>/frames/0/element/generalized_strain
|
||||||
|
/steps/<step-name>/frames/0/element/generalized_resultant
|
||||||
|
/steps/<step-name>/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가 담당한다.
|
||||||
@@ -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<std::string>& 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 <model.inp> --output <results.h5>`와 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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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을 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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/<step-name>/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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
@@ -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<Diagnostic> diagnostics);
|
||||||
|
bool isOk() const noexcept;
|
||||||
|
const std::vector<Diagnostic>& diagnostics() const noexcept;
|
||||||
|
};
|
||||||
|
template<class T> class Result;
|
||||||
|
```
|
||||||
|
|
||||||
|
`Result<T>`는 성공 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가 담당한다.
|
||||||
@@ -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가 담당한다.
|
||||||
Reference in New Issue
Block a user