feat(cpp-object-oriented-modular-refactoring): step 9 - result-io-vector3
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "fesa/analysis/analysis_model.h"
|
||||
#include "fesa/build_info.h"
|
||||
#include "fesa/fem/dof_manager.h"
|
||||
#include "fesa/math/vector3.h"
|
||||
|
||||
namespace fesa {
|
||||
namespace {
|
||||
@@ -163,11 +164,6 @@ Status OutputFailure(const std::string& code, const std::string& message) {
|
||||
{{Severity::kError, code, {}, "", "", message}});
|
||||
}
|
||||
|
||||
bool IsFinite(const std::array<double, 3>& values) {
|
||||
return std::all_of(values.begin(), values.end(),
|
||||
[](const double value) { return std::isfinite(value); });
|
||||
}
|
||||
|
||||
template <std::size_t Size>
|
||||
bool IsFinite(const std::array<double, Size>& values) {
|
||||
return std::all_of(values.begin(), values.end(),
|
||||
@@ -244,26 +240,21 @@ const char* ShellSourceTypeName(const ShellSourceElementType type) {
|
||||
bool IsOrthonormalRightHanded(
|
||||
const std::array<std::array<double, 3>, 3>& frame) {
|
||||
constexpr double kTolerance = 1.0e-12;
|
||||
const auto 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];
|
||||
};
|
||||
for (const auto& axis : frame) {
|
||||
if (!IsFinite(axis) || std::abs(dot(axis, axis) - 1.0) > kTolerance) {
|
||||
const std::array<Vector3, 3> axes = {Vector3{frame[0U]}, Vector3{frame[1U]},
|
||||
Vector3{frame[2U]}};
|
||||
for (const Vector3& axis : axes) {
|
||||
if (!axis.IsFinite() || std::abs(axis.Dot(axis) - 1.0) > kTolerance) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (std::abs(dot(frame[0U], frame[1U])) > kTolerance ||
|
||||
std::abs(dot(frame[0U], frame[2U])) > kTolerance ||
|
||||
std::abs(dot(frame[1U], frame[2U])) > kTolerance) {
|
||||
if (std::abs(axes[0U].Dot(axes[1U])) > kTolerance ||
|
||||
std::abs(axes[0U].Dot(axes[2U])) > kTolerance ||
|
||||
std::abs(axes[1U].Dot(axes[2U])) > kTolerance) {
|
||||
return false;
|
||||
}
|
||||
const std::array<double, 3> cross = {
|
||||
frame[0U][1U] * frame[1U][2U] - frame[0U][2U] * frame[1U][1U],
|
||||
frame[0U][2U] * frame[1U][0U] - frame[0U][0U] * frame[1U][2U],
|
||||
frame[0U][0U] * frame[1U][1U] - frame[0U][1U] * frame[1U][0U]};
|
||||
return dot(cross, frame[2U]) > 0.0 &&
|
||||
std::abs(dot(cross, frame[2U]) - 1.0) <= kTolerance;
|
||||
const Vector3 cross = axes[0U].Cross(axes[1U]);
|
||||
const double handedness = cross.Dot(axes[2U]);
|
||||
return handedness > 0.0 && std::abs(handedness - 1.0) <= kTolerance;
|
||||
}
|
||||
|
||||
bool ComputeLocalAxes(const Domain& domain,
|
||||
@@ -275,30 +266,25 @@ bool ComputeLocalAxes(const Domain& domain,
|
||||
}
|
||||
const auto& first = domain.Nodes()[element.node_indices[0U]].coordinates;
|
||||
const auto& second = domain.Nodes()[element.node_indices[1U]].coordinates;
|
||||
const auto& guide = domain.Sections()[element.section_index].first_axis;
|
||||
const std::array<double, 3> delta = {
|
||||
second[0U] - first[0U], second[1U] - first[1U], second[2U] - first[2U]};
|
||||
const double length = std::hypot(delta[0U], delta[1U], delta[2U]);
|
||||
if (!IsFinite(first) || !IsFinite(second) || !IsFinite(guide) ||
|
||||
!IsFinite(delta) || !std::isfinite(length) || !(length > 0.0)) {
|
||||
const Vector3 first_position{first};
|
||||
const Vector3 second_position{second};
|
||||
const Vector3 guide{domain.Sections()[element.section_index].first_axis};
|
||||
const Vector3 delta = second_position - first_position;
|
||||
const double length = delta.Norm();
|
||||
if (!first_position.IsFinite() || !second_position.IsFinite() ||
|
||||
!guide.IsFinite() || !delta.IsFinite() || !std::isfinite(length) ||
|
||||
!(length > 0.0)) {
|
||||
return false;
|
||||
}
|
||||
const std::array<double, 3> x = {delta[0U] / length, delta[1U] / length,
|
||||
delta[2U] / length};
|
||||
const double projection =
|
||||
guide[0U] * x[0U] + guide[1U] * x[1U] + guide[2U] * x[2U];
|
||||
const std::array<double, 3> y_trial = {guide[0U] - projection * x[0U],
|
||||
guide[1U] - projection * x[1U],
|
||||
guide[2U] - projection * x[2U]};
|
||||
const double y_norm = std::hypot(y_trial[0U], y_trial[1U], y_trial[2U]);
|
||||
if (!IsFinite(y_trial) || !std::isfinite(y_norm) || !(y_norm > 0.0)) {
|
||||
const Vector3 x = delta / length;
|
||||
const double projection = guide.Dot(x);
|
||||
const Vector3 y_trial = guide - projection * x;
|
||||
const double y_norm = y_trial.Norm();
|
||||
if (!y_trial.IsFinite() || !std::isfinite(y_norm) || !(y_norm > 0.0)) {
|
||||
return false;
|
||||
}
|
||||
const std::array<double, 3> y = {y_trial[0U] / y_norm, y_trial[1U] / y_norm,
|
||||
y_trial[2U] / y_norm};
|
||||
const std::array<double, 3> z = {x[1U] * y[2U] - x[2U] * y[1U],
|
||||
x[2U] * y[0U] - x[0U] * y[2U],
|
||||
x[0U] * y[1U] - x[1U] * y[0U]};
|
||||
const Vector3 y = y_trial / y_norm;
|
||||
const Vector3 z = x.Cross(y);
|
||||
axes = {x[0U], x[1U], x[2U], y[0U], y[1U], y[2U], z[0U], z[1U], z[2U]};
|
||||
return IsFinite(axes);
|
||||
}
|
||||
@@ -417,7 +403,7 @@ Status ValidateShellWriterInput(const Domain& domain,
|
||||
++position) {
|
||||
if (row.stress[position].position != positions[position] ||
|
||||
row.stress[position].zeta != kZeta[position] ||
|
||||
!IsFinite(row.stress[position].components)) {
|
||||
!Vector3{row.stress[position].components}.IsFinite()) {
|
||||
return OutputFailure("invalid-result-rows",
|
||||
"Shell stress rows must preserve BOTTOM, "
|
||||
"MIDDLE, TOP identity.");
|
||||
@@ -426,7 +412,7 @@ Status ValidateShellWriterInput(const Domain& domain,
|
||||
}
|
||||
if (!std::isfinite(state.PhysicalStrainEnergy()) ||
|
||||
!IsFinite(state.Equilibrium()) ||
|
||||
!IsFinite(state.VerificationMetrics())) {
|
||||
!Vector3{state.VerificationMetrics()}.IsFinite()) {
|
||||
return OutputFailure(
|
||||
"invalid-result-rows",
|
||||
"Shell energy, equilibrium, and verification metrics must be finite.");
|
||||
@@ -493,7 +479,7 @@ Status ValidateWriterInput(const std::filesystem::path& output_path,
|
||||
node.source_id.source_label_text.empty() ||
|
||||
!IsValidUtf8(node.source_id.instance_name) ||
|
||||
!IsValidUtf8(node.source_id.source_label_text) ||
|
||||
!IsFinite(node.coordinates)) {
|
||||
!Vector3{node.coordinates}.IsFinite()) {
|
||||
return OutputFailure(
|
||||
"invalid-result-identity",
|
||||
"Every node requires finite coordinates and UTF-8 source identity.");
|
||||
|
||||
Reference in New Issue
Block a user