feat(linear-static-3d-euler-beam): step 20 - mkl-pardiso-solver-review-fix
This commit is contained in:
@@ -55,14 +55,45 @@ TEST(MklPardisoSolver, RejectsInvalidCsrStateAndDimensions) {
|
||||
static_assert(std::has_virtual_destructor_v<fesa::LinearSolver>);
|
||||
|
||||
fesa::MklPardisoSolver solver;
|
||||
fesa::Vector solution{2U};
|
||||
expectSolverFailure(solver.solve(fesa::Vector{2U, 1.0}, solution));
|
||||
fesa::Vector untouched{2U};
|
||||
untouched[0U] = 17.0;
|
||||
untouched[1U] = -4.0;
|
||||
const auto beforeFactorize =
|
||||
solver.solve(fesa::Vector{2U, 1.0}, untouched);
|
||||
expectSolverFailure(beforeFactorize);
|
||||
EXPECT_EQ(
|
||||
solver.solve(fesa::Vector{2U, 1.0}, solution)
|
||||
.diagnostics()
|
||||
.front()
|
||||
.code,
|
||||
beforeFactorize.diagnostics().front().code,
|
||||
"solver-not-factorized");
|
||||
EXPECT_DOUBLE_EQ(untouched[0U], 17.0);
|
||||
EXPECT_DOUBLE_EQ(untouched[1U], -4.0);
|
||||
|
||||
// A fully constrained model has a valid 0x0 Kff. It still observes the
|
||||
// factorize-then-solve lifecycle without invoking a numerical backend.
|
||||
const auto empty = makeDenseCsr(0U, 0U, {});
|
||||
ASSERT_TRUE(solver.factorize(empty).isOk());
|
||||
fesa::Vector emptySolution{0U};
|
||||
EXPECT_TRUE(solver.solve(fesa::Vector{0U}, emptySolution).isOk());
|
||||
EXPECT_EQ(emptySolution.size(), 0U);
|
||||
|
||||
// Refactorization from the trivial state must establish ordinary PARDISO
|
||||
// state rather than retaining a zero-equation shortcut.
|
||||
const auto spd = makeDenseCsr(2U, 2U, {4.0, 1.0, 1.0, 3.0});
|
||||
ASSERT_TRUE(solver.factorize(spd).isOk());
|
||||
fesa::Vector solution{2U};
|
||||
ASSERT_TRUE(solver.solve(fesa::Vector{2U, 1.0}, solution).isOk());
|
||||
EXPECT_NEAR(solution[0U], 2.0 / 11.0, 1.0e-14);
|
||||
EXPECT_NEAR(solution[1U], 3.0 / 11.0, 1.0e-14);
|
||||
|
||||
const double solvedFirst = solution[0U];
|
||||
const double solvedSecond = solution[1U];
|
||||
expectSolverFailure(solver.solve(fesa::Vector{1U, 1.0}, solution));
|
||||
EXPECT_DOUBLE_EQ(solution[0U], solvedFirst);
|
||||
EXPECT_DOUBLE_EQ(solution[1U], solvedSecond);
|
||||
|
||||
fesa::Vector wrongSolution{1U};
|
||||
wrongSolution[0U] = 41.0;
|
||||
expectSolverFailure(solver.solve(fesa::Vector{2U, 1.0}, wrongSolution));
|
||||
EXPECT_DOUBLE_EQ(wrongSolution[0U], 41.0);
|
||||
|
||||
const auto rectangular = makeDenseCsr(
|
||||
2U, 3U, {2.0, 0.0, 0.0, 0.0, 3.0, 0.0});
|
||||
@@ -72,11 +103,6 @@ TEST(MklPardisoSolver, RejectsInvalidCsrStateAndDimensions) {
|
||||
rectangularStatus.diagnostics().front().code,
|
||||
"solver-matrix-not-square");
|
||||
|
||||
const auto empty = makeDenseCsr(0U, 0U, {});
|
||||
const auto emptyStatus = solver.factorize(empty);
|
||||
expectSolverFailure(emptyStatus);
|
||||
EXPECT_EQ(emptyStatus.diagnostics().front().code, "solver-empty-matrix");
|
||||
|
||||
fesa::SparsePattern invalidPattern{{0U, 2U}, {0U}};
|
||||
auto invalidCsr = fesa::SparseMatrix::fromCoo(
|
||||
1U,
|
||||
@@ -92,6 +118,18 @@ TEST(MklPardisoSolver, RejectsInvalidCsrStateAndDimensions) {
|
||||
nonsymmetricStatus.diagnostics().front().code,
|
||||
"solver-matrix-not-symmetric");
|
||||
|
||||
const auto scaledNonsymmetric = makeDenseCsr(
|
||||
2U, 2U, {2.0e-20, 1.0e-20, 1.1e-20, 3.0e-20});
|
||||
const auto scaledNonsymmetricStatus =
|
||||
solver.factorize(scaledNonsymmetric);
|
||||
// Stop this case before inspecting diagnostics when the production code
|
||||
// incorrectly accepts the matrix; this keeps the RED failure deterministic.
|
||||
ASSERT_FALSE(scaledNonsymmetricStatus.isOk());
|
||||
expectSolverFailure(scaledNonsymmetricStatus);
|
||||
EXPECT_EQ(
|
||||
scaledNonsymmetricStatus.diagnostics().front().code,
|
||||
"solver-matrix-not-symmetric");
|
||||
|
||||
fesa::SparsePattern noDiagonalPattern{{0U, 1U, 2U}, {1U, 0U}};
|
||||
auto noDiagonal = fesa::SparseMatrix::fromCoo(
|
||||
2U,
|
||||
@@ -105,9 +143,4 @@ TEST(MklPardisoSolver, RejectsInvalidCsrStateAndDimensions) {
|
||||
noDiagonalStatus.diagnostics().front().code,
|
||||
"solver-missing-diagonal");
|
||||
|
||||
const auto spd = makeDenseCsr(2U, 2U, {4.0, 1.0, 1.0, 3.0});
|
||||
ASSERT_TRUE(solver.factorize(spd).isOk());
|
||||
expectSolverFailure(solver.solve(fesa::Vector{1U, 1.0}, solution));
|
||||
fesa::Vector wrongSolution{1U};
|
||||
expectSolverFailure(solver.solve(fesa::Vector{2U, 1.0}, wrongSolution));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user