#ifndef FESA_ANALYSIS_THERMAL_ANALYSIS_STATE_H_ #define FESA_ANALYSIS_THERMAL_ANALYSIS_STATE_H_ #include #include #include #include "fesa/analysis/thermal_time_grid.h" #include "fesa/core/status.h" #include "fesa/results/thermal_result_records.h" namespace fesa { class AnalysisModel; class DofManager; class ThermalAssembly; /// @brief Owns the immutable thermal result inventory and accepted history. /// @note No Domain/model/assembly references survive Create; state may outlive /// them. Numerical equilibrium and energy checks belong to the procedure before /// Commit. class ThermalAnalysisState final { public: /// @brief Validates the inventory/schedule and commits raw initial /// temperature. /// @note Initial frame has no recovery payload and is never projected onto /// BCs. static Result Create(const AnalysisModel& model, const DofManager& dofs, const ThermalAssembly& assembly); /// @brief Builds a complete typed candidate without changing accepted /// history. /// @param temperature Full node-major temperature, including prescribed /// values. /// @param reaction Constrained full residual in ReactionDofs() order, even if /// empty. /// @param flux Global element fluxes in ElementOrder(), point/trace order. Result MakeCompletedFrame( std::uint32_t index, Vector temperature, Vector reaction, std::vector flux) const; /// @brief Atomically appends the next finite frame after exact /// mapping/schedule checks. /// @note Rejection preserves every existing frame; caller-owned candidates /// stay independent. Status CommitAcceptedFrame(const ThermalAcceptedFrame& frame); /// @brief Returns accepted frames, beginning with raw frame zero. const std::vector& AcceptedFrames() const noexcept; /// @brief Returns the most recently committed state; Create always supplies /// frame zero. const ThermalAcceptedFrame& CommittedState() const noexcept; /// @brief Reports whether every scheduled increment has been committed. bool IsComplete() const noexcept; /// @brief Returns the exact time-grid schedule used to validate accepted /// frames. const ThermalTimeGrid& TimeGrid() const noexcept; /// @brief Returns original nominal dt for metadata, independent of actual /// last delta. double NominalTimeIncrement() const noexcept; /// @brief Returns the exact input end time for metadata. double TimePeriod() const noexcept; /// @brief Returns active Domain node IDs in temperature row order. const std::vector& NodeOrder() const noexcept; /// @brief Returns immutable source identities corresponding to NodeOrder(). const std::vector& NodeSourceIds() const noexcept; /// @brief Returns Domain element IDs in flux/frame row order. const std::vector& ElementOrder() const noexcept; /// @brief Returns immutable source identities corresponding to /// ElementOrder(). const std::vector& ElementSourceIds() const noexcept; /// @brief Returns the N by 5 free=0/prescribed=1 mask. const std::vector>& ConstraintMask() const noexcept; /// @brief Returns prescribed node/source-DOF identities in node/station /// order. const std::vector& ReactionDofs() const noexcept; /// @brief Returns E by 4 fixed local frames, stored once for the entire /// history. const std::vector& FluxLocalFrames() const noexcept; private: /// @brief Takes an exact schedule; Create then fills the validated inventory. ThermalAnalysisState(ThermalTimeGrid grid, double nominal, double period); /// @brief Checks frame metadata, mapping, payload shape and finite values. Status ValidateFrame(const ThermalAcceptedFrame& frame) const; ThermalTimeGrid grid_; double nominal_; double period_; std::vector node_order_; std::vector node_source_ids_; std::vector element_order_; std::vector element_source_ids_; std::vector> constraint_mask_; std::vector reaction_dofs_; std::vector local_frames_; std::vector frames_; }; } // namespace fesa #endif // FESA_ANALYSIS_THERMAL_ANALYSIS_STATE_H_