feat(hex8): use reference-weighted mean-volume energy

This commit is contained in:
KOKO\Mimi
2026-10-10 23:32:40 +09:00
parent 29670e168d
commit 18b36c1c22
8 changed files with 537 additions and 155 deletions
@@ -295,4 +295,40 @@ TEST(Hex8HighLow, FiniteRotationRetainsTinyShearForceCovariance) {
EXPECT_LE(std::abs(Subtract(rotated[2], baseline[2]).high), 1e-13*gamma);
}
}
TEST(Hex8HighLow,
MeanVolumeLowOnlyNonuniformTraceRetainsMeanAndCrossPointHessian) {
auto brick = UnitBrick(0, .25);
fesa::Vector high(24), low(24), zero(24);
const double c = std::ldexp(1.0, -60);
for (std::size_t n = 0; n < 8; ++n) high[3 * n] = 1;
low[6] = c;
low[18] = c;
const double coefficient = 7 * 4.8 / 18 + 8.0 / 8;
const auto response = brick.EvaluateLinearHighLow(high, low);
const auto high_only = brick.EvaluateLinearHighLow(high, zero);
ASSERT_TRUE(response.HasValue());
ASSERT_TRUE(high_only.HasValue());
EXPECT_EQ(high_only.Value().high.strain_energy, 0);
EXPECT_NEAR(response.Value().high.strain_energy, coefficient * c * c,
1e-13 * c * c);
EXPECT_NEAR(response.Value().high.internal_force[6] +
response.Value().high.internal_force[18],
2 * coefficient * c, 1e-13 * c);
for (const auto& point : response.Value().high.points) {
const auto& s = point.cauchy_stress;
EXPECT_NEAR((s[0] + s[1] + s[2]) / 3, 4 * c, 1e-13 * c);
EXPECT_NEAR(point.strain[0], c * point.reference_coordinates[1], 1e-13 * c);
}
const auto& k = response.Value().high.tangent;
EXPECT_NEAR(k(0, 0), 41.0 / 18, 2e-14);
EXPECT_NEAR(k(0, 1), 19.0 / 30, 2e-14);
const auto nonlinear = brick.EvaluateNonlinearHighLow(high, low);
ASSERT_TRUE(nonlinear.HasValue());
const auto cubic_energy = Subtract({nonlinear.Value().high.strain_energy,
nonlinear.Value().strain_energy_low},
{response.Value().high.strain_energy,
response.Value().strain_energy_low});
EXPECT_NEAR(cubic_energy.high, (5 * 4.8 / 18 + 8.0 / 6) * c * c * c,
1e-12 * c * c * c);
}
} // namespace