# Step 24: Linear Static Orchestration and CLI ## 담당 역할과 필수 스킬 - 담당 역할: `implementation-agent` - 필수 스킬: `fesa-cpp-msvc-tdd` - 모든 C++ build/test와 최종 VERIFY는 MSVC x64 Debug 기준으로 수행한다. ## 읽어야 할 파일 - `/AGENTS.md` - `/docs/ARCHITECTURE.md` - `/docs/ADR.md` - `/docs/requirements/linear-static-3d-euler-beam.md` - `/docs/formulations/3d-isoparametric-euler-beam-formulation.md` - `/docs/io-definitions/linear-static-3d-euler-beam-io.md` - `/docs/reference-models/linear-static-3d-euler-beam-reference-models.md` - `/docs/implementation-plans/linear-static-3d-euler-beam.md` - `/include/fesa/io/abaqus/input_reader.hpp` - `/include/fesa/io/abaqus/domain_mapper.hpp` - `/include/fesa/analysis/analysis_model.hpp` - `/include/fesa/analysis/analysis_state.hpp` - `/include/fesa/fem/dof_manager.hpp` - `/include/fesa/assembly/parallel_for.hpp` - `/include/fesa/assembly/sparse_assembler.hpp` - `/include/fesa/constraints/essential_constraints.hpp` - `/include/fesa/solvers/linear/linear_solver.hpp` - `/include/fesa/assembly/load_assembler.hpp` - `/include/fesa/results/result_recovery.hpp` - `/include/fesa/results/results_writer.hpp` - `/include/fesa/io/hdf5/hdf5_results_writer.hpp` - `/src/fesa/CMakeLists.txt` - `/tests/CMakeLists.txt` - `/reference/cantilever beam/`의 승인된 네 파일 ## 소유 파일 - Create: `/include/fesa/analysis/linear_static_analysis.hpp` - Create: `/src/fesa/analysis/linear_static_analysis.cpp` - Create: `/include/fesa/app/fesa_application.hpp` - Create: `/src/fesa/app/fesa_application.cpp` - Create: `/src/fesa/app/main.cpp` - Create: `/tests/integration/analysis/linear_static_analysis_test.cpp` - Create: `/tests/integration/app/fesa_application_test.cpp` - Create: `/tests/reference/reference_comparison.hpp` - Create: `/tests/reference/reference_comparison.cpp` - Create: `/tests/reference/reference_comparison_test.cpp` - Create: `/tests/reference/b33_reference_comparison_test.cpp` - Modify: `/src/fesa/CMakeLists.txt` - Modify: `/tests/CMakeLists.txt` ## 작업 전체 single-step lifecycle과 `fesa.exe` CLI를 구현하고 Step 26이 재사용할 read-only reference comparison test utility를 완성하라. ```cpp struct AnalysisRequest { std::filesystem::path inputPath; std::filesystem::path outputPath; }; class Analysis { public: virtual ~Analysis() = default; Status run(const AnalysisRequest& request); protected: virtual Status initialize(const AnalysisRequest& request) = 0; virtual Status buildAnalysisModel() = 0; virtual Status buildDofMapAndSparsePattern() = 0; virtual Status assembleAndPartitionStiffness() = 0; virtual Status factorize() = 0; virtual Status assembleLoadsAndEffectiveRhs() = 0; virtual Status substituteAndReconstruct() = 0; virtual Status recoverAndWriteResults() = 0; }; class LinearStaticAnalysis final : public Analysis { /* V0 hook implementations */ }; class FesaApplication { public: int run(const std::vector& arguments); }; ``` `LinearStaticAnalysis::run`은 다음 event order를 exact하게 고정하고 각 실패를 diagnostic/ exit category에 연결한다. ```text parse input -> Domain -> AnalysisModel -> DofManager/sparse pattern -> parallel element stiffness -> deterministic COO-to-CSR -> free/constrained partition -> factorize(Kff) -> assemble full nodal load -> rhs=Ff-Kfc*dc -> solve substitution -> reconstruct full displacement -> residual/reaction/element recovery -> atomic HDF5 write ``` Spy/fake adapters를 사용한 orchestration test는 `factorize` event가 load assembly보다 먼저고 `solve`가 factorization을 재수행하지 않음을 검증한다. 실제 production default는 TbbParallelFor, MklPardisoSolver, Hdf5ResultsWriter를 사용한다. CLI는 `fesa.exe --output `와 output 생략 시 current directory `results.h5`를 지원한다. Exit code는 `0 success`, `2 usage`, `3 input syntax/semantic`, `4 model validation`, `5 factorization/substitution`, `6 HDF5 output`이다. Error diagnostics는 stderr에 deterministic order로 쓰고 warning은 output diagnostics에도 보존한다. CMake executable target은 내부 이름이 다르더라도 `OUTPUT_NAME fesa`를 설정해 Debug output이 실제로 `fesa.exe`가 되게 한다. Test-only reference support를 `tests/reference/` 아래 구현하라. - approved input으로 `.harness/build/reference/cantilever-beam-b33/results.h5`를 생성한다. - legacy displacement/reaction/elemental-force CSV를 read-only로 parse하고 실제 CAE header `U-U*`, `UR-UR*`, `RF-RF*`, `RM-RM*`, `SF-SF1`, `SM-SM*`을 canonical component로 normalize한다. - row matching 전에 expected header, B33 input, unique identity, missing/extra/nonfinite를 검사한다. - same model/step/frame/quantity/component의 Abaqus-only scale과 `absolute_floor + 1e-6*reference_scale`로 모든 row를 판정한다. - section resultants는 node station과 `SF1->N`, `SM1->My`, `SM2->Mz`, `SM3->T`로 비교한다. - Stress comparison은 N/A로 기록하되 HDF5 stress dataset/test 통과를 요구한다. - max absolute, component-scale normalized, RMS, norm, worst row/component를 `.harness/build/reference/cantilever-beam-b33/comparison.json`에 결정적으로 기록한다. - 같은 JSON에 matched FESA/reference rows, full free residual norm, applied/reaction force와 origin 기준 moment 합, endpoint consistency를 `physics_evidence`로 기록해 Step 27이 source/test 변경 없이 물리 sanity를 독립 검토할 수 있게 한다. Tests는 orchestration order, CLI default/explicit output, all exit codes, output-request no-op, approved input end-to-end, reference tolerance zero/near-zero/failure cases를 포함한다. CTest regex/label은 `LinearStaticCli`, `ReferenceComparisonContract`, `B33ReferenceComparison`으로 실행 가능하게 한다. ## Acceptance Criteria ```powershell cmake --build .harness/build --config Debug --target fesa_tests ctest --test-dir .harness/build -C Debug -R "LinearStaticCli|ReferenceComparisonContract|B33ReferenceComparison" --output-on-failure ``` 위 command에서 missing orchestration/CLI/reference utility RED를 확인한 후 구현한다. ```powershell cmake -S . -B .harness/build -A x64 ` -DFESA_GTEST_SOURCE_DIR=C:/git/googletest ` "-DMKL_DIR=C:/Program Files (x86)/Intel/oneAPI/mkl/2026.1/lib/cmake/mkl" ` "-DTBB_DIR=C:/Program Files (x86)/Intel/oneAPI/tbb/2023.1/lib/cmake/tbb" ` "-DHDF5_DIR=C:/Program Files/HDF_Group/HDF5/2.1.1/cmake" cmake --build .harness/build --config Debug ctest --test-dir .harness/build -C Debug -R "LinearStaticCli|ReferenceComparisonContract|B33ReferenceComparison" --output-on-failure ctest --test-dir .harness/build -C Debug --show-only=json-v1 ctest --test-dir .harness/build -C Debug --output-on-failure if (-not (Test-Path '.harness/build/reference/cantilever-beam-b33/results.h5')) { throw 'Missing reference-run HDF5' } if (-not (Test-Path '.harness/build/reference/cantilever-beam-b33/comparison.json')) { throw 'Missing comparison metrics' } git diff --exit-code -- reference/ ``` ## 검증 절차 1. orchestration/CLI/reference contract tests를 먼저 작성하고 targeted RED를 확인한다. 2. exact lifecycle과 minimal CLI/test utility로 targeted GREEN을 만든다. 3. approved input end-to-end, comparison metrics, CTest discovery/full VERIFY를 실행한다. 4. reference artifacts가 unchanged인지 확인한다. 5. `/docs/implementation-plans/linear-static-3d-euler-beam-implementation-report.md`의 Step 24 section에 실제 RED/GREEN/VERIFY command, exit code, 핵심 output, 변경 파일과 generated HDF5/comparison evidence를 기록한다. 6. Step 24를 `completed`로 갱신하고 CLI path, exit codes, generated HDF5/metrics와 RED/GREEN/VERIFY evidence를 summary에 기록한다. ## 금지사항 - load assembly를 factorization 앞으로 옮기지 마라. 이유: 승인 runtime order와 반대다. - factorize와 substitution을 합치지 마라. 이유: solver contract와 repeated RHS 검증을 깨뜨린다. - B31/multiple-step/transform/`*DLOAD`를 지원하지 마라. 이유: V0 범위 밖이다. - reference CSV를 보정·rename·rewrite하지 마라. 이유: comparison baseline을 오염시킨다. - stress reference comparison을 만들어내지 마라. 이유: 승인 범위에서 명시적 N/A다. - 직접 commit하지 마라. 이유: Harness executor가 담당한다.