feat(cpp-object-oriented-modular-refactoring): step 9 - result-io-vector3

This commit is contained in:
KOKO\Mimi
2026-08-16 07:40:16 +09:00
parent 1cb1f26cdc
commit 0be8d1bd89
6 changed files with 140 additions and 148 deletions
+32 -52
View File
@@ -16,6 +16,7 @@
#include "fesa/elements/euler_beam_3d.h"
#include "fesa/elements/mitc4_shell.h"
#include "fesa/math/vector3.h"
namespace fesa {
namespace {
@@ -389,27 +390,12 @@ Result<std::vector<EntityIndex>> ResolveLoadTarget(const Domain& domain,
"A station-eligibility load target must resolve to a node or node set.");
}
std::array<double, 3> Cross(const std::array<double, 3>& left,
const std::array<double, 3>& right) {
return {left[1U] * right[2U] - left[2U] * right[1U],
left[2U] * right[0U] - left[0U] * right[2U],
left[0U] * right[1U] - left[1U] * right[0U]};
}
double Dot(const std::array<double, 3>& left,
const std::array<double, 3>& right) {
return left[0U] * right[0U] + left[1U] * right[1U] + left[2U] * right[2U];
}
double Norm(const std::array<double, 3>& value) {
return std::hypot(value[0U], value[1U], value[2U]);
}
bool AccumulateVectorAndScale(std::array<double, 3>& total, double& scale,
const std::array<double, 3>& contribution) {
const double magnitude = Norm(contribution);
const Vector3 contribution_vector{contribution};
const double magnitude = contribution_vector.Norm();
const double accumulated_scale = scale + magnitude;
if (!IsFinite(contribution) || !std::isfinite(magnitude) ||
if (!contribution_vector.IsFinite() || !std::isfinite(magnitude) ||
!std::isfinite(accumulated_scale)) {
return false;
}
@@ -427,7 +413,7 @@ bool AccumulateVectorAndScale(std::array<double, 3>& total, double& scale,
double NormalizedBalance(const std::array<double, 3>& balance,
const double scale) {
const double balance_norm = Norm(balance);
const double balance_norm = Vector3{balance}.Norm();
if (!std::isfinite(balance_norm) || !std::isfinite(scale)) {
return (std::numeric_limits<double>::infinity)();
}
@@ -474,10 +460,11 @@ Status PopulateShellGlobalEvidence(const Domain& domain, const DofManager& dofs,
}
}
const auto applied_force_moment =
Cross(domain.Nodes()[node].coordinates, nodal_applied_force);
const auto reaction_force_moment =
Cross(domain.Nodes()[node].coordinates, nodal_reaction_force);
const Vector3 position{domain.Nodes()[node].coordinates};
const Vector3 applied_force_moment =
position.Cross(Vector3{nodal_applied_force});
const Vector3 reaction_force_moment =
position.Cross(Vector3{nodal_reaction_force});
for (std::size_t component = 0U; component < 3U; ++component) {
nodal_applied_moment[component] += applied_force_moment[component];
nodal_reaction_moment[component] += reaction_force_moment[component];
@@ -498,24 +485,24 @@ Status PopulateShellGlobalEvidence(const Domain& domain, const DofManager& dofs,
}
}
std::array<double, 3> force_balance{};
std::array<double, 3> moment_balance{};
const Vector3 force_balance =
Vector3{applied_force} + Vector3{reaction_force};
const Vector3 moment_balance =
Vector3{applied_moment} + Vector3{reaction_moment};
for (std::size_t component = 0U; component < 3U; ++component) {
force_balance[component] =
applied_force[component] + reaction_force[component];
moment_balance[component] =
applied_moment[component] + reaction_moment[component];
candidate.equilibrium[component] = force_balance[component];
candidate.equilibrium[3U + component] = moment_balance[component];
}
const double force_metric = NormalizedBalance(
force_balance, (std::max)(applied_force_scale, reaction_force_scale));
const double force_metric =
NormalizedBalance(force_balance.Components(),
(std::max)(applied_force_scale, reaction_force_scale));
const double moment_metric = NormalizedBalance(
moment_balance, (std::max)(applied_moment_scale, reaction_moment_scale));
moment_balance.Components(),
(std::max)(applied_moment_scale, reaction_moment_scale));
candidate.verification_metrics = {normalized_residual, force_metric,
moment_metric};
if (!IsFinite(candidate.equilibrium) ||
!IsFinite(candidate.verification_metrics)) {
!Vector3{candidate.verification_metrics}.IsFinite()) {
return RecoveryFailure("nonfinite-recovery-value",
{domain.SourcePath(), 0U}, "global-equilibrium",
"Global equilibrium values and their physical "
@@ -535,32 +522,25 @@ std::optional<AxisSet> LocalAxes(const Domain& domain,
const EulerBeam3DDefinition& element) {
const auto& first = domain.Nodes()[element.node_indices[0U]].coordinates;
const auto& second = domain.Nodes()[element.node_indices[1U]].coordinates;
const std::array<double, 3> delta = {
second[0U] - first[0U], second[1U] - first[1U], second[2U] - first[2U]};
const double length = Norm(delta);
const Vector3 delta = Vector3{second} - Vector3{first};
const double length = delta.Norm();
if (!std::isfinite(length) || !(length > 0.0)) {
return std::nullopt;
}
const std::array<double, 3> ex = {delta[0U] / length, delta[1U] / length,
delta[2U] / length};
const auto& guide = domain.Sections()[element.section_index].first_axis;
const double projection = Dot(guide, ex);
const std::array<double, 3> ey_trial = {guide[0U] - projection * ex[0U],
guide[1U] - projection * ex[1U],
guide[2U] - projection * ex[2U]};
const double ey_norm = Norm(ey_trial);
const Vector3 ex = delta / length;
const Vector3 guide{domain.Sections()[element.section_index].first_axis};
const double projection = guide.Dot(ex);
const Vector3 ey_trial = guide - projection * ex;
const double ey_norm = ey_trial.Norm();
if (!std::isfinite(ey_norm) || !(ey_norm > 0.0)) {
return std::nullopt;
}
const std::array<double, 3> ey = {
ey_trial[0U] / ey_norm, ey_trial[1U] / ey_norm, ey_trial[2U] / ey_norm};
const std::array<double, 3> ez = Cross(ex, ey);
const AxisSet axes = {ex, ey, ez};
const Vector3 ey = ey_trial / ey_norm;
const Vector3 ez = ex.Cross(ey);
const AxisSet axes = {ex.Components(), ey.Components(), ez.Components()};
for (const auto& axis : axes) {
for (const double component : axis) {
if (!std::isfinite(component)) {
return std::nullopt;
}
if (!Vector3{axis}.IsFinite()) {
return std::nullopt;
}
}
return axes;