feat(hex8): use reference-weighted mean-volume energy
This commit is contained in:
@@ -86,7 +86,10 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
Hex8HighLowResponse response;
|
||||
std::array<HighLow, 24> force{};
|
||||
std::array<std::array<HighLow, 24>, 24> material{}, geometric{};
|
||||
HighLow energy;
|
||||
HighLow energy, volume, trace_integral;
|
||||
std::array<Tensor, 8> deformations{}, strains{};
|
||||
std::array<std::array<Triple, 8>, 8> point_gradients{};
|
||||
std::array<Triple, 8> integrated_fg{};
|
||||
for (std::size_t g = 0; g < 8; ++g) {
|
||||
const auto& point = points_[g];
|
||||
std::array<Triple, 8> gradients{};
|
||||
@@ -104,7 +107,7 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
for (std::size_t j = 0; j < 3; ++j)
|
||||
gradients[0][j] = math_internal::Negate(gradient_sum[j]);
|
||||
Tensor f{};
|
||||
Tensor strain{}, s{}, p{}, fft{};
|
||||
Tensor strain{};
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
for (std::size_t j = 0; j < 3; ++j) {
|
||||
f[i][j] = nonlinear ? h[i][j] : HighLow{};
|
||||
@@ -114,13 +117,48 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
for (std::size_t k = 0; k < 3; ++k)
|
||||
strain[i][j] += HighLow{0.5} * h[k][i] * h[k][j];
|
||||
}
|
||||
if (!Finite(h) || !Finite(f) || !Finite(strain))
|
||||
return Result<Hex8HighLowResponse>::Failure(Failure(
|
||||
"Hex8 high+low strain arithmetic is outside its supported range."));
|
||||
point_gradients[g] = gradients;
|
||||
deformations[g] = f;
|
||||
strains[g] = strain;
|
||||
volume += HighLow{point.weight};
|
||||
trace_integral +=
|
||||
HighLow{point.weight} * (strain[0][0] + strain[1][1] + strain[2][2]);
|
||||
}
|
||||
if (!IsNormalized(volume) || math_internal::Compare(volume, HighLow{}) != 1 ||
|
||||
!IsNormalized(trace_integral))
|
||||
return Result<Hex8HighLowResponse>::Failure(
|
||||
Failure("Hex8 high+low reference volume or trace is unsupported."));
|
||||
const HighLow mean_trace = trace_integral / volume;
|
||||
if (!IsNormalized(mean_trace))
|
||||
return Result<Hex8HighLowResponse>::Failure(
|
||||
Failure("Hex8 high+low weighted mean is unsupported."));
|
||||
const HighLow twice_mu = HighLow{2} * HighLow{mu_};
|
||||
const HighLow deviatoric_coefficient =
|
||||
math_internal::Negate(twice_mu) / HighLow{3};
|
||||
const HighLow bulk_coefficient = HighLow{kappa_} / volume;
|
||||
if (!IsNormalized(twice_mu) || !IsNormalized(deviatoric_coefficient) ||
|
||||
!IsNormalized(bulk_coefficient))
|
||||
return Result<Hex8HighLowResponse>::Failure(
|
||||
Failure("Hex8 high+low constitutive coefficients are unsupported."));
|
||||
energy = HighLow{0.5} * HighLow{kappa_} * volume * mean_trace * mean_trace;
|
||||
for (std::size_t g = 0; g < 8; ++g) {
|
||||
const auto& point = points_[g];
|
||||
const auto& gradients = point_gradients[g];
|
||||
const auto& f = deformations[g];
|
||||
const auto& strain = strains[g];
|
||||
const HighLow trace = strain[0][0] + strain[1][1] + strain[2][2];
|
||||
HighLow density_energy = HighLow{0.5} * HighLow{lambda_} * trace * trace;
|
||||
Tensor s{}, p{}, fft{};
|
||||
HighLow density_energy;
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
for (std::size_t j = 0; j < 3; ++j) {
|
||||
s[i][j] = HighLow{2} * HighLow{mu_} * strain[i][j];
|
||||
if (i == j) s[i][j] += HighLow{lambda_} * trace;
|
||||
density_energy += HighLow{mu_} * strain[i][j] * strain[i][j];
|
||||
const HighLow dev =
|
||||
strain[i][j] - (i == j ? trace / HighLow{3} : HighLow{});
|
||||
s[i][j] = twice_mu * dev;
|
||||
if (i == j) s[i][j] += HighLow{kappa_} * mean_trace;
|
||||
density_energy += HighLow{mu_} * dev * dev;
|
||||
}
|
||||
energy += density_energy * HighLow{point.weight};
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
@@ -144,8 +182,8 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
stress[i][j] = stress[i][j] / det;
|
||||
}
|
||||
}
|
||||
if (!Finite(h) || !Finite(f) || !Finite(strain) || !Finite(s) ||
|
||||
!Finite(p) || !Finite(fft) || !Finite(stress))
|
||||
if (!Finite(f) || !Finite(strain) || !Finite(s) || !Finite(p) ||
|
||||
!Finite(fft) || !Finite(stress))
|
||||
return Result<Hex8HighLowResponse>::Failure(Failure(
|
||||
"Hex8 high+low tensor arithmetic is outside its supported range."));
|
||||
response.high.points[g] = {element_index_, static_cast<int>(g + 1U),
|
||||
@@ -160,6 +198,9 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
for (std::size_t a = 0; a < 8; ++a)
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
fg[a][i] = Dot(f[i], gradients[a]);
|
||||
for (std::size_t a = 0; a < 8; ++a)
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
integrated_fg[a][i] += fg[a][i] * HighLow{point.weight};
|
||||
for (std::size_t a = 0; a < 8; ++a)
|
||||
for (std::size_t b = 0; b < 8; ++b) {
|
||||
const auto dot = Dot(gradients[a], gradients[b]);
|
||||
@@ -172,7 +213,7 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
for (std::size_t k = 0; k < 3; ++k) {
|
||||
const auto row = 3U * a + i;
|
||||
const auto column = 3U * b + k;
|
||||
const auto mat = HighLow{lambda_} * fg[a][i] * fg[b][k] +
|
||||
const auto mat = deviatoric_coefficient * fg[a][i] * fg[b][k] +
|
||||
HighLow{mu_} * fg[b][i] * fg[a][k] +
|
||||
HighLow{mu_} * fft[i][k] * dot;
|
||||
material[row][column] += mat * HighLow{point.weight};
|
||||
@@ -181,6 +222,13 @@ Result<Hex8HighLowResponse> Hex8Element::EvaluateHighLow(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nonlinear || !paired_linear_tangent_ready_)
|
||||
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)
|
||||
for (std::size_t k = 0; k < 3; ++k)
|
||||
material[3 * a + i][3 * b + k] +=
|
||||
bulk_coefficient * integrated_fg[a][i] * integrated_fg[b][k];
|
||||
if (!IsNormalized(energy))
|
||||
return Result<Hex8HighLowResponse>::Failure(
|
||||
Failure("Hex8 high+low energy is unsupported or nonfinite."));
|
||||
|
||||
Reference in New Issue
Block a user