166 lines
7.8 KiB
Markdown
166 lines
7.8 KiB
Markdown
# Step 8: nonlinear-state-commit-rollback
|
|
|
|
## 읽어야 할 파일
|
|
|
|
- `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/io.md`
|
|
- `include/fesa/analysis/analysis_state.h`
|
|
- `src/fesa/analysis/analysis_state.cpp`
|
|
- `include/fesa/core/source_identity.h`
|
|
- `include/fesa/fem/dof_manager.h`
|
|
- `include/fesa/model/domain.h`
|
|
- `include/fesa/results/result_records.h`
|
|
- Step 3 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
|
|
- Step 4 files: `include/fesa/elements/nonlinear_mitc4_shell.h`
|
|
- 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 전제
|
|
|
|
Steps 3-7 provide nonlinear element recovery, residual/tangent, controls, tangent solver, and Newton log record types.
|
|
|
|
## 소유 파일
|
|
|
|
- Create: `include/fesa/analysis/nonlinear_analysis_state.h`
|
|
- Create: `src/fesa/analysis/nonlinear_analysis_state.cpp`
|
|
- Create: `tests/unit/analysis/nonlinear_analysis_state_test.cpp`
|
|
- Modify: `src/fesa/CMakeLists.txt`
|
|
- Modify: `tests/CMakeLists.txt`
|
|
|
|
## 인터페이스
|
|
|
|
```cpp
|
|
namespace fesa {
|
|
|
|
struct NonlinearNodeBaseline {
|
|
EntityIndex node_index;
|
|
SourceEntityId source_id;
|
|
std::array<std::array<double, 3>, 3> triad;
|
|
std::array<double, 3> director;
|
|
};
|
|
|
|
struct NonlinearStateBaselineInput {
|
|
std::vector<NonlinearNodeBaseline> node_baselines;
|
|
};
|
|
|
|
struct NonlinearTrialState {
|
|
std::uint32_t increment_index;
|
|
double load_factor;
|
|
bool is_factor_zero_baseline;
|
|
std::vector<EntityIndex> nodal_internal_order;
|
|
std::vector<SourceEntityId> nodal_source_ids;
|
|
Vector generalized_coordinates;
|
|
Vector displacement;
|
|
Vector rotation_vector;
|
|
std::vector<std::array<std::array<double, 3>, 3>> nodal_triad;
|
|
std::vector<std::array<double, 3>> nodal_director;
|
|
Vector internal_force;
|
|
Vector external_force;
|
|
Vector residual;
|
|
Vector reaction;
|
|
std::vector<ShellResultRow> shell_results;
|
|
double physical_strain_energy;
|
|
std::array<double, 6> global_equilibrium;
|
|
};
|
|
|
|
struct AcceptedFrameState {
|
|
std::uint32_t frame_index;
|
|
std::uint32_t increment_index;
|
|
double load_factor;
|
|
std::uint32_t iteration_count;
|
|
bool is_factor_one;
|
|
std::vector<EntityIndex> nodal_internal_order;
|
|
std::vector<SourceEntityId> nodal_source_ids;
|
|
Vector generalized_coordinates;
|
|
Vector displacement;
|
|
Vector rotation_vector;
|
|
std::vector<std::array<std::array<double, 3>, 3>> nodal_triad;
|
|
std::vector<std::array<double, 3>> nodal_director;
|
|
Vector internal_force;
|
|
Vector external_force;
|
|
Vector residual;
|
|
Vector reaction;
|
|
std::vector<ShellResultRow> shell_results;
|
|
double physical_strain_energy;
|
|
std::array<double, 6> global_equilibrium;
|
|
};
|
|
|
|
class NonlinearAnalysisState {
|
|
public:
|
|
static Result<NonlinearAnalysisState> Create(
|
|
const Domain& domain,
|
|
const DofManager& dofs,
|
|
const NonlinearStateBaselineInput& baseline);
|
|
|
|
Result<NonlinearTrialState> BeginTrialFromCommitted() const;
|
|
Status CommitAcceptedFrame(const AcceptedFrameState& frame);
|
|
void DiscardTrial() noexcept;
|
|
const std::vector<AcceptedFrameState>& AcceptedFrames() const noexcept;
|
|
const NonlinearTrialState& CommittedState() const noexcept;
|
|
};
|
|
|
|
} // namespace fesa
|
|
```
|
|
|
|
## RED
|
|
|
|
Add tests first.
|
|
|
|
- `NSNR-STATE-000`: `NonlinearAnalysisState::Create` requires exactly one `NonlinearNodeBaseline` per `Domain.Nodes()` entry in stable internal order; each entry has `node_index` equal to its vector offset and `source_id` equal to `Domain.Nodes()[node_index].source_id`.
|
|
- `NSNR-STATE-001`: `NonlinearAnalysisState::Create` rejects missing, extra, duplicate, out-of-order, or instance-label mismatched node identities before any mutable state is produced.
|
|
- `NSNR-STATE-002`: `NonlinearAnalysisState::Create` validates node/DOF/frame inventory, sizes all vectors, preserves `nodal_internal_order` and `nodal_source_ids`, and creates a committed factor-zero baseline with `increment_index=0`, `load_factor=0.0`, `is_factor_zero_baseline=true`, and no accepted frames.
|
|
- `NSNR-STATE-003`: duplicate source labels across different instances remain distinct when `SourceEntityId::instance_name` differs.
|
|
- `NSNR-STATE-004`: trial state starts from committed state and can be discarded without mutation.
|
|
- `NSNR-STATE-005`: accepted frames are appended in stable accepted-factor order.
|
|
- `NSNR-STATE-006`: frame index is zero-based accepted-frame order; the factor-zero committed baseline is metadata/state only and is never appended as an accepted frame.
|
|
- `NSNR-STATE-007`: final frame at load factor `1.0` has `is_factor_one=true`.
|
|
- `NSNR-STATE-008`: residual and reaction are stored from full residual `r = f_int - f_ext`.
|
|
- `NSNR-STATE-009`: accepted frame owns generalized coordinates, displacement, rotation vector, per-node identity/order, per-node triad/director, internal/external/residual/reaction, stable `ShellResultRow` recovery, physical strain energy, and global equilibrium.
|
|
- `NSNR-STATE-010`: all accepted-frame vectors match node/DOF counts and all `ShellResultRow` rows are stable element/midsurface order.
|
|
- `NSNR-STATE-011`: commit validates finite values for every approved scalar and atomically rejects nonfinite frames with `invalid-accepted-state`.
|
|
- `NSNR-STATE-012`: failed trial preserves prior committed state.
|
|
- `NSNR-STATE-013`: no unapproved verification data is stored.
|
|
- `NSNR-STATE-014`: committed and accepted nodal identity vectors are preserved for Step 9 HDF5 node datasets and Step 11 HDF5-to-reference source mapping; source label alone is never used as identity.
|
|
|
|
Run:
|
|
|
|
```powershell
|
|
cmake --build --preset windows-msvc-ninja-debug
|
|
ctest --preset windows-msvc-ninja-debug -R "NonlinearAnalysisState|CommitRollback" --output-on-failure
|
|
```
|
|
|
|
Expected: new tests fail. Unexpected pass stops.
|
|
|
|
## GREEN
|
|
|
|
Implement `NonlinearAnalysisState::Create` as the only construction seam for a valid nonlinear state. It uses `Domain`, `DofManager`, and `NonlinearStateBaselineInput` to require one baseline per Domain node in stable internal order, match both `EntityIndex` and full `SourceEntityId`, allocate zero generalized/displacement/rotation/internal/external/residual/reaction vectors, preserve nodal order/source identity for HDF5/reference mapping, install finite per-node triads/directors, and establish the committed factor-zero baseline without adding an accepted frame. Commit validates inventory, order, shape, identity, and finiteness before mutating committed state.
|
|
|
|
## VERIFY
|
|
|
|
```powershell
|
|
cmake --preset windows-msvc-ninja-debug
|
|
cmake --build --preset windows-msvc-ninja-debug
|
|
ctest --preset windows-msvc-ninja-debug -R "NonlinearAnalysisState|CommitRollback" --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 8 status and one-line payload. Executor owns timestamps, commits, retry, and advancement.
|
|
|
|
## 금지사항
|
|
|
|
- Do not put equation ids into Node or Element objects. 이유: `DofManager` owns equation numbering.
|
|
- Do not identify baseline nodes by source label alone. 이유: labels are not unique across instances and cannot support stable HDF5/reference mapping.
|
|
- Do not commit trial data before convergence gates pass. 이유: rollback/preservation contract depends on committed-state isolation.
|
|
- Do not expand existing `AnalysisState` for future nonlinear features. 이유: this Step owns only approved NSNR state.
|
|
- Do not store stress projections or verification data outside approved `ShellResultRow`, physical energy, and global equilibrium fields. 이유: schema v1 has a bounded accepted-state contract.
|