feat(result-contract-completion): step 0 — beam-element-end-recovery
This commit is contained in:
@@ -22,6 +22,7 @@ constexpr double kShearAreaZ = 0.2;
|
||||
fesa::Beam3D2Input make_x_axis_input(const double length) {
|
||||
return {
|
||||
{{{0.0, 0.0, 0.0}, {length, 0.0, 0.0}}},
|
||||
{fesa::NodeId{1}, fesa::NodeId{2}},
|
||||
{fesa::MaterialId{1}, "elastic", kYoung, kPoisson},
|
||||
{
|
||||
fesa::SectionId{1},
|
||||
@@ -369,4 +370,191 @@ TEST(Beam3D2, PreservesGlobalEnergyUnderRigidCoordinateRotation) {
|
||||
4096.0 * std::numeric_limits<double>::epsilon());
|
||||
}
|
||||
|
||||
TEST(BeamRecovery, RecoversPureAxialStrainAndForceAtBothEnds) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[6] = 0.4;
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
EXPECT_DOUBLE_EQ(results[0].xi, -1.0);
|
||||
EXPECT_EQ(results[0].end_node, fesa::NodeId{101});
|
||||
EXPECT_DOUBLE_EQ(results[1].xi, 1.0);
|
||||
EXPECT_EQ(results[1].end_node, fesa::NodeId{202});
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_strain[0], 0.2);
|
||||
expect_relative_near(result.section_force[0], 16.8);
|
||||
expect_relative_near(result.centroid_sigma_xx, 42.0);
|
||||
for (std::size_t component = 1; component < 6; ++component) {
|
||||
expect_relative_near(result.section_strain[component], 0.0);
|
||||
expect_relative_near(result.section_force[component], 0.0);
|
||||
}
|
||||
EXPECT_TRUE(result.sigma_xx.empty());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BeamRecovery, RecoversPureTorsionAtBothEnds) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[9] = 0.6;
|
||||
const double shear_modulus = kYoung / (2.0 * (1.0 + kPoisson));
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_strain[3], 0.3);
|
||||
expect_relative_near(
|
||||
result.section_force[3],
|
||||
shear_modulus * kTorsionJ * 0.3);
|
||||
for (const std::size_t component :
|
||||
std::array<std::size_t, 5>{0, 1, 2, 4, 5}) {
|
||||
expect_relative_near(result.section_strain[component], 0.0);
|
||||
expect_relative_near(result.section_force[component], 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BeamRecovery, UsesReducedIntegrationPointForShearAtBothEnds) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[7] = 1.2;
|
||||
displacement[5] = 0.2;
|
||||
displacement[11] = 0.6;
|
||||
displacement[8] = -0.4;
|
||||
displacement[4] = 0.1;
|
||||
displacement[10] = 0.5;
|
||||
const double shear_modulus = kYoung / (2.0 * (1.0 + kPoisson));
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_strain[1], 0.2);
|
||||
expect_relative_near(result.section_strain[2], 0.1);
|
||||
expect_relative_near(
|
||||
result.section_force[1],
|
||||
shear_modulus * kShearAreaY * 0.2);
|
||||
expect_relative_near(
|
||||
result.section_force[2],
|
||||
shear_modulus * kShearAreaZ * 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(BeamRecovery, UsesBeamFrameForGlobalDisplacements) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.coordinates = {{{0.0, 0.0, 0.0}, {0.0, 2.0, 0.0}}};
|
||||
input.section.orientation = {0.0, 0.0, 1.0};
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[7] = 0.4;
|
||||
displacement[10] = 0.6;
|
||||
const double shear_modulus = kYoung / (2.0 * (1.0 + kPoisson));
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_strain[0], 0.2);
|
||||
expect_relative_near(result.section_force[0], 16.8);
|
||||
expect_relative_near(result.section_strain[3], 0.3);
|
||||
expect_relative_near(
|
||||
result.section_force[3],
|
||||
shear_modulus * kTorsionJ * 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SectionForce, RecoversPureBendingAboutLocalYAtBothEnds) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[4] = -0.4;
|
||||
displacement[10] = 0.4;
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_strain[4], 0.4);
|
||||
expect_relative_near(result.section_force[4], 2.52);
|
||||
for (const std::size_t component :
|
||||
std::array<std::size_t, 5>{0, 1, 2, 3, 5}) {
|
||||
expect_relative_near(result.section_strain[component], 0.0);
|
||||
expect_relative_near(result.section_force[component], 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SectionForce, RecoversPureBendingAboutLocalZAtBothEnds) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[5] = 0.25;
|
||||
displacement[11] = -0.25;
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_strain[5], -0.25);
|
||||
expect_relative_near(result.section_force[5], -2.625);
|
||||
for (const std::size_t component :
|
||||
std::array<std::size_t, 5>{0, 1, 2, 3, 4}) {
|
||||
expect_relative_near(result.section_strain[component], 0.0);
|
||||
expect_relative_near(result.section_force[component], 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SectionForce, PreservesBiaxialBendingSignsAtBothEnds) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[4] = -0.4;
|
||||
displacement[10] = 0.4;
|
||||
displacement[5] = 0.25;
|
||||
displacement[11] = -0.25;
|
||||
|
||||
const auto results = fesa::recover_beam3d2(input, displacement, {});
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.section_force[4], 2.52);
|
||||
expect_relative_near(result.section_force[5], -2.625);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CentroidStress, UsesAxialStressAndPreservesRecoveryPointOrder) {
|
||||
fesa::Beam3D2Input input = make_x_axis_input(2.0);
|
||||
input.node_ids = {fesa::NodeId{101}, fesa::NodeId{202}};
|
||||
std::array<double, 12> displacement{};
|
||||
displacement[6] = 0.2;
|
||||
displacement[4] = -0.2;
|
||||
displacement[10] = 0.2;
|
||||
displacement[5] = 0.3;
|
||||
displacement[11] = -0.3;
|
||||
const std::array<std::array<double, 2>, 3> recovery_points{{
|
||||
{2.0, 3.0},
|
||||
{-1.0, 4.0},
|
||||
{5.0, -2.0},
|
||||
}};
|
||||
|
||||
const auto results = fesa::recover_beam3d2(
|
||||
input,
|
||||
displacement,
|
||||
recovery_points);
|
||||
|
||||
ASSERT_EQ(results.size(), 2U);
|
||||
for (const auto& result : results) {
|
||||
expect_relative_near(result.centroid_sigma_xx, 21.0);
|
||||
ASSERT_EQ(result.sigma_xx.size(), recovery_points.size());
|
||||
expect_relative_near(result.sigma_xx[0], 273.0);
|
||||
expect_relative_near(result.sigma_xx[1], 126.0);
|
||||
expect_relative_near(result.sigma_xx[2], 252.0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user