feat(domain-and-input-skeleton): step 0 — semantic-domain-and-origin-types

This commit is contained in:
KOKO\Mimi
2026-07-30 16:38:05 +09:00
parent b851575554
commit c7e64eb841
12 changed files with 455 additions and 0 deletions
+24
View File
@@ -75,3 +75,27 @@ add_test(
NAME CoreValueTypes
COMMAND "$<TARGET_FILE:fesa_core_value_tests>"
)
add_executable(fesa_model_value_tests
unit/model/entity_origin_test.cpp
unit/model/model_types_test.cpp
)
target_compile_features(fesa_model_value_tests PRIVATE cxx_std_20)
target_compile_options(fesa_model_value_tests PRIVATE /W4 /permissive- /EHsc)
target_link_libraries(fesa_model_value_tests
PRIVATE
fesa_core
GTest::gtest_main
)
add_test(
NAME ModelTypes
COMMAND "$<TARGET_FILE:fesa_model_value_tests>" --gtest_filter=ModelTypes.*
)
add_test(
NAME EntityOrigin
COMMAND "$<TARGET_FILE:fesa_model_value_tests>" --gtest_filter=EntityOrigin.*
)
+55
View File
@@ -0,0 +1,55 @@
#include <fesa/model/domain.hpp>
#include <span>
#include <type_traits>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
namespace {
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().nodes()),
std::span<const fesa::Node>>);
static_assert(std::is_same_v<
decltype(std::declval<const fesa::Domain&>().node(
std::declval<fesa::NodeId>())),
const fesa::Node&>);
TEST(EntityOrigin, UsesEmptyScopeNamesForFlatMeshEntities) {
const fesa::EntityOrigin origin{"", "", 17};
EXPECT_TRUE(origin.part_name.empty());
EXPECT_TRUE(origin.instance_name.empty());
EXPECT_EQ(origin.local_label, 17);
}
TEST(EntityOrigin, FindsHierarchicalNodeByCompositeOrigin) {
const fesa::Node node{
fesa::NodeId{0},
fesa::EntityOrigin{"BeamPart", "Beam-1", 101},
fesa::Vec3{1.0, 2.0, 3.0},
};
const fesa::Domain domain{
std::vector<fesa::Node>{node},
{},
{},
{},
{},
{},
fesa::StepDefinition{"Load", {}, {}},
};
const fesa::EntityOrigin lookup{"BeamPart", "Beam-1", 101};
const fesa::Node& found_by_origin = domain.node(lookup);
const fesa::Node& found_by_id = domain.node(fesa::NodeId{0});
EXPECT_EQ(&found_by_origin, &domain.nodes().front());
EXPECT_EQ(&found_by_id, &domain.nodes().front());
EXPECT_EQ(found_by_origin.origin.part_name, "BeamPart");
EXPECT_EQ(found_by_origin.origin.instance_name, "Beam-1");
EXPECT_EQ(found_by_origin.origin.local_label, 101);
}
} // namespace
+121
View File
@@ -0,0 +1,121 @@
#include <fesa/model/beam_element.hpp>
#include <fesa/model/beam_section.hpp>
#include <fesa/model/entity_set.hpp>
#include <fesa/model/material.hpp>
#include <fesa/model/node.hpp>
#include <fesa/model/step_definition.hpp>
#include <array>
#include <vector>
#include <gtest/gtest.h>
namespace {
TEST(ModelTypes, PreservesNodeAndBeamElementValues) {
const fesa::Node first_node{
fesa::NodeId{0},
fesa::EntityOrigin{"BeamPart", "Beam-1", 101},
fesa::Vec3{1.0, 2.0, 3.0},
};
const fesa::BeamElement element{
fesa::ElementId{4},
fesa::EntityOrigin{"BeamPart", "Beam-1", 201},
{fesa::NodeId{0}, fesa::NodeId{1}},
fesa::MaterialId{2},
fesa::SectionId{3},
};
EXPECT_EQ(first_node.id.value(), 0);
EXPECT_EQ(first_node.origin.part_name, "BeamPart");
EXPECT_EQ(first_node.origin.instance_name, "Beam-1");
EXPECT_EQ(first_node.origin.local_label, 101);
EXPECT_DOUBLE_EQ(first_node.position.x, 1.0);
EXPECT_DOUBLE_EQ(first_node.position.y, 2.0);
EXPECT_DOUBLE_EQ(first_node.position.z, 3.0);
EXPECT_EQ(element.id.value(), 4);
EXPECT_EQ(element.origin.local_label, 201);
EXPECT_EQ(element.nodes[0].value(), 0);
EXPECT_EQ(element.nodes[1].value(), 1);
EXPECT_EQ(element.material.value(), 2);
EXPECT_EQ(element.section.value(), 3);
}
TEST(ModelTypes, PreservesMaterialAndBeamSectionValues) {
const fesa::IsotropicElastic material{
fesa::MaterialId{2},
"Steel",
210.0e9,
0.3,
};
const fesa::BeamSection section{
fesa::SectionId{3},
"General",
0.04,
1.2e-4,
1.4e-4,
2.0e-4,
0.03,
0.031,
fesa::ShearPropertySource::input,
fesa::Vec3{0.0, 1.0, 0.0},
{{-0.1, 0.0}, {0.1, 0.0}},
};
EXPECT_EQ(material.id.value(), 2);
EXPECT_EQ(material.name, "Steel");
EXPECT_DOUBLE_EQ(material.young, 210.0e9);
EXPECT_DOUBLE_EQ(material.poisson, 0.3);
EXPECT_EQ(section.id.value(), 3);
EXPECT_EQ(section.name, "General");
EXPECT_DOUBLE_EQ(section.area, 0.04);
EXPECT_DOUBLE_EQ(section.iy, 1.2e-4);
EXPECT_DOUBLE_EQ(section.iz, 1.4e-4);
EXPECT_DOUBLE_EQ(section.torsion_j, 2.0e-4);
EXPECT_DOUBLE_EQ(section.shear_area_y, 0.03);
EXPECT_DOUBLE_EQ(section.shear_area_z, 0.031);
EXPECT_EQ(section.shear_source, fesa::ShearPropertySource::input);
EXPECT_DOUBLE_EQ(section.orientation.y, 1.0);
ASSERT_EQ(section.recovery_points.size(), 2);
EXPECT_DOUBLE_EQ(section.recovery_points[0][0], -0.1);
EXPECT_DOUBLE_EQ(section.recovery_points[1][0], 0.1);
}
TEST(ModelTypes, PreservesSetsAndLinearStaticStepValues) {
const fesa::NodeSet node_set{
"Fixed",
{fesa::NodeId{0}, fesa::NodeId{1}},
};
const fesa::ElementSet element_set{
"Beam",
{fesa::ElementId{4}},
};
const fesa::StepDefinition step{
"Load",
{{fesa::NodeId{0}, 6, 0.25}},
{{
fesa::NodeId{1},
{10.0, 20.0, 30.0, 40.0, 50.0, 60.0},
}},
};
EXPECT_EQ(node_set.name, "Fixed");
ASSERT_EQ(node_set.members.size(), 2);
EXPECT_EQ(node_set.members[1].value(), 1);
EXPECT_EQ(element_set.name, "Beam");
ASSERT_EQ(element_set.members.size(), 1);
EXPECT_EQ(element_set.members[0].value(), 4);
EXPECT_EQ(step.name, "Load");
ASSERT_EQ(step.prescribed_dofs.size(), 1);
EXPECT_EQ(step.prescribed_dofs[0].node.value(), 0);
EXPECT_EQ(step.prescribed_dofs[0].dof, 6);
EXPECT_DOUBLE_EQ(step.prescribed_dofs[0].value, 0.25);
ASSERT_EQ(step.nodal_loads.size(), 1);
EXPECT_EQ(step.nodal_loads[0].node.value(), 1);
EXPECT_DOUBLE_EQ(step.nodal_loads[0].values[5], 60.0);
}
} // namespace