feat(cpp-object-oriented-modular-refactoring): step 18 - load-hierarchy
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <filesystem>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "fesa/analysis/analysis_model.h"
|
||||
#include "fesa/fem/dof_manager.h"
|
||||
#include "fesa/loads/concentrated_nodal_load.h"
|
||||
#include "fesa/model/domain.h"
|
||||
#include "fesa/model/source_target_resolver.h"
|
||||
|
||||
namespace {
|
||||
|
||||
fesa::Domain MakeDomain() {
|
||||
const std::filesystem::path source{"models/load-hierarchy.inp"};
|
||||
fesa::ModelDefinition definition{};
|
||||
definition.source_path = source;
|
||||
definition.source_content_identity = "fnv1a64:loadhierarchy";
|
||||
definition.nodes = {{{"Part-1-1", 10, "10"}, {0.0, 0.0, 0.0}, {source, 2U}},
|
||||
{{"Part-1-1", 20, "20"}, {1.0, 0.0, 0.0}, {source, 3U}}};
|
||||
definition.node_sets = {
|
||||
{"Pair", std::string{"Part-1-1"}, {0U, 1U}, {source, 4U}}};
|
||||
definition.steps = {{"Step-1", {}, {}, 0.1, 1.0, 0.01, 1.0, {source, 5U}}};
|
||||
auto domain = fesa::Domain::Create(std::move(definition));
|
||||
if (!domain.HasValue()) {
|
||||
throw std::runtime_error{"Load hierarchy Domain construction failed."};
|
||||
}
|
||||
return std::move(domain.Value());
|
||||
}
|
||||
|
||||
void ExpectFailureCode(
|
||||
const fesa::Result<std::vector<fesa::LoadContribution>>& result,
|
||||
const std::string& code) {
|
||||
ASSERT_FALSE(result.HasValue());
|
||||
EXPECT_EQ(result.GetStatus().Category(), fesa::FailureCategory::kModel);
|
||||
ASSERT_EQ(result.GetStatus().Diagnostics().size(), 1U);
|
||||
EXPECT_EQ(result.GetStatus().Diagnostics()[0U].code, code);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// C-LOAD-001
|
||||
TEST(Load, ConcentratedNodalLoadEmitsStableFullDofContributions) {
|
||||
static_assert(std::has_virtual_destructor_v<fesa::Load>);
|
||||
static_assert(!std::is_copy_constructible_v<fesa::StepDefinition>);
|
||||
static_assert(std::is_move_constructible_v<fesa::StepDefinition>);
|
||||
|
||||
fesa::Domain domain = MakeDomain();
|
||||
auto model = fesa::AnalysisModel::Create(domain);
|
||||
ASSERT_TRUE(model.HasValue());
|
||||
auto dofs = fesa::DofManager::Create(model.Value());
|
||||
ASSERT_TRUE(dofs.HasValue());
|
||||
const fesa::SourceTargetIndex target_index =
|
||||
fesa::SourceTargetIndex::FromDomain(domain);
|
||||
const fesa::SourceTargetResolver resolver{target_index};
|
||||
const fesa::LoadContext context{domain, dofs.Value(), resolver};
|
||||
const std::array<double, 6> components{1.0, -2.0, 0.0, 4.0, 0.0, -6.0};
|
||||
const fesa::ConcentratedNodalLoad load(
|
||||
{fesa::SourceEntityKind::kNode, "Part-1-1", "pair"}, components, 7U);
|
||||
|
||||
const auto result = load.ComputeContributions(context);
|
||||
|
||||
ASSERT_TRUE(result.HasValue());
|
||||
ASSERT_EQ(result.Value().size(), 12U);
|
||||
for (std::size_t node = 0U; node < 2U; ++node) {
|
||||
for (std::size_t component = 0U; component < components.size();
|
||||
++component) {
|
||||
const auto& contribution =
|
||||
result.Value()[node * components.size() + component];
|
||||
EXPECT_EQ(contribution.source_order, 7U);
|
||||
EXPECT_EQ(contribution.full_dof_index,
|
||||
node * components.size() + component);
|
||||
EXPECT_DOUBLE_EQ(contribution.value, components[component]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Load, ConcentratedNodalLoadRejectsInvalidInputWithoutContributions) {
|
||||
fesa::Domain domain = MakeDomain();
|
||||
auto model = fesa::AnalysisModel::Create(domain);
|
||||
ASSERT_TRUE(model.HasValue());
|
||||
auto dofs = fesa::DofManager::Create(model.Value());
|
||||
ASSERT_TRUE(dofs.HasValue());
|
||||
const fesa::SourceTargetIndex target_index =
|
||||
fesa::SourceTargetIndex::FromDomain(domain);
|
||||
const fesa::SourceTargetResolver resolver{target_index};
|
||||
const fesa::LoadContext context{domain, dofs.Value(), resolver};
|
||||
|
||||
std::array<double, 6> nonfinite{};
|
||||
nonfinite[2U] = std::numeric_limits<double>::infinity();
|
||||
const fesa::ConcentratedNodalLoad invalid_value(
|
||||
{fesa::SourceEntityKind::kNode, "Part-1-1", "10"}, nonfinite, 0U);
|
||||
ExpectFailureCode(invalid_value.ComputeContributions(context),
|
||||
"nonfinite-load-value");
|
||||
|
||||
const fesa::ConcentratedNodalLoad invalid_target(
|
||||
{fesa::SourceEntityKind::kNode, "Part-1-1", "Missing"}, {}, 0U);
|
||||
ExpectFailureCode(invalid_target.ComputeContributions(context),
|
||||
"invalid-load-target");
|
||||
}
|
||||
Reference in New Issue
Block a user