# Nonlinear Static Newton-Raphson Implementation Plan > For Harness workers: this plan is an approved Stage 6 planning artifact. It authorizes planning files only. It does not authorize `scripts/execute.py`, C++ implementation, build, CTest, reference solver execution, or evidence-document creation. **Goal:** `nonlinear-static-newton-raphson` 기능을 C++17/MSVC/CMake/CTest TDD 순서로 구현하고, 승인된 nonlinear MITC4 Newton-Raphson 절차, HDF5 schema v1, log lifecycle, shellNL/shell reference comparison을 검증한다. **Architecture:** App layer가 argv 검증, lexical output path derivation, move-only `OutputWriteLease`, log open/close와 final HDF5 writer 호출 순서를 소유한다. 입력 parse/map은 정확히 한 번 수행하고, `StepDefinition::ProcedureKind()`로 linear와 nonlinear procedure executor를 분리한다. `LinearStaticAnalysis`의 기존 private lifecycle에는 nonlinear 조건문을 넣지 않고, 기존 linear numerical/HDF5 의미는 repository-wide output name/log lifecycle 변경만 제외하고 보존한다. **Tech Stack:** C++17, MSVC on Windows, CMake, CTest, GoogleTest, Intel oneAPI MKL/TBB, HDF5, Abaqus `.inp` approved subset, Python 3 Harness scripts. **Spec:** `docs/nonlinear-static-newton-raphson/{requirements,research,formulation,numerical-review,reference-model,io}.md` ## Metadata | key | value | | --- | --- | | feature_id | `nonlinear-static-newton-raphson` | | status | `approved-planning-files-materialized` | | owner_agent | `implementation-planning-agent` | | date | `2026-08-24` | | approval | User approved the final 13-Step draft on `2026-08-24`; Coordinator recorded `DECISION-036`. | | source_requirement | `docs/nonlinear-static-newton-raphson/requirements.md` | | source_research | `docs/nonlinear-static-newton-raphson/research.md` | | source_formulation | `docs/nonlinear-static-newton-raphson/formulation.md` | | source_numerical_review | `docs/nonlinear-static-newton-raphson/numerical-review.md` | | source_reference_models | `docs/nonlinear-static-newton-raphson/reference-model.md` | | source_io_definition | `docs/nonlinear-static-newton-raphson/io.md` | ## Approved Upstream Hashes | document | SHA-256 | | --- | --- | | `requirements.md` | `910E351F3F90FFA42F07D15206B55E62C05EAE821E250424430148337506EBF2` | | `research.md` | `C920A6B02381230D1DB419D73FE767D611B36720D27D6410507BA88C3CA28EEE` | | `formulation.md` | `DFA629888041D5762FD0DF4271353464A692B325DC0C821A8D8689688C1EAFD0` | | `numerical-review.md` | `9517E11804C45A6F3822D18821D52EA493AE20353C8FFAD61E960F4315977D01` | | `reference-model.md` | `52D10B1D0C0500B295C5E48BCB3618B309D9696371B8070D4E3DCEE8D3D74CD3` | | `io.md` | `DBB959A68F17D67CA2B42569610B9C1B595A8BFB5502BC194B7E62B656031B28` | ## Readiness Check - Upstream document status: Stage 1 requirements approved, Stage 2 research passed, Stage 3 formulation ready for numerical review and approved downstream, Stage 4 numerical/reference review passed for I/O definition, Stage 5 I/O definition approved. - Missing decisions: none. - Missing required comparison files: none for declared blocking/reference families. - Planning can proceed: yes. - `.harness/config.json`: absent during planning inspection. Each Step must recheck at execution time and use it first if it appears. ## Global Constraints - Use `RED -> observed failure -> minimal GREEN -> focused VERIFY -> full CTest` in every implementation Step. - C++ production edits require related C++ tests in the same Step. - Do not edit requirements, research, formulation, numerical review, reference-model, I/O, tolerance, or reference artifacts. - Do not run Abaqus, Nastran, or any reference solver. - Do not create `implementation-report.md`, `build-test.md`, or `reference-comparison.md` before Step 12 produces actual command evidence. - Do not run Harness from this planning approval. `scripts/execute.py` requires a separate explicit request. - Implementation and Harness execution remain unauthorized by this materialized plan until the user separately requests Executor execution. - Preserve source label/instance identity, deterministic row order, deterministic diagnostics, finite checks, and docs/TOLERANCE.md exactly. - Preserve `U1/U2/U3` blocking and `UR1/UR2/UR3` warning-only. For shellNL, preserve constrained `RF1/RF2`, `RF3`, physical spatial `RM1/RM2` blocking, and exclude `RM3` plus stress from numeric comparison. ## Repository Seam Map | area | current seam | implementation direction | | --- | --- | --- | | CLI/app | `src/fesa/app/fesa_application.cpp` currently accepts `[--output ]` and constructs `LinearStaticAnalysis`. | Add output path derivation and `OutputWriteLease`, reject any argv token containing `--output`, own log/HDF5 lifecycle. | | Analysis request | `include/fesa/analysis/analysis.h` contains `input_path` and `output_path`. | Add `log_path`; Step 10 introduces prepared analysis flow for single parse/map and delayed HDF5 finalization. | | Linear lifecycle | `LinearStaticAnalysis::Run()` currently parses/maps and writes HDF5 inside `RecoverAndWrite()`. | Refactor into `PrepareAnalysisInput`, `LinearStaticProcedureExecutor`, and final writer call after log close; keep linear numerical behavior. | | Domain | `StaticStepDefinition` in `include/fesa/model/model_types.h`; `StepDefinition` in `include/fesa/model/domain.h`. | Store procedure identity, `NLGEOM`, raw four `*STATIC` values and provenance. Do not store derived factor sequence or PRESELECT state. | | Parser mapping | `src/fesa/io/abaqus/domain_mapping_context.cpp`, `step_definition_mapper.cpp`. | Accept nonlinear static subset, warning no-op PRESELECT, reject unsupported procedure fail-closed. | | MITC4 | `include/fesa/elements/mitc4_shell.h`, `src/fesa/elements/mitc4_shell.cpp` are linear small-rotation. | Add separate nonlinear MITC4 files with `Create(...)` from four nodes, four initial frames, `ShellSection`, and `LinearElasticMaterial`; element kernels compute internal residual/tangent/recovery only. | | Loads/control | Current loads are assembled for linear static RHS. | Step 5 owns global-once fixed CLOAD external vector `f_ext` and exact external load tangent `K_ext`, including projected moment `J_l`/map-Hessian terms, with no incident-element multiplication. Step 5 also owns exact convergence constants: relative `1.0e-2`, zero-scale `1.0e-3` with channel-specific units. Step 10 forms `r = f_int - f_ext` and `K_T = K_int - K_ext`. | | Source identity | `SourceEntityId { instance_name, source_label, source_label_text }` and `EntityIndex` exist in `include/fesa/core/source_identity.h`; nodes are stored in stable Domain order. | Step 8 baseline uses both `EntityIndex` and full `SourceEntityId`, requires one node baseline per Domain node in stable internal order, rejects label-only or mismatched identities, and preserves identity into HDF5/reference mapping. | | Solver | `MklPardisoSolver` uses SPD `mtype=2` and upper-triangle copy. | Preserve unchanged; add `TangentSolver` and MKL unsymmetric full CSR `mtype=11`. | | Results writer | `ResultsWriter` is the backend-neutral linear writer; `Hdf5ResultsWriter` writes schema-v0 single-frame linear output. | Add `NonlinearResultsWriter` backend-neutral boundary and `NonlinearHdf5ResultsWriter` schema-v1 implementation with delayed finalization after log close. | | Tests | `fesa_unit_tests`, `fesa_integration_tests`, `fesa_reference_tests` use executable-wide labels. | Add focused test sources and use `ctest -R` regex; do not globally relabel existing tests as nonlinear. | ## Work Breakdown | Step | name | dependency | primary responsibility | | ---: | --- | --- | --- | | 0 | `cli-output-lease-and-derived-names` | none | CLI output derivation, `--output` substring rejection, RAII output lease, app-owned log/HDF5 lifecycle entry. | | 1 | `nonlinear-static-domain-contract` | 0 | Domain/parser semantic contract for `NLGEOM=YES`, raw `*STATIC`, PRESELECT warning no-op. | | 2 | `finite-rotation-state` | 1 | SO(3) finite rotation state, left Jacobian, branch/invariant validation. | | 3 | `nonlinear-mitc4-kinematics-and-recovery` | 1,2 | TL MITC4 nonlinear kinematics and recovery rows. | | 4 | `nonlinear-mitc4-residual-and-tangent` | 2,3 | Same-trial internal residual and internal consistent tangent with recovery. | | 5 | `load-boundary-path-and-convergence-gates` | 1-4 | Fixed factor path, proportional load/BC path, global-once fixed-load `f_ext`/`K_ext` with approved subtraction signs, `rho_M`, typed four-channel convergence with constants owned by evaluator. | | 6 | `backend-neutral-tangent-solver` | 4 | Separate nonsymmetric tangent solver boundary and MKL adapter. | | 7 | `newton-iteration-log-writer` | 0,5 | Exact 39-field Newton text log writer. | | 8 | `nonlinear-state-commit-rollback` | 3-7 | Factor-zero baseline construction with `EntityIndex` plus `SourceEntityId`, trial/committed nonlinear state, accepted frames, rollback/preservation. | | 9 | `nonlinear-hdf5-schema-v1-writer` | 8 | Nonlinear HDF5 schema v1 writer using `std::vector`. | | 10 | `prepared-analysis-flow-and-full-procedure` | 0-9 | Single parse/map prepared analysis flow, separate linear/nonlinear executors, delayed writer finalization. | | 11 | `reference-comparison-gate` | 0-10 | shellNL nonlinear and shell linear real-input reference comparison. | | 12 | `execution-closure-and-evidence-docs` | 0-11 | Fresh MSVC evidence, deterministic repeat/reference audit, actual-output evidence docs. | ## TDD Test Plan | test id family | RED assertion scope | Step | | --- | --- | --- | | `NSNR-CLI-*` | `--output` substring first-token rejection, lexical result/log names, no-output-change proof, lease lifetime. | 0 | | `NSNR-IO-*` | `NLGEOM=YES`, raw `*STATIC`, `NLGEOM=NO` regression, PRESELECT warning no-op, unsupported procedure diagnostics. | 1 | | `NSNR-ROT-*` | finite rotation invariants, `J_l`, branch margin, director update. | 2 | | `NSNR-ELEM-KIN-*` | nonlinear MITC4 creation inputs, TL shell kinematics, fixed-size four-GP recovery rows, degeneracy fail-closed, linear limit. | 3 | | `NSNR-ELEM-TAN-*` | same-trial internal residual/tangent, directional derivative, objectivity, symmetry only for internal/no-external cases. | 4 | | `NSNR-CTRL-*` | load factor path, absolute boundary path, global-once fixed loads and load tangent, moment admissibility, typed four convergence gates with `relative`/`zero-scale` branches and non-injectable exact thresholds/units. | 5 | | `NSNR-SOLVER-*` | nonsymmetric tangent solve, 0x0, nonfinite/failure translation, SPD solver unchanged. | 6 | | `NSNR-LOG-*` | serializer-owned 39-field UTF-8/LF/TAB Newton log from explicit stage/failure/channel records and fail-closed write/flush/close. | 7 | | `NSNR-STATE-*` | factor-zero baseline creation with stable node order and full source identity, trial/committed separation, accepted frame order, full schema-v1 state inventory, finite atomic commit, rollback. | 8 | | `NSNR-HDF5-*` | `NonlinearResultsWriter` boundary, schema v1 metadata/model/frame datasets, factor-zero metadata, atomic finalization. | 9 | | `NSNR-PROC-*` | full procedure orchestration, single parse/map, log close before HDF5, deterministic repeat. | 10 | | `NSNR-REF-*` | original artifact snapshot, temp input copy run, HDF5-to-original-CSV identity mapping, tolerance, classification, report data. | 11 | | `NSNR-EVID-*` | fresh evidence docs and diff/hash/warning audits from actual command outputs. | 12 | ## CMake And CTest Plan - Add C++ sources to `src/fesa/CMakeLists.txt` under existing `fesa_solver`. - Add unit tests to `fesa_unit_tests`, integration tests to `fesa_integration_tests`, reference tests to `fesa_reference_tests`. - Preserve current executable-wide labels. Use focused regex such as `ctest --test-dir .harness/build -C Debug -R "NonlinearStaticReference|ReferenceTolerance|Mitc4Reference" --output-on-failure`. - If scoped per-test labels are introduced, the Step that introduces the mechanism must test it and avoid changing labels for unrelated discovered tests. - Configure/build/test commands: ```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 --show-only=json-v1 ctest --test-dir .harness/build -C Debug --output-on-failure ``` ## Data Flow Contract 1. CLI receives `fesa.exe `. 2. App scans all argv tokens left-to-right. The first token containing case-sensitive substring `--output` fails with one `cli-usage` diagnostic before path resolution, parse/map, analysis, lease, log, or HDF5. 3. App derives `_results.h5` and `_log.txt` beside the lexically normalized user-addressed `.inp`. 4. App acquires move-only `OutputWriteLease` and retains it until all log and HDF5 work ends. 5. App opens/truncates the log, then `PrepareAnalysisInput(input_path)` parses/maps once into `Domain`. 6. Procedure executor receives injected `ParallelFor` plus `LinearSolver` or `TangentSolver` and computes a fully validated linear or nonlinear state without opening HDF5. Nonlinear assembly forms `r = f_int - f_ext` and `K_T = K_int - K_ext` from Step 4 internal quantities and Step 5 global-once external quantities. Nonlinear state construction preserves each node's stable `EntityIndex` and full `SourceEntityId`; source label alone is never a row identity. 7. App closes the log successfully before invoking injected `ResultsWriter` or `NonlinearResultsWriter`. 8. HDF5 is the authoritative solver output. CSV views are comparison/debug artifacts only. ## Reference Inventory | path | role | rows | SHA-256 | | --- | --- | ---: | --- | | `reference/shellNL/shellNL.inp` | nonlinear input | input | `4BF3ECB0F7F1E8462C573E993DBC97AC5D920C91CF6F23AD4C6891D77FFBADA2` | | `reference/shellNL/shellNL displacements.csv` | required displacement CSV | 49 | `4E0F99CA9372B1ADF7FAF102F43BC0B887DC743FDEDA378E4342D2CF8E0C0786` | | `reference/shellNL/shellNL reactions.csv` | required reaction CSV | 49 | `001CB1541A9E94424E5E650509D46BC8724970DF4DE47184D9DB09C7938AB069` | | `reference/shellNL/shellNL stresses.csv` | nonblocking inventory artifact | 288 | `5500E5114B1C44887528E30CEC054A1EB0F68BE3F4B8CE81FA59FC74A881483F` | | `reference/shell/shell.inp` | linear input | input | `4005851E1AB22FD3A16AC17A8D5DA3E051233F69F37419079F3553AD134ECFCF` | | `reference/shell/shell displacements.csv` | required displacement CSV | 49 | `C81D94E0B4A849F87AA0F79C83A79B94D5661AC79E44ED826919AB432C87746B` | | `reference/shell/shell reactions.csv` | nonblocking inventory artifact | 49 | `0E34EEC27E700C3C0C744C1DAFD8A3B95EFEF34B8616FE96665876586FE82D41` | | `reference/shell/shell stresses.csv` | nonblocking inventory artifact | 288 | `2B75A5B0DEB045A283C9BB7E9B1153B79F7537FF487214BF4A23316B59B660A7` | Blocking and warning families: | family | components | rows | disposition | | --- | --- | ---: | --- | | `linear.translation` | `U1,U2,U3`, nodes `1..49` | 147 | blocking | | `linear.rotation` | `UR1,UR2,UR3`, nodes `1..49` | 147 | warning-only | | `nonlinear.translation` | `U1,U2,U3`, nodes `1..49` | 147 | blocking | | `nonlinear.rotation` | `UR1,UR2,UR3`, nodes `1..49` | 147 | warning-only | | `nonlinear.reaction_inplane_force` | `RF1,RF2`, constrained nodes | 48 | blocking | | `nonlinear.reaction_transverse_force` | `RF3`, constrained nodes | 24 | blocking | | `nonlinear.reaction_physical_moment` | `RM1,RM2`, constrained nodes | 48 | blocking | Constrained node labels for shellNL reactions: `1,3,4,5,6,7,8,9,14,15,16,17,22,23,24,25,26,27,28,29,30,31,32,33`. Exact shellNL `Frame`: `Increment 10: Step Time = 1.000`. Step 11 must not run original reference input paths directly. It snapshots exact original artifact inventory, copies input bytes unchanged into a unique build-local temp case directory, runs `FesaApplication` on the copied `.inp`, consumes copied-sibling `_results.h5` and `_log.txt`, compares generated HDF5 to original read-only CSVs, and then verifies original reference directory inventory, bytes, timestamps, and hashes are unchanged. HDF5 source path identity matches the copied user-addressed input; source content identity matches the approved input hash. ## Acceptance Traceability Matrix | requirement | Steps | test ids | | --- | --- | --- | | `FESA-REQ-NSNR-001` | 1,10 | `NSNR-IO-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-003` | 1,3,4,10 | `NSNR-IO-*`, `NSNR-ELEM-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-041` | 1,3,10 | `NSNR-IO-*`, `NSNR-ELEM-KIN-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-074` | 2,8,10 | `NSNR-ROT-*`, `NSNR-STATE-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-006` | 4,6,10 | `NSNR-ELEM-TAN-*`, `NSNR-SOLVER-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-007` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-069` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-070` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-008` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-014` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-046` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-048` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-018` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-063` | 5,10 | `NSNR-CTRL-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-016` | 1,5 | `NSNR-IO-*`, `NSNR-CTRL-*` | | `FESA-REQ-NSNR-011` | 8,9,10 | `NSNR-STATE-*`, `NSNR-HDF5-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-019` | 4,8,10 | `NSNR-ELEM-TAN-*`, `NSNR-STATE-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-020` | 1 | `NSNR-IO-*` | | `FESA-REQ-NSNR-021` | 8,9,10 | `NSNR-STATE-*`, `NSNR-HDF5-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-024` | 7,10 | `NSNR-LOG-*`, `NSNR-PROC-*` | | `FESA-REQ-NSNR-083` | 0,10,12 | `NSNR-CLI-*`, `NSNR-PROC-*`, `NSNR-EVID-*` | | `FESA-REQ-NSNR-026` | 8,10,11,12 | `NSNR-STATE-*`, `NSNR-PROC-*`, `NSNR-REF-*`, `NSNR-EVID-*` | | `FESA-REQ-NSNR-030` | 2,3,4,5,6,7,8,9,10,11 | `NSNR-ROT-*`, `NSNR-ELEM-*`, `NSNR-CTRL-*`, `NSNR-SOLVER-*`, `NSNR-LOG-*`, `NSNR-STATE-*`, `NSNR-HDF5-*`, `NSNR-PROC-*`, `NSNR-REF-*` | | `FESA-REQ-NSNR-034` | 11 | `NSNR-REF-*` | ## Numerical Review Coverage | category | Steps | | --- | --- | | linear-limit reduction | 3,4,10,11 | | rotation invariants and branch margin | 2,8,10 | | tangent directional derivative schedule | 4 | | no-moment tangent symmetry | 4 | | finite rigid objectivity | 3,4 | | patch/sign recovery | 3,4 | | load/boundary path and `rho_M` | 5,10 | | Newton factor/iteration lifecycle | 5,7,10 | | four convergence gates | 5,7,10 | | commit/rollback/determinism | 8,10,11,12 | ## Validation Commands Each Step must: 1. Recheck `.harness/config.json`. If present, use the configured Harness build/test commands. 2. If absent, use: ```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 --show-only=json-v1 ctest --test-dir .harness/build -C Debug --output-on-failure ``` Focused CTest commands are written explicitly in each `stepN.md`. Harness Python validation is not in scope unless a Step changes Harness Python behavior, hook behavior, or agent configuration. ## Risks And Downstream Handoff - Main implementation risk: current `LinearStaticAnalysis` owns parse/map and HDF5 write internally. Step 10 must refactor through prepared analysis flow so log close precedes HDF5 finalization for both linear and nonlinear runs. - Main numerical risk: nonlinear MITC4 tangent and finite rotation derivatives must pass internal derivative/objectivity tests before reference comparison can be meaningful. - Main backend risk: nonlinear tangent can be nonsymmetric. Preserve SPD `MklPardisoSolver` unchanged and add separate `TangentSolver`. - Handoff to Implementation Agent through Coordinator: execute Steps 0..12 in order, one current Step at a time, with RED observed failure evidence before GREEN implementation, then focused/full CTest. Final reference gate is Step 11; evidence-document closure is Step 12. ## Open Issues None. ## Plan Approval Boundary The user-approved plan and pending phase files do not authorize Harness execution. `scripts/execute.py nonlinear-static-newton-raphson` requires a separate explicit user request.