87 lines
3.4 KiB
C++
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_
|