fix(equation-and-linear-solve): address review findings

This commit is contained in:
KOKO\Mimi
2026-07-31 16:36:07 +09:00
parent 2dd17be5d0
commit 741fc9eaea
12 changed files with 329 additions and 147 deletions
+59 -27
View File
@@ -4,6 +4,7 @@
#include <array>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <stdexcept>
#include <utility>
#include <vector>
@@ -49,7 +50,7 @@ TEST(EssentialBc, ZeroPrescribedValueDoesNotShiftReducedForce) {
const fesa::DofManager dofs = build_dofs(prescribed);
const fesa::ConstraintResult result =
fesa::eliminate_essential_bcs(hand_system(), dofs, prescribed);
fesa::eliminate_essential_bcs(hand_system(), dofs);
ASSERT_TRUE(result.reduced_system.has_value());
EXPECT_TRUE(result.diagnostics.empty());
@@ -69,7 +70,7 @@ TEST(
const fesa::EquationSystem before = original;
const fesa::ConstraintResult result =
fesa::eliminate_essential_bcs(original, dofs, prescribed);
fesa::eliminate_essential_bcs(original, dofs);
ASSERT_TRUE(result.reduced_system.has_value());
EXPECT_TRUE(result.diagnostics.empty());
@@ -87,12 +88,6 @@ TEST(
EXPECT_EQ(
reduced.force,
(std::vector<double>{5.0, -3.0, 0.0, 0.0, 0.0}));
EXPECT_EQ(
reduced.free_to_full,
(std::vector<std::size_t>{0, 2, 3, 4, 5}));
EXPECT_EQ(
reduced.prescribed_full,
(std::vector<double>{0.0, 2.0, 0.0, 0.0, 0.0, 0.0}));
EXPECT_EQ(original.stiffness.order, before.stiffness.order);
EXPECT_EQ(
@@ -122,7 +117,7 @@ TEST(ConstraintElimination, AcceptsAllDofsConstrained) {
const fesa::DofManager dofs = build_dofs(prescribed);
const fesa::ConstraintResult result =
fesa::eliminate_essential_bcs(hand_system(), dofs, prescribed);
fesa::eliminate_essential_bcs(hand_system(), dofs);
ASSERT_TRUE(result.reduced_system.has_value());
const fesa::ReducedSystem& reduced = *result.reduced_system;
@@ -133,36 +128,51 @@ TEST(ConstraintElimination, AcceptsAllDofsConstrained) {
EXPECT_TRUE(reduced.stiffness.column_indices.empty());
EXPECT_TRUE(reduced.stiffness.values.empty());
EXPECT_TRUE(reduced.force.empty());
EXPECT_TRUE(reduced.free_to_full.empty());
EXPECT_EQ(
reduced.prescribed_full,
(std::vector<double>{1.0, 2.0, 3.0, 4.0, 5.0, 6.0}));
EXPECT_EQ(
dofs.reconstruct_full({}),
reduced.prescribed_full);
(std::vector<double>{1.0, 2.0, 3.0, 4.0, 5.0, 6.0}));
}
TEST(ConstraintElimination, RejectsConflictingPrescribedValues) {
TEST(ConstraintElimination, RejectsNonfiniteSystemData) {
const fesa::DofManager dofs = build_dofs({});
fesa::EquationSystem nonfinite_matrix = hand_system();
nonfinite_matrix.stiffness.values[0] =
std::numeric_limits<double>::quiet_NaN();
fesa::EquationSystem nonfinite_force = hand_system();
nonfinite_force.force[0] =
std::numeric_limits<double>::infinity();
const fesa::ConstraintResult matrix_result =
fesa::eliminate_essential_bcs(nonfinite_matrix, dofs);
const fesa::ConstraintResult force_result =
fesa::eliminate_essential_bcs(nonfinite_force, dofs);
ASSERT_FALSE(matrix_result.diagnostics.empty());
EXPECT_EQ(
matrix_result.diagnostics.front().code,
"equation.invalid_system");
ASSERT_FALSE(force_result.diagnostics.empty());
EXPECT_EQ(
force_result.diagnostics.front().code,
"equation.invalid_system");
}
TEST(ConstraintElimination, RejectsNonfiniteReducedForce) {
const fesa::DofManager dofs = build_dofs({
{fesa::NodeId{0}, 2, 2.0},
});
const std::vector<fesa::PrescribedDof> conflicting{
{fesa::NodeId{0}, 2, 2.0},
{fesa::NodeId{0}, 2, 3.0},
};
fesa::EquationSystem overflowing = hand_system();
overflowing.stiffness.values[1] =
std::numeric_limits<double>::max();
const fesa::ConstraintResult result =
fesa::eliminate_essential_bcs(
hand_system(), dofs, conflicting);
fesa::eliminate_essential_bcs(overflowing, dofs);
EXPECT_FALSE(result.reduced_system.has_value());
ASSERT_FALSE(result.diagnostics.empty());
EXPECT_NE(
std::ranges::find(
result.diagnostics,
"equation.conflicting_prescribed_dof",
&fesa::Diagnostic::code),
result.diagnostics.end());
EXPECT_EQ(
result.diagnostics.front().code,
"equation.nonfinite_result");
}
TEST(Reaction, UsesOriginalFullEquilibriumEquation) {
@@ -175,4 +185,26 @@ TEST(Reaction, UsesOriginalFullEquilibriumEquation) {
(std::vector<double>{5.0, 17.0, 20.0, 0.0, 0.0, 0.0}));
}
TEST(Reaction, RejectsNonfiniteFullDisplacement) {
std::vector<double> displacement(6, 0.0);
displacement[0] = std::numeric_limits<double>::quiet_NaN();
EXPECT_THROW(
static_cast<void>(
fesa::recover_reaction(hand_system(), displacement)),
std::invalid_argument);
}
TEST(Reaction, RejectsNonfiniteRecoveredValue) {
fesa::EquationSystem overflowing = hand_system();
overflowing.stiffness.values[0] =
std::numeric_limits<double>::max();
EXPECT_THROW(
static_cast<void>(fesa::recover_reaction(
overflowing,
std::vector<double>{2.0, 0.0, 0.0, 0.0, 0.0, 0.0})),
std::invalid_argument);
}
} // namespace