108 lines
4.1 KiB
C++
108 lines
4.1 KiB
C++
#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");
|
|
}
|