#ifndef FESA_ELEMENTS_SHELL_KERNEL_VALUES_H_ #define FESA_ELEMENTS_SHELL_KERNEL_VALUES_H_ #include #include #include #include #include "fesa/elements/mitc4_shell.h" #include "fesa/math/matrix.h" #include "fesa/math/vector3.h" #include "fesa/model/model_types.h" namespace fesa::shell_kernel_internal { /// @brief Constructs the shared model-category shell-kernel failure envelope. template Result Failure(const std::string& code, const SourceLocation& location, const std::string& identity, std::string message) { return Result::Failure(Status::Failure( FailureCategory::kModel, {{Severity::kError, code, location, "*ELEMENT", identity, std::move(message)}})); } /// @brief Preserves raw source labels and the existing null-skip diagnostic identity. inline std::string ElementIdentity(const std::array& nodes) { std::string identity; for (const Node* node : nodes) { if (node == nullptr) { continue; } if (!identity.empty()) { identity += "-"; } identity += node->source_id.source_label_text; } return identity; } /// @brief Copies the initial semantic frame into its three ordered columns. inline Matrix FrameMatrix(const ShellNodeInitialFrame& frame) { Matrix result{3U, 3U}; for (std::size_t row = 0U; row < 3U; ++row) { result(row, 0U) = frame.tangent_a[row]; result(row, 1U) = frame.tangent_b[row]; result(row, 2U) = frame.director[row]; } return result; } /// @brief Contracts one ordinary tensor component in the original row/column order. inline double FrameComponent( const Vector3& left, const std::array, 3>& tensor, const Vector3& right) { double value = 0.0; for (std::size_t row = 0U; row < 3U; ++row) { for (std::size_t column = 0U; column < 3U; ++column) { value += left[row] * tensor[row][column] * right[column]; } } return value; } /// @brief Projects fixed-reference tensor strain to the five engineering components. inline std::array LocalEngineeringComponents( const std::array, 3>& tensor, const Mitc4LocalFrame& frame) { const Vector3 e1{frame.e1}; const Vector3 e2{frame.e2}; const Vector3 e3{frame.e3}; return {FrameComponent(e1, tensor, e1), FrameComponent(e2, tensor, e2), 2.0 * FrameComponent(e1, tensor, e2), 2.0 * FrameComponent(e1, tensor, e3), 2.0 * FrameComponent(e2, tensor, e3)}; } } // namespace fesa::shell_kernel_internal #endif // FESA_ELEMENTS_SHELL_KERNEL_VALUES_H_