완성된 HHT trial의 constraint 자료 중복 평가 제거

This commit is contained in:
KOKO\Mimi
2026-10-14 21:46:11 +09:00
parent 2850ceaa89
commit 0e5b3e05dd
11 changed files with 939 additions and 16 deletions
+109 -13
View File
@@ -60,6 +60,88 @@ Vector Local(const Vector& full,
return local;
}
/// @brief Preserves the exact floating representation, including signed zero.
bool SameBits(const double left, const double right) {
return std::memcmp(&left, &right, sizeof(double)) == 0;
}
/// @brief Compares semantic and original source identity without object keys.
bool SameSource(const SourceEntityId& left, const SourceEntityId& right) {
return left.instance_name == right.instance_name &&
left.source_label == right.source_label &&
left.source_label_text == right.source_label_text;
}
/// @brief Finds only the current complete directional response, otherwise miss.
const hht_internal::DirectionalShellConstraintData* MatchingConstraints(
const Domain& domain, const hht_internal::RuntimeShell& shell,
const hht_internal::DynamicAssembly& assembly, const std::size_t index,
const std::size_t shell_count, const Vector& q, const Vector& v) {
if (assembly.frame.is_initial || !assembly.trial_constraints.has_value())
return nullptr;
const auto& owner = *assembly.trial_constraints;
const auto& frame = assembly.frame;
if (owner.shells.size() != shell_count || index >= owner.shells.size() ||
owner.source_path != domain.SourcePath() ||
!std::isfinite(owner.time) || !std::isfinite(frame.time) ||
!SameBits(owner.time, frame.time) ||
owner.frame_index != frame.frame_index ||
owner.increment_index != frame.increment_index ||
owner.iteration_count != frame.iteration_count)
return nullptr;
const auto& record = owner.shells[index];
if (!record.directional_internal ||
record.element_index != shell.element_index ||
record.scatter != shell.scatter ||
!hht_internal::ReusableTrialContext(
record.evaluation_context,
hht_internal::ReadTrialEvaluationContext()))
return nullptr;
const auto configuration =
nonlinear_mitc4_internal::ConfigurationSnapshot::Read(shell.internal);
if (record.configuration.source.file != configuration.source.file ||
record.configuration.source.line != configuration.source.line ||
record.configuration.identity != configuration.identity)
return nullptr;
for (std::size_t i = 0U; i < configuration.values.size(); ++i)
if (!std::isfinite(record.configuration.values[i]) ||
!std::isfinite(configuration.values[i]) ||
!SameBits(record.configuration.values[i], configuration.values[i]))
return nullptr;
for (std::size_t i = 0U; i < 24U; ++i)
if (!std::isfinite(record.q[i]) || !std::isfinite(q[i]) ||
!std::isfinite(record.v[i]) || !std::isfinite(v[i]) ||
!SameBits(record.q[i], q[i]) || !SameBits(record.v[i], v[i]))
return nullptr;
for (std::size_t node = 0U; node < 4U; ++node) {
const auto global_node = shell.scatter[6U * node] / 6U;
if (global_node >= domain.Nodes().size() ||
!SameSource(record.node_source_ids[node],
domain.Nodes()[global_node].source_id))
return nullptr;
}
if (record.drilling_constraint.Size() != 4U ||
record.drilling_constraint_gradient.Rows() != 4U ||
record.drilling_constraint_gradient.Columns() != 24U)
return nullptr;
for (std::size_t node = 0U; node < 4U; ++node) {
const auto& hessian = record.drilling_constraint_hessian[node];
const auto& third =
record.drilling_constraint_third_directional_gradient[node];
if (hessian.Rows() != 24U || hessian.Columns() != 24U ||
third.Size() != 24U || !std::isfinite(record.drilling_constraint[node]))
return nullptr;
for (std::size_t i = 0U; i < 24U; ++i) {
if (!std::isfinite(record.drilling_constraint_gradient(node, i)) ||
!std::isfinite(third[i]))
return nullptr;
for (std::size_t j = 0U; j < 24U; ++j)
if (!std::isfinite(hessian(i, j))) return nullptr;
}
}
return &record;
}
NonlinearMitc4TrialDofs Trial(const Vector& local) {
NonlinearMitc4TrialDofs trial{};
for (std::size_t node = 0U; node < 4U; ++node) {
@@ -443,32 +525,46 @@ Result<ConstraintOperators> EvaluateConstraintOperators(
node_row[chart.null_nodes[row]] = row;
}
std::vector<bool> external_done(domain.Nodes().size(), false);
std::size_t shell_index = 0U;
for (const auto& shell : shells) {
const auto q = Local(assembly.frame.generalized_coordinates, shell);
const auto v = Local(assembly.frame.velocity, shell);
const auto internal = EvaluateInternalResidualAndTangent(shell.internal,
Trial(q), &v);
if (!internal.HasValue())
return Result<ConstraintOperators>::Failure(internal.GetStatus());
const auto* saved = MatchingConstraints(domain, shell, assembly,
shell_index++, shells.size(), q, v);
std::optional<NonlinearMitc4InternalEquilibrium> fresh;
if (saved == nullptr) {
auto internal =
EvaluateInternalResidualAndTangent(shell.internal, Trial(q), &v);
if (!internal.HasValue())
return Result<ConstraintOperators>::Failure(internal.GetStatus());
fresh = std::move(internal.Value());
}
const auto& constraint = saved != nullptr ? saved->drilling_constraint
: fresh->drilling_constraint;
const auto& gradient_data = saved != nullptr
? saved->drilling_constraint_gradient
: fresh->drilling_constraint_gradient;
const auto& third_data =
saved != nullptr
? saved->drilling_constraint_third_directional_gradient
: fresh->drilling_constraint_third_directional_gradient;
const auto& hessian_data = saved != nullptr
? saved->drilling_constraint_hessian
: fresh->drilling_constraint_hessian;
for (std::size_t local_node = 0U; local_node < 4U; ++local_node) {
const auto global_node = shell.scatter[6U * local_node] / 6U;
if (global_node >= node_row.size() || node_row[global_node] == rows)
continue;
const auto row = node_row[global_node];
result.rows[row].value +=
internal.Value().drilling_constraint[local_node];
result.rows[row].value += constraint[local_node];
for (std::size_t i = 0U; i < 24U; ++i) {
const auto global_i = shell.scatter[i];
const double gradient =
internal.Value().drilling_constraint_gradient(local_node, i);
const double third = internal.Value()
.drilling_constraint_third_directional_gradient
[local_node][i];
const double gradient = gradient_data(local_node, i);
const double third = third_data[local_node][i];
if (gradient != 0.0) gradients[row][global_i] += gradient;
if (third != 0.0) third_gradients[row][global_i] += third;
for (std::size_t j = 0U; j < 24U; ++j) {
const double hessian =
internal.Value().drilling_constraint_hessian[local_node](i, j);
const double hessian = hessian_data[local_node](i, j);
if (hessian != 0.0)
hessians[row][{global_i, shell.scatter[j]}] += hessian;
}