feat(solid): add Hex8 input and three-DOF semantics
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user