#ifndef FESA_ANALYSIS_EQUILIBRIUM_ALGORITHM_H_ #define FESA_ANALYSIS_EQUILIBRIUM_ALGORITHM_H_ #include #include #include #include #include "fesa/core/status.h" namespace fesa { /// @brief Controls evaluated iteration order without owning a family candidate. /// @note Evaluation and its referenced trial context remain alive and unmoved /// throughout this call. A successful evaluation value means candidate ready. class EquilibriumAlgorithm { public: using Evaluation = std::function(std::uint32_t)>; virtual ~EquilibriumAlgorithm() = default; virtual Status SolveCurrentStep(std::uint32_t first, std::uint32_t last, const Evaluation& evaluate) = 0; }; /// @brief Preserves the original inclusive full-Newton evaluation sequence. class NewtonStepAlgorithm final : public EquilibriumAlgorithm { public: Status SolveCurrentStep(std::uint32_t first, std::uint32_t last, const Evaluation& evaluate) override { for (std::uint32_t iteration = first; iteration <= last; ++iteration) { auto result = evaluate(iteration); if (!result.HasValue()) return result.GetStatus(); if (result.Value()) return Status::Ok(); } // Family evaluators retain their original final-evaluation failure. return Status::Ok(); } }; /// @brief Owns one procedure-local typed evaluator and unpublished candidate. /// @note This value is not an algorithm interface. The injected algorithm never /// owns or type-erases Candidate, and neither callback nor context may escape. template class EquilibriumStep { public: using Evaluation = std::function>(std::uint32_t)>; EquilibriumStep(Evaluation evaluate, std::uint32_t maximum) : evaluate_(std::move(evaluate)), maximum_(maximum) {} EquilibriumStep(const EquilibriumStep&) = delete; EquilibriumStep& operator=(const EquilibriumStep&) = delete; Status Solve(EquilibriumAlgorithm& algorithm) { const EquilibriumAlgorithm::Evaluation evaluate = [this](std::uint32_t iteration) -> Result { auto result = evaluate_(iteration); if (!result.HasValue()) return Result::Failure(result.GetStatus()); if (result.Value().has_value()) { pending_ = std::move(result.Value()); return Result::Success(true); } return Result::Success(false); }; return algorithm.SolveCurrentStep(kFirstIteration, maximum_, evaluate); } bool HasCandidate() const { return pending_.has_value(); } /// @brief Transfers the validated candidate to the procedure commit boundary. Candidate TakeCandidate() { return std::move(pending_.value()); } private: Evaluation evaluate_; std::uint32_t maximum_; std::optional pending_; }; // Static evaluations start at one; mechanical HHT corrections start at zero. // Evaluation at the maximum still performs the existing endpoint validation. template using ShellFullNewtonStep = EquilibriumStep; template using SolidFullNewtonStep = EquilibriumStep; template using ReducedShellHhtStep = EquilibriumStep; template using SolidHhtStep = EquilibriumStep; } // namespace fesa #endif // FESA_ANALYSIS_EQUILIBRIUM_ALGORITHM_H_