From 7741025895f5a8796bfe35e3a72ae5ed99287d43 Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Mon, 20 Apr 2026 11:37:23 +0000 Subject: [PATCH 01/17] Intermediate working version --- ...ction_contact_beam_to_solid_conditions.cpp | 3 + ...nteraction_contact_beam_to_solid_input.hpp | 4 +- ...nteraction_contact_beam_to_solid_utils.cpp | 22 ++++ ..._to_solid_volume_meshtying_pair_mortar.cpp | 29 ++++- ..._volume_meshtying_pair_mortar_rotation.cpp | 17 ++- ...C_fem_general_utils_fem_shapefunctions.hpp | 107 ++++++++++++++++++ .../4C_geometry_pair_element.hpp | 45 +++++++- ..._geometry_pair_element_shape_functions.hpp | 52 +++++++++ 8 files changed, 273 insertions(+), 6 deletions(-) diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp index 4548fb2f46e..4dafb07eab8 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp @@ -360,6 +360,9 @@ BeamInteraction::create_beam_to_solid_volume_pair_mortar(const Core::FE::CellTyp case BeamToSolid::BeamToSolidMortarShapefunctions::line4: return create_beam_to_solid_volume_pair_mortar(shape, other_mortar_shape_function...); + case BeamToSolid::BeamToSolidMortarShapefunctions::dual_hermite: + return create_beam_to_solid_volume_pair_mortar(shape, other_mortar_shape_function...); default: FOUR_C_THROW("Wrong mortar shape function."); return nullptr; diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_input.hpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_input.hpp index 7ec009dd727..503b4d5b7a9 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_input.hpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_input.hpp @@ -153,7 +153,9 @@ namespace BeamToSolid //! Quadratic. line3, //! Cubic. - line4 + line4, + //! dual hermite + dual_hermite, }; /** diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp index dd286be8deb..9029dd3dbca 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp @@ -130,6 +130,10 @@ BeamInteraction::mortar_shape_functions_to_number_of_lagrange_values( const int n_fourier_modes = beam_to_volume_parameters->get_number_of_fourier_modes(); return (n_fourier_modes * 2 + 1); } + else if (shape_function == BeamToSolid::BeamToSolidMortarShapefunctions::dual_hermite) + { + return 2; + } else { return 1; @@ -164,6 +168,12 @@ BeamInteraction::mortar_shape_functions_to_number_of_lagrange_values( const unsigned int n_lambda_element = 2 * n_dim * number_of_values_per_entry; return {n_lambda_node, n_lambda_element}; } + case BeamToSolid::BeamToSolidMortarShapefunctions::dual_hermite: + { + const unsigned int n_lambda_node = n_dim * number_of_values_per_entry; + const unsigned int n_lambda_element = 0; + return {n_lambda_node, n_lambda_element}; + } default: FOUR_C_THROW("Mortar shape function not implemented!"); } @@ -920,50 +930,62 @@ namespace BeamInteraction initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex8, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex8, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex8, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex8, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex20, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex20, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex20, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex20, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex27, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex27, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex27, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_hex27, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet4, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet4, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet4, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet4, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet10, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet10, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet10, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_tet10, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs27, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs27, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs27, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs27, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad4, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad4, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad4, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad4, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad8, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad8, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad8, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad8, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad9, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad9, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad9, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_quad9, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri3, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri3, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri3, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri3, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri6, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri6, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri6, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_tri6, t_hermite_dual); initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs9, t_line2); initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs9, t_line3); initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs9, t_line4); + initialize_template_assemble_local_mortar_contributions(t_hermite, t_nurbs9, t_hermite_dual); } // namespace BeamInteraction FOUR_C_NAMESPACE_CLOSE diff --git a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp index 15206675b22..a1099a5e52d 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp @@ -113,6 +113,13 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortar element_data_lambda; + + if constexpr (std::is_same_v) + { + element_data_lambda.shape_function_data_.ref_length_ = + this->ele1pos_.shape_function_data_.ref_length_; + } + Core::LinAlg::Matrix<3, 1, scalar_type> X; Core::LinAlg::Matrix<3, 1, scalar_type> r; Core::LinAlg::Matrix<3, 1, scalar_type> u; @@ -330,8 +337,19 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortar: N_mortar.clear(); N_beam.clear(); N_solid.clear(); - GeometryPair::EvaluateShapeFunction::evaluate( - N_mortar, projected_gauss_point.get_eta()); + if constexpr (std::is_same_v) + { + GeometryPair::ShapeFunctionData mortar_shape_function_data; + mortar_shape_function_data.ref_length_ = this->ele1pos_.shape_function_data_.ref_length_; + + GeometryPair::EvaluateShapeFunction::evaluate( + N_mortar, projected_gauss_point.get_eta(), mortar_shape_function_data); + } + else + { + GeometryPair::EvaluateShapeFunction::evaluate( + N_mortar, projected_gauss_point.get_eta()); + } GeometryPair::EvaluateShapeFunction::evaluate( N_beam, projected_gauss_point.get_eta(), this->ele1pos_.shape_function_data_); GeometryPair::EvaluateShapeFunction::evaluate( @@ -425,6 +443,13 @@ namespace BeamInteraction template class BeamToSolidVolumeMeshtyingPairMortar; template class BeamToSolidVolumeMeshtyingPairMortar; template class BeamToSolidVolumeMeshtyingPairMortar; + + template class BeamToSolidVolumeMeshtyingPairMortar; + template class BeamToSolidVolumeMeshtyingPairMortar; + template class BeamToSolidVolumeMeshtyingPairMortar; + template class BeamToSolidVolumeMeshtyingPairMortar; + template class BeamToSolidVolumeMeshtyingPairMortar; + template class BeamToSolidVolumeMeshtyingPairMortar; } // namespace BeamInteraction FOUR_C_NAMESPACE_CLOSE diff --git a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp index d5c6267d4b0..6717a82bb6a 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp @@ -259,8 +259,10 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation mortar_shape_function_data; + mortar_shape_function_data.ref_length_ = this->ele1pos_.shape_function_data_.ref_length_; GeometryPair::EvaluateShapeFunction::evaluate( - lambda_shape_functions, projected_gauss_point.get_eta()); + lambda_shape_functions, projected_gauss_point.get_eta(), mortar_shape_function_data); for (unsigned int i_node = 0; i_node < MortarRot::n_nodes_; i_node++) for (unsigned int i_dim = 0; i_dim < 3; i_dim++) lambda_shape_functions_full(i_dim, 3 * i_node + i_dim) = lambda_shape_functions(i_node); @@ -553,8 +555,10 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation mortar_shape_function_data; + mortar_shape_function_data.ref_length_ = this->ele1pos_.shape_function_data_.ref_length_; GeometryPair::EvaluateShapeFunction::evaluate( - lambda_shape_functions, projected_gauss_point.get_eta()); + lambda_shape_functions, projected_gauss_point.get_eta(), mortar_shape_function_data); for (unsigned int i_node = 0; i_node < MortarRot::n_nodes_; i_node++) for (unsigned int i_dim = 0; i_dim < 3; i_dim++) lambda_shape_functions_full(i_dim, 3 * i_node + i_dim) = lambda_shape_functions(i_node); @@ -651,14 +655,23 @@ namespace BeamInteraction initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line2, t_line2); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line2, t_line3); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line2, t_line4); + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line2, t_hermite_dual); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line3, t_line2); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line3, t_line3); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line3, t_line4); + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line3, t_hermite_dual); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line4, t_line2); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line4, t_line3); initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line4, t_line4); + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_line4, t_hermite_dual); + + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_hermite_dual, t_line2); + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_hermite_dual, t_line3); + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation(t_hermite_dual, t_line4); + initialize_template_beam_to_solid_volume_meshtying_pair_mortar_rotation( + t_hermite_dual, t_hermite_dual); } // namespace BeamInteraction FOUR_C_NAMESPACE_CLOSE diff --git a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp index 4ef58f41d7f..a326edde38b 100644 --- a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp +++ b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp @@ -3024,6 +3024,113 @@ namespace Core::FE return; } + /*! + \brief Fill a matrix of type VectorType with 1D dual hermite shape functions + */ + template + void shape_function_dual_hermite_1d( + VectorType& funct, ///< to be filled with dual shape function values + const NumberType1& xi, ///< xi coordinate + const NumberType2& L, ///< length of element + const Core::FE::CellType& distype ///< distinguish between DiscretizationType + ) + { + static_assert(!std::is_integral_v); + + switch (distype) + { + case Core::FE::CellType::line2: + { + const NumberType1 xi2 = xi * xi; + const NumberType1 xi3 = xi2 * xi; + + funct(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; + + funct(1) = (105.0 * xi3 - 45.0 / 2.0 * xi2 - 60.0 * xi + 15.0 / 2.0) / L; + + funct(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; + + funct(3) = (105.0 * xi3 + 45.0 / 2.0 * xi2 - 60.0 * xi - 15.0 / 2.0) / L; + break; + } + default: + FOUR_C_THROW("distype unknown\n"); + break; + } + + return; + } + + /*! + \brief Fill a matrix of type MatrixType with 1D dual hermite shape function first derivatives + */ + template + void shape_function_dual_hermite_1d_deriv1( + MatrixType& + deriv1, ///< to be filled with dual hermite shape function first derivative values + const NumberType1& xi, ///< xi coordinate + const NumberType2& L, ///< length of element + const Core::FE::CellType& distype) + { + static_assert(!std::is_integral_v); + + switch (distype) + { + case Core::FE::CellType::line2: + { + const NumberType1 xi2 = xi * xi; + + deriv1(0, 0) = -105.0 / 4.0 * xi2 + 15.0 / 2.0 * xi + 15.0 / 4.0; + + deriv1(0, 1) = (315.0 * xi2 - 45.0 * xi - 60.0) / L; + + deriv1(0, 2) = 105.0 / 4.0 * xi2 + 15.0 / 2.0 * xi - 15.0 / 4.0; + + deriv1(0, 3) = (315.0 * xi2 + 45.0 * xi - 60.0) / L; + break; + } + default: + FOUR_C_THROW("distype unknown\n"); + break; + } + + return; + } + + /*! + \brief Fill a matrix of type MatrixType with 1D dual hermite shape function second derivatives + */ + template + void shape_function_dual_hermite_1d_deriv2( + MatrixType& + deriv2, ///< to be filled with dual hermite shape function second derivative values + const NumberType1& xi, ///< xi coordinate + const NumberType2& L, ///< length of element + const Core::FE::CellType& distype) + { + static_assert(!std::is_integral_v); + + switch (distype) + { + case Core::FE::CellType::line2: + { + deriv2(0, 0) = -105.0 / 2.0 * xi + 15.0 / 2.0; + + deriv2(0, 1) = (630.0 * xi - 45.0) / L; + + deriv2(0, 2) = 105.0 / 2.0 * xi + 15.0 / 2.0; + + deriv2(0, 3) = (630.0 * xi + 45.0) / L; + break; + } + default: + FOUR_C_THROW("distype unknown\n"); + break; + } + + return; + } + /*! \brief Fill a matrix of type VectorType with 1D hermite shape functions of order five */ diff --git a/src/geometry_pair/4C_geometry_pair_element.hpp b/src/geometry_pair/4C_geometry_pair_element.hpp index 878a6fa22a0..af9fbdc00f4 100644 --- a/src/geometry_pair/4C_geometry_pair_element.hpp +++ b/src/geometry_pair/4C_geometry_pair_element.hpp @@ -46,6 +46,17 @@ namespace GeometryPair wedge }; + /** + * \brief type of basis used for the shape functions. + */ + enum class BasisType + { + //! standard + standard, + //! dual + dual, + }; + /** * \brief This structure "converts" the discretization type to a geometry type. * @@ -154,7 +165,7 @@ namespace GeometryPair * of the element */ template + unsigned int spatial_dim = 3, BasisType type = BasisType::standard> class ElementDiscretizationBase { public: @@ -176,6 +187,9 @@ namespace GeometryPair //! Number of unknowns for this element. static constexpr unsigned int n_dof_ = spatial_dim_ * n_val_ * n_nodes_; + //! Basis type used for shape function. + static constexpr BasisType type_ = type; + //! Geometry type of the element. static constexpr GeometryPair::DiscretizationTypeGeometry geometry_type_ = ElementDiscretizationToGeometryType::geometry_type_; @@ -188,6 +202,8 @@ namespace GeometryPair //! 1D elements using t_hermite = ElementDiscretizationBase; + using t_hermite_dual = + ElementDiscretizationBase; using t_line2 = ElementDiscretizationBase; using t_line2_scalar = ElementDiscretizationBase; using t_line3 = ElementDiscretizationBase; @@ -369,6 +385,15 @@ namespace GeometryPair double ref_length_; }; + /** + * \brief Specialization for hermite elements which need a reference length + */ + template <> + struct ShapeFunctionData + { + double ref_length_; + }; + /** * \brief Specialization for nurbs9 surface elements which require an additional factor to specify * outward pointing normals @@ -602,6 +627,24 @@ namespace GeometryPair } }; + /** + * \brief Specialization for dual Hermite elements + */ + template <> + struct PrintElementData + { + template + static void print( + const ElementData& element_data, std::ostream& out) + { + constexpr auto max_precision{std::numeric_limits::digits10 + 1}; + out << std::setprecision(max_precision); + out << "\nElement reference length: " << element_data.shape_function_data_.ref_length_; + out << "\nElement state vector: "; + element_data.element_position_.print(out); + } + }; + /** * \brief Specialization for elements with averaged nodal normals */ diff --git a/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp b/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp index c7d263dc6b9..272fe634ded 100644 --- a/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp +++ b/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp @@ -185,6 +185,58 @@ namespace GeometryPair } }; + /** + * \brief Specialization for Hermite elements + */ + template <> + struct EvaluateShapeFunction + { + /** + * \brief Evaluate the shape functions of the element at xi. + * + * @param N (out) shape functions. + * @param xi (in) Parameter coordinate on the element. + * @param shape_function_data (in) Shape function data container. + */ + template + static void evaluate( + V& N, const T& xi, const ShapeFunctionData& shape_function_data) + { + Core::FE::shape_function_dual_hermite_1d( + N, xi, shape_function_data.ref_length_, t_hermite::discretization_); + } + + /** + * \brief Evaluate the derivatives of the shape functions of the element at xi. + * + * @param dN (out) derivatives of shape functions. + * @param xi (in) Parameter coordinate on the element. + * @param shape_function_data (in) Shape function data container. + */ + template + static void evaluate_deriv1( + V& dN, const T& xi, const ShapeFunctionData& shape_function_data) + { + Core::FE::shape_function_dual_hermite_1d_deriv1( + dN, xi, shape_function_data.ref_length_, t_hermite::discretization_); + } + + /** + * \brief Evaluate the 2nd derivatives of the shape functions of the element at xi. + * + * @param ddN (out) 2nd derivatives of shape functions. + * @param xi (in) Parameter coordinate on the element. + * @param shape_function_data (in) Shape function data container. + */ + template + static void evaluate_deriv2( + V& ddN, const T& xi, const ShapeFunctionData& shape_function_data) + { + Core::FE::shape_function_dual_hermite_1d_deriv2( + ddN, xi, shape_function_data.ref_length_, t_hermite::discretization_); + } + }; + /** * \brief Specialization for NURBS elements */ From dd4ac73d2050004a1f2e7460bef70fdea051854a Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Fri, 24 Apr 2026 09:12:36 +0000 Subject: [PATCH 02/17] Add tests for the shapefunctions --- ..._general_utils_fem_shapefunctions_test.cpp | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp b/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp index d8d1da5f79d..e30fcc97c1b 100644 --- a/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp +++ b/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp @@ -35,4 +35,62 @@ namespace for (std::size_t i = 0; i < ddN_ref.size(); ++i) EXPECT_NEAR(ddN(i), ddN_ref[i], 1e-10); } + TEST(ElementShapeFunctionsTest, TestDualHermiteLine2) + { + const double r = 0.123456789; + const double L = 1.0; + + Core::LinAlg::Matrix<4, 1> Phi(Core::LinAlg::Initialization::zero); + Core::FE::shape_function_dual_hermite_1d(Phi, r, L, Core::FE::CellType::line2); + + std::vector Phi_ref = { + -0.24634578918994066, -0.05276684284142519, -1.1393423701836305, -14.366895799082851}; + + for (std::size_t i = 0; i < Phi_ref.size(); ++i) EXPECT_NEAR(Phi(i), Phi_ref[i], 1e-10); + + Core::LinAlg::Matrix<1, 4> dPhi(Core::LinAlg::Initialization::zero); + Core::FE::shape_function_dual_hermite_1d_deriv1(dPhi, r, L, Core::FE::CellType::line2); + + std::vector dPhi_ref = { + 4.275834475307499, -60.75445819868999, -2.423982640307499, -49.64334718868999}; + + for (std::size_t i = 0; i < dPhi_ref.size(); ++i) EXPECT_NEAR(dPhi(i), dPhi_ref[i], 1e-10); + + Core::LinAlg::Matrix<1, 4> ddPhi(Core::LinAlg::Initialization::zero); + Core::FE::shape_function_dual_hermite_1d_deriv2(ddPhi, r, L, Core::FE::CellType::line2); + + std::vector ddPhi_ref = {1.0185185775, 32.77777707, 13.9814814225, 122.77777707}; + + for (std::size_t i = 0; i < ddPhi_ref.size(); ++i) EXPECT_NEAR(ddPhi(i), ddPhi_ref[i], 1e-10); + } + + TEST(ElementShapeFunctionsTest, TestDualHermiteLine2Length03) + { + const double r = 0.123456789; + const double L = 0.3; + + Core::LinAlg::Matrix<4, 1> Phi(Core::LinAlg::Initialization::zero); + Core::FE::shape_function_dual_hermite_1d(Phi, r, L, Core::FE::CellType::line2); + + std::vector Phi_ref = { + -0.24634578918994066, -0.17588947613808398, -1.1393423701836305, -47.8896526636095}; + + for (std::size_t i = 0; i < Phi_ref.size(); ++i) EXPECT_NEAR(Phi(i), Phi_ref[i], 1e-10); + + Core::LinAlg::Matrix<1, 4> dPhi(Core::LinAlg::Initialization::zero); + Core::FE::shape_function_dual_hermite_1d_deriv1(dPhi, r, L, Core::FE::CellType::line2); + + std::vector dPhi_ref = { + 4.275834475307499, -202.51486066229998, -2.423982640307499, -165.47782396229996}; + + for (std::size_t i = 0; i < dPhi_ref.size(); ++i) EXPECT_NEAR(dPhi(i), dPhi_ref[i], 1e-10); + + Core::LinAlg::Matrix<1, 4> ddPhi(Core::LinAlg::Initialization::zero); + Core::FE::shape_function_dual_hermite_1d_deriv2(ddPhi, r, L, Core::FE::CellType::line2); + + std::vector ddPhi_ref = {1.0185185775, 109.2592569, 13.9814814225, 409.2592569}; + + for (std::size_t i = 0; i < ddPhi_ref.size(); ++i) EXPECT_NEAR(ddPhi(i), ddPhi_ref[i], 1e-10); + } + } // namespace From b13534204c6a22ad965405de8bf40195e387b473 Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Thu, 7 May 2026 08:50:23 +0000 Subject: [PATCH 03/17] Correct shape functions --- .../general/utils/4C_fem_general_utils_fem_shapefunctions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp index a326edde38b..89beb233c62 100644 --- a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp +++ b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp @@ -3046,11 +3046,11 @@ namespace Core::FE funct(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; - funct(1) = (105.0 * xi3 - 45.0 / 2.0 * xi2 - 60.0 * xi + 15.0 / 2.0) / L; + funct(1) = (35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 - 10.0 * xi + 5.0 / 4.0) / L; funct(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; - funct(3) = (105.0 * xi3 + 45.0 / 2.0 * xi2 - 60.0 * xi - 15.0 / 2.0) / L; + funct(3) = (-35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 + 10.0 * xi + 5.0 / 4.0) / L; break; } default: From 9cb3062e33033b76c80e3008d9d794f46d063955 Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Sat, 30 May 2026 14:38:29 +0000 Subject: [PATCH 04/17] Move shapefunction implementation to header --- ...ction_contact_beam_to_solid_conditions.cpp | 5 +- ...id_mortar_shape_functions_dual_hermite.hpp | 115 ++++++++++++++++++ ...nteraction_contact_beam_to_solid_utils.cpp | 1 + ..._to_solid_volume_meshtying_pair_mortar.cpp | 25 ++-- ..._volume_meshtying_pair_mortar_rotation.cpp | 13 +- ...C_fem_general_utils_fem_shapefunctions.hpp | 107 ---------------- ..._general_utils_fem_shapefunctions_test.cpp | 50 +++----- .../4C_geometry_pair_element.hpp | 45 +------ ..._geometry_pair_element_shape_functions.hpp | 52 -------- 9 files changed, 152 insertions(+), 261 deletions(-) create mode 100644 src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp index 4dafb07eab8..e61f87ffa8f 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp @@ -13,6 +13,7 @@ #include "4C_beaminteraction_contact_beam_to_solid_input.hpp" #include "4C_beaminteraction_contact_beam_to_solid_mortar_manager.hpp" #include "4C_beaminteraction_contact_beam_to_solid_mortar_manager_contact.hpp" +#include "4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp" #include "4C_beaminteraction_contact_beam_to_solid_surface_meshtying_pair_gauss_point.hpp" #include "4C_beaminteraction_contact_beam_to_solid_surface_meshtying_pair_gauss_point_FAD.hpp" #include "4C_beaminteraction_contact_beam_to_solid_surface_meshtying_pair_mortar.hpp" @@ -362,7 +363,7 @@ BeamInteraction::create_beam_to_solid_volume_pair_mortar(const Core::FE::CellTyp GeometryPair::t_line4>(shape, other_mortar_shape_function...); case BeamToSolid::BeamToSolidMortarShapefunctions::dual_hermite: return create_beam_to_solid_volume_pair_mortar(shape, other_mortar_shape_function...); + BeamInteraction::t_hermite_dual>(shape, other_mortar_shape_function...); default: FOUR_C_THROW("Wrong mortar shape function."); return nullptr; @@ -413,7 +414,7 @@ BeamInteraction::BeamToSolidConditionVolumeMeshtying::create_contact_pair_intern } else { - // Create the rotational mortart pairs. + // Create the rotational mortar pairs. return create_beam_to_solid_volume_pair_mortar( shape, mortar_shape_function, mortar_shape_function_rotation); } diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp new file mode 100644 index 00000000000..bac5d899fb2 --- /dev/null +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp @@ -0,0 +1,115 @@ +// This file is part of 4C multiphysics licensed under the +// GNU Lesser General Public License v3.0 or later. +// +// See the LICENSE.md file in the top-level for license information. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef FOUR_C_BEAMINTERACTION_CONTACT_BEAM_TO_SOLID_MORTAR_SHAPE_FUNCTIONS_DUAL_HERMITE_HPP +#define FOUR_C_BEAMINTERACTION_CONTACT_BEAM_TO_SOLID_MORTAR_SHAPE_FUNCTIONS_DUAL_HERMITE_HPP + +#include "4C_config.hpp" + +#include "4C_fem_general_utils_fem_shapefunctions.hpp" +#include "4C_geometry_pair_element.hpp" +#include "4C_geometry_pair_element_shape_functions.hpp" + +FOUR_C_NAMESPACE_OPEN + +namespace BeamInteraction +{ + struct t_hermite_dual + : public GeometryPair::ElementDiscretizationBase + { + }; +} // namespace BeamInteraction + +namespace GeometryPair +{ + template <> + struct ShapeFunctionData + { + double ref_length_; + }; + + template <> + struct EvaluateShapeFunction + { + template + static void evaluate(V& N, const T& xi, + const ShapeFunctionData& shape_function_data) + { + switch (BeamInteraction::t_hermite_dual::discretization_) + { + case Core::FE::CellType::line2: + { + const T xi2 = xi * xi; + const T xi3 = xi2 * xi; + + N(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; + + N(1) = (35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 - 10.0 * xi + 5.0 / 4.0) / + (shape_function_data.ref_length_); + + N(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; + + N(3) = (-35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 + 10.0 * xi + 5.0 / 4.0) / + (shape_function_data.ref_length_); + break; + } + default: + FOUR_C_THROW("distype unknown\n"); + break; + } + + return; + } + }; + + template <> + struct PrintElementData + { + template + static void print(const ElementData& element_data, + std::ostream& out) + { + constexpr auto max_precision{std::numeric_limits::digits10 + 1}; + out << std::setprecision(max_precision); + out << "\nElement reference length: " << element_data.shape_function_data_.ref_length_; + out << "\nElement state vector: "; + element_data.element_position_.print(out); + } + }; +} // namespace GeometryPair + +namespace BeamInteraction +{ + template + inline void set_beam_to_solid_mortar_shape_function_data( + GeometryPair::ElementData& element_data_lambda, + const BeamElementData& beam_element_data) + { + // Default: no additional mortar shape-function data needed. + } + + template + inline void set_beam_to_solid_mortar_shape_function_data( + GeometryPair::ElementData& element_data_lambda, + const BeamElementData& beam_element_data) + { + element_data_lambda.shape_function_data_.ref_length_ = + beam_element_data.shape_function_data_.ref_length_; + } + + template + inline void evaluate_beam_to_solid_mortar_shape_function( + V& N, const T& eta, const GeometryPair::ElementData& mortar_element_data) + { + GeometryPair::EvaluateShapeFunction::evaluate( + N, eta, mortar_element_data.shape_function_data_); + } +} // namespace BeamInteraction + +FOUR_C_NAMESPACE_CLOSE + +#endif \ No newline at end of file diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp index 9029dd3dbca..10d28b54d4d 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_utils.cpp @@ -12,6 +12,7 @@ #include "4C_beaminteraction_calc_utils.hpp" #include "4C_beaminteraction_contact_beam_to_solid_input.hpp" #include "4C_beaminteraction_contact_beam_to_solid_mortar_manager.hpp" +#include "4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp" #include "4C_beaminteraction_contact_beam_to_solid_surface_params.hpp" #include "4C_beaminteraction_contact_beam_to_solid_volume_meshtying_params.hpp" #include "4C_beaminteraction_contact_pair.hpp" diff --git a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp index a1099a5e52d..8510e6841e2 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp @@ -8,6 +8,7 @@ #include "4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.hpp" #include "4C_beaminteraction_contact_beam_to_solid_mortar_manager.hpp" +#include "4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp" #include "4C_beaminteraction_contact_beam_to_solid_utils.hpp" #include "4C_beaminteraction_contact_beam_to_solid_visualization_output_writer_base.hpp" #include "4C_beaminteraction_contact_beam_to_solid_visualization_output_writer_visualization.hpp" @@ -114,11 +115,8 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortar element_data_lambda; - if constexpr (std::is_same_v) - { - element_data_lambda.shape_function_data_.ref_length_ = - this->ele1pos_.shape_function_data_.ref_length_; - } + BeamInteraction::set_beam_to_solid_mortar_shape_function_data( + element_data_lambda, this->ele1pos_); Core::LinAlg::Matrix<3, 1, scalar_type> X; Core::LinAlg::Matrix<3, 1, scalar_type> r; @@ -337,19 +335,12 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortar: N_mortar.clear(); N_beam.clear(); N_solid.clear(); - if constexpr (std::is_same_v) - { - GeometryPair::ShapeFunctionData mortar_shape_function_data; - mortar_shape_function_data.ref_length_ = this->ele1pos_.shape_function_data_.ref_length_; + GeometryPair::ElementData mortar_element_data; + BeamInteraction::set_beam_to_solid_mortar_shape_function_data( + mortar_element_data, this->ele1pos_); - GeometryPair::EvaluateShapeFunction::evaluate( - N_mortar, projected_gauss_point.get_eta(), mortar_shape_function_data); - } - else - { - GeometryPair::EvaluateShapeFunction::evaluate( - N_mortar, projected_gauss_point.get_eta()); - } + BeamInteraction::evaluate_beam_to_solid_mortar_shape_function( + N_mortar, projected_gauss_point.get_eta(), mortar_element_data); GeometryPair::EvaluateShapeFunction::evaluate( N_beam, projected_gauss_point.get_eta(), this->ele1pos_.shape_function_data_); GeometryPair::EvaluateShapeFunction::evaluate( diff --git a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp index 6717a82bb6a..0d23c270089 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp @@ -11,6 +11,7 @@ #include "4C_beam3_triad_interpolation_local_rotation_vectors.hpp" #include "4C_beaminteraction_calc_utils.hpp" #include "4C_beaminteraction_contact_beam_to_solid_mortar_manager.hpp" +#include "4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp" #include "4C_beaminteraction_contact_beam_to_solid_utils.hpp" #include "4C_beaminteraction_contact_beam_to_solid_volume_meshtying_params.hpp" #include "4C_beaminteraction_contact_params.hpp" @@ -259,7 +260,7 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation mortar_shape_function_data; + GeometryPair::ShapeFunctionData mortar_shape_function_data; mortar_shape_function_data.ref_length_ = this->ele1pos_.shape_function_data_.ref_length_; GeometryPair::EvaluateShapeFunction::evaluate( lambda_shape_functions, projected_gauss_point.get_eta(), mortar_shape_function_data); @@ -555,10 +556,12 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation mortar_shape_function_data; - mortar_shape_function_data.ref_length_ = this->ele1pos_.shape_function_data_.ref_length_; - GeometryPair::EvaluateShapeFunction::evaluate( - lambda_shape_functions, projected_gauss_point.get_eta(), mortar_shape_function_data); + GeometryPair::ElementData mortar_rot_element_data; + BeamInteraction::set_beam_to_solid_mortar_shape_function_data( + mortar_rot_element_data, this->ele1pos_); + + BeamInteraction::evaluate_beam_to_solid_mortar_shape_function( + lambda_shape_functions, projected_gauss_point.get_eta(), mortar_rot_element_data); for (unsigned int i_node = 0; i_node < MortarRot::n_nodes_; i_node++) for (unsigned int i_dim = 0; i_dim < 3; i_dim++) lambda_shape_functions_full(i_dim, 3 * i_node + i_dim) = lambda_shape_functions(i_node); diff --git a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp index 89beb233c62..4ef58f41d7f 100644 --- a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp +++ b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp @@ -3024,113 +3024,6 @@ namespace Core::FE return; } - /*! - \brief Fill a matrix of type VectorType with 1D dual hermite shape functions - */ - template - void shape_function_dual_hermite_1d( - VectorType& funct, ///< to be filled with dual shape function values - const NumberType1& xi, ///< xi coordinate - const NumberType2& L, ///< length of element - const Core::FE::CellType& distype ///< distinguish between DiscretizationType - ) - { - static_assert(!std::is_integral_v); - - switch (distype) - { - case Core::FE::CellType::line2: - { - const NumberType1 xi2 = xi * xi; - const NumberType1 xi3 = xi2 * xi; - - funct(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; - - funct(1) = (35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 - 10.0 * xi + 5.0 / 4.0) / L; - - funct(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; - - funct(3) = (-35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 + 10.0 * xi + 5.0 / 4.0) / L; - break; - } - default: - FOUR_C_THROW("distype unknown\n"); - break; - } - - return; - } - - /*! - \brief Fill a matrix of type MatrixType with 1D dual hermite shape function first derivatives - */ - template - void shape_function_dual_hermite_1d_deriv1( - MatrixType& - deriv1, ///< to be filled with dual hermite shape function first derivative values - const NumberType1& xi, ///< xi coordinate - const NumberType2& L, ///< length of element - const Core::FE::CellType& distype) - { - static_assert(!std::is_integral_v); - - switch (distype) - { - case Core::FE::CellType::line2: - { - const NumberType1 xi2 = xi * xi; - - deriv1(0, 0) = -105.0 / 4.0 * xi2 + 15.0 / 2.0 * xi + 15.0 / 4.0; - - deriv1(0, 1) = (315.0 * xi2 - 45.0 * xi - 60.0) / L; - - deriv1(0, 2) = 105.0 / 4.0 * xi2 + 15.0 / 2.0 * xi - 15.0 / 4.0; - - deriv1(0, 3) = (315.0 * xi2 + 45.0 * xi - 60.0) / L; - break; - } - default: - FOUR_C_THROW("distype unknown\n"); - break; - } - - return; - } - - /*! - \brief Fill a matrix of type MatrixType with 1D dual hermite shape function second derivatives - */ - template - void shape_function_dual_hermite_1d_deriv2( - MatrixType& - deriv2, ///< to be filled with dual hermite shape function second derivative values - const NumberType1& xi, ///< xi coordinate - const NumberType2& L, ///< length of element - const Core::FE::CellType& distype) - { - static_assert(!std::is_integral_v); - - switch (distype) - { - case Core::FE::CellType::line2: - { - deriv2(0, 0) = -105.0 / 2.0 * xi + 15.0 / 2.0; - - deriv2(0, 1) = (630.0 * xi - 45.0) / L; - - deriv2(0, 2) = 105.0 / 2.0 * xi + 15.0 / 2.0; - - deriv2(0, 3) = (630.0 * xi + 45.0) / L; - break; - } - default: - FOUR_C_THROW("distype unknown\n"); - break; - } - - return; - } - /*! \brief Fill a matrix of type VectorType with 1D hermite shape functions of order five */ diff --git a/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp b/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp index e30fcc97c1b..f80ced72dbd 100644 --- a/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp +++ b/src/core/fem/tests/utils/4C_fem_general_utils_fem_shapefunctions_test.cpp @@ -9,6 +9,8 @@ #include "4C_fem_general_utils_fem_shapefunctions.hpp" +#include "4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp" + namespace { using namespace FourC; @@ -41,27 +43,17 @@ namespace const double L = 1.0; Core::LinAlg::Matrix<4, 1> Phi(Core::LinAlg::Initialization::zero); - Core::FE::shape_function_dual_hermite_1d(Phi, r, L, Core::FE::CellType::line2); - - std::vector Phi_ref = { - -0.24634578918994066, -0.05276684284142519, -1.1393423701836305, -14.366895799082851}; - - for (std::size_t i = 0; i < Phi_ref.size(); ++i) EXPECT_NEAR(Phi(i), Phi_ref[i], 1e-10); - Core::LinAlg::Matrix<1, 4> dPhi(Core::LinAlg::Initialization::zero); - Core::FE::shape_function_dual_hermite_1d_deriv1(dPhi, r, L, Core::FE::CellType::line2); + GeometryPair::ShapeFunctionData shape_function_data; + shape_function_data.ref_length_ = L; - std::vector dPhi_ref = { - 4.275834475307499, -60.75445819868999, -2.423982640307499, -49.64334718868999}; + GeometryPair::EvaluateShapeFunction::evaluate( + Phi, r, shape_function_data); - for (std::size_t i = 0; i < dPhi_ref.size(); ++i) EXPECT_NEAR(dPhi(i), dPhi_ref[i], 1e-10); - - Core::LinAlg::Matrix<1, 4> ddPhi(Core::LinAlg::Initialization::zero); - Core::FE::shape_function_dual_hermite_1d_deriv2(ddPhi, r, L, Core::FE::CellType::line2); - - std::vector ddPhi_ref = {1.0185185775, 32.77777707, 13.9814814225, 122.77777707}; + std::vector Phi_ref = { + -0.24634578918994066, -0.008794473806904124, -1.1393423701836305, 2.394482633180475}; - for (std::size_t i = 0; i < ddPhi_ref.size(); ++i) EXPECT_NEAR(ddPhi(i), ddPhi_ref[i], 1e-10); + for (std::size_t i = 0; i < Phi_ref.size(); ++i) EXPECT_NEAR(Phi(i), Phi_ref[i], 1e-10); } TEST(ElementShapeFunctionsTest, TestDualHermiteLine2Length03) @@ -70,27 +62,17 @@ namespace const double L = 0.3; Core::LinAlg::Matrix<4, 1> Phi(Core::LinAlg::Initialization::zero); - Core::FE::shape_function_dual_hermite_1d(Phi, r, L, Core::FE::CellType::line2); - std::vector Phi_ref = { - -0.24634578918994066, -0.17588947613808398, -1.1393423701836305, -47.8896526636095}; - - for (std::size_t i = 0; i < Phi_ref.size(); ++i) EXPECT_NEAR(Phi(i), Phi_ref[i], 1e-10); - - Core::LinAlg::Matrix<1, 4> dPhi(Core::LinAlg::Initialization::zero); - Core::FE::shape_function_dual_hermite_1d_deriv1(dPhi, r, L, Core::FE::CellType::line2); + GeometryPair::ShapeFunctionData shape_function_data; + shape_function_data.ref_length_ = L; - std::vector dPhi_ref = { - 4.275834475307499, -202.51486066229998, -2.423982640307499, -165.47782396229996}; + GeometryPair::EvaluateShapeFunction::evaluate( + Phi, r, shape_function_data); - for (std::size_t i = 0; i < dPhi_ref.size(); ++i) EXPECT_NEAR(dPhi(i), dPhi_ref[i], 1e-10); - - Core::LinAlg::Matrix<1, 4> ddPhi(Core::LinAlg::Initialization::zero); - Core::FE::shape_function_dual_hermite_1d_deriv2(ddPhi, r, L, Core::FE::CellType::line2); - - std::vector ddPhi_ref = {1.0185185775, 109.2592569, 13.9814814225, 409.2592569}; + std::vector Phi_ref = { + -0.24634578918994066, -0.029314912689680415, -1.1393423701836305, 7.981608777268251}; - for (std::size_t i = 0; i < ddPhi_ref.size(); ++i) EXPECT_NEAR(ddPhi(i), ddPhi_ref[i], 1e-10); + for (std::size_t i = 0; i < Phi_ref.size(); ++i) EXPECT_NEAR(Phi(i), Phi_ref[i], 1e-10); } } // namespace diff --git a/src/geometry_pair/4C_geometry_pair_element.hpp b/src/geometry_pair/4C_geometry_pair_element.hpp index af9fbdc00f4..878a6fa22a0 100644 --- a/src/geometry_pair/4C_geometry_pair_element.hpp +++ b/src/geometry_pair/4C_geometry_pair_element.hpp @@ -46,17 +46,6 @@ namespace GeometryPair wedge }; - /** - * \brief type of basis used for the shape functions. - */ - enum class BasisType - { - //! standard - standard, - //! dual - dual, - }; - /** * \brief This structure "converts" the discretization type to a geometry type. * @@ -165,7 +154,7 @@ namespace GeometryPair * of the element */ template + unsigned int spatial_dim = 3> class ElementDiscretizationBase { public: @@ -187,9 +176,6 @@ namespace GeometryPair //! Number of unknowns for this element. static constexpr unsigned int n_dof_ = spatial_dim_ * n_val_ * n_nodes_; - //! Basis type used for shape function. - static constexpr BasisType type_ = type; - //! Geometry type of the element. static constexpr GeometryPair::DiscretizationTypeGeometry geometry_type_ = ElementDiscretizationToGeometryType::geometry_type_; @@ -202,8 +188,6 @@ namespace GeometryPair //! 1D elements using t_hermite = ElementDiscretizationBase; - using t_hermite_dual = - ElementDiscretizationBase; using t_line2 = ElementDiscretizationBase; using t_line2_scalar = ElementDiscretizationBase; using t_line3 = ElementDiscretizationBase; @@ -385,15 +369,6 @@ namespace GeometryPair double ref_length_; }; - /** - * \brief Specialization for hermite elements which need a reference length - */ - template <> - struct ShapeFunctionData - { - double ref_length_; - }; - /** * \brief Specialization for nurbs9 surface elements which require an additional factor to specify * outward pointing normals @@ -627,24 +602,6 @@ namespace GeometryPair } }; - /** - * \brief Specialization for dual Hermite elements - */ - template <> - struct PrintElementData - { - template - static void print( - const ElementData& element_data, std::ostream& out) - { - constexpr auto max_precision{std::numeric_limits::digits10 + 1}; - out << std::setprecision(max_precision); - out << "\nElement reference length: " << element_data.shape_function_data_.ref_length_; - out << "\nElement state vector: "; - element_data.element_position_.print(out); - } - }; - /** * \brief Specialization for elements with averaged nodal normals */ diff --git a/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp b/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp index 272fe634ded..c7d263dc6b9 100644 --- a/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp +++ b/src/geometry_pair/4C_geometry_pair_element_shape_functions.hpp @@ -185,58 +185,6 @@ namespace GeometryPair } }; - /** - * \brief Specialization for Hermite elements - */ - template <> - struct EvaluateShapeFunction - { - /** - * \brief Evaluate the shape functions of the element at xi. - * - * @param N (out) shape functions. - * @param xi (in) Parameter coordinate on the element. - * @param shape_function_data (in) Shape function data container. - */ - template - static void evaluate( - V& N, const T& xi, const ShapeFunctionData& shape_function_data) - { - Core::FE::shape_function_dual_hermite_1d( - N, xi, shape_function_data.ref_length_, t_hermite::discretization_); - } - - /** - * \brief Evaluate the derivatives of the shape functions of the element at xi. - * - * @param dN (out) derivatives of shape functions. - * @param xi (in) Parameter coordinate on the element. - * @param shape_function_data (in) Shape function data container. - */ - template - static void evaluate_deriv1( - V& dN, const T& xi, const ShapeFunctionData& shape_function_data) - { - Core::FE::shape_function_dual_hermite_1d_deriv1( - dN, xi, shape_function_data.ref_length_, t_hermite::discretization_); - } - - /** - * \brief Evaluate the 2nd derivatives of the shape functions of the element at xi. - * - * @param ddN (out) 2nd derivatives of shape functions. - * @param xi (in) Parameter coordinate on the element. - * @param shape_function_data (in) Shape function data container. - */ - template - static void evaluate_deriv2( - V& ddN, const T& xi, const ShapeFunctionData& shape_function_data) - { - Core::FE::shape_function_dual_hermite_1d_deriv2( - ddN, xi, shape_function_data.ref_length_, t_hermite::discretization_); - } - }; - /** * \brief Specialization for NURBS elements */ From cbb093178d37ae28575fc8ae13534d391b454896 Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Sat, 30 May 2026 19:41:15 +0000 Subject: [PATCH 05/17] Move shape function definition to FEM core --- ...id_mortar_shape_functions_dual_hermite.hpp | 26 +------------ ...C_fem_general_utils_fem_shapefunctions.hpp | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp index bac5d899fb2..4c438e353c2 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp @@ -39,30 +39,8 @@ namespace GeometryPair static void evaluate(V& N, const T& xi, const ShapeFunctionData& shape_function_data) { - switch (BeamInteraction::t_hermite_dual::discretization_) - { - case Core::FE::CellType::line2: - { - const T xi2 = xi * xi; - const T xi3 = xi2 * xi; - - N(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; - - N(1) = (35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 - 10.0 * xi + 5.0 / 4.0) / - (shape_function_data.ref_length_); - - N(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; - - N(3) = (-35.0 / 2.0 * xi3 - 15.0 / 4.0 * xi2 + 10.0 * xi + 5.0 / 4.0) / - (shape_function_data.ref_length_); - break; - } - default: - FOUR_C_THROW("distype unknown\n"); - break; - } - - return; + Core::FE::shape_function_dual_hermite_1d( + N, xi, shape_function_data.ref_length_, t_hermite::discretization_); } }; diff --git a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp index 4ef58f41d7f..fec5351b0df 100644 --- a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp +++ b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp @@ -3024,6 +3024,43 @@ namespace Core::FE return; } + /*! + \brief Fill a matrix of type VectorType with 1D dual hermite shape functions + */ + template + void shape_function_dual_hermite_1d( + VectorType& funct, ///< to be filled with dual shape function values + const NumberType1& xi, ///< xi coordinate + const NumberType2& L, ///< length of element + const Core::FE::CellType& distype ///< distinguish between DiscretizationType + ) + { + static_assert(!std::is_integral_v); + + switch (distype) + { + case Core::FE::CellType::line2: + { + const NumberType1 xi2 = xi * xi; + const NumberType1 xi3 = xi2 * xi; + + funct(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; + + funct(1) = (105.0 * xi3 - 45.0 / 2.0 * xi2 - 60.0 * xi + 15.0 / 2.0) / L; + + funct(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; + + funct(3) = (105.0 * xi3 + 45.0 / 2.0 * xi2 - 60.0 * xi - 15.0 / 2.0) / L; + break; + } + default: + FOUR_C_THROW("distype unknown\n"); + break; + } + + return; + } + /*! \brief Fill a matrix of type VectorType with 1D hermite shape functions of order five */ From e59a1b0853ab6ee86a37802da39228de0db15746 Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Wed, 3 Jun 2026 08:23:14 +0000 Subject: [PATCH 06/17] Refactor shapefunction evaluation function --- ...id_mortar_shape_functions_dual_hermite.hpp | 56 +++++++++---------- ..._to_solid_volume_meshtying_pair_mortar.cpp | 13 ++--- ..._volume_meshtying_pair_mortar_rotation.cpp | 20 ++++--- ...C_fem_general_utils_fem_shapefunctions.hpp | 37 ------------ 4 files changed, 42 insertions(+), 84 deletions(-) diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp index 4c438e353c2..214dfd7beb7 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_mortar_shape_functions_dual_hermite.hpp @@ -39,8 +39,32 @@ namespace GeometryPair static void evaluate(V& N, const T& xi, const ShapeFunctionData& shape_function_data) { - Core::FE::shape_function_dual_hermite_1d( - N, xi, shape_function_data.ref_length_, t_hermite::discretization_); + static_assert(!std::is_integral_v); + + switch (t_hermite::discretization_) + { + case Core::FE::CellType::line2: + { + const T xi2 = xi * xi; + const T xi3 = xi2 * xi; + + N(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; + + N(1) = (105.0 * xi3 - 45.0 / 2.0 * xi2 - 60.0 * xi + 15.0 / 2.0) / + shape_function_data.ref_length_; + + N(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; + + N(3) = (105.0 * xi3 + 45.0 / 2.0 * xi2 - 60.0 * xi - 15.0 / 2.0) / + shape_function_data.ref_length_; + break; + } + default: + FOUR_C_THROW("distype unknown\n"); + break; + } + + return; } }; @@ -60,34 +84,6 @@ namespace GeometryPair }; } // namespace GeometryPair -namespace BeamInteraction -{ - template - inline void set_beam_to_solid_mortar_shape_function_data( - GeometryPair::ElementData& element_data_lambda, - const BeamElementData& beam_element_data) - { - // Default: no additional mortar shape-function data needed. - } - - template - inline void set_beam_to_solid_mortar_shape_function_data( - GeometryPair::ElementData& element_data_lambda, - const BeamElementData& beam_element_data) - { - element_data_lambda.shape_function_data_.ref_length_ = - beam_element_data.shape_function_data_.ref_length_; - } - - template - inline void evaluate_beam_to_solid_mortar_shape_function( - V& N, const T& eta, const GeometryPair::ElementData& mortar_element_data) - { - GeometryPair::EvaluateShapeFunction::evaluate( - N, eta, mortar_element_data.shape_function_data_); - } -} // namespace BeamInteraction - FOUR_C_NAMESPACE_CLOSE #endif \ No newline at end of file diff --git a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp index 8510e6841e2..64a9e7a1109 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar.cpp @@ -115,9 +115,6 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortar element_data_lambda; - BeamInteraction::set_beam_to_solid_mortar_shape_function_data( - element_data_lambda, this->ele1pos_); - Core::LinAlg::Matrix<3, 1, scalar_type> X; Core::LinAlg::Matrix<3, 1, scalar_type> r; Core::LinAlg::Matrix<3, 1, scalar_type> u; @@ -335,12 +332,10 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortar: N_mortar.clear(); N_beam.clear(); N_solid.clear(); - GeometryPair::ElementData mortar_element_data; - BeamInteraction::set_beam_to_solid_mortar_shape_function_data( - mortar_element_data, this->ele1pos_); - - BeamInteraction::evaluate_beam_to_solid_mortar_shape_function( - N_mortar, projected_gauss_point.get_eta(), mortar_element_data); + GeometryPair::ShapeFunctionData shape_function_data; + GeometryPair::SetShapeFunctionData::set(shape_function_data, this->element1()); + GeometryPair::EvaluateShapeFunction::evaluate( + N_mortar, projected_gauss_point.get_eta(), shape_function_data); GeometryPair::EvaluateShapeFunction::evaluate( N_beam, projected_gauss_point.get_eta(), this->ele1pos_.shape_function_data_); GeometryPair::EvaluateShapeFunction::evaluate( diff --git a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp index 0d23c270089..c5b4f101034 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/volume/4C_beaminteraction_contact_beam_to_solid_volume_meshtying_pair_mortar_rotation.cpp @@ -185,7 +185,10 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation T_solid_inv; Core::LinAlg::Matrix<3, 3, double> T_rel; - Core::LinAlg::Matrix lambda_shape_functions; + // Core::LinAlg::Matrix lambda_shape_functions; + static constexpr unsigned int n_lambda_shape_functions = MortarRot::n_dof_ / 3; + + Core::LinAlg::Matrix lambda_shape_functions; Core::LinAlg::Matrix<3, MortarRot::n_dof_, double> lambda_shape_functions_full( Core::LinAlg::Initialization::zero); Core::LinAlg::SerialDenseVector L_i(3); @@ -472,7 +475,10 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation T_solid_inv; Core::LinAlg::Matrix<3, 3, scalar_type_rot_1st> T_rel; - Core::LinAlg::Matrix lambda_shape_functions; + // Core::LinAlg::Matrix lambda_shape_functions; + static constexpr unsigned int n_lambda_shape_functions = MortarRot::n_dof_ / 3; + + Core::LinAlg::Matrix lambda_shape_functions; Core::LinAlg::Matrix<3, MortarRot::n_dof_, scalar_type_rot_1st> lambda_shape_functions_full( Core::LinAlg::Initialization::zero); Core::LinAlg::SerialDenseVector L_i(3); @@ -556,12 +562,10 @@ void BeamInteraction::BeamToSolidVolumeMeshtyingPairMortarRotation mortar_rot_element_data; - BeamInteraction::set_beam_to_solid_mortar_shape_function_data( - mortar_rot_element_data, this->ele1pos_); - - BeamInteraction::evaluate_beam_to_solid_mortar_shape_function( - lambda_shape_functions, projected_gauss_point.get_eta(), mortar_rot_element_data); + GeometryPair::ShapeFunctionData shape_function_data; + GeometryPair::SetShapeFunctionData::set(shape_function_data, this->element1()); + GeometryPair::EvaluateShapeFunction::evaluate( + lambda_shape_functions, projected_gauss_point.get_eta(), shape_function_data); for (unsigned int i_node = 0; i_node < MortarRot::n_nodes_; i_node++) for (unsigned int i_dim = 0; i_dim < 3; i_dim++) lambda_shape_functions_full(i_dim, 3 * i_node + i_dim) = lambda_shape_functions(i_node); diff --git a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp index fec5351b0df..4ef58f41d7f 100644 --- a/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp +++ b/src/core/fem/src/general/utils/4C_fem_general_utils_fem_shapefunctions.hpp @@ -3024,43 +3024,6 @@ namespace Core::FE return; } - /*! - \brief Fill a matrix of type VectorType with 1D dual hermite shape functions - */ - template - void shape_function_dual_hermite_1d( - VectorType& funct, ///< to be filled with dual shape function values - const NumberType1& xi, ///< xi coordinate - const NumberType2& L, ///< length of element - const Core::FE::CellType& distype ///< distinguish between DiscretizationType - ) - { - static_assert(!std::is_integral_v); - - switch (distype) - { - case Core::FE::CellType::line2: - { - const NumberType1 xi2 = xi * xi; - const NumberType1 xi3 = xi2 * xi; - - funct(0) = -35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 + 15.0 / 4.0 * xi - 3.0 / 4.0; - - funct(1) = (105.0 * xi3 - 45.0 / 2.0 * xi2 - 60.0 * xi + 15.0 / 2.0) / L; - - funct(2) = 35.0 / 4.0 * xi3 + 15.0 / 4.0 * xi2 - 15.0 / 4.0 * xi - 3.0 / 4.0; - - funct(3) = (105.0 * xi3 + 45.0 / 2.0 * xi2 - 60.0 * xi - 15.0 / 2.0) / L; - break; - } - default: - FOUR_C_THROW("distype unknown\n"); - break; - } - - return; - } - /*! \brief Fill a matrix of type VectorType with 1D hermite shape functions of order five */ From 269a2afceab07ad6e33d10c1552318e721ea1b00 Mon Sep 17 00:00:00 2001 From: Dharini Balachandran Date: Wed, 3 Jun 2026 14:11:12 +0000 Subject: [PATCH 07/17] Split template factory --- ...ction_contact_beam_to_solid_conditions.cpp | 60 ++++++++++++++++++- ...id_mortar_shape_functions_dual_hermite.hpp | 13 ++-- ...nteraction_contact_beam_to_solid_utils.cpp | 24 ++++---- ..._to_solid_volume_meshtying_pair_mortar.cpp | 12 ++-- ..._volume_meshtying_pair_mortar_rotation.cpp | 23 ++----- ..._general_utils_fem_shapefunctions_test.cpp | 8 +-- 6 files changed, 91 insertions(+), 49 deletions(-) diff --git a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp index e61f87ffa8f..aeddc38b222 100644 --- a/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp +++ b/src/beaminteraction/src/contact/beam_to_solid/4C_beaminteraction_contact_beam_to_solid_conditions.cpp @@ -363,7 +363,7 @@ BeamInteraction::create_beam_to_solid_volume_pair_mortar(const Core::FE::CellTyp GeometryPair::t_line4>(shape, other_mortar_shape_function...); case BeamToSolid::BeamToSolidMortarShapefunctions::dual_hermite: return create_beam_to_solid_volume_pair_mortar(shape, other_mortar_shape_function...); + BeamInteraction::HermiteDual>(shape, other_mortar_shape_function...); default: FOUR_C_THROW("Wrong mortar shape function."); return nullptr; @@ -380,6 +380,37 @@ BeamInteraction::create_beam_to_solid_volume_pair_mortar(const Core::FE::CellTyp return create_beam_to_solid_volume_pair_shape(shape); } +template