Integrate Refactor solver sources and dual MSVC CMake builds
This commit is contained in:
@@ -9,6 +9,9 @@
|
||||
|
||||
#include "fesa/model/model_types.h"
|
||||
#include "math/dense_blas_internal.h"
|
||||
#include "math/finite_values.h"
|
||||
#include "math/vector3_operations.h"
|
||||
#include "elements/shell_kernel_values.h"
|
||||
|
||||
namespace fesa {
|
||||
|
||||
@@ -63,6 +66,13 @@ void Mitc4ShellDefinition::SynchronizeNodeIndices() {
|
||||
|
||||
namespace {
|
||||
|
||||
using shell_kernel_internal::FrameComponent;
|
||||
using shell_kernel_internal::LocalEngineeringComponents;
|
||||
using shell_kernel_internal::ElementIdentity;
|
||||
using math_internal::DerivativeSum;
|
||||
using math_internal::WeightedSum;
|
||||
using math_internal::IsFinite;
|
||||
|
||||
constexpr std::size_t kNodeCount = 4U;
|
||||
constexpr std::size_t kPhysicalDofsPerNode = 5U;
|
||||
constexpr std::size_t kGlobalDofsPerNode = 6U;
|
||||
@@ -71,24 +81,6 @@ constexpr std::size_t kGlobalDofCount = 24U;
|
||||
constexpr double kShearCorrection = 5.0 / 6.0;
|
||||
constexpr double kFrameTolerance = 1.0e-12;
|
||||
|
||||
Vector3 WeightedSum(const std::array<double, kNodeCount>& weights,
|
||||
const std::array<Vector3, kNodeCount>& values) {
|
||||
Vector3 result{};
|
||||
for (std::size_t node = 0U; node < kNodeCount; ++node) {
|
||||
result = result + weights[node] * values[node];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3 DerivativeSum(const std::array<double, kNodeCount>& derivatives,
|
||||
const std::array<Vector3, kNodeCount>& values) {
|
||||
std::array<Vector3, kNodeCount> relative{};
|
||||
for (std::size_t node = 0U; node < kNodeCount; ++node) {
|
||||
relative[node] = values[node] - values[0];
|
||||
}
|
||||
return WeightedSum(derivatives, relative);
|
||||
}
|
||||
|
||||
bool SameCoordinates(const Vector3& left, const Vector3& right) {
|
||||
return left == right;
|
||||
}
|
||||
@@ -129,20 +121,6 @@ std::array<Vector3, kNodeCount> NodalTangentsB(
|
||||
return tangents;
|
||||
}
|
||||
|
||||
std::string ElementIdentity(const std::array<const Node*, kNodeCount>& 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;
|
||||
}
|
||||
|
||||
Result<Mitc4Shell> ModelFailure(std::string code,
|
||||
const SourceLocation& location,
|
||||
const std::string& identity,
|
||||
@@ -169,58 +147,36 @@ std::array<std::array<double, 3>, 3> CovariantStrainColumn(
|
||||
return strain;
|
||||
}
|
||||
|
||||
/// @brief Reconstructs Cartesian strain in the approved reciprocal-basis
|
||||
/// reduction order.
|
||||
/// @brief Solves C^T E C = E_cov for the actual strain tensor.
|
||||
std::array<std::array<double, 3>, 3> ReconstructCartesianStrain(
|
||||
const std::array<std::array<double, 3>, 3>& covariant_strain,
|
||||
const std::array<Vector3, 3>& reciprocal) {
|
||||
const dense_blas_internal::DenseFactor& factor) {
|
||||
Matrix rhs{3U, 3U};
|
||||
for (std::size_t i = 0; i < 3U; ++i)
|
||||
for (std::size_t j = 0; j < 3U; ++j) rhs(i, j) = covariant_strain[i][j];
|
||||
const auto left = factor.Solve(rhs, true);
|
||||
if (!left.HasValue())
|
||||
throw std::invalid_argument{"MITC4 Cartesian strain is nonfinite."};
|
||||
const auto solved = factor.SolveRight(left.Value());
|
||||
if (!solved.HasValue())
|
||||
throw std::invalid_argument{"MITC4 Cartesian strain is nonfinite."};
|
||||
std::array<std::array<double, 3>, 3> tensor{};
|
||||
for (std::size_t row = 0U; row < 3U; ++row) {
|
||||
for (std::size_t column = 0U; column < 3U; ++column) {
|
||||
for (std::size_t first = 0U; first < 3U; ++first) {
|
||||
for (std::size_t second = 0U; second < 3U; ++second) {
|
||||
tensor[row][column] += covariant_strain[first][second] *
|
||||
reciprocal[first][row] *
|
||||
reciprocal[second][column];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (std::size_t i = 0; i < 3U; ++i)
|
||||
for (std::size_t j = 0; j < 3U; ++j) tensor[i][j] = solved.Value()(i, j);
|
||||
return tensor;
|
||||
}
|
||||
|
||||
double FrameComponent(const Vector3& left,
|
||||
const std::array<std::array<double, 3>, 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 tensor strain into signed local engineering components.
|
||||
std::array<double, 5> LocalEngineeringComponents(
|
||||
const std::array<std::array<double, 3>, 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)};
|
||||
/// @brief Packs covariant columns without constructing reciprocal vectors.
|
||||
Matrix CovariantMatrix(const std::array<Vector3, 3>& covariant) {
|
||||
Matrix coefficients{3U, 3U};
|
||||
for (std::size_t i = 0; i < 3U; ++i)
|
||||
for (std::size_t j = 0; j < 3U; ++j) coefficients(i, j) = covariant[j][i];
|
||||
return coefficients;
|
||||
}
|
||||
|
||||
Matrix ScaledMatrix(const Matrix& source, double factor) {
|
||||
Matrix result{source.Rows(), source.Columns()};
|
||||
for (std::size_t row = 0U; row < source.Rows(); ++row) {
|
||||
for (std::size_t column = 0U; column < source.Columns(); ++column) {
|
||||
result(row, column) = factor * source(row, column);
|
||||
}
|
||||
}
|
||||
Matrix result{source};
|
||||
result.Scale(factor);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -241,26 +197,6 @@ Matrix Congruence(const Matrix& local, const Matrix& transformation) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsFinite(const Matrix& matrix) {
|
||||
for (std::size_t row = 0U; row < matrix.Rows(); ++row) {
|
||||
for (std::size_t column = 0U; column < matrix.Columns(); ++column) {
|
||||
if (!std::isfinite(matrix(row, column))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsFinite(const Vector& vector) {
|
||||
for (std::size_t index = 0U; index < vector.Size(); ++index) {
|
||||
if (!std::isfinite(vector[index])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Result<Mitc4Stiffness> StiffnessFailure(const SourceLocation& location,
|
||||
const std::string& identity,
|
||||
std::string message) {
|
||||
@@ -1092,12 +1028,25 @@ bool Mitc4Shell::EvaluateGeometry(double xi, double eta, double zeta,
|
||||
return false;
|
||||
}
|
||||
|
||||
result.reciprocal[0] =
|
||||
(1.0 / result.jacobian) * result.covariant[1].Cross(result.covariant[2]);
|
||||
result.reciprocal[1] =
|
||||
(1.0 / result.jacobian) * result.covariant[2].Cross(result.covariant[0]);
|
||||
result.reciprocal[2] =
|
||||
(1.0 / result.jacobian) * result.covariant[0].Cross(result.covariant[1]);
|
||||
if (!std::isfinite(1.0 / result.jacobian) ||
|
||||
!result.covariant[1].Cross(result.covariant[2]).IsFinite() ||
|
||||
!result.covariant[2].Cross(result.covariant[0]).IsFinite() ||
|
||||
!result.covariant[0].Cross(result.covariant[1]).IsFinite()) return false;
|
||||
// Preserve the reciprocal finiteness gate, streaming each action directly
|
||||
// into validation rather than retaining a reciprocal-basis matrix.
|
||||
try {
|
||||
const auto factor = dense_blas_internal::DenseFactor::Lu(
|
||||
CovariantMatrix(result.covariant));
|
||||
if (!factor.HasValue()) return false;
|
||||
Matrix rhs{3U, 1U};
|
||||
for (std::size_t axis = 0; axis < 3U; ++axis) {
|
||||
if (axis != 0U) rhs(axis - 1U, 0U) = 0.0;
|
||||
rhs(axis, 0U) = 1.0;
|
||||
if (!factor.Value().Solve(rhs, true).HasValue()) return false;
|
||||
}
|
||||
} catch (const std::exception&) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Vector3 area = midsurface_xi.Cross(midsurface_eta);
|
||||
const double director_norm = director_value.Norm();
|
||||
@@ -1120,8 +1069,7 @@ bool Mitc4Shell::EvaluateGeometry(double xi, double eta, double zeta,
|
||||
const Vector3 e2 = e3.Cross(e1);
|
||||
result.frame.e1 = e1.Components();
|
||||
result.frame.e2 = e2.Components();
|
||||
return result.reciprocal[0].IsFinite() && result.reciprocal[1].IsFinite() &&
|
||||
result.reciprocal[2].IsFinite() && e2.IsFinite();
|
||||
return e2.IsFinite();
|
||||
}
|
||||
|
||||
std::array<std::array<Vector3, 3>, 20> Mitc4Shell::BasisDerivatives(
|
||||
@@ -1165,6 +1113,11 @@ Matrix Mitc4Shell::StrainDisplacement(double xi, double eta, double zeta,
|
||||
throw std::invalid_argument{
|
||||
"MITC4 strain geometry is invalid at the requested point."};
|
||||
}
|
||||
const auto factor = dense_blas_internal::DenseFactor::Lu(
|
||||
CovariantMatrix(geometry.covariant));
|
||||
if (!factor.HasValue())
|
||||
throw std::invalid_argument{
|
||||
"MITC4 strain geometry is invalid at the requested point."};
|
||||
const auto derivatives = BasisDerivatives(xi, eta, zeta);
|
||||
const Mitc4TyingWeights weights = TyingWeights(xi, eta);
|
||||
Matrix result{5U, kPhysicalDofCount};
|
||||
@@ -1180,7 +1133,7 @@ Matrix Mitc4Shell::StrainDisplacement(double xi, double eta, double zeta,
|
||||
covariant[2U][1U] = covariant[1U][2U];
|
||||
}
|
||||
const auto engineering = LocalEngineeringComponents(
|
||||
ReconstructCartesianStrain(covariant, geometry.reciprocal),
|
||||
ReconstructCartesianStrain(covariant, factor.Value()),
|
||||
geometry.frame);
|
||||
for (std::size_t component = 0U; component < engineering.size();
|
||||
++component) {
|
||||
|
||||
Reference in New Issue
Block a user