diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index d6c9078..6fcfdf5 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -1,192 +1,290 @@ # FESA Session Handoff -## 1. 문서 목적 +## 1. 문서 목적과 기준 -이 문서는 results-and-pipeline과 abaqus-subset-completion 완료 후 새 세션에서 -deterministic-parallel-assembly Phase를 바로 시작하기 위한 인수인계 기록이다. -요구사항과 설계의 기준은 이 문서가 아니라 다음 파일이다. +이 문서는 `deterministic-parallel-assembly` 완료 후 새 세션에서 +`result-contract-completion` Phase를 바로 시작하기 위한 인수인계 기록이다. +요구사항과 설계의 최종 기준은 다음 파일이다. -- /AGENTS.md -- /docs/PRD.md -- /docs/ARCHITECTURE.md -- /docs/ADR.md -- /docs/HARNESS.md -- /docs/ABAQUS_INPUT_SUBSET.md -- /docs/HDF5_SCHEMA.md -- /phases/deterministic-parallel-assembly/index.json -- /phases/deterministic-parallel-assembly/step0.md부터 step2.md +- `AGENTS.md` +- `docs/PRD.md` +- `docs/ARCHITECTURE.md` +- `docs/ADR.md` +- `docs/HARNESS.md` +- `docs/formulation/timoshenko-beam-3d.md` +- `docs/HDF5_SCHEMA.md` +- `phases/result-contract-completion/index.json` +- `phases/result-contract-completion/step0.md`부터 `step2.md` -내용이 충돌하면 AGENTS.md, 제품·아키텍처 문서와 phases/의 현재 상태를 우선한다. -이 문서는 현재 구현, 검증 baseline과 실행환경에서 특히 놓치기 쉬운 계약을 +내용이 충돌하면 위 기준 문서와 `phases/`의 현재 metadata를 우선한다. 이 문서는 +현재 구현, 검증 baseline, 다음 Phase에서 먼저 정렬해야 할 계약과 실행환경을 보충한다. -## 2. 현재 저장소 상태 +## 2. 현재 저장소와 Phase 상태 -2026-08-01 확인 기준: +2026-08-02 확인 기준: -- 기준 브랜치: dev -- 이 HANDOFF 작성 직전 구현 HEAD: cbb621bb282a301b6708d95ff697b40644188e46 -- cbb621b는 abaqus-subset-completion의 최종 보완 commit이다. -- 이 문서는 cbb621b 다음 commit으로 dev에 기록하고 origin/dev에 함께 push한다. - 새 세션에서는 아래 명령으로 실제 동기화 상태를 다시 확인한다. +- 기준 브랜치: `dev` +- 이 HANDOFF 갱신 직전 구현 HEAD: + `7d52247d6c6180ac4f4dab2e6ecb0ee1be2608d0` +- 갱신 직전 `dev`는 `origin/dev`보다 9개 commit 앞서 있었고 작업 트리는 clean이었다. +- `feat-deterministic-parallel-assembly`는 `dev`에 fast-forward 병합한 뒤 삭제했다. - 완료 Phase: - - solver-bootstrap - - domain-and-input-skeleton - - fem-and-beam-kernel - - equation-and-linear-solve - - results-and-pipeline - - abaqus-subset-completion -- 다음 Phase: deterministic-parallel-assembly -- 다음 Step: 0 - canonical-contribution-order -- deterministic-parallel-assembly의 Step 0~2는 모두 pending이다. -- 후속 Phase인 result-contract-completion, beam-reference-qualification, - internal-release도 아직 pending이다. -- feat-abaqus-subset-completion은 dev에 fast-forward 병합된 뒤 삭제되었다. -- 이 문서 갱신 전 작업 트리는 clean이었다. + - `solver-bootstrap` + - `domain-and-input-skeleton` + - `fem-and-beam-kernel` + - `equation-and-linear-solve` + - `results-and-pipeline` + - `abaqus-subset-completion` + - `deterministic-parallel-assembly` +- 다음 Phase: `result-contract-completion` +- 다음 Step: Step 0 `beam-element-end-recovery` +- `result-contract-completion`의 Step 0~2는 모두 pending이다. +- 후속 Phase `beam-reference-qualification`과 `internal-release`도 pending이다. -새 세션에서 원격에 맞추기 위한 reset, rebase, force push를 수행하지 않는다. -먼저 다음 상태를 확인하고 dev와 origin/dev가 다르면 원인을 조사한다. +이 문서는 위 9개 구현/phase commit 다음 commit으로 `dev`에 기록하고 모두 +`origin/dev`에 push한다. 새 세션에서는 reset, rebase 또는 force push로 상태를 +맞추지 말고 먼저 실제 동기화 상태를 확인한다. - git switch dev - git status --short --branch - git rev-parse HEAD - git rev-parse origin/dev - git rev-list --left-right --count origin/dev...dev +```powershell +git switch dev +git status --short --branch +git rev-parse HEAD +git rev-parse origin/dev +git rev-list --left-right --count origin/dev...dev +``` -## 3. 완료된 results-and-pipeline +이번에 함께 push할 선행 commit은 다음과 같다. -Phase metadata는 /phases/results-and-pipeline/index.json에 기록되어 있으며 Step -0~3이 모두 completed다. +```text +40a7e6c feat(deterministic-parallel-assembly): step 0 — canonical-contribution-order +b9bb439 chore(deterministic-parallel-assembly): step 0 output +6c2e1f3 feat(deterministic-parallel-assembly): step 1 — tbb-element-evaluation +dc6baed chore(deterministic-parallel-assembly): step 1 output +127286c feat(deterministic-parallel-assembly): step 2 — thread-count-determinism +6ee51a8 chore(deterministic-parallel-assembly): step 2 output +6ad9f3c chore(deterministic-parallel-assembly): mark phase completed +ac8d24a test(assembly): cover deterministic kernel failures +7d52247 fix(assembly): stage benchmark TBB runtime +``` + +## 3. 완료된 deterministic parallel assembly + +Phase metadata는 `phases/deterministic-parallel-assembly/index.json`에 기록되어 +있으며 Step 0~2가 모두 completed다. 주요 결과: -- HDF5 API에 의존하지 않는 ResultDatabase, ResultStep, ResultFrame, NodalFrame - semantic model과 results-stage validation -- /docs/HDF5_SCHEMA.md의 schema 1.0.0 계약 -- move-only HDF5 RAII writer와 public reader round trip -- serial assembly, essential BC, PARDISO, full reconstruction과 reaction recovery를 - 조율하는 LinearStaticAnalysis -- free equation이 0인 all-constrained 해석의 PARDISO 우회 -- parser부터 HDF5 writer까지 연결하는 run_solver와 solve CLI -- fesa solve --output 수직 파이프라인 +- `MatrixContribution`의 canonical key를 + `(row, column, element, local_order)`로 고정했다. +- upper-triangle CSR pattern과 값을 한 번의 deterministic serial merge로 만든다. +- oneTBB는 Beam 요소별 `compute_beam3d2` 평가에만 사용한다. +- worker는 요소별 로컬 contribution을 만들고 shared CSR values에 쓰지 않는다. +- `AssemblyOptions.max_threads`와 `grain_size`는 0을 거부한다. +- element storage order와 external label 순열에 관계없이 기존 serial oracle의 + `EntityOrigin` 순서를 보존하도록 canonical rank를 contribution의 `ElementId`에 + 사용한다. +- 여러 Beam kernel failure가 동시에 발생해도 canonical element origin상 첫 오류를 + 반환한다. 해당 독립 review 보완은 mutation test로 RED를 확인한 뒤 추가했다. +- thread count 1, 2, 16에서 10회 반복하며 CSR 구조/값, RHS, displacement와 + reaction의 bit pattern이 동일함을 검증한다. +- `fesa_assembly_benchmark`는 production serial/parallel API를 사용하고 시간과 + element count만 출력한다. speedup은 correctness 조건이 아니다. +- benchmark target의 output directory에 imported `TBB::tbb` runtime DLL을 + post-build로 복사하므로 새 셸의 PATH에 TBB가 없어도 정확한 exe 경로로 실행된다. 관련 파일: -- /include/fesa/results/ -- /src/fesa/results/ -- /include/fesa/io/hdf5/ -- /src/fesa/io/hdf5/ -- /include/fesa/analysis/ -- /src/fesa/analysis/ -- /include/fesa/analysis/run_solver.hpp -- /src/fesa/analysis/run_solver.cpp -- /docs/HDF5_SCHEMA.md -- /tests/integration/pipeline/minimal_cantilever_test.cpp +- `include/fesa/assembly/contribution.hpp` +- `include/fesa/assembly/assembler.hpp` +- `src/fesa/assembly/contribution.cpp` +- `src/fesa/assembly/parallel_assembler.cpp` +- `src/fesa/assembly/serial_assembler.cpp` +- `tests/unit/assembly/serial_assembler_test.cpp` +- `tests/unit/assembly/parallel_assembler_test.cpp` +- `tests/integration/assembly/thread_count_determinism_test.cpp` +- `tests/performance/assembly_benchmark.cpp` -핵심 계약: +유지할 핵심 경계: -- results semantic model은 HDF5 타입이나 handle을 노출하지 않는다. -- 모든 HDF5 resource는 adapter 내부의 move-only RAII wrapper가 소유한다. -- nodal result의 node ID와 6성분 displacement/reaction 배열 순서는 DofManager의 - full-vector 순서와 일치한다. -- 반력은 reduced system이 아니라 원래 full system의 r=Ku-f에서 계산한다. -- all-constrained system은 유효한 analysis case이며 PARDISO order 0 입력으로 - 전달하지 않는다. -- CLI와 run_solver는 parser, semantic mapper, analysis와 writer를 조율하는 - application orchestration 경계다. LinearStaticAnalysis 자체는 parser나 HDF5를 - 호출하지 않는다. -- CTest의 CLI test에는 설치된 oneAPI/HDF5 runtime PATH가 test property로 - 전달된다. 기본 셸 PATH에 해당 디렉터리가 없어도 CTest가 성공해야 한다. +- `assemble_serial`은 계속 bitwise oracle이다. +- TBB task가 끝난 후에만 solver를 호출한다. +- TBB type은 `core`, `model`, `fem`, `elements` public contract에 노출하지 않는다. +- scheduling 순서가 contribution 합산 순서나 오류 선택을 결정하면 안 된다. +- `LinearStaticAnalysis`는 현재도 `assemble_serial`을 호출한다. 다음 Phase 요구사항에 + 없는 parallel backend 선택 기능을 끼워 넣지 않는다. -이 vertical slice 완료는 요소 결과 계약, Abaqus reference 자격 또는 내부 배포 -완료를 의미하지 않는다. +## 4. 현재 결과·HDF5 baseline과 남은 간극 -## 4. 완료된 abaqus-subset-completion +`results-and-pipeline`에서 최소 수직 파이프라인은 완성되어 있다. -Phase metadata는 /phases/abaqus-subset-completion/index.json에 기록되어 있으며 -Step 0~4가 모두 completed다. +- `ResultDatabase -> ResultStep -> ResultFrame -> NodalFrame` semantic model +- serial assembly, essential BC, PARDISO, full displacement reconstruction과 + `r=Ku-f` 반력 복구를 조율하는 `LinearStaticAnalysis` +- all-constrained case의 order-0 PARDISO 우회 +- schema `1.0.0` HDF5 writer와 public reader +- parser부터 HDF5 output까지 연결하는 `run_solver`와 `fesa solve` -주요 결과: +현재 구현의 정확한 한계: -- /docs/ABAQUS_INPUT_SUBSET.md에 Phase 1 입력 계약을 명문화 -- public parser/mapper fixture matrix를 74 cases로 확대 -- strict keyword scope, parameter form, data ownership과 정확한 source diagnostic -- Part/Assembly의 명시적, GENERATE, nested, forward set resolution -- flat mesh 또는 좌표변환 없는 단일 Part/Assembly/Instance 선택 -- 전역 material, Part-local Beam section과 ELSET assignment -- 명시적 transverse shear와 Phase 1 기본값 Asy=Asz=5A/6, SCF=0 -- 단일 Step/Static, Boundary, Cload와 명시적 no-op directive -- active Part뿐 아니라 inactive Part의 NODE, ELEMENT, section record와 reference - 유효성 검증 +- `ResultFrame`은 `step_time`, nodal displacement/reaction, diagnostics만 가진다. +- node/element `EntityOrigin`, field 좌표계, component label/order가 semantic result에 + 명시되어 있지 않다. +- Beam section strain/resultant, local frame, centroid/recovery-point stress가 없다. +- `LinearStaticAnalysis`는 nodal result만 채우며 element recovery를 호출하지 않는다. +- HDF5 schema `1.0.0`은 node 좌표·origin, Beam connectivity/section ID, 적용된 + shear area/source와 nodal result만 저장한다. +- HDF5 reader의 model은 adapter 전용 `Hdf5ModelSnapshot`이며 완전한 model/analysis + 재구성 계약이 아니다. +- material 전체 속성, sets, section 전체 속성/orientation/recovery points, + step BC/load/solver settings, element result와 diagnostics는 파일에 없다. +- writer는 non-empty frame diagnostics를 + `hdf5.unsupported_result_diagnostics`로 거부한다. 관련 파일: -- /docs/ABAQUS_INPUT_SUBSET.md -- /include/fesa/io/abaqus/active_input.hpp -- /include/fesa/io/abaqus/set_resolver.hpp -- /src/fesa/io/abaqus/parser.cpp -- /src/fesa/io/abaqus/active_input.cpp -- /src/fesa/io/abaqus/set_resolver.cpp -- /src/fesa/io/abaqus/semantic_mapper.cpp -- /tests/fixtures/abaqus/contract.tsv -- /tests/unit/io/abaqus/ -- /tests/integration/io/minimal_deck_to_domain_test.cpp +- `include/fesa/results/result_database.hpp` +- `src/fesa/results/result_database.cpp` +- `include/fesa/analysis/linear_static_analysis.hpp` +- `src/fesa/analysis/linear_static_analysis.cpp` +- `include/fesa/io/hdf5/writer.hpp` +- `src/fesa/io/hdf5/writer.cpp` +- `docs/HDF5_SCHEMA.md` +- `tests/unit/results/result_database_test.cpp` +- `tests/unit/analysis/linear_static_analysis_test.cpp` +- `tests/integration/io/hdf5_results_test.cpp` +- `tests/integration/pipeline/minimal_cantilever_test.cpp` -특히 유지할 계약: +이 간극을 `result-contract-completion`에서만 필요한 만큼 채운다. -- 사용되지 않는 Part는 파싱·record/reference validation하지만 Domain에는 넣지 않는다. -- NODE와 ELEMENT data row의 field 수는 정확해야 한다. -- enum 값 B31과 GENERAL은 대소문자를 구분하지 않는다. -- 계층형 Step의 Boundary/Cload target은 Assembly node set으로 해석한다. -- 모든 active B31 element만 정확히 하나의 section assignment를 가져야 한다. - inactive Part의 완전한 해석 가능성을 요구하도록 범위를 넓히지 않는다. -- missing_section diagnostic은 element keyword가 아니라 해당 element data row를 - source로 사용한다. -- unsupported keyword/parameter를 일반 ignore 경로로 숨기지 않는다. -- Heading, Preprint, Restart, Output만 문서화된 조건에서 no-op으로 허용한다. +## 5. 다음 Phase 목표와 Step 순서 -최종 독립 review에서 Critical, Important, Minor finding은 모두 0건이었다. +### Step 0 - beam-element-end-recovery -## 5. 현재 serial assembly oracle +- 두 요소 끝의 section strain과 section resultant를 계산한다. +- strain 순서는 + `(epsilon, gamma_y, gamma_z, kappa_x, kappa_y, kappa_z)`, force 순서는 + `(N, Vy, Vz, T, My, Mz)`로 고정한다. +- centroid stress는 `N/A`, recovery point `(y,z)`의 stress는 axial+bending + `sigma_xx`만 계산한다. +- 순수 축, 비틀림, 각 축 굽힘, 이축 굽힘, 양 끝 부호와 입력 recovery-point 순서를 + hand calculation으로 먼저 고정한다. +- stiffness와 동일한 `BeamFrame`, DOF, 회전 및 부호 convention을 재사용한다. -다음 Phase가 변경할 핵심 코드는 현재 /src/fesa/assembly/serial_assembler.cpp 한 -파일에 private helper로 모여 있다. +Focused acceptance: -현재 흐름: +```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. 모든 full DOF의 diagonal을 포함하는 upper-triangle CSR sparsity pattern 생성 -2. 각 Beam 요소의 compute_beam3d2 호출 -3. local upper triangle 78개를 NumericContribution으로 수집 -4. row, column, EntityOrigin, local_order 순으로 정렬 -5. 같은 row/column을 고정된 순서로 합산 -6. nodal load를 full force vector로 조립 +### Step 1 - complete-result-contract -관련 public 계약: +- `BeamElementFrame`에 element ID/origin, local frame과 두 끝 + `BeamSectionResult`를 저장한다. +- `ResultFrame`에 `ElementFrame`을 추가한다. +- node/element provenance, field 좌표계와 component label/order를 semantic contract에 + 명시한다. +- duplicate element/end node, wrong connectivity, nonfinite value와 mismatched + recovery-point count를 validation에서 거부한다. +- `LinearStaticAnalysis`가 production Beam recovery API를 호출해 element result를 + 채운다. recovery 수식을 analysis에 복제하지 않는다. -- /include/fesa/assembly/symmetric_csr.hpp -- /include/fesa/assembly/equation_system.hpp -- /include/fesa/assembly/serial_assembler.hpp -- /src/fesa/assembly/serial_assembler.cpp -- /tests/unit/assembly/serial_assembler_test.cpp +Focused acceptance: -현재 테스트가 고정하는 oracle: +```powershell +cmake --build --preset windows-debug +ctest --preset windows-debug -R "CompleteResultContract|ElementFrame" --output-on-failure +ctest --preset windows-debug --output-on-failure +``` -- SymmetricCsr는 0-based upper triangle만 저장한다. -- row_offsets와 column_indices는 유효하며 각 row의 column이 strictly increasing이다. -- 연결되지 않은 node DOF도 값 0의 diagonal entry를 갖는다. -- element storage order와 external label 순열이 결과를 바꾸지 않는다. -- 1 + 1 + 1e16 규모의 contribution은 EntityOrigin 순으로 합산한 bit pattern을 - 고정한다. -- Beam kernel failure를 0 contribution으로 바꾸지 않고 assembly failure로 - 전달한다. -- full force vector의 load accumulation도 기존 결과와 같아야 한다. +### Step 2 - self-contained-hdf5 -parallel 구현을 이유로 이 serial oracle을 먼저 변경하거나 tolerance 비교로 -약화하지 않는다. +- 구현보다 먼저 `docs/HDF5_SCHEMA.md`에 새 version과 모든 dataset의 type, rank, + shape, component/coordinate attributes를 확정한다. +- 파일 하나로 model, single-step analysis settings와 모든 Phase 1 result를 + 재구성한다. +- model에는 coordinates/connectivity/origin, sets, materials, section 전체 속성, + orientation, recovery points와 적용 shear 값/source를 포함한다. +- analysis에는 step, BC, load와 solver settings를 포함한다. +- results에는 nodal displacement/reaction, Beam local frame, 두 끝 strain/force, + centroid/recovery-point `Sxx`와 diagnostics를 포함한다. +- public reader round trip과 `h5ls`로 구조를 독립 검증한다. -## 6. 검증된 baseline과 개발환경 +Focused acceptance: -2026-08-01 현재 확인한 도구: +```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 +``` + +## 6. 구현 전에 정렬할 설계점 + +아래는 범위 확장이 아니라 Step 문서와 현재 타입 사이에서 테스트 전에 명시적으로 +결정해야 할 최소 계약이다. + +1. `end_node`의 소유권 + - Step 0 초안의 `BeamSectionResult`에는 `NodeId end_node`가 있지만 제시된 + `recover_beam3d2(const Beam3D2Input&, ...)` 입력에는 Node ID가 없다. + - 가짜 ID를 만들지 않는다. recovery API가 node IDs를 받게 할지, kernel은 + end ordinal/`xi`만 반환하고 orchestration이 실제 NodeId를 붙일지 최소 설계를 + 정한 뒤 테스트로 고정한다. + +2. 끝점 strain/resultant와 부호 + - `docs/formulation/timoshenko-beam-3d.md`의 국부 DOF, shear strain, curvature와 + `sigma_xx=E(epsilon+z*kappa_y-y*kappa_z)`를 기준으로 한다. + - section resultant의 양의 방향과 element nodal resisting-force 방향을 혼동하지 + 않는다. 끝값에 임의 절댓값이나 후처리 sign flip을 적용하지 않는다. + +3. Recovery point 계약 + - `BeamSection.recovery_points`의 `(y,z)` 순서와 입력 순서를 보존한다. + - 빈 목록의 유효성, 두 끝의 expected count와 nonfinite coordinate/result 처리를 + result validation 및 round-trip test에서 명시한다. + - 단면 형상 정보가 없으므로 point shear/torsional stress를 추정하지 않는다. + +4. Result provenance와 component metadata + - semantic result는 Abaqus/CSV/HDF5 명칭이나 handle에 의존하지 않는다. + - node와 element origin, local/global coordinate system, component ordering을 + 중복된 문자열 상수로 흩뜨리지 않을 최소 표현을 선택한다. + +5. HDF5 version과 reader 반환 계약 + - 현재 `1.0.0`은 required object의 의미/형상/type을 같은 major에서 바꾸지 않는 + 계약이다. 완전한 schema를 무버전으로 덮어쓰지 말고 version 정책을 문서와 + reader/writer test에 함께 반영한다. + - public reader가 `Domain` 자체를 반환할지 완전한 serialization snapshot을 + 반환할지는 아키텍처 경계를 확인해 결정하되, 원본 `.inp` 경로에 기대지 않고 + 모든 요구 항목을 재구성할 수 있어야 한다. + +6. Diagnostics와 analysis settings + - 현재 diagnostics는 semantic frame에 있지만 HDF5 writer가 non-empty 값을 + 거부한다. stage/severity/code/message/source의 손실 없는 저장 계약을 먼저 + 정한다. + - solver settings는 실제 Phase 1 실행 설정만 저장한다. 사용하지 않는 미래 + backend/history/dynamic 설정을 빈 구조로 추가하지 않는다. + +## 7. 아키텍처와 범위 경계 + +- `core`, `model`, `fem`, `elements`는 Abaqus, HDF5, MKL 및 TBB API에 의존하지 않는다. +- Beam kernel에는 Abaqus output column 이름이나 CSV-specific field를 넣지 않는다. +- `ResultDatabase`에는 HDF5 object/handle 또는 serialization 전용 type을 노출하지 + 않는다. +- HDF5 resource는 adapter의 move-only RAII wrapper 내부에 둔다. +- DofManager가 DOF와 equation mapping을 계속 단독 소유한다. +- analysis는 production recovery API를 조율하고 수식을 복제하지 않는다. +- 기존 parser/model validation/solver 경로를 test helper로 우회하지 않는다. +- 실제 두 번째 구현이 생기기 전에는 generic registry나 backend hierarchy를 만들지 + 않는다. +- 이번 Phase에서 Abaqus CSV mapping, golden comparison와 물리량별 tolerance를 + 선행하지 않는다. 이는 `beam-reference-qualification` 범위다. +- installer, Release package와 validation report를 선행하지 않는다. 이는 + `internal-release` 범위다. + +## 8. 검증된 baseline과 개발환경 + +2026-08-02 기준 도구와 dependency: - CMake 4.4.0 - MSBuild 18.8.2.30814 @@ -196,264 +294,163 @@ parallel 구현을 이유로 이 serial oracle을 먼저 변경하거나 toleran - HDF5 2.1.1 - GoogleTest 1.17.0, v145 x64 CRT build -새 PowerShell 세션에서 configure 또는 Harness 실행 전에 다음 환경 변수를 설정한다. -절대경로를 tracked CMake 파일이나 Preset에 넣지 않는다. +새 PowerShell 세션에서 configure 또는 Harness 실행 전에 설정한다. 절대경로를 +tracked CMake/Preset에 넣지 않는다. - $env:MKL_DIR = "C:\Program Files (x86)\Intel\oneAPI\2026.1\lib\cmake\mkl" - $env:TBB_DIR = "C:\Program Files (x86)\Intel\oneAPI\2026.1\lib\cmake\tbb" - $env:HDF5_DIR = "C:\Program Files\HDF_Group\HDF5\2.1.1\cmake" - $env:GTest_DIR = "C:\Users\baram\AppData\Local\FESA\dependencies\googletest-1.17.0-v145-x64-crt\lib\cmake\GTest" +```powershell +$env:MKL_DIR = "C:\Program Files (x86)\Intel\oneAPI\2026.1\lib\cmake\mkl" +$env:TBB_DIR = "C:\Program Files (x86)\Intel\oneAPI\2026.1\lib\cmake\tbb" +$env:HDF5_DIR = "C:\Program Files\HDF_Group\HDF5\2.1.1\cmake" +$env:GTest_DIR = "C:\Users\baram\AppData\Local\FESA\dependencies\googletest-1.17.0-v145-x64-crt\lib\cmake\GTest" - Test-Path "$env:MKL_DIR\MKLConfig.cmake" - Test-Path "$env:TBB_DIR\TBBConfig.cmake" - Test-Path "$env:HDF5_DIR\hdf5-config.cmake" - Test-Path "$env:GTest_DIR\GTestConfig.cmake" +Test-Path "$env:MKL_DIR\MKLConfig.cmake" +Test-Path "$env:TBB_DIR\TBBConfig.cmake" +Test-Path "$env:HDF5_DIR\hdf5-config.cmake" +Test-Path "$env:GTest_DIR\GTestConfig.cmake" +``` -네 package config와 다음 h5ls 경로가 존재함을 확인했다. +기본 검증 명령: - C:\Program Files\HDF_Group\HDF5\2.1.1\bin\h5ls.exe +```powershell +cmake --build --preset windows-debug +ctest --preset windows-debug --output-on-failure +uv run --with pytest python -m pytest -v -rs +.\out\build\windows-debug\Debug\fesa_assembly_benchmark.exe +``` -검증 명령: - - cmake --build --preset windows-debug - ctest --preset windows-debug --output-on-failure - uv run --with pytest python -m pytest -v -rs - -현재 baseline: +HANDOFF 갱신 직전 확인한 baseline: - MSVC Debug build 성공, 새 warning 없음 -- CTest 49개 중 49개 성공 -- Harness pytest 20개 중 20개 성공 -- pytest가 실제 20개를 수집했으므로 0-test 성공이 아님 -- 최소 cantilever CLI solve와 HDF5 public schema inspection 성공 +- CTest 54개 중 54개 성공 +- Harness pytest 20개 중 20개 성공; 0-test 성공이 아님 +- phase focused CTest 5개 모두 성공 +- benchmark 예시: + `elements=1000 serial_ms=488.602 parallel_ms=287.849 parallel_threads=16` + (시간과 speedup은 환경 의존적이며 pass 조건이 아니다.) CMake cache가 없거나 package 경로가 바뀐 경우에만 같은 환경 변수 세션에서 먼저 다음을 실행한다. - cmake --fresh --preset windows-debug +```powershell +cmake --fresh --preset windows-debug +``` -h5ls를 직접 실행할 때는 HDF5 DLL 외에 Intel libmmd.dll이 필요하다. HDF5 bin만 -PATH에 추가하면 Windows exit 0xC0000135가 발생할 수 있으므로 두 runtime -디렉터리를 현재 세션 PATH에 추가한다. 시스템 PATH는 영구 변경하지 않는다. +`h5ls` 직접 실행에는 HDF5 DLL과 Intel `libmmd.dll`이 모두 필요하다. 시스템 PATH는 +영구 변경하지 말고 현재 셸에만 추가한다. - $env:PATH = @( - "C:\Program Files\HDF_Group\HDF5\2.1.1\bin", - "C:\Program Files (x86)\Intel\oneAPI\2026.1\bin", - $env:PATH - ) -join ";" - h5ls --version +```powershell +$env:PATH = @( + "C:\Program Files\HDF_Group\HDF5\2.1.1\bin", + "C:\Program Files (x86)\Intel\oneAPI\2026.1\bin", + $env:PATH +) -join ";" +h5ls --version +``` -## 7. 다음 Phase 목표와 Step 순서 +## 9. Harness child 환경 주의사항 -deterministic-parallel-assembly의 목표는 oneTBB로 요소 계산을 병렬화하면서 -serial oracle과 thread count 사이의 CSR, RHS와 최종 해석 결과를 bit-for-bit -동일하게 유지하는 것이다. +이전 Phase의 최초 Harness 실행에서 child가 WindowsApps PowerShell을 시작할 때 +access denied가 발생했고, 일부 재시도 build process가 겹치며 timeout과 stale +blocked metadata가 잠시 남았다. 최종적으로 모든 Step output의 `exitCode`는 0이고 +phase metadata도 completed로 정리되었다. -### Step 0 - canonical-contribution-order +현재 `C:\Users\baram\.codex\config.toml`은 원래 값인 +`[windows] sandbox = "elevated"`로 복원되어 있음을 2026-08-02에 재확인했다. +다음 Phase에서는 먼저 표준 실행을 시도하고 같은 문제가 재현될 때만 아래 임시 +workaround를 적용한다. -- serial assembly를 변경하지 않은 상태에서 병렬 경로가 공유할 - MatrixContribution과 canonical merge contract를 분리한다. -- 입력 순열, 같은 row/column의 여러 element, cancellation과 signed zero를 포함한 - 실패 테스트를 먼저 작성한다. -- 정렬 key는 row, column, stable element identity, local_order다. -- canonicalize_contributions와 merge_contributions는 하나의 고정 total order와 - 하나의 merge 구현만 가져야 한다. -- 아직 TBB code를 추가하지 않는다. +- 기존 `scripts/execute.py`, child Codex, CMake/MSBuild process가 완전히 종료됐는지 + 확인해 중복 executor를 만들지 않는다. +- global config의 원래 값을 기록한 뒤 Harness 실행 동안만 sandbox를 + `unelevated`로 바꾼다. +- PATH 앞에는 standalone Codex와 Windows PowerShell 5.1을 두고 WindowsApps 및 + OpenAI Codex app-bin entry를 제거한다. +- 성공/실패와 관계없이 종료 즉시 config를 `elevated`로 복원하고 다시 읽어 확인한다. -Focused acceptance: +```powershell +$codexReleaseBin = "C:\Users\baram\.codex\packages\standalone\releases\0.146.0-x86_64-pc-windows-msvc\bin" +$windowsPowerShell = "$env:SystemRoot\System32\WindowsPowerShell\v1.0" +$filteredPath = $env:PATH -split ";" | Where-Object { + $_ -and + $_ -ne $codexReleaseBin -and + $_ -ne $windowsPowerShell -and + $_ -notmatch "WindowsApps" -and + $_ -notmatch "\\OpenAI\\Codex\\bin$" +} +$env:PATH = (@($codexReleaseBin, $windowsPowerShell) + $filteredPath) -join ";" - cmake --build --preset windows-debug - ctest --preset windows-debug -R "CanonicalContribution|DeterministicMerge" --output-on-failure - ctest --preset windows-debug --output-on-failure +(Get-Command codex).Source +(Get-Command powershell).Source +``` -### Step 1 - tbb-element-evaluation +설치 버전이나 경로가 바뀌었다면 위 절대경로를 그대로 사용하지 말고 실제 standalone +release와 `codex-resources` 존재를 먼저 확인한다. 사용자 profile 전체나 drive root를 +`--codex-add-dir`로 허용하지 않는다. -- oneTBB는 독립적인 Beam element evaluation에만 사용한다. -- worker는 thread-local contribution을 만들며 공유 CSR values에 쓰지 않는다. -- merge는 Step 0의 canonical serial 순서를 그대로 사용한다. -- AssemblyOptions의 max_threads와 grain_size로 실행을 제한한다. -- max_threads=1과 2 이상에서 serial/parallel CSR와 force를 bit-for-bit 비교한다. -- PARDISO를 TBB task 안에서 호출하지 않는다. +## 10. 새 세션 시작 절차 -Focused acceptance: +먼저 이 문서와 다음 파일을 읽는다. - cmake --build --preset windows-debug - ctest --preset windows-debug -R "ParallelAssembly|TbbElementEvaluation" --output-on-failure - ctest --preset windows-debug --output-on-failure +```text +phases/result-contract-completion/index.json +phases/result-contract-completion/step0.md +phases/result-contract-completion/step1.md +phases/result-contract-completion/step2.md +docs/formulation/timoshenko-beam-3d.md +docs/HDF5_SCHEMA.md +include/fesa/elements/beam/beam3d2.hpp +include/fesa/model/beam_section.hpp +include/fesa/results/result_database.hpp +include/fesa/io/hdf5/writer.hpp +src/fesa/elements/beam/beam3d2.cpp +src/fesa/results/result_database.cpp +src/fesa/analysis/linear_static_analysis.cpp +src/fesa/io/hdf5/writer.cpp +``` -### Step 2 - thread-count-determinism +그 다음 Git/package 상태와 8절 baseline을 재검증하고 다음을 실행한다. -- thread count 1, 2, available concurrency에서 CSR, RHS, displacement와 reaction을 - bit-for-bit 비교한다. -- 최소 10회 반복해 scheduling 변화 회귀를 검사한다. -- 측정용 fesa_assembly_benchmark를 추가해 serial/parallel 시간과 element count를 - 출력한다. -- benchmark speedup은 환경 의존적이므로 pass 조건으로 만들지 않는다. -- assembly test 동안 MKL thread 수를 중첩해 키우지 않는다. +```powershell +python scripts/execute.py result-contract-completion +``` -Focused acceptance: - - 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 - -## 8. 구현 전에 정렬할 설계점 - -아래 항목은 범위를 늘리라는 의미가 아니다. Step 계약과 현재 serial oracle 사이에서 -구현 전에 결정하고 테스트로 고정할 최소 질문이다. - -1. Stable element identity - - Step 0 초안의 MatrixContribution은 ElementId를 제시한다. - - 현재 oracle은 EntityOrigin의 instance_name, local_label, part_name 순으로 - 정렬한다. - - ElementId만으로 기존 bit pattern과 storage-order 독립성을 보존할 수 있는지 - 먼저 확인한다. 확인 없이 oracle의 정렬 key를 바꾸지 않는다. - -2. Canonical API와 serial 경로 - - Step 0은 serial assembly를 변경하지 말라고 요구하면서 공통 merge contract를 - 분리한다. - - 먼저 public/internal 경계를 최소화하고, 기존 assemble_serial의 관찰 가능한 - 결과가 bit-for-bit 유지되는 테스트를 둔다. - - 실제 두 번째 사용처가 생기기 전에 범용 registry나 backend hierarchy를 만들지 - 않는다. - -3. Parallel failure ordering - - worker에서 여러 Beam kernel failure가 발생해도 scheduling 순서로 어느 오류를 - 반환할지 결정하면 재현성이 깨진다. - - shared CSR write나 first-writer-wins exception 상태를 만들지 말고 canonical - element identity 기준으로 deterministic하게 처리한다. - -4. AssemblyOptions validation - - max_threads와 grain_size의 0 의미를 묵시적으로 정하지 않는다. - - automatic 또는 invalid 중 가장 단순한 계약을 선택하고 focused test로 고정한다. - -5. Force assembly - - 현재 RHS는 nodal load를 serial full-vector 순서로 누적한다. - - 이번 Phase는 element evaluation 병렬화가 목적이다. force accumulation을 별도 - 병렬 기능으로 확장하지 말고 serial oracle과 bitwise equality를 유지한다. - -6. Benchmark 격리 - - benchmark는 제품 correctness test를 우회하는 별도 assembly를 사용하지 않는다. - - fixed Domain과 production serial/parallel API를 호출한다. - - speedup이나 release 성능 목표를 임의 assertion으로 추가하지 않는다. - -## 9. 아키텍처와 범위 경계 - -- oneTBB 의존성은 assembly adapter/implementation 경계에 가둔다. -- core, model, fem, elements의 public contract에 TBB type을 노출하지 않는다. -- Beam kernel은 element-local contribution만 계산하고 전역 CSR을 알지 않는다. -- DofManager가 DOF와 equation mapping을 계속 단독 소유한다. -- worker는 공유 CSR values에 atomic add하지 않는다. -- contribution의 부동소수점 합산 순서를 thread scheduling과 분리한다. -- TBB element work가 모두 끝난 후에만 PARDISO를 호출한다. -- 기존 assemble_serial은 oracle로 유지한다. -- tolerance 비교를 bitwise 재현성의 대체물로 사용하지 않는다. -- result-contract-completion의 element result, HDF5 확장, CSV adapter를 선행하지 - 않는다. -- beam-reference-qualification의 Abaqus 골든 비교와 tolerance 작업을 선행하지 - 않는다. -- internal-release의 installer, Release package와 validation report를 선행하지 - 않는다. - -## 10. Harness child 환경 - -이전 Harness 실행에서 WindowsApps PowerShell을 child process로 시작할 때 access -denied가 발생했다. 확인된 구성: - -- standalone Codex release: - C:\Users\baram\.codex\packages\standalone\releases\0.146.0-x86_64-pc-windows-msvc -- WindowsApps가 제거된 PATH -- Windows PowerShell 5.1 -- Harness 실행 동안만 [windows] sandbox = "unelevated" - -현재 C:\Users\baram\.codex\config.toml은 원래 값인 -[windows] sandbox = "elevated"로 복원되어 있음을 2026-08-01에 확인했다. - -같은 문제가 재현될 때만 다음 순서를 사용한다. - -1. 다른 Codex 작업에 미칠 영향을 확인하고 config 원래 값을 기록한다. -2. Harness 실행 동안만 sandbox를 unelevated로 바꾼다. -3. 현재 PowerShell 세션 PATH 앞에 standalone bin과 Windows PowerShell 5.1을 - 두고 모든 WindowsApps entry를 제거한다. -4. package 환경 변수와 baseline을 확인한 뒤 같은 세션에서 Harness를 실행한다. -5. 성공·실패와 무관하게 finally에 해당하는 정리 단계에서 global config를 즉시 - elevated로 복원하고 실제 값을 다시 읽는다. - - $codexReleaseBin = "C:\Users\baram\.codex\packages\standalone\releases\0.146.0-x86_64-pc-windows-msvc\bin" - $windowsPowerShell = "$env:SystemRoot\System32\WindowsPowerShell\v1.0" - $filteredPath = $env:PATH -split ";" | Where-Object { - $_ -and - $_ -ne $codexReleaseBin -and - $_ -ne $windowsPowerShell -and - $_ -notmatch "WindowsApps" -and - $_ -notmatch "\\OpenAI\\Codex\\bin$" - } - $env:PATH = (@($codexReleaseBin, $windowsPowerShell) + $filteredPath) -join ";" - - (Get-Command codex).Source - (Get-Command powershell).Source - -사용자 profile 전체나 drive root를 --codex-add-dir로 허용하지 않는다. 설치 버전이나 -경로가 달라졌다면 위 절대경로를 그대로 사용하지 말고 실제 standalone release와 -codex-resources 존재를 먼저 확인한다. - -Harness가 모든 Step과 phase commit을 완료한 뒤 stderr reader의 CP949/UTF-8 decode -예외를 출력할 수 있다. exit code만 보지 말고 phase metadata, output JSON, Git -commit과 전체 검증 결과를 함께 확인한다. - -## 11. 새 세션 시작 절차 - -먼저 이 문서와 다음 파일을 모두 읽는다. - - /phases/deterministic-parallel-assembly/index.json - /phases/deterministic-parallel-assembly/step0.md - /phases/deterministic-parallel-assembly/step1.md - /phases/deterministic-parallel-assembly/step2.md - /src/fesa/assembly/serial_assembler.cpp - /tests/unit/assembly/serial_assembler_test.cpp - -그 다음 Git과 package 상태를 재검증하고 6절의 baseline 명령을 실행한다. 필요하면 -10절의 child sandbox 조건을 적용한 뒤 다음을 실행한다. - - python scripts/execute.py deterministic-parallel-assembly - -executor는 feat-deterministic-parallel-assembly 브랜치를 생성하거나 checkout하고 -Step 상태와 output metadata를 기록한다. 사용자가 명시적으로 요청하지 않은 한 ---push를 사용하지 않는다. +executor는 feature branch를 생성하거나 checkout하고 Step 상태와 +`stepN-output.json`을 기록한다. 사용자가 명시적으로 요청하지 않은 한 `--push`를 +사용하지 않는다. 각 Step은 다음 순서를 지킨다. -1. Step 파일의 필수 문서와 선행 구현을 모두 읽는다. -2. 성공 기준과 canonical ordering/threading invariant를 명시한다. -3. 8절의 모호한 계약을 구현 전에 정렬한다. -4. 실패 테스트를 먼저 작성하고 예상한 이유로 실패함을 확인한다. -5. 테스트를 통과시키는 최소 production code만 구현한다. -6. focused test, 전체 CTest와 Harness pytest를 실행한다. -7. Step summary와 output metadata가 실제 결과와 일치하는지 확인한다. -8. Phase 종료 전 전체 diff를 determinism, race avoidance, TBB 경계와 기존 serial - oracle 기준으로 review한다. +1. Step 파일의 필수 문서와 현재 구현을 모두 읽는다. +2. 6절의 모호한 계약을 구현 전에 명시하고 focused test로 고정한다. +3. hand-calculated/unit/integration test가 예상한 이유로 실패함을 먼저 확인한다. +4. 테스트를 통과시키는 최소 production code만 구현한다. +5. focused CTest, 전체 CTest와 Harness pytest를 실행한다. +6. Step 2에서는 public reader와 정확한 `h5ls -r` 명령으로 파일 구조를 확인한다. +7. Step summary/output metadata와 실제 결과를 대조한다. +8. Phase 종료 전 결과 부호, provenance, schema completeness, adapter 경계와 + round-trip 손실 여부를 독립 review한다. -## 12. 다음 Phase 완료 조건 +## 11. 다음 Phase 완료 조건 -- /phases/deterministic-parallel-assembly/index.json의 Step 0~2가 모두 completed -- /phases/index.json에서 deterministic-parallel-assembly가 completed -- shuffled/cancellation/signed-zero contribution의 canonical 결과가 bit-for-bit 동일 -- serial과 parallel의 CSR row offsets, column indices, values와 force가 동일 -- thread count 1, 2, available concurrency와 최소 10회 반복에서 결과가 동일 -- 최종 linear static displacement와 reaction이 thread count에 무관하게 동일 -- worker가 thread-local contribution만 생성하고 공유 CSR에 atomic add하지 않음 -- TBB task와 PARDISO 실행이 중첩되지 않음 -- deterministic Beam kernel failure propagation 검증 -- benchmark가 production API를 사용하고 speedup을 pass 조건으로 만들지 않음 +- `phases/result-contract-completion/index.json`의 Step 0~2가 모두 completed +- `phases/index.json`에서 `result-contract-completion`이 completed +- pure axial/torsion/bending/biaxial recovery의 값·끝 부호·point 순서 검증 +- section strain/resultant와 centroid/recovery-point `Sxx`의 명시적 component 및 + coordinate contract +- Beam element result의 ID/origin/connectivity/local frame 보존과 validation +- `LinearStaticAnalysis`가 production recovery로 complete `ResultDatabase` 생성 +- 새 version의 HDF5 하나만으로 model, analysis settings, nodal/element results와 + diagnostics 재구성 +- public reader round trip과 `h5ls -r` 구조 검증 - focused test와 전체 CTest 통과 - Harness pytest가 0개가 아닌 상태로 전체 통과 - 새 MSVC warning 없음 - 독립 review의 Critical/Important finding 해결 -- 사용자 선택 전 원격 push나 dev 병합을 수행하지 않음 +- Abaqus golden/tolerance나 internal release 범위를 선행하지 않음 +- 사용자 요청 없이 원격 push 또는 `dev` 병합을 수행하지 않음 새 세션의 권장 첫 요청: -> docs/HANDOFF.md와 deterministic-parallel-assembly의 index/step0~2를 읽고 현재 -> dev baseline, oneTBB 환경과 Harness child 실행 조건을 확인한 뒤 -> deterministic-parallel-assembly Phase를 시작해주세요. +> `docs/HANDOFF.md`와 `result-contract-completion`의 index/step0~2를 읽고 현재 +> `dev` baseline, Beam recovery의 미결 계약과 Harness child 실행 조건을 확인한 뒤 +> `result-contract-completion` Phase를 시작해주세요.