feat(solid): add Hex8 input and three-DOF semantics

This commit is contained in:
KOKO\Mimi
2026-10-09 01:12:30 +09:00
parent df0388ae2f
commit 9acf18db4b
16 changed files with 1468 additions and 98 deletions
+19 -8
View File
@@ -98,7 +98,8 @@ Status ValidateShellMoments(const Domain& domain, const Vector& full_load) {
} // namespace
Result<Vector> LoadAssembler::AssembleFullNodalLoad(const AnalysisModel& model,
const DofManager& dofs) {
const DofManager& dofs,
double step_time) {
const auto& active_loads = model.ActiveLoads();
const auto& owned_loads = model.Step().Loads();
if (active_loads.size() != owned_loads.size()) {
@@ -122,21 +123,31 @@ Result<Vector> LoadAssembler::AssembleFullNodalLoad(const AnalysisModel& model,
}
loads.push_back(owned_loads[load_index]);
}
return AssembleFullNodalLoad(model, dofs, loads);
return AssembleFullNodalLoad(model, dofs, loads, step_time);
}
Result<Vector> LoadAssembler::AssembleFullNodalLoad(const AnalysisModel& model,
const DofManager& dofs,
const LoadView& loads) {
const LoadView& loads,
double step_time) {
const Domain& domain = model.GetDomain();
const std::size_t components = dofs.ComponentsPerNode();
if (dofs.Profile() == DofProfile::kThermal ||
(domain.IsSolid() != (dofs.Profile() == DofProfile::kSolidStructural)) ||
!std::isfinite(step_time) || step_time < 0.0) {
return Result<Vector>::Failure(LoadFailure(
"invalid-load-context", {domain.SourcePath(), 0U}, "LOAD_ASSEMBLER", "",
"Nodal loads require the matching structural profile and finite "
"nonnegative endpoint time."));
}
if (domain.Nodes().size() >
(std::numeric_limits<std::size_t>::max)() / kDofsPerNode) {
(std::numeric_limits<std::size_t>::max)() / components) {
return Result<Vector>::Failure(LoadFailure(
"invalid-load-dimensions", {domain.SourcePath(), 0U}, "LOAD_ASSEMBLER",
domain.SourceContentIdentity(),
"The semantic node count cannot be represented in full-DOF order."));
}
const std::size_t expected_full_count = domain.Nodes().size() * kDofsPerNode;
const std::size_t expected_full_count = domain.Nodes().size() * components;
if (dofs.FullDofCount() != expected_full_count) {
return Result<Vector>::Failure(LoadFailure(
"invalid-load-dimensions", {domain.SourcePath(), 0U}, "LOAD_ASSEMBLER",
@@ -148,11 +159,11 @@ Result<Vector> LoadAssembler::AssembleFullNodalLoad(const AnalysisModel& model,
return Result<Vector>::Failure(dof_status);
}
for (std::size_t node = 0U; node < domain.Nodes().size(); ++node) {
for (std::size_t component = 0U; component < kDofsPerNode; ++component) {
for (std::size_t component = 0U; component < components; ++component) {
try {
if (dofs.FullDof(static_cast<EntityIndex>(node),
static_cast<DofComponent>(component)) !=
node * kDofsPerNode + component) {
node * components + component) {
return Result<Vector>::Failure(LoadFailure(
"invalid-load-order", domain.Nodes()[node].location,
"LOAD_ASSEMBLER",
@@ -170,7 +181,7 @@ Result<Vector> LoadAssembler::AssembleFullNodalLoad(const AnalysisModel& model,
const SourceTargetIndex target_index = SourceTargetIndex::FromDomain(domain);
const SourceTargetResolver target_resolver{target_index};
const LoadContext context{domain, dofs, target_resolver};
const LoadContext context{domain, dofs, target_resolver, step_time};
std::vector<std::vector<LoadContribution>> contributions_by_load;
contributions_by_load.reserve(loads.size());