fix(hht): preserve metric association and complete MKL actions
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user