# Step 10: prepared-analysis-flow-and-full-procedure > 과거 개발 계획이다. 아래 작업·상태·예시는 현재 실행 지시가 아니다. > 현재 구현과 검증 한계는 [기능 요약](../../docs/nonlinear-static-newton-raphson/README.md)을 따른다. ## 읽어야 할 파일 - `AGENTS.md` - `../../docs/solver-core/README.md` - `../../docs/solver-core/README.md` - `../../docs/nonlinear-static-newton-raphson/README.md` - `../../docs/nonlinear-static-newton-raphson/formulation.md` - `../../docs/nonlinear-static-newton-raphson/README.md` - `../../docs/nonlinear-static-newton-raphson/README.md` - `include/fesa/analysis/analysis.h` - `include/fesa/analysis/linear_static_analysis.h` - `src/fesa/analysis/linear_static_analysis.cpp` - `src/fesa/app/fesa_application.cpp` - `include/fesa/io/hdf5/hdf5_results_writer.h` - `include/fesa/results/results_writer.h` - `include/fesa/results/nonlinear_results_writer.h` - Step 0 files: `include/fesa/app/output_paths.h`, `src/fesa/app/output_paths.cpp` - Step 1 files: `include/fesa/model/domain.h`, `src/fesa/io/abaqus/domain_mapping_context.cpp` - Step 5 files: `include/fesa/analysis/nonlinear_static_control.h` - Step 6 files: `include/fesa/solvers/linear/tangent_solver.h` - Step 7 files: `include/fesa/analysis/newton_iteration_log.h` - Step 8 files: `include/fesa/analysis/nonlinear_analysis_state.h` - Step 9 files: `include/fesa/results/nonlinear_results_writer.h`, `include/fesa/io/hdf5/nonlinear_hdf5_results_writer.h` ## 이전 Step 전제 Steps 0-9 provide path/lease, Domain procedure identity, nonlinear element/control/solver/log/state, and nonlinear HDF5 writer. ## 소유 파일 - Create: `include/fesa/analysis/prepared_analysis.h` - Create: `src/fesa/analysis/prepared_analysis.cpp` - Create: `include/fesa/analysis/linear_static_procedure.h` - Create: `src/fesa/analysis/linear_static_procedure.cpp` - Create: `include/fesa/analysis/nonlinear_static_procedure.h` - Create: `src/fesa/analysis/nonlinear_static_procedure.cpp` - Modify: `include/fesa/analysis/linear_static_analysis.h` - Modify: `src/fesa/analysis/linear_static_analysis.cpp` - Modify: `src/fesa/app/fesa_application.cpp` - Test: `tests/integration/analysis/linear_static_analysis_test.cpp` - Create: `tests/integration/analysis/nonlinear_static_procedure_test.cpp` - Test: `tests/integration/app/fesa_application_test.cpp` - Modify: `src/fesa/CMakeLists.txt` - Modify: `tests/CMakeLists.txt` ## 인터페이스 ```cpp namespace fesa { struct PreparedAnalysisInput { Domain domain; std::vector diagnostics; }; Result PrepareAnalysisInput( const std::filesystem::path& input_path); struct LinearStaticExecutionResult { AnalysisState state; std::vector diagnostics; }; class LinearStaticProcedureExecutor { public: LinearStaticProcedureExecutor(const ParallelFor& parallel_for, LinearSolver& linear_solver); Result Execute(const Domain& domain) const; private: const ParallelFor& parallel_for_; LinearSolver& linear_solver_; }; struct NonlinearStaticExecutionResult { NonlinearAnalysisState state; std::vector diagnostics; }; class NonlinearStaticProcedureExecutor { public: NonlinearStaticProcedureExecutor(const ParallelFor& parallel_for, TangentSolver& tangent_solver); Result Execute( const Domain& domain, NewtonIterationLogWriter& log) const; private: const ParallelFor& parallel_for_; TangentSolver& tangent_solver_; }; using PreparedAnalysisOutcome = std::variant; Result ExecutePreparedAnalysis( const Domain& domain, LinearStaticProcedureExecutor& linear_executor, NonlinearStaticProcedureExecutor& nonlinear_executor, NewtonIterationLogWriter& log); Status FinalizePreparedAnalysisResult( const DerivedOutputPaths& paths, const Domain& domain, const PreparedAnalysisOutcome& outcome, const std::vector& diagnostics, ResultsWriter& linear_writer, NonlinearResultsWriter& nonlinear_writer); } // namespace fesa ``` ## RED Add tests first. - `NSNR-PROC-001`: app validates argv, derives paths, acquires `OutputWriteLease`, opens log, then parses/maps exactly once. - `NSNR-PROC-002`: parse/map diagnostics are sorted and preserved in prepared input. - `NSNR-PROC-003`: linear `NLGEOM=NO` run uses `LinearStaticProcedureExecutor` and preserves existing numerical/HDF5 meaning except output names and log lifecycle. - `NSNR-PROC-004`: nonlinear `NLGEOM=YES` run uses `NonlinearStaticProcedureExecutor`. - `NSNR-PROC-005`: linear executor receives injected `ParallelFor` and existing `LinearSolver`; nonlinear executor receives injected `ParallelFor` and `TangentSolver`. - `NSNR-PROC-006`: app constructs and owns concrete `TbbParallelFor`, `MklPardisoSolver`, `MklPardisoTangentSolver`, `Hdf5ResultsWriter`, and `NonlinearHdf5ResultsWriter`. - `NSNR-PROC-007`: procedure computation/recovery returns a validated outcome without opening HDF5. - `NSNR-PROC-008`: app closes log successfully before calling injected linear or nonlinear writer. - `NSNR-PROC-009`: log close failure blocks HDF5 candidate creation. - `NSNR-PROC-010`: nonlinear executor builds `NonlinearStateBaselineInput` from Domain nodes in stable internal order, preserving each node's `EntityIndex` and full `SourceEntityId`, then constructs state through `NonlinearAnalysisState::Create(domain, dofs, baseline)` before the first increment; the factor-zero baseline is committed state only and is not an accepted frame. - `NSNR-PROC-011`: nonlinear increment loop uses factors from Step 5 and iterations `1..100`. - `NSNR-PROC-012`: each entered iteration performs fresh tangent factorization and solves `Kff * delta = -r_f`. - `NSNR-PROC-013`: global external vector/tangent from Step 5 is assembled once and combined with approved signs `r = f_int - f_ext`, `K_T = K_int - K_ext`; the fixed-moment tangent is subtracted once and is never duplicated per incident element. - `NSNR-PROC-014`: iteration 100 can accept if gates pass; failure at 100 emits `nonlinear-nonconvergence` with no retry. - `NSNR-PROC-015`: nonfinite data, factorization failure, solve failure, invalid accepted state, and log failure map to approved diagnostics. - `NSNR-PROC-016`: constrained correction is zero and reactions/free residuals come from full residual `r = f_int - f_ext`. - `NSNR-PROC-017`: failed nonlinear run preserves prior final HDF5 according to output lifecycle. - `NSNR-PROC-018`: deterministic repeat produces same sparse structure, nodal source-identity order, result row order, diagnostics, and log line ordering. ### USER-DECISION-003 option-1 revision addendum Step 10의 completed status, summary, timestamps와 commits는 보존한다. Existing procedure는 same-trial free residual/internal/external vectors를 force와 moment channel별로 분리하여 `EvaluateNewtonConvergence`에 전달하고 fresh same-iteration correction을 별도로 전달한다. 따라서 option 1의 production correction은 Step 11의 `nonlinear_static_control.cpp`에 한정하며 `nonlinear_static_procedure.cpp`, prepared-analysis API와 log writer production 변경은 예상하지 않는다. Step 11의 shellNL copied-input run과 log assertions이 unloaded rotational external channel의 exact-zero branch, loaded force channel의 retained relative branch, four-channel AND 및 intended factors `0.1..1.0`을 integration 수준에서 검증한다. Run: ```powershell cmake --build --preset windows-msvc-ninja-debug ctest --preset windows-msvc-ninja-debug -R "LinearStaticAnalysis|NonlinearStaticProcedure|FesaApplication" --output-on-failure ``` Expected: new tests fail. Unexpected pass stops. ## GREEN Refactor current parse/map and linear compute/recovery out of `LinearStaticAnalysis::Run()` into `PrepareAnalysisInput` and `LinearStaticProcedureExecutor`. Keep `LinearStaticAnalysis` as a compatibility wrapper that delegates through the new flow and does not contain nonlinear conditions. Implement `NonlinearStaticProcedureExecutor` in `nonlinear_static_procedure.*` using Steps 2-8, constructing state only through `NonlinearAnalysisState::Create(...)` with one baseline per Domain node in stable internal order, forming `r = f_int - f_ext` and `K_T = K_int - K_ext`, preserving `EntityIndex` plus full `SourceEntityId` into final writer inputs, and delaying all HDF5 work until `FinalizePreparedAnalysisResult`. The app owns concrete adapters and passes them through interfaces. ## VERIFY ```powershell cmake --preset windows-msvc-ninja-debug cmake --build --preset windows-msvc-ninja-debug ctest --preset windows-msvc-ninja-debug -R "LinearStaticAnalysis|NonlinearStaticProcedure|FesaApplication" --output-on-failure ctest --preset windows-msvc-ninja-debug --show-only=json-v1 ctest --preset windows-msvc-ninja-debug --output-on-failure ``` Use the ignored 과거 검증 자료(정리됨) preset contract. The Harness process must inherit VsDevCmd x64 and `FESA_GTEST_SOURCE_DIR`, `MKL_DIR`, `TBB_DIR`, and `HDF5_DIR` from its parent launch environment. ## 상태 기록 Update only Step 10 status and one-line payload. Executor owns timestamps, commits, retry, and advancement. ## 금지사항 - Do not parse/map twice. 이유: source identity, diagnostics, and Domain lifetime must be deterministic. - Do not reconstruct nodal identity from source labels alone. 이유: labels can repeat across instances and HDF5/reference matching requires full `SourceEntityId`. - Do not open HDF5 before log close succeeds. 이유: io.md requires log close success before HDF5 candidate open/write/final replace. - Do not insert nonlinear branches into `LinearStaticAnalysis` private lifecycle. 이유: new procedure owns its own lifecycle. - Do not replace final HDF5 on failed analysis, log failure, or HDF5 failure. 이유: asymmetric preservation contract requires prior valid final preservation. - Do not construct MKL/TBB/HDF5 backends inside procedure executors. 이유: dependencies are injected so tests can observe lifecycle and no backend type crosses analysis/core public boundaries. - Do not duplicate the option-1 selector in the procedure or log writer. 이유: the existing procedure already transports the three residual vectors separately and convergence ownership remains in `nonlinear_static_control`.