feat(cpp-object-oriented-modular-refactoring): step 14 - runtime-element-factory
This commit is contained in:
@@ -288,6 +288,16 @@ Result<Mitc4PhysicalRecovery> RecoveryFailure(const SourceLocation& location,
|
||||
"*ELEMENT", identity, std::move(message)}}));
|
||||
}
|
||||
|
||||
/// @brief Creates a structured failure at the runtime element boundary.
|
||||
template <class T>
|
||||
Result<T> RuntimeFailure(const SourceLocation& location,
|
||||
const SourceEntityId& source_id, std::string message) {
|
||||
return Result<T>::Failure(Status::Failure(
|
||||
FailureCategory::kModel,
|
||||
{{Severity::kError, "invalid-runtime-element", location, "*ELEMENT",
|
||||
source_id.source_label_text, std::move(message)}}));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Result<Mitc4Shell> Mitc4Shell::Create(
|
||||
@@ -794,6 +804,95 @@ Result<Mitc4PhysicalRecovery> Mitc4Shell::RecoverPhysical(
|
||||
return Result<Mitc4PhysicalRecovery>::Success(std::move(recovery));
|
||||
}
|
||||
|
||||
const ElementDofLayout& Mitc4Shell::DofLayout() const noexcept {
|
||||
return dof_layout_;
|
||||
}
|
||||
|
||||
Result<ElementStiffnessContribution> Mitc4Shell::ComputeStiffness() const {
|
||||
if (dof_layout_.node_indices.size() != kNodeCount ||
|
||||
dof_layout_.components_per_node.size() != kGlobalDofsPerNode) {
|
||||
return RuntimeFailure<ElementStiffnessContribution>(
|
||||
runtime_location_, dof_layout_.source_id,
|
||||
"MITC4 runtime stiffness requires a bound four-node six-DOF layout.");
|
||||
}
|
||||
try {
|
||||
auto stiffness = Stiffness();
|
||||
if (!stiffness.HasValue()) {
|
||||
return Result<ElementStiffnessContribution>::Failure(
|
||||
stiffness.GetStatus());
|
||||
}
|
||||
return Result<ElementStiffnessContribution>::Success(
|
||||
{dof_layout_, std::move(stiffness.Value().stabilized_global24)});
|
||||
} catch (const std::exception& error) {
|
||||
return RuntimeFailure<ElementStiffnessContribution>(
|
||||
runtime_location_, dof_layout_.source_id, error.what());
|
||||
}
|
||||
}
|
||||
|
||||
Result<ElementResultBundle> Mitc4Shell::Recover(
|
||||
const Vector& element_displacement) const {
|
||||
if (dof_layout_.node_indices.size() != kNodeCount ||
|
||||
dof_layout_.components_per_node.size() != kGlobalDofsPerNode ||
|
||||
element_displacement.Size() != kGlobalDofCount) {
|
||||
return RuntimeFailure<ElementResultBundle>(
|
||||
runtime_location_, dof_layout_.source_id,
|
||||
"MITC4 runtime recovery requires a bound four-node layout and 24 "
|
||||
"DOFs.");
|
||||
}
|
||||
|
||||
Result<Mitc4PhysicalRecovery> recovered = [&]() {
|
||||
try {
|
||||
return RecoverPhysical(element_displacement);
|
||||
} catch (const std::exception& error) {
|
||||
return RuntimeFailure<Mitc4PhysicalRecovery>(
|
||||
runtime_location_, dof_layout_.source_id, error.what());
|
||||
}
|
||||
}();
|
||||
if (!recovered.HasValue()) {
|
||||
return Result<ElementResultBundle>::Failure(recovered.GetStatus());
|
||||
}
|
||||
|
||||
constexpr std::array<ShellMidsurfaceLocation, kNodeCount> locations{
|
||||
ShellMidsurfaceLocation::kGp1, ShellMidsurfaceLocation::kGp2,
|
||||
ShellMidsurfaceLocation::kGp3, ShellMidsurfaceLocation::kGp4};
|
||||
constexpr std::array<ShellSectionPosition, 3> positions{
|
||||
ShellSectionPosition::kBottom, ShellSectionPosition::kMiddle,
|
||||
ShellSectionPosition::kTop};
|
||||
constexpr std::array<double, 3> zeta{-1.0, 0.0, 1.0};
|
||||
|
||||
ShellElementResultRows rows{};
|
||||
rows.rows.reserve(kNodeCount);
|
||||
rows.physical_strain_energy = recovered.Value().strain_energy;
|
||||
for (std::size_t point = 0U; point < recovered.Value().points.size();
|
||||
++point) {
|
||||
const auto& physical_point = recovered.Value().points[point];
|
||||
ShellResultRow row{};
|
||||
row.element = element_index_;
|
||||
row.location = locations[point];
|
||||
row.natural_coordinates = physical_point.natural_coordinates;
|
||||
row.local_frame = {physical_point.local_frame.e1,
|
||||
physical_point.local_frame.e2,
|
||||
physical_point.local_frame.e3};
|
||||
row.generalized_strain = physical_point.generalized_strain;
|
||||
row.section_resultant = physical_point.section_resultant;
|
||||
for (std::size_t position = 0U; position < positions.size(); ++position) {
|
||||
row.stress[position] = {positions[position], zeta[position],
|
||||
physical_point.in_plane_stress[position]};
|
||||
}
|
||||
rows.rows.push_back(std::move(row));
|
||||
}
|
||||
return Result<ElementResultBundle>::Success(
|
||||
{dof_layout_.source_id, std::move(rows)});
|
||||
}
|
||||
|
||||
void Mitc4Shell::BindRuntime(ElementDofLayout layout,
|
||||
const EntityIndex element_index,
|
||||
SourceLocation location) {
|
||||
dof_layout_ = std::move(layout);
|
||||
element_index_ = element_index;
|
||||
runtime_location_ = std::move(location);
|
||||
}
|
||||
|
||||
Mitc4Shell::Mitc4Shell(std::array<Vector3, 4> coordinates,
|
||||
std::array<Vector3, 4> directors,
|
||||
std::array<Vector3, 4> tangent_a,
|
||||
|
||||
Reference in New Issue
Block a user