feat(cpp-object-oriented-modular-refactoring): step 13 - element-definition-domain

This commit is contained in:
KOKO\Mimi
2026-08-16 09:10:38 +09:00
parent cf6fc6e1d9
commit 19ba02a6a4
26 changed files with 740 additions and 242 deletions
+105 -19
View File
@@ -8,6 +8,8 @@
#include <utility>
#include <vector>
#include "fesa/elements/element_definition.h"
namespace {
fesa::ModelDefinition MakeOwnedDefinition() {
@@ -63,6 +65,90 @@ fesa::ModelDefinition MakeOwnedDefinition() {
} // namespace
// C-MODEL-002
TEST(ElementDefinition, DomainOwnsMixedDefinitionsInStableBaseOrder) {
static_assert(std::has_virtual_destructor_v<fesa::ElementDefinition>);
static_assert(!std::is_copy_constructible_v<fesa::Domain>);
static_assert(!std::is_copy_assignable_v<fesa::Domain>);
static_assert(std::is_move_constructible_v<fesa::Domain>);
static_assert(std::is_move_assignable_v<fesa::Domain>);
fesa::ModelDefinition definition{};
definition.source_path = "models/mixed-owned.inp";
definition.source_content_identity = "fnv1a64:mixed";
definition.materials = {
{"Steel", 210.0e9, 0.3, {definition.source_path, 30U}}};
definition.sections = {{"BeamSection",
0.02,
1.0e-5,
0.0,
2.0e-5,
5.0e-6,
{0.0, 1.0, 0.0},
{},
{definition.source_path, 40U}}};
definition.shell_sections = {
{"ShellSection", 0.01, 0U, {definition.source_path, 41U}}};
definition.elements = {
{{"Beam-1", 7, "0007"}, {0U, 1U}, 0U, 0U, {definition.source_path, 20U}}};
definition.shell_elements = {{{"Shell-1", 9, "0009"},
fesa::ShellSourceElementType::kS4r,
{2U, 3U, 4U, 5U},
0U,
0U,
{definition.source_path, 21U}}};
auto result = fesa::Domain::Create(definition);
ASSERT_TRUE(result.HasValue());
fesa::Domain domain = std::move(result.Value());
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().Elements()[0U]),
const fesa::ElementDefinition&>);
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().Materials()[0U]),
const fesa::Material&>);
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().Properties()[0U]),
const fesa::ElementProperty&>);
ASSERT_EQ(domain.Elements().Size(), 2U);
const fesa::ElementDefinition& beam = domain.Elements()[0U];
EXPECT_EQ(beam.Kind(), fesa::ElementDefinitionKind::kEulerBeam3D);
EXPECT_EQ(beam.SourceId().source_label_text, "0007");
EXPECT_EQ(beam.SourceElementType(), "B33");
EXPECT_EQ(beam.NodeIndices(), (std::vector<fesa::EntityIndex>{0U, 1U}));
EXPECT_EQ(beam.MaterialIndex(), fesa::EntityIndex{0U});
EXPECT_EQ(beam.PropertyIndex(), fesa::EntityIndex{0U});
const fesa::ElementDefinition& shell = domain.Elements()[1U];
EXPECT_EQ(shell.Kind(), fesa::ElementDefinitionKind::kMitc4Shell);
EXPECT_EQ(shell.SourceId().source_label_text, "0009");
EXPECT_EQ(shell.SourceElementType(), "S4R");
EXPECT_EQ(shell.NodeIndices(),
(std::vector<fesa::EntityIndex>{2U, 3U, 4U, 5U}));
EXPECT_EQ(shell.MaterialIndex(), fesa::EntityIndex{0U});
EXPECT_EQ(shell.PropertyIndex(), fesa::EntityIndex{1U});
ASSERT_EQ(domain.BeamElements().Size(), 1U);
ASSERT_EQ(domain.ShellElements().Size(), 1U);
EXPECT_EQ(&domain.BeamElements()[0U], &beam);
EXPECT_EQ(&domain.ShellElements()[0U], &shell);
ASSERT_EQ(domain.Materials().Size(), 1U);
EXPECT_EQ(domain.Materials()[0U].Kind(),
fesa::MaterialKind::kIsotropicLinearElastic);
EXPECT_EQ(&domain.LinearElasticMaterials()[0U], &domain.Materials()[0U]);
ASSERT_EQ(domain.Properties().Size(), 2U);
EXPECT_EQ(domain.Properties()[0U].Kind(),
fesa::ElementPropertyKind::kGeneralBeamSection);
EXPECT_EQ(domain.Properties()[1U].Kind(),
fesa::ElementPropertyKind::kShellSection);
EXPECT_EQ(&domain.Sections()[0U], &domain.Properties()[0U]);
EXPECT_EQ(&domain.ShellSections()[0U], &domain.Properties()[1U]);
}
TEST(DomainModel, ImmutableOwnershipPreservesStableOrder) {
auto definition = MakeOwnedDefinition();
auto result = fesa::Domain::Create(definition);
@@ -81,9 +167,9 @@ TEST(DomainModel, ImmutableOwnershipPreservesStableOrder) {
static_assert(
std::is_same_v<decltype(std::declval<const fesa::Domain&>().Nodes()),
const std::vector<fesa::Node>&>);
static_assert(
std::is_same_v<decltype(std::declval<const fesa::Domain&>().Elements()),
const std::vector<fesa::EulerBeam3DDefinition>&>);
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().Elements()),
const fesa::DomainCollectionView<fesa::ElementDefinition>&>);
EXPECT_EQ(domain.SourcePath(), std::filesystem::path{"models/owned.inp"});
EXPECT_EQ(domain.SourceContentIdentity(), "fnv1a64:fedcba9876543210");
@@ -94,11 +180,11 @@ TEST(DomainModel, ImmutableOwnershipPreservesStableOrder) {
EXPECT_EQ(domain.Nodes()[1].source_id.source_label, 10);
EXPECT_EQ(domain.Nodes().data(), first_node_address);
ASSERT_EQ(domain.Elements().size(), 1U);
EXPECT_EQ(domain.Elements()[0].node_indices[0], 1U);
EXPECT_EQ(domain.Elements()[0].node_indices[1], 0U);
ASSERT_EQ(domain.Materials().size(), 1U);
ASSERT_EQ(domain.Sections().size(), 1U);
ASSERT_EQ(domain.BeamElements().Size(), 1U);
EXPECT_EQ(domain.BeamElements()[0].node_indices[0], 1U);
EXPECT_EQ(domain.BeamElements()[0].node_indices[1], 0U);
ASSERT_EQ(domain.Materials().Size(), 1U);
ASSERT_EQ(domain.Sections().Size(), 1U);
EXPECT_DOUBLE_EQ(domain.Sections()[0].section_points[0][0], -0.1);
ASSERT_EQ(domain.NodeSets().size(), 1U);
EXPECT_EQ(domain.NodeSets()[0].node_indices[0], 0U);
@@ -189,13 +275,13 @@ TEST(DomainModel, MultipleIdentityInstancesDoNotMerge) {
EXPECT_NE(domain.Nodes()[0].source_id.instance_name,
domain.Nodes()[2].source_id.instance_name);
ASSERT_EQ(domain.Elements().size(), 2U);
EXPECT_EQ(domain.Elements()[0].source_id.source_label, 1);
EXPECT_EQ(domain.Elements()[1].source_id.source_label, 1);
EXPECT_EQ(domain.Elements()[0].source_id.instance_name, "Instance-A");
EXPECT_EQ(domain.Elements()[1].source_id.instance_name, "Instance-B");
EXPECT_EQ(domain.Elements()[0].node_indices[0], 0U);
EXPECT_EQ(domain.Elements()[1].node_indices[0], 2U);
ASSERT_EQ(domain.BeamElements().Size(), 2U);
EXPECT_EQ(domain.BeamElements()[0].source_id.source_label, 1);
EXPECT_EQ(domain.BeamElements()[1].source_id.source_label, 1);
EXPECT_EQ(domain.BeamElements()[0].source_id.instance_name, "Instance-A");
EXPECT_EQ(domain.BeamElements()[1].source_id.instance_name, "Instance-B");
EXPECT_EQ(domain.BeamElements()[0].node_indices[0], 0U);
EXPECT_EQ(domain.BeamElements()[1].node_indices[0], 2U);
}
// MITC4-MODEL-002
@@ -235,16 +321,16 @@ TEST(DomainModel, ShellOwnershipPreservesResolvedAssignmentsAndOptionalFrames) {
const fesa::Domain& domain = result.Value();
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().ShellElements()),
const std::vector<fesa::Mitc4ShellDefinition>&>);
const fesa::DomainCollectionView<fesa::Mitc4ShellDefinition>&>);
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().ShellSections()),
const std::vector<fesa::ShellSection>&>);
const fesa::DomainCollectionView<fesa::ShellSection>&>);
static_assert(
std::is_same_v<decltype(std::declval<const fesa::Domain&>()
.ShellNodeInitialFrames()),
const std::vector<fesa::ShellNodeInitialFrame>&>);
ASSERT_EQ(domain.ShellElements().size(), 2U);
ASSERT_EQ(domain.ShellElements().Size(), 2U);
EXPECT_EQ(domain.ShellElements()[0].source_id.source_label, 20);
EXPECT_EQ(domain.ShellElements()[0].source_id.source_label_text, "0020");
EXPECT_EQ(domain.ShellElements()[1].source_id.source_label, 10);
@@ -256,7 +342,7 @@ TEST(DomainModel, ShellOwnershipPreservesResolvedAssignmentsAndOptionalFrames) {
EXPECT_EQ(domain.ShellElements()[0].material_index, 0U);
EXPECT_EQ(domain.ShellElements()[0].section_index, 0U);
ASSERT_EQ(domain.ShellSections().size(), 2U);
ASSERT_EQ(domain.ShellSections().Size(), 2U);
EXPECT_EQ(domain.ShellSections()[0].name, "Section-B");
EXPECT_DOUBLE_EQ(domain.ShellSections()[0].thickness, 0.02);
EXPECT_EQ(domain.ShellSections()[0].material_index, 0U);