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