feat: adopt lumped mass and reduced-coordinate shell HHT

Integrate Hex8 mass verification and fixed-null-basis shell dynamics with numerical and physics handoff evidence. Preserve interrupted reference and full-validation status; full integration validation is deferred until after performance optimization.
This commit is contained in:
KOKO\Mimi
2026-10-13 16:57:19 +09:00
parent ede137c6b4
commit eaa5cbeb21
110 changed files with 15274 additions and 971 deletions
@@ -90,7 +90,16 @@ double GradientIntegral(std::size_t a, std::size_t b, std::size_t i,
}
std::vector<double> DenseOracle(const std::vector<std::size_t>& free) {
const auto n = free.size();
std::vector<double> k(n * n, 0.0), m(n * n, 0.0), eigen(n, 0.0);
std::vector<double> k(n * n, 0.0), full_mass(24U * 24U, 0.0),
m(n * n, 0.0), eigen(n, 0.0);
for (std::size_t a = 0; a < 8; ++a)
for (std::size_t b = 0; b < 8; ++b)
for (std::size_t i = 0; i < 3; ++i) {
double value = 2.0 * 48.0 / 64.0;
for (std::size_t d = 0; d < 3; ++d)
value *= 1.0 + kSigns[a][d] * kSigns[b][d] / 3.0;
full_mass[(3U * a + i) * 24U + 3U * b + i] = value;
}
for (std::size_t row = 0; row < n; ++row)
for (std::size_t col = 0; col < n; ++col) {
const auto a = free[row] / 3U, b = free[col] / 3U;
@@ -104,12 +113,12 @@ std::vector<double> DenseOracle(const std::vector<std::size_t>& free) {
GradientIntegral(a, b, j, i) + (i == j ? gradient_dot : 0.0)) +
(80.0 / 48.0) * (48.0 * kSigns[a][i] / (8.0 * (i + 1))) *
(48.0 * kSigns[b][j] / (8.0 * (j + 1)));
if (i == j) {
m[row * n + col] = 2.0 * 48.0 / 64.0;
for (std::size_t d = 0; d < 3; ++d)
m[row * n + col] *= 1.0 + kSigns[a][d] * kSigns[b][d] / 3.0;
}
}
for (std::size_t row = 0; row < n; ++row) {
const auto full_row = free[row];
for (std::size_t col = 0; col < 24U; ++col)
m[row * n + row] += full_mass[full_row * 24U + col];
}
EXPECT_EQ(
LAPACKE_dsygv(LAPACK_ROW_MAJOR, 1, 'N', 'U', static_cast<MKL_INT>(n),
k.data(), static_cast<MKL_INT>(n), m.data(),
@@ -126,7 +135,7 @@ std::vector<std::size_t> FaceFree() {
}
} // namespace
TEST(SolidFrequencyProcedure,
OriginalConsistentPencilMatchesIndependentDenseOracle) {
RowSumLumpedPencilMatchesIndependentDenseOracle) {
for (const bool constrained : {false, true}) {
const std::size_t count = constrained ? 12U : 24U;
auto domain = Brick(count, constrained ? kFaceFixed : "");
@@ -282,9 +291,9 @@ TEST(SolidFrequencyProcedure,
TEST(SolidFrequencyProcedure, RejectsOverflowingOriginalPencilValidationScale) {
// Every local K entry, eigenvalue, and spectral enclosure is representable.
// The all-odd x Walsh mode still overflows the original residual/energy
// denominators: finite / infinity must never become passing zero evidence.
auto domain = Brick(24U, "", 1.0, 2.0, 3e306);
// With M_L=12*I, the highest mode makes ||K||_F+|lambda|*||M||_F
// overflow: finite / infinity must never become passing zero evidence.
auto domain = Brick(24U, "", 1.0, 2.0, 4e306);
ASSERT_TRUE(domain.HasValue()) << StatusText(domain.GetStatus());
const auto result =
fesa::SolidFrequencyProcedureExecutor{}.Execute(domain.Value());