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

9.0 KiB

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

인터페이스

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:

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

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 .harness/config.json 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.