# 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 end_node_label; }; struct ComparisonSample final { ReferenceQuantity quantity; ResultPosition position; std::vector reference; std::vector actual; Tolerance tolerance; }; struct ComparisonReport final { bool passed; double maximum_normalized_error; std::vector failures; }; [[nodiscard]] ComparisonReport compare_samples( std::span); ``` 각 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 경계다.