feat(cpp-object-oriented-modular-refactoring): step 15 - generic-dof-manager

This commit is contained in:
KOKO\Mimi
2026-08-16 10:07:02 +09:00
parent c8c32236de
commit 9e74398655
5 changed files with 527 additions and 218 deletions
+2 -67
View File
@@ -22,71 +22,6 @@ Status ConstraintFailure(const std::string& code, const std::string& identity,
message}});
}
bool IsStrictlyIncreasing(const std::vector<std::size_t>& values) {
return std::adjacent_find(
values.begin(), values.end(),
[](const std::size_t left, const std::size_t right) {
return left >= right;
}) == values.end();
}
/// @brief Validates the stable full/free/constrained numbering invariant.
Status ValidateDofOrder(const DofManager& dofs) {
const std::size_t full_count = dofs.FullDofCount();
const auto& free_dofs = dofs.FreeDofs();
const auto& constrained_dofs = dofs.ConstrainedDofs();
if (free_dofs.size() != dofs.FreeDofCount() ||
constrained_dofs.size() != dofs.ConstrainedDofCount() ||
dofs.PrescribedValues().Size() != constrained_dofs.size() ||
constrained_dofs.size() > full_count ||
free_dofs.size() != full_count - constrained_dofs.size()) {
return ConstraintFailure("invalid-constraint-dimensions",
std::to_string(full_count),
"DofManager full, free, constrained, and "
"prescribed dimensions must agree.");
}
if (!IsStrictlyIncreasing(free_dofs) ||
!IsStrictlyIncreasing(constrained_dofs)) {
return ConstraintFailure(
"invalid-constraint-order", std::to_string(full_count),
"Free and constrained DOFs must use stable increasing full-DOF order.");
}
std::vector<unsigned char> ownership(full_count, 0U);
try {
for (std::size_t equation = 0U; equation < free_dofs.size(); ++equation) {
const std::size_t full_dof = free_dofs[equation];
if (full_dof >= full_count || ownership[full_dof] != 0U ||
dofs.FreeEquation(full_dof) != equation) {
return ConstraintFailure(
"invalid-constraint-order", std::to_string(full_dof),
"Free equation numbering must match the stable free-DOF order.");
}
ownership[full_dof] = 1U;
}
for (const std::size_t full_dof : constrained_dofs) {
if (full_dof >= full_count || ownership[full_dof] != 0U ||
dofs.FreeEquation(full_dof).has_value()) {
return ConstraintFailure(
"invalid-constraint-order", std::to_string(full_dof),
"Constrained DOFs must be unique and absent from free equations.");
}
ownership[full_dof] = 2U;
}
} catch (const std::out_of_range&) {
return ConstraintFailure(
"invalid-constraint-dimensions", std::to_string(full_count),
"DofManager equation storage does not cover every full DOF.");
}
if (std::find(ownership.begin(), ownership.end(), 0U) != ownership.end()) {
return ConstraintFailure("invalid-constraint-order",
std::to_string(full_count),
"Free and constrained DOFs must partition the "
"complete full-DOF range.");
}
return Status::Ok();
}
/// @brief Extracts one partition without changing the supplied DOF order.
Result<SparseMatrix> ExtractBlock(const SparseMatrix& full,
const std::vector<std::size_t>& row_dofs,
@@ -123,7 +58,7 @@ Result<SparseMatrix> ExtractBlock(const SparseMatrix& full,
}
void RequireDofOrder(const DofManager& dofs) {
if (!ValidateDofOrder(dofs).IsOk()) {
if (!dofs.ValidateInvariants().IsOk()) {
throw std::invalid_argument{
"DofManager constraint dimensions or order are invalid."};
}
@@ -144,7 +79,7 @@ Result<PartitionedStiffness> EssentialConstraints::Partition(
"Full stiffness must be square and match the DofManager full "
"dimension."));
}
const Status dof_status = ValidateDofOrder(dofs);
const Status dof_status = dofs.ValidateInvariants();
if (!dof_status.IsOk()) {
return Result<PartitionedStiffness>::Failure(dof_status);
}