#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/math/vector.h" namespace fesa { class DofManagerTestAccess; /// @brief Stores the stable structural 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 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 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 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 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 structural CSR pattern. 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_; }; } // namespace fesa #endif // FESA_FEM_DOF_MANAGER_H_