fix(hht): preserve metric association and complete MKL actions

This commit is contained in:
KOKO\Mimi
2026-10-14 18:38:00 +09:00
parent 2853051896
commit c58d499727
6 changed files with 155 additions and 43 deletions
+45 -3
View File
@@ -7,6 +7,7 @@
#include <utility>
#include "analysis/hht_dynamic_internal.h"
#include "math/dense_blas_internal.h"
#include "fesa/assembly/parallel_for.h"
#include "fesa/elements/finite_rotation.h"
#include "fesa/loads/load.h"
@@ -54,6 +55,27 @@ Vector Gather(const Vector& full, const RuntimeShell& shell) {
return local;
}
/// @brief Preserves rejected entries while batching finite products in MKL.
Vector EntryProducts(const Vector& left, const Vector& right) {
Vector result(left.Size(), std::numeric_limits<double>::quiet_NaN());
std::vector<std::size_t> positions;
positions.reserve(left.Size());
for (std::size_t i = 0U; i < left.Size(); ++i)
if (std::isfinite(left[i]) && std::isfinite(right[i])) positions.push_back(i);
Vector valid_left{positions.size()};
Vector valid_right{positions.size()};
for (std::size_t i = 0U; i < positions.size(); ++i) {
valid_left[i] = left[positions[i]];
valid_right[i] = right[positions[i]];
}
const dense_blas_internal::ScopedLocalDenseThreads local_threads{};
const Vector products =
dense_blas_internal::MultiplyDiagonal(valid_left, valid_right);
for (std::size_t i = 0U; i < positions.size(); ++i)
result[positions[i]] = products[i];
return result;
}
} // namespace
Result<std::vector<RuntimeShell>> BuildRuntimeShells(const Domain& domain,
@@ -455,6 +477,15 @@ Result<DynamicAssembly> EvaluateAssembly(
}
}
const auto a = Gather(frame.acceleration, shells[e]);
Vector mass_values{24U * 24U};
Vector acceleration_values{24U * 24U};
for (std::size_t row = 0U; row < 24U; ++row)
for (std::size_t column = 0U; column < 24U; ++column) {
const auto index = 24U * row + column;
mass_values[index] = m.mass(row, column);
acceleration_values[index] = a[column];
}
const Vector mass_action = EntryProducts(mass_values, acceleration_values);
for (std::size_t row = 0U; row < 24U; ++row) {
const auto global = shells[e].scatter[row];
frame.internal_force[global] += f.internal_force[row];
@@ -466,7 +497,7 @@ Result<DynamicAssembly> EvaluateAssembly(
std::abs(f.drilling_force[row]);
for (std::size_t column = 0U; column < 24U; ++column) {
frame.residual_scale[global] +=
std::abs(m.mass(row, column) * a[column]);
std::abs(mass_action[24U * row + column]);
const std::array<double, 6> values{
m.mass(row, column), m.position_tangent(row, column),
m.velocity_tangent(row, column), f.internal_tangent(row, column),
@@ -543,9 +574,20 @@ Result<DynamicAssembly> EvaluateAssembly(
Vector hidden_second(domain.Nodes().size());
Vector hidden_second_scale(domain.Nodes().size());
for (std::size_t node = 0U; node < constraint_hessians.size(); ++node) {
Vector coefficients{constraint_hessians[node].size()};
Vector first_velocity{coefficients.Size()};
Vector second_velocity{coefficients.Size()};
std::size_t index = 0U;
for (const auto& entry : constraint_hessians[node]) {
const double term = entry.second * frame.velocity[entry.first.first] *
frame.velocity[entry.first.second];
coefficients[index] = entry.second;
first_velocity[index] = frame.velocity[entry.first.first];
second_velocity[index] = frame.velocity[entry.first.second];
++index;
}
const Vector products = EntryProducts(
EntryProducts(coefficients, first_velocity), second_velocity);
for (std::size_t i = 0U; i < products.Size(); ++i) {
const double term = products[i];
hidden_second[node] += term;
hidden_second_scale[node] += std::abs(term);
}