diff --git a/ProcessLib/Deformation/LinearBMatrix.h b/ProcessLib/Deformation/LinearBMatrix.h index f153c89485cb4c1c26f50ec00b6d48747edc46d9..e97d0e5452246a77689af7e83942279625a4d0ff 100644 --- a/ProcessLib/Deformation/LinearBMatrix.h +++ b/ProcessLib/Deformation/LinearBMatrix.h @@ -10,8 +10,11 @@ #pragma once +#include <Eigen/Core> #include <cmath> +#include "MeshLib/Elements/Elements.h" +#include "NumLib/Fem/Integration/GenericIntegrationMethod.h" #include "ProcessLib/Deformation/BMatrixPolicy.h" namespace ProcessLib @@ -81,5 +84,127 @@ BMatrixType computeBMatrix(DNDX_Type const& dNdx, return B; } + +template <int DisplacementDim, int NPOINTS, typename ShapeFunction, + typename BBarMatrixType, typename ShapeMatricesType, typename IpData> +BBarMatrixType computeDilatationalBbar( + std::vector<IpData, Eigen::aligned_allocator<IpData>> const& ip_data, + MeshLib::Element const& element, + NumLib::GenericIntegrationMethod const& integration_method, + const bool is_axially_symmetric) +{ + unsigned const n_integration_points = + integration_method.getNumberOfPoints(); + + BBarMatrixType B_bar = BBarMatrixType::Zero(3, ShapeFunction::NPOINTS); + + // Compute the element volume + double volume = 0.0; + for (unsigned ip = 0; ip < n_integration_points; ip++) + { + auto const& w = ip_data[ip].integration_weight; + volume += w; + } + + for (int i = 0; i < NPOINTS; i++) + { + auto B_bar_i = B_bar.col(i); + for (unsigned ip = 0; ip < n_integration_points; ip++) + { + auto const& N = ip_data[ip].N_u; + auto const& dNdx = ip_data[ip].dNdx_u; + + auto const dNidx = dNdx.col(i); + + auto const& w = ip_data[ip].integration_weight; + B_bar_i.template segment<DisplacementDim>(0) += dNidx * w; + + if (is_axially_symmetric) + { + auto const x_coord = + NumLib::interpolateXCoordinate<ShapeFunction, + ShapeMatricesType>(element, + N); + B_bar_i[2] += w * N(i) / x_coord; + } + } + } + + return B_bar / volume; +} + +namespace detail +{ +template <int DisplacementDim, int NPOINTS, typename BBarMatrixType, + typename BMatrixType> +void applyBbar(BBarMatrixType const& B_bar, BMatrixType& B, + const bool is_axially_symmetric) +{ + if (DisplacementDim == 3) + { + for (int i = 0; i < NPOINTS; ++i) + { + auto const B_bar_i = B_bar.col(i); + + // The following loop is based on the following facts: + // B1 (dN/dx) is the 1st element of the 1st column of B, + // B2 (dN/dy) is the 2nd element of the 2nd column of B, + // B3 (dN/dz) is the 3rd element of the 3rd column of B. + for (int k = 0; k < 3; k++) + { + // k-th column of B matrix at node i + auto B_i_k = B.col(k * NPOINTS + i); + + B_i_k.template segment<3>(0) -= + Eigen::Vector3d::Constant((B_i_k[k] - B_bar_i[k]) / 3.0); + } + } + + return; + } + + for (int i = 0; i < NPOINTS; ++i) + { + auto B_i_0 = B.col(i); + auto B_i_1 = B.col(NPOINTS + i); + + auto const B_bar_i = B_bar.col(i); + + double const b0_dil_pertubation = + is_axially_symmetric + ? (B_i_0[0] - B_bar_i[0] + B_i_0[2] - B_bar_i[2]) + : (B_i_0[0] - B_bar_i[0]); + + B_i_0.template segment<3>(0) -= + Eigen::Vector3d::Constant((b0_dil_pertubation) / 3.); + B_i_1.template segment<3>(0) -= + Eigen::Vector3d::Constant((B_i_1[1] - B_bar_i[1]) / 3.); + } +} +} // namespace detail + +/// Fills a B matrix, or a B bar matrix if required. +template <int DisplacementDim, int NPOINTS, typename BBarMatrixType, + typename BMatrixType, typename N_Type, typename DNDX_Type> +BMatrixType computeBMatrixPossiblyWithBbar(DNDX_Type const& dNdx, + N_Type const& N, + BBarMatrixType const& B_dil_bar, + const double radius, + const bool is_axially_symmetric, + const bool use_b_bar) +{ + auto B = computeBMatrix<DisplacementDim, NPOINTS, BMatrixType, N_Type, + DNDX_Type>(dNdx, N, radius, is_axially_symmetric); + if (!use_b_bar) + { + return B; + } + + detail::applyBbar<DisplacementDim, NPOINTS, BBarMatrixType, BMatrixType>( + B_dil_bar, B, is_axially_symmetric); + + return B; +} + } // namespace LinearBMatrix } // namespace ProcessLib