Integrate Refactor solver sources and dual MSVC CMake builds

This commit is contained in:
KOKO\Mimi
2026-10-18 02:10:51 +09:00
parent 7ee32e5837
commit 12d51480de
218 changed files with 17842 additions and 9689 deletions
@@ -18,6 +18,7 @@
#include "fesa/elements/hex8_element.h"
#include "fesa/fem/dof_manager.h"
#include "fesa/math/sparse_matrix.h"
#include "fesa/solvers/eigen/mkl_feast_eigen_solver.h"
#include "fesa/math/vector.h"
#include "fesa/model/domain.h"
@@ -50,7 +51,8 @@ double Ratio(double numerator, double denominator) {
return numerator / denominator;
}
/// @brief Builds an immutable candidate; all returns precede public commit.
Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain,
const EigenSolver& solver) {
const auto* frequency = domain.Frequency();
if (!domain.IsSolid() || frequency == nullptr ||
frequency->requested_mode_count <= 0)
@@ -76,6 +78,7 @@ Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
}
ElementFactory factory;
std::vector<std::unique_ptr<Element>> owned;
std::vector<std::unique_ptr<SolidTrialElement>> trials;
ElementView view;
for (const auto index : model.Value().ActiveElements()) {
const auto& definition = domain.Elements()[index];
@@ -87,11 +90,13 @@ Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
auto element = factory.Create(definition, domain);
if (!element.HasValue())
return Result<SolidFrequencyState>::Failure(element.GetStatus());
if (dynamic_cast<const Hex8Element*>(element.Value().get()) == nullptr)
auto trial = factory.BindSolidTrial(*element.Value());
if (trial == nullptr)
return Result<SolidFrequencyState>::Failure(
Failure("unsupported-frequency-element", "Only C3D8 is supported."));
view.emplace_back(*element.Value());
owned.push_back(std::move(element.Value()));
trials.push_back(std::move(trial));
}
DofManager dofs;
const Status mapping = dofs.Build(model.Value(), view);
@@ -121,7 +126,7 @@ Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
std::vector<std::size_t> additions_by_dof(dofs.FullDofCount(), 0U);
constexpr double eps = std::numeric_limits<double>::epsilon();
for (std::size_t e = 0; e < owned.size(); ++e) {
const auto& hex = static_cast<const Hex8Element&>(*owned[e]);
const auto& hex = *trials[e];
auto mass = hex.ComputeMass();
if (!mass.HasValue())
return Result<SolidFrequencyState>::Failure(mass.GetStatus());
@@ -220,7 +225,7 @@ Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
return Result<SolidFrequencyState>::Failure(
Failure("invalid-solid-eigen-scale",
"A positive finite classification scale is required."));
auto backend = MklFeastEigenSolver{}.SolveGeneralized(k, m, requested,
auto backend = solver.SolveGeneralized(k, m, requested,
mass_lower, scale);
if (!backend.HasValue())
return Result<SolidFrequencyState>::Failure(backend.GetStatus());
@@ -269,11 +274,11 @@ Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
"Normalized modal vector is not finite."));
}
mv = m.Multiply(vector);
const Vector kv = k.Multiply(vector);
Vector kv = k.Multiply(vector);
const double lambda = state.backend.eigenvalues[c];
const double modal_mass = vector.Dot(mv);
const double energy = vector.Dot(kv);
Vector residual = kv;
Vector residual = std::move(kv);
residual.Axpy(-lambda, mv);
const double norm_phi = vector.Norm();
const double residual_norm = residual.Norm();
@@ -355,7 +360,8 @@ Result<SolidFrequencyState> ExecuteCandidate(const Domain& domain) {
Result<SolidFrequencyState> SolidFrequencyProcedureExecutor::Execute(
const Domain& domain) const {
try {
auto result = ExecuteCandidate(domain);
const MklFeastEigenSolver default_solver;
auto result = ExecuteCandidate(domain, solver_ ? *solver_ : default_solver);
if (result.HasValue()) return result;
auto diagnostics = result.GetStatus().Diagnostics();
for (auto& diagnostic : diagnostics)