From ae11b3b495704812897d8e7e8c123da4682be9f5 Mon Sep 17 00:00:00 2001 From: Ivo Steinbrecher Date: Thu, 10 Jul 2025 11:11:36 +0200 Subject: [PATCH] Move functionality out of wrapper --- src/cubitpy/cubit_group.py | 3 +- .../cubit_wrapper/cubit_wrapper_host.py | 44 ----------- src/cubitpy/cubitpy.py | 7 +- .../{cubit_utility.py => geometry_utils.py} | 5 +- src/cubitpy/utils.py | 74 +++++++++++++++++++ src/tutorial/tutorial.py | 6 +- tests/test_cubitpy.py | 17 +++-- 7 files changed, 95 insertions(+), 61 deletions(-) rename src/cubitpy/{cubit_utility.py => geometry_utils.py} (91%) create mode 100644 src/cubitpy/utils.py diff --git a/src/cubitpy/cubit_group.py b/src/cubitpy/cubit_group.py index c35aa5a..038d9f7 100644 --- a/src/cubitpy/cubit_group.py +++ b/src/cubitpy/cubit_group.py @@ -23,6 +23,7 @@ from cubitpy.conf import cupy from cubitpy.cubit_wrapper.cubit_wrapper_host import CubitObject +from cubitpy.utils import get_geometry_type class CubitGroup(object): @@ -125,7 +126,7 @@ def add(self, add_value): self.cubit.add_entity_to_group( self._id, add_value.id(), - add_value.get_geometry_type().get_cubit_string(), + get_geometry_type(add_value).get_cubit_string(), ) elif isinstance(add_value, list): for item in add_value: diff --git a/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py b/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py index 941a669..7a7142d 100644 --- a/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py +++ b/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py @@ -325,50 +325,6 @@ def get_attributes(self): """Return a list of all non callable cubit methods for this object.""" return [method for method, callable in self.get_self_dir() if not callable] - def get_geometry_type(self): - """Return the type of this item.""" - - if self.isinstance("cubitpy_vertex"): - return cupy.geometry.vertex - elif self.isinstance("cubitpy_curve"): - return cupy.geometry.curve - elif self.isinstance("cubitpy_surface"): - return cupy.geometry.surface - elif self.isinstance("cubitpy_volume"): - return cupy.geometry.volume - - # Default value -> not a valid geometry - raise TypeError("The item is not a valid geometry!") - - def get_node_ids(self): - """Return a list with the node IDs (index 1) of this object. - - This is done by creating a temporary node set that this geometry - is added to. It is not possible to get the node list directly - from cubit. - """ - - # Get a node set ID that is not yet taken - node_set_ids = [0] - node_set_ids.extend(self.cubit_connect.cubit.get_nodeset_id_list()) - temp_node_set_id = max(node_set_ids) + 1 - - # Add a temporary node set with this geometry - self.cubit_connect.cubit.cmd( - "nodeset {} {} {}".format( - temp_node_set_id, self.get_geometry_type().get_cubit_string(), self.id() - ) - ) - - # Get the nodes in the created node set - node_ids = self.cubit_connect.cubit.get_nodeset_nodes_inclusive( - temp_node_set_id - ) - - # Delete the temp node set and return the node list - self.cubit_connect.cubit.cmd("delete nodeset {}".format(temp_node_set_id)) - return node_ids - class CubitObjectMain(CubitObject): """The main cubit object will be of this type, it can not delete itself.""" diff --git a/src/cubitpy/cubitpy.py b/src/cubitpy/cubitpy.py index 26d1f89..ee4d012 100644 --- a/src/cubitpy/cubitpy.py +++ b/src/cubitpy/cubitpy.py @@ -32,6 +32,7 @@ from cubitpy.cubit_group import CubitGroup from cubitpy.cubit_to_fourc_input import get_input_file_with_mesh from cubitpy.cubit_wrapper.cubit_wrapper_host import CubitConnect +from cubitpy.utils import get_geometry_type class CubitPy(object): @@ -160,7 +161,7 @@ def add_element_type( ) # Get element type of item. - geometry_type = item.get_geometry_type() + geometry_type = get_geometry_type(item) self.cubit.cmd("create block {}".format(n_blocks + 1)) @@ -247,7 +248,7 @@ def add_node_set( # Get element type of item if it was not explicitly given. if geometry_type is None: - geometry_type = item.get_geometry_type() + geometry_type = get_geometry_type(item) self.cubit.cmd("create nodeset {}".format(n_node_sets + 1)) if not isinstance(item, CubitGroup): @@ -314,7 +315,7 @@ def set_line_interval(self, item, n_el): """ # Check if item is line. - if not item.get_geometry_type() == cupy.geometry.curve: + if not get_geometry_type(item) == cupy.geometry.curve: raise TypeError("Expected line, got {}".format(type(item))) self.cubit.cmd("curve {} interval {} scheme equal".format(item.id(), n_el)) diff --git a/src/cubitpy/cubit_utility.py b/src/cubitpy/geometry_utils.py similarity index 91% rename from src/cubitpy/cubit_utility.py rename to src/cubitpy/geometry_utils.py index df4ecea..0a49529 100644 --- a/src/cubitpy/cubit_utility.py +++ b/src/cubitpy/geometry_utils.py @@ -19,16 +19,17 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -"""Utility functions for the use of cubitpy.""" +"""Utility functions for the use of geometries in cubit.""" from cubitpy.conf import cupy +from cubitpy.utils import get_geometry_type def get_surface_center(surf): """Get a 3D point that has the local coordinated on the surface of (0,0), with the parameter space being ([-1,1],[-1,1]).""" - if not surf.get_geometry_type() == cupy.geometry.surface: + if not get_geometry_type(surf) == cupy.geometry.surface: raise TypeError("Did not expect {}".format(type(surf))) range_u = surf.get_param_range_U() diff --git a/src/cubitpy/utils.py b/src/cubitpy/utils.py new file mode 100644 index 0000000..51b0522 --- /dev/null +++ b/src/cubitpy/utils.py @@ -0,0 +1,74 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018-2025 CubitPy Authors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +"""Utility functions for the use of cubitpy.""" + +from cubitpy.conf import cupy + + +def get_geometry_type(item): + """Return the type of this item.""" + + # At the moment we need to import this here to avoid circular imports + from cubitpy.cubit_group import CubitGroup + + if isinstance(item, CubitGroup): + return item.get_geometry_type() + else: + if item.isinstance("cubitpy_vertex"): + return cupy.geometry.vertex + elif item.isinstance("cubitpy_curve"): + return cupy.geometry.curve + elif item.isinstance("cubitpy_surface"): + return cupy.geometry.surface + elif item.isinstance("cubitpy_volume"): + return cupy.geometry.volume + + # Default value -> not a valid geometry + raise TypeError("The item is not a valid geometry!") + + +def get_node_ids(cubit, item): + """Return a list with the node IDs (index 1) of this object. + + This is done by creating a temporary node set that this geometry is + added to. It is not possible to get the node list directly from + cubit. + """ + + # Get a node set ID that is not yet taken + node_set_ids = [0] + node_set_ids.extend(cubit.get_nodeset_id_list()) + temp_node_set_id = max(node_set_ids) + 1 + + # Add a temporary node set with this geometry + cubit.cmd( + "nodeset {} {} {}".format( + temp_node_set_id, get_geometry_type(item).get_cubit_string(), item.id() + ) + ) + + # Get the nodes in the created node set + node_ids = cubit.get_nodeset_nodes_inclusive(temp_node_set_id) + + # Delete the temp node set and return the node list + cubit.cmd("delete nodeset {}".format(temp_node_set_id)) + return node_ids diff --git a/src/tutorial/tutorial.py b/src/tutorial/tutorial.py index 903ac77..11ad0cd 100644 --- a/src/tutorial/tutorial.py +++ b/src/tutorial/tutorial.py @@ -32,7 +32,7 @@ import numpy as np from cubitpy import CubitPy, cupy -from cubitpy.cubit_utility import get_surface_center +from cubitpy.geometry_utils import get_surface_center def cubit_step_by_step_tutorial_cli( @@ -77,7 +77,7 @@ def cubit_step_by_step_tutorial_cli( # Now you must create the cylinder which will be used to cut the hole # from the brick. This is accomplished with the CLI. # (Alternatively we could also use the cubit python command `cubit.cylinder`) - cubit.cmd(f"create cylinder height {brick_size*1.2} radius {hole_radius}") + cubit.cmd(f"create cylinder height {brick_size * 1.2} radius {hole_radius}") # Executing a command via the CLI does not return the geometry object. To get the # cylinder object we can write @@ -143,7 +143,7 @@ def cubit_step_by_step_tutorial_cli( if np.abs(radius - hole_radius) < 1e-10: # The curve lies on the cylinder radius, now set the meshing interval - cubit.cmd(f"curve {curve.id()} interval size {size/2}") + cubit.cmd(f"curve {curve.id()} interval size {size / 2}") # Now we can mesh the surface cubit.cmd(f"mesh surface {mesh_surface.id()}") diff --git a/tests/test_cubitpy.py b/tests/test_cubitpy.py index 4d0b205..6ca1cec 100644 --- a/tests/test_cubitpy.py +++ b/tests/test_cubitpy.py @@ -38,14 +38,15 @@ # CubitPy imports. from cubitpy.conf import cupy -from cubitpy.cubit_utility import get_surface_center, import_fluent_geometry from cubitpy.cubitpy import CubitPy from cubitpy.geometry_creation_functions import ( create_brick_by_corner_points, create_parametric_surface, create_spline_interpolation_curve, ) +from cubitpy.geometry_utils import get_surface_center, import_fluent_geometry from cubitpy.mesh_creation_functions import create_brick, extrude_mesh_normal_to_surface +from cubitpy.utils import get_node_ids # Global variable if this test is run by GitLab. if "TESTING_GITHUB" in os.environ.keys() and os.environ["TESTING_GITHUB"] == "1": @@ -1009,14 +1010,14 @@ def test_point_coupling(): # Sort the node IDs, by doing so the results are independent of the ordering # of the node IDs returned by cubit (which can change between versions). - node_ids_1 = surf[0].get_node_ids() + node_ids_1 = get_node_ids(cubit, surf[0]) node_ids_1.sort() - node_ids_2 = surf[1].get_node_ids() + node_ids_2 = get_node_ids(cubit, surf[1]) node_ids_2.sort() for node_id_1 in node_ids_1: coordinates_1 = np.array(cubit.get_nodal_coordinates(node_id_1)) - for node_id_2 in surf[1].get_node_ids(): + for node_id_2 in get_node_ids(cubit, surf[1]): coordinates_2 = cubit.get_nodal_coordinates(node_id_2) if np.linalg.norm(coordinates_2 - coordinates_1) < cupy.eps_pos: cubit.add_node_set( @@ -1373,19 +1374,19 @@ def test_get_node_id_function(): brick = create_brick(cubit, 1, 1, 1, mesh_interval=[2, 2, 2]) # Compare volume, surface, curve and vertex nodes. - node_ids = brick.volumes()[0].get_node_ids() + node_ids = get_node_ids(cubit, brick.volumes()[0]) node_ids.sort() assert node_ids == list(range(1, 28)) - node_ids = brick.surfaces()[3].get_node_ids() + node_ids = get_node_ids(cubit, brick.surfaces()[3]) node_ids.sort() assert node_ids == [4, 6, 7, 13, 15, 16, 19, 22, 23] - node_ids = brick.curves()[4].get_node_ids() + node_ids = get_node_ids(cubit, brick.curves()[4]) node_ids.sort() assert node_ids == [10, 11, 12] - node_ids = brick.vertices()[7].get_node_ids() + node_ids = get_node_ids(cubit, brick.vertices()[7]) node_ids.sort() assert node_ids == [15]