#ifndef FESA_ANALYSIS_SOLID_DYNAMIC_ANALYSIS_STATE_H_ #define FESA_ANALYSIS_SOLID_DYNAMIC_ANALYSIS_STATE_H_ #include #include #include #include #include #include #include "fesa/fem/dof_manager.h" #include "fesa/results/solid_result_records.h" namespace fesa { /// @brief Dimensionally explicit translation-only Newton evidence. struct SolidDynamicIterationEvidence { std::uint32_t iteration_index{0}; double residual_numerator{0}; // Force infinity norm. double residual_scale{0}; // Uncancelled force infinity scale. double residual_metric{0}; // Maximum componentwise force ratio. std::size_t worst_full_dof{0}; std::array worst_force_terms{}; // r,Ma,fint,F,uncancelled scale. double weighted_residual_numerator{0}; // Original HHT force infinity norm. double recombined_residual_numerator{ 0}; // Actual solved weighted force norm. double old_residual_numerator{0}; // Previous physical free force norm. double weighted_equivalence_metric{0}; // Uncancelled force identity ratio. std::array worst_weighted_terms{}; // Original,recombined,old r,scale. bool zero_scale_exact{true}; std::array correction_metrics{}; // du/L,h*dv/L,h²*da/L,h²*dA/L. double update_metric{0}; // Maximum uncancelled update equality ratio. bool residual_pass{false}; bool correction_pass{false}; bool update_pass{false}; }; /// @brief Failure-only shadow dot products; these never change force or /// acceptance. struct SolidDynamicLinearDotEvidence { EntityIndex element_index{0}; std::size_t local_row{0}; double absolute_product_sum{0}; double kernel_force{0}; double compensated_force{ 0}; // Shadow using rounded relative differences only. }; /// @brief Failure-only coordinate arithmetic evidence, with length units. struct SolidDynamicCoordinateEvidence { EntityIndex element_index{0}; std::size_t local_row{0}; double displacement{0}; double previous_displacement{0}; double fresh_correction{0}; double reference_displacement{0}; double previous_reference_displacement{0}; double relative_high{0}; double previous_relative_high{0}; }; /// @brief Failure-only arithmetic shadow; never substitutes physical forces. struct SolidDynamicForceSumEvidence { double assembled_internal{0}; double compensated_internal{0}; double absolute_local_internal_sum{0}; double assembled_inertia{0}; double compensated_inertia{0}; double absolute_inertia_product_sum{0}; }; /// @brief Internal exact-candidate recurrence evidence, separate from gates. struct SolidDynamicNewtonRepeatEvidence { std::size_t history_entry_count{0}; std::uint32_t matched_entry_iteration{0}; std::size_t changed_translations{0}; std::size_t changed_holding_mask{0}; std::size_t changed_correction_metrics{0}; bool repeat{false}; }; /// @brief Keeps failed attempt evidence outside the accepted physical history. struct SolidDynamicIterationRecord { std::uint32_t increment_index{0}; double time{0}; std::string stage; std::string outcome; std::string failure_code; SolidDynamicIterationEvidence evidence; std::vector failure_linear_dot; std::vector failure_coordinates; std::optional failure_force_sum; std::optional newton_repeat; }; /// @brief Retains normalized physical low parts; never serialized as extra /// result fields. Corresponding endpoint fields contain the nearest Float64 /// high parts. Both parts are copied and validated together at commit. struct SolidDynamicFrameLowParts { Vector displacement{0}; Vector velocity{0}; Vector acceleration{0}; Vector algorithmic_acceleration{0}; Vector inertia_force{0}; Vector internal_force{0}; Vector external_force{0}; Vector residual{0}; Vector reaction{0}; Vector residual_scale{0}; double strain_energy{0}; double kinetic_energy{0}; double external_work{0}; double energy_balance_error{0}; std::array linear_momentum{}; std::array angular_momentum{}; std::array linear_momentum_rate{}; std::array angular_momentum_rate{}; std::array global_equilibrium{}; std::array linearization_current_internal_moment{}; std::array reference_internal_moment{}; std::array current_free_residual_moment{}; }; /// @brief Owns one complete Solid endpoint; physical a differs from auxiliary /// A. struct SolidDynamicAcceptedFrameState { std::uint32_t frame_index{0}; std::uint32_t increment_index{0}; std::uint32_t iteration_count{0}; double time{0}; bool is_initial{false}; std::vector nodal_internal_order; std::vector nodal_source_ids; Vector displacement{0}; Vector velocity{0}; Vector acceleration{0}; Vector algorithmic_acceleration{0}; Vector inertia_force{0}; Vector internal_force{0}; Vector external_force{0}; Vector residual{0}; Vector reaction{0}; Vector residual_scale{0}; std::vector solid_results; double strain_energy{0}; double kinetic_energy{0}; double external_work{0}; double energy_balance_error{0}; std::array linear_momentum{}; std::array angular_momentum{}; std::array linear_momentum_rate{}; std::array angular_momentum_rate{}; std::array global_equilibrium{}; // Internal evidence, not additional official output fields. std::array linearization_current_internal_moment{}; std::array reference_internal_moment{}; std::array current_free_residual_moment{}; std::vector iterations; SolidDynamicFrameLowParts low; }; /// @brief Owns only validated accepted Solid history; rejects partial /// candidates. class SolidDynamicAnalysisState { public: /// @brief Creates an empty state for exactly one zero-BC fixed dynamic /// schedule. static Result Create(const Domain& domain, const DofManager& dofs); /// @brief Validates shape, identity, schedule, finite values and Newton /// evidence. /// @note A failed candidate never changes accepted frames or current state. Status CommitAcceptedFrame(const SolidDynamicAcceptedFrameState& frame); /// @brief Returns an independent accepted endpoint copy for trial /// preparation. Result BeginTrialFromCommitted() const; /// @brief Returns accepted endpoints in source increment order. const std::vector& AcceptedFrames() const noexcept; /// @brief Returns the last endpoint; throws when no frame is accepted. const SolidDynamicAcceptedFrameState& CommittedState() const; /// @brief Reports whether schedule and inventory have been initialized. bool IsInitialized() const noexcept; /// @brief Appends attempt evidence without committing physical state. void RecordIteration(SolidDynamicIterationRecord record); /// @brief Returns attempt evidence, including a terminal failure if present. const std::vector& IterationRecords() const noexcept; private: std::size_t full_dof_count_{0}; std::uint32_t increment_count_{0}; double time_increment_{0}; std::vector constrained_dofs_; std::vector source_ids_; std::vector point_inventory_; std::vector accepted_frames_; std::vector iteration_records_; bool initialized_{false}; }; } // namespace fesa #endif // FESA_ANALYSIS_SOLID_DYNAMIC_ANALYSIS_STATE_H_