fix(hex8): retain original contraction order in MKL entry products

This commit is contained in:
KOKO\Mimi
2026-10-14 17:01:35 +09:00
parent eabaf6c893
commit 71e08169ec
+30 -14
View File
@@ -5,6 +5,7 @@
#include <stdexcept> #include <stdexcept>
#include <utility> #include <utility>
#include "../math/dense_blas_internal.h"
#include "hex8_geometry.h" #include "hex8_geometry.h"
namespace fesa { namespace fesa {
@@ -38,24 +39,39 @@ Matrix Outer(const std::array<Triple, 8>& values, double coefficient) {
} }
return left.Multiply(right); return left.Multiply(right);
} }
/// @brief Forms node-gradient Gram and stress congruence through dense MKL. /// @brief Uses MKL entry products and the original ordered Gram/stress sums.
Matrix GradientProduct(const std::array<Triple, 8>& gradients, Matrix GradientProduct(const std::array<Triple, 8>& gradients,
const Tensor* stress = nullptr) { const Tensor* stress = nullptr) {
Matrix left{8U, 3U}; const std::size_t terms = stress == nullptr ? 3U : 9U;
Matrix transpose{3U, 8U}; Vector left{64U * terms};
Vector right{64U * terms};
Vector final_factor{64U * terms};
for (std::size_t a = 0; a < 8; ++a) for (std::size_t a = 0; a < 8; ++a)
for (std::size_t i = 0; i < 3; ++i) { for (std::size_t b = 0; b < 8; ++b)
left(a, i) = gradients[a][i];
transpose(i, a) = gradients[a][i];
}
if (stress != nullptr) {
Matrix stress_transpose{3U, 3U};
for (std::size_t i = 0; i < 3; ++i)
for (std::size_t j = 0; j < 3; ++j) for (std::size_t j = 0; j < 3; ++j)
stress_transpose(i, j) = (*stress)[j][i]; for (std::size_t l = 0; l < (stress == nullptr ? 1U : 3U); ++l) {
left = left.Multiply(stress_transpose); const auto entry = (8U * a + b) * terms +
} (stress == nullptr ? j : 3U * j + l);
return left.Multiply(transpose); left[entry] = gradients[a][j];
right[entry] = stress == nullptr ? gradients[b][j] : (*stress)[l][j];
final_factor[entry] = gradients[b][l];
}
auto products = dense_blas_internal::MultiplyDiagonal(left, right);
if (stress != nullptr)
products = dense_blas_internal::MultiplyDiagonal(products, final_factor);
Matrix result{8U, 8U};
for (std::size_t a = 0; a < 8; ++a)
for (std::size_t b = 0; b < 8; ++b) {
const auto first = (8U * a + b) * terms;
if (stress == nullptr) {
result(a, b) = (products[first] + products[first + 1U]) +
products[first + 2U];
} else {
for (std::size_t term = 0; term < terms; ++term)
result(a, b) += products[first + term];
}
}
return result;
} }
/// @brief Retains product and cancellation errors in fixed-order contractions. /// @brief Retains product and cancellation errors in fixed-order contractions.
void AccumulateProduct(double left, double right, double& sum, void AccumulateProduct(double left, double right, double& sum,