diff --git a/README.md b/README.md index 7c064e5..fc45583 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -[![build-test](https://github.com/imcs-compsim/cubitpy/actions/workflows/.github/workflows/build-test.yml/badge.svg)](https://github.com/imcs-compsim/cubitpy/actions/workflows/.github/workflows/build-test.yml) - # CubitPy Utility functions and 4C related functionality for the Cubit and Coreform python interface, Especially for the creation of input files for 4C. +[![Cubit testing](https://github.com/imcs-compsim/cubitpy/actions/workflows/testing.yml/badge.svg)](https://github.com/imcs-compsim/cubitpy/actions/workflows/testing.yml) + ## Usage A tutorial can be found in the `/tutorial` directory. @@ -59,7 +59,7 @@ pip install . If you intend to actively develop `cubitpy`, install it in *editable mode* ```bash -pip install -e . +pip install -e ".[dev]" ``` To run CubitPy it is required to set an environment variable with the path to the Cubit directory. This should be the "root" directory for the installation. @@ -67,10 +67,10 @@ To run CubitPy it is required to set an environment variable with the path to th export CUBIT_ROOT=path_to_cubit_root_directory ``` -To check if everything worked as expected, run the tests from within the `tests` directory +To check if everything worked as expected, run the test suite (from the root directory) ```bash cd path_to_cubitpy/tests -pytest -q testing.py +pytest ``` If you intend to actively develop CubitPy, please make sure to install the `pre-commit` hook within the python environment to follow our style guides: diff --git a/src/cubitpy/cubitpy_types.py b/src/cubitpy/cubitpy_types.py index 7a38c12..c31f91b 100644 --- a/src/cubitpy/cubitpy_types.py +++ b/src/cubitpy/cubitpy_types.py @@ -22,6 +22,7 @@ """This module contains ENums for types used in cubitpy as well as functions to convert them to strings for cubit or 4C commands or the wrapper.""" +import warnings from enum import Enum, auto @@ -286,7 +287,11 @@ class BoundaryConditionType(Enum): beam_to_solid_volume_meshtying = auto() beam_to_solid_surface_meshtying = auto() beam_to_solid_surface_contact = auto() + # The following value "solid_to_solid_surface_contact" is deprecated and + # only kept for legacy reasons. + # Please use "solid_to_solid_contact" instead. solid_to_solid_surface_contact = auto() + solid_to_solid_contact = auto() # fluid flow_rate = auto() @@ -322,25 +327,30 @@ def get_dat_bc_section_header(self, geometry_type): and geometry_type == GeometryType.surface ): return "BEAM INTERACTION/BEAM TO SOLID SURFACE CONTACT SURFACE" - elif self == self.point_coupling and ( - geometry_type == GeometryType.vertex - or geometry_type == FiniteElementObject.node - ): + elif self == self.point_coupling and (geometry_type == GeometryType.vertex): return "DESIGN POINT COUPLING CONDITIONS" elif self == self.solid_to_solid_surface_contact and ( geometry_type == GeometryType.surface - or geometry_type == FiniteElementObject.node ): + warnings.warn( + "The 'solid_to_solid_surface_contact' boundary condition enum is deprecated " + "and will be removed in a future version. " + "Use 'solid_to_solid_contact' instead.", + category=DeprecationWarning, + stacklevel=2, + ) return "DESIGN SURF MORTAR CONTACT CONDITIONS 3D" - elif self == self.fsi_coupling and ( + elif self == self.solid_to_solid_contact and ( geometry_type == GeometryType.surface - or geometry_type == FiniteElementObject.node ): - return "DESIGN FSI COUPLING SURF CONDITIONS" - elif self == self.ale_dirichlet and ( - geometry_type == GeometryType.surface - or geometry_type == FiniteElementObject.node + return "DESIGN SURF MORTAR CONTACT CONDITIONS 3D" + elif self == self.solid_to_solid_contact and ( + geometry_type == GeometryType.curve ): + return "DESIGN LINE MORTAR CONTACT CONDITIONS 2D" + elif self == self.fsi_coupling and (geometry_type == GeometryType.surface): + return "DESIGN FSI COUPLING SURF CONDITIONS" + elif self == self.ale_dirichlet and (geometry_type == GeometryType.surface): return "DESIGN SURF ALE DIRICH CONDITIONS" elif self == self.flow_rate and (geometry_type == GeometryType.surface): return "DESIGN FLOW RATE SURF CONDITIONS" diff --git a/tests/input-files-ref/test_contact_condition_curve_to_curve.4C.yaml b/tests/input-files-ref/test_contact_condition_curve_to_curve.4C.yaml new file mode 100644 index 0000000..555a8c5 --- /dev/null +++ b/tests/input-files-ref/test_contact_condition_curve_to_curve.4C.yaml @@ -0,0 +1,28 @@ +DESIGN LINE MORTAR CONTACT CONDITIONS 2D: + - InterfaceID: 0 + Side: "Master" + E: 1 + - InterfaceID: 0 + Side: "Slave" + E: 2 +DLINE-NODE TOPOLOGY: + - "NODE 3 DLINE 1" + - "NODE 4 DLINE 1" + - "NODE 5 DLINE 2" + - "NODE 6 DLINE 2" + - "NODE 9 DLINE 2" +NODE COORDS: + - "NODE 1 COORD 0.5 0.5 0.0" + - "NODE 2 COORD -0.5 0.5 0.0" + - "NODE 3 COORD -0.5 -0.5 0.0" + - "NODE 4 COORD 0.5 -0.5 0.0" + - "NODE 5 COORD 1.0 -0.5 0.0" + - "NODE 6 COORD 0.0 -0.5 0.0" + - "NODE 7 COORD 0.0 -1.5 0.0" + - "NODE 8 COORD 1.0 -1.5 0.0" + - "NODE 9 COORD -1.0 -0.5 0.0" + - "NODE 10 COORD -1.0 -1.5 0.0" +STRUCTURE ELEMENTS: + - "1 WALL QUAD4 1 2 3 4 MAT 1 KINEM nonlinear EAS None THICK 1 STRESS_STRAIN plain_strain GP 2 2" + - "2 WALL QUAD4 5 6 7 8 MAT 1 KINEM nonlinear EAS None THICK 1 STRESS_STRAIN plain_strain GP 2 2" + - "3 WALL QUAD4 6 9 10 7 MAT 1 KINEM nonlinear EAS None THICK 1 STRESS_STRAIN plain_strain GP 2 2" diff --git a/tests/test_cubitpy.py b/tests/test_cubitpy.py index 4d0b205..ff3ab0d 100644 --- a/tests/test_cubitpy.py +++ b/tests/test_cubitpy.py @@ -842,6 +842,57 @@ def test_contact_condition_beam_to_surface(): compare_yaml(cubit) +def test_contact_condition_curve_to_curve(): + """Test the curve-to-curve contact condition BC.""" + cubit = CubitPy() + + # Create and mesh two rectangles + cubit.cmd("create surface rectangle width 1 height 1 zplane") + solid1 = cubit.surface(cubit.get_last_id(cupy.geometry.surface)) + cubit.cmd(f"surface {solid1.id()} size 1") + cubit.cmd("create surface rectangle width 2 height 1 zplane") + solid2 = cubit.surface(cubit.get_last_id(cupy.geometry.surface)) + cubit.cmd(f"move surface {solid2.id()} x 0 y -1 z 0 include_merged") + cubit.cmd(f"surface {solid2.id()} size 1") + cubit.cmd("mesh surface all") + + # Add elements + bc_desc = { + "KINEM": "nonlinear", + "EAS": None, + "THICK": 1, + "STRESS_STRAIN": "plain_strain", + "GP": [2, 2], + } + cubit.add_element_type( + solid1.surfaces()[0], + el_type=cupy.element_type.quad4, + bc_description=bc_desc, + ) + cubit.add_element_type( + solid2.surfaces()[0], + el_type=cupy.element_type.quad4, + bc_description=bc_desc, + ) + + # Test contact conditions + cubit.add_node_set( + solid1.curves()[2], + name="block1_contact_side", + bc_type=cupy.bc_type.solid_to_solid_contact, + bc_description={"InterfaceID": 0, "Side": "Master"}, + ) + cubit.add_node_set( + solid2.curves()[0], + name="block2_contact_side", + bc_type=cupy.bc_type.solid_to_solid_contact, + bc_description={"InterfaceID": 0, "Side": "Slave"}, + ) + + # Compare the input file created for 4C. + compare_yaml(cubit) + + def test_contact_condition_surface_to_surface(): """Test the surface-to-surface contact condition BC.""" cubit = CubitPy() @@ -861,7 +912,7 @@ def test_contact_condition_surface_to_surface(): cubit.add_node_set( solid2.surfaces()[3], name="block2_contact_side", - bc_type=cupy.bc_type.solid_to_solid_surface_contact, + bc_type=cupy.bc_type.solid_to_solid_contact, bc_description={"InterfaceID": 0, "Side": "Slave"}, )