feat(cpp-object-oriented-modular-refactoring): step 8 - element-geometry-vector3

This commit is contained in:
KOKO\Mimi
2026-08-16 07:27:51 +09:00
parent cbad5c3592
commit a9ff75b3fa
9 changed files with 320 additions and 233 deletions
+60
View File
@@ -12,6 +12,8 @@
#include <string>
#include <vector>
#include "fesa/math/vector3.h"
namespace {
using Vector3 = std::array<double, 3>;
@@ -588,6 +590,64 @@ TEST(Mitc4ShellKernel,
EXPECT_DOUBLE_EQ(repeated.drilling_stiffness, stiffness.drilling_stiffness);
}
TEST(Mitc4ShellKernel,
PreservesExactStiffnessRecoveryAndPatchAcrossVector3Migration) {
const auto nodes = PlanarNodes();
const auto shell_candidate = fesa::Mitc4Shell::Create(
NodePointers(nodes), Directors(), Section(), Material());
ASSERT_TRUE(shell_candidate.HasValue());
const auto& shell = shell_candidate.Value();
const auto stiffness_candidate = shell.Stiffness();
ASSERT_TRUE(stiffness_candidate.HasValue());
const auto& stiffness = stiffness_candidate.Value();
const fesa::Vector3 frame_e3{shell.LocalFrame(0.0, 0.0).e3};
EXPECT_DOUBLE_EQ(frame_e3.X(), 0.0);
EXPECT_DOUBLE_EQ(frame_e3.Y(), 0.0);
EXPECT_DOUBLE_EQ(frame_e3.Z(), 1.0);
constexpr std::array<double, 8> kGeneralized{0.1, -0.05, 0.2, 0.3,
-0.15, 0.25, 0.4, -0.3};
fesa::Vector global_field{24U};
for (std::size_t node_index = 0U; node_index < nodes.size(); ++node_index) {
const double x = nodes[node_index].coordinates[0];
const double y = nodes[node_index].coordinates[1];
const std::size_t offset = 6U * node_index;
global_field[offset] = kGeneralized[0] * x + 0.5 * kGeneralized[2] * y;
global_field[offset + 1U] = kGeneralized[1] * y + 0.5 * kGeneralized[2] * x;
global_field[offset + 2U] = kGeneralized[6] * x + kGeneralized[7] * y -
0.5 * kGeneralized[5] * x * y;
global_field[offset + 3U] =
-kGeneralized[4] * y - 0.5 * kGeneralized[5] * x;
global_field[offset + 4U] = kGeneralized[3] * x + 0.5 * kGeneralized[5] * y;
}
const auto recovery_candidate = shell.RecoverPhysical(global_field);
ASSERT_TRUE(recovery_candidate.HasValue());
const auto& recovery = recovery_candidate.Value();
std::array<std::array<double, 5>, 4> e11_values{};
for (std::size_t node_index = 0U; node_index < nodes.size(); ++node_index) {
e11_values[node_index][0U] = 0.2 * nodes[node_index].coordinates[0U];
}
const double gauss = 1.0 / std::sqrt(3.0);
const fesa::Vector patch = shell.StrainDisplacement20(gauss, -gauss, gauss)
.Multiply(PhysicalField(e11_values));
EXPECT_DOUBLE_EQ(stiffness.physical_local20(0U, 0U), 0x1.d555555555554p+6);
EXPECT_DOUBLE_EQ(stiffness.physical_local20(0U, 4U), 0.0);
EXPECT_DOUBLE_EQ(stiffness.physical_global24(2U, 2U), 0x1.aaaaaaaaaaaadp+5);
EXPECT_DOUBLE_EQ(stiffness.drilling_stiffness, 0x1.0d6cffc5beeb5p-4);
EXPECT_DOUBLE_EQ(recovery.strain_energy, 0x1.20a3d70a3d70bp+6);
constexpr std::array<double, 8> kExpectedStrain{
0x1.999999999999ap-4, -0x1.999999999999bp-5, 0x1.9999999999998p-3,
0x1.3333333333335p-2, -0x1.3333333333335p-3, 0x1.0000000000000p-2,
0x1.999999999999cp-2, -0x1.3333333333334p-2};
EXPECT_EQ(recovery.points[0U].generalized_strain, kExpectedStrain);
EXPECT_DOUBLE_EQ(patch[0U], 0x1.9999999999999p-3);
for (std::size_t component = 1U; component < patch.Size(); ++component) {
EXPECT_DOUBLE_EQ(patch[component], 0.0);
}
}
// MITC4-KERNEL-002
TEST(Mitc4ShellKernel,
PreservesPhysicalEnergyUnderTwentyToTwentyFourCongruence) {