perf(hex8): cache immutable paired linear Hessian
This commit is contained in:
@@ -65,6 +65,26 @@ TEST(Hex8HighLow, NonlinearLowGradientProducesSecondOrderForce) {
|
||||
1e-12 * strain * strain);
|
||||
}
|
||||
|
||||
TEST(Hex8HighLow, VolumetricAndTransverseTermsRetainLowStrain) {
|
||||
auto brick = UnitBrick(0, 0.25);
|
||||
fesa::Vector high(24), low(24);
|
||||
const double strain = std::ldexp(1.0, -60);
|
||||
for (std::size_t a = 0; a < 8; ++a) high[3*a] = 1;
|
||||
for (auto a : {1, 2, 5, 6}) low[3*a] = strain;
|
||||
const auto linear = brick.EvaluateLinearHighLow(high, low);
|
||||
const auto nonlinear = brick.EvaluateNonlinearHighLow(high, low);
|
||||
ASSERT_TRUE(linear.HasValue()); ASSERT_TRUE(nonlinear.HasValue());
|
||||
// Uniform axial strain: lambda=mu=4.8, each nodal face integral is 1/4.
|
||||
EXPECT_NEAR(linear.Value().high.internal_force[3], 3.6*strain, 1e-13*strain);
|
||||
EXPECT_NEAR(linear.Value().high.internal_force[7], 1.2*strain, 1e-13*strain);
|
||||
EXPECT_NEAR(linear.Value().high.strain_energy, 7.2*strain*strain,
|
||||
1e-13*strain*strain);
|
||||
const auto quadratic = Subtract(
|
||||
{nonlinear.Value().high.internal_force[3], nonlinear.Value().internal_force_low[3]},
|
||||
{linear.Value().high.internal_force[3], linear.Value().internal_force_low[3]});
|
||||
EXPECT_NEAR(quadratic.high, 5.4*strain*strain, 1e-12*strain*strain);
|
||||
}
|
||||
|
||||
TEST(Hex8HighLow, RejectsInvalidLowShapeAndOverlappingComponents) {
|
||||
auto brick = UnitBrick();
|
||||
fesa::Vector high(24), low(24);
|
||||
@@ -90,6 +110,30 @@ TEST(Hex8HighLow, LinearAndNonlinearZeroStateHaveSameFullHessian) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Hex8HighLow, CachedLinearHessianIsIndependentOfTrialAndPriorFailure) {
|
||||
auto brick = UnitBrick(0, 0.25);
|
||||
fesa::Vector zero(24), high(24), low(24);
|
||||
high[3] = 0.1;
|
||||
low[3] = std::ldexp(1.0, -60);
|
||||
const auto reference = brick.EvaluateLinearHighLow(zero, zero);
|
||||
ASSERT_TRUE(reference.HasValue());
|
||||
EXPECT_FALSE(brick.EvaluateLinearHighLow(high, fesa::Vector(23)).HasValue());
|
||||
const auto strained = brick.EvaluateLinearHighLow(high, low);
|
||||
ASSERT_TRUE(strained.HasValue());
|
||||
for (std::size_t i = 0; i < 24; ++i)
|
||||
for (std::size_t j = 0; j < 24; ++j) {
|
||||
EXPECT_EQ(reference.Value().high.tangent(i,j), strained.Value().high.tangent(i,j));
|
||||
EXPECT_EQ(reference.Value().tangent_low(i,j), strained.Value().tangent_low(i,j));
|
||||
}
|
||||
const auto nonlinear_zero = brick.EvaluateNonlinearHighLow(zero, zero);
|
||||
ASSERT_TRUE(nonlinear_zero.HasValue());
|
||||
for (std::size_t i = 0; i < 24; ++i)
|
||||
for (std::size_t j = 0; j < 24; ++j) {
|
||||
EXPECT_EQ(reference.Value().high.tangent(i,j), nonlinear_zero.Value().high.tangent(i,j));
|
||||
EXPECT_EQ(reference.Value().tangent_low(i,j), nonlinear_zero.Value().tangent_low(i,j));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Hex8HighLow, CoupledBricksTransmitLowStrainAcrossSharedFace) {
|
||||
const auto left = UnitBrick(), right = UnitBrick(1);
|
||||
fesa::Vector high(24), left_low(24), right_low(24);
|
||||
|
||||
Reference in New Issue
Block a user