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
@@ -5,6 +5,7 @@
#include <cmath>
#include <cstddef>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>
@@ -26,33 +27,25 @@ double IndexedNorm(const Vector& values,
return result;
}
/// @brief Computes separate Kff*df and Kfc*dc norms in stable CSR order.
/// @brief Computes separate Kff*df and Kfc*dc norms through sparse MKL.
std::array<double, 2> FreeEquationInternalTermNorms(
const SparseMatrix& stiffness, const Vector& displacement,
const DofManager& dofs) {
std::vector<unsigned char> free_column(dofs.FullDofCount(), 0U);
Vector free_displacement{displacement.Size()};
Vector constrained_displacement = displacement;
for (const std::size_t full_dof : dofs.FreeDofs()) {
free_column[full_dof] = 1U;
free_displacement[full_dof] = displacement[full_dof];
constrained_displacement[full_dof] = 0.0;
}
const auto free_term = stiffness.Multiply(free_displacement);
const auto constrained_term = stiffness.Multiply(constrained_displacement);
double free_term_norm = 0.0;
double constrained_term_norm = 0.0;
for (const std::size_t row : dofs.FreeDofs()) {
double free_term = 0.0;
double constrained_term = 0.0;
for (std::size_t position = stiffness.RowOffsets()[row];
position < stiffness.RowOffsets()[row + 1U]; ++position) {
const std::size_t column = stiffness.ColumnIndices()[position];
const double contribution =
stiffness.Values()[position] * displacement[column];
if (free_column[column] != 0U) {
free_term += contribution;
} else {
constrained_term += contribution;
}
}
free_term_norm = std::hypot(free_term_norm, free_term);
constrained_term_norm = std::hypot(constrained_term_norm, constrained_term);
// Only the original free-row terms enter these acceptance scales.
free_term_norm = std::hypot(free_term_norm, free_term[row]);
constrained_term_norm =
std::hypot(constrained_term_norm, constrained_term[row]);
}
return {free_term_norm, constrained_term_norm};
}
@@ -96,7 +89,7 @@ double NormalizedBalance(const std::array<double, 3>& balance,
Result<GlobalEquilibriumResult> GlobalEquilibriumRecovery(
const Domain& domain, const DofManager& dofs,
const SparseMatrix& full_stiffness, const Vector& full_displacement,
const Vector& full_external_force) {
const Vector& full_external_force) try {
const std::size_t full_count = dofs.FullDofCount();
if (full_stiffness.Rows() != full_count ||
full_stiffness.Columns() != full_count ||
@@ -171,6 +164,15 @@ Result<GlobalEquilibriumResult> GlobalEquilibriumRecovery(
// shell global equilibrium below separately filters constrained reactions.
result.reaction = result.residual;
return Result<GlobalEquilibriumResult>::Success(std::move(result));
} catch (const std::length_error&) {
return RecoveryResultFailure<GlobalEquilibriumResult>(
"recovery-index-overflow", {domain.SourcePath(), 0U},
domain.SourceContentIdentity(),
"Recovery multiplication exceeds the backend integer range.");
} catch (const std::runtime_error&) {
return RecoveryResultFailure<GlobalEquilibriumResult>(
"recovery-multiplication-failed", {domain.SourcePath(), 0U},
domain.SourceContentIdentity(), "Recovery sparse multiplication failed.");
}
Status RecoverShellGlobalEvidence(const Domain& domain, const DofManager& dofs,