perf(math): route ordinary products through MKL and preserve arithmetic

This commit is contained in:
KOKO\Mimi
2026-10-14 15:09:53 +09:00
parent b4fc1bb54b
commit 59c8e93b07
18 changed files with 793 additions and 169 deletions
+21 -19
View File
@@ -10,6 +10,7 @@
#include <vector>
#include "fesa/fem/dof_manager.h"
#include "math/dense_blas_internal.h"
namespace fesa::eigen_internal {
namespace {
@@ -117,7 +118,8 @@ Result<NodalLift> MakeLift(const Matrix& mass,
if (positive == 0U) return Result<NodalLift>::Success(std::move(result));
const Matrix scaled = ScaledMass(mass, length);
Matrix mp(positive, positive);
Matrix mp = dense_blas_internal::MultiplyTransposeLeft(basis, scaled)
.Multiply(basis);
double scale = 0.0;
double basis_error = 0.0;
for (std::size_t i = 0; i < positive; ++i) {
@@ -125,9 +127,6 @@ Result<NodalLift> MakeLift(const Matrix& mass,
double gram = 0.0;
for (std::size_t a = 0; a < 6U; ++a) {
gram += basis(a, i) * basis(a, j);
for (std::size_t b = 0; b < 6U; ++b) {
mp(i, j) += basis(a, i) * scaled(a, b) * basis(b, j);
}
}
basis_error = std::hypot(basis_error, gram - (i == j ? 1.0 : 0.0));
scale = (std::max)(scale, std::abs(mp(i, j)));
@@ -343,17 +342,18 @@ Result<EigenReduction> BuildEigenReduction(
kz_error = std::hypot(kz_error, item.second);
}
const auto& left = lifts[node];
std::map<std::size_t, Matrix> projected_blocks;
for (const auto& entry : blocks) {
projected_blocks.emplace(
entry.first, dense_blas_internal::MultiplyTransposeLeft(
left.scaled_lift, entry.second)
.Multiply(lifts[entry.first].scaled_lift));
}
for (std::size_t i = 0; i < left.scaled_lift.Columns(); ++i) {
for (const auto& entry : blocks) {
for (const auto& entry : projected_blocks) {
const auto& right = lifts[entry.first];
for (std::size_t j = 0; j < right.scaled_lift.Columns(); ++j) {
double value = 0.0;
for (std::size_t a = 0; a < 6U; ++a) {
for (std::size_t b = 0; b < 6U; ++b) {
value += left.scaled_lift(a, i) * entry.second(a, b) *
right.scaled_lift(b, j);
}
}
const double value = entry.second(i, j);
pattern.column_indices.push_back(right.offset + j);
contributions.push_back({left.offset + i, right.offset + j, value,
node, pattern.column_indices.size() - 1U});
@@ -385,11 +385,12 @@ Vector RestoreScaledMode(const EigenReduction& reduction, const Matrix& vectors,
Vector result(reduction.nodes.size() * 6U);
for (std::size_t node = 0; node < reduction.nodes.size(); ++node) {
const auto& lift = reduction.nodes[node];
Vector reduced{lift.scaled_lift.Columns()};
for (std::size_t j = 0; j < reduced.Size(); ++j)
reduced[j] = vectors(lift.offset + j, column);
const auto restored = lift.scaled_lift.Multiply(reduced);
for (std::size_t a = 0; a < 6U; ++a) {
for (std::size_t j = 0; j < lift.scaled_lift.Columns(); ++j) {
result[6U * node + a] +=
lift.scaled_lift(a, j) * vectors(lift.offset + j, column);
}
result[6U * node + a] = restored[a];
}
}
return result;
@@ -399,10 +400,11 @@ Vector MultiplyNodalMass(const std::vector<Matrix>& mass,
const Vector& vector) {
Vector result(vector.Size());
for (std::size_t node = 0; node < mass.size(); ++node) {
Vector local{6U};
for (std::size_t b = 0; b < 6U; ++b) local[b] = vector[6U * node + b];
const auto product = mass[node].Multiply(local);
for (std::size_t a = 0; a < 6U; ++a) {
for (std::size_t b = 0; b < 6U; ++b) {
result[6U * node + a] += mass[node](a, b) * vector[6U * node + b];
}
result[6U * node + a] = product[a];
}
}
return result;