perf(math): route ordinary products through MKL and preserve arithmetic
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user