feat(cpp-object-oriented-modular-refactoring): step 18 - load-hierarchy
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
#include "fesa/loads/concentrated_nodal_load.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "fesa/fem/dof_manager.h"
|
||||
#include "fesa/model/domain.h"
|
||||
|
||||
namespace fesa {
|
||||
namespace {
|
||||
|
||||
constexpr std::size_t kDofsPerNode = 6U;
|
||||
|
||||
Status LoadFailure(const std::string& code, const SourceLocation& location,
|
||||
const std::string& identity, const std::string& message) {
|
||||
return Status::Failure(
|
||||
FailureCategory::kModel,
|
||||
{{Severity::kError, code, location, "CLOAD", identity, message}});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConcentratedNodalLoad::ConcentratedNodalLoad(
|
||||
SourceTargetQuery target, std::array<double, 6> global_components,
|
||||
const std::size_t source_order)
|
||||
: target_{std::move(target)},
|
||||
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)
|
||||
: target_{std::move(target)},
|
||||
source_order_{source_order},
|
||||
location_{std::move(location)},
|
||||
source_dof_{source_dof} {
|
||||
if (source_dof >= 1 && source_dof <= static_cast<int>(kDofsPerNode)) {
|
||||
global_components_[static_cast<std::size_t>(source_dof - 1)] = magnitude;
|
||||
}
|
||||
}
|
||||
|
||||
Result<std::vector<LoadContribution>>
|
||||
ConcentratedNodalLoad::ComputeContributions(const LoadContext& context) const {
|
||||
const std::string& identity = target_.target_name_or_label;
|
||||
if (source_dof_ != 0 &&
|
||||
(source_dof_ < 1 || source_dof_ > static_cast<int>(kDofsPerNode))) {
|
||||
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
|
||||
"invalid-load-dof", location_, identity,
|
||||
"A nodal load component must be in the range 1 through 6."));
|
||||
}
|
||||
for (const double component : global_components_) {
|
||||
if (!std::isfinite(component)) {
|
||||
return Result<std::vector<LoadContribution>>::Failure(
|
||||
LoadFailure("nonfinite-load-value", location_, identity,
|
||||
"A nodal load magnitude must be finite."));
|
||||
}
|
||||
}
|
||||
if (target_.entity_kind != SourceEntityKind::kNode) {
|
||||
return Result<std::vector<LoadContribution>>::Failure(
|
||||
LoadFailure("invalid-load-target", location_, identity,
|
||||
"A concentrated nodal load requires a node target."));
|
||||
}
|
||||
|
||||
auto resolved = context.target_resolver.Resolve(target_);
|
||||
if (!resolved.HasValue()) {
|
||||
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
|
||||
"invalid-load-target", location_, identity,
|
||||
"The load target must resolve unambiguously to one node or one "
|
||||
"expanded node set."));
|
||||
}
|
||||
|
||||
std::vector<unsigned char> seen(context.domain.Nodes().size(), 0U);
|
||||
std::vector<LoadContribution> contributions;
|
||||
contributions.reserve(resolved.Value().size() * kDofsPerNode);
|
||||
for (const auto& target : resolved.Value()) {
|
||||
const EntityIndex node = target.entity_index;
|
||||
if (node >= context.domain.Nodes().size() || seen[node] != 0U) {
|
||||
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
|
||||
"invalid-load-target", location_, identity,
|
||||
"The expanded node set must contain unique in-range stable node "
|
||||
"identities."));
|
||||
}
|
||||
seen[node] = 1U;
|
||||
for (std::size_t component = 0U; component < kDofsPerNode; ++component) {
|
||||
try {
|
||||
contributions.push_back(
|
||||
{source_order_,
|
||||
context.dof_manager.FullDof(node,
|
||||
static_cast<DofComponent>(component)),
|
||||
global_components_[component]});
|
||||
} catch (const std::out_of_range&) {
|
||||
return Result<std::vector<LoadContribution>>::Failure(LoadFailure(
|
||||
"invalid-load-target", location_, identity,
|
||||
"The resolved load target must have all six full DOFs."));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result<std::vector<LoadContribution>>::Success(
|
||||
std::move(contributions));
|
||||
}
|
||||
|
||||
const SourceTargetQuery& ConcentratedNodalLoad::Target() const noexcept {
|
||||
return target_;
|
||||
}
|
||||
|
||||
const std::array<double, 6>& ConcentratedNodalLoad::GlobalComponents()
|
||||
const noexcept {
|
||||
return global_components_;
|
||||
}
|
||||
|
||||
std::size_t ConcentratedNodalLoad::SourceOrder() const noexcept {
|
||||
return source_order_;
|
||||
}
|
||||
|
||||
const SourceLocation& ConcentratedNodalLoad::Location() const noexcept {
|
||||
return location_;
|
||||
}
|
||||
|
||||
} // namespace fesa
|
||||
Reference in New Issue
Block a user