#pragma once #include "fesa/Math/Vector.hpp" #include "fesa/Util/Diagnostics.hpp" #include #include #include #include #include namespace fesa { using MITC4StrainVector = std::array; using MITC4MaterialMatrix = std::array, 6>; enum class MITC4StrainComponent { Eps11 = 0, Eps22 = 1, Eps33 = 2, Gamma23 = 3, Gamma13 = 4, Gamma12 = 5 }; inline std::size_t strainComponentIndex(MITC4StrainComponent component) { return static_cast(component); } inline std::array mitc4StrainComponentLabels() { return {"eps11", "eps22", "eps33", "gamma23", "gamma13", "gamma12"}; } struct MITC4MaterialMatrixEvaluation { MITC4MaterialMatrix matrix{}; std::vector diagnostics; bool ok() const { return !hasError(diagnostics); } }; inline Diagnostic mitc4MaterialDiagnostic(std::string code, std::string message) { return makeDiagnostic(Severity::Error, std::move(code), std::move(message), "mitc4", "", 0); } inline MITC4MaterialMatrixEvaluation mitc4PlaneStressMaterialMatrix(Real elastic_modulus, Real poisson_ratio, Real shear_correction = 5.0 / 6.0, Real tolerance = 1.0e-12) { MITC4MaterialMatrixEvaluation result; if (!isFinite(elastic_modulus) || elastic_modulus <= tolerance) { result.diagnostics.push_back( mitc4MaterialDiagnostic("FESA-MITC4-MATERIAL", "MITC4 elastic modulus must be positive and finite")); } if (!isFinite(poisson_ratio) || poisson_ratio <= -1.0 || poisson_ratio >= 0.5) { result.diagnostics.push_back( mitc4MaterialDiagnostic("FESA-MITC4-POISSON", "MITC4 isotropic Poisson ratio must satisfy -1 < nu < 0.5")); } if (!isFinite(shear_correction) || shear_correction <= tolerance) { result.diagnostics.push_back(mitc4MaterialDiagnostic("FESA-MITC4-SHEAR-CORRECTION", "MITC4 shear correction factor must be positive and finite")); } if (hasError(result.diagnostics)) { return result; } const Real scale = elastic_modulus / (1.0 - poisson_ratio * poisson_ratio); const Real shear_modulus = elastic_modulus / (2.0 * (1.0 + poisson_ratio)); const std::size_t eps11 = strainComponentIndex(MITC4StrainComponent::Eps11); const std::size_t eps22 = strainComponentIndex(MITC4StrainComponent::Eps22); const std::size_t gamma23 = strainComponentIndex(MITC4StrainComponent::Gamma23); const std::size_t gamma13 = strainComponentIndex(MITC4StrainComponent::Gamma13); const std::size_t gamma12 = strainComponentIndex(MITC4StrainComponent::Gamma12); result.matrix[eps11][eps11] = scale; result.matrix[eps11][eps22] = poisson_ratio * scale; result.matrix[eps22][eps11] = poisson_ratio * scale; result.matrix[eps22][eps22] = scale; result.matrix[gamma23][gamma23] = shear_correction * shear_modulus; result.matrix[gamma13][gamma13] = shear_correction * shear_modulus; result.matrix[gamma12][gamma12] = shear_modulus; return result; } inline MITC4StrainVector multiplyMITC4MaterialMatrix(const MITC4MaterialMatrix& matrix, const MITC4StrainVector& vector) { MITC4StrainVector result{}; for (std::size_t row = 0; row < 6; ++row) { for (std::size_t col = 0; col < 6; ++col) { result[row] += matrix[row][col] * vector[col]; } } return result; } inline Real dotMITC4Vector(const MITC4StrainVector& a, const MITC4StrainVector& b) { Real result = 0.0; for (std::size_t i = 0; i < 6; ++i) { result += a[i] * b[i]; } return result; } inline MITC4MaterialMatrix mitc4TransformMaterialMatrix(const MITC4MaterialMatrix& local_material, const MITC4MaterialMatrix& covariant_to_local) { MITC4MaterialMatrix result{}; for (std::size_t i = 0; i < 6; ++i) { for (std::size_t j = 0; j < 6; ++j) { Real value = 0.0; for (std::size_t a = 0; a < 6; ++a) { for (std::size_t b = 0; b < 6; ++b) { value += covariant_to_local[a][i] * local_material[a][b] * covariant_to_local[b][j]; } } result[i][j] = value; } } return result; } } // namespace fesa