Files
FESADev/src/fesa/analysis/equilibrium_algorithm.h
T

87 lines
3.4 KiB
C++

#ifndef FESA_ANALYSIS_EQUILIBRIUM_ALGORITHM_H_
#define FESA_ANALYSIS_EQUILIBRIUM_ALGORITHM_H_
#include <cstdint>
#include <functional>
#include <optional>
#include <utility>
#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<Result<bool>(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 <typename Candidate, std::uint32_t kFirstIteration>
class EquilibriumStep {
public:
using Evaluation =
std::function<Result<std::optional<Candidate>>(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<bool> {
auto result = evaluate_(iteration);
if (!result.HasValue()) return Result<bool>::Failure(result.GetStatus());
if (result.Value().has_value()) {
pending_ = std::move(result.Value());
return Result<bool>::Success(true);
}
return Result<bool>::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<Candidate> pending_;
};
// Static evaluations start at one; mechanical HHT corrections start at zero.
// Evaluation at the maximum still performs the existing endpoint validation.
template <typename Candidate>
using ShellFullNewtonStep = EquilibriumStep<Candidate, 1U>;
template <typename Candidate>
using SolidFullNewtonStep = EquilibriumStep<Candidate, 1U>;
template <typename Candidate>
using ReducedShellHhtStep = EquilibriumStep<Candidate, 0U>;
template <typename Candidate>
using SolidHhtStep = EquilibriumStep<Candidate, 0U>;
} // namespace fesa
#endif // FESA_ANALYSIS_EQUILIBRIUM_ALGORITHM_H_