Files
FESADev/phases/nonlinear-static-newton-raphson/step10.md
T

178 lines
9.0 KiB
Markdown

# Step 10: prepared-analysis-flow-and-full-procedure
## 읽어야 할 파일
- `AGENTS.md`
- `docs/ARCHITECTURE.md`
- `docs/ADR.md`
- `docs/nonlinear-static-newton-raphson/requirements.md`
- `docs/nonlinear-static-newton-raphson/formulation.md`
- `docs/nonlinear-static-newton-raphson/numerical-review.md`
- `docs/nonlinear-static-newton-raphson/io.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<Diagnostic> diagnostics;
};
Result<PreparedAnalysisInput> PrepareAnalysisInput(
const std::filesystem::path& input_path);
struct LinearStaticExecutionResult {
AnalysisState state;
std::vector<Diagnostic> diagnostics;
};
class LinearStaticProcedureExecutor {
public:
LinearStaticProcedureExecutor(const ParallelFor& parallel_for,
LinearSolver& linear_solver);
Result<LinearStaticExecutionResult> Execute(const Domain& domain) const;
private:
const ParallelFor& parallel_for_;
LinearSolver& linear_solver_;
};
struct NonlinearStaticExecutionResult {
NonlinearAnalysisState state;
std::vector<Diagnostic> diagnostics;
};
class NonlinearStaticProcedureExecutor {
public:
NonlinearStaticProcedureExecutor(const ParallelFor& parallel_for,
TangentSolver& tangent_solver);
Result<NonlinearStaticExecutionResult> Execute(
const Domain& domain, NewtonIterationLogWriter& log) const;
private:
const ParallelFor& parallel_for_;
TangentSolver& tangent_solver_;
};
using PreparedAnalysisOutcome =
std::variant<LinearStaticExecutionResult, NonlinearStaticExecutionResult>;
Result<PreparedAnalysisOutcome> 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<Diagnostic>& 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.
Run:
```powershell
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C 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 --fresh -S . -B .harness/build -G "Visual Studio 18 2026" -A x64 `
"-DFESA_GTEST_SOURCE_DIR=$gtestSource" `
"-DMKL_DIR=$mklDir" `
"-DTBB_DIR=$tbbDir" `
"-DHDF5_DIR=$hdf5Dir"
cmake --build .harness/build --config Debug
ctest --test-dir .harness/build -C Debug -R "LinearStaticAnalysis|NonlinearStaticProcedure|FesaApplication" --output-on-failure
ctest --test-dir .harness/build -C Debug --show-only=json-v1
ctest --test-dir .harness/build -C Debug --output-on-failure
```
Recheck `.harness/config.json` before default commands.
## 상태 기록
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.