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
+45 -9
View File
@@ -30,15 +30,18 @@ ConcentratedNodalLoad::ConcentratedNodalLoad(
global_components_{global_components},
source_order_{source_order} {}
ConcentratedNodalLoad::ConcentratedNodalLoad(SourceTargetQuery target,
const int source_dof,
const double magnitude,
const std::size_t source_order,
SourceLocation location)
ConcentratedNodalLoad::ConcentratedNodalLoad(
SourceTargetQuery target, const int source_dof, const double magnitude,
const std::size_t source_order, SourceLocation location,
std::optional<EntityIndex> amplitude_index, std::string amplitude_name_raw,
SourceLocation amplitude_location)
: target_{std::move(target)},
source_order_{source_order},
location_{std::move(location)},
source_dof_{source_dof} {
source_dof_{source_dof},
amplitude_index_{amplitude_index},
amplitude_name_raw_{std::move(amplitude_name_raw)},
amplitude_location_{std::move(amplitude_location)} {
if (source_dof >= 1 && source_dof <= static_cast<int>(kDofsPerNode)) {
global_components_[static_cast<std::size_t>(source_dof - 1)] = magnitude;
}
@@ -47,6 +50,33 @@ ConcentratedNodalLoad::ConcentratedNodalLoad(SourceTargetQuery target,
Result<std::vector<LoadContribution>>
ConcentratedNodalLoad::ComputeContributions(const LoadContext& context) const {
const std::string& identity = target_.target_name_or_label;
const std::size_t components = context.dof_manager.ComponentsPerNode();
if (context.dof_manager.Profile() == DofProfile::kThermal ||
(source_dof_ != 0 && source_dof_ > static_cast<int>(components))) {
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
"invalid-load-dof", location_, identity,
"The source load component is inactive for this physical profile."));
}
for (std::size_t component = components; component < kDofsPerNode;
++component) {
if (global_components_[component] != 0.0) {
return Result<std::vector<LoadContribution>>::Failure(
LoadFailure("invalid-load-dof", location_, identity,
"A Solid load cannot contain rotational components."));
}
}
double amplitude = 1.0;
if (amplitude_index_) {
if (!context.domain.IsSolid() || context.domain.Dynamic() == nullptr ||
*amplitude_index_ >= context.domain.Amplitudes().size() ||
!std::isfinite(context.step_time) || context.step_time < 0.0) {
return Result<std::vector<LoadContribution>>::Failure(
LoadFailure("invalid-load-amplitude", location_, identity,
"Amplitude requires a valid Solid dynamic endpoint."));
}
amplitude = context.domain.Amplitudes()[*amplitude_index_].Evaluate(
context.step_time);
}
if (source_dof_ != 0 &&
(source_dof_ < 1 || source_dof_ > static_cast<int>(kDofsPerNode))) {
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
@@ -76,7 +106,7 @@ ConcentratedNodalLoad::ComputeContributions(const LoadContext& context) const {
std::vector<unsigned char> seen(context.domain.Nodes().size(), 0U);
std::vector<LoadContribution> contributions;
contributions.reserve(resolved.Value().size() * kDofsPerNode);
contributions.reserve(resolved.Value().size() * components);
for (const auto& target : resolved.Value()) {
const EntityIndex node = target.entity_index;
if (node >= context.domain.Nodes().size() || seen[node] != 0U) {
@@ -86,13 +116,19 @@ ConcentratedNodalLoad::ComputeContributions(const LoadContext& context) const {
"identities."));
}
seen[node] = 1U;
for (std::size_t component = 0U; component < kDofsPerNode; ++component) {
for (std::size_t component = 0U; component < components; ++component) {
const double value = global_components_[component] * amplitude;
if (!std::isfinite(value)) {
return Result<std::vector<LoadContribution>>::Failure(
LoadFailure("nonfinite-load-value", location_, identity,
"Sampled load magnitude must remain finite."));
}
try {
contributions.push_back(
{source_order_,
context.dof_manager.FullDof(node,
static_cast<DofComponent>(component)),
global_components_[component]});
value});
} catch (const std::out_of_range&) {
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
"invalid-load-target", location_, identity,