#pragma once #include "fesa/core/status.h" #include "fesa/fem/dof_manager.hpp" #include "fesa/math/vector.h" #include "fesa/results/result_records.hpp" #include #include #include namespace fesa { // Owns only the mutable quantities required by the V0 linear-static frame. class AnalysisState { public: static AnalysisState create( const DofManager& dofs, StepFrameIdentity identity); Vector& displacement() noexcept; const Vector& displacement() const noexcept; Vector& externalForce() noexcept; const Vector& externalForce() const noexcept; Vector& internalForce() noexcept; const Vector& internalForce() const noexcept; Vector& residual() noexcept; const Vector& residual() const noexcept; Vector& reaction() noexcept; const Vector& reaction() const noexcept; const StepFrameIdentity& identity() const noexcept; std::vector& endpointResults() noexcept; const std::vector& endpointResults() const noexcept; std::vector& gaussResults() noexcept; const std::vector& gaussResults() const noexcept; std::vector& stressResults() noexcept; const std::vector& stressResults() const noexcept; Status commitShellResults( const std::vector& expectedElementOrder, ShellStateCandidate candidate); const std::vector& shellResults() const noexcept; double physicalStrainEnergy() const noexcept; const std::array& equilibrium() const noexcept; const std::array& verificationMetrics() const noexcept; private: AnalysisState(std::size_t fullDofCount, StepFrameIdentity identity); StepFrameIdentity identity_; Vector displacement_; Vector externalForce_; Vector internalForce_; Vector residual_; // Reactions retain full-index space so free residual components remain visible. Vector reaction_; // Recovery appends rows in stable element/location order. std::vector endpointResults_; std::vector gaussResults_; std::vector stressResults_; // Shell recovery is replaced only through validated candidate commit. std::vector shellResults_; double physicalStrainEnergy_{0.0}; std::array equilibrium_{}; std::array verificationMetrics_{}; }; } // namespace fesa