183 lines
6.4 KiB
C++
183 lines
6.4 KiB
C++
#pragma once
|
|
|
|
#include "fesa/Element/MITC4Kinematics.hpp"
|
|
#include "fesa/Material/MITC4PlaneStressMaterial.hpp"
|
|
|
|
#include <array>
|
|
#include <cmath>
|
|
#include <vector>
|
|
|
|
namespace fesa {
|
|
|
|
struct MITC4StrainTransform {
|
|
MITC4MaterialMatrix matrix{};
|
|
std::vector<Diagnostic> diagnostics;
|
|
|
|
bool ok() const {
|
|
return !hasError(diagnostics);
|
|
}
|
|
};
|
|
|
|
struct MITC4IntegrationPoint {
|
|
Real xi = 0.0;
|
|
Real eta = 0.0;
|
|
Real zeta = 0.0;
|
|
Real weight = 0.0;
|
|
};
|
|
|
|
struct MITC4MaterialIntegrationSample {
|
|
MITC4IntegrationPoint point;
|
|
MITC4IntegrationBasis basis;
|
|
MITC4StrainRows strain_rows;
|
|
MITC4MaterialMatrix local_material{};
|
|
MITC4MaterialMatrix strain_transform{};
|
|
MITC4MaterialMatrix convected_material{};
|
|
std::vector<Diagnostic> diagnostics;
|
|
|
|
bool ok() const {
|
|
return !hasError(diagnostics);
|
|
}
|
|
};
|
|
|
|
struct MITC4MaterialIntegrationData {
|
|
std::vector<MITC4MaterialIntegrationSample> samples;
|
|
std::vector<Diagnostic> diagnostics;
|
|
|
|
bool ok() const {
|
|
return !hasError(diagnostics);
|
|
}
|
|
};
|
|
|
|
inline std::array<MITC4IntegrationPoint, 8> mitc4GaussQuadrature2x2x2() {
|
|
const Real gauss = 1.0 / std::sqrt(3.0);
|
|
const std::array<Real, 2> points = {-gauss, gauss};
|
|
std::array<MITC4IntegrationPoint, 8> integration_points{};
|
|
std::size_t index = 0;
|
|
for (Real xi : points) {
|
|
for (Real eta : points) {
|
|
for (Real zeta : points) {
|
|
integration_points[index++] = {xi, eta, zeta, 1.0};
|
|
}
|
|
}
|
|
}
|
|
return integration_points;
|
|
}
|
|
|
|
inline std::array<std::array<Real, 3>, 3> mitc4TensorFromEngineeringComponent(std::size_t component) {
|
|
std::array<std::array<Real, 3>, 3> tensor{};
|
|
switch (static_cast<MITC4StrainComponent>(component)) {
|
|
case MITC4StrainComponent::Eps11:
|
|
tensor[0][0] = 1.0;
|
|
break;
|
|
case MITC4StrainComponent::Eps22:
|
|
tensor[1][1] = 1.0;
|
|
break;
|
|
case MITC4StrainComponent::Eps33:
|
|
tensor[2][2] = 1.0;
|
|
break;
|
|
case MITC4StrainComponent::Gamma23:
|
|
tensor[1][2] = 0.5;
|
|
tensor[2][1] = 0.5;
|
|
break;
|
|
case MITC4StrainComponent::Gamma13:
|
|
tensor[0][2] = 0.5;
|
|
tensor[2][0] = 0.5;
|
|
break;
|
|
case MITC4StrainComponent::Gamma12:
|
|
tensor[0][1] = 0.5;
|
|
tensor[1][0] = 0.5;
|
|
break;
|
|
}
|
|
return tensor;
|
|
}
|
|
|
|
inline MITC4StrainVector mitc4EngineeringVectorFromTensor(const std::array<std::array<Real, 3>, 3>& tensor) {
|
|
MITC4StrainVector vector{};
|
|
vector[strainComponentIndex(MITC4StrainComponent::Eps11)] = tensor[0][0];
|
|
vector[strainComponentIndex(MITC4StrainComponent::Eps22)] = tensor[1][1];
|
|
vector[strainComponentIndex(MITC4StrainComponent::Eps33)] = tensor[2][2];
|
|
vector[strainComponentIndex(MITC4StrainComponent::Gamma23)] = 2.0 * tensor[1][2];
|
|
vector[strainComponentIndex(MITC4StrainComponent::Gamma13)] = 2.0 * tensor[0][2];
|
|
vector[strainComponentIndex(MITC4StrainComponent::Gamma12)] = 2.0 * tensor[0][1];
|
|
return vector;
|
|
}
|
|
|
|
inline MITC4StrainTransform mitc4CovariantToLocalStrainTransform(const MITC4IntegrationBasis& basis,
|
|
Real tolerance = 1.0e-12) {
|
|
MITC4StrainTransform result;
|
|
result.diagnostics = basis.diagnostics;
|
|
const Real jacobian = dot(cross(basis.g1, basis.g2), basis.g3);
|
|
if (!isFinite(jacobian) || std::fabs(jacobian) <= tolerance) {
|
|
result.diagnostics.push_back(
|
|
mitc4Diagnostic("FESA-MITC4-SINGULAR-JACOBIAN", "MITC4 material transform Jacobian is near zero"));
|
|
return result;
|
|
}
|
|
if (hasError(result.diagnostics)) {
|
|
return result;
|
|
}
|
|
|
|
const std::array<Vec3, 3> contravariant = {
|
|
(1.0 / jacobian) * cross(basis.g2, basis.g3),
|
|
(1.0 / jacobian) * cross(basis.g3, basis.g1),
|
|
(1.0 / jacobian) * cross(basis.g1, basis.g2)};
|
|
const std::array<Vec3, 3> local = {basis.local.e1, basis.local.e2, basis.local.e3};
|
|
std::array<std::array<Real, 3>, 3> direction_cosines{};
|
|
for (std::size_t local_axis = 0; local_axis < 3; ++local_axis) {
|
|
for (std::size_t convected_axis = 0; convected_axis < 3; ++convected_axis) {
|
|
direction_cosines[local_axis][convected_axis] = dot(local[local_axis], contravariant[convected_axis]);
|
|
}
|
|
}
|
|
|
|
for (std::size_t column = 0; column < 6; ++column) {
|
|
const auto covariant_tensor = mitc4TensorFromEngineeringComponent(column);
|
|
std::array<std::array<Real, 3>, 3> local_tensor{};
|
|
for (std::size_t a = 0; a < 3; ++a) {
|
|
for (std::size_t b = 0; b < 3; ++b) {
|
|
for (std::size_t i = 0; i < 3; ++i) {
|
|
for (std::size_t j = 0; j < 3; ++j) {
|
|
local_tensor[a][b] += direction_cosines[a][i] * direction_cosines[b][j] * covariant_tensor[i][j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const auto local_vector = mitc4EngineeringVectorFromTensor(local_tensor);
|
|
for (std::size_t row = 0; row < 6; ++row) {
|
|
result.matrix[row][column] = local_vector[row];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
inline MITC4MaterialIntegrationData mitc4BuildMaterialIntegrationData(const MITC4Geometry& geometry,
|
|
Real elastic_modulus,
|
|
Real poisson_ratio,
|
|
Real shear_correction = 5.0 / 6.0) {
|
|
MITC4MaterialIntegrationData data;
|
|
const auto material = mitc4PlaneStressMaterialMatrix(elastic_modulus, poisson_ratio, shear_correction);
|
|
appendDiagnostics(data.diagnostics, material.diagnostics);
|
|
if (hasError(data.diagnostics)) {
|
|
return data;
|
|
}
|
|
|
|
for (const MITC4IntegrationPoint& point : mitc4GaussQuadrature2x2x2()) {
|
|
MITC4MaterialIntegrationSample sample;
|
|
sample.point = point;
|
|
sample.local_material = material.matrix;
|
|
sample.basis = computeMITC4IntegrationBasis(geometry, point.xi, point.eta, point.zeta);
|
|
appendDiagnostics(sample.diagnostics, sample.basis.diagnostics);
|
|
const auto transform = mitc4CovariantToLocalStrainTransform(sample.basis);
|
|
sample.strain_transform = transform.matrix;
|
|
appendDiagnostics(sample.diagnostics, transform.diagnostics);
|
|
sample.strain_rows = mitc4TiedCovariantStrainRows(geometry, point.xi, point.eta, point.zeta);
|
|
appendDiagnostics(sample.diagnostics, sample.strain_rows.diagnostics);
|
|
if (!hasError(sample.diagnostics)) {
|
|
sample.convected_material = mitc4TransformMaterialMatrix(sample.local_material, sample.strain_transform);
|
|
}
|
|
appendDiagnostics(data.diagnostics, sample.diagnostics);
|
|
data.samples.push_back(sample);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
} // namespace fesa
|