add uncommitted files

This commit is contained in:
KOKO\Mimi
2026-07-29 23:32:26 +09:00
parent fb0f8f39a0
commit f5379472ce
80 changed files with 7461 additions and 1 deletions
@@ -0,0 +1,31 @@
{
"project": "FESA",
"phase": "abaqus-subset-completion",
"steps": [
{
"step": 0,
"name": "abaqus-input-contract",
"status": "pending"
},
{
"step": 1,
"name": "part-and-assembly-set-resolution",
"status": "pending"
},
{
"step": 2,
"name": "single-instance-semantic-validation",
"status": "pending"
},
{
"step": 3,
"name": "material-section-and-shear-defaults",
"status": "pending"
},
{
"step": 4,
"name": "step-bc-load-and-noop-directives",
"status": "pending"
}
]
}
+52
View File
@@ -0,0 +1,52 @@
# Step 0: Abaqus Input Contract
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/specs/2026-07-29-abaqus-assembly-reference-design.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/io/abaqus/`
- `/reference/cantilever beam/cantilever beam.inp`
## 작업
production parser를 수정하기 전에 `docs/ABAQUS_INPUT_SUBSET.md`를 normative contract로
작성하고 valid/invalid fixture matrix를 등록한다.
문서에 각 keyword의 허용 scope, parameter, data line, diagnostic을 정확히 정의한다.
- `*NODE`, `*ELEMENT,TYPE=B31`
- `*PART/*END PART`, `*ASSEMBLY/*END ASSEMBLY`,
`*INSTANCE/*END INSTANCE`
- `*NSET`, `*ELSET`, `GENERATE`, nested set, `INSTANCE=`
- `*MATERIAL`, `*ELASTIC`, `*BEAM GENERAL SECTION`
- optional `*TRANSVERSE SHEAR STIFFNESS`
- `*BOUNDARY`, `*CLOAD`, `*STEP`, `*STATIC`, `*END STEP`
- no-op `*HEADING`, `*PREPRINT`, `*RESTART`, `*OUTPUT`
`tests/fixtures/abaqus/valid``invalid`에 최소 한 규칙당 fixture를 정의하고
data-driven contract test를 먼저 실패시킨다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R AbaqusInputContract --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 문서와 fixture manifest를 먼저 작성한다.
2. 아직 미구현인 계약 테스트가 실패하는 것을 확인한다.
3. 이 step에서는 parser behavior를 확장하지 않는다.
4. index summary에 계약 문서와 미통과 fixture 범위를 기록한다.
## 금지사항
- Abaqus 전체 문법 지원을 약속하지 마라. 이유: 명시된 subset만 대상이다.
- unknown keyword ignore 규칙을 만들지 마라. 이유: 조용한 모델 손실을 유발한다.
- reference 원본을 고치지 마라. 이유: golden provenance를 보존해야 한다.
+55
View File
@@ -0,0 +1,55 @@
# Step 1: Part and Assembly Set Resolution
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/ABAQUS_INPUT_SUBSET.md`
- `/include/fesa/io/abaqus/`
- `/include/fesa/model/entity_set.hpp`
- `/tests/fixtures/abaqus/`
## 작업
Part 및 Assembly scope의 `NSET/ELSET`을 결정적으로 해석한다.
```cpp
struct ResolvedSet final {
std::string scope_name;
std::string set_name;
std::vector<std::int64_t> sorted_unique_labels;
};
struct SetResolutionResult final {
std::vector<ResolvedSet> sets;
std::vector<Diagnostic> diagnostics;
};
[[nodiscard]] SetResolutionResult resolve_sets(const ParsedDeck&);
```
- explicit member, `GENERATE`, nested reference, forward reference, duplicate member,
empty set, cycle, unknown set/entity, invalid range를 실패 테스트로 먼저 작성한다.
- Part와 Assembly의 같은 set 이름을 별도 scope로 허용한다.
- Assembly `INSTANCE=`는 활성 단일 Instance의 Part-local label만 lift한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "SetResolution|PartSet|AssemblySet" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. scope collision과 cycle 테스트의 실패를 확인한다.
2. graph resolution과 canonical sorted-unique 결과를 구현한다.
3. source diagnostic과 deterministic order를 assertion한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- Part와 Assembly set namespace를 합치지 마라. 이유: 이름 충돌 의미가 달라진다.
- cycle을 recursion overflow로 발견하지 마라. 이유: 명시적 cycle diagnostic이 필요하다.
- 여러 Instance key를 지원하지 마라. 이유: Phase 1 단일 Instance 범위다.
+56
View File
@@ -0,0 +1,56 @@
# Step 2: Single Instance Semantic Validation
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/ABAQUS_INPUT_SUBSET.md`
- `/include/fesa/io/abaqus/parser.hpp`
- `/include/fesa/io/abaqus/semantic_mapper.hpp`
- `/include/fesa/io/abaqus/set_resolver.hpp`
## 작업
flat/hierarchical organization과 Phase 1 단일 Instance 제한을 semantic validation으로
완성한다.
```cpp
struct ActiveInputView final {
bool flat;
std::string part_name;
std::string instance_name;
std::span<const DeckRecord> part_records;
std::span<const DeckRecord> assembly_records;
};
[[nodiscard]] ActiveInputResult select_active_input(const ParsedDeck&);
```
- flat input은 Part/Assembly가 없어야 한다.
- hierarchical input은 여러 Part를 허용하지만 Assembly와 Instance는 각각 정확히
하나여야 한다.
- missing Part, transform data, instance-local node/element, mixed organization,
wrong `INSTANCE=`를 먼저 실패 테스트로 작성한다.
- unreferenced Part가 Domain entity를 만들지 않는지 검증한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "SingleInstance|ActiveInput|SemanticScope" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 각 미지원 organization의 실패 테스트를 확인한다.
2. selection/validation만 구현하고 좌표 변환 코드는 만들지 않는다.
3. source location과 활성 Part 결과를 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- transformation data를 0으로 간주해 무시하지 마라. 이유: 계약상 명시적 오류다.
- unreferenced Part를 Domain에 병합하지 마라. 이유: 사용자 요구와 다르다.
- future multi-instance abstraction을 만들지 마라. 이유: 실제 두 번째 구현이 없다.
+48
View File
@@ -0,0 +1,48 @@
# Step 3: Material, Section, and Shear Defaults
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/ABAQUS_INPUT_SUBSET.md`
- `/include/fesa/io/abaqus/semantic_mapper.hpp`
- `/include/fesa/model/material.hpp`
- `/include/fesa/model/beam_section.hpp`
- `/include/fesa/model/domain_builder.hpp`
## 작업
전역 material과 Part-local Beam section/ELSET assignment를 complete-deck resolution으로
semantic model에 연결한다.
- `*ELASTIC`의 \(E,\nu\)에서 \(G=E/[2(1+\nu)]\)를 계산한다.
- general section의 \(A,I_y,I_{yz},I_z,J\), orientation을 읽되 \(I_{yz}=0\)만
허용한다.
- explicit transverse stiffness를 \(A_{sy},A_{sz}\)로 변환한다.
- 생략 시 \(A_{sy}=A_{sz}=5A/6\), `SCF=0`,
`ShearPropertySource::phase1_default`를 적용한다.
- nonzero `SCF`, missing/duplicate material/section assignment, invalid properties를
실패 테스트로 먼저 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "MaterialMapping|BeamSection|ShearDefault" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. material이 Part 뒤에 정의된 forward-resolution 테스트를 먼저 실패시킨다.
2. explicit/default shear 두 경로를 최소 구현한다.
3. HDF5에 저장할 source enum까지 Domain에 보존되는지 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- 임의 단면에 대한 Abaqus 보편 기본값이라고 문서화하지 마라. 이유: FESA Phase 1 가정이다.
- nonzero \(I_{yz}\)를 버리지 마라. 이유: 조용한 정식화 변경이다.
- orientation을 자동 생성하지 마라. 이유: mandatory 입력 계약이다.
+47
View File
@@ -0,0 +1,47 @@
# Step 4: Step, BC, Load, and No-op Directives
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/ABAQUS_INPUT_SUBSET.md`
- `/include/fesa/io/abaqus/`
- `/reference/cantilever beam/cantilever beam.inp`
- `/include/fesa/model/step_definition.hpp`
## 작업
단일 `*STEP/*STATIC`, Assembly set 기반 `*BOUNDARY/*CLOAD`와 명시적 no-op directive
처리를 완성한다.
- `*BOUNDARY`는 DOF 1~6의 0/비영 값을 지원한다.
- `*CLOAD`는 force/moment component 1~6을 누적한다.
- 중복 동일 BC는 canonicalize하고 충돌 prescribed value는 거부한다.
- `*HEADING`, `*PREPRINT`, `*RESTART`, `*OUTPUT`과 소유 data는 명시적으로
consume하되 Domain behavior를 만들지 않는다.
- 여러 step, `nlgeom` nonzero, unsupported output/keyword option을 실패시킨다.
- 제공된 cantilever가 11 nodes, 10 elements, 6 fixed DOFs, node 11의
\(F_z=-10000\)으로 정규화되는 통합 테스트를 먼저 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "StepMapping|Boundary|Cload|SuppliedCantilever" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 제공 샘플을 복사/변경하지 않고 public parser로 실패를 확인한다.
2. 문서화된 keyword만 구현한다.
3. expected Domain과 source diagnostic을 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- no-op 목록을 general ignore로 확장하지 마라. 이유: 모델 정의 손실을 숨긴다.
- 여러 step/load history를 추가하지 마라. 이유: Phase 1 범위 밖이다.
- reference input을 rewrite하지 마라. 이유: 검증 원본을 보존해야 한다.
@@ -0,0 +1,26 @@
{
"project": "FESA",
"phase": "beam-reference-qualification",
"steps": [
{
"step": 0,
"name": "comparison-metric-and-entity-matching",
"status": "pending"
},
{
"step": 1,
"name": "reference-csv-adapters",
"status": "pending"
},
{
"step": 2,
"name": "cantilever-reference-comparison",
"status": "pending"
},
{
"step": 3,
"name": "qualification-report",
"status": "pending"
}
]
}
@@ -0,0 +1,69 @@
# Step 0: Comparison Metric and Entity Matching
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/specs/2026-07-29-abaqus-assembly-reference-design.md`
- `/include/fesa/results/result_database.hpp`
- `/include/fesa/model/entity_origin.hpp`
## 작업
CSV와 독립적인 reference comparison metric, entity position과 report를 구현한다.
```cpp
enum class ReferenceQuantity {
displacement,
reaction,
internal_force,
centroid_stress
};
struct Tolerance final { double relative; double absolute_scale; };
struct ResultPosition final {
std::string instance_name;
std::int64_t entity_label;
std::optional<std::int64_t> end_node_label;
};
struct ComparisonSample final {
ReferenceQuantity quantity;
ResultPosition position;
std::vector<double> reference;
std::vector<double> actual;
Tolerance tolerance;
};
struct ComparisonReport final {
bool passed;
double maximum_normalized_error;
std::vector<Diagnostic> failures;
};
[[nodiscard]] ComparisonReport compare_samples(
std::span<const ComparisonSample>);
```
각 scalar는 \(e_n=|a-r|/(a_{scale}+r_{tol}|r|)\)이며 \(e_n\le1\)만 통과한다.
nonfinite, duplicate position, component mismatch, unknown origin, invalid element-node
pair를 실패 테스트로 먼저 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "ComparisonMetric|EntityMatching" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. near-zero와 큰 값의 실패 테스트를 먼저 실행한다.
2. report에 quantity/entity/component/reference/actual/error를 기록한다.
3. unit-free metric과 명시 tolerance만 사용한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- NaN 비교를 통과시키지 마라. 이유: 수치 실패를 숨긴다.
- 모든 물리량에 하나의 absolute scale을 강제하지 마라. 이유: 규모가 다르다.
- CSV parsing을 이 파일에 넣지 마라. 이유: 다음 adapter 경계다.
@@ -0,0 +1,63 @@
# Step 1: Reference CSV Adapters
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/specs/2026-07-29-abaqus-assembly-reference-design.md`
- `/include/fesa/validation/comparison.hpp`
- `/reference/cantilever beam/cantilever beam displacements.csv`
- `/reference/cantilever beam/cantilever beam reactions.csv`
## 작업
네 물리량의 명시적 CSV schema를 읽어 canonical reference row로 변환한다.
```cpp
struct ReferenceRow final {
ReferenceQuantity quantity;
ResultPosition position;
std::vector<double> values;
};
struct ReferenceCsvReadResult final {
std::vector<ReferenceRow> rows;
std::vector<Diagnostic> diagnostics;
};
[[nodiscard]] ReferenceCsvReadResult read_reference_csv(
ReferenceQuantity,
const std::filesystem::path&,
std::string_view single_instance_name);
```
- displacement/reaction은 제공된 whitespace 포함 Abaqus header를 읽는다.
- internal force schema:
`Part Instance Name, Element Label, Node Label, SF-SF1..SF-SF3,
SM-SM1..SM-SM3`
- stress schema:
`Part Instance Name, Element Label, Node Label, Sxx`
- 단일 Instance에서는 Instance 열 생략을 허용하고 request 이름으로 보완한다.
- `tests/fixtures/reference`에 synthetic internalforce/stress CSV를 먼저 만들고,
6개 내력 component와 centroid stress row를 실패 테스트로 고정한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "ReferenceCsv|InternalForceCsv|StressCsv" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. four-schema parser test 실패를 확인한다.
2. header/value trim과 선택적 UTF-8 BOM만 허용한다.
3. missing column, duplicate row, invalid number를 진단한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- metadata.json을 요구하지 마라. 이유: 승인된 reference 계약과 다르다.
- unknown column으로 필수 column 누락을 숨기지 마라. 이유: 잘못된 비교를 만든다.
- 내력/응력 파일이 없다는 이유로 adapter 구현을 생략하지 마라. 이유: 필수 루틴이다.
@@ -0,0 +1,50 @@
# Step 2: Cantilever Reference Comparison
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/reference/cantilever beam/cantilever beam.inp`
- `/reference/cantilever beam/cantilever beam displacements.csv`
- `/reference/cantilever beam/cantilever beam reactions.csv`
- `/include/fesa/analysis/run_solver.hpp`
- `/include/fesa/io/hdf5/reader.hpp`
- `/include/fesa/validation/reference_csv.hpp`
## 작업
제공된 계층형 캔틸레버를 production pipeline으로 해석하고 현재 존재하는 변위와
반력만 Abaqus 2024 결과와 비교한다.
- `tests/reference/cantilever_reference_test.cpp`와 reference compare CLI를 먼저
작성한다.
- comparison request는 Instance `Part-1-1`, relative tolerance `1e-5`,
displacement absolute scale `1e-10`, reaction absolute scale `1e-8`을 명시한다.
- HDF5 결과와 CSV를 public adapter로 읽어 `(Instance,Node Label)`로 join한다.
- 요청하지 않은 internal force/stress 파일을 검색하거나 pass로 보고하지 않는다.
- equilibrium과 finite result도 함께 assertion한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R CantileverReference --output-on-failure
.\out\build\windows-debug\Debug\fesa.exe solve "reference\cantilever beam\cantilever beam.inp" --output out\cantilever-beam.h5
.\out\build\windows-debug\Debug\fesa-reference-compare.exe --results out\cantilever-beam.h5 --instance Part-1-1 --displacements "reference\cantilever beam\cantilever beam displacements.csv" --reactions "reference\cantilever beam\cantilever beam reactions.csv" --relative-tolerance 1e-5 --displacement-absolute-scale 1e-10 --reaction-absolute-scale 1e-8
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. reference test가 실제 오차를 보고하며 실패하는 것을 확인한다.
2. discrepancy마다 가장 작은 analytical test를 추가한 뒤 근거 있는 kernel만 수정한다.
3. tolerance를 넓혀 결함을 숨기지 않는다.
4. 전체 테스트와 최대 정규화 오차를 index summary에 기록한다.
## 금지사항
- reference `.inp` 또는 CSV를 수정하지 마라. 이유: 원본 golden을 보존해야 한다.
- 미제공 내력/응력 Abaqus 검증을 통과했다고 주장하지 마라. 이유: 증거가 없다.
- test-only parser/solver 경로를 만들지 마라. 이유: production pipeline 검증이다.
@@ -0,0 +1,51 @@
# Step 3: Qualification Report
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/formulation/timoshenko-beam-3d.md`
- `/docs/HDF5_SCHEMA.md`
- `/tests/unit/elements/`
- `/tests/reference/`
- `/tests/fixtures/reference/`
## 작업
`docs/VALIDATION.md`에 Phase 1의 실제 검증 증거와 제한을 기록한다.
- analytical: axial, torsion, bending y/z, biaxial, shear-dominant, rigid body,
rotated frame, slenderness sweep
- physics: equilibrium, symmetry, reaction, nonzero prescribed DOF
- determinism: tested thread counts와 repeated runs
- Abaqus: 현재 cantilever displacement/reaction의 tolerance와 maximum error
- contract-only: synthetic internal-force/stress CSV schema와 component mapping
- 미제공 Abaqus internal-force/stress는 `not yet Abaqus-qualified`라고 명시한다.
보고서 수치를 새 test output에서 수집하며 수동 추정값을 쓰지 않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug --output-on-failure
ctest --preset windows-debug -R "Reference|Beam3D2|Determinism" --output-on-failure
```
모든 실행이 통과하고 보고서의 test 이름, tolerance, 최대오차와 disposition이 실제
출력과 일치해야 한다.
## 검증 절차
1. 전체 suite를 새로 실행한다.
2. 결과를 benchmark/quantity별 표에 기록한다.
3. synthetic coverage와 Abaqus-backed qualification을 명확히 분리한다.
4. index summary에 보고서 경로와 test counts를 기록한다.
## 금지사항
- 실행하지 않은 결과를 보고서에 쓰지 마라. 이유: 검증 증거가 아니다.
- Abaqus 내력/응력 qualification을 추론하지 마라. 이유: CSV가 아직 없다.
- 실패 테스트를 제외하거나 disable하지 마라. 이유: release gate를 약화한다.
@@ -0,0 +1,21 @@
{
"project": "FESA",
"phase": "deterministic-parallel-assembly",
"steps": [
{
"step": 0,
"name": "canonical-contribution-order",
"status": "pending"
},
{
"step": 1,
"name": "tbb-element-evaluation",
"status": "pending"
},
{
"step": 2,
"name": "thread-count-determinism",
"status": "pending"
}
]
}
@@ -0,0 +1,56 @@
# Step 0: Canonical Contribution Order
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/assembly/`
- `/src/fesa/assembly/`
- `/include/fesa/model/entity_origin.hpp`
## 작업
serial assembly를 변경하지 않고 병렬 계산이 사용할 canonical contribution record와
merge contract를 분리한다.
```cpp
struct MatrixContribution final {
std::size_t row;
std::size_t column;
ElementId element;
std::uint16_t local_order;
double value;
};
[[nodiscard]] std::vector<MatrixContribution> canonicalize_contributions(
std::span<const MatrixContribution>);
[[nodiscard]] SymmetricCsr merge_contributions(
std::size_t order,
std::span<const MatrixContribution> canonical);
```
- 입력 순열, 같은 row/column의 여러 element, cancellation, signed zero를 포함해
결과 CSR이 bit-for-bit 같은 테스트를 먼저 작성한다.
- 정렬 key는 row, column, stable element identity, local order다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "CanonicalContribution|DeterministicMerge" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. shuffled contribution 테스트의 실패를 확인한다.
2. stable total order와 단일 merge 구현만 추가한다.
3. serial oracle의 CSR과 bitwise 비교한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- tolerance 기반으로 assembly 값을 같다고 처리하지 마라. 이유: bitwise 재현성 계약이다.
- parallel code를 추가하지 마라. 이유: 다음 step의 책임이다.
- unordered concurrent accumulation을 준비하지 마라. 이유: 결정성을 깨뜨린다.
@@ -0,0 +1,54 @@
# Step 1: TBB Element Evaluation
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/cmake/FesaDependencies.cmake`
- `/include/fesa/assembly/assembler.hpp`
- `/include/fesa/assembly/contribution.hpp`
- `/include/fesa/elements/beam/beam3d2.hpp`
## 작업
oneTBB로 독립적인 요소 계산만 병렬화하고 contribution merge는 canonical serial
순서를 사용한다.
```cpp
struct AssemblyOptions final {
std::size_t max_threads;
std::size_t grain_size;
};
[[nodiscard]] EquationSystem assemble_parallel(
const Domain&,
const DofManager&,
AssemblyOptions);
```
- fixed Beam chain/branched Domain에서 serial과 parallel의 row offsets, column indices,
values, force vector를 bit-for-bit 비교하는 실패 테스트를 먼저 작성한다.
- worker는 thread-local contribution을 생성하고 공유 CSR values에 쓰지 않는다.
- `max_threads=1`과 2 이상을 명시적으로 제한할 수 있어야 한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "ParallelAssembly|TbbElementEvaluation" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. parallel API 부재로 실패하는 테스트를 확인한다.
2. element evaluation 범위에만 TBB를 적용한다.
3. serial/parallel bitwise 결과와 TSAN 대신 구조적 race 회피 설계를 검토한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- 공유 CSR value에 atomic add하지 마라. 이유: 합산 순서가 비결정적이다.
- PARDISO 호출을 TBB task 안에 넣지 마라. 이유: oversubscription 위험이 있다.
- 성능을 위해 tolerance를 완화하지 마라. 이유: 검증 결정성이 우선이다.
@@ -0,0 +1,46 @@
# Step 2: Thread Count Determinism
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/assembly/assembler.hpp`
- `/tests/unit/assembly/`
- `/tests/integration/assembly/`
## 작업
thread count와 반복 실행이 assembly 및 최종 선형 정적 결과를 바꾸지 않는 통합
검증과 측정용 benchmark를 추가한다.
- `tests/integration/assembly/thread_count_determinism_test.cpp`
- `tests/performance/assembly_benchmark.cpp`
- thread counts 1, 2, available concurrency에서 CSR, RHS, displacement, reaction을
bit-for-bit 비교한다.
- 최소 10회 반복으로 scheduling 변화 회귀를 확인한다.
- benchmark는 serial/parallel 시간과 element count를 출력하되 speedup을 assertion하지
않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R ThreadCountDeterminism --output-on-failure
.\out\build\windows-debug\Debug\fesa_assembly_benchmark.exe
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 다양한 thread count 통합 테스트를 먼저 실행한다.
2. 차이가 있으면 canonical key/merge 원인을 고치고 tolerance 비교로 대체하지 않는다.
3. benchmark output을 기록하고 전체 테스트를 실행한다.
4. index summary에 tested thread counts를 기록한다.
## 금지사항
- benchmark에서 속도 향상을 pass 조건으로 만들지 마라. 이유: 환경 의존적이다.
- MKL thread 수를 assembly test와 중첩해 키우지 마라. 이유: 측정이 오염된다.
- release 성능 목표를 임의로 만들지 마라. 이유: 문서화된 측정만 요구된다.
@@ -0,0 +1,26 @@
{
"project": "FESA",
"phase": "domain-and-input-skeleton",
"steps": [
{
"step": 0,
"name": "semantic-domain-and-origin-types",
"status": "pending"
},
{
"step": 1,
"name": "domain-validation",
"status": "pending"
},
{
"step": 2,
"name": "abaqus-scoped-syntax-parser",
"status": "pending"
},
{
"step": 3,
"name": "active-instance-domain-normalization",
"status": "pending"
}
]
}
+65
View File
@@ -0,0 +1,65 @@
# Step 0: Semantic Domain and Origin Types
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/specs/2026-07-29-abaqus-assembly-reference-design.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/core/entity_id.hpp`
- `/include/fesa/core/vec3.hpp`
- `/include/fesa/core/diagnostic.hpp`
## 작업
정규화된 solver semantic model의 값 타입과 불변 조회 계약을 만든다.
- `include/fesa/model/` 아래 `ids.hpp`, `entity_origin.hpp`, `node.hpp`,
`material.hpp`, `beam_section.hpp`, `beam_element.hpp`, `entity_set.hpp`,
`step_definition.hpp`, `domain.hpp`를 만든다.
- 핵심 타입:
```cpp
struct EntityOrigin final {
std::string part_name;
std::string instance_name;
std::int64_t local_label;
};
struct Node final { NodeId id; EntityOrigin origin; Vec3 position; };
struct BeamElement final {
ElementId id;
EntityOrigin origin;
std::array<NodeId, 2> nodes;
MaterialId material;
SectionId section;
};
```
- `BeamSection`은 \(A,I_y,I_z,J,A_{sy},A_{sz}\), orientation과 recovery point를
가진다. 전단값 출처는 `enum class ShearPropertySource { input, phase1_default };`
로 표현한다.
- flat mesh는 빈 `part_name/instance_name`, 계층형 mesh는 실제 이름을 사용한다.
- 먼저 값 보존과 origin 조회가 실패하는 테스트를 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "ModelTypes|EntityOrigin" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 테스트를 먼저 작성하고 compile failure를 확인한다.
2. 저장과 읽기에 필요한 최소 API만 구현한다.
3. `model` public header에 Abaqus/MKL/TBB/HDF5 타입이 없는지 확인한다.
4. focused 및 전체 테스트를 실행하고 index를 갱신한다.
## 금지사항
- parser record를 `Domain`에 저장하지 마라. 이유: syntax/semantic 경계를 깨뜨린다.
- 여러 Instance container를 만들지 마라. 이유: Phase 1은 단일 Instance다.
- equation 번호를 Node/Element에 저장하지 마라. 이유: DofManager 책임이다.
+63
View File
@@ -0,0 +1,63 @@
# Step 1: Domain Validation
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/model/`
- `/tests/unit/model/`
이전 step의 타입 이름과 필드를 변경하지 말고 builder validation을 추가하라.
## 작업
`DomainBuilder`가 모든 semantic entity를 검증한 뒤 불변 `Domain` 하나를 생성하게
한다.
```cpp
struct DomainBuildResult final {
std::optional<Domain> domain;
std::vector<Diagnostic> diagnostics;
};
class DomainBuilder final {
public:
void add_node(Node);
void add_material(IsotropicElastic);
void add_section(BeamSection);
void add_beam_element(BeamElement);
void add_node_set(NodeSet);
void add_element_set(ElementSet);
void set_step(StepDefinition);
[[nodiscard]] DomainBuildResult build() &&;
};
```
- 중복 internal ID, 중복 origin, missing reference, invalid \(E,\nu,A,I,J,A_s\),
nonfinite 값, zero-length element, invalid orientation, section/material 누락,
충돌 BC를 각각 실패 테스트로 먼저 작성한다.
- 내부 dense lookup과 origin lookup을 만들되 public mutable access는 제공하지 않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "DomainBuilder|DomainValidation" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 각 거부 조건의 실패 테스트를 먼저 확인한다.
2. 하나의 오류가 다른 오류를 숨기지 않도록 가능한 진단을 수집한다.
3. valid Domain test와 전체 CTest를 실행한다.
4. index summary에 검증 규칙과 생성 파일을 기록한다.
## 금지사항
- 잘못된 입력값을 자동 보정하지 마라. 이유: explicit diagnostic 계약을 위반한다.
- solver 또는 parser validation을 이 builder에 넣지 마라. 이유: 모듈 책임이 다르다.
- mutable Domain accessor를 추가하지 마라. 이유: 해석 중 모델 불변성을 깨뜨린다.
+74
View File
@@ -0,0 +1,74 @@
# Step 2: Abaqus Scoped Syntax Parser
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/specs/2026-07-29-abaqus-assembly-reference-design.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/core/source_location.hpp`
- `/include/fesa/core/diagnostic.hpp`
## 작업
Abaqus keyword를 해석하지 않고 scope가 보존된 syntax tree로 읽는 parser를 만든다.
```cpp
struct DeckRecord final {
std::string keyword;
std::map<std::string, std::string, std::less<>> parameters;
std::vector<std::vector<std::string>> data;
SourceLocation source;
};
struct ParsedPart final {
std::string name;
std::vector<DeckRecord> records;
SourceLocation source;
};
struct ParsedInstance final {
std::string name;
std::string part_name;
std::vector<std::vector<std::string>> transform_data;
SourceLocation source;
};
struct ParsedAssembly final {
std::string name;
std::vector<ParsedInstance> instances;
std::vector<DeckRecord> records;
SourceLocation source;
};
struct ParsedDeck final {
std::vector<DeckRecord> global_records;
std::vector<ParsedPart> parts;
std::optional<ParsedAssembly> assembly;
};
[[nodiscard]] ParseDeckResult parse_deck(const std::filesystem::path&);
```
- flat fixture와 단일 Part/Assembly/Instance fixture를 먼저 만든다.
- case-insensitive keyword, comment, blank line, comma field, UTF-8, source line,
scope 종료 오류를 테스트한다.
- 이 step은 syntax만 파싱하며 active Part를 선택하지 않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "AbaqusParser|ScopedDeck" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. parser test를 작성하고 실패를 확인한다.
2. `io/abaqus`에 lexer/parser만 최소 구현한다.
3. source location과 scope tree를 assertion한다.
4. 전체 테스트 후 index를 갱신한다.
## 금지사항
- Domain을 생성하지 마라. 이유: 다음 semantic normalization step의 책임이다.
- unknown keyword를 일반적으로 무시하지 마라. 이유: 명시적 입력 계약을 훼손한다.
- Instance 변환을 적용하지 마라. 이유: Phase 1에서 거부할 syntax 정보로 보존한다.
+52
View File
@@ -0,0 +1,52 @@
# Step 3: Active Instance Domain Normalization
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/specs/2026-07-29-abaqus-assembly-reference-design.md`
- `/include/fesa/model/domain_builder.hpp`
- `/include/fesa/io/abaqus/deck_record.hpp`
- `/include/fesa/io/abaqus/parser.hpp`
- `/tests/fixtures/abaqus/minimal_cantilever.inp`
- `/tests/fixtures/abaqus/minimal_part_instance_cantilever.inp`
## 작업
flat 또는 단일 무변환 Instance 입력을 동일한 `Domain`으로 변환한다.
```cpp
[[nodiscard]] DomainBuildResult map_deck_to_domain(const ParsedDeck& deck);
```
- 먼저 두 fixture가 동등한 활성 절점·요소·재료·단면·하중·BC를 만드는 통합
테스트를 작성한다.
- 계층형 deck은 정확히 하나의 Assembly와 Instance를 요구한다.
- transform data가 있거나 Part reference가 없으면 source diagnostic을 반환한다.
- Instance가 참조하지 않는 Part는 Domain에 포함하지 않는다.
- origin에는 실제 Part/Instance/local label을 보존한다.
- 전단강성이 없으면 \(A_{sy}=A_{sz}=5A/6\), `SCF=0`,
`ShearPropertySource::phase1_default`를 사용한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "DeckToDomain|ActiveInstance" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. public parser와 mapper를 사용하는 실패 테스트를 확인한다.
2. syntax record를 복제해 Domain에 저장하지 않고 semantic 값으로 변환한다.
3. unreferenced Part exclusion과 provenance를 assertion한다.
4. focused/full test 후 index summary를 갱신한다.
## 금지사항
- 여러 Instance를 평탄화하지 마라. 이유: Phase 1 범위 밖이다.
- 변환 좌표를 조용히 무시하지 마라. 이유: 잘못된 해석 모델을 만든다.
- 테스트에서 Domain을 직접 구성하지 마라. 이유: production 경로를 우회한다.
@@ -0,0 +1,21 @@
{
"project": "FESA",
"phase": "equation-and-linear-solve",
"steps": [
{
"step": 0,
"name": "symmetric-csr-assembly",
"status": "pending"
},
{
"step": 1,
"name": "essential-bc-elimination",
"status": "pending"
},
{
"step": 2,
"name": "pardiso-linear-solver",
"status": "pending"
}
]
}
+58
View File
@@ -0,0 +1,58 @@
# Step 0: Symmetric CSR Assembly
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/model/domain.hpp`
- `/include/fesa/fem/dof_manager.hpp`
- `/include/fesa/elements/beam/beam3d2.hpp`
## 작업
Beam local contribution으로부터 deterministic serial symmetric CSR과 full load vector를
조립한다.
```cpp
struct SymmetricCsr final {
std::size_t order;
std::vector<std::int32_t> row_offsets;
std::vector<std::int32_t> column_indices;
std::vector<double> values;
};
struct EquationSystem final {
SymmetricCsr stiffness;
std::vector<double> force;
};
[[nodiscard]] EquationSystem assemble_serial(
const Domain&,
const DofManager&);
```
- sparsity pattern builder와 numeric contribution merge를 분리한다.
- `(row,column,element-origin,local-order)`의 안정된 순서로 합산한다.
- hand-calculated 2-element system, duplicate contribution, external ID 순서 변화,
CSR invariant를 실패 테스트로 먼저 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "SparsePattern|SerialAssembly|SymmetricCsr" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. expected CSR 구조와 값을 고정한 실패 테스트를 실행한다.
2. pattern과 numeric assembly를 최소 구현한다.
3. row offset, sorted column, upper/lower storage 계약을 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- 공유 CSR에 병렬 누적하지 마라. 이유: 이 phase는 serial oracle을 만든다.
- PARDISO를 호출하지 마라. 이유: backend step의 책임이다.
- element formulation을 assembly에 복제하지 마라. 이유: 모듈 경계를 깨뜨린다.
+56
View File
@@ -0,0 +1,56 @@
# Step 1: Essential BC Elimination
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/assembly/symmetric_csr.hpp`
- `/include/fesa/assembly/equation_system.hpp`
- `/include/fesa/fem/dof_manager.hpp`
- `/include/fesa/model/step_definition.hpp`
## 작업
0과 비영 지정변위를 지원하는 essential-BC elimination과 full-vector 복원을 구현한다.
```cpp
struct ReducedSystem final {
SymmetricCsr stiffness;
std::vector<double> force;
std::vector<std::size_t> free_to_full;
std::vector<double> prescribed_full;
};
[[nodiscard]] ConstraintResult eliminate_essential_bcs(
const EquationSystem& original,
const DofManager& dofs,
std::span<const PrescribedDof> prescribed);
[[nodiscard]] std::vector<double> recover_reaction(
const EquationSystem& original,
std::span<const double> full_displacement);
```
- 작은 hand calculation으로 RHS shift, 0/비영 prescribed value, all constrained,
충돌 조건, \(r=Ku-f\) 반력 복원을 먼저 테스트한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "EssentialBc|ConstraintElimination|Reaction" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 비영 지정값 테스트의 실패를 먼저 확인한다.
2. 원래 EquationSystem을 보존한 채 reduced system을 생성한다.
3. 복원 변위와 원래 평형식 반력을 assertion한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- penalty나 큰 수를 사용하지 마라. 이유: 승인된 elimination 정책과 다르다.
- 반력을 reduced matrix에서 계산하지 마라. 이유: 원래 \(K,u,f\)가 필요하다.
- MPC/Lagrange multiplier를 추가하지 마라. 이유: 범위 밖이다.
+65
View File
@@ -0,0 +1,65 @@
# Step 2: PARDISO Linear Solver
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/cmake/FesaDependencies.cmake`
- `/include/fesa/assembly/symmetric_csr.hpp`
- `/include/fesa/core/diagnostic.hpp`
## 작업
MKL PARDISO를 RAII adapter 뒤에 격리하고 symmetric positive-definite reduced system을
푼다.
```cpp
struct LinearSolveResult final {
std::vector<double> solution;
double relative_residual;
std::vector<Diagnostic> diagnostics;
};
class LinearSolver {
public:
virtual ~LinearSolver() = default;
[[nodiscard]] virtual LinearSolveResult solve(
const SymmetricCsr&,
std::span<const double> rhs) = 0;
};
class PardisoLinearSolver final : public LinearSolver {
public:
PardisoLinearSolver();
~PardisoLinearSolver() override;
[[nodiscard]] LinearSolveResult solve(
const SymmetricCsr&,
std::span<const double>) override;
};
```
- 3x3 SPD, repeated solve, invalid CSR, dimension mismatch, singular matrix를 먼저
테스트한다.
- `mtype=2`, LP64 index, `iparm[34]=1`, matrix checker, analysis/factor/solve/release
phase를 사용한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "Pardiso|LinearSolver" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. adapter test의 link/behavior 실패를 확인한다.
2. 모든 MKL handle/workspace를 RAII로 해제한다.
3. 해와 상대잔차를 독립 계산으로 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- MKL 타입을 `LinearSolver` public contract에 노출하지 마라. 이유: backend 격리다.
- singular system을 임의 regularization하지 마라. 이유: 모델 오류를 숨긴다.
- PARDISO 실행 중 TBB task를 중첩하지 마라. 이유: oversubscription 정책 위반이다.
+26
View File
@@ -0,0 +1,26 @@
{
"project": "FESA",
"phase": "fem-and-beam-kernel",
"steps": [
{
"step": 0,
"name": "quadrature-and-shape-functions",
"status": "pending"
},
{
"step": 1,
"name": "dof-manager",
"status": "pending"
},
{
"step": 2,
"name": "beam-local-frame",
"status": "pending"
},
{
"step": 3,
"name": "timoshenko-stiffness-kernel",
"status": "pending"
}
]
}
+47
View File
@@ -0,0 +1,47 @@
# Step 0: Quadrature and Shape Functions
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/core/vec3.hpp`
## 작업
특정 analysis에 종속되지 않는 1D Gauss quadrature와 2절점 선형 shape function을
`fem` 모듈에 구현한다.
```cpp
struct GaussPoint1D final { double xi; double weight; };
[[nodiscard]] std::span<const GaussPoint1D> gauss_rule_1d(int order);
[[nodiscard]] std::array<double, 2> line2_shape(double xi);
[[nodiscard]] std::array<double, 2> line2_shape_derivative(double xi);
[[nodiscard]] double line2_jacobian(double length);
```
- partition of unity, endpoint interpolation, derivative sum zero, 1점/2점 적분의
정확도, length/2 Jacobian, invalid order/length를 실패 테스트로 먼저 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "Quadrature|ShapeFunction|Jacobian" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 수학 invariant 테스트의 실패를 확인한다.
2. 고정 크기 값 타입과 최소 함수만 구현한다.
3. tolerance 근거를 테스트 이름 또는 주석에 명시한다.
4. 전체 CTest와 index 갱신을 수행한다.
## 금지사항
- Beam stiffness를 이 step에 구현하지 마라. 이유: 수학 primitive 경계를 유지한다.
- runtime quadrature registry를 만들지 마라. 이유: 1점과 2점만 필요하다.
- 잘못된 길이에 임의 epsilon을 더하지 마라. 이유: model 오류를 숨긴다.
+57
View File
@@ -0,0 +1,57 @@
# Step 1: DOF Manager
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/model/domain.hpp`
- `/include/fesa/model/step_definition.hpp`
- `/include/fesa/fem/`
## 작업
절점당 6자유도와 constrained/free equation numbering을 전담하는 `DofManager`
구현한다.
```cpp
enum class NodeDof : std::uint8_t { ux, uy, uz, rx, ry, rz };
struct DofAddress final { NodeId node; NodeDof dof; };
class DofManager final {
public:
[[nodiscard]] static DofManager build(const Domain&);
[[nodiscard]] std::size_t full_dof_count() const noexcept;
[[nodiscard]] std::size_t free_equation_count() const noexcept;
[[nodiscard]] std::optional<std::size_t> equation(DofAddress) const;
[[nodiscard]] std::array<std::size_t, 12> element_full_dofs(
const BeamElement&) const;
[[nodiscard]] std::vector<double> reconstruct_full(
std::span<const double> reduced) const;
};
```
- external label 순서와 무관한 deterministic numbering, 비영 지정값, full/reduced
reconstruction, invalid DOF를 실패 테스트로 먼저 고정한다.
- equation ID를 Node/Element에 쓰지 않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "DofManager|EquationNumbering" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 실패 테스트를 먼저 실행한다.
2. Domain 읽기 전용 view만 사용해 numbering을 구현한다.
3. constrained/free mapping과 reconstruction을 직접 assertion한다.
4. 전체 테스트와 index 갱신을 수행한다.
## 금지사항
- sparse matrix pattern을 소유하지 마라. 이유: assembly 책임이다.
- Node/Element에 equation ID를 저장하지 마라. 이유: 아키텍처 규칙 위반이다.
- MPC나 penalty 자유도를 추가하지 마라. 이유: Phase 1 범위 밖이다.
+53
View File
@@ -0,0 +1,53 @@
# Step 2: Beam Local Frame
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/core/vec3.hpp`
- `/include/fesa/model/beam_section.hpp`
- `/include/fesa/model/beam_element.hpp`
## 작업
두 절점과 mandatory orientation vector로 오른손 직교 Beam 국부 기저와 12x12
좌표변환을 계산한다.
```cpp
struct BeamFrame final { Vec3 ex; Vec3 ey; Vec3 ez; };
struct BeamFrameResult final {
std::optional<BeamFrame> frame;
std::vector<Diagnostic> diagnostics;
};
[[nodiscard]] BeamFrameResult make_beam_frame(
const Vec3& first,
const Vec3& second,
const Vec3& orientation);
[[nodiscard]] Matrix12 beam_transformation(const BeamFrame&);
```
- 축 방향 정규화, Gram-Schmidt, 오른손성, 직교성, 회전 불변성을 테스트한다.
- zero length, zero orientation, orientation parallel to element axis를 실패시킨다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "BeamFrame|BeamTransformation" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 축 정렬 및 임의 회전 테스트의 실패를 확인한다.
2. tolerance를 scale-aware하게 적용한다.
3. \(R R^T=I\), determinant \(+1\), 변환 energy invariant를 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- orientation을 자동 추측하지 마라. 이유: 입력 계약에서 필수다.
- degenerate vector를 임의 축으로 대체하지 마라. 이유: 모델 오류를 숨긴다.
- element stiffness를 추가하지 마라. 이유: 다음 kernel step의 책임이다.
+59
View File
@@ -0,0 +1,59 @@
# Step 3: Timoshenko Stiffness Kernel
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/include/fesa/fem/`
- `/include/fesa/model/material.hpp`
- `/include/fesa/model/beam_section.hpp`
- `/docs/formulation/timoshenko-beam-3d.md`가 있으면 전체
## 작업
먼저 `docs/formulation/timoshenko-beam-3d.md`에 자유도 순서, 변형률, 부호,
constitutive matrix, Jacobian과 선택적 감차적분 식을 작성한다. 그 식으로 실제
2절점 3D isoparametric Timoshenko Beam stiffness를 구현한다.
```cpp
struct Beam3D2Input final {
std::array<Vec3, 2> coordinates;
IsotropicElastic material;
BeamSection section;
};
struct Beam3D2Contribution final {
Matrix12 local_stiffness;
Matrix12 global_stiffness;
BeamFrame frame;
};
[[nodiscard]] BeamKernelResult compute_beam3d2(const Beam3D2Input&);
```
- 축·굽힘·비틀림은 2점, 전단은 1점 Gauss 적분한다.
- \(G=E/[2(1+\nu)]\)를 사용한다.
- 먼저 대칭성, 강체운동 zero energy, 축/비틀림/굽힘 해석해, shear-dominant,
세장비 sweep과 좌표회전 invariant 테스트를 실패시킨다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "Beam3D2|Timoshenko|RigidBody" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 정식화 문서를 production code보다 먼저 확정한다.
2. 실패 테스트를 실행해 가짜 matrix로 통과하지 않음을 확인한다.
3. 최소 kernel을 구현하고 focused/full test를 실행한다.
4. 식과 코드의 DOF/component 순서를 대조하고 index를 갱신한다.
## 금지사항
- 닫힌형 가짜 stiffness를 임시로 넣지 마라. 이유: 파이프라인 수치 신뢰성을 훼손한다.
- shear term을 2점 적분하지 마라. 이유: 승인된 selective integration과 다르다.
- 비선형, 워핑, offset 또는 \(I_{yz}\)를 추가하지 마라. 이유: Phase 1 밖이다.
+44
View File
@@ -0,0 +1,44 @@
{
"phases": [
{
"dir": "solver-bootstrap",
"status": "pending"
},
{
"dir": "domain-and-input-skeleton",
"status": "pending"
},
{
"dir": "fem-and-beam-kernel",
"status": "pending"
},
{
"dir": "equation-and-linear-solve",
"status": "pending"
},
{
"dir": "results-and-pipeline",
"status": "pending"
},
{
"dir": "abaqus-subset-completion",
"status": "pending"
},
{
"dir": "deterministic-parallel-assembly",
"status": "pending"
},
{
"dir": "result-contract-completion",
"status": "pending"
},
{
"dir": "beam-reference-qualification",
"status": "pending"
},
{
"dir": "internal-release",
"status": "pending"
}
]
}
+31
View File
@@ -0,0 +1,31 @@
{
"project": "FESA",
"phase": "internal-release",
"steps": [
{
"step": 0,
"name": "release-checklist",
"status": "pending"
},
{
"step": 1,
"name": "cmake-install-package",
"status": "pending"
},
{
"step": 2,
"name": "install-tree-smoke-test",
"status": "pending"
},
{
"step": 3,
"name": "phase1-scale-benchmark",
"status": "pending"
},
{
"step": 4,
"name": "release-evidence-gate",
"status": "pending"
}
]
}
+54
View File
@@ -0,0 +1,54 @@
# Step 0: Release Checklist
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/VALIDATION.md`
- `/docs/HDF5_SCHEMA.md`
- `/docs/ABAQUS_INPUT_SUBSET.md`
- `/CMakePresets.json`
## 작업
packaging 전에 `docs/BUILDING.md`, `docs/INPUT_FORMAT.md`,
`docs/RELEASE_CHECKLIST.md`를 작성한다.
체크리스트는 다음 증거 위치와 command를 포함해야 한다.
- MSVC v143 x64, C++20 및 dependency versions
- Debug/Release configure, build, zero-warning, nonzero CTest count
- flat 및 단일 무변환 Instance example
- HDF5 schema inspection
- 현재 Abaqus displacement/reaction comparison
- synthetic internal-force/stress adapter coverage
- deterministic thread-count test
- 100k-DOF scale measurement
- runtime DLL inventory와 clean install-tree smoke test
PRD section 8 각 항목에 고유 checklist ID를 부여한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug --output-on-failure
```
문서의 모든 command가 현재 target/preset 이름과 일치하고 미제공 Abaqus
내력·응력을 qualification 완료로 표시하지 않아야 한다.
## 검증 절차
1. PRD release criterion을 하나씩 checklist에 매핑한다.
2. 현재 test/target 이름을 CMake에서 재확인한다.
3. 증거가 없는 항목은 pass로 쓰지 않고 미실행 상태로 둔다.
4. index summary에 세 문서와 checklist ID 범위를 기록한다.
## 금지사항
- installer나 외부 고객 SDK를 약속하지 마라. 이유: 내부 배포 범위다.
- evidence 없는 checkbox를 완료 표시하지 마라. 이유: release gate를 왜곡한다.
- per-model metadata 파일을 다시 요구하지 마라. 이유: 승인된 검증 계약과 다르다.
+49
View File
@@ -0,0 +1,49 @@
# Step 1: CMake Install Package
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/BUILDING.md`
- `/docs/RELEASE_CHECKLIST.md`
- `/CMakeLists.txt`
- `/CMakePresets.json`
## 작업
`cmake --install`로 내부 배포용 install tree를 만든다.
- `cmake/install.cmake`, `cmake/FESAConfig.cmake.in`을 추가한다.
- install tree에 `fesa.exe`, `fesa_core` static library, public headers,
CMake package config, required runtime DLL inventory, example input,
`HDF5_SCHEMA.md`, `INPUT_FORMAT.md`, `VALIDATION.md`를 포함한다.
- absolute build path가 install config에 남지 않는 실패 검사부터 작성한다.
- Phase 1 public ABI compatibility를 약속하지 않는다.
## Acceptance Criteria
```powershell
cmake --preset windows-release
cmake --build --preset windows-release
ctest --preset windows-release --output-on-failure
cmake --install out\build\windows-release --config Release --prefix out\package\fesa
Get-ChildItem -Recurse out\package\fesa
```
install tree가 build source tree 밖에서 사용 가능한 상대 경로와 명시적 runtime inventory를
가져야 한다.
## 검증 절차
1. install manifest 검사 실패를 먼저 확인한다.
2. 최소 install/export rule을 구현한다.
3. package tree와 CMake config의 절대 경로 누출을 확인한다.
4. index summary에 install manifest를 기록한다.
## 금지사항
- registry write나 MSI installer를 추가하지 마라. 이유: 배포 범위 밖이다.
- dependency를 package 중 다운로드하지 마라. 이유: 사전 설치 정책 위반이다.
- Debug/Release binary를 혼합하지 마라. 이유: runtime 불일치 위험이 있다.
+44
View File
@@ -0,0 +1,44 @@
# Step 2: Install-tree Smoke Test
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/BUILDING.md`
- `/docs/RELEASE_CHECKLIST.md`
- `/cmake/FESAConfig.cmake.in`
- `/cmake/install.cmake`
## 작업
source/build tree를 참조하지 않는 clean install consumer와 CLI smoke test를 만든다.
- `tests/install/consumer/CMakeLists.txt`, `tests/install/consumer/main.cpp`,
`tests/install/install_tree_smoke.cmake`를 만든다.
- installed `FESAConfig.cmake`로 작은 consumer를 configure/link한다.
- installed CLI의 `--version`, example solve, 생성 HDF5 public inspection을 실행한다.
- source include path나 build library path를 숨긴 상태에서 먼저 실패를 확인한다.
## Acceptance Criteria
```powershell
cmake --preset windows-release
cmake --build --preset windows-release
ctest --preset windows-release -R InstallTreeSmoke --output-on-failure
ctest --preset windows-release --output-on-failure
```
## 검증 절차
1. 설치 전 smoke test 실패를 확인한다.
2. install tree만 사용하도록 test working directory와 environment를 격리한다.
3. consumer link, CLI solve, HDF5 open을 모두 확인한다.
4. 전체 Release test와 index를 갱신한다.
## 금지사항
- source directory include를 fallback으로 넣지 마라. 이유: packaging 결함을 숨긴다.
- PATH의 개발용 `fesa.exe`를 실행하지 마라. 이유: installed binary 검증이 아니다.
- external dependency installer를 만들지 마라. 이유: inventory만 제공한다.
+46
View File
@@ -0,0 +1,46 @@
# Step 3: Phase 1 Scale Benchmark
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/RELEASE_CHECKLIST.md`
- `/include/fesa/analysis/run_solver.hpp`
- `/tests/performance/assembly_benchmark.cpp`
## 작업
약 100,000 DOF의 deterministic Beam chain 모델로 메모리와 시간을 측정하는
`tests/performance/phase1_scale_benchmark.cpp`를 만든다.
- model generation, parsing/Domain build, assembly, PARDISO solve, recovery, HDF5 write
시간을 구분해 출력한다.
- peak working set 또는 Windows에서 재현 가능한 memory metric을 기록한다.
- benchmark는 finite result, equilibrium, expected DOF count와 정상 종료만 assertion한다.
- 임의 성능 기준이나 speedup을 pass 조건으로 만들지 않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-release
.\out\build\windows-release\Release\fesa_phase1_scale_benchmark.exe
ctest --preset windows-release --output-on-failure
```
출력에 모델 크기, 각 stage 시간, memory metric, thread 설정, solver 설정이 포함되어야
한다.
## 검증 절차
1. 작은 model에서 benchmark correctness test를 먼저 실패시킨다.
2. 동일 generator로 목표 크기를 실행한다.
3. 측정값과 환경을 release checklist에 기록한다.
4. index summary에 결과 위치와 실제 DOF count를 기록한다.
## 금지사항
- benchmark를 unit test timeout에 묶지 마라. 이유: 머신 성능에 따라 달라진다.
- 결과 정확성 검사를 생략하지 마라. 이유: 빠른 오답은 성능 증거가 아니다.
- 실제 측정 없이 목표 시간을 만들지 마라. 이유: 요구사항에 근거가 없다.
+57
View File
@@ -0,0 +1,57 @@
# Step 4: Release Evidence Gate
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/VALIDATION.md`
- `/docs/BUILDING.md`
- `/docs/INPUT_FORMAT.md`
- `/docs/RELEASE_CHECKLIST.md`
- `/docs/HDF5_SCHEMA.md`
## 작업
새 실행 증거로 PRD section 8의 내부 배포 수용 조건을 모두 판정한다.
- Debug와 Release configure/build/test를 각각 실행한다.
- test count가 0이 아닌지 확인한다.
- Harness Python self-test를 실행한다.
- reference, determinism, install-tree, HDF5 inspection, scale benchmark 결과를
checklist ID에 연결한다.
- 현재 검증 범위가 Abaqus displacement/reaction이며 내력/응력은 synthetic adapter
coverage임을 release note에 명시한다.
- 하나라도 증거가 없거나 실패하면 release를 완료 처리하지 말고 `blocked` 또는
`error`로 기록한다.
## Acceptance Criteria
```powershell
uv run --with pytest python -m pytest -v -rs
cmake --preset windows-debug
cmake --build --preset windows-debug
ctest --preset windows-debug --output-on-failure
cmake --preset windows-release
cmake --build --preset windows-release
ctest --preset windows-release --output-on-failure
.\out\build\windows-release\Release\fesa_phase1_scale_benchmark.exe
cmake --install out\build\windows-release --config Release --prefix out\package\fesa
```
모든 명령이 종료 코드 0이고 release checklist의 각 criterion이 해당 출력 또는
validation report 항목으로 추적되어야 한다.
## 검증 절차
1. 위 명령을 생략 없이 새로 실행한다.
2. warning, test count, reference maximum error, benchmark와 install manifest를 기록한다.
3. 성공한 경우에만 step/phase를 `completed`로 갱신한다.
4. 미제공 외부 데이터가 필요하면 범위를 확대하지 말고 정확한 blocker를 기록한다.
## 금지사항
- 실패 테스트를 disable하거나 제외하지 마라. 이유: release 증거를 조작한다.
- 구현되지 않은 Abaqus 내력/응력 qualification을 선언하지 마라. 이유: golden이 없다.
- 자동 push하지 마라. 이유: 사용자가 `--push`를 명시한 경우에만 허용된다.
@@ -0,0 +1,21 @@
{
"project": "FESA",
"phase": "result-contract-completion",
"steps": [
{
"step": 0,
"name": "beam-element-end-recovery",
"status": "pending"
},
{
"step": 1,
"name": "complete-result-contract",
"status": "pending"
},
{
"step": 2,
"name": "self-contained-hdf5",
"status": "pending"
}
]
}
@@ -0,0 +1,56 @@
# Step 0: Beam Element-end Recovery
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/formulation/timoshenko-beam-3d.md`
- `/include/fesa/elements/beam/beam3d2.hpp`
- `/include/fesa/model/beam_section.hpp`
## 작업
요소 양 끝 절점에서 section strain/resultant, 도심 응력과 선택 회복점 축응력을
계산한다.
```cpp
struct BeamSectionResult final {
double xi;
NodeId end_node;
std::array<double, 6> section_strain;
std::array<double, 6> section_force;
double centroid_sigma_xx;
std::vector<double> sigma_xx;
};
[[nodiscard]] std::vector<BeamSectionResult> recover_beam3d2(
const Beam3D2Input&,
std::span<const double, 12> element_displacement,
std::span<const std::array<double, 2>> recovery_points);
```
- component 순서는 \(N,V_y,V_z,T,M_y,M_z\)다.
- `centroid_sigma_xx=N/A`; 회복점은 axial+bending \(\sigma_{xx}\)만 계산한다.
- 순수 축/비틀림/각 축 굽힘/이축 굽힘, 양 끝 부호, 회복점 순서를 먼저 테스트한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "BeamRecovery|CentroidStress|SectionForce" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. hand-calculated recovery test 실패를 확인한다.
2. stiffness와 같은 frame/부호 convention을 재사용한다.
3. 도심에서 bending contribution이 0인지 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- point shear/torsional stress를 출력하지 마라. 이유: 단면 형상 정보가 부족하다.
- Abaqus column 이름을 element kernel에 넣지 마라. 이유: validation adapter 책임이다.
- 절점별 내력 부호를 임의 절댓값으로 바꾸지 마라. 이유: 평형 검증을 깨뜨린다.
@@ -0,0 +1,55 @@
# Step 1: Complete Result Contract
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/results/result_database.hpp`
- `/include/fesa/elements/beam/beam3d2.hpp`
- `/include/fesa/model/entity_origin.hpp`
## 작업
ResultDatabase에 element-end Beam 결과, local frame, model provenance와 diagnostics를
추가한다.
```cpp
struct BeamElementFrame final {
ElementId element;
EntityOrigin origin;
BeamFrame local_frame;
std::array<BeamSectionResult, 2> end_results;
};
struct ElementFrame final {
std::vector<BeamElementFrame> beams;
};
```
- `ResultFrame``ElementFrame element`를 추가한다.
- node/element origin, field coordinate system, component labels와 ordering을 명시한다.
- duplicate element/end node, wrong connectivity, nonfinite result, mismatched recovery
point count를 실패 테스트로 먼저 작성한다.
- LinearStaticAnalysis가 production recovery를 호출해 ResultDatabase를 채우게 한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "CompleteResultContract|ElementFrame" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. result validation과 analysis integration test 실패를 확인한다.
2. 의미 타입과 orchestration만 수정한다.
3. element-end/node connectivity와 origin 보존을 assertion한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- CSV-specific field를 ResultDatabase에 넣지 마라. 이유: 결과 semantic 모델을 오염시킨다.
- history/velocity를 빈 구조로 추가하지 마라. 이유: Phase 1에서 사용하지 않는다.
- recovery를 analysis 코드에 복제하지 마라. 이유: element kernel 계약을 재사용해야 한다.
@@ -0,0 +1,47 @@
# Step 2: Self-contained HDF5
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/HDF5_SCHEMA.md`
- `/include/fesa/results/result_database.hpp`
- `/include/fesa/io/hdf5/`
## 작업
HDF5 schema와 reader/writer를 완성해 파일 하나로 모델·설정·전체 Phase 1 결과를
재구성할 수 있게 한다.
- model: coordinates, connectivity, Part/Instance/local labels, sets, materials,
sections, orientation, applied shear values와 input/default source
- analysis: single step, BC, load, solver settings
- results: nodal displacement/reaction, Beam local frame, 양 끝 section
strain/force, centroid `Sxx`, recovery-point `Sxx`, diagnostics
- `docs/HDF5_SCHEMA.md`의 dataset rank/type/component/coordinate attribute를 먼저
갱신한다.
- public reader만으로 모든 항목을 재구성하는 실패 통합 테스트를 작성한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R SelfContainedHdf5 --output-on-failure
h5ls -r .\out\build\windows-debug\Testing\Temporary\fesa-self-contained.h5
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. complete schema round-trip test 실패를 확인한다.
2. schema version 호환성 규칙을 문서와 코드에 함께 반영한다.
3. public reader와 h5ls로 구조를 독립 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- 원본 `.inp` 경로만 저장하고 모델 데이터를 생략하지 마라. 이유: 자기완결 계약이다.
- HDF5 object를 result model에 노출하지 마라. 이유: adapter 경계를 깨뜨린다.
- schema를 무버전 변경하지 마라. 이유: reader 호환성을 잃는다.
+26
View File
@@ -0,0 +1,26 @@
{
"project": "FESA",
"phase": "results-and-pipeline",
"steps": [
{
"step": 0,
"name": "result-database",
"status": "pending"
},
{
"step": 1,
"name": "minimal-hdf5-schema",
"status": "pending"
},
{
"step": 2,
"name": "linear-static-analysis",
"status": "pending"
},
{
"step": 3,
"name": "cli-pipeline-integration",
"status": "pending"
}
]
}
+60
View File
@@ -0,0 +1,60 @@
# Step 0: Result Database
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/model/domain.hpp`
- `/include/fesa/core/diagnostic.hpp`
## 작업
HDF5와 독립적인 최소 Phase 1 result semantic model을 만든다.
```cpp
struct NodalFrame final {
std::vector<NodeId> node_ids;
std::vector<std::array<double, 6>> displacement;
std::vector<std::array<double, 6>> reaction;
};
struct ResultFrame final {
double step_time;
NodalFrame nodal;
std::vector<Diagnostic> diagnostics;
};
struct ResultStep final {
std::string name;
std::vector<ResultFrame> frames;
};
struct ResultDatabase final {
std::string schema_version;
std::vector<ResultStep> steps;
};
```
- size mismatch, duplicate node, nonfinite field, duplicate step/frame을 실패 테스트로
먼저 작성한다.
- 이 step에는 element result를 미리 만들지 않는다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "ResultDatabase|NodalFrame" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. 유효/무효 result model 테스트를 먼저 실행한다.
2. 불변 읽기 계약에 필요한 최소 저장만 구현한다.
3. HDF5 include가 없는지 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- HDF5 handle을 result model에 넣지 마라. 이유: semantic/adaptor 경계를 깨뜨린다.
- velocity, acceleration, temperature를 추가하지 마라. 이유: Phase 1에서 사용하지 않는다.
- 빈 element output hierarchy를 만들지 마라. 이유: 필요한 phase에서만 실체화한다.
+56
View File
@@ -0,0 +1,56 @@
# Step 1: Minimal HDF5 Schema
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/results/result_database.hpp`
- `/include/fesa/model/domain.hpp`
- `/cmake/FesaDependencies.cmake`
## 작업
먼저 `docs/HDF5_SCHEMA.md`에 schema `1.0.0`의 최소 group/dataset/attribute 계약을
작성하고 HDF5 writer/reader round trip을 구현한다.
```cpp
struct Hdf5ReadResult final {
std::optional<ResultDatabase> database;
std::vector<Diagnostic> diagnostics;
};
[[nodiscard]] std::vector<Diagnostic> write_hdf5(
const std::filesystem::path&,
const Domain&,
const ResultDatabase&);
[[nodiscard]] Hdf5ReadResult read_hdf5_results(
const std::filesystem::path&);
```
- schema/version, node origin `(part,instance,local label)`, dense ID map, 좌표,
connectivity, shear property source, nodal displacement/reaction을 round trip한다.
- 먼저 public reader로 모든 값을 재확인하는 실패 테스트를 작성한다.
- 모든 `hid_t`는 move-only RAII wrapper로 관리한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "Hdf5|ResultRoundTrip" --output-on-failure
h5ls -r .\out\build\windows-debug\Testing\Temporary\fesa-round-trip.h5
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. schema 문서를 writer보다 먼저 작성한다.
2. round-trip test 실패를 확인한 뒤 최소 adapter를 구현한다.
3. HDF5 도구와 public reader 결과를 모두 확인한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- global HDF5 handle을 만들지 마라. 이유: 수명과 오류 경계를 훼손한다.
- reference CSV 기능을 추가하지 마라. 이유: validation phase 책임이다.
- schema에 빈 미래 분석 결과를 넣지 마라. 이유: 현재 계약만 저장한다.
+56
View File
@@ -0,0 +1,56 @@
# Step 2: Linear Static Analysis
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/model/domain.hpp`
- `/include/fesa/fem/dof_manager.hpp`
- `/include/fesa/assembly/`
- `/include/fesa/constraints/`
- `/include/fesa/solvers/linear/`
- `/include/fesa/results/result_database.hpp`
## 작업
기존 production 모듈을 조율하는 `LinearStaticAnalysis` lifecycle을 구현한다.
```cpp
struct AnalysisRunResult final {
bool succeeded;
std::optional<ResultDatabase> results;
std::vector<Diagnostic> diagnostics;
};
class LinearStaticAnalysis final {
public:
[[nodiscard]] AnalysisRunResult run(const Domain&) const;
};
```
- parser나 HDF5를 호출하지 않고 이미 검증된 Domain을 입력받는다.
- DofManager, pattern/assembly, BC elimination, PARDISO, full reconstruction,
reaction recovery, nodal ResultDatabase 순서로 실행한다.
- hand-check 가능한 한 요소 Domain으로 변위, 반력, residual을 먼저 테스트한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "LinearStaticAnalysis|StaticEquilibrium" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. analysis test가 연결 누락으로 실패하는 것을 확인한다.
2. orchestration만 구현하고 수치 kernel을 복제하지 않는다.
3. \(Ku-f-r\) 평형과 finite result를 검사한다.
4. 전체 테스트와 index를 갱신한다.
## 금지사항
- CLI option parsing을 analysis에 넣지 마라. 이유: application 경계를 깨뜨린다.
- nonlinear loop나 여러 step을 추가하지 마라. 이유: Phase 1 범위 밖이다.
- test-only solver 경로를 만들지 마라. 이유: production pipeline을 검증해야 한다.
+60
View File
@@ -0,0 +1,60 @@
# Step 3: CLI Pipeline Integration
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/include/fesa/io/abaqus/parser.hpp`
- `/include/fesa/io/abaqus/semantic_mapper.hpp`
- `/include/fesa/analysis/linear_static_analysis.hpp`
- `/include/fesa/io/hdf5/writer.hpp`
- `/src/fesa/cli/main.cpp`
## 작업
flat minimal fixture를 입력부터 HDF5까지 실행하는 public application 경로를 연결한다.
```cpp
struct AnalysisRequest final {
std::filesystem::path input_path;
std::filesystem::path output_path;
};
[[nodiscard]] AnalysisRunResult run_solver(const AnalysisRequest&);
```
CLI 계약:
```text
fesa solve <model.inp> --output <results.h5>
fesa --version
```
- 먼저 `MinimalCantileverPipeline` 통합 테스트를 작성한다.
- test는 `run_solver` 또는 CLI와 public HDF5 reader만 사용한다.
- 성공 파일의 ID, finite displacement, reaction/equilibrium diagnostic과 schema path,
실패 입력의 nonzero exit 및 source diagnostic을 검증한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R MinimalCantileverPipeline --output-on-failure
.\out\build\windows-debug\Debug\fesa.exe solve tests\fixtures\abaqus\minimal_cantilever.inp --output out\minimal-cantilever.h5
h5ls -r out\minimal-cantilever.h5
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. end-to-end test 실패를 확인한다.
2. parser→Domain→analysis→writer만 조율한다.
3. command와 public reader로 산출물을 재검증한다.
4. 이 milestone을 수치 자격 완료로 표시하지 말고 index를 갱신한다.
## 금지사항
- hierarchical sample의 전체 keyword를 우회 처리하지 마라. 이유: 다음 input phase다.
- fake stiffness/result를 쓰지 마라. 이유: 실제 pipeline 검증을 무효화한다.
- CLI에 solver 내부 구현을 넣지 마라. 이유: core/library 재사용성을 훼손한다.
+21
View File
@@ -0,0 +1,21 @@
{
"project": "FESA",
"phase": "solver-bootstrap",
"steps": [
{
"step": 0,
"name": "cmake-project-scaffold",
"status": "pending"
},
{
"step": 1,
"name": "dependency-smoke-tests",
"status": "pending"
},
{
"step": 2,
"name": "core-ids-and-diagnostics",
"status": "pending"
}
]
}
+62
View File
@@ -0,0 +1,62 @@
# Step 0: CMake Project Scaffold
## 읽어야 할 파일
먼저 아래 파일을 모두 읽고 저장소 계약을 파악하라.
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/HARNESS.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/.harness/config.example.json`
## 작업
C++20/MSVC x64 프로젝트의 최소 실행 가능한 build/test 뼈대를 만든다.
- `CMakeLists.txt`, `CMakePresets.json`, `cmake/FesaDependencies.cmake`,
`.harness/config.json`, `tests/CMakeLists.txt`를 만든다.
- 실제 target은 `fesa_core` 정적 라이브러리와 `fesa` CLI 두 개만 만든다.
- `include/fesa/core/version.hpp`, `src/fesa/core/version.cpp`,
`src/fesa/cli/main.cpp`에 다음 계약을 구현한다.
```cpp
namespace fesa {
[[nodiscard]] std::string_view version() noexcept;
}
```
- CLI는 이 step에서 `fesa --version`만 처리한다.
- 먼저 `VersionCommand` CTest를 등록해 실패를 확인한 뒤 최소 구현한다.
- `windows-debug`, `windows-release` configure/build/test preset을 정의한다.
- build 산출물은 `out/build/<preset>` 아래에만 둔다.
- MSVC가 아니거나 x64가 아니면 configure 단계에서 명확히 실패시킨다.
## Acceptance Criteria
```powershell
uv run --with pytest python -m pytest -v -rs
cmake --preset windows-debug
cmake --build --preset windows-debug
ctest --preset windows-debug -R VersionCommand --output-on-failure
ctest --preset windows-debug --output-on-failure
```
`fesa --version`은 비어 있지 않은 FESA 버전을 출력하고 종료 코드 0을 반환해야 한다.
CTest는 0개가 아니어야 한다.
## 검증 절차
1. 테스트가 구현 전 실패하는 것을 확인한다.
2. Acceptance Criteria 명령을 새로 실행한다.
3. MSVC/C++20/x64와 산출물 경로를 확인한다.
4. 성공 시 index의 step을 `completed`로 바꾸고 생성 파일을 summary에 기록한다.
5. 도구가 없으면 자동 설치하지 말고 `blocked`와 정확한 누락 항목을 기록한다.
## 금지사항
- 외부 패키지를 다운로드하지 마라. 이유: 사전 설치 의존성 정책을 위반한다.
- MKL, TBB, HDF5 기능을 구현하지 마라. 이유: 다음 step의 독립 범위다.
- 빈 미래 모듈을 만들지 마라. 이유: Phase 1 최소 실체화 원칙을 위반한다.
+55
View File
@@ -0,0 +1,55 @@
# Step 1: Dependency Smoke Tests
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/HARNESS.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/CMakeLists.txt`
- `/CMakePresets.json`
- `/cmake/FesaDependencies.cmake`
- `/.harness/config.json`
- `/tests/CMakeLists.txt`
이전 step의 CMake target과 preset을 그대로 확장하라.
## 작업
사전 설치된 oneMKL, oneTBB, HDF5 C API, GoogleTest/GoogleMock을 CMake imported
target으로 찾고 링크 계약을 검증한다.
- `tests/unit/dependencies/dependency_smoke_test.cpp`를 먼저 작성한다.
- 테스트는 MKL의 작은 vector 연산, TBB의 제한된 parallel loop, HDF5 임시 파일
생성·닫기, GoogleTest 실행을 확인한다.
- `FesaDependencies.cmake``MKL::MKL`, TBB imported target, HDF5 C target,
GoogleTest target을 제공해야 한다.
- oneMKL은 LP64, dynamic link, TBB threading 조합을 사용한다.
- runtime DLL 또는 architecture 불일치는 configure diagnostic으로 보고한다.
## Acceptance Criteria
```powershell
cmake --preset windows-debug
cmake --build --preset windows-debug
ctest --preset windows-debug -R DependencySmoke --output-on-failure
ctest --preset windows-debug --output-on-failure
```
네 의존성을 실제 호출하는 smoke test가 통과해야 하며 새 MSVC 경고가 없어야 한다.
## 검증 절차
1. smoke test를 먼저 추가하고 link 또는 실행 실패를 확인한다.
2. dependency discovery와 target link만 최소 수정한다.
3. 전체 configure/build/test를 새로 실행한다.
4. 성공 시 정확한 imported target과 탐색 파일을 summary에 기록한다.
5. 패키지나 MSVC가 없으면 세 차례 임의 수정하지 말고 `blocked`로 종료한다.
## 금지사항
- FetchContent, vcpkg, Conan 또는 다운로드를 추가하지 마라. 이유: ADR-002 위반이다.
- vendor 절대경로를 public header에 노출하지 마라. 이유: backend 격리를 깨뜨린다.
- solver 기능을 구현하지 마라. 이유: 이 step은 build dependency 계약만 다룬다.
+72
View File
@@ -0,0 +1,72 @@
# Step 2: Core IDs and Diagnostics
## 읽어야 할 파일
- `/AGENTS.md`
- `/docs/PRD.md`
- `/docs/ARCHITECTURE.md`
- `/docs/ADR.md`
- `/docs/superpowers/plans/2026-07-29-fesa-phase-1.md`
- `/CMakeLists.txt`
- `/tests/CMakeLists.txt`
- `/include/fesa/core/version.hpp`
## 작업
외부 라이브러리에 의존하지 않는 `core` 값 타입을 TDD로 구현한다.
- 생성 파일:
`include/fesa/core/entity_id.hpp`, `vec3.hpp`, `source_location.hpp`,
`diagnostic.hpp`, `status.hpp`와 대응 테스트
- 인터페이스:
```cpp
template<class Tag>
class EntityId final {
public:
explicit constexpr EntityId(std::int64_t value);
[[nodiscard]] constexpr std::int64_t value() const noexcept;
auto operator<=>(const EntityId&) const = default;
};
struct Vec3 final { double x; double y; double z; };
struct SourceLocation final {
std::filesystem::path file;
std::size_t line;
std::size_t column;
};
enum class DiagnosticStage { io, syntax, semantic, model, equation, solver, results, validation };
enum class Severity { warning, error };
struct Diagnostic final {
DiagnosticStage stage;
Severity severity;
std::string code;
std::string message;
std::optional<SourceLocation> source;
};
```
- typed ID의 잘못된 암시 변환, 음수 ID, nonfinite vector와 diagnostic source 보존을
실패 테스트로 먼저 고정한다.
## Acceptance Criteria
```powershell
cmake --build --preset windows-debug
ctest --preset windows-debug -R "Core|Diagnostic|EntityId" --output-on-failure
ctest --preset windows-debug --output-on-failure
```
## 검증 절차
1. production header 전에 실패하는 GoogleTest를 작성한다.
2. 최소 값 타입만 구현한다.
3. focused test와 전체 CTest를 실행한다.
4. `core`가 MKL, TBB, HDF5, Abaqus header를 include하지 않는지 확인한다.
5. index와 summary를 갱신한다.
## 금지사항
- 단위 변환 시스템을 만들지 마라. 이유: FESA는 일관 단위계만 사용한다.
- 범용 reflection이나 serialization을 만들지 마라. 이유: 요구되지 않았다.
- equation ID를 정의하지 마라. 이유: `DofManager` 단계의 책임이다.