fix(hht): preserve metric association and complete MKL actions
This commit is contained in:
@@ -1141,4 +1141,58 @@ TEST(HhtReducedChannelNewton, RestrictedSingularityIsNotFullInvertibility) {
|
||||
EXPECT_FALSE(solver.FactorizeFresh(restricted.Value().tangent).IsOk());
|
||||
}
|
||||
|
||||
TEST(HhtReducedOperators, NullMetricKeepsFiniteLeftAssociatedProducts) {
|
||||
const auto fixture = MakeFixture(false);
|
||||
const auto shells = fesa::hht_internal::BuildRuntimeShells(*fixture.domain,
|
||||
fixture.dofs);
|
||||
ASSERT_TRUE(shells.HasValue());
|
||||
const fesa::Vector zero(fixture.dofs.FullDofCount());
|
||||
const auto assembled = Assemble(fixture, shells.Value(), zero, zero, zero,
|
||||
zero, false);
|
||||
ASSERT_TRUE(assembled.HasValue());
|
||||
auto assembly = assembled.Value();
|
||||
const double maximum = (std::numeric_limits<double>::max)();
|
||||
const double epsilon = std::ldexp(1.0, -26);
|
||||
const double t = std::sqrt(1.0 - epsilon * epsilon);
|
||||
const std::array<double, 3U> n{epsilon, 0.6 * t, 0.8 * t};
|
||||
const std::array<double, 9U> block{0.0, maximum, maximum,
|
||||
maximum, 0.0, 0.0,
|
||||
maximum, 0.0, 0.0};
|
||||
double original_metric = 0.0;
|
||||
for (std::size_t i = 0U; i < 3U; ++i)
|
||||
for (std::size_t j = 0U; j < 3U; ++j)
|
||||
original_metric += (n[i] * block[3U * i + j]) * n[j];
|
||||
ASSERT_TRUE(std::isfinite(original_metric));
|
||||
ASSERT_GT(original_metric, 0.0);
|
||||
ASSERT_FALSE(std::isfinite(block[1U] * n[1U] + block[2U] * n[2U]));
|
||||
std::vector<fesa::CooContribution> entries;
|
||||
for (std::size_t node = 0U; node < assembly.rotations.size(); ++node) {
|
||||
assembly.rotations[node].drill_null = fesa::Vector3(n);
|
||||
for (std::size_t i = 0U; i < 3U; ++i)
|
||||
for (std::size_t j = 0U; j < 3U; ++j)
|
||||
entries.push_back({6U * node + 3U + i, 6U * node + 3U + j,
|
||||
block[3U * i + j], node, 3U * i + j});
|
||||
}
|
||||
const auto metric = fesa::hht_internal::MakeSparse(
|
||||
fixture.dofs.FullDofCount(), fixture.dofs.FullDofCount(),
|
||||
std::move(entries));
|
||||
ASSERT_TRUE(metric.HasValue());
|
||||
assembly.drilling_metric = metric.Value();
|
||||
const auto chart = fesa::hht_reduced_internal::BuildFixedChart(
|
||||
fixture.dofs, assembly.rotations);
|
||||
ASSERT_TRUE(chart.HasValue());
|
||||
fesa::hht_reduced_internal::ConstraintOperators operators;
|
||||
operators.rows.resize(chart.Value().null_nodes.size());
|
||||
for (std::size_t row = 0U; row < operators.rows.size(); ++row)
|
||||
for (std::size_t component = 0U; component < 3U; ++component)
|
||||
operators.rows[row].gradient.push_back(
|
||||
{6U * chart.Value().null_nodes[row] + 3U + component,
|
||||
original_metric * n[component]});
|
||||
fesa::MklPardisoTangentSolver solver;
|
||||
const auto checked = fesa::hht_reduced_internal::CheckGraphRegularity(
|
||||
assembly, chart.Value(), operators, solver);
|
||||
ASSERT_TRUE(checked.HasValue());
|
||||
EXPECT_GE(checked.Value(), std::ldexp(1.0, -32));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user