feat(cpp-object-oriented-modular-refactoring): step 18 - load-hierarchy

This commit is contained in:
KOKO\Mimi
2026-08-16 10:56:57 +09:00
parent 08d352ae46
commit 9ad72e6d21
18 changed files with 705 additions and 137 deletions
@@ -16,6 +16,7 @@
#include "fesa/analysis/analysis_model.h"
#include "fesa/fem/dof_manager.h"
#include "fesa/loads/load.h"
#include "fesa/model/domain.h"
namespace {
@@ -167,8 +168,66 @@ void ExpectFailureCode(const fesa::Result<fesa::Vector>& result,
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].code, code);
}
class FakeLoad final : public fesa::Load {
public:
explicit FakeLoad(std::vector<fesa::LoadContribution> contributions)
: contributions_{std::move(contributions)} {}
fesa::Result<std::vector<fesa::LoadContribution>> ComputeContributions(
const fesa::LoadContext&) const override {
return fesa::Result<std::vector<fesa::LoadContribution>>::Success(
contributions_);
}
private:
std::vector<fesa::LoadContribution> contributions_;
};
} // namespace
// C-LOAD-001
TEST(LoadAssembly, AccumulatesGenericContributionsInSuppliedSourceOrder) {
auto fixture = MakeFixture(1U, {}, {}, {});
const FakeLoad first(
{{0U, 0U, 1.0e16}, {0U, 0U, -1.0e16}, {0U, 0U, 1.0}, {0U, 2U, -4.0}});
const FakeLoad second({{1U, 2U, 1.5}, {1U, 0U, -2.0}});
const fesa::LoadView loads{std::cref(first), std::cref(second)};
const auto result = fesa::LoadAssembler::AssembleFullNodalLoad(
*fixture.model, *fixture.dofs, loads);
ASSERT_TRUE(result.HasValue());
EXPECT_DOUBLE_EQ(result.Value()[0U], -1.0);
EXPECT_DOUBLE_EQ(result.Value()[2U], -2.5);
}
TEST(LoadAssembly, RejectsGenericContributionErrorsBeforeCandidateCommit) {
auto fixture = MakeFixture(1U, {}, {}, {});
const FakeLoad valid({{0U, 1U, 3.0}});
const FakeLoad nonfinite(
{{1U, 2U, std::numeric_limits<double>::quiet_NaN()}});
const FakeLoad out_of_range({{1U, 6U, 4.0}});
const FakeLoad wrong_order({{3U, 2U, 4.0}});
ExpectFailureCode(fesa::LoadAssembler::AssembleFullNodalLoad(
*fixture.model, *fixture.dofs,
{std::cref(valid), std::cref(nonfinite)}),
"nonfinite-load-value");
ExpectFailureCode(fesa::LoadAssembler::AssembleFullNodalLoad(
*fixture.model, *fixture.dofs,
{std::cref(valid), std::cref(out_of_range)}),
"invalid-load-index");
ExpectFailureCode(fesa::LoadAssembler::AssembleFullNodalLoad(
*fixture.model, *fixture.dofs,
{std::cref(valid), std::cref(wrong_order)}),
"invalid-load-order");
const auto repeated = fesa::LoadAssembler::AssembleFullNodalLoad(
*fixture.model, *fixture.dofs, {std::cref(valid)});
ASSERT_TRUE(repeated.HasValue());
EXPECT_DOUBLE_EQ(repeated.Value()[1U], 3.0);
}
TEST(LoadAssembly, AssemblesNodeSetAndSixComponentLoads) {
const std::filesystem::path source{"models/load-assembly.inp"};
auto fixture =