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
@@ -1,4 +1,7 @@
#include "fesa/analysis/solid_static_procedure.h"
#include "analysis/solid_static_core.h"
#include "analysis/equilibrium_algorithm.h"
#include "fesa/core/source_identity.h"
#include <gtest/gtest.h>
@@ -7,6 +10,7 @@
#include <fstream>
#include <iostream>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
@@ -824,3 +828,116 @@ TEST(SolidStaticProcedure,
<< " energy=" << frame.physical_strain_energy << '\n';
}
}
namespace {
fesa::Status StaticPolicyFailure() {
return fesa::Status::Failure(fesa::FailureCategory::kSolver,
{{fesa::Severity::kError, "injected-static-algorithm", {}, "STATIC",
"original-owner", "Original algorithm failure."}});
}
class UnusedStaticSolvers final : public fesa::LinearSolver,
public fesa::TangentSolver {
public:
mutable int calls = 0;
fesa::Status Factorize(const fesa::SparseMatrix&) override {
++calls; return StaticPolicyFailure();
}
fesa::Status Solve(const fesa::Vector&, fesa::Vector&) const override {
++calls; return StaticPolicyFailure();
}
fesa::Status FactorizeFresh(const fesa::SparseMatrix&) override {
++calls; return StaticPolicyFailure();
}
fesa::Status SolveCorrection(const fesa::Vector&, fesa::Vector&) const override {
++calls; return StaticPolicyFailure();
}
};
class RefusingStaticAlgorithm final : public fesa::EquilibriumAlgorithm {
public:
RefusingStaticAlgorithm(const fesa::SolidStaticState& state, bool& destroyed)
: state_(state), destroyed_(destroyed) {}
~RefusingStaticAlgorithm() override { destroyed_ = true; }
int calls = 0;
fesa::SolidStaticFrame baseline;
fesa::Status SolveCurrentStep(std::uint32_t first, std::uint32_t last,
const Evaluation&) override {
++calls;
EXPECT_EQ(first, 1U); EXPECT_EQ(last, 100U);
EXPECT_TRUE(state_.AcceptedFrames().empty());
EXPECT_TRUE(state_.IterationRecords().empty());
baseline = state_.CommittedState();
return StaticPolicyFailure();
}
private:
const fesa::SolidStaticState& state_;
bool& destroyed_;
};
} // namespace
TEST(SolidStaticProcedure, InjectedAlgorithmFailurePreservesInitializedBaseline) {
auto domain = Map(Deck(Supports(), Tension(1.0), true));
ASSERT_TRUE(domain.HasValue()) << Message(domain.GetStatus());
fesa::SerialParallelFor serial;
UnusedStaticSolvers solvers;
fesa::SolidStaticState state;
bool destroyed = false;
auto owned = std::make_unique<RefusingStaticAlgorithm>(state, destroyed);
auto* selected = owned.get();
std::unique_ptr<fesa::EquilibriumAlgorithm> algorithm = std::move(owned);
{
fesa::SolidStaticCore core(serial, solvers, solvers, *algorithm);
const auto status = core.ExecuteInto(domain.Value(), state);
ASSERT_FALSE(status.IsOk());
EXPECT_EQ(status.Category(), fesa::FailureCategory::kSolver);
ASSERT_EQ(status.Diagnostics().size(), 1U);
const auto& diagnostic = status.Diagnostics()[0];
EXPECT_EQ(diagnostic.code, "injected-static-algorithm");
EXPECT_EQ(diagnostic.keyword, "STATIC");
EXPECT_EQ(diagnostic.entity_identity, "original-owner");
EXPECT_EQ(diagnostic.message, "Original algorithm failure.");
}
EXPECT_EQ(selected->calls, 1); EXPECT_EQ(solvers.calls, 0);
EXPECT_TRUE(state.AcceptedFrames().empty());
EXPECT_TRUE(state.IterationRecords().empty());
// Core initialization legitimately installs the zero-factor baseline before
// iteration. Compare to that exact baseline at algorithm entry, not to the
// initially uninitialized observer.
const auto& expected = selected->baseline;
const auto& actual = state.CommittedState();
EXPECT_EQ(actual.frame_index, expected.frame_index);
EXPECT_EQ(actual.increment_index, expected.increment_index);
EXPECT_DOUBLE_EQ(actual.load_factor, expected.load_factor);
EXPECT_EQ(actual.iteration_count, expected.iteration_count);
EXPECT_EQ(actual.is_factor_one, expected.is_factor_one);
EXPECT_EQ(actual.nodal_internal_order, expected.nodal_internal_order);
ASSERT_EQ(actual.nodal_source_ids.size(), expected.nodal_source_ids.size());
for (std::size_t i = 0; i < actual.nodal_source_ids.size(); ++i)
EXPECT_TRUE(fesa::SourceIdentityEquals(actual.nodal_source_ids[i], expected.nodal_source_ids[i]));
const auto same_vector = [](const fesa::Vector& a, const fesa::Vector& b) {
ASSERT_EQ(a.Size(), b.Size());
for (std::size_t i = 0; i < a.Size(); ++i) EXPECT_DOUBLE_EQ(a[i], b[i]);
};
same_vector(actual.displacement, expected.displacement);
same_vector(actual.internal_force, expected.internal_force);
same_vector(actual.external_force, expected.external_force);
same_vector(actual.residual, expected.residual); same_vector(actual.reaction, expected.reaction);
EXPECT_DOUBLE_EQ(actual.physical_strain_energy, expected.physical_strain_energy);
EXPECT_EQ(actual.global_equilibrium, expected.global_equilibrium);
EXPECT_EQ(actual.balance.internal_force_sum, expected.balance.internal_force_sum);
EXPECT_EQ(actual.balance.reference_internal_moment, expected.balance.reference_internal_moment);
EXPECT_EQ(actual.balance.current_internal_moment, expected.balance.current_internal_moment);
EXPECT_EQ(actual.balance.free_residual_moment, expected.balance.free_residual_moment);
EXPECT_EQ(actual.balance.linearization_moment, expected.balance.linearization_moment);
EXPECT_EQ(actual.balance.internal_force_scale, expected.balance.internal_force_scale);
EXPECT_EQ(actual.balance.reference_moment_scale, expected.balance.reference_moment_scale);
EXPECT_EQ(actual.balance.current_moment_scale, expected.balance.current_moment_scale);
ASSERT_EQ(actual.solid_results.size(), expected.solid_results.size());
for (std::size_t i = 0; i < actual.solid_results.size(); ++i) {
const auto& a = actual.solid_results[i]; const auto& b = expected.solid_results[i];
EXPECT_EQ(a.element, b.element); EXPECT_EQ(a.integration_point, b.integration_point);
EXPECT_EQ(a.natural_coordinates, b.natural_coordinates);
EXPECT_EQ(a.reference_coordinates, b.reference_coordinates);
EXPECT_EQ(a.cauchy_stress, b.cauchy_stress); EXPECT_EQ(a.strain, b.strain);
}
EXPECT_FALSE(destroyed); algorithm.reset(); EXPECT_TRUE(destroyed);
}