#ifndef FESA_FEM_DOF_MANAGER_H_ #define FESA_FEM_DOF_MANAGER_H_ #include #include #include #include #include "fesa/analysis/analysis_model.h" #include "fesa/constraints/boundary_condition.h" #include "fesa/elements/element.h" #include "fesa/elements/thermal_element_layout.h" #include "fesa/math/vector.h" namespace fesa { class DofManagerTestAccess; /// @brief Distinguishes six-component, Solid translation, and thermal maps. enum class DofProfile { kStructural, kThermal, kSolidStructural }; /// @brief Stores the stable full-space CSR pattern. struct SparsePattern { std::vector row_offsets; std::vector column_indices; }; /// @brief Owns full/free/constrained numbering, scatter maps, and CSR pattern. class DofManager { public: /// @brief Creates an empty candidate for atomic Build replacement. DofManager() = default; /// @brief Creates every equation-space mapping for an active model. /// @note This compatibility entry point derives temporary semantic layouts; /// the procedure-owned runtime element view supersedes it in Step 20. static Result Create(const AnalysisModel& model); /// @brief Builds the active DS4 five-station equation mapping. static Result CreateThermal(const AnalysisModel& model); /// @brief Builds mappings from runtime element layouts in supplied order. /// @param analysis_model Non-owning active model view that outlives this /// call. /// @param elements Runtime elements in stable active source order. /// @return Success after atomic replacement or a structured model failure. Status Build(const AnalysisModel& analysis_model, const ElementView& elements); /// @brief Builds mappings from explicit runtime elements and boundaries. /// @param boundaries Non-owning definitions in stable source order. /// @return Success after atomic replacement or a structured failure. Status Build(const AnalysisModel& analysis_model, const ElementView& elements, const BoundaryConditionView& boundaries); /// @brief Builds thermal mappings from stable DS4 semantic layouts. Status BuildThermal(const AnalysisModel& analysis_model, const std::vector& layouts); /// @brief Reports which physical component profile owns this mapping. DofProfile Profile() const noexcept; /// @brief Returns the physical component count for the active profile. std::size_t ComponentsPerNode() const noexcept; /// @brief Returns the full node-by-component DOF count. std::size_t FullDofCount() const noexcept; /// @brief Returns the free-equation count. std::size_t FreeDofCount() const noexcept; /// @brief Returns the prescribed-DOF count. std::size_t ConstrainedDofCount() const noexcept; /// @brief Maps a stable node index and component to a full DOF. std::size_t FullDof(EntityIndex node, DofComponent component) const; /// @brief Maps an active thermal Domain node and station to a full DOF. std::size_t FullThermalDof(EntityIndex node, ThermalDofComponent component) const; /// @brief Returns the free equation for a full DOF when unconstrained. std::optional FreeEquation(std::size_t full_dof) const; /// @brief Maps one declared runtime layout to stable full DOFs. /// @return The declared node/component scatter or a layout failure. Result> ElementScatter( const ElementDofLayout& layout) const; /// @brief Maps one DS4 layout to its node-major 20-entry scatter. Result> ThermalElementScatter( const ThermalElementDofLayout& layout) const; /// @brief Returns a beam scatter in endpoint/component order. /// @note This compatibility wrapper delegates to the generic stored layout. std::array ElementScatter(EntityIndex element) const; /// @brief Returns a shell scatter in node/component order. /// @note This compatibility wrapper delegates to the generic stored layout. std::array ShellElementScatter(EntityIndex element) const; /// @brief Returns free full DOFs in stable increasing order. const std::vector& FreeDofs() const noexcept; /// @brief Returns constrained full DOFs in stable increasing order. const std::vector& ConstrainedDofs() const noexcept; /// @brief Returns dc in constrained-DOF order. const Vector& PrescribedValues() const noexcept; /// @brief Returns the full-space CSR pattern for the active profile. const SparsePattern& GetSparsePattern() const noexcept; /// @brief Validates the complete owner-issued equation and pattern mapping. Status ValidateInvariants() const; private: friend class DofManagerTestAccess; /// @brief Builds from copied layouts after the caller fixes their order. Status BuildLayouts(const AnalysisModel& analysis_model, const std::vector& layouts, const BoundaryConditionView& boundaries); /// @brief Takes ownership of fully validated stable equation mappings. DofManager(std::size_t full_dof_count, std::vector> free_equations, std::vector> element_scatters, std::vector free_dofs, std::vector constrained_dofs, Vector prescribed_values, SparsePattern sparse_pattern); std::size_t full_dof_count_{0U}; std::vector> free_equations_; std::vector> element_scatters_; std::vector free_dofs_; std::vector constrained_dofs_; Vector prescribed_values_{0U}; SparsePattern sparse_pattern_; DofProfile profile_{DofProfile::kStructural}; std::vector> thermal_node_rows_; }; } // namespace fesa #endif // FESA_FEM_DOF_MANAGER_H_