From 643fd372540a1209fca0b71d7ebc9d2bdbf6a82c Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Mon, 13 Apr 2026 14:23:40 +0200 Subject: [PATCH 01/10] feat: update to Python 3.14 --- .github/actions/setup_python_environment/action.yml | 2 +- .github/actions/source_distribution_build/action.yml | 2 +- .../build_sdist_build_test_wheels_PR_and_merge.yml | 10 +++++----- ...t_build_test_wheels_nightly_and_publish_release.yml | 2 +- .github/workflows/testing.yml | 2 +- .github/workflows/website.yml | 2 +- README.md | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/actions/setup_python_environment/action.yml b/.github/actions/setup_python_environment/action.yml index a7b4cdbb..e4b4ceac 100644 --- a/.github/actions/setup_python_environment/action.yml +++ b/.github/actions/setup_python_environment/action.yml @@ -5,7 +5,7 @@ inputs: python-version: description: "Python version to use" required: false - default: "3.13" + default: "3.14" env_type: description: "Environment type: `conda`, `venv` or `system`" # on Windows `bash -l {0}` shell is required for conda environments diff --git a/.github/actions/source_distribution_build/action.yml b/.github/actions/source_distribution_build/action.yml index 568b15b7..0e64bbf6 100644 --- a/.github/actions/source_distribution_build/action.yml +++ b/.github/actions/source_distribution_build/action.yml @@ -7,7 +7,7 @@ runs: - name: Setup python environment uses: ./.github/actions/setup_python_environment with: - python-version: "3.13" + python-version: "3.14" env_type: venv - name: Install build tool diff --git a/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml b/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml index 799516a2..6b72141a 100644 --- a/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml +++ b/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml @@ -21,7 +21,7 @@ jobs: uses: ./.github/actions/source_distribution_build build-test-wheels: - name: build-test-wheel python 3.13 on ${{ matrix.os }} + name: build-test-wheel python 3.14 on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -34,10 +34,10 @@ jobs: - name: Build wheels uses: ./.github/actions/wheel_build with: - python-version: "3.13" - wheel-name: wheels-${{ matrix.os }}-py3.13 + python-version: "3.14" + wheel-name: wheels-${{ matrix.os }}-py3.14 - name: Test wheels uses: ./.github/actions/wheel_test with: - python-version: "3.13" - wheel-name: wheels-${{ matrix.os }}-py3.13 + python-version: "3.14" + wheel-name: wheels-${{ matrix.os }}-py3.14 diff --git a/.github/workflows/build_sdist_build_test_wheels_nightly_and_publish_release.yml b/.github/workflows/build_sdist_build_test_wheels_nightly_and_publish_release.yml index 2025ba9a..4746c39e 100644 --- a/.github/workflows/build_sdist_build_test_wheels_nightly_and_publish_release.yml +++ b/.github/workflows/build_sdist_build_test_wheels_nightly_and_publish_release.yml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.10", "3.11", "3.12", "3.13"] + python-version: ["3.11", "3.12", "3.13", "3.14"] steps: - name: Checkout code diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index e0f3b124..b5fe2b0a 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -20,7 +20,7 @@ jobs: fail-fast: false matrix: os-version: [ubuntu-latest, macos-latest, windows-latest] - python-version: ["3.10", "3.13"] + python-version: ["3.11", "3.14"] runs-on: ${{ matrix.os-version }} steps: - name: Checkout PR code diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 50a71a5c..5ea83de2 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -24,7 +24,7 @@ jobs: - name: Setup python environment uses: ./.github/actions/setup_python_environment with: - python-version: '3.13' + python-version: '3.14' - name: Install dependencies run: | pip install -r website/requirements.txt diff --git a/README.md b/README.md index ad4e80b5..35ceb0a3 100644 --- a/README.md +++ b/README.md @@ -219,11 +219,11 @@ interaction, , (2022) ### Python environment -BeamMe is tested with, and supports Python versions 3.10-3.13. It is recommended to use a virtual Python environment such as [Conda](https://anaconda.org/anaconda/conda)/[Miniforge](https://conda-forge.org/download/) or [venv](https://docs.python.org/3/library/venv.html). +BeamMe is tested with, and supports Python versions 3.10-3.14. It is recommended to use a virtual Python environment such as [Conda](https://anaconda.org/anaconda/conda)/[Miniforge](https://conda-forge.org/download/) or [venv](https://docs.python.org/3/library/venv.html). - A [Conda](https://anaconda.org/anaconda/conda)/[Miniforge](https://conda-forge.org/download/) environment can be created and loaded with ```bash # Create the environment (this only has to be done once) - conda create -n beamme python=3.13 + conda create -n beamme python=3.14 # Activate the environment conda activate beamme ``` From 1f93e50ef8e73625785c4fc6deb236b067477b3f Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 10:36:49 +0200 Subject: [PATCH 02/10] chore: update pre-commit hooks --- .pre-commit-config.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e45cd983..dccb0e51 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: check-added-large-files args: ['—-maxkb=1000'] @@ -37,24 +37,24 @@ repos: - id: trailing-whitespace name: Check for trailing whitespaces - repo: https://github.com/PyCQA/bandit - rev: 1.8.0 + rev: 1.9.4 hooks: - id: bandit name: Run bandit (security linter for python) args: ["--configfile", "pyproject.toml", "--exclude", "tests/*"] additional_dependencies: ["bandit[toml]"] - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v19.1.5 + rev: v22.1.5 hooks: - id: clang-format name: Run clang-format (C/C++ formatter) types_or: [c, c++] - repo: https://github.com/PyCQA/docformatter - rev: "eb1df347edd128b30cd3368dddc3aa65edcfac38" # change back to version once bug is fixed in latest version to be compatible with pre-commit + rev: v1.7.8 hooks: - id: docformatter name: Run docformatter (formatter for docstrings) - args: ["--in-place", "--config=./pyproject.toml", "-r", "src/beamme/", "tests/"] + args: ["--in-place", "--black", "--config=./pyproject.toml", "-r", "src/beamme/", "tests/"] - repo: https://github.com/econchick/interrogate rev: 1.7.0 hooks: @@ -63,19 +63,19 @@ repos: args: [--fail-under=100, --ignore-init-module, --style=google, -vv] exclude: ^website/ - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + rev: v2.1.0 hooks: - id: mypy name: Run mypy (static type checker for python) args: ["--install-types", "--non-interactive", "--ignore-missing-imports", "--follow-imports=silent"] exclude: "^website/" - repo: https://github.com/kynan/nbstripout - rev: 0.8.1 + rev: 0.9.1 hooks: - id: nbstripout name: Run nbstripout (strip output from Jupyter notebooks) - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.5.5 + rev: v1.5.6 hooks: - id: insert-license name: Insert license header (//) @@ -102,7 +102,7 @@ repos: - id: removestar name: Run removestar (remove wildcard imports) - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.2 + rev: v0.15.20 hooks: - id: ruff # linter name: Run ruff (linter for Python) @@ -110,7 +110,7 @@ repos: - id: ruff-format # formatter name: Run ruff (formatter for Python) - repo: https://github.com/crate-ci/typos - rev: v1.28.4 + rev: v1.48.0 hooks: - id: typos name: Run typo checker @@ -122,7 +122,7 @@ repos: name: Run xml-formatter args: [--indent, "2", --indent-char, " ", --selfclose, --overwrite, --eof-newline] - repo: https://github.com/google/yamlfmt - rev: v0.14.0 + rev: v0.21.0 hooks: - id: yamlfmt name: Run yamlfmt From 1e9e528e1c05580dc91412ef892637dc69f4f69c Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 10:48:44 +0200 Subject: [PATCH 03/10] fix: pre-commit updates to code base --- .typos.toml | 3 + examples/example_1_finite_rotations.ipynb | 2 +- examples/utils/example_1_utils.py | 5 +- src/beamme/abaqus/__init__.py | 3 +- src/beamme/abaqus/beam.py | 6 +- src/beamme/abaqus/input_file.py | 22 ++---- src/beamme/abaqus/material.py | 7 +- src/beamme/core/__init__.py | 3 +- src/beamme/core/base_mesh_item.py | 10 +-- src/beamme/core/boundary_condition.py | 16 ++-- src/beamme/core/conf.py | 4 +- src/beamme/core/container.py | 12 +-- src/beamme/core/coupling.py | 7 +- src/beamme/core/element.py | 1 - src/beamme/core/element_beam.py | 2 - src/beamme/core/function.py | 6 +- src/beamme/core/geometry_set.py | 46 +++++------ src/beamme/core/material.py | 10 +-- src/beamme/core/mesh.py | 54 +++++-------- src/beamme/core/mesh_representation.py | 18 ++--- src/beamme/core/mesh_utils.py | 10 +-- src/beamme/core/node.py | 6 +- src/beamme/core/nurbs_patch.py | 26 +++---- src/beamme/core/rotation.py | 49 ++++-------- src/beamme/cosserat_curve/__init__.py | 8 +- src/beamme/cosserat_curve/cosserat_curve.py | 30 +++----- .../warping_along_cosserat_curve.py | 26 +++---- .../four_c/beam_interaction_conditions.py | 15 ++-- src/beamme/four_c/beam_potential.py | 3 - src/beamme/four_c/dbc_monitor.py | 40 +++++----- src/beamme/four_c/element_beam.py | 6 +- src/beamme/four_c/element_data.py | 13 +--- src/beamme/four_c/element_solid.py | 1 - src/beamme/four_c/function_utility.py | 17 ++--- src/beamme/four_c/header_functions.py | 14 +--- src/beamme/four_c/input_file.py | 18 +---- .../four_c/input_file_dump_functions.py | 12 +-- src/beamme/four_c/input_file_mappings.py | 3 +- src/beamme/four_c/locsys_condition.py | 5 +- src/beamme/four_c/material.py | 9 +-- src/beamme/four_c/model_importer.py | 29 +++---- src/beamme/four_c/run_four_c.py | 8 +- .../four_c/solid_shell_thickness_direction.py | 37 ++++----- src/beamme/geometric_search/arborx.py | 7 +- src/beamme/geometric_search/cython.py | 3 +- .../geometric_search/find_close_points.py | 22 +++--- src/beamme/geometric_search/scipy.py | 2 - src/beamme/geometric_search/utils.py | 2 - .../applications/beam_fibers_in_rectangle.py | 8 +- .../applications/beam_honeycomb.py | 11 +-- .../applications/beam_stent.py | 76 +++++++++---------- .../applications/beam_wire.py | 9 +-- .../mesh_creation_functions/beam_arc.py | 3 - .../mesh_creation_functions/beam_generic.py | 12 +-- .../mesh_creation_functions/beam_helix.py | 9 +-- .../mesh_creation_functions/beam_line.py | 1 - .../beam_node_continuation.py | 12 +-- .../beam_parametric_curve.py | 41 +++++----- .../mesh_creation_functions/beam_splinepy.py | 11 ++- .../mesh_creation_functions/nurbs_generic.py | 9 +-- .../nurbs_geometries.py | 35 ++++----- .../mesh_creation_functions/nurbs_utils.py | 3 - src/beamme/space_time/beam_to_space_time.py | 2 - src/beamme/utils/environment.py | 11 +-- src/beamme/utils/nodes.py | 24 +++--- .../beamme/core/test_beamme_core_coupling.py | 9 +-- .../core/test_beamme_core_geometry_set.py | 20 ++--- tests/beamme/core/test_beamme_core_mesh.py | 16 ++-- .../core/test_beamme_core_mesh_utils.py | 1 - tests/beamme/core/test_beamme_core_node.py | 1 - .../beamme/core/test_beamme_core_rotations.py | 33 +++----- .../test_beamme_cosserat_curve.py | 6 +- ...amme_four_c_beam_interaction_conditions.py | 4 +- .../four_c/test_beamme_four_c_dbc_monitor.py | 6 +- .../test_beamme_four_c_function_utility.py | 4 +- .../four_c/test_beamme_four_c_material.py | 7 -- .../four_c/test_beamme_four_c_run_four_c.py | 3 +- .../test_beamme_geometric_search_utils.py | 2 - ...me_mesh_creation_functions_beam_generic.py | 27 ++----- ...eation_functions_beam_node_continuation.py | 9 +-- ...reation_functions_beam_parametric_curve.py | 10 +-- ...e_mesh_creation_functions_beam_splinepy.py | 5 +- ...e_mesh_creation_functions_nurbs_generic.py | 5 +- ...mme_mesh_creation_functions_nurbs_utils.py | 17 ++--- .../test_beamme_utils_data_structures.py | 1 - .../utils/test_beamme_utils_environment.py | 7 -- tests/beamme/utils/test_beamme_utils_nodes.py | 3 - tests/conftest.py | 52 +++++-------- tests/conftest_performance_tests.py | 9 +-- tests/conftest_result_comparison.py | 18 ++--- tests/conftest_test_object_generators.py | 43 ++++------- tests/create_test_models.py | 20 ++--- tests/integration/test_integration_abaqus.py | 6 +- .../test_integration_core_geometry_set.py | 5 +- .../integration/test_integration_core_mesh.py | 28 +++---- ...est_integration_core_mesh_visualization.py | 4 - .../test_integration_cosserat_curve.py | 7 -- tests/integration/test_integration_four_c.py | 32 +++----- ...tion_four_c_beam_interaction_conditions.py | 5 +- .../test_integration_four_c_beam_potential.py | 5 +- .../test_integration_four_c_element_beam.py | 7 +- ...est_integration_four_c_header_functions.py | 12 +-- .../test_integration_four_c_input_file.py | 17 ++--- ...est_integration_four_c_locsys_condition.py | 6 +- .../test_integration_four_c_material.py | 8 +- .../test_integration_four_c_model_importer.py | 23 ++---- .../test_integration_four_c_simulation.py | 42 ++++------ ..._four_c_solid_shell_thickness_direction.py | 9 +-- .../test_integration_geometric_search.py | 24 +++--- ...sh_creation_functions_beam_applications.py | 9 +-- ...ration_mesh_creation_functions_beam_arc.py | 19 ++--- ...on_mesh_creation_functions_beam_generic.py | 16 ++-- ...tion_mesh_creation_functions_beam_helix.py | 4 - ...eation_functions_beam_node_continuation.py | 1 - ...reation_functions_beam_parametric_curve.py | 20 ++--- ...n_mesh_creation_functions_beam_splinepy.py | 1 - ...tegration_mesh_creation_functions_nurbs.py | 18 ----- .../test_integration_space_time.py | 13 +--- .../test_other_create_cubit_input_files.py | 11 +-- tests/other/test_other_create_input_files.py | 1 - tests/other/test_other_examples.py | 5 +- tests/performance/test_performance_beamme.py | 43 +++-------- ...reation_functions_beam_parametric_curve.py | 12 ++- .../test_performance_space_time.py | 5 +- utils/check_python_imports.py | 18 ++--- utils/logo.py | 15 +--- utils/validate_4C_files.py | 5 +- website/docs/prepare_docs.py | 4 +- 128 files changed, 579 insertions(+), 1154 deletions(-) diff --git a/.typos.toml b/.typos.toml index 0d8d157f..c83ce080 100644 --- a/.typos.toml +++ b/.typos.toml @@ -1,4 +1,7 @@ # exlude the following words from the typos pre-commit hook +[default.extend-words] +DISCRET = "DISCRET" # in 4C yaml input files + [default.extend-identifiers] _NDArray = "_NDArray" diff --git a/examples/example_1_finite_rotations.ipynb b/examples/example_1_finite_rotations.ipynb index ba2e474e..54307be5 100644 --- a/examples/example_1_finite_rotations.ipynb +++ b/examples/example_1_finite_rotations.ipynb @@ -419,7 +419,7 @@ "\n", "rotation = Rotation([1, 2, 3], np.pi / 6.0)\n", "lambda_sr = smallest_rotation(rotation, [1, 0.5, 0])\n", - "print(f\"First basis vector of lambda_sr: {lambda_sr * [1,0,0]}\")" + "print(f\"First basis vector of lambda_sr: {lambda_sr * [1, 0, 0]}\")" ] }, { diff --git a/examples/utils/example_1_utils.py b/examples/utils/example_1_utils.py index 2e0990f6..7ebccb13 100644 --- a/examples/utils/example_1_utils.py +++ b/examples/utils/example_1_utils.py @@ -41,7 +41,6 @@ def print_rotation_matrix(name, rotation): def add_cube_plot(plotter, row, col, rotation, text, *, plot_outlines=True): """Add a cube to the plotter.""" - plotter.subplot(row, col) # Define and optionally plot the original cube @@ -114,15 +113,13 @@ def __init__(self, *args, **kwargs): def __enter__(self): """Return the plotter with the given arguments.""" - self.plotter = pv.Plotter(*self.args, **self.kwargs) return self.plotter def __exit__(self, exc_type, exc_value, traceback): """When exiting the with statement, call this function. - We show the plotter (except during testing and we reset the - console print out). + We show the plotter (except during testing and we reset the console print out). """ if not is_testing(): self.plotter.show() diff --git a/src/beamme/abaqus/__init__.py b/src/beamme/abaqus/__init__.py index 2c4866d1..f06f3a1b 100644 --- a/src/beamme/abaqus/__init__.py +++ b/src/beamme/abaqus/__init__.py @@ -19,5 +19,4 @@ # 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. -"""This module defines classes and functions to create an Abaqus beam input -file.""" +"""This module defines classes and functions to create an Abaqus beam input file.""" diff --git a/src/beamme/abaqus/beam.py b/src/beamme/abaqus/beam.py index e7f1bae6..72a6b773 100644 --- a/src/beamme/abaqus/beam.py +++ b/src/beamme/abaqus/beam.py @@ -26,8 +26,9 @@ def generate_abaqus_beam(beam_type: str): - """Return a class representing a beam in Abaqus. This class can be used in - the standard mesh generation functions. + """Return a class representing a beam in Abaqus. + + This class can be used in the standard mesh generation functions. Args: beam_type: Abaqus identifier for this beam element. For more details, @@ -37,7 +38,6 @@ def generate_abaqus_beam(beam_type: str): A class representing the Abaqus beam element. The class inherits from the BeamX class, depending on the number of nodes. """ - if not beam_type[0].lower() == "b": raise TypeError("Could not identify the given Abaqus beam element") diff --git a/src/beamme/abaqus/input_file.py b/src/beamme/abaqus/input_file.py index bda169bb..43bf241a 100644 --- a/src/beamme/abaqus/input_file.py +++ b/src/beamme/abaqus/input_file.py @@ -19,8 +19,7 @@ # 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. -"""This module defines the class that is used to create an input file for -Abaqus.""" +"""This module defines the class that is used to create an input file for Abaqus.""" from enum import Enum as _Enum from enum import auto as _auto @@ -51,7 +50,6 @@ def set_i_global(data_list, *, start_index=0): start_index: int Starting index of the numbering """ - # A check is performed that every entry in data_list is unique. if len(data_list) != len(set(data_list)): raise ValueError("Elements in data_list are not unique!") @@ -62,8 +60,7 @@ def set_i_global(data_list, *, start_index=0): def get_set_lines(set_type, items, name): - """Get the Abaqus input file lines for a set of items (max 16 items per - row)""" + """Get the Abaqus input file lines for a set of items (max 16 items per row)""" max_entries_per_line = 16 lines = ["*{}, {}={}".format(set_type, set_type.lower(), name)] set_ids = [item.i_global + 1 for item in items] @@ -119,7 +116,6 @@ def write_input_file( normal_definition: AbaqusBeamNormalDefinition How the beam cross-section should be defined. """ - # Write the input file to disk with open(file_path, "w") as input_file: input_file.write(self.get_input_file_string(normal_definition)) @@ -127,7 +123,6 @@ def write_input_file( def get_input_file_string(self, normal_definition): """Generate the string for the Abaqus input file.""" - # Assign global indices to all materials set_i_global(self.mesh.materials) @@ -144,9 +139,8 @@ def get_input_file_string(self, normal_definition): return "\n".join(input_file_lines) def calculate_cross_section_normal_data(self, normal_definition): - """Evaluate all data that is required to fully specify the cross- - section orientation in Abaqus. The evaluated data is stored in the - elements. + """Evaluate all data that is required to fully specify the cross- section + orientation in Abaqus. The evaluated data is stored in the elements. For more information see the Abaqus documentation on: "Beam element cross-section orientation" @@ -210,7 +204,6 @@ def normalize(vector): def get_nodes_lines(self): """Get the lines for the input file that represent the nodes.""" - # The nodes require postprocessing, as we have to identify coupled nodes in Abaqus. # Internally in Abaqus, coupled nodes are a single node with different normals for the # connected element. Therefore, for nodes which are coupled to each other, we keep the @@ -244,7 +237,6 @@ def get_nodes_lines(self): def get_element_lines(self): """Get the lines for the input file that represent the elements.""" - # Sort the elements after their types. element_types = {} for element in self.mesh.elements: @@ -289,9 +281,8 @@ def get_element_lines(self): return element_lines def get_material_lines(self): - """Get the lines for the input file that represent the element sets - with the same material.""" - + """Get the lines for the input file that represent the element sets with the + same material.""" materials = {} for element in self.mesh.elements: element_material = element.material @@ -309,7 +300,6 @@ def get_material_lines(self): def get_set_lines(self): """Add lines to the input file that represent node and element sets.""" - input_file_lines = [] for point_set in self.mesh.geometry_sets[_bme.geo.point]: if point_set.name is None: diff --git a/src/beamme/abaqus/material.py b/src/beamme/abaqus/material.py index f3e4cb3c..04bf0a0a 100644 --- a/src/beamme/abaqus/material.py +++ b/src/beamme/abaqus/material.py @@ -28,9 +28,10 @@ class AbaqusBeamMaterial(_MaterialBeamBase): """A class representing an Abaqus beam material.""" def __init__(self, name: str): - """Initialize the material. For now it is only supported to state the - name of the resulting element set here. The material and cross-section - lines in the input file have to be defined manually. + """Initialize the material. + + For now it is only supported to state the name of the resulting element set here. + The material and cross-section lines in the input file have to be defined manually. Args ---- diff --git a/src/beamme/core/__init__.py b/src/beamme/core/__init__.py index aee561a7..a4272322 100644 --- a/src/beamme/core/__init__.py +++ b/src/beamme/core/__init__.py @@ -19,5 +19,4 @@ # 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. -"""This module defines classes and functions to create and edit a 4C input -file.""" +"""This module defines classes and functions to create and edit a 4C input file.""" diff --git a/src/beamme/core/base_mesh_item.py b/src/beamme/core/base_mesh_item.py index 498c929f..eeb2ea2f 100644 --- a/src/beamme/core/base_mesh_item.py +++ b/src/beamme/core/base_mesh_item.py @@ -19,13 +19,14 @@ # 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. -"""This module implements the base class for boundary conditions, functions, -geometry sets and materials.""" +"""This module implements the base class for boundary conditions, functions, geometry +sets and materials.""" + +# This comment avoids docformatter's issue: https://github.com/PyCQA/docformatter/issues/350 class BaseMeshItem: - """Base class for boundary conditions, functions, geometry sets and - materials.""" + """Base class for boundary conditions, functions, geometry sets and materials.""" def __init__(self, data: dict | None = None): """Create the base object. @@ -34,7 +35,6 @@ def __init__(self, data: dict | None = None): data: General data to be stored for this item. Defaults to and empty dictionary. """ - if data is not None: self.data = data else: diff --git a/src/beamme/core/boundary_condition.py b/src/beamme/core/boundary_condition.py index 19ec35db..e4df300c 100644 --- a/src/beamme/core/boundary_condition.py +++ b/src/beamme/core/boundary_condition.py @@ -48,15 +48,13 @@ def __init__( geometry_set: Geometry that this boundary condition acts on. bc_type: Type of the boundary condition. """ - super().__init__(**kwargs) self.bc_type = bc_type self.geometry_set = geometry_set class BoundaryCondition(BoundaryConditionBase): - """This object represents one boundary condition, e.g., Dirichlet, Neumann, - ...""" + """This object represents one boundary condition, e.g., Dirichlet, Neumann, ...""" def __init__( self, @@ -78,7 +76,6 @@ def __init__( double_nodes: Depending on this parameter, it will be checked if point Neumann conditions do contain nodes at the same spatial positions. """ - super().__init__(geometry_set, bc_type, data=data, **kwargs) self.double_nodes = double_nodes @@ -86,14 +83,13 @@ def __init__( self.check() def check(self): - """Check for point Neumann boundaries that there is not a double Node - in the set. + """Check for point Neumann boundaries that there is not a double Node in the + set. - Duplicate nodes in a point Neumann boundary condition can lead - to the same force being applied multiple times at the same - spatial position, which results in incorrect load application. + Duplicate nodes in a point Neumann boundary condition can lead to the same force + being applied multiple times at the same spatial position, which results in + incorrect load application. """ - if self.double_nodes is _bme.double_nodes.keep: return diff --git a/src/beamme/core/conf.py b/src/beamme/core/conf.py index fdd0f043..c3c04abd 100644 --- a/src/beamme/core/conf.py +++ b/src/beamme/core/conf.py @@ -59,8 +59,7 @@ class BoundaryCondition(_Enum): point_coupling_indirect = _auto() def is_point_coupling_pairwise(self) -> bool: - """Check whether the point coupling condition should be applied - pairwise. + """Check whether the point coupling condition should be applied pairwise. Returns: bool: True if the coupling should be applied individually between pairs of nodes, @@ -120,7 +119,6 @@ def __init__(self): def set_default_values(self): """Set the configuration to the default values.""" - # Set the epsilons for comparison of different types of values. self.eps_quaternion = 1e-10 self.eps_knot_vector = 1e-10 diff --git a/src/beamme/core/container.py b/src/beamme/core/container.py index d049551b..afd6ac99 100644 --- a/src/beamme/core/container.py +++ b/src/beamme/core/container.py @@ -19,17 +19,18 @@ # 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. -"""This module implements containers to manage boundary conditions and geometry -sets in one object.""" +"""This module implements containers to manage boundary conditions and geometry sets in +one object.""" + +# This comment avoids docformatter's issue: https://github.com/PyCQA/docformatter/issues/350 class ContainerBase(dict): """A base class for containers.""" def append(self, key, item): - """Append item to this container and check if the item is already in - the list corresponding to key.""" - + """Append item to this container and check if the item is already in the list + corresponding to key.""" type_ok = False for item_type in self.item_types: if isinstance(item, item_type): @@ -49,7 +50,6 @@ def append(self, key, item): def extend(self, container): """Add all items of another container to this container.""" - if not isinstance(container, self.__class__): raise TypeError( f"Only containers of type {self.__class__} can be merged here, you tried " diff --git a/src/beamme/core/coupling.py b/src/beamme/core/coupling.py index 63578abc..353de5ef 100644 --- a/src/beamme/core/coupling.py +++ b/src/beamme/core/coupling.py @@ -57,7 +57,6 @@ def __init__( check_overlapping_nodes: If all nodes of this coupling condition have to be at the same physical position. """ - if isinstance(geometry, _GeometrySetBase): pass elif isinstance(geometry, list): @@ -78,9 +77,8 @@ def __init__( self.check() def check(self): - """Check that all nodes that are coupled have the same position - (depending on the check_overlapping_nodes parameter).""" - + """Check that all nodes that are coupled have the same position (depending on + the check_overlapping_nodes parameter).""" if not self.check_overlapping_nodes: return @@ -119,7 +117,6 @@ def coupling_factory( - If the selected coupling type requires pairwise coupling (e.g., due to solver restrictions), multiple coupling objects are returned, each coupling a pair of nodes accordingly. """ - if not coupling_type.is_point_coupling_pairwise(): return [Coupling(geometry, coupling_type, coupling_dof_type, **kwargs)] else: diff --git a/src/beamme/core/element.py b/src/beamme/core/element.py index f1338e6c..15a8e4ed 100644 --- a/src/beamme/core/element.py +++ b/src/beamme/core/element.py @@ -55,7 +55,6 @@ def flip(self): def replace_node(self, old_node, new_node): """Replace old_node with new_node.""" - # Look for old_node and replace it. If it is not found, throw error. for i, node in enumerate(self.nodes): if node == old_node: diff --git a/src/beamme/core/element_beam.py b/src/beamme/core/element_beam.py index df6b87cb..75a4b72d 100644 --- a/src/beamme/core/element_beam.py +++ b/src/beamme/core/element_beam.py @@ -49,7 +49,6 @@ def __init__(self, material=None, nodes=None): @classmethod def get_coupling_dict(cls, coupling_dof_type): """Return the dict to couple this beam to another beam.""" - match coupling_dof_type: case _bme.coupling_dof.joint: if cls.coupling_joint_dict is None: @@ -81,7 +80,6 @@ def generate_beam_class(n_nodes: int): Returns: A beam object that has n_nodes along the centerline. """ - # Define the class variable responsible for creating the nodes. nodes_create = _np.linspace(-1, 1, num=n_nodes) diff --git a/src/beamme/core/function.py b/src/beamme/core/function.py index 54e41a8e..defd4466 100644 --- a/src/beamme/core/function.py +++ b/src/beamme/core/function.py @@ -34,10 +34,8 @@ def __init__(self, function_data) -> None: self.i_global: None | int = None def __deepcopy__(self, memo): - """When deepcopy is called on a mesh, we do not want the same functions - to be copied, as this will result in multiple equal functions in the - input file.""" - + """When deepcopy is called on a mesh, we do not want the same functions to be + copied, as this will result in multiple equal functions in the input file.""" # Add this object to the memo dictionary. memo[id(self)] = self diff --git a/src/beamme/core/geometry_set.py b/src/beamme/core/geometry_set.py index e8b3d456..207343c5 100644 --- a/src/beamme/core/geometry_set.py +++ b/src/beamme/core/geometry_set.py @@ -19,8 +19,7 @@ # 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. -"""This module implements a basic class to manage geometry in the input -file.""" +"""This module implements a basic class to manage geometry in the input file.""" from typing import KeysView as _KeysView from typing import Sequence as _Sequence @@ -57,7 +56,6 @@ def check_replaced_nodes(self) -> None: We need to do this for explicitly contained nodes in this set. """ - explicit_nodes_in_this_set = self.get_node_dict() nodes_replaced = { current_node.get_target_node(): None @@ -67,8 +65,8 @@ def check_replaced_nodes(self) -> None: explicit_nodes_in_this_set.update(nodes_replaced) def get_node_dict(self) -> dict[_Node, None]: - """Determine the explicitly added nodes for this set, i.e., nodes - contained in elements are not returned. + """Determine the explicitly added nodes for this set, i.e., nodes contained in + elements are not returned. Returns: A dictionary containing the explicitly added nodes for this set. @@ -103,8 +101,8 @@ def get_all_nodes(self) -> list[_Node]: ) def __add__(self, other): - """Create a new geometry set with the combined geometries from this set - and the other set. + """Create a new geometry set with the combined geometries from this set and the + other set. Args: other: Geometry set to be added to this one. This has to be of the same geometry type as this set. @@ -129,7 +127,6 @@ def __init__( Args: geometry: Geometry entries to be contained in this set. """ - # This is ok, we check every single type in the add method if isinstance(geometry, list): geometry_type = self._get_geometry_type(geometry[0]) @@ -152,7 +149,6 @@ def _get_geometry_type( Returns: Geometry type of the geometry set. """ - if isinstance(item, _Node): return _bme.geo.point elif isinstance(item, _Beam): @@ -170,7 +166,6 @@ def add( self, item: _Node | _Element | _Sequence[_Node | _Element] | "GeometrySet" ) -> None: """Add geometry item(s) to this object.""" - if isinstance(item, list): for sub_item in item: self.add(sub_item) @@ -191,8 +186,8 @@ def add( raise TypeError(f"Got unexpected geometry type {type(item)}") def get_node_dict(self) -> dict[_Node, None]: - """Determine the explicitly added nodes for this set, i.e., nodes - contained in elements for element sets are not returned. + """Determine the explicitly added nodes for this set, i.e., nodes contained in + elements for element sets are not returned. Thus, for non-point sets an empty dict is returned. @@ -229,7 +224,6 @@ def get_all_nodes(self) -> list[_Node]: Returns: A list containing all associated nodes. """ - if self.geometry_type is _bme.geo.point: return list( _cast(_KeysView[_Node], self.geometry_objects[_bme.geo.point].keys()) @@ -259,8 +253,8 @@ def get_geometry_objects(self) -> _Sequence[_Node | _Element]: return list(self.geometry_objects[self.geometry_type].keys()) def copy(self) -> "GeometrySet": - """Create a shallow copy of this object, the reference to the nodes - will be the same, but the containers storing them will be copied. + """Create a shallow copy of this object, the reference to the nodes will be the + same, but the containers storing them will be copied. Returns: A shallow copy of the geometry set. @@ -284,7 +278,6 @@ def __init__( and input file depend on that type. nodes: Node(s) or list of nodes to be added to this geometry set. """ - if geometry_type not in _bme.geo: raise TypeError(f"Expected geometry enum, got {geometry_type}") @@ -299,7 +292,6 @@ def add(self, value: "_Node | list[_Node] | GeometrySetNodes") -> None: Args: nodes: Node(s) or list of nodes to be added to this geometry set. """ - if isinstance(value, list): # Loop over items and check if they are either Nodes or integers. # This improves the performance considerably when large list of @@ -359,8 +351,8 @@ def get_all_nodes(self) -> list[_Node]: return list(self.get_node_dict().keys()) def copy(self) -> "GeometrySetNodes": - """Create a shallow copy of this object, the reference to the nodes - will be the same, but the containers storing them will be copied. + """Create a shallow copy of this object, the reference to the nodes will be the + same, but the containers storing them will be copied. Returns: A shallow copy of the geometry set. @@ -374,15 +366,13 @@ def copy(self) -> "GeometrySetNodes": class GeometryName(dict): """Group node geometry sets together. - This is mainly used for export from mesh functions. The sets can be - accessed by a unique name. There is no distinction between different - types of geometry, every name can only be used once -> use - meaningful names. + This is mainly used for export from mesh functions. The sets can be accessed by a + unique name. There is no distinction between different types of geometry, every name + can only be used once -> use meaningful names. """ def __setitem__(self, key, value): """Set a geometry set in this container.""" - if not isinstance(key, str): raise TypeError(f"Expected string, got {type(key)}!") if isinstance(value, GeometrySetBase): @@ -392,8 +382,7 @@ def __setitem__(self, key, value): class GeometrySetContainer(_ContainerBase): - """A class to group geometry sets together with the key being the geometry - type.""" + """A class to group geometry sets together with the key being the geometry type.""" def __init__(self, *args, **kwargs): """Initialize the container and create the default keys in the map.""" @@ -405,9 +394,8 @@ def __init__(self, *args, **kwargs): self[geometry_key] = [] def copy(self): - """When creating a copy of this object, all lists in this object will - be copied also.""" - + """When creating a copy of this object, all lists in this object will be copied + also.""" # Create a new geometry set container. copy = GeometrySetContainer() diff --git a/src/beamme/core/material.py b/src/beamme/core/material.py index 8b8554d0..780263de 100644 --- a/src/beamme/core/material.py +++ b/src/beamme/core/material.py @@ -33,10 +33,8 @@ def __init__(self, **kwargs): super().__init__(**kwargs) def __deepcopy__(self, memo): - """When deepcopy is called on a mesh, we do not want the materials to - be copied, as this will result in multiple equal materials in the input - file.""" - + """When deepcopy is called on a mesh, we do not want the materials to be copied, + as this will result in multiple equal materials in the input file.""" # Add this object to the memo dictionary. memo[id(self)] = self @@ -58,7 +56,6 @@ def __init__( **kwargs, ): """Set the material values that all beams have.""" - super().__init__(**kwargs) self.radius = radius @@ -73,8 +70,7 @@ def __init__( self.polar = None def calc_area_stiffness(self): - """Calculate the relevant stiffness terms and the area for the given - beam.""" + """Calculate the relevant stiffness terms and the area for the given beam.""" area = 4 * self.radius**2 * _np.pi * 0.25 mom2 = self.radius**4 * _np.pi * 0.25 mom3 = mom2 diff --git a/src/beamme/core/mesh.py b/src/beamme/core/mesh.py index 26b103d6..b54b8658 100644 --- a/src/beamme/core/mesh.py +++ b/src/beamme/core/mesh.py @@ -19,8 +19,8 @@ # 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. -"""This module defines the Mesh class, which holds the content (nodes, -elements, sets, ...) for a meshed geometry.""" +"""This module defines the Mesh class, which holds the content (nodes, elements, sets, +...) for a meshed geometry.""" import copy as _copy import warnings as _warnings @@ -73,12 +73,11 @@ class Mesh: - """A class that contains a full mesh, i.e. Nodes, Elements, Boundary - Conditions, Sets, Couplings, Materials and Functions.""" + """A class that contains a full mesh, i.e. Nodes, Elements, Boundary Conditions, + Sets, Couplings, Materials and Functions.""" def __init__(self): """Initialize all empty containers.""" - self.nodes = [] self.elements = [] self.materials = [] @@ -96,7 +95,6 @@ def get_base_mesh_item_type(item): Args: item: The object we want to get the base type from. """ - for cls in ( Mesh, _Function, @@ -114,12 +112,10 @@ def get_base_mesh_item_type(item): def add(self, *args, **kwargs): """Add an item to this mesh, depending on its type. - If an list is given each list element is added with this - function. If multiple arguments are given, each one is - individually added with this function. Keyword arguments are - passed through to the adding function. + If an list is given each list element is added with this function. If multiple + arguments are given, each one is individually added with this function. Keyword + arguments are passed through to the adding function. """ - match len(args): case 0: raise ValueError("At least one argument is required!") @@ -150,7 +146,6 @@ def add(self, *args, **kwargs): def add_mesh(self, mesh): """Add the content of another mesh to this mesh.""" - # Add each item from mesh to self. self.add(mesh.nodes) self.add(mesh.elements) @@ -202,8 +197,8 @@ def add_geometry_set(self, geometry_set): def add_geometry_name(self, geometry_name): """Add a set of geometry sets to this mesh. - Sort by the keys here to create a deterministic ordering, - especially for testing purposes + Sort by the keys here to create a deterministic ordering, especially for testing + purposes """ keys = list(geometry_name.keys()) keys.sort() @@ -227,7 +222,6 @@ def add_list(self, add_list: _List, **kwargs) -> None: For all other types of items, we add each element individually via the Mesh.add method. """ - types = {self.get_base_mesh_item_type(item) for item in add_list} if len(types) > 1: raise TypeError( @@ -239,8 +233,7 @@ def add_list(self, add_list: _List, **kwargs) -> None: def extend_internal_list(self_list: _List, new_list: _List) -> None: """Extend an internal list with the new list. - It is checked that the final list does not have - duplicate entries. + It is checked that the final list does not have duplicate entries. """ self_list.extend(new_list) if not len(set(self_list)) == len(self_list): @@ -263,7 +256,6 @@ def replace_nodes(self, replace_nodes: dict[_Node, _Node]) -> None: replace_nodes: A dictionary that maps source nodes to target nodes. The source nodes will be replaced with the target nodes in the mesh. """ - # Nothing to do if the replacement map is empty. if len(replace_nodes) == 0: return @@ -300,8 +292,8 @@ def replace_nodes(self, replace_nodes: dict[_Node, _Node]) -> None: def get_unique_geometry_sets( self, *, coupling_sets: bool = True ) -> _GeometrySetContainer: - """Return a geometry set container that contains geometry sets - explicitly added to the mesh, as well as sets for boundary conditions. + """Return a geometry set container that contains geometry sets explicitly added + to the mesh, as well as sets for boundary conditions. The i_global values are set in the returned geometry sets. @@ -312,7 +304,6 @@ def get_unique_geometry_sets( Returns: A geometry set container that contains all geometry sets of this mesh. """ - # Make a copy of the sets in this mesh. mesh_sets = self.geometry_sets.copy() @@ -341,7 +332,6 @@ def get_named_geometry_sets(self) -> dict[str, _GeometrySetBase]: object. Only named geometry sets are returned. This function throws an error if there are multiple geometry sets with the same name. """ - named_geometry_sets = {} for geometry_set_list in self.get_unique_geometry_sets().values(): for geometry_set in geometry_set_list: @@ -384,7 +374,6 @@ def rotate( only_rotate_triads: If this is true, the nodal positions are not changed. """ - # Get array with all quaternions for the nodes. rot1 = _get_nodal_quaternions(self.nodes) @@ -486,11 +475,12 @@ def reflect(self, normal_vector, origin=None, flip_beams: bool = False) -> None: def wrap_around_cylinder( self, radius: float | None = None, advanced_warning: bool = True ) -> None: - """Wrap the geometry around a cylinder. The y-z plane gets morphed into - the z-axis of symmetry. If all nodes are on the same y-z plane, the - radius of the created cylinder is the x coordinate of that plane. If - the nodes are not on the same y-z plane, the radius has to be given - explicitly. + """Wrap the geometry around a cylinder. + + The y-z plane gets morphed into the z-axis of symmetry. If all nodes are + on the same y-z plane, the radius of the created cylinder is the x coordinate + of that plane. If the nodes are not on the same y-z plane, the radius has to + be given explicitly. Args: radius: If this value is given AND not all nodes are on the same y-z @@ -500,7 +490,6 @@ def wrap_around_cylinder( to the y-z or x-z plane. This is computationally expensive, but in most cases (up to 100,000 elements) this check can be left activated. """ - pos = _get_nodal_coordinates(self.nodes) quaternions = _np.zeros([len(self.nodes), 4]) @@ -599,8 +588,7 @@ def couple_nodes( coupling_type=_bme.bc.point_coupling, coupling_dof_type=_bme.coupling_dof.fix, ) -> None: - """Search through nodes and connect all nodes with the same - coordinates. + """Search through nodes and connect all nodes with the same coordinates. Args: nodes: @@ -619,7 +607,6 @@ def couple_nodes( `bme.coupling_dof.joint`: Fix all positional DOFs of the nodes together. """ - # Check that a coupling BC is given. if coupling_type not in ( _bme.bc.point_coupling, @@ -760,7 +747,6 @@ def get_mesh_representation( nurbs_patch_to_i_global: A dictionary that maps each NURBS patch to the global ID of that patch. """ - if material_to_i_global is None: material_to_i_global = {} @@ -974,7 +960,6 @@ def get_vtu_representation(self) -> _pv.UnstructuredGrid: Returns: A pyvista UnstructuredGrid object that represents this mesh. """ - # Get mesh representation. mesh_representation, _, _, _ = self.get_mesh_representation() @@ -1071,7 +1056,6 @@ def display_pyvista( parallel_projection: bool Flag to change camera view to parallel projection. """ - grid = self.get_vtu_representation() plotter = _pv.Plotter() diff --git a/src/beamme/core/mesh_representation.py b/src/beamme/core/mesh_representation.py index cbb20fd0..76da9006 100644 --- a/src/beamme/core/mesh_representation.py +++ b/src/beamme/core/mesh_representation.py @@ -127,8 +127,7 @@ def _convert_argument_numpy( default_shape: tuple[int, ...], dtype: type, ) -> _NDArray: - """Convert given array arguments so we can store them in this - object.""" + """Convert given array arguments so we can store them in this object.""" if argument is None: return _np.empty(default_shape, dtype=dtype) else: @@ -137,8 +136,8 @@ def _convert_argument_numpy( def _filter_none_entries( argument: dict[str, _NDArray | None] | None, expected_size: int ) -> dict[str, _NDArray]: - """Check if a dictionary is given, and if so, filter None entries - from it.""" + """Check if a dictionary is given, and if so, filter None entries from + it.""" if argument is None: return {} else: @@ -252,8 +251,7 @@ def connectivity_iterator( yield self.cell_connectivity[start:end] def data_iterator(self, data_field: str, data_name: str) -> _Iterable: - """This method returns an iterator for the given data field and data - name. + """This method returns an iterator for the given data field and data name. This is useful, when looping over the data, as accessing the data field in each loop iteration can be expensive. If the data field is not present, a iterator @@ -297,7 +295,6 @@ def offset_indices( material_offset: The offset to add to the material IDs. geometry_set_offset: The offset to add to the geometry set IDs. """ - if element_type_id_offset is not None: if "element_type_id" in self.cell_data: self.cell_data["element_type_id"] += element_type_id_offset @@ -336,8 +333,7 @@ def get_pyvista_grid( point_data_fields: bool | list[str] = False, add_geometry_sets: bool = False, ) -> _pv.UnstructuredGrid: - """Return a PyVista UnstructuredGrid representation of this mesh - representation. + """Return a PyVista UnstructuredGrid representation of this mesh representation. Args: cell_data_fields: The cell data fields to add to the grid. This can be @@ -453,8 +449,8 @@ def _merge_data_dicts( """Merge the given data dictionaries and fill in non-existing data.""" def _ensure_array_size(size: int, reference_array: _NDArray) -> _NDArray: - """Create an empty array that matches the columns of the reference - array and has the given size, i.e., number of rows.""" + """Create an empty array that matches the columns of the reference array and + has the given size, i.e., number of rows.""" new_shape = reference_array.shape if len(new_shape) == 1: new_shape = (size,) diff --git a/src/beamme/core/mesh_utils.py b/src/beamme/core/mesh_utils.py index 73d511c1..f91727eb 100644 --- a/src/beamme/core/mesh_utils.py +++ b/src/beamme/core/mesh_utils.py @@ -41,8 +41,8 @@ def get_coupled_nodes_to_master_map( mesh: _Mesh, *, assign_i_global: bool = False ) -> _Tuple[_Dict[_Node, _Node], _List[_Node]]: - """Get a mapping of nodes in a mesh that should be "replaced" because they - are coupled via a joint. + """Get a mapping of nodes in a mesh that should be "replaced" because they are + coupled via a joint. In some finite element (FE) solvers, nodes coupled via joints are resolved by assigning a "master" node to represent the joint. This function identifies @@ -64,7 +64,6 @@ def get_coupled_nodes_to_master_map( A list containing all unique nodes in the mesh, i.e., all nodes which are not coupled and the master nodes. """ - # Get a dictionary that maps the "replaced" nodes to the "master" ones replaced_node_to_master_map = {} for coupling in mesh.boundary_conditions[_bme.bc.point_coupling, _bme.geo.point]: @@ -105,8 +104,8 @@ def apply_nodal_coupling_to_mesh_representation( geometry_sets_to_i_global: _Dict[_GeometrySetBase, int], coupling_conditions: list[_Coupling], ): - """Modify a mesh representation such that coupled nodes are represented by - a single node. + """Modify a mesh representation such that coupled nodes are represented by a single + node. Args: mesh_representation: The mesh representation where coupling nodes should @@ -116,7 +115,6 @@ def apply_nodal_coupling_to_mesh_representation( coupling_conditions: A list of coupling conditions that define which nodes should be coupled. """ - # Get a dictionary that maps the "replaced" nodes to the "master" ones replaced_node_to_master_map = {} for coupling in coupling_conditions: diff --git a/src/beamme/core/node.py b/src/beamme/core/node.py index 8d3f1a63..9dc8f690 100644 --- a/src/beamme/core/node.py +++ b/src/beamme/core/node.py @@ -62,7 +62,6 @@ def get_target_node(self) -> "Node": If this node has a linked target node, then this target node is returned, otherwise this node is returned. """ - if self.target_node is None: return self else: @@ -74,8 +73,8 @@ def unlink(self) -> None: class NodeCosserat(Node): - """This object represents a Cosserat node in the mesh, i.e., it contains - three positions and three rotations.""" + """This object represents a Cosserat node in the mesh, i.e., it contains three + positions and three rotations.""" node_type = _bme.node_type.cosserat @@ -111,7 +110,6 @@ def rotate( only_rotate_triads: If True, only the rotation of this node will be affected, the position of the node stays the same. """ - self.rotation = rotation * self.rotation # Rotate the positions (around origin). diff --git a/src/beamme/core/nurbs_patch.py b/src/beamme/core/nurbs_patch.py index 7eb4d505..7dc6e087 100644 --- a/src/beamme/core/nurbs_patch.py +++ b/src/beamme/core/nurbs_patch.py @@ -65,8 +65,8 @@ def get_nurbs_dimension(self) -> int: return n_knots def get_number_of_control_points_per_dir(self) -> list[int]: - """Determine the number of control points in each parameter direction - of the patch. + """Determine the number of control points in each parameter direction of the + patch. Returns: List of control points per direction. @@ -87,7 +87,6 @@ def get_non_empty_knot_span_indices(self) -> list[list[int]]: List of lists with the indices of the non-empty knot spans in each parameter direction. """ - non_empty_knot_spans_indices: list[list[int]] = [ [] for _ in range(self.get_nurbs_dimension()) ] @@ -105,13 +104,12 @@ def get_non_empty_knot_span_indices(self) -> list[list[int]]: return non_empty_knot_spans_indices def get_number_of_elements(self) -> int: - """Determine the number of elements in this patch by checking the - amount of nonzero knot spans in the knot vector. + """Determine the number of elements in this patch by checking the amount of + nonzero knot spans in the knot vector. Returns: Number of elements for this patch. """ - non_empty_knot_spans_indices = self.get_non_empty_knot_span_indices() num_elements_dir = [len(indices) for indices in non_empty_knot_spans_indices] total_num_elements = _np.prod(num_elements_dir) @@ -123,8 +121,8 @@ def get_knot_span_iterator(self) -> _Iterator[tuple[int, ...]]: @_abstractmethod def get_ids_ctrlpts(self, *args) -> list[int]: - """Compute the global indices of the control points that influence the - element defined by the given knot span.""" + """Compute the global indices of the control points that influence the element + defined by the given knot span.""" class NURBSSurface(NURBSPatch): @@ -135,7 +133,6 @@ def __init__(self, *args, **kwargs): def get_knot_span_iterator(self) -> _Iterator[tuple[int, ...]]: """Return a tuple with the knot spans for this patch.""" - non_empty_knot_spans_indices = self.get_non_empty_knot_span_indices() return ( (u, v) @@ -144,9 +141,8 @@ def get_knot_span_iterator(self) -> _Iterator[tuple[int, ...]]: ) def get_ids_ctrlpts(self, knot_span_u: int, knot_span_v: int) -> list[int]: - """Compute the global indices of the control points that influence the - element defined by the given knot span.""" - + """Compute the global indices of the control points that influence the element + defined by the given knot span.""" p, q = self.polynomial_orders ctrlpts_size_u = len(self.knot_vectors[0]) - p - 1 id_u = knot_span_u - p @@ -167,7 +163,6 @@ def __init__(self, *args, **kwargs): def get_knot_span_iterator(self) -> _Iterator[tuple[int, ...]]: """Return a tuple with the knot spans for this patch.""" - non_empty_knot_spans_indices = self.get_non_empty_knot_span_indices() return ( (u, v, w) @@ -179,9 +174,8 @@ def get_knot_span_iterator(self) -> _Iterator[tuple[int, ...]]: def get_ids_ctrlpts( self, knot_span_u: int, knot_span_v: int, knot_span_w: int ) -> list[int]: - """Compute the global indices of the control points that influence the - element defined by the given knot span.""" - + """Compute the global indices of the control points that influence the element + defined by the given knot span.""" p, q, r = self.polynomial_orders id_u = knot_span_u - p id_v = knot_span_v - q diff --git a/src/beamme/core/rotation.py b/src/beamme/core/rotation.py index 5ac73379..b9506414 100644 --- a/src/beamme/core/rotation.py +++ b/src/beamme/core/rotation.py @@ -57,7 +57,6 @@ def __init__(self, *args): - Rotation(axis, phi) Create a rotation around the vector axis with the angle phi. """ - self.q = _np.zeros(4) if len(args) == 0: @@ -108,7 +107,6 @@ def from_rotation_matrix(cls, R): R. A. Spurrier (1978): “Comment on “Singularity-free extraction of a quaternion from a direction-cosine matrix” """ - R = _np.asarray(R) q = _np.zeros(4) trace = _np.trace(R) @@ -136,10 +134,9 @@ def from_rotation_matrix(cls, R): def from_basis(cls, t1, t2): """Create the object from two basis vectors t1, t2. - t2 will be orthogonalized on t1, and t3 will be calculated with - the cross product. + t2 will be orthogonalized on t1, and t3 will be calculated with the cross + product. """ - t1_norm = _np.linalg.norm(t1) if t1_norm < _bme.eps_quaternion: raise ValueError(f"The given vector t1 can not be a zero vector, got {t1}.") @@ -160,7 +157,6 @@ def from_basis(cls, t1, t2): @classmethod def from_rotation_vector(cls, rotation_vector): """Create the object from a rotation vector.""" - q = _np.zeros(4) rotation_vector = _np.asarray(rotation_vector) phi = _np.linalg.norm(rotation_vector) @@ -178,9 +174,8 @@ def check(self): self.check_quaternion_constraint() def check_uniqueness(self): - """We always want q0 to be positive -> the range for the rotational - angle is 0 <= phi <= pi.""" - + """We always want q0 to be positive -> the range for the rotational angle is 0 + <= phi <= pi.""" if self.q[0] < 0: self.q *= -1 @@ -211,13 +206,11 @@ def get_quaternion(self): return _np.array(self.q) def get_numpy_quaternion(self): - """Return a numpy quaternion object representing this rotation - (copy).""" + """Return a numpy quaternion object representing this rotation (copy).""" return _quaternion.from_float_array(self.q) def get_rotation_vector(self): """Return the rotation vector for this object.""" - self.check() norm = _np.linalg.norm(self.q[1:]) @@ -246,10 +239,9 @@ def get_rotation_vector(self): def get_transformation_matrix(self): """Return the transformation matrix for this rotation. - The transformation matrix maps the (infinitesimal) - multiplicative rotational increments onto the additive ones. + The transformation matrix maps the (infinitesimal) multiplicative rotational + increments onto the additive ones. """ - omega = self.get_rotation_vector() omega_norm = _np.linalg.norm(omega) @@ -277,11 +269,9 @@ def get_transformation_matrix(self): def get_transformation_matrix_inv(self): """Return the inverse of the transformation matrix for this rotation. - The inverse of the transformation matrix maps the - (infinitesimal) additive rotational increments onto the - multiplicative ones. + The inverse of the transformation matrix maps the (infinitesimal) additive + rotational increments onto the multiplicative ones. """ - omega = self.get_rotation_vector() omega_norm = _np.linalg.norm(omega) @@ -306,14 +296,12 @@ def get_transformation_matrix_inv(self): def inv(self): """Return the inverse of this rotation.""" - tmp_quaternion = self.q.copy() tmp_quaternion[0] *= -1.0 return Rotation.from_quaternion(tmp_quaternion) def __mul__(self, other): """Add this rotation to another, or apply it on a vector.""" - # Check if the other object is also a rotation. if isinstance(other, Rotation): # Get quaternions of the two objects. @@ -331,7 +319,6 @@ def __mul__(self, other): def __eq__(self, other): """Check if the other rotation is equal to this one.""" - if isinstance(other, Rotation): return bool( (_np.linalg.norm(self.q - other.q) < _bme.eps_quaternion) @@ -346,7 +333,6 @@ def copy(self): def __str__(self): """String representation of object.""" - self.check() return f"Rotation:\n q0: {self.q[0]}\n q: {self.q[1:]}" @@ -364,7 +350,6 @@ def add_rotations( Returns: An array with the compound quaternions. """ - # Transpose the arrays, to work with the following code. if isinstance(rotation_10, Rotation): rot1 = rotation_10.get_quaternion().transpose() @@ -412,7 +397,6 @@ def rotate_coordinates( origin (3D vector): If this is given, the mesh is rotated about this point. Defaults to (0, 0, 0). """ - if isinstance(rotation, Rotation): rotation = rotation.get_quaternion().transpose() @@ -464,9 +448,9 @@ def rotate_coordinates( def smallest_rotation(q: Rotation, t): - """Get the triad that results from the smallest rotation (rotation without - twist) from the triad q such that the rotated first basis vector aligns - with t. For more details see Christoph Meier's dissertation chapter 2.1.2. + """Get the triad that results from the smallest rotation (rotation without twist) + from the triad q such that the rotated first basis vector aligns with t. For more + details see Christoph Meier's dissertation chapter 2.1.2. Args ---- @@ -479,7 +463,6 @@ def smallest_rotation(q: Rotation, t): q_sr: Rotation The triad that results from a smallest rotation. """ - R_old = q.get_rotation_matrix() g1_old = R_old[:, 0] g1 = _np.asarray(t) / _np.linalg.norm(t) @@ -499,8 +482,8 @@ def smallest_rotation(q: Rotation, t): def get_rotation_vector_series( rotation_vectors: list | _NDArray | list[Rotation], ) -> _NDArray: - """Return an array containing the rotation vectors representing the given - rotation vectors. + """Return an array containing the rotation vectors representing the given rotation + vectors. The main feature of this function is, that the returned rotation vectors don't have jumps when the rotation angle exceeds 2*pi. We @@ -517,7 +500,6 @@ def get_rotation_vector_series( Returns: An array containing the "continuous" rotation vectors. """ - if isinstance(rotation_vectors, list): rotation_vector_array = _np.zeros((len(rotation_vectors), 3)) for i_rotation, rotation_entry in enumerate(rotation_vectors): @@ -527,8 +509,7 @@ def get_rotation_vector_series( rotation_vector_array[i_rotation] = rotation_entry def closest_multiple_of_two_pi(x: float) -> float: - """Given the value x, return the multiple of 2*pi that is closest to - it.""" + """Given the value x, return the multiple of 2*pi that is closest to it.""" return 2.0 * _np.pi * round(x / (2 * _np.pi)) rotation_vectors_continuous = _np.zeros((len(rotation_vector_array), 3)) diff --git a/src/beamme/cosserat_curve/__init__.py b/src/beamme/cosserat_curve/__init__.py index 43b78624..7a4d75b8 100644 --- a/src/beamme/cosserat_curve/__init__.py +++ b/src/beamme/cosserat_curve/__init__.py @@ -19,10 +19,8 @@ # 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. -"""This module contains functionality to convert a curve in 3D to a Cosserat -curve. +"""This module contains functionality to convert a curve in 3D to a Cosserat curve. -Furthermore, additional utility functions are included, such as warping -a mesh along the curve and the creation of non-homogeneous DBC to -achieve such a warping. +Furthermore, additional utility functions are included, such as warping a mesh along the +curve and the creation of non-homogeneous DBC to achieve such a warping. """ diff --git a/src/beamme/cosserat_curve/cosserat_curve.py b/src/beamme/cosserat_curve/cosserat_curve.py index 17cb675a..90231c37 100644 --- a/src/beamme/cosserat_curve/cosserat_curve.py +++ b/src/beamme/cosserat_curve/cosserat_curve.py @@ -19,8 +19,8 @@ # 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. -"""Define a Cosserat curve object that can be used to describe warping of -curve-like objects.""" +"""Define a Cosserat curve object that can be used to describe warping of curve-like +objects.""" from pathlib import Path as _Path from typing import Tuple as _Tuple @@ -50,7 +50,6 @@ def get_piecewise_linear_arc_length_along_points( coordinates: Array containing the point coordinates """ - n_points = len(coordinates) point_distance = _np.linalg.norm(coordinates[1:] - coordinates[:-1], axis=1) point_arc_length = _np.zeros(n_points) @@ -76,7 +75,6 @@ def get_spline_interpolation( centerline_interpolation: The spline interpolation object """ - # Interpolate coordinates along arc length # Note: The numeric evaluation of the spline interpolation can depend on the # operating system, thus introducing slight numerical differences (~1e-12). @@ -101,7 +99,6 @@ def get_quaternions_along_curve( point_arc_length: Array of parameter coordinates for which the quaternions should be calculated """ - centerline_interpolation_derivative = centerline.derivative() def basis(i): @@ -136,7 +133,6 @@ def get_relative_distance_and_rotations( ]: """Get relative distances and rotations that can be used to evaluate "intermediate" states of the Cosserat curve.""" - n_points = len(coordinates) relative_distances = _np.zeros(n_points - 1) relative_distances_rotation = _np.zeros(n_points - 1, dtype=_quaternion.quaternion) @@ -184,7 +180,6 @@ def __init__( - The automatically calculated triad, rotated onto the first basis vector of the starting guess triad using the smallest rotation. """ - self.coordinates = point_coordinates.copy() self.n_points = len(self.coordinates) @@ -256,21 +251,19 @@ def ds(t): self.twist(twist_angle) def set_centerline_interpolation(self): - """Set the interpolation of the centerline based on the coordinates and - arc length stored in this object.""" + """Set the interpolation of the centerline based on the coordinates and arc + length stored in this object.""" self.centerline_interpolation = get_spline_interpolation( self.coordinates, self.point_arc_length ) def translate(self, vector): """Translate the curve by the given vector.""" - self.coordinates += vector self.set_centerline_interpolation() def rotate(self, rotation: _Rotation, *, origin=None): """Rotate the curve and the quaternions.""" - self.quaternions = rotation.get_numpy_quaternion() * self.quaternions self.coordinates = _rotate_coordinates( self.coordinates, rotation, origin=origin @@ -302,8 +295,7 @@ def twist(self, twist_angle: float) -> None: def get_centerline_position_and_rotation( self, arc_length: float, **kwargs ) -> _Tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: - """Return the position and rotation at a given centerline arc - length.""" + """Return the position and rotation at a given centerline arc length.""" pos, rot = self.get_centerline_positions_and_rotations([arc_length], **kwargs) return pos[0], rot[0] @@ -334,7 +326,6 @@ def get_centerline_positions_and_rotations( the scaled curvature of the curve to obtain a intuitive wrapping. (factor=0 gives a straight line) """ - # Get the points that are within the arc length of the given curve. points_on_arc_length = _np.asarray(points_on_arc_length) points_in_bounds = _np.logical_and( @@ -451,9 +442,8 @@ def get_centerline_positions_and_rotations( return sol_r_final, sol_q_final def project_point(self, p, t0=None) -> float: - """Project a point to the curve, return the parameter coordinate for - the projection point.""" - + """Project a point to the curve, return the parameter coordinate for the + projection point.""" centerline_interpolation_p = self.centerline_interpolation.derivative(1) centerline_interpolation_pp = self.centerline_interpolation.derivative(2) @@ -476,8 +466,8 @@ def fp(t): return _optimize.newton(f, t0, fprime=fp) def get_pyvista_polyline(self, *, factor: float = 1.0) -> _pv.PolyData: - """Create a pyvista representation of the curve with the evaluated - triad basis vectors. + """Create a pyvista representation of the curve with the evaluated triad basis + vectors. Args: factor: Factor to scale the curvature along the curve (see @@ -486,7 +476,6 @@ def get_pyvista_polyline(self, *, factor: float = 1.0) -> _pv.PolyData: Returns: A pyvista PolyData object representing the curve. """ - positions, rotations = self.get_centerline_positions_and_rotations( self.point_arc_length, factor=factor ) @@ -525,7 +514,6 @@ def write_pvd_series( n_steps: Number of steps to create a uniform series of factors. Mutually exclusive with 'factors'. binary: If True, save the vtk files in binary format. """ - pvd_path = _Path(pvd_path) if pvd_path.suffix != ".pvd": raise ValueError( diff --git a/src/beamme/cosserat_curve/warping_along_cosserat_curve.py b/src/beamme/cosserat_curve/warping_along_cosserat_curve.py index 9fce1e6e..db5d26c9 100644 --- a/src/beamme/cosserat_curve/warping_along_cosserat_curve.py +++ b/src/beamme/cosserat_curve/warping_along_cosserat_curve.py @@ -19,8 +19,7 @@ # 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. -"""This file contains functionality to warp an existing mesh along a 1D -curve.""" +"""This file contains functionality to warp an existing mesh along a 1D curve.""" from typing import Tuple as _Tuple @@ -47,8 +46,8 @@ def get_arc_length_and_cross_section_coordinates( coordinates: _np.ndarray, origin: _np.ndarray, reference_rotation: _Rotation ) -> _Tuple[float, _np.ndarray]: - """Return the arc length and the cross section coordinates for a coordinate - system defined by the reference rotation and the origin. + """Return the arc length and the cross section coordinates for a coordinate system + defined by the reference rotation and the origin. Args ---- @@ -60,7 +59,6 @@ def get_arc_length_and_cross_section_coordinates( Rotation of the coordinate system. The first basis vector is the arc length direction. """ - transformed_coordinates = reference_rotation.inv() * (coordinates - origin) centerline_position = transformed_coordinates[0] cross_section_coordinates = [0.0, *transformed_coordinates[1:]] @@ -77,9 +75,8 @@ def get_mesh_transformation( initial_configuration: bool = True, **kwargs, ) -> _Tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: - """Generate a list of positions for each node that describe the - transformation of the nodes from the given configuration to the Cosserat - curve. + """Generate a list of positions for each node that describe the transformation of + the nodes from the given configuration to the Cosserat curve. Args ---- @@ -109,7 +106,6 @@ def get_mesh_transformation( A list for each time step containing the relative rotations for all nodes at that time step """ - # Define the factors for which we will generate the positions and rotations factors = _np.linspace(0.0, 1.0, n_steps + 1) if initial_configuration: @@ -243,8 +239,9 @@ def create_transform_boundary_conditions( n_dof_per_node: int = 3, **kwargs, ) -> None: - """Create the Dirichlet boundary conditions that enforce the warping. The - warped object is assumed to align with the x-axis in the reference + """Create the Dirichlet boundary conditions that enforce the warping. + + The warped object is assumed to align with the x-axis in the reference configuration. Args @@ -265,7 +262,6 @@ def create_transform_boundary_conditions( kwargs: Keyword arguments passed to get_mesh_transformation """ - # If no nodes are given, use all nodes in the mesh if nodes is None: nodes = mesh.nodes @@ -318,11 +314,9 @@ def warp_mesh_along_curve( ) -> None: """Warp an existing mesh along the given curve. - The reference coordinates for the transformation are defined by the - given origin and rotation, where the first basis vector of the triad - defines the centerline axis. + The reference coordinates for the transformation are defined by the given origin and + rotation, where the first basis vector of the triad defines the centerline axis. """ - pos, rot = get_mesh_transformation( curve, mesh.nodes, diff --git a/src/beamme/four_c/beam_interaction_conditions.py b/src/beamme/four_c/beam_interaction_conditions.py index 073ae7ab..8c0d7569 100644 --- a/src/beamme/four_c/beam_interaction_conditions.py +++ b/src/beamme/four_c/beam_interaction_conditions.py @@ -19,8 +19,7 @@ # 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. -"""This file contains a function to add the beam interaction conditions for -4C.""" +"""This file contains a function to add the beam interaction conditions for 4C.""" import beamme.core.conf as _conf from beamme.core.boundary_condition import BoundaryCondition as _BoundaryCondition @@ -34,8 +33,8 @@ def get_next_possible_id_for_boundary_condition( geometry_type: _conf.Geometry, condition_string: str, ) -> int: - """Returns the next possible id, which can be used for a boundary condition - based on all previous added boundary conditions within a mesh. + """Returns the next possible id, which can be used for a boundary condition based on + all previous added boundary conditions within a mesh. It returns the first ID which is not yet occupied within the existing boundary conditions w.r.t. to the given search_string and regex group index. @@ -49,7 +48,6 @@ def get_next_possible_id_for_boundary_condition( Returns: id: Smallest available ID """ - found_conditions = [] # loop through every possible geometry and find the conditions @@ -84,9 +82,9 @@ def add_beam_interaction_condition( *, id: int | None = None, ) -> int: - """Adds a pair of beam interaction boundary conditions to the given mesh - and estimates automatically the id of them based on all previously added - boundary conditions of the mesh. + """Adds a pair of beam interaction boundary conditions to the given mesh and + estimates automatically the id of them based on all previously added boundary + conditions of the mesh. Args: mesh: Mesh to which the boundary conditions will be added. @@ -97,7 +95,6 @@ def add_beam_interaction_condition( Returns: id: Used id for the created condition. """ - condition_string = "COUPLING_ID" if id is None: id = get_next_possible_id_for_boundary_condition( diff --git a/src/beamme/four_c/beam_potential.py b/src/beamme/four_c/beam_potential.py index 201195ef..a17e54d7 100644 --- a/src/beamme/four_c/beam_potential.py +++ b/src/beamme/four_c/beam_potential.py @@ -61,7 +61,6 @@ def __init__( power law. Same number of functions and prefactors/exponents/line charge densities must be provided! """ - # if only one potential law prefactor/exponent is present, convert it # into a list for simplified usage if isinstance(pot_law_prefactor, (float, int)): @@ -162,7 +161,6 @@ def create_header( Returns: Header for beam potential interactions. """ - header = { "beam_potential": { "type": potential_type, @@ -211,7 +209,6 @@ def create_potential_charge_conditions( Returns: List of boundary conditions for potential charge. """ - bcs = [] for i, (line_charge, func) in enumerate( diff --git a/src/beamme/four_c/dbc_monitor.py b/src/beamme/four_c/dbc_monitor.py index 83402f64..d8727508 100644 --- a/src/beamme/four_c/dbc_monitor.py +++ b/src/beamme/four_c/dbc_monitor.py @@ -19,8 +19,8 @@ # 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. -"""This function converts the DBC monitor log files to Neumann boundary -conditions in a mesh.""" +"""This function converts the DBC monitor log files to Neumann boundary conditions in a +mesh.""" import numpy as _np import yaml as _yaml @@ -41,8 +41,8 @@ def linear_time_transformation( time, values, time_span, *, flip=False, valid_start_and_end_point=False ): - """Performs a transformation of the time to a new interval with an - appropriate value vector. + """Performs a transformation of the time to a new interval with an appropriate value + vector. Args ---- @@ -58,7 +58,6 @@ def linear_time_transformation( valid_start_and_end_point: Bool optionally adds a valid starting point at t=0 and timespan[3] if provided """ - # flip values if desired and adjust time if flip is True: values = _np.flipud(values) @@ -100,8 +99,8 @@ def linear_time_transformation( def read_dbc_monitor_file(file_path): - """Load the Dirichlet boundary condition monitor log and return the data as - well as the nodes of this boundary condition. + """Load the Dirichlet boundary condition monitor log and return the data as well as + the nodes of this boundary condition. Args ---- @@ -112,7 +111,6 @@ def read_dbc_monitor_file(file_path): ---- [node_ids], [time], [force], [moment] """ - with open(file_path, "r") as f: dbc_monitor_file = _yaml.safe_load(f) @@ -142,8 +140,8 @@ def add_point_neuman_condition_to_mesh( *, n_dof: int = 3, ): - """Adds a Neumann boundary condition to a mesh for the given node_ids with - the function_array and force values by creating a new geometry set. + """Adds a Neumann boundary condition to a mesh for the given node_ids with the + function_array and force values by creating a new geometry set. Args ---- @@ -158,7 +156,6 @@ def add_point_neuman_condition_to_mesh( n_dof: int Number of DOFs per node. """ - # check if the dimensions of force and functions match if force.size != 3: raise ValueError( @@ -200,14 +197,13 @@ def dbc_monitor_to_mesh_all_values( functions: list[_Function] = [], **kwargs, ): - """Extracts all the force values of the monitored Dirichlet boundary - condition and converts them into a Function with a Neumann boundary - condition for a given mesh. The monitor log force values must be obtained - from a previous simulation with constant step size. The discretization of - the previous simulation must be identical to the one within the mesh. The - extracted force values are passed to a linear interpolation 4C-function. It - is advisable to only call this function once all nodes have been added to - the mesh. + """Extracts all the force values of the monitored Dirichlet boundary condition and + converts them into a Function with a Neumann boundary condition for a given mesh. + The monitor log force values must be obtained from a previous simulation with + constant step size. The discretization of the previous simulation must be identical + to the one within the mesh. The extracted force values are passed to a linear + interpolation 4C-function. It is advisable to only call this function once all nodes + have been added to the mesh. Args ---- @@ -233,7 +229,6 @@ def dbc_monitor_to_mesh_all_values( functions: [Function, Function, Function] Array consisting of 3 custom functions(x,y,z). The value for boundary condition is selected from the last steps. """ - nodes, time, force, _ = read_dbc_monitor_file(file_path) # The forces are the negative reactions at the Dirichlet boundaries. @@ -333,8 +328,8 @@ def dbc_monitor_to_mesh( function: _Function, **kwargs, ): - """Converts the last value of a Dirichlet boundary condition monitor log to - a Neumann boundary condition in the mesh. + """Converts the last value of a Dirichlet boundary condition monitor log to a + Neumann boundary condition in the mesh. Args ---- @@ -350,7 +345,6 @@ def dbc_monitor_to_mesh( function: Function Function for the Neumann boundary condition. """ - # read the force nodes, _, force, _ = read_dbc_monitor_file(file_path) diff --git a/src/beamme/four_c/element_beam.py b/src/beamme/four_c/element_beam.py index e7beb5e6..ad13b539 100644 --- a/src/beamme/four_c/element_beam.py +++ b/src/beamme/four_c/element_beam.py @@ -44,7 +44,6 @@ def get_four_c_reissner_beam(n_nodes: int, is_hermite_centerline: bool) -> type[_Beam]: """Return a Simo-Reissner beam for 4C.""" - four_c_type = _INPUT_FILE_MAPPINGS["four_c_type_to_four_c_type"][_BeamType.reissner] four_c_cell = _INPUT_FILE_MAPPINGS["element_type_and_n_nodes_to_four_c_cell"][ _bme.element_type.beam, n_nodes @@ -82,7 +81,6 @@ def get_four_c_kirchhoff_beam( is_fad: bool = True, ) -> type[_Beam]: """Return a Kirchhoff-Love beam for 4C.""" - # Show warning when not using rotvec. if not parametrization == _BeamKirchhoffParametrizationType.rot: _warnings.warn( @@ -141,9 +139,7 @@ class BeamFourCEulerBernoulli(_Beam2): ) def check(self) -> None: - """Check that the beam is straight and that the two rotations are the - same.""" - + """Check that the beam is straight and that the two rotations are the same.""" # Perform checks from the parent class. super().check() diff --git a/src/beamme/four_c/element_data.py b/src/beamme/four_c/element_data.py index defcb3b8..ffc3eb4c 100644 --- a/src/beamme/four_c/element_data.py +++ b/src/beamme/four_c/element_data.py @@ -69,9 +69,8 @@ def get_block_dict( def get_yaml_dict( self, element_id, connectivity, element_material_id, additional_element_data ) -> dict: - """Return the dictionary to write this element data to a yaml element - definition in the input file.""" - + """Return the dictionary to write this element data to a yaml element definition + in the input file.""" return { "id": element_id + 1, "cell": { @@ -108,8 +107,7 @@ def __eq__(self, other) -> bool: def four_c_element_data_from_yaml_dict( yaml_dict: dict, ) -> tuple[FourCElementData, int, _NDArray, int]: - """Extract the 4C element data from a yaml element definition in the input - file. + """Extract the 4C element data from a yaml element definition in the input file. Args: yaml_dict: The yaml element definition in the input file, will be modified in place. @@ -117,7 +115,6 @@ def four_c_element_data_from_yaml_dict( Returns: A tuple containing the 4C element data, the element ID, the connectivity, and the material ID. """ - element_id = yaml_dict["id"] connectivity = _np.array(yaml_dict["cell"]["connectivity"], dtype=int) - 1 four_c_cell = yaml_dict["cell"]["type"] @@ -138,8 +135,7 @@ def four_c_element_data_from_yaml_dict( def four_c_element_data_from_exo_dict(exo_dict: dict) -> tuple[FourCElementData, int]: - """Extract the 4C element data from an exodus element definition in the - input file. + """Extract the 4C element data from an exodus element definition in the input file. Args: exo_dict: The exodus element definition in the input file, will be modified in @@ -148,7 +144,6 @@ def four_c_element_data_from_exo_dict(exo_dict: dict) -> tuple[FourCElementData, Returns: A tuple containing the 4C element data and the material ID. """ - # First, we have to remove the ID entry exo_dict.pop("ID") diff --git a/src/beamme/four_c/element_solid.py b/src/beamme/four_c/element_solid.py index 2a28f4a7..dbe14787 100644 --- a/src/beamme/four_c/element_solid.py +++ b/src/beamme/four_c/element_solid.py @@ -60,7 +60,6 @@ def get_four_c_solid( Returns: A type that defines a solid element block for 4C solid elements. """ - if element_technology is None: element_technology = {} else: diff --git a/src/beamme/four_c/function_utility.py b/src/beamme/four_c/function_utility.py index a3bdf3a1..faaf5a86 100644 --- a/src/beamme/four_c/function_utility.py +++ b/src/beamme/four_c/function_utility.py @@ -19,8 +19,7 @@ # 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. -"""This module implements utility functions to create 4C space time -function.""" +"""This module implements utility functions to create 4C space time function.""" from typing import List as _List @@ -32,8 +31,7 @@ def create_linear_interpolation_dict( times: _List[float], values: _List[float], *, variable_name="var", variable_index=0 ): - """Create a string that describes a variable that is linear interpolated - over time. + """Create a string that describes a variable that is linear interpolated over time. Args times, values: @@ -43,7 +41,6 @@ def create_linear_interpolation_dict( variable_index: Index of this created variable """ - if not len(times) == len(values): raise ValueError( f"The dimensions of time ({len(times)}) and values ({len(values)}) do not match" @@ -72,22 +69,21 @@ def create_linear_interpolation_function( *, function_type="SYMBOLIC_FUNCTION_OF_SPACE_TIME", ): - """Create a function that describes a linear interpolation between the - given time points and values. Before and after it will be constant. + """Create a function that describes a linear interpolation between the given time + points and values. Before and after it will be constant. Args ---- times, values: Time and values that will be interpolated with piecewise linear functions """ - function_dict = create_linear_interpolation_dict(times, values, variable_name="var") return _Function([{function_type: "var"}, function_dict]) def ensure_length_of_function_array(function_array: _List, length: int = 3): - """Performs size check of a function array and appends the function array - to the given length, if a list with only one item is provided. + """Performs size check of a function array and appends the function array to the + given length, if a list with only one item is provided. Args: function_array: list with functions @@ -96,7 +92,6 @@ def ensure_length_of_function_array(function_array: _List, length: int = 3): Returns: function_array: list with functions with provided length """ - # extend items of function automatically if it is only provided once if len(function_array) == 1: function_array = function_array * length diff --git a/src/beamme/four_c/header_functions.py b/src/beamme/four_c/header_functions.py index 93a2dc3f..ee646a22 100644 --- a/src/beamme/four_c/header_functions.py +++ b/src/beamme/four_c/header_functions.py @@ -19,8 +19,8 @@ # 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. -"""This module defines functions that can be used to add header information to -an input file.""" +"""This module defines functions that can be used to add header information to an input +file.""" from typing import Any as _Any from typing import List as _List @@ -87,7 +87,6 @@ def set_runtime_output( output_strains: bool If the strains in the Gauss points should be output. """ - # Set the basic runtime output options. input_file.add( { @@ -206,7 +205,6 @@ def set_beam_to_solid_meshtying( coupling_type: str Type of coupling for beam-to-surface coupling. """ - # Set the beam contact options. # check if these keys are already set, otherwise set them if ( @@ -318,7 +316,6 @@ def set_header_static( If the nonlinear solver parameters should be set via a NOX xml file or directly in the input file. """ - input_file_parameters: dict[str, _Any] = {} # Set the parameters for a static analysis. @@ -449,7 +446,6 @@ def set_beam_interaction_section( search_strategy: Type of search strategy used for finding coupling pairs. """ - input_file.add({"BEAM INTERACTION": {"REPARTITIONSTRATEGY": repartition_strategy}}) @@ -463,7 +459,6 @@ def set_beam_contact_runtime_output( every_iteration: If output at every Newton iteration should be written. """ - input_file.add( { "BEAM INTERACTION/BEAM TO BEAM CONTACT/RUNTIME VTK OUTPUT": { @@ -492,8 +487,8 @@ def set_beam_contact_section( penalty_regularization_c0: float = 0, beam_interaction_parameters: dict = {}, ): - """Set default beam contact section, for more and updated details see - respective input file within 4C. + """Set default beam contact section, for more and updated details see respective + input file within 4C. Parameters for `set_beam_interaction_section` are forwarded as keyword arguments. @@ -524,7 +519,6 @@ def set_beam_contact_section( beam_interaction_parameters: Keyword parameters for `set_beam_interaction_section` """ - if len(per_shift_angle) != 2: raise ValueError( "Please provide lower and upper value of BEAMS_PERPSHIFTANGLE." diff --git a/src/beamme/four_c/input_file.py b/src/beamme/four_c/input_file.py index 99371afd..4ef53a65 100644 --- a/src/beamme/four_c/input_file.py +++ b/src/beamme/four_c/input_file.py @@ -19,8 +19,7 @@ # 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. -"""This module defines the classes that are used to create an input file for -4C.""" +"""This module defines the classes that are used to create an input file for 4C.""" import os as _os from datetime import datetime as _datetime @@ -58,7 +57,6 @@ class InputFile: def __init__(self) -> None: """Initialize the input file.""" - self.fourc_input = _FourCInput() # Register converters to directly convert non-primitive types @@ -83,7 +81,6 @@ def __contains__(self, key: str) -> bool: Returns: True if section is set """ - return key in self.fourc_input def __setitem__(self, key: str, value: _Any) -> None: @@ -93,7 +90,6 @@ def __setitem__(self, key: str, value: _Any) -> None: key: Section name value: Section entry """ - self.fourc_input[key] = value def __getitem__(self, key: str) -> _Any: @@ -107,7 +103,6 @@ def __getitem__(self, key: str) -> _Any: Returns: The section content """ - return self.fourc_input[key] @classmethod @@ -123,7 +118,6 @@ def from_4C_yaml( Returns: Initialised object """ - obj = cls() obj.fourc_input = _FourCInput.from_4C_yaml(input_file_path, header_only) return obj @@ -135,7 +129,6 @@ def sections(self) -> dict: Returns: dict: Set sections """ - return self.fourc_input.sections def pop(self, key: str, default_value: _Any = _NOT_SET) -> _Any: @@ -147,7 +140,6 @@ def pop(self, key: str, default_value: _Any = _NOT_SET) -> _Any: Returns: The section content """ - return self.fourc_input.pop(key, default_value) def add(self, object_to_add, **kwargs): @@ -157,7 +149,6 @@ def add(self, object_to_add, **kwargs): object: The object to be added. This can be a mesh or a dictionary. **kwargs: Additional arguments to be passed to the add method. """ - if isinstance(object_to_add, _Mesh): _dump_mesh_to_input_file(self, mesh=object_to_add, **kwargs) @@ -165,8 +156,8 @@ def add(self, object_to_add, **kwargs): self.fourc_input.combine_sections(object_to_add) def get_fourcipp_input_with_mesh(self) -> _FourCInput: - """Return a copy of the FourCIPP input file with the contents of the - mesh representation dumped to the yaml sections.""" + """Return a copy of the FourCIPP input file with the contents of the mesh + representation dumped to the yaml sections.""" fourc_input = self.fourc_input.copy() _dump_mesh_representation_to_input_file_yaml( fourc_input, @@ -224,7 +215,6 @@ def dump( fourcipp_yaml_style: If True, the input file is written in the fourcipp yaml style. """ - # Make sure the given input file is a Path instance. input_file_path = _Path(input_file_path) @@ -305,7 +295,6 @@ def _get_header(self) -> dict: Returns: A dictionary with the header information. """ - header: dict = {"BeamMe": {}} header["BeamMe"]["creation_date"] = _datetime.now().isoformat( @@ -360,7 +349,6 @@ def _get_application_script(self, application_path: _Path) -> list[str]: Returns: A list of strings with the script that created this input file. """ - application_script_lines = [ "# Application script which created this input file:\n" ] diff --git a/src/beamme/four_c/input_file_dump_functions.py b/src/beamme/four_c/input_file_dump_functions.py index bbb386ab..57af29a2 100644 --- a/src/beamme/four_c/input_file_dump_functions.py +++ b/src/beamme/four_c/input_file_dump_functions.py @@ -71,7 +71,6 @@ def dump_function(function: _Function, i_global: int) -> dict[str, _Any]: def dump_coupling(coupling): """Return the input file representation of the coupling condition.""" - if isinstance(coupling.data, dict): data = coupling.data else: @@ -110,7 +109,6 @@ def dump_coupling(coupling): def dump_nurbs_patch_knotvectors(input_file, nurbs_patch: _NURBSPatch) -> None: """Set the knot vectors of the NURBS patch in the input file.""" - patch_data: dict[str, _Any] = { "KNOT_VECTORS": [], } @@ -171,7 +169,6 @@ def dump_mesh_to_input_file(input_file, mesh: _Mesh) -> None: input_file: The input file where we want to add the mesh information. mesh: The mesh to be added to the input file. """ - # Compute starting index for element types start_index_element_types = len(input_file.element_type_id_to_data) @@ -337,15 +334,14 @@ def dump_mesh_representation_to_input_file_yaml( mesh_representation: _MeshRepresentation, element_type_id_to_data: dict[int, _FourCElementData], ) -> None: - """Dump the information contained in the mesh representation to the 4C - input file via FourCIPP, in yaml format. + """Dump the information contained in the mesh representation to the 4C input file + via FourCIPP, in yaml format. Args: fourc_input: 4C input file via FourCIPP where the mesh information data will be dumped to. mesh_representation: The mesh representation that is added to the input file. element_type_id_to_data: The mapping between element type ID and the element type data. """ - # Compute the starting indices for the nodes and elements entities. start_index_nodes = len(fourc_input.sections.get("NODE COORDS", [])) start_index_elements = sum( @@ -354,8 +350,7 @@ def dump_mesh_representation_to_input_file_yaml( ) def _dump(section_name: str, dictionary_list: _List): - """Append the given list of dictionaries to the section in the input - file.""" + """Append the given list of dictionaries to the section in the input file.""" if len(dictionary_list) == 0: return full_item_list = fourc_input.pop(section_name, []) @@ -518,7 +513,6 @@ def dump_mesh_representation_to_input_file_vtu( Returns: The unstructured grid containing the vtu mesh. """ - # VTU output can not be combined with yaml output. n_yaml_nodes = len(fourc_input.sections.get("NODE COORDS", [])) n_yaml_elements = sum( diff --git a/src/beamme/four_c/input_file_mappings.py b/src/beamme/four_c/input_file_mappings.py index 58222a99..898b4450 100644 --- a/src/beamme/four_c/input_file_mappings.py +++ b/src/beamme/four_c/input_file_mappings.py @@ -19,8 +19,7 @@ # 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. -"""This file provides the mappings between BeamMe objects and 4C input -files.""" +"""This file provides the mappings between BeamMe objects and 4C input files.""" from typing import Any as _Any diff --git a/src/beamme/four_c/locsys_condition.py b/src/beamme/four_c/locsys_condition.py index b1d0e3da..d733ef18 100644 --- a/src/beamme/four_c/locsys_condition.py +++ b/src/beamme/four_c/locsys_condition.py @@ -36,8 +36,8 @@ class LocSysCondition(_BoundaryCondition): """This object represents a locsys condition in 4C. - It allows to rotate the local coordinate system used to apply - Dirichlet boundary conditions. + It allows to rotate the local coordinate system used to apply Dirichlet boundary + conditions. """ def __init__( @@ -62,7 +62,6 @@ def __init__( update_node_position: Flag to enable the updated node position use_consistent_node_normal: Flag to use a consistent node normal """ - # Check for invalid input arguments if ( function_array is not None diff --git a/src/beamme/four_c/material.py b/src/beamme/four_c/material.py index d1fffaa6..df8e63bd 100644 --- a/src/beamme/four_c/material.py +++ b/src/beamme/four_c/material.py @@ -31,8 +31,8 @@ def get_material_and_all_contained_sub_materials( material: _Material, _visited_materials: set[int] | None = None ) -> list[_Material]: - """Recursively collect all materials contained within a material, including - nested ones. + """Recursively collect all materials contained within a material, including nested + ones. Args: material: @@ -49,7 +49,6 @@ def get_material_and_all_contained_sub_materials( ValueError: If a circular material reference is detected. """ - if _visited_materials is None: _visited_materials = set() @@ -143,7 +142,6 @@ def __init__( def dump_to_list(self): """Return a list with the (single) item representing this material.""" - if self.radius is None or self.youngs_modulus is None: raise ValueError( "Radius and Young's modulus must be provided for beam materials." @@ -252,7 +250,6 @@ def __init__(self, is_fad=False, **kwargs): def dump_to_list(self): """Return a list with the (single) item representing this material.""" - if self.radius is None or self.youngs_modulus is None: raise ValueError( "Radius and Young's modulus must be provided for beam materials." @@ -306,7 +303,6 @@ def __init__(self, **kwargs): def dump_to_list(self): """Return a list with the (single) item representing this material.""" - if self.radius is None or self.youngs_modulus is None: raise ValueError( "Radius and Young's modulus must be provided for beam materials." @@ -343,7 +339,6 @@ def __init__(self, material_string=None, **kwargs): def dump_to_list(self): """Return a list with the (single) item representing this material.""" - return {"MAT": self, self.material_string: self.data} diff --git a/src/beamme/four_c/model_importer.py b/src/beamme/four_c/model_importer.py index 9753762f..6f32a8aa 100644 --- a/src/beamme/four_c/model_importer.py +++ b/src/beamme/four_c/model_importer.py @@ -76,18 +76,19 @@ class UniqueDataTracker: """Helper class to track unique data dictionaries and assign IDs to them. - When importing input files, we need to identify elements of the same - type. The type information is given in dictionaries. This class - provides a tracker that can be queried with a given element data and - return an already matching element type ID or create a new one. + When importing input files, we need to identify elements of the same type. The type + information is given in dictionaries. This class provides a tracker that can be + queried with a given element data and return an already matching element type ID or + create a new one. """ def __init__(self) -> None: self.unique_id_to_data: dict[int, _FourCElementData] = {} def get_unique_id(self, data: _FourCElementData) -> int: - """Get the unique ID for the given data. If the data has not been seen - before, a new ID will be assigned to it. + """Get the unique ID for the given data. + + If the data has not been seen before, a new ID will be assigned to it. Args: data: The data dictionary to get the ID for. @@ -138,8 +139,7 @@ def import_cubitpy_model( def import_four_c_model( input_file_path: _Path, convert_input_to_mesh: bool = False ) -> _Tuple[_InputFile, _Mesh]: - """Import an existing 4C input file and optionally convert it into a BeamMe - mesh. + """Import an existing 4C input file and optionally convert it into a BeamMe mesh. Args: input_file_path: A file path to an existing 4C input file that will be @@ -152,7 +152,6 @@ def import_four_c_model( False, the mesh will be empty. Note that the input sections which are converted to a BeamMe mesh are removed from the input file object. """ - input_file = _InputFile().from_4C_yaml(input_file_path=input_file_path) base_path = input_file_path.parent @@ -192,8 +191,8 @@ def import_four_c_model( def _extract_mesh_representation( input_file: _InputFile, ) -> tuple[_MeshRepresentation, dict[int, _FourCElementData], dict[int, int]]: - """Extract the mesh representation from mesh data directly contained in the - input file. + """Extract the mesh representation from mesh data directly contained in the input + file. This will do an inplace removal of the mesh data from the provided input file. @@ -208,7 +207,6 @@ def _extract_mesh_representation( - `node_set_id_mesh_representation_to_input_file`: A mapping that can be used to map the IDs in the mesh representation to the IDs in the input file. """ - # extract nodes nodes = input_file.pop("NODE COORDS", []) n_nodes = len(nodes) @@ -342,7 +340,6 @@ def _get_exodus_path_from_input_file(input_file: _InputFile, base_path: _Path) - Returns: The path to the exodus file linked in the input file. """ - if "STRUCTURE GEOMETRY" in input_file.fourc_input: structure_geometry_section = input_file.fourc_input["STRUCTURE GEOMETRY"] if "FILE" in structure_geometry_section: @@ -388,7 +385,6 @@ def _extract_mesh_representation_from_exo( - `node_set_id_mesh_representation_to_input_file`: A mapping that can be used to map the geometry set IDs in the mesh representation to the ones in the input file. """ - # Load the exodus file. with _netCDF4.Dataset( _get_exodus_path_from_input_file(input_file, base_path) @@ -552,7 +548,6 @@ def _create_mesh_from_mesh_representation( A tuple (input_file, mesh). The input_file is modified in place to remove sections converted into the BeamMe mesh. """ - # convert all sections to native objects and add to a new mesh mesh = _Mesh() @@ -666,8 +661,7 @@ def _create_mesh_from_mesh_representation( def _extract_materials_from_input_file( input_file: _InputFile, ) -> dict[int, _MaterialSolid]: - """Extract all materials from the input file and convert them to BeamMe - materials. + """Extract all materials from the input file and convert them to BeamMe materials. Args: input_file: The input file containing the material sections. @@ -675,7 +669,6 @@ def _extract_materials_from_input_file( Returns: A mapping of material IDs to BeamMe material objects. """ - material_id_map_all = {} for mat in input_file.pop("MATERIALS", []): diff --git a/src/beamme/four_c/run_four_c.py b/src/beamme/four_c/run_four_c.py index dfb98deb..d4c86e88 100644 --- a/src/beamme/four_c/run_four_c.py +++ b/src/beamme/four_c/run_four_c.py @@ -74,7 +74,6 @@ def run_four_c( return_code: int Return code of 4C run """ - # Fist get all needed parameters if four_c_exe is None: four_c_exe = _get_env_variable("BEAMME_FOUR_C_EXE") @@ -119,8 +118,10 @@ def run_four_c( def clean_simulation_directory(sim_dir, *, ask_before_clean=False): - """Clear the simulation directory. If it does not exist, it is created. - Optionally the user can be asked before a deletion of files. + """Clear the simulation directory. + + If it does not exist, it is created. Optionally the user can be + asked before a deletion of files. Args ---- @@ -129,7 +130,6 @@ def clean_simulation_directory(sim_dir, *, ask_before_clean=False): ask_before_clean: bool Flag which indicates whether the user must confirm removal of files and directories """ - # Check if simulation directory exists. if _os.path.exists(sim_dir): if ask_before_clean: diff --git a/src/beamme/four_c/solid_shell_thickness_direction.py b/src/beamme/four_c/solid_shell_thickness_direction.py index b4ab2422..3bb2cb5f 100644 --- a/src/beamme/four_c/solid_shell_thickness_direction.py +++ b/src/beamme/four_c/solid_shell_thickness_direction.py @@ -19,8 +19,8 @@ # 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. -"""This function allows to reorder the connectivity of solid shell elements -such that the solid shell direction is correctly represented.""" +"""This function allows to reorder the connectivity of solid shell elements such that +the solid shell direction is correctly represented.""" from typing import List as _List @@ -89,9 +89,7 @@ def shape_functions_derivative_hex8(xi1, xi2, xi3): def get_hex8_element_center_and_jacobian_mapping(element): - """Return the center of a hex8 element and the Jacobian mapping for that - point.""" - + """Return the center of a hex8 element and the Jacobian mapping for that point.""" nodal_coordinates = _get_nodal_coordinates(element.nodes) if not len(nodal_coordinates) == 8: raise ValueError(f"Expected 8 nodes, got {len(nodal_coordinates)}") @@ -106,14 +104,13 @@ def get_hex8_element_center_and_jacobian_mapping(element): def get_reordering_index_thickness(jacobian, *, identify_threshold=None): - """Return the reordering index from the Jacobian such that the thinnest - direction is the 3rd parameter direction. + """Return the reordering index from the Jacobian such that the thinnest direction is + the 3rd parameter direction. Additionally it is checked, that the thinnest direction is at least - identify_threshold times smaller than the next thinnest, to avoid - wrongly detected directions. + identify_threshold times smaller than the next thinnest, to avoid wrongly detected + directions. """ - # The direction with the smallest parameter derivative is the thickness direction parameter_derivative_norms = [ _np.linalg.norm(parameter_direction) for parameter_direction in jacobian @@ -139,10 +136,8 @@ def get_reordering_index_thickness(jacobian, *, identify_threshold=None): def get_reordering_index_director_projection( jacobian, director, *, identify_threshold=None ): - """Return the reordering index from the Jacobian such that the thickness - direction is the one that has the largest dot product with the given - director.""" - + """Return the reordering index from the Jacobian such that the thickness direction + is the one that has the largest dot product with the given director.""" projections = [] for parameter_director in jacobian: parameter_director = parameter_director / _np.linalg.norm(parameter_director) @@ -171,8 +166,7 @@ def set_solid_shell_thickness_direction( director_function=None, identify_threshold=2.0, ): - """Set the solid shell directions for all solid shell elements in the - element list. + """Set the solid shell directions for all solid shell elements in the element list. Args: ---- @@ -194,7 +188,6 @@ def set_solid_shell_thickness_direction( To ensure that the found directions are well-defined, i.e., that not multiple directions are almost equally suited to the thickness direction. """ - if len(elements) == 0: raise ValueError("Expected a non empty element list") @@ -256,9 +249,8 @@ def set_solid_shell_thickness_direction( def get_visualization_third_parameter_direction_hex8(mesh: _Mesh): - """Return a pyvista mesh with cell data for the third parameter direction - for hex8 elements.""" - + """Return a pyvista mesh with cell data for the third parameter direction for hex8 + elements.""" grid = mesh.get_vtu_representation() grid_solid = grid.extract_cells( grid.cell_data["beamme_type"] == _bme.element_type.solid.value @@ -286,10 +278,9 @@ def get_visualization_third_parameter_direction_hex8(mesh: _Mesh): def visualize_third_parameter_direction_hex8(mesh: _Mesh): """Visualize the third parameter direction for hex8 elements. - This can be used to check the correct definition of the shell - thickness for solid shell elements. + This can be used to check the correct definition of the shell thickness for solid + shell elements. """ - grid = get_visualization_third_parameter_direction_hex8(mesh) grid = grid.clean() cell_centers = grid.cell_centers() diff --git a/src/beamme/geometric_search/arborx.py b/src/beamme/geometric_search/arborx.py index 19e5ff25..43a00a46 100644 --- a/src/beamme/geometric_search/arborx.py +++ b/src/beamme/geometric_search/arborx.py @@ -19,8 +19,7 @@ # 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. -"""This file defines the interface to the ArborX geometric search -functionality.""" +"""This file defines the interface to the ArborX geometric search functionality.""" from beamme.geometric_search.utils import arborx_is_available as _arborx_is_available @@ -44,8 +43,8 @@ def __init__(self): _kokkos_initialize() def __del__(self): - """Finalize Kokkos after this object goes out of scope, i.e., at the - end of this modules lifetime.""" + """Finalize Kokkos after this object goes out of scope, i.e., at the end of this + modules lifetime.""" _kokkos_finalize() diff --git a/src/beamme/geometric_search/cython.py b/src/beamme/geometric_search/cython.py index cee44b3f..0cf694cd 100644 --- a/src/beamme/geometric_search/cython.py +++ b/src/beamme/geometric_search/cython.py @@ -19,8 +19,7 @@ # 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. -"""This file defines the interface to the Cython geometric search -functionality.""" +"""This file defines the interface to the Cython geometric search functionality.""" import warnings as _warnings diff --git a/src/beamme/geometric_search/find_close_points.py b/src/beamme/geometric_search/find_close_points.py index 66195aff..12bd65ed 100644 --- a/src/beamme/geometric_search/find_close_points.py +++ b/src/beamme/geometric_search/find_close_points.py @@ -19,8 +19,8 @@ # 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. -"""Find unique points in a point cloud, i.e., points that are within a certain -tolerance of each other will be considered as unique.""" +"""Find unique points in a point cloud, i.e., points that are within a certain tolerance +of each other will be considered as unique.""" from enum import Enum as _Enum from enum import auto as _auto @@ -51,8 +51,8 @@ class FindClosePointAlgorithm(_Enum): def point_partners_to_unique_indices(point_partners): - """Convert the partner indices to lists that can be used for converting - between the full and unique coordinates. + """Convert the partner indices to lists that can be used for converting between the + full and unique coordinates. Returns ---- @@ -61,7 +61,6 @@ def point_partners_to_unique_indices(point_partners): inverse_indices: list(int) Indices of the unique array that can be used to reconstruct of the original points coordinates. """ - unique_indices = [] inverse_indices = [-1 for i in range(len(point_partners))] partner_id_to_unique_map = {} @@ -91,8 +90,8 @@ def point_partners_to_unique_indices(point_partners): def point_partners_to_partner_indices(point_partners, n_partners): - """Convert the partner indices for each point to a list of lists with the - indices for all partners.""" + """Convert the partner indices for each point to a list of lists with the indices + for all partners.""" partner_indices = [[] for i in range(n_partners)] for i, partner_index in enumerate(point_partners): if partner_index != -1: @@ -101,8 +100,8 @@ def point_partners_to_partner_indices(point_partners, n_partners): def partner_indices_to_point_partners(partner_indices, n_points): - """Convert the list of lists with the indices for all partners to the - partner indices for each point.""" + """Convert the list of lists with the indices for all partners to the partner + indices for each point.""" point_partners = [-1 for _i in range(n_points)] for i_partner, partners in enumerate(partner_indices): for index in partners: @@ -111,8 +110,8 @@ def partner_indices_to_point_partners(partner_indices, n_points): def find_close_points(point_coordinates, *, algorithm=None, tol=1e-8, **kwargs): - """Find unique points in a point cloud, i.e., points that are within a - certain tolerance of each other will be considered as unique. + """Find unique points in a point cloud, i.e., points that are within a certain + tolerance of each other will be considered as unique. Args ---- @@ -136,7 +135,6 @@ def find_close_points(point_coordinates, *, algorithm=None, tol=1e-8, **kwargs): partner: int Largest partner index. """ - n_points = len(point_coordinates) if algorithm is None: diff --git a/src/beamme/geometric_search/scipy.py b/src/beamme/geometric_search/scipy.py index e3b1bd5c..09ebae9a 100644 --- a/src/beamme/geometric_search/scipy.py +++ b/src/beamme/geometric_search/scipy.py @@ -27,7 +27,6 @@ def pairs_to_partner_list(pairs, n_points): """Convert the pairs to a partner list.""" - # Sort the pairs by the first column pairs = pairs[pairs[:, 0].argsort()] @@ -57,7 +56,6 @@ def pairs_to_partner_list(pairs, n_points): def find_close_points_scipy(point_coordinates, tol): """Call the Scipy implementation of find close_points.""" - kd_tree = _KDTree(point_coordinates) pairs = kd_tree.query_pairs(r=tol, output_type="ndarray") return pairs_to_partner_list(pairs, len(point_coordinates)) diff --git a/src/beamme/geometric_search/utils.py b/src/beamme/geometric_search/utils.py index 26a3b9e1..711649a5 100644 --- a/src/beamme/geometric_search/utils.py +++ b/src/beamme/geometric_search/utils.py @@ -30,7 +30,6 @@ def arborx_is_available() -> bool: Returns: True if ArborX is installed, False otherwise """ - if _find_spec("beamme.geometric_search.arborx_lib") is None: return False return True @@ -42,7 +41,6 @@ def cython_is_available() -> bool: Returns: True if Cython is installed, False otherwise """ - if _find_spec("beamme.geometric_search.cython_lib") is None: return False return True diff --git a/src/beamme/mesh_creation_functions/applications/beam_fibers_in_rectangle.py b/src/beamme/mesh_creation_functions/applications/beam_fibers_in_rectangle.py index c9616d9d..f3d58798 100644 --- a/src/beamme/mesh_creation_functions/applications/beam_fibers_in_rectangle.py +++ b/src/beamme/mesh_creation_functions/applications/beam_fibers_in_rectangle.py @@ -19,11 +19,9 @@ # 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. -"""This file has functions to generate multiple parallel fibers within a -rectangle. +"""This file has functions to generate multiple parallel fibers within a rectangle. -This can for example be used to create fiber reinforced composite -plates. +This can for example be used to create fiber reinforced composite plates. """ import numpy as _np @@ -65,7 +63,6 @@ def _intersect_line_with_rectangle( projection_found: bool True if intersection is valid. """ - # Convert the input values to np.arrays. start_line = _np.asarray(start_line) direction_line = _np.asarray(direction_line) @@ -152,7 +149,6 @@ def create_fibers_in_rectangle( Minimum fiber length. If a fiber is shorter than this value, it will not be created. The default value is half of fiber_element_length. """ - if reference_point is None: reference_point = 0.5 * _np.array([length, width]) else: diff --git a/src/beamme/mesh_creation_functions/applications/beam_honeycomb.py b/src/beamme/mesh_creation_functions/applications/beam_honeycomb.py index 62087c0a..066c7d56 100644 --- a/src/beamme/mesh_creation_functions/applications/beam_honeycomb.py +++ b/src/beamme/mesh_creation_functions/applications/beam_honeycomb.py @@ -46,8 +46,9 @@ def create_beam_mesh_honeycomb_flat( closed_height=True, create_couplings=True, ): - """Add a flat honeycomb structure. The structure will be created in the x-y - plane. + """Add a flat honeycomb structure. + + The structure will be created in the x-y plane. Args ---- @@ -169,8 +170,9 @@ def create_beam_mesh_honeycomb( closed_top=True, vertical=True, ): - """Wrap a honeycomb structure around a cylinder. The cylinder axis will be - the z-axis. + """Wrap a honeycomb structure around a cylinder. + + The cylinder axis will be the z-axis. Args ---- @@ -201,7 +203,6 @@ def create_beam_mesh_honeycomb( contains end nodes of lines, not the middle ones. The set "all" contains all nodes. """ - # Calculate the input values for the flat honeycomb mesh. if vertical: width = diameter * _np.pi / n_circumference diff --git a/src/beamme/mesh_creation_functions/applications/beam_stent.py b/src/beamme/mesh_creation_functions/applications/beam_stent.py index 83c9a984..142c5924 100644 --- a/src/beamme/mesh_creation_functions/applications/beam_stent.py +++ b/src/beamme/mesh_creation_functions/applications/beam_stent.py @@ -50,39 +50,39 @@ def create_stent_cell( S3=True, n_el=1, ): - """Create a cell of the stent. This cell is on the x-y plane. - - Args - ---- - beam_class: Beam - Class that will be used to create the beam elements. - material: Material - Material for the beam. - width: float - Width of the total cell. - height: float - Height of the total cell. - fac_bottom: the ratio of the bottom's width to the cell's width - fac_neck: the ratio of the neck's width to the cell's width - fac_radius: the ratio of the S1's radius to the cell's width - alpha: radiant - The angle between the lines and horizontal line - n_el: int - Number of elements per beam line. - S1, S2, S3: bool - This check weather the curve S1, S2 or S3 will be created. - If the cell is on bottom of the stent flat S1 and S2 won't - be created. If the cell is on top of the flat S1 and S3 - won't be created - - ( these variables are described in a file ) - - Return - ---- - mesh: Mesh - A mesh with this structure + """Create a cell of the stent. + + This cell is on the x-y plane. + Args + ---- + beam_class: Beam + Class that will be used to create the beam elements. + material: Material + Material for the beam. + width: float + Width of the total cell. + height: float + Height of the total cell. + fac_bottom: the ratio of the bottom's width to the cell's width + fac_neck: the ratio of the neck's width to the cell's width + fac_radius: the ratio of the S1's radius to the cell's width + alpha: radiant + The angle between the lines and horizontal line + n_el: int + Number of elements per beam line. + S1, S2, S3: bool + This check weather the curve S1, S2 or S3 will be created. + If the cell is on bottom of the stent flat S1 and S2 won't + be created. If the cell is on top of the flat S1 and S3 + won't be created + + ( these variables are described in a file ) + + Return + ---- + mesh: Mesh + A mesh with this structure """ - mesh = _Mesh() def add_line(pointa, pointb, n_el_line): @@ -155,8 +155,10 @@ def add_segment(center, axis_rotation, radius, angle, n_el_segment): def create_stent_column( beam_class, material, width, height, n_height, n_el=1, **kwargs ): - """Create a column of completed cells. A completed cell consists of one - cell, that is created with the create cell function and it's reflection. + """Create a column of completed cells. + + A completed cell consists of one cell, that is created with the create cell + function and it's reflection. Args ---- @@ -179,7 +181,6 @@ def create_stent_column( mesh: Mesh A mesh with this structure. """ - mesh_column = _Mesh() for i in range(n_height): S1 = True @@ -244,7 +245,6 @@ def create_beam_mesh_stent_flat( mesh: Mesh A mesh with this structure """ - mesh_flat = _Mesh() width = width_flat / n_column / 2 height = height_flat / n_height @@ -287,8 +287,7 @@ def create_beam_mesh_stent( n_circumference, **kwargs, ): - """Create a stent structure around cylinder, The cylinder axis will be the - z-axis. + """Create a stent structure around cylinder, The cylinder axis will be the z-axis. Args ---- @@ -315,7 +314,6 @@ def create_beam_mesh_stent( sets only contains end nodes of lines, not the middle ones. The set 'all' contains all nodes. """ - # Only allow even number of columns. if n_circumference % 2 == 1: raise ValueError("has to be even even number!") diff --git a/src/beamme/mesh_creation_functions/applications/beam_wire.py b/src/beamme/mesh_creation_functions/applications/beam_wire.py index ef4b72f0..cd9dc692 100644 --- a/src/beamme/mesh_creation_functions/applications/beam_wire.py +++ b/src/beamme/mesh_creation_functions/applications/beam_wire.py @@ -34,8 +34,9 @@ def create_wire_fibers( mesh, beam_class, material, length, *, radius=None, layers=1, n_el=1 ): - """Create a steel wire consisting of multiple filaments. The wire will be - oriented in x-direction. + """Create a steel wire consisting of multiple filaments. + + The wire will be oriented in x-direction. Args ---- @@ -61,7 +62,6 @@ def create_wire_fibers( Set with the 'start' and 'end' nodes of the wire. Also a 'all' set with all nodes of the wire. """ - if len(mesh.nodes) != 0: raise ValueError( "The create_wire_fibers function can only be used with an empty mesh." @@ -73,8 +73,7 @@ def create_wire_fibers( wire_beam_radius = radius def create_line(pos_yz): - """Create a line starting at the yz-plane with the 2D coordinates - pos_yz.""" + """Create a line starting at the yz-plane with the 2D coordinates pos_yz.""" _create_beam_mesh_line( mesh, beam_class, diff --git a/src/beamme/mesh_creation_functions/beam_arc.py b/src/beamme/mesh_creation_functions/beam_arc.py index 642bac5a..20bbe30b 100644 --- a/src/beamme/mesh_creation_functions/beam_arc.py +++ b/src/beamme/mesh_creation_functions/beam_arc.py @@ -77,7 +77,6 @@ def create_beam_mesh_arc_segment_via_rotation( Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - # Convert the input to the one for create_beam_mesh_arc_segment_via_axis axis = axis_rotation * [0, 0, 1] start_point = center + radius * (axis_rotation * [0, -1, 0]) @@ -134,7 +133,6 @@ def create_beam_mesh_arc_segment_via_axis( Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - # The angle can not be negative with the current implementation. if angle <= 0.0: raise ValueError( @@ -221,7 +219,6 @@ def create_beam_mesh_arc_segment_2d( Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - # The center point has to be on the x-y plane. if _np.abs(center[2]) > _bme.eps_pos: raise ValueError("The z-value of center has to be 0!") diff --git a/src/beamme/mesh_creation_functions/beam_generic.py b/src/beamme/mesh_creation_functions/beam_generic.py index a7635996..a62b8720 100644 --- a/src/beamme/mesh_creation_functions/beam_generic.py +++ b/src/beamme/mesh_creation_functions/beam_generic.py @@ -73,7 +73,6 @@ def _get_interval_node_positions_of_elements( Returns: Numpy array with the node positions within the interval. """ - # Check for mutually exclusive parameters n_given_arguments = sum( 1 @@ -150,7 +149,6 @@ def _get_interval_nodal_positions( middle_node_flags: Numpy array with flags that indicate if a node is an element internal node. """ - if ( _np.abs(nodes_create[0] + 1.0) > _bme.eps_parameter_space or _np.abs(nodes_create[-1] - 1.0) > _bme.eps_parameter_space @@ -187,8 +185,8 @@ def _evaluate_positions_and_rotations( beam_function: _Callable[[float], tuple[_np.ndarray, _Rotation, float | None]], evaluation_positions: _np.ndarray, ) -> tuple[_np.ndarray, list[_Rotation], _np.ndarray]: - """Evaluate positions, rotations and arc lengths along the filament, also - return a flag indicating middle nodes. + """Evaluate positions, rotations and arc lengths along the filament, also return a + flag indicating middle nodes. Args: beam_function: @@ -205,7 +203,6 @@ def _evaluate_positions_and_rotations( arc_lengths: Numpy array with the arc lengths of all nodes along the beam. """ - n_nodes = len(evaluation_positions) coordinates = _np.zeros((n_nodes, 3)) rotations: list[_Rotation] = [] @@ -227,8 +224,7 @@ def _check_given_node_and_return_relative_twist( rotation_from_function: _Rotation, name: str, ) -> _Rotation | None: - """Perform some checks for given nodes and return relative twist if - necessary. + """Perform some checks for given nodes and return relative twist if necessary. If the rotations do not match, check if the first basis vector of the triads is the same. If that is the case, a simple relative twist can be applied to ensure that the triad field is continuous. This relative twist can lead to issues if the beam cross-section is not double symmetric. @@ -248,7 +244,6 @@ def _check_given_node_and_return_relative_twist( be applied to the rotation field is returned. If no relative twist is necessary, None is returned. """ - if node not in mesh.nodes: raise ValueError("The given node is not in the current mesh") @@ -371,7 +366,6 @@ def create_beam_mesh_generic( Geometry sets with the 'start' and 'end' node of the curve. Also a 'line' set with all nodes of the curve. """ - if close_beam and end_node is not None: raise ValueError( 'The arguments "close_beam" and "end_node" are mutually exclusive' diff --git a/src/beamme/mesh_creation_functions/beam_helix.py b/src/beamme/mesh_creation_functions/beam_helix.py index c6dc9255..2d7f2bc8 100644 --- a/src/beamme/mesh_creation_functions/beam_helix.py +++ b/src/beamme/mesh_creation_functions/beam_helix.py @@ -45,10 +45,10 @@ def create_beam_mesh_helix( warning_straight_line=True, **kwargs, ): - """Generate a helical segment starting at a given start point around a - predefined axis (defined by axis_vector and axis_point). The helical - segment is defined by a start_point and exactly two of the basic helical - quantities [helix_angle, height_helix, turns]. + """Generate a helical segment starting at a given start point around a predefined + axis (defined by axis_vector and axis_point). The helical segment is defined by a + start_point and exactly two of the basic helical quantities [helix_angle, + height_helix, turns]. Args ---- @@ -92,7 +92,6 @@ def create_beam_mesh_helix( Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - if [helix_angle, height_helix, turns].count(None) != 1: raise ValueError( "Exactly two arguments of [helix_angle, height_helix, turns]" diff --git a/src/beamme/mesh_creation_functions/beam_line.py b/src/beamme/mesh_creation_functions/beam_line.py index 7345ae64..7d40861b 100644 --- a/src/beamme/mesh_creation_functions/beam_line.py +++ b/src/beamme/mesh_creation_functions/beam_line.py @@ -65,7 +65,6 @@ def create_beam_mesh_line(mesh, beam_class, material, start_point, end_point, ** Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - # Get geometrical values for this line. start_point = _np.asarray(start_point) end_point = _np.asarray(end_point) diff --git a/src/beamme/mesh_creation_functions/beam_node_continuation.py b/src/beamme/mesh_creation_functions/beam_node_continuation.py index 295f5f70..12767ec8 100644 --- a/src/beamme/mesh_creation_functions/beam_node_continuation.py +++ b/src/beamme/mesh_creation_functions/beam_node_continuation.py @@ -36,8 +36,9 @@ def create_beam_mesh_line_at_node( mesh, beam_class, material, start_node, length, **kwargs ): - """Generate a straight line at a given node. The tangent will be the same - as at that node. + """Generate a straight line at a given node. + + The tangent will be the same as at that node. Args ---- @@ -68,7 +69,6 @@ def create_beam_mesh_line_at_node( Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - if length < 0: raise ValueError("Length has to be positive!") @@ -92,8 +92,9 @@ def create_beam_mesh_line_at_node( def create_beam_mesh_arc_at_node( mesh, beam_class, material, start_node, arc_axis_normal, radius, angle, **kwargs ): - """Generate a circular segment starting at a given node. The arc will be - tangent to the given node. + """Generate a circular segment starting at a given node. + + The arc will be tangent to the given node. Args ---- @@ -129,7 +130,6 @@ def create_beam_mesh_arc_at_node( Set with the 'start' and 'end' node of the line. Also a 'line' set with all nodes of the line. """ - # If the angle is negative, the normal is switched arc_axis_normal = _np.asarray(arc_axis_normal) if angle < 0: diff --git a/src/beamme/mesh_creation_functions/beam_parametric_curve.py b/src/beamme/mesh_creation_functions/beam_parametric_curve.py index 10c0b622..d2394a94 100644 --- a/src/beamme/mesh_creation_functions/beam_parametric_curve.py +++ b/src/beamme/mesh_creation_functions/beam_parametric_curve.py @@ -42,12 +42,11 @@ class _ArcLengthEvaluation: - """Class to allow evaluation of the arc length S(t) and the inverse mapping - t(S). + """Class to allow evaluation of the arc length S(t) and the inverse mapping t(S). - This class uses precomputed samples to interpolate between arc - length values. This is much more efficient than root finding - algorithms and should provide a suitable accuracy. + This class uses precomputed samples to interpolate between arc length values. This + is much more efficient than root finding algorithms and should provide a suitable + accuracy. """ def __init__( @@ -92,7 +91,6 @@ def __init__( space, but the middle nodes are placed such that the elements themselves are not distorted. """ - if not scipy_integrate and scipy_integrate_points is not None: raise ValueError( "scipy_integrate_points cannot be provided if scipy_integrate is False!" @@ -111,11 +109,9 @@ def __init__( def _compute_samples(self) -> None: """Compute the samples for the arc length mapping. - This function computes the arc length S(t) at a set of sample - points along the parameter coordinate t with the accumulative - Simpson integration. + This function computes the arc length S(t) at a set of sample points along the + parameter coordinate t with the accumulative Simpson integration. """ - if self.scipy_integrate: ds_dt = lambda t: _np.linalg.norm(self.function_derivative([t])[0]) integral = _quad( @@ -198,16 +194,16 @@ def _compute_interpolation_functions(self) -> None: def approximate_total_arc_length(self) -> float: """Approximate the total arc length along the curve. - This value is only needed to choose the number of elements along - the curve. + This value is only needed to choose the number of elements along the curve. """ return self.S_grid[-1] def get_total_arc_length(self) -> float: """Get the total arc length along the curve. - This function might return a different arc-length than `approximate_total_arc_length`, - if the integral is adaptively refined in `evaluate_all`. + This function might return a different arc-length than + `approximate_total_arc_length`, if the integral is adaptively refined in + `evaluate_all`. """ return self.S_grid[-1] @@ -230,7 +226,6 @@ def evaluate_all( S_evaluate: Arc-length coordinates along the curve for each evaluation point. """ - # Todo: Check if it makes sense to adaptively refine the arc-length # integration here. @@ -296,9 +291,10 @@ def create_beam_mesh_parametric_curve( arc_length_integrator_kwargs: dict | None = None, **kwargs, ) -> _GeometryName | tuple[_GeometryName, float]: - """Generate a beam from a parametric curve. Integration along the beam is - performed with scipy, and if the gradient is not explicitly provided, it is - calculated with the numpy wrapper autograd. + """Generate a beam from a parametric curve. + + Integration along the beam is performed with scipy, and if the gradient is + not explicitly provided, it is calculated with the numpy wrapper autograd. Args ---- @@ -352,7 +348,6 @@ def create_beam_mesh_parametric_curve( Set with the 'start' and 'end' node of the curve. Also a 'line' set with all nodes of the curve. """ - # Set default values for optional arguments. if arc_length_integrator_kwargs is None: arc_length_integrator_kwargs = {} @@ -414,8 +409,7 @@ def function_derivative(t_array): ) class _BeamFunctionGenerator: - """This class manages the creation the actual beam nodes and - rotations.""" + """This class manages the creation the actual beam nodes and rotations.""" def __init__( self, @@ -443,8 +437,8 @@ def __init__( def evaluate_positions_and_rotations( self, evaluation_positions: _np.ndarray, middle_node_flags: _np.ndarray ) -> tuple[_np.ndarray, list[_Rotation], _np.ndarray]: - """This function evaluates the positions and rotations for given - node positions within the interval [0,1]. + """This function evaluates the positions and rotations for given node + positions within the interval [0,1]. Args: evaluation_positions: @@ -460,7 +454,6 @@ def evaluate_positions_and_rotations( rotations: Rotations at all nodes points along the curve. """ - # Get the nodal parameter coordinates and the nodal arc-lengths. t_evaluate, S_evaluate = arc_length_evaluator.evaluate_all( evaluation_positions, middle_node_flags diff --git a/src/beamme/mesh_creation_functions/beam_splinepy.py b/src/beamme/mesh_creation_functions/beam_splinepy.py index 4ee3f67c..8ef9ffe6 100644 --- a/src/beamme/mesh_creation_functions/beam_splinepy.py +++ b/src/beamme/mesh_creation_functions/beam_splinepy.py @@ -30,6 +30,7 @@ def get_curve_function_and_jacobian_for_integration(curve): """Return function objects for evaluating the curve and the derivative. + These functions are used in the curve integration. Args @@ -49,15 +50,14 @@ def get_curve_function_and_jacobian_for_integration(curve): curve_end: Parameter coordinate for the end for the curve """ - curve_start = curve.parametric_bounds[0][0] curve_end = curve.parametric_bounds[1][0] def eval_r(t): """Evaluate the position along the curve. - We need to pass an array with shape (n, 1) to the splinepy - function, we do this by passing a reordered view of t. + We need to pass an array with shape (n, 1) to the splinepy function, we do this + by passing a reordered view of t. """ t = _np.asarray(t) return curve.evaluate(t[:, None]) @@ -65,8 +65,8 @@ def eval_r(t): def eval_rp(t): """Evaluate the derivative along the curve. - We need to pass an array with shape (n, 1) to the splinepy - function, we do this by passing a reordered view of t. + We need to pass an array with shape (n, 1) to the splinepy function, we do this + by passing a reordered view of t. """ t = _np.asarray(t) return curve.derivative(t[:, None], orders=[1]) @@ -101,7 +101,6 @@ def create_beam_mesh_from_splinepy(mesh, beam_class, material, curve, **kwargs): Return: Return value from create_beam_mesh_function """ - ( function, jacobian, diff --git a/src/beamme/mesh_creation_functions/nurbs_generic.py b/src/beamme/mesh_creation_functions/nurbs_generic.py index 5c40a108..45bab41a 100644 --- a/src/beamme/mesh_creation_functions/nurbs_generic.py +++ b/src/beamme/mesh_creation_functions/nurbs_generic.py @@ -85,7 +85,6 @@ def add_splinepy_nurbs_to_mesh( Surfaces: 'surf_w_min', 'surf_w_max', 'surf_v_min', 'surf_v_max', 'surf_v_max', 'surf_u_min' Volume: 'vol' """ - # Make sure that the control points are 3D nurbs_cp_dim = splinepy_obj.control_points.shape[1] if not nurbs_cp_dim == 3: @@ -153,7 +152,6 @@ def add_geomdl_nurbs_to_mesh( Surfaces: 'surf_w_min', 'surf_w_max', 'surf_v_min', 'surf_v_max', 'surf_v_max', 'surf_u_min' Volume: 'vol' """ - # Make sure the material is in the mesh mesh.add_material(material) @@ -191,8 +189,7 @@ def add_geomdl_nurbs_to_mesh( def create_control_points_surface(geomdl_obj): - """Creates a list with the ControlPoint objects of a surface created with - geomdl.""" + """Creates a list with the ControlPoint objects of a surface created with geomdl.""" control_points = [] for dir_v in range(geomdl_obj.ctrlpts_size_v): for dir_u in range(geomdl_obj.ctrlpts_size_u): @@ -212,8 +209,7 @@ def create_control_points_surface(geomdl_obj): def create_control_points_volume(geomdl_obj): - """Creates a list with the ControlPoint objects of a volume created with - geomdl.""" + """Creates a list with the ControlPoint objects of a volume created with geomdl.""" control_points = [] for dir_w in range(geomdl_obj.ctrlpts_size_w): for dir_v in range(geomdl_obj.ctrlpts_size_v): @@ -249,7 +245,6 @@ def create_geometry_sets(element: _NURBSSurface | _NURBSVolume) -> _GeometryName Returns: The geometry set container for the given NURBS patch. """ - # Create return set return_set = _GeometryName() diff --git a/src/beamme/mesh_creation_functions/nurbs_geometries.py b/src/beamme/mesh_creation_functions/nurbs_geometries.py index 2c9a4670..2c80526f 100644 --- a/src/beamme/mesh_creation_functions/nurbs_geometries.py +++ b/src/beamme/mesh_creation_functions/nurbs_geometries.py @@ -51,7 +51,6 @@ def create_nurbs_hollow_cylinder_segment_2d( surf: geomdl object geomdl object that contains the surface information """ - # Check the validity of the input values: if radius_in >= radius_out: raise ValueError( @@ -145,6 +144,7 @@ def create_nurbs_cylindrical_shell_sector( radius: float, angle: float, length: float, *, n_ele_u: int = 1, n_ele_v: int = 1 ) -> _NURBS.Surface: """Creates a NURBS surface representing a 3D sector of a cylindrical shell. + The center of the cylindrical shell sector is located at [0, 0, 0]. Args: @@ -160,7 +160,6 @@ def create_nurbs_cylindrical_shell_sector( Returns: geomdl.NURBS.Surface: A geomdl object that contains the surface information. """ - # Check the validity of the input values: if (angle >= _np.pi) or (angle < 0): raise ValueError( @@ -256,7 +255,6 @@ def create_nurbs_flat_plate_2d(width, length, *, n_ele_u=1, n_ele_v=1): surf: geomdl object geomdl object that contains the surface information """ - # Create a NURBS surface instance surf = _NURBS.Surface() @@ -298,8 +296,9 @@ def create_nurbs_flat_plate_2d(width, length, *, n_ele_u=1, n_ele_v=1): def create_nurbs_sphere_surface(radius, n_ele_u=1, n_ele_v=1): - """Generates a patch of a sphere as a NURBS surface. This function - constructs a segment of a spherical surface using Non-Uniform Rational + """Generates a patch of a sphere as a NURBS surface. + + This function constructs a segment of a spherical surface using Non-Uniform Rational B-Splines (NURBS) based on the specified radius and the number of elements in the parametric u and v directions. @@ -317,7 +316,6 @@ def create_nurbs_sphere_surface(radius, n_ele_u=1, n_ele_v=1): surf: geomdl object geomdl object that contains the surface information """ - # Create a NURBS surface instance surf = _NURBS.Surface() @@ -430,13 +428,14 @@ def create_nurbs_sphere_surface(radius, n_ele_u=1, n_ele_v=1): def create_nurbs_hemisphere_surface(radius, n_ele_uv=1): - """Generates a hemisphere as a NURBS surface. This function constructs five - segments that represent the surface of a hemisphere using Non-Uniform - Rational B-Splines (NURBS) based on the specified radius and the number of - elements in the parametric u and v directions. To secure the connectivity - between surfaces, all surfaces must have the same parametric representation - in any parametric direction. Therefore, the number of elements in u- and v- - directions must be the same. + """Generates a hemisphere as a NURBS surface. + + This function constructs five segments that represent the surface of a + hemisphere using Non-Uniform Rational B-Splines (NURBS) based on the specified + radius and the number of elements in the parametric u and v directions. + To secure the connectivity between surfaces, all surfaces must have the same + parametric representation in any parametric direction. Therefore, the number + of elements in u- and v-directions must be the same. This function generates a list of five NURBS geomdl objects. @@ -452,7 +451,6 @@ def create_nurbs_hemisphere_surface(radius, n_ele_uv=1): list: list(geomdl object) A list of geomdl objects that contains the surface information """ - # Create the first section of the hemisphere hemisphere_1 = create_nurbs_sphere_surface(radius, n_ele_u=1, n_ele_v=1) @@ -697,7 +695,6 @@ def create_nurbs_brick(width, length, height, *, n_ele_u=1, n_ele_v=1, n_ele_w=1 vol: geomdl object geomdl object that contains the volume information """ - # Create a NURBS volume instance vol = _NURBS.Volume() @@ -761,8 +758,7 @@ def create_nurbs_brick(width, length, height, *, n_ele_u=1, n_ele_v=1, n_ele_w=1 def do_uniform_knot_refinement_surface(surf, n_ele_u, n_ele_v): - """This function does an uniform knot refinement in the u- and v- - direction. + """This function does an uniform knot refinement in the u- and v- direction. Args ---- @@ -777,7 +773,6 @@ def do_uniform_knot_refinement_surface(surf, n_ele_u, n_ele_v): ---- surf: geomdl object """ - size_of_knotvector_u = 1 / n_ele_u size_of_knotvector_v = 1 / n_ele_v @@ -788,8 +783,7 @@ def do_uniform_knot_refinement_surface(surf, n_ele_u, n_ele_v): def do_uniform_knot_refinement_volume(vol, n_ele_u, n_ele_v, n_ele_w): - """This function does an uniform knot refinement in the u-, v- and w- - direction. + """This function does an uniform knot refinement in the u-, v- and w- direction. Args ---- @@ -806,7 +800,6 @@ def do_uniform_knot_refinement_volume(vol, n_ele_u, n_ele_v, n_ele_w): ---- vol: geomdl object """ - size_of_knotvector_u = 1 / n_ele_u size_of_knotvector_v = 1 / n_ele_v size_of_knotvector_w = 1 / n_ele_w diff --git a/src/beamme/mesh_creation_functions/nurbs_utils.py b/src/beamme/mesh_creation_functions/nurbs_utils.py index 2a3336b0..e91092b8 100644 --- a/src/beamme/mesh_creation_functions/nurbs_utils.py +++ b/src/beamme/mesh_creation_functions/nurbs_utils.py @@ -36,7 +36,6 @@ def ensure_3d_splinepy_object(splinepy_obj) -> None: 3 dimensions, it will be converted to 3D by adding the missing coordinates with a value of 0. """ - control_points_dim = splinepy_obj.control_points.shape[1] if control_points_dim == 3: pass @@ -58,7 +57,6 @@ def translate_splinepy(splinepy_obj, vector) -> None: vector: _np.array, list 2D/3D vector to translate the splinepy object. """ - if not len(vector) == splinepy_obj.control_points.shape[1]: raise ValueError( f"Dimensions of translation vector and splinepy object do not match: {len(vector)} != {splinepy_obj.control_points.shape[1]}" @@ -70,7 +68,6 @@ def translate_splinepy(splinepy_obj, vector) -> None: def rotate_splinepy(splinepy_obj, rotation: _Rotation, origin=None) -> None: """Rotate a splinepy object by a rotation object.""" - rotation_matrix = rotation.get_rotation_matrix() dimension = splinepy_obj.control_points.shape[1] diff --git a/src/beamme/space_time/beam_to_space_time.py b/src/beamme/space_time/beam_to_space_time.py index 0c87b7ee..277e2264 100644 --- a/src/beamme/space_time/beam_to_space_time.py +++ b/src/beamme/space_time/beam_to_space_time.py @@ -110,7 +110,6 @@ def beam_to_space_time( The nodes sets to be returned for the space time mesh: "start", "end", "surface" """ - # Get the "reference" spatial mesh if callable(mesh_space_or_generator): mesh_space_reference = mesh_space_or_generator(time_start) @@ -337,7 +336,6 @@ def get_space_time_mesh_representation(mesh: _Mesh) -> _MeshRepresentation: Returns: The mesh representation for the space time mesh. """ - element_types = list(set([type(element) for element in mesh.elements])) if len(element_types) > 1: raise ValueError("Got more than a single element type, this is not supported") diff --git a/src/beamme/utils/environment.py b/src/beamme/utils/environment.py index ccbc95d9..bed2a25d 100644 --- a/src/beamme/utils/environment.py +++ b/src/beamme/utils/environment.py @@ -36,7 +36,6 @@ def cubitpy_is_available() -> bool: Returns: True if CubitPy is installed, False otherwise """ - if _find_spec("cubitpy") is None: return False return True @@ -72,8 +71,8 @@ def get_env_variable(name, *, default="default_not_set"): def get_git_data(repo_path: _Path) -> _Tuple[str | None, str | None]: - """Return the hash and date of the current git commit of a git repo for a - given repo path. + """Return the hash and date of the current git commit of a git repo for a given repo + path. Args: repo_path: Path to the git repository. @@ -81,7 +80,6 @@ def get_git_data(repo_path: _Path) -> _Tuple[str | None, str | None]: A tuple with the hash and date of the current git commit if available, otherwise None. """ - git = _shutil.which("git") if git is None: raise RuntimeError("Git executable not found") @@ -110,13 +108,12 @@ def get_git_data(repo_path: _Path) -> _Tuple[str | None, str | None]: def get_application_path() -> _Path | None: - """Returns the application path which created this input file and ensures - that the file exists. + """Returns the application path which created this input file and ensures that the + file exists. Returns: A path to the file, which created this input file or None. """ - # return valid application path if it exists. if _Path(_sys.argv[0]).resolve().exists(): return _Path(_sys.argv[0]).resolve() diff --git a/src/beamme/utils/nodes.py b/src/beamme/utils/nodes.py index 7f74dc6d..f511de32 100644 --- a/src/beamme/utils/nodes.py +++ b/src/beamme/utils/nodes.py @@ -39,8 +39,7 @@ def find_close_nodes(nodes: list[_Node], **kwargs) -> list[list[_Node]]: - """Find nodes in a point cloud that are within a certain tolerance of each - other. + """Find nodes in a point cloud that are within a certain tolerance of each other. Args: nodes: Nodes who are part of the point cloud. @@ -51,7 +50,6 @@ def find_close_nodes(nodes: list[_Node], **kwargs) -> list[list[_Node]]: each element in the returned list contains nodes that are close to each other. """ - coords = _np.zeros([len(nodes), 3]) for i, node in enumerate(nodes): coords[i, :] = node.coordinates @@ -62,14 +60,13 @@ def find_close_nodes(nodes: list[_Node], **kwargs) -> list[list[_Node]]: def adjust_close_nodes(nodes: list[_Node], *, tol=_bme.eps_pos) -> None: - """Adjust the coordinates of nodes that are within the given tolerance by - setting all involved coordinates of the nodes to their common mean. + """Adjust the coordinates of nodes that are within the given tolerance by setting + all involved coordinates of the nodes to their common mean. Args: nodes: List of nodes whose coordinates need adjustment. tol: Distance tolerance used to detect partner nodes. """ - partner_nodes = find_close_nodes(nodes, tol=tol) for close_nodes in partner_nodes: average_coords = _np.mean([node.coordinates for node in close_nodes], axis=0) @@ -96,8 +93,7 @@ def check_node_by_coordinate(node, axis, value, eps=_bme.eps_pos): def get_min_max_coordinates(nodes): - """Return an array with the minimal and maximal coordinates of the given - nodes. + """Return an array with the minimal and maximal coordinates of the given nodes. Return ---- @@ -144,8 +140,9 @@ def get_single_node(item: _Node | _GeometrySetBase) -> _NodeCosserat: def filter_nodes(nodes, *, middle_nodes=True) -> list[_Node]: - """Filter the list of the given nodes. Be aware that if no filters are - enabled the original list will be returned. + """Filter the list of the given nodes. + + Be aware that if no filters are enabled the original list will be returned. Args ---- @@ -154,7 +151,6 @@ def filter_nodes(nodes, *, middle_nodes=True) -> list[_Node]: middle_nodes: bool If middle nodes should be returned or not. """ - if not middle_nodes: return [node for node in nodes if middle_nodes or not node.is_middle_node] else: @@ -224,7 +220,6 @@ def get_min_max_nodes(nodes, *, middle_nodes=False): middle_nodes: bool If this is true, middle nodes of a beam are also returned. """ - node_list = filter_nodes(nodes, middle_nodes=middle_nodes) geometry = _GeometryName() @@ -248,8 +243,8 @@ def get_min_max_nodes(nodes, *, middle_nodes=False): def is_node_on_plane( node, *, normal=None, origin_distance=None, point_on_plane=None, tol=_bme.eps_pos ): - """Query if a node lies on a plane defined by a point_on_plane or the - origin distance. + """Query if a node lies on a plane defined by a point_on_plane or the origin + distance. Args ---- @@ -269,7 +264,6 @@ def is_node_on_plane( ---- True if the point lies on the plane, False otherwise. """ - if origin_distance is None and point_on_plane is None: raise ValueError("Either provide origin_distance or point_on_plane!") elif origin_distance is not None and point_on_plane is not None: diff --git a/tests/beamme/core/test_beamme_core_coupling.py b/tests/beamme/core/test_beamme_core_coupling.py index 9ee755d6..9ac74321 100644 --- a/tests/beamme/core/test_beamme_core_coupling.py +++ b/tests/beamme/core/test_beamme_core_coupling.py @@ -33,7 +33,6 @@ def test_beamme_core_coupling_factory(): """Test that the coupling factory can be used with the desired inputs.""" - nodes = [Node([0, 0, 0]) for i in range(4)] node_set = GeometrySet(nodes) @@ -75,13 +74,11 @@ def test_beamme_core_coupling_factory(): def test_beamme_core_coupling_check_overlapping_coupling_nodes( within_tolerance, check_overlapping_nodes ): - """Per default, we check that coupling nodes are at the same physical - position. + """Per default, we check that coupling nodes are at the same physical position. - This check can be deactivated with the keyword - check_overlapping_nodes when creating a Coupling. + This check can be deactivated with the keyword check_overlapping_nodes when creating + a Coupling. """ - # Create the nodes factor = 0.5 if within_tolerance else 2.0 ref_position = [0.0, 1.5, 3.0] diff --git a/tests/beamme/core/test_beamme_core_geometry_set.py b/tests/beamme/core/test_beamme_core_geometry_set.py index 5646d288..e4009738 100644 --- a/tests/beamme/core/test_beamme_core_geometry_set.py +++ b/tests/beamme/core/test_beamme_core_geometry_set.py @@ -36,14 +36,12 @@ @pytest.fixture() def assert_geometry_set_add_operator() -> Callable: - """Return a function to check the results in the geometry set operator - tests.""" + """Return a function to check the results in the geometry set operator tests.""" def _compare_results( mesh_objects, combined_geometry, set_1_geometry, set_2_geometry ): """Compare the results.""" - # Check that the added geometry set contains the combined geometry assert len(combined_geometry) == 5 assert combined_geometry[0] is mesh_objects[2] @@ -77,10 +75,9 @@ def test_beamme_core_geometry_set_add_operator( ): """Test that geometry sets can be added to each other. - We test this once with a point geometry set based on nodes and once - with a line geometry set based on beam elements. + We test this once with a point geometry set based on nodes and once with a line + geometry set based on beam elements. """ - mesh_objects = [mesh_object(*mesh_object_args) for _ in range(5)] set_1 = GeometrySet(mesh_objects[:3]) set_2 = GeometrySet(mesh_objects[2:]) @@ -100,7 +97,6 @@ def test_beamme_core_geometry_set_nodes_add_operator( geometry_type, assert_geometry_set_add_operator ): """Test that node based geometry sets can be added to each other.""" - mesh_objects = [Node([1, 2, 3]) for _ in range(5)] set_1 = GeometrySetNodes(geometry_type, nodes=mesh_objects[:3]) set_2 = GeometrySetNodes(geometry_type, nodes=mesh_objects[2:]) @@ -114,7 +110,6 @@ def test_beamme_core_geometry_set_nodes_add_operator( def test_beamme_core_geometry_set_add(): """Test functionality of the GeometrySet add method.""" - mesh = Mesh() for i in range(6): mesh.add(NodeCosserat([i, 2 * i, 3 * i], Rotation())) @@ -157,9 +152,8 @@ def test_beamme_core_geometry_set_add(): def test_beamme_core_geometry_set_unique_ordering_of_get_all_nodes_for_line_condition( get_default_test_beam_material, ): - """This test ensures that the ordering of the nodes returned from the - function get_all_nodes is unique for line sets.""" - + """This test ensures that the ordering of the nodes returned from the function + get_all_nodes is unique for line sets.""" # set up a beam mesh with material mesh = Mesh() mat = get_default_test_beam_material(material_type="base") @@ -174,9 +168,7 @@ def test_beamme_core_geometry_set_unique_ordering_of_get_all_nodes_for_line_cond def test_beamme_core_geometry_set_get_geometry_objects(get_default_test_beam_material): - """Test if the geometry set returns the objects(elements) in the correct - order.""" - + """Test if the geometry set returns the objects(elements) in the correct order.""" # Initialize material and mesh mat = get_default_test_beam_material(material_type="base") mesh = Mesh() diff --git a/tests/beamme/core/test_beamme_core_mesh.py b/tests/beamme/core/test_beamme_core_mesh.py index 5f309253..4aec9999 100644 --- a/tests/beamme/core/test_beamme_core_mesh.py +++ b/tests/beamme/core/test_beamme_core_mesh.py @@ -57,9 +57,8 @@ def get_nodes_at_x(node, x_value): def test_beamme_core_mesh_add_checks(): - """This test checks that Mesh raises an error when double objects are added - to the mesh.""" - + """This test checks that Mesh raises an error when double objects are added to the + mesh.""" # Mesh instance for this test. mesh = Mesh() @@ -93,9 +92,8 @@ def test_beamme_core_mesh_add_checks(): def test_beamme_core_mesh_multiple_couple_nodes(): - """The current implementation can handle more than one coupling on a node - correctly, therefore we check this here.""" - + """The current implementation can handle more than one coupling on a node correctly, + therefore we check this here.""" # Create mesh object mesh = Mesh() mat = MaterialBeamBase() @@ -123,7 +121,6 @@ def test_beamme_core_mesh_multiple_couple_nodes(): def test_beamme_core_mesh_get_named_geometry_sets(): """Test the `get_named_geometry_sets` method.""" - mesh = Mesh() mat = MaterialBeamBase() beam_set_1 = create_beam_mesh_line(mesh, Beam3, mat, [0, 0, 0], [1, 0, 0]) @@ -153,9 +150,8 @@ def test_beamme_core_mesh_get_named_geometry_sets(): def test_beamme_core_mesh_get_named_geometry_sets_error(): - """Test that the `get_named_geometry_sets` method raises an error when - geometry sets have duplicate names.""" - + """Test that the `get_named_geometry_sets` method raises an error when geometry sets + have duplicate names.""" mesh = Mesh() mat = MaterialBeamBase() beam_set = create_beam_mesh_line(mesh, Beam3, mat, [0, 0, 0], [1, 0, 0]) diff --git a/tests/beamme/core/test_beamme_core_mesh_utils.py b/tests/beamme/core/test_beamme_core_mesh_utils.py index 49149d93..bfd96b18 100644 --- a/tests/beamme/core/test_beamme_core_mesh_utils.py +++ b/tests/beamme/core/test_beamme_core_mesh_utils.py @@ -30,7 +30,6 @@ def test_beamme_core_mesh_utils_get_coupled_nodes_to_master_map(): """Test the get_coupled_nodes_to_master_map function.""" - beam_class = Beam2 mat = MaterialBeamBase() mesh = Mesh() diff --git a/tests/beamme/core/test_beamme_core_node.py b/tests/beamme/core/test_beamme_core_node.py index d2a40c2b..08d6dff2 100644 --- a/tests/beamme/core/test_beamme_core_node.py +++ b/tests/beamme/core/test_beamme_core_node.py @@ -53,7 +53,6 @@ def test_beamme_core_node_coordinates_data_types( coordinates, increment, assert_results_close ): """Test that different data types for coordinates are handled correctly.""" - node = Node(coordinates=coordinates) node.coordinates += increment diff --git a/tests/beamme/core/test_beamme_core_rotations.py b/tests/beamme/core/test_beamme_core_rotations.py index fd2f0b2b..d89413d8 100644 --- a/tests/beamme/core/test_beamme_core_rotations.py +++ b/tests/beamme/core/test_beamme_core_rotations.py @@ -57,7 +57,6 @@ def test_beamme_core_rotations_cartesian_rotations(assert_results_close): And compare with the rotation matrix. """ - theta = 1.0 # Loop per direction. for i in range(3): @@ -77,7 +76,6 @@ def test_beamme_core_rotations_cartesian_rotations(assert_results_close): def test_beamme_core_rotations_euler_angles(assert_results_close): """Create a rotation with Euler angles and compare to known results.""" - # Euler angles. alpha = 1.1 beta = 1.2 * np.pi * 10 @@ -119,9 +117,8 @@ def test_beamme_core_rotations_euler_angles(assert_results_close): def test_beamme_core_rotations_negative_angles(): - """Check if a rotation is created correctly if a negative angle or a large - angle is given.""" - + """Check if a rotation is created correctly if a negative angle or a large angle is + given.""" vector = 10 * np.array([-1.234243, -2.334343, -1.123123]) phi = -12.152101868665 rot = Rotation(vector, phi) @@ -136,7 +133,6 @@ def test_beamme_core_rotations_negative_angles(): def test_beamme_core_rotations_inverse_rotation(): """Test the inv() function for rotations.""" - # Define test rotation. rot = Rotation([1, 2, 3], 2) @@ -152,7 +148,6 @@ def test_beamme_core_rotations_inverse_rotation(): def test_beamme_core_rotations_rotation_vector(assert_results_close): """Test if the rotation vector functions give a correct result.""" - # Calculate rotation vector and quaternion. axis = np.array([1.36568, -2.96784, 3.23346878]) angle = 0.7189467 @@ -174,7 +169,6 @@ def test_beamme_core_rotations_rotation_vector(assert_results_close): def test_beamme_core_rotations_rotation_operator_overload(assert_results_close): """Test if the operator overloading gives a correct result.""" - # Calculate rotation and vector. axis = np.array([1.36568, -2.96784, 3.23346878]) angle = 0.7189467 @@ -199,10 +193,9 @@ def test_beamme_core_rotations_rotation_operator_overload(assert_results_close): def test_beamme_core_rotations_from_rotation_matrix(vectors, assert_results_close): """Test if the correct quaternions are generated from a rotation matrix. - The from_rotation_matrix function has different branches, the input - vectors to this functions are chosen to trigger all branches. + The from_rotation_matrix function has different branches, the input vectors to this + functions are chosen to trigger all branches. """ - t1, t2 = vectors rot = Rotation().from_basis(t1, t2) t1_rot = rot * [1, 0, 0] @@ -213,7 +206,6 @@ def test_beamme_core_rotations_from_rotation_matrix(vectors, assert_results_clos def test_beamme_core_rotations_from_basis(assert_results_close): """Test the from_basis function for general input values.""" - t1 = [1, 2, 3] t2 = [-1, 3, 1] rot = Rotation().from_basis(t1, t2) @@ -238,7 +230,6 @@ def test_beamme_core_rotations_from_basis(assert_results_close): def test_beamme_core_rotations_transformation_matrix(assert_results_close): """Test that the transformation matrix is computed correctly.""" - rotation_vector_large = [1.0, 2.0, np.pi / 5.0] rotation_large = Rotation.from_rotation_vector(rotation_vector_large) rotation_vector_small = ( @@ -280,7 +271,6 @@ def test_beamme_core_rotations_transformation_matrix(assert_results_close): def test_beamme_core_rotations_smallest_rotation_triad(assert_results_close): """Test that the smallest rotation triad is calculated correctly.""" - # Get the triad obtained by a smallest rotation from an arbitrary triad # onto an arbitrary tangent vector. rot = Rotation([1, 2, 3], 0.431 * np.pi) @@ -297,9 +287,8 @@ def test_beamme_core_rotations_smallest_rotation_triad(assert_results_close): def test_beamme_core_rotations_error_accumulation_multiplication(assert_results_close): - """Test that error accumulation of successive multiplications of rotations - does not affect the results.""" - + """Test that error accumulation of successive multiplications of rotations does not + affect the results.""" rotation_1 = Rotation([1, 2, 3], 0.3) rotation_2 = Rotation([1, -1, -2], np.pi / 6) rotation_3 = Rotation([-1, -2, -3], 7 * np.pi / 17) @@ -320,13 +309,12 @@ def test_beamme_core_rotations_error_accumulation_multiplication(assert_results_ def test_beamme_core_rotations_error_accumulation_smallest_rotation( assert_results_close, ): - """Test that error accumulation of successive smallest rotation mappings - does not affect the results. + """Test that error accumulation of successive smallest rotation mappings does not + affect the results. - Calculate the smallest rotation onto a vector and then rotate that - vector "away" to calculate the next smallest rotation and so on... + Calculate the smallest rotation onto a vector and then rotate that vector "away" to + calculate the next smallest rotation and so on... """ - tangent = [0.9, 0.1, -0.3] rotation_old = Rotation([1, 2, 3], 0.3) @@ -346,7 +334,6 @@ def test_beamme_core_rotations_error_accumulation_smallest_rotation( def test_beamme_core_rotations_rotations_rotation_vector_series(assert_results_close): """Test the function get_rotation_vector_series.""" - director = np.array([1, 2, 3]) director = director / np.linalg.norm(director) director_2 = np.array([1.1, 2.5, 3.1]) diff --git a/tests/beamme/cosserat_curve/test_beamme_cosserat_curve.py b/tests/beamme/cosserat_curve/test_beamme_cosserat_curve.py index 4011dbe8..37c0a1bb 100644 --- a/tests/beamme/cosserat_curve/test_beamme_cosserat_curve.py +++ b/tests/beamme/cosserat_curve/test_beamme_cosserat_curve.py @@ -37,9 +37,8 @@ def test_beamme_cosserat_curve_bad_guess_triad(get_cosserat_curve): def test_beamme_cosserat_curve_pvd_series_arguments(get_cosserat_curve): - """Test the that arguments are correctly processed in the pvd series - representation of the Cosserat curve.""" - + """Test the that arguments are correctly processed in the pvd series representation + of the Cosserat curve.""" curve = get_cosserat_curve() pvd_name = "temp.pvd" @@ -65,7 +64,6 @@ def test_beamme_cosserat_curve_pvd_series_arguments(get_cosserat_curve): def test_beamme_cosserat_curve_project_point(get_cosserat_curve, assert_results_close): """Test that the project point function works as expected.""" - # Load the curve curve = get_cosserat_curve() diff --git a/tests/beamme/four_c/test_beamme_four_c_beam_interaction_conditions.py b/tests/beamme/four_c/test_beamme_four_c_beam_interaction_conditions.py index 9e8b0789..65e890c6 100644 --- a/tests/beamme/four_c/test_beamme_four_c_beam_interaction_conditions.py +++ b/tests/beamme/four_c/test_beamme_four_c_beam_interaction_conditions.py @@ -33,9 +33,7 @@ def test_beamme_four_c_beam_interaction_conditions_condition_id( get_default_test_beam_material, ): - """Ensure that the contact-boundary conditions ids are estimated - correctly.""" - + """Ensure that the contact-boundary conditions ids are estimated correctly.""" # Create the mesh. mesh = Mesh() diff --git a/tests/beamme/four_c/test_beamme_four_c_dbc_monitor.py b/tests/beamme/four_c/test_beamme_four_c_dbc_monitor.py index f924013a..4117044c 100644 --- a/tests/beamme/four_c/test_beamme_four_c_dbc_monitor.py +++ b/tests/beamme/four_c/test_beamme_four_c_dbc_monitor.py @@ -30,7 +30,6 @@ def test_beamme_four_c_dbc_monitor_read_dbc_monitor_file( assert_results_close, get_corresponding_reference_file_path ): """Test that a dbc monitor file can be read correctly.""" - nodes, time, force, moment = read_dbc_monitor_file( get_corresponding_reference_file_path(extension="yaml") ) @@ -43,10 +42,8 @@ def test_beamme_four_c_dbc_monitor_read_dbc_monitor_file( def test_beamme_four_c_dbc_monitor_linear_time_transformation_scaling(): """Test the scaling of the interval for the function. - Starts with a function within the interval [0,1] and transforms - them. + Starts with a function within the interval [0,1] and transforms them. """ - # starting time array time = np.array([0, 0.5, 0.75, 1.0]) @@ -93,7 +90,6 @@ def test_beamme_four_c_dbc_monitor_linear_time_transformation_scaling(): def test_beamme_four_c_dbc_monitor_linear_time_transformation_flip(): """Test the flip flag option of linear_time_transformation to mirror the function.""" - # base case no scaling no end points should be attached # starting time array time = np.array([0, 0.5, 0.75, 1.0]) diff --git a/tests/beamme/four_c/test_beamme_four_c_function_utility.py b/tests/beamme/four_c/test_beamme_four_c_function_utility.py index 02cde0ee..10eeb619 100644 --- a/tests/beamme/four_c/test_beamme_four_c_function_utility.py +++ b/tests/beamme/four_c/test_beamme_four_c_function_utility.py @@ -19,8 +19,7 @@ # 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. -"""This script is used to test the functionality of the function_utility -module.""" +"""This script is used to test the functionality of the function_utility module.""" from beamme.four_c.function_utility import ( create_linear_interpolation_dict, @@ -32,7 +31,6 @@ def test_beamme_four_c_function_utility_linear_interpolation_function( assert_results_close, ): """Test that linear interpolation functions are created correctly.""" - t = [1.5, 2.5, 3.5, 10.0] values = [1.0, -1.0, 3.5, -10.3] diff --git a/tests/beamme/four_c/test_beamme_four_c_material.py b/tests/beamme/four_c/test_beamme_four_c_material.py index 45ed8866..8ee7010f 100644 --- a/tests/beamme/four_c/test_beamme_four_c_material.py +++ b/tests/beamme/four_c/test_beamme_four_c_material.py @@ -37,7 +37,6 @@ def test_beamme_four_c_material_reissner(assert_results_close): """Test Reissner material.""" - mat = MaterialReissner( radius=0.5, youngs_modulus=1234.56, @@ -67,7 +66,6 @@ def test_beamme_four_c_material_reissner(assert_results_close): def test_beamme_four_c_material_reissner_by_modes(assert_results_close): """Test Reissner material by modes with scaling factors.""" - mat = MaterialReissner( radius=0.5, youngs_modulus=1234.56, @@ -104,7 +102,6 @@ def test_beamme_four_c_material_reissner_by_modes(assert_results_close): def test_beamme_four_c_material_reissner_elasto_plastic(assert_results_close): """Test the elasto plastic Reissner beam material.""" - kwargs = { "radius": 0.1, "nu": 1.0, @@ -223,7 +220,6 @@ def set_stiff(material): def test_beamme_four_c_material_stvenantkirchhoff_solid(assert_results_close): """Test that the solid with St_Venant Kirchhoff material.""" - material = MaterialStVenantKirchhoff(youngs_modulus=157, nu=0.17, density=6.1e-7) assert_results_close( material.dump_to_list(), @@ -240,7 +236,6 @@ def test_beamme_four_c_material_stvenantkirchhoff_solid(assert_results_close): def test_beamme_four_c_material_sub_materials(): """Test that sub-materials are correctly returned from the material.""" - material_1_1 = MaterialSolid(material_string="mat_1_1") material_1_2 = MaterialSolid(material_string="mat_1_2") material_1 = MaterialSolid( @@ -284,7 +279,6 @@ def test_beamme_four_c_material_sub_materials(): def test_beamme_four_c_material_sub_materials_circular_loop(): """Test that sub-materials containing circular loops are detected.""" - material_3 = MaterialSolid(material_string="mat_3", data={"MATIDS": [None]}) material_2 = MaterialSolid(material_string="mat_2", data={"MATIDS": [material_3]}) material_1 = MaterialSolid(material_string="mat_2", data={"MATIDS": [material_2]}) @@ -299,7 +293,6 @@ def test_beamme_four_c_material_sub_materials_circular_loop(): def test_beamme_four_c_material_sub_materials_indexing(): """Check the error for incorrectly added sub-materials.""" - mesh = Mesh() material_sub = MaterialSolid( material_string="ELAST_CoupSVK", data={"YOUNG": 1.0, "NUE": 0.0} diff --git a/tests/beamme/four_c/test_beamme_four_c_run_four_c.py b/tests/beamme/four_c/test_beamme_four_c_run_four_c.py index 3e40634d..ce82a0c1 100644 --- a/tests/beamme/four_c/test_beamme_four_c_run_four_c.py +++ b/tests/beamme/four_c/test_beamme_four_c_run_four_c.py @@ -30,8 +30,7 @@ @pytest.fixture def create_simulation_dir(tmp_path): - """Fixture to create a dummy simulation directory with a file and - subdirectory.""" + """Fixture to create a dummy simulation directory with a file and subdirectory.""" simulation_dir = tmp_path / "existing_dir" simulation_dir.mkdir() simulation_sub_dir = simulation_dir / "sub" diff --git a/tests/beamme/geometric_search/test_beamme_geometric_search_utils.py b/tests/beamme/geometric_search/test_beamme_geometric_search_utils.py index 428e866b..0da8fa01 100644 --- a/tests/beamme/geometric_search/test_beamme_geometric_search_utils.py +++ b/tests/beamme/geometric_search/test_beamme_geometric_search_utils.py @@ -31,7 +31,6 @@ def test_beamme_geometric_search_utils_is_arborx_available() -> None: """Test is_arborx_available function.""" - with patch("beamme.geometric_search.utils._find_spec", return_value=True): assert arborx_is_available() is True @@ -41,7 +40,6 @@ def test_beamme_geometric_search_utils_is_arborx_available() -> None: def test_beamme_geometric_search_utils_is_cython_available() -> None: """Test is_cython_available function.""" - with patch("beamme.geometric_search.utils._find_spec", return_value=True): assert cython_is_available() is True diff --git a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_generic.py b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_generic.py index dc8295b3..3b5533d2 100644 --- a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_generic.py +++ b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_generic.py @@ -41,9 +41,8 @@ def test_beamme_mesh_creation_functions_beam_generic_start_end_node_error( get_default_test_beam_material, ): - """Check that an error is raised if wrong start and end nodes are given to - a mesh creation function.""" - + """Check that an error is raised if wrong start and end nodes are given to a mesh + creation function.""" # Create mesh object. mesh = Mesh() mat = get_default_test_beam_material(material_type="base") @@ -63,7 +62,6 @@ def test_beamme_mesh_creation_functions_beam_generic_start_end_node_error( def test_beamme_mesh_creation_functions_beam_generic_argument_checks(): """Test that wrong input values leads to failure.""" - dummy_arg = "dummy" # Check error messages for input parameters @@ -201,7 +199,6 @@ def test_beamme_mesh_creation_functions_beam_generic_arc_length_argument_checks( get_default_test_beam_material, ): """Test that wrong input values leads to failure.""" - dummy_arg = "dummy" # Check error messages for input parameters @@ -374,9 +371,7 @@ def test_beamme_mesh_creation_functions_beam_generic_arc_length( get_default_test_beam_material, assert_results_close, ): - """Test that the arc length can be stored in the nodes when creating a - filament.""" - + """Test that the arc length can be stored in the nodes when creating a filament.""" node_positions_of_elements = [0, 0.25, 1] mat = get_default_test_beam_material(material_type="reissner") offset = 3.0 @@ -389,9 +384,7 @@ def test_beamme_mesh_creation_functions_beam_generic_arc_length( end_rot = Rotation() def create_beam(mesh, **kwargs): - """Wrapper for the common arguments in the call to create the - line.""" - + """Wrapper for the common arguments in the call to create the line.""" create_beam_mesh_line( mesh, Beam3, @@ -410,9 +403,7 @@ def create_beam(mesh, **kwargs): end_rot = Rotation([0, 0, 1], 1.5 * np.pi) def create_beam(mesh, **kwargs): - """Wrapper for the common arguments in the call to create the - arc.""" - + """Wrapper for the common arguments in the call to create the arc.""" create_beam_mesh_arc_segment_2d( mesh, Beam3, @@ -443,9 +434,8 @@ def create_beam(mesh, **kwargs): n = 0.5 def create_beam(mesh, **kwargs): - """Wrapper for the common arguments in the call to create the - parametric curve beam mesh (helix).""" - + """Wrapper for the common arguments in the call to create the parametric + curve beam mesh (helix).""" create_beam_mesh_parametric_curve( mesh, Beam3, @@ -476,8 +466,7 @@ def get_start_and_end_node(*, arc_length_start=None, arc_length_end=None): return (start_node, end_node) def check_arc_length(mesh, arc_length_ref): - """Compare the arc lengths of the nodes in mesh with reference - values.""" + """Compare the arc lengths of the nodes in mesh with reference values.""" arc_length_from_mesh = np.array([node.arc_length for node in mesh.nodes]) assert_results_close( {"arc_length": arc_length_from_mesh}, {"arc_length": arc_length_ref} diff --git a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_node_continuation.py b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_node_continuation.py index 47b82693..52b8f7a7 100644 --- a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_node_continuation.py +++ b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_node_continuation.py @@ -35,13 +35,12 @@ def test_beamme_mesh_creation_functions_beam_node_continuation_accumulated_arc( get_default_test_beam_material, assert_results_close ): - """Test that the arc node continuation function can be applied multiple - times in a row. + """Test that the arc node continuation function can be applied multiple times in a + row. - This function can lead to accumulated errors in the rotations if not - implemented carefully. + This function can lead to accumulated errors in the rotations if not implemented + carefully. """ - mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") mesh.add(mat) diff --git a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_parametric_curve.py b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_parametric_curve.py index 83207d36..8b89d508 100644 --- a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_parametric_curve.py +++ b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_parametric_curve.py @@ -183,8 +183,8 @@ def test_beamme_mesh_creation_functions_beam_parametric_curve_arc_length_evaluat def function_derivative(t): """A C0 continuous function to test the arc length integration. - The first part is a sinus, and then constant. Thus the - analytical integral is easy to compute. + The first part is a sinus, and then constant. Thus the analytical integral is + easy to compute. """ if t < 2.0 * np.pi: return [2.0 + np.sin(t), 0.0, 0.0] @@ -220,7 +220,6 @@ def function_derivative_vectorized(t): def test_beamme_mesh_creation_functions_beam_parametric_curve_arc_length_evaluation_arguments(): """Check that an error is raised for wrong combination of arguments.""" - with pytest.raises( ValueError, match=re.escape( @@ -234,7 +233,6 @@ def test_beamme_mesh_creation_functions_beam_parametric_curve_arc_length_evaluat def test_beamme_mesh_creation_functions_beam_parametric_curve_interval(): """Check that an error is raised if wrong intervals are given.""" - with pytest.raises( ValueError, match=re.escape( @@ -257,8 +255,8 @@ def test_beamme_mesh_creation_functions_beam_parametric_curve_interval(): def test_beamme_mesh_creation_functions_beam_parametric_curve_vectorized(): - """Check that an error is raised if wrong combination of vectorized - functions is given.""" + """Check that an error is raised if wrong combination of vectorized functions is + given.""" def function_vectorized(dummy): """A dummy function for testing.""" diff --git a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_splinepy.py b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_splinepy.py index f5dcc0c0..40cf3d43 100644 --- a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_splinepy.py +++ b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_beam_splinepy.py @@ -29,9 +29,8 @@ def test_beamme_mesh_creation_functions_beam_splinepy_function_and_jacobian( get_splinepy_object, assert_results_close ): - """Unittest the function and jacobian creation in the - create_beam_mesh_from_splinepy function.""" - + """Unittest the function and jacobian creation in the create_beam_mesh_from_splinepy + function.""" curve = get_splinepy_object("curve_nurbs") r, dr, _, _ = get_curve_function_and_jacobian_for_integration(curve) diff --git a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_generic.py b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_generic.py index d7d2791e..160b9861 100644 --- a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_generic.py +++ b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_generic.py @@ -213,9 +213,8 @@ def test_beamme_mesh_creation_functions_nurbs_generic_sets( nurbs_patch, solid_type_string, get_default_test_solid_element, reference_values ): - """Test that the add NURBS to mesh functionality returns the correct - geometry sets.""" - + """Test that the add NURBS to mesh functionality returns the correct geometry + sets.""" # Add the nurbs to a mesh mesh = Mesh() element_type = get_default_test_solid_element(solid_type_string) diff --git a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_utils.py b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_utils.py index d15cc20f..7181b059 100644 --- a/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_utils.py +++ b/tests/beamme/mesh_creation_functions/test_beamme_mesh_creation_functions_nurbs_utils.py @@ -35,8 +35,8 @@ class MockSpline: """Minimal mock class to mimic a splinepy object with control points. - By using this mock, we can test that the translate and rotate - functions only modify the control points. + By using this mock, we can test that the translate and rotate functions only modify + the control points. """ def __init__(self, control_points): @@ -66,8 +66,7 @@ def test_beamme_mesh_creation_functions_nurbs_utils_translate_splinepy_3d( def test_beamme_mesh_creation_functions_nurbs_utils_translate_invalid_dimension(): - """Test that translation with a vector of incorrect dimension raises - error.""" + """Test that translation with a vector of incorrect dimension raises error.""" spline = MockSpline([[0.0, 0.0]]) with pytest.raises(ValueError, match="Dimensions of translation"): translate_splinepy(spline, [1.0, 2.0, 3.0]) @@ -86,8 +85,8 @@ def test_beamme_mesh_creation_functions_nurbs_utils_rotate_splinepy_2d( def test_beamme_mesh_creation_functions_nurbs_utils_rotate_splinepy_invalid_2d_rotation(): - """Test that a 2D splinepy object can only be rotated by a rotation around - the z-axis.""" + """Test that a 2D splinepy object can only be rotated by a rotation around the + z-axis.""" spline = MockSpline([[1.0, 0.0]]) rotation = Rotation([1, 1, 0], np.pi / 3) with pytest.raises(ValueError, match="Rotation vector must be in"): @@ -98,8 +97,7 @@ def test_beamme_mesh_creation_functions_nurbs_utils_rotate_splinepy_invalid_2d_r def test_beamme_mesh_creation_functions_nurbs_utils_rotate_splinepy_3d_origin( origin, assert_results_close ): - """Test rotation of a 3D splinepy object with and without given origin - argument.""" + """Test rotation of a 3D splinepy object with and without given origin argument.""" points = np.array([[1.0, 2.0, 3.0], [2.0, 3.0, 4.0]]) spline = MockSpline(points) rotation = Rotation([1.0, 2.0, 3.0], np.pi / 3.0) @@ -128,8 +126,7 @@ def test_beamme_mesh_creation_functions_nurbs_utils_ensure_3d_splinepy_object_al def test_beamme_mesh_creation_functions_nurbs_utils_ensure_3d_splinepy_object_from_1d( assert_results_close, ): - """Ensure that a 1D splinepy object is converted to 3D by adding y=0 and - z=0.""" + """Ensure that a 1D splinepy object is converted to 3D by adding y=0 and z=0.""" original_points = np.array([[1.0], [3.0]]) spline = MockSpline(original_points) ensure_3d_splinepy_object(spline) diff --git a/tests/beamme/utils/test_beamme_utils_data_structures.py b/tests/beamme/utils/test_beamme_utils_data_structures.py index 7fd28793..e44371ce 100644 --- a/tests/beamme/utils/test_beamme_utils_data_structures.py +++ b/tests/beamme/utils/test_beamme_utils_data_structures.py @@ -28,7 +28,6 @@ def test_beamme_utils_data_structures_create_inverse_mapping(): """Test the create_inverse_mapping function.""" - # Test with a simple mapping. mapping = {1: "a", 2: "b", 3: "c"} inverse_mapping = create_inverse_mapping(mapping) diff --git a/tests/beamme/utils/test_beamme_utils_environment.py b/tests/beamme/utils/test_beamme_utils_environment.py index 02818dd5..06cab237 100644 --- a/tests/beamme/utils/test_beamme_utils_environment.py +++ b/tests/beamme/utils/test_beamme_utils_environment.py @@ -38,7 +38,6 @@ def test_beamme_utils_environment_is_cubitpy_available() -> None: """Test is_cubitpy_available function.""" - with patch("beamme.utils.environment._find_spec", return_value=True): assert cubitpy_is_available() is True @@ -48,7 +47,6 @@ def test_beamme_utils_environment_is_cubitpy_available() -> None: def test_beamme_utils_environment_is_mybinder() -> None: """Test is_mybinder function.""" - with patch.dict(os.environ, {"BINDER_LAUNCH_HOST": "some_value"}): assert is_mybinder() is True @@ -58,7 +56,6 @@ def test_beamme_utils_environment_is_mybinder() -> None: def test_beamme_utils_environment_is_testing() -> None: """Test is_testing function.""" - with patch.dict(os.environ, {"PYTEST_CURRENT_TEST": "some_value"}): assert is_testing() is True @@ -68,7 +65,6 @@ def test_beamme_utils_environment_is_testing() -> None: def test_beamme_utils_environment_get_env_variable() -> None: """Test get_env_variable function.""" - with patch.dict(os.environ, {"TEST_VAR": "test_value"}): assert get_env_variable("TEST_VAR") == "test_value" @@ -86,7 +82,6 @@ def test_beamme_utils_environment_get_env_variable() -> None: @patch("beamme.utils.environment._subprocess.run") def test_beamme_utils_environment_get_git_data_success(mock_run, mock_which): """Test get_git_data function with successful git command execution.""" - mock_which.return_value = "/usr/bin/git" mock_sha_process = MagicMock() @@ -109,7 +104,6 @@ def test_beamme_utils_environment_get_git_data_success(mock_run, mock_which): @patch("beamme.utils.environment._shutil.which") def test_beamme_utils_environment_get_git_data_git_not_found(mock_which): """Test get_git_data function when git executable is not found.""" - mock_which.return_value = None with pytest.raises(RuntimeError, match="Git executable not found"): @@ -120,7 +114,6 @@ def test_beamme_utils_environment_get_git_data_git_not_found(mock_which): @patch("beamme.utils.environment._subprocess.run") def test_beamme_utils_environment_get_git_data_subprocess_failure(mock_run, mock_which): """Test get_git_data function with subprocess command failure.""" - mock_which.return_value = "/usr/bin/git" mock_failed_process = MagicMock() diff --git a/tests/beamme/utils/test_beamme_utils_nodes.py b/tests/beamme/utils/test_beamme_utils_nodes.py index bb583161..00f036d7 100644 --- a/tests/beamme/utils/test_beamme_utils_nodes.py +++ b/tests/beamme/utils/test_beamme_utils_nodes.py @@ -34,7 +34,6 @@ def test_beamme_utils_nodes_adjusting_of_nodes(assert_results_close): """Test the mesh function adjust_close_nodes.""" - coordinates = np.array( [[0, 0, 0], [1, 0, 0], [2, 0, 0], [1.3, 0, 0], [1.0, 0.3, 0], [2, 0, 0.2]] ) @@ -55,7 +54,6 @@ def test_beamme_utils_nodes_adjusting_of_nodes(assert_results_close): def test_beamme_utils_nodes_is_node_on_plane(): """Test if node on plane function works properly.""" - # node on plane with origin_distance node = Node([1.0, 1.0, 1.0]) assert is_node_on_plane(node, normal=[0.0, 0.0, 1.0], origin_distance=1.0) @@ -79,7 +77,6 @@ def test_beamme_utils_nodes_is_node_on_plane(): def test_beamme_utils_nodes_get_min_max_coordinates(assert_results_close): """Test if the get_min_max_coordinates function works properly.""" - # Create the mesh. nodes = [] nodes.append(Node([0.0, 0.0, 0.0])) diff --git a/tests/conftest.py b/tests/conftest.py index 16bc9129..d7d06573 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -39,8 +39,8 @@ ] # Track used and unused reference files during testing if corresponding flag is enabled -USED_REFERENCE_FILES = set() -UNUSED_REFERENCE_FILES = set() +USED_REFERENCE_FILES: set[str] = set() +UNUSED_REFERENCE_FILES: set[str] = set() def pytest_addoption(parser: Parser) -> None: @@ -49,7 +49,6 @@ def pytest_addoption(parser: Parser) -> None: Args: parser: Pytest parser """ - parser.addoption( "--4C", action="store_true", @@ -94,10 +93,9 @@ def pytest_addoption(parser: Parser) -> None: def _check_naming_convention(item) -> None: - """Check that the test name aligns with the naming conventions, i.e., the - test file name has to be named according to the directory structure and the - test name must start with the test file name.""" - + """Check that the test name aligns with the naming conventions, i.e., the test file + name has to be named according to the directory structure and the test name must + start with the test file name.""" test_name = item.name testing_root = Path(__file__).parent @@ -138,7 +136,6 @@ def pytest_collection_modifyitems(config: Config, items: list) -> None: config: Pytest config items: Pytest list of tests """ - # Get all active markers for this pytest run active_markers = set() for flag, marker in zip( @@ -192,7 +189,6 @@ def reference_file_directory() -> Path: Returns: Path: A Path object representing the full path to the reference file directory. """ - testing_path = Path(__file__).resolve().parent return testing_path / "reference-files" @@ -207,7 +203,6 @@ def current_test_name(request: pytest.FixtureRequest) -> str: Returns: str: The name of the current pytest test. """ - return request.node.originalname @@ -215,8 +210,7 @@ def current_test_name(request: pytest.FixtureRequest) -> str: def get_corresponding_reference_file_path( reference_file_directory, current_test_name ) -> Callable: - """Return function to get path to corresponding reference file for each - test. + """Return function to get path to corresponding reference file for each test. Necessary to enable the function call through pytest fixtures. """ @@ -228,9 +222,10 @@ def _get_corresponding_reference_file_path( additional_identifier_separator: str = "_", extension: str = "4C.yaml", ) -> Path: - """Get path to corresponding reference file for each test. Also check - if this file exists. Basename, additional identifier and extension can - be adjusted. + """Get path to corresponding reference file for each test. + + Also check if this file exists. Basename, additional identifier and + extension can be adjusted. Args: reference_file_base_name: Basename of reference file, if none is @@ -250,7 +245,6 @@ def _get_corresponding_reference_file_path( Returns: Path to reference file. """ - if ( reference_file_base_name is not None and test_name_suffix_trim_count is not None @@ -293,11 +287,9 @@ def _get_corresponding_reference_file_path( def sessionfinish_unused_reference_files(session): """Exit with exit code 1 if any unused reference files are detected. - This is utilized to ensure that the Github Actions workflow fails if - unused reference files are detected when the corresponding flag is - enabled. + This is utilized to ensure that the Github Actions workflow fails if unused + reference files are detected when the corresponding flag is enabled. """ - if session.config.getoption("--check-for-unused-reference-files"): # reference_file_directory fixture is not able to be used here (fixtures cannot be called directly) reference_file_directory = Path(__file__).resolve().parent / "reference-files" @@ -313,9 +305,7 @@ def sessionfinish_unused_reference_files(session): def terminal_summary_unused_reference_files(terminalreporter): - """Print a summary of unused reference files at the end of the pytest - run.""" - + """Print a summary of unused reference files at the end of the pytest run.""" if UNUSED_REFERENCE_FILES: terminalreporter.write_sep( "=", "Unused Reference Files Found", red=True, bold=True @@ -325,14 +315,13 @@ def terminal_summary_unused_reference_files(terminalreporter): def pytest_sessionfinish(session): - """Exit with exit code 1 if any performance test failed or unused reference - files are detected. + """Exit with exit code 1 if any performance test failed or unused reference files + are detected. - This is utilized to ensure that the Github Actions workflow fails if - performance tests exceed their expected execution time or if unused - reference files are detected when the corresponding flag is enabled. + This is utilized to ensure that the Github Actions workflow fails if performance + tests exceed their expected execution time or if unused reference files are detected + when the corresponding flag is enabled. """ - # import here instead of at the top, otherwise pytest warns due to double import via pytest_plugins from tests.conftest_performance_tests import sessionfinish_performance_tests @@ -341,9 +330,8 @@ def pytest_sessionfinish(session): def pytest_terminal_summary(terminalreporter): - """Print a summary of performance tests or unused reference files at the - end of the pytest run.""" - + """Print a summary of performance tests or unused reference files at the end of the + pytest run.""" # import here instead of at the top, otherwise pytest warns due to double import via pytest_plugins from tests.conftest_performance_tests import terminal_summary_performance_tests diff --git a/tests/conftest_performance_tests.py b/tests/conftest_performance_tests.py index 06af5435..c819a42c 100644 --- a/tests/conftest_performance_tests.py +++ b/tests/conftest_performance_tests.py @@ -27,7 +27,7 @@ import pytest -PERFORMANCE_LOG = {} +PERFORMANCE_LOG: dict[str, dict[str, float]] = {} @pytest.fixture(scope="module") @@ -57,7 +57,6 @@ def _evaluate_execution_time( kwargs: Keyword arguments for the function. expected_time: Expected execution time in seconds. """ - start_time = time.time() result = function(*args, **kwargs) elapsed_time = time.time() - start_time @@ -81,10 +80,9 @@ def _evaluate_execution_time( def sessionfinish_performance_tests(session): """Exit with exit code 1 if any performance test failed. - This is utilized to ensure that the Github Actions workflow fails if - performance tests exceed their expected execution time. + This is utilized to ensure that the Github Actions workflow fails if performance + tests exceed their expected execution time. """ - if PERFORMANCE_LOG: for data in PERFORMANCE_LOG.values(): if data["execution_time"] > data["expected_time"]: @@ -94,7 +92,6 @@ def sessionfinish_performance_tests(session): def terminal_summary_performance_tests(terminalreporter): """Print a summary of performance tests at the end of the pytest run.""" - if PERFORMANCE_LOG: terminalreporter.write_sep("=", "Performance Test Summary") diff --git a/tests/conftest_result_comparison.py b/tests/conftest_result_comparison.py index 98237d18..f4bce92a 100644 --- a/tests/conftest_result_comparison.py +++ b/tests/conftest_result_comparison.py @@ -72,8 +72,7 @@ def _assert_results_close( atol: float = ABSOLUTE_TOLERANCE, four_c_input_file_data_format: str = "yaml", ) -> None: - """Comparison between reference and result with relative or absolute - tolerance. + """Comparison between reference and result with relative or absolute tolerance. If the comparison fails, an assertion is raised. @@ -84,7 +83,6 @@ def _assert_results_close( atol: The absolute tolerance. four_c_input_file_data_format: Mesh format for the FourC input file. """ - # convert all other types into dicts/lists converted_reference = convert_to_primitive_type( reference, four_c_input_file_data_format=four_c_input_file_data_format @@ -116,8 +114,8 @@ def convert_to_primitive_type( obj: str | int | float | dict | list | np.ndarray | Path | Mesh | InputFile, four_c_input_file_data_format: str | None = None, ) -> int | float | dict | list | np.ndarray | pv.UnstructuredGrid: - """Convert the given object to a primitive type, e.g., dict, list, numpy - array, or pyvista grid. + """Convert the given object to a primitive type, e.g., dict, list, numpy array, or + pyvista grid. Args: obj: The object to convert. @@ -126,7 +124,6 @@ def convert_to_primitive_type( Returns: The raw data (either a dictionary, list, numpy array, or pyvista grid). """ - if isinstance(obj, (int, float, dict, list, np.ndarray)): return obj @@ -199,8 +196,7 @@ def convert_to_primitive_type( # Split the string into individual fragments which can then be compared with tolerance def str_to_float(string: str) -> str | float: - """Convert string to float if possible, otherwise return the - string. + """Convert string to float if possible, otherwise return the string. Args: string: The string to convert. @@ -227,8 +223,8 @@ def str_to_float(string: str) -> str | float: def custom_fourcipp_comparison( obj: Any, reference_obj: Any, rtol: float, atol: float ) -> bool | None: - """Custom comparison function for the FourCIPP - compare_nested_dicts_or_lists function. + """Custom comparison function for the FourCIPP compare_nested_dicts_or_lists + function. Comparison between two special objects like numpy arrays or pyvista grids. @@ -240,7 +236,6 @@ def custom_fourcipp_comparison( True if the objects are equal, otherwise raises an AssertionError. If no comparison took place, None is returned. """ - if isinstance(obj, (np.ndarray, np.generic)) or isinstance( reference_obj, (np.ndarray, np.generic) ): @@ -278,7 +273,6 @@ def handle_failed_assertion( reference: The reference data. result: The result data. """ - # if reference is not a file or if result is not a Mesh or InputFile we do not open the diff if not isinstance(reference, Path) or not isinstance(result, (Mesh, InputFile)): return diff --git a/tests/conftest_test_object_generators.py b/tests/conftest_test_object_generators.py index e208e72b..94b4a892 100644 --- a/tests/conftest_test_object_generators.py +++ b/tests/conftest_test_object_generators.py @@ -42,22 +42,20 @@ @pytest.fixture(scope="function") def get_bc_data() -> Callable: - """Return a function to create a dummy definition for a boundary condition - in 4C. + """Return a function to create a dummy definition for a boundary condition in 4C. Returns: A function to create a dummy boundary condition definition. """ def _get_bc_data(*, identifier=None, num_dof: int = 3) -> Dict: - """Return a dummy definition for a boundary condition in 4C that can be - used for testing purposes. + """Return a dummy definition for a boundary condition in 4C that can be used for + testing purposes. Args: identifier: Any value, will be written to the value for the first DOF. This can be used to create multiple boundary conditions and distinguish them in the input file. num_dof: Number of degrees of freedom constrained by this boundary condition. """ - val = [0] * num_dof if identifier is not None: val[0] = identifier @@ -74,8 +72,7 @@ def _get_bc_data(*, identifier=None, num_dof: int = 3) -> Dict: @pytest.fixture(scope="function") def get_default_test_beam_material() -> Callable: - """Return a function to create a default beam material for testing - purposes. + """Return a function to create a default beam material for testing purposes. Returns: A function that creates a default beam material. @@ -90,7 +87,6 @@ def _get_default_test_beam_material(material_type: str = "base", **kwargs): Returns: A material object corresponding to the specified beam type. """ - if material_type == "base": return MaterialBeamBase(radius=1.0, **kwargs) @@ -107,8 +103,7 @@ def _get_default_test_beam_material(material_type: str = "base", **kwargs): @pytest.fixture(scope="function") def get_default_test_solid_material() -> Callable: - """Return a function to create a default solid material for testing - purposes. + """Return a function to create a default solid material for testing purposes. Returns: A function that creates a default solid material. @@ -125,7 +120,6 @@ def _get_default_test_solid_material( Returns: A material object corresponding to the specified solid material type. """ - if material_type == "st_venant_kirchhoff": return MaterialStVenantKirchhoff(youngs_modulus=1.0, nu=0.3, density=1.0) @@ -171,8 +165,7 @@ def _get_default_test_solid_material( @pytest.fixture(scope="function") def get_default_test_solid_element() -> Callable: - """Return a function to create a default solid element type for testing - purposes. + """Return a function to create a default solid element type for testing purposes. Returns: A function that creates a default solid element type. @@ -187,7 +180,6 @@ def _get_default_test_solid_element(element_type: str) -> type[Element]: Returns: A type defining a solid element for testing purposes. """ - if element_type == "nurbs_2d": return get_four_c_solid( bme.element_type.nurbs, @@ -237,10 +229,11 @@ def get_helix_function( transformation_factor: float | None = None, number_of_turns: float | None = None, ) -> Callable[[float], npAD.ndarray]: - """Create and return a parametric function that represents a helix - shape. The parameter coordinate can optionally be stretched to make the - curve arc-length along the parameter coordinated non-constant and - create a more complex curve for testing purposes. + """Create and return a parametric function that represents a helix shape. + + The parameter coordinate can optionally be stretched to make the curve arc-length + along the parameter coordinated non-constant and create a more complex curve for + testing purposes. Args: radius: Radius of the helix @@ -253,7 +246,6 @@ def get_helix_function( Returns: A function that describes a helix in 3D space. """ - if transformation_factor is None and number_of_turns is None: def transformation(t): @@ -294,15 +286,13 @@ def helix(t): def distorted_helix(t: float): """Parametric function to describe a distorted helix. - The resulting curve has a large variation in the Jacobian along - the curve, thus making it a good test case for the curve - integration robustness and performance. + The resulting curve has a large variation in the Jacobian along the curve, thus + making it a good test case for the curve integration robustness and performance. """ return npAD.array([t, 10 * npAD.sin(t), npAD.cos(t)]) def _get_parametric_function(function_type: str, *args, **kwargs) -> Callable: - """Return a function representing a parametric curve for testing - purposes. + """Return a function representing a parametric curve for testing purposes. Args: function_type: The type of parametric function to create. @@ -312,7 +302,6 @@ def _get_parametric_function(function_type: str, *args, **kwargs) -> Callable: Returns: A function that creates a parametric curve. """ - if function_type == "helix": return get_helix_function(*args, **kwargs) elif function_type == "distorted_helix": @@ -336,7 +325,6 @@ def _get_splinepy_object(splinepy_type: str) -> splinepy.Spline: Returns: A splinepy object. """ - if splinepy_type == "curve_bezier": control_points = np.array( [ @@ -377,8 +365,7 @@ def get_cosserat_curve() -> Callable: coordinates.""" def _get_cosserat_curve(**kwargs) -> CosseratCurve: - """Create a Cosserat curve from a predefined set of point - coordinates.""" + """Create a Cosserat curve from a predefined set of point coordinates.""" point_coordinates = np.array( [ [ diff --git a/tests/create_test_models.py b/tests/create_test_models.py index 90b34aef..fddcf33d 100644 --- a/tests/create_test_models.py +++ b/tests/create_test_models.py @@ -19,8 +19,8 @@ # 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. -"""This script contains functionality to create solid input files (or plain -cubit instances) with CubitPy which are then used in testing.""" +"""This script contains functionality to create solid input files (or plain cubit +instances) with CubitPy which are then used in testing.""" from beamme.core.boundary_condition import BoundaryCondition from beamme.core.conf import bme @@ -59,7 +59,6 @@ def create_tube_cubit_mesh(r, h, n_circumference, n_height): ---- The created cubit object. """ - # Initialize cubit. cubit = CubitPy() @@ -80,7 +79,6 @@ def create_tube_cubit_mesh(r, h, n_circumference, n_height): def create_tube_cubit(): """Load the solid tube and add input file parameters.""" - # Initialize cubit. cubit, cylinder = create_tube_cubit_mesh(0.25, 10.0, 6, 10) @@ -172,7 +170,6 @@ def create_tube_cubit(): def create_block_cubit(): """Create a solid block in cubit and add a volume condition.""" - # Initialize cubit. cubit = CubitPy() @@ -269,7 +266,6 @@ def rotate_list(original_list, n): def create_solid_shell_dome() -> InputFile: """Create the meshes needed for the solid shell block tests.""" - # Create the dome input cubit = CubitPy() cubit.cmd("create sphere radius 1 zpositive") @@ -294,7 +290,6 @@ def create_beam_to_solid_conditions_model( full_import: bool, ): """Create the input file for the beam-to-solid input conditions tests.""" - # Create input file input_file, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( @@ -335,9 +330,8 @@ def create_beam_to_solid_conditions_model( def create_single_solid_element_brick(get_default_test_solid_material): - """Create an input file with a single solid element brick in CubitPy for - testing purposes.""" - + """Create an input file with a single solid element brick in CubitPy for testing + purposes.""" # Create the brick with a single solid element cubit = CubitPy() create_brick( @@ -352,7 +346,6 @@ def create_single_solid_element_brick(get_default_test_solid_material): def create_solid_brick(get_default_test_solid_material): """Create an a brick with the dimensions 1x3x15.""" - cubit = CubitPy() brick = create_brick( cubit, @@ -375,10 +368,8 @@ def create_solid_brick(get_default_test_solid_material): def create_multiple_solid_bricks(): """Create blocks with all supported element types. - Also add some node sets to ensure their correct representation in - BeamMe. + Also add some node sets to ensure their correct representation in BeamMe. """ - if not cupy.is_coreform(): raise ValueError("This script requires Cubit Coreform") @@ -483,7 +474,6 @@ def get_wedge_indices(cubit) -> set[int]: def create_cubit_model_with_user_defined_node_set_and_block_ids(): """Create a Cubit model with user-defined node set and block IDs.""" - # Set up Cubit. cubit = CubitPy() diff --git a/tests/integration/test_integration_abaqus.py b/tests/integration/test_integration_abaqus.py index 58e66fdc..815e5e78 100644 --- a/tests/integration/test_integration_abaqus.py +++ b/tests/integration/test_integration_abaqus.py @@ -19,8 +19,8 @@ # 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. -"""This script is used to test general functionality of the BeamMe Abaqus -module with end-to-end integration tests.""" +"""This script is used to test general functionality of the BeamMe Abaqus module with +end-to-end integration tests.""" import numpy as np import pytest @@ -50,7 +50,6 @@ def test_integration_abaqus_helix( get_corresponding_reference_file_path, ): """Create a helix and check the created Abaqus input file.""" - # Helix parameters n_el = 10 turns = 1.5 @@ -100,7 +99,6 @@ def test_integration_abaqus_frame( get_corresponding_reference_file_path, ): """Create a frame out of connected beams with different materials.""" - mesh = Mesh() mat_1 = AbaqusBeamMaterial("beam_material_1") mat_2 = AbaqusBeamMaterial("beam_material_2") diff --git a/tests/integration/test_integration_core_geometry_set.py b/tests/integration/test_integration_core_geometry_set.py index 8e9e6fc9..bd782039 100644 --- a/tests/integration/test_integration_core_geometry_set.py +++ b/tests/integration/test_integration_core_geometry_set.py @@ -19,8 +19,8 @@ # 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. -"""This script is used to test general functionality of the core geometry set -class with end-to-end integration tests.""" +"""This script is used to test general functionality of the core geometry set class with +end-to-end integration tests.""" import pytest @@ -42,7 +42,6 @@ def test_integration_core_geometry_set_replace_nodes_geometry_set( get_corresponding_reference_file_path, ): """Test case for coupling of nodes, and reusing the identical nodes.""" - mat = get_default_test_beam_material(material_type="reissner") rot = Rotation([1, 2, 43], 213123) diff --git a/tests/integration/test_integration_core_mesh.py b/tests/integration/test_integration_core_mesh.py index b9222a8c..6fbd9ebe 100644 --- a/tests/integration/test_integration_core_mesh.py +++ b/tests/integration/test_integration_core_mesh.py @@ -19,8 +19,8 @@ # 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. -"""This script is used to test general functionality of the core mesh class -with end-to-end integration tests.""" +"""This script is used to test general functionality of the core mesh class with end-to- +end integration tests.""" import copy import random @@ -46,7 +46,6 @@ def create_test_mesh(get_default_test_beam_material): """Create a mesh with a couple of test nodes and elements.""" - # Set the seed for the pseudo random numbers random.seed(0) @@ -87,9 +86,8 @@ def test_integration_core_mesh_rotation( get_corresponding_reference_file_path, assert_results_close, ): - """Check if the Mesh function rotation gives the same results as rotating - each node it self.""" - + """Check if the Mesh function rotation gives the same results as rotating each node + it self.""" mesh_1 = create_test_mesh(get_default_test_beam_material) mesh_2 = create_test_mesh(get_default_test_beam_material) @@ -118,9 +116,8 @@ def test_integration_core_mesh_rotation_individual( get_corresponding_reference_file_path, assert_results_close, ): - """Check if the Mesh function rotation gives the same results as rotating - each node it self, when an array is passed with different rotations.""" - + """Check if the Mesh function rotation gives the same results as rotating each node + it self, when an array is passed with different rotations.""" mesh_1 = create_test_mesh(get_default_test_beam_material) mesh_2 = create_test_mesh(get_default_test_beam_material) @@ -156,9 +153,7 @@ def test_integration_core_mesh_reflection( get_corresponding_reference_file_path, assert_results_close, ): - """Create a mesh, and its mirrored counterpart and then compare the input - files.""" - + """Create a mesh, and its mirrored counterpart and then compare the input files.""" # Rotations to be applied. rot_1 = Rotation([0, 1, 1], np.pi / 6) rot_2 = Rotation([1, 2.455, -1.2324], 1.2342352) @@ -239,7 +234,6 @@ def test_integration_core_mesh_couple_nodes( assert_results_close, ): """Test the couple nodes functionality when replacing nodes.""" - mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") @@ -302,7 +296,6 @@ def test_integration_core_mesh_transformations_with_solid( ): """Test the different mesh transformation methods in combination with solid elements.""" - with context: # First, we create a line and wrap it with passing radius to the wrap function. @@ -350,7 +343,6 @@ def test_integration_core_mesh_wrap_cylinder_not_on_same_plane( get_corresponding_reference_file_path, ): """Create a helix that is itself wrapped around a cylinder.""" - # Ignore the warnings from wrap around cylinder. warnings.filterwarnings("ignore") @@ -391,7 +383,6 @@ def test_integration_core_mesh_deep_copy( ): """This test checks that the deep copy function on a mesh does not copy the materials or functions.""" - # Create material and function object. mat = get_default_test_beam_material(material_type="reissner") fun = Function([{"COMPONENT": 0, "SYMBOLIC_FUNCTION_OF_SPACE_TIME": "t"}]) @@ -448,9 +439,8 @@ def test_integration_core_mesh_deep_copy_with_geometry_sets( assert_results_close, get_corresponding_reference_file_path, ): - """Test that deep-copying a mesh together with geometry sets referencing it - works such that the copied geometry sets also reference the copied mesh.""" - + """Test that deep-copying a mesh together with geometry sets referencing it works + such that the copied geometry sets also reference the copied mesh.""" mesh = Mesh() beam_set = create_beam_mesh_line( mesh=mesh, diff --git a/tests/integration/test_integration_core_mesh_visualization.py b/tests/integration/test_integration_core_mesh_visualization.py index 1c883ef9..33c3d59d 100644 --- a/tests/integration/test_integration_core_mesh_visualization.py +++ b/tests/integration/test_integration_core_mesh_visualization.py @@ -36,7 +36,6 @@ def test_integration_core_mesh_visualization_beam( get_corresponding_reference_file_path, ): """Create a sample mesh and check the VTU output.""" - mesh = Mesh() honeycomb_set = create_beam_mesh_honeycomb( mesh, @@ -59,7 +58,6 @@ def test_integration_core_mesh_visualization_solid( assert_results_close, get_corresponding_reference_file_path ): """Import a solid mesh and check the VTU output.""" - # Convert the solid mesh to beamme objects. We use the exo mesh here, thus # we will also have the node set names added to the visualization. _, mesh = import_four_c_model( @@ -79,7 +77,6 @@ def test_integration_core_mesh_visualization_solid_elements( assert_results_close, get_corresponding_reference_file_path ): """Import a solid mesh with all solid types and check the VTU output.""" - # Convert the solid mesh to beamme objects. _, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( @@ -101,7 +98,6 @@ def test_integration_core_mesh_visualization_display_pyvista( TODO: Add a check for the created visualization """ - _, mesh = create_beam_to_solid_conditions_model( get_default_test_beam_material, get_corresponding_reference_file_path, diff --git a/tests/integration/test_integration_cosserat_curve.py b/tests/integration/test_integration_cosserat_curve.py index 63515273..81f92c5f 100644 --- a/tests/integration/test_integration_cosserat_curve.py +++ b/tests/integration/test_integration_cosserat_curve.py @@ -43,7 +43,6 @@ def create_beam_solid_input_file( beam_type, material, get_corresponding_reference_file_path ): """Create a beam and solid input file for testing purposes.""" - _, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( reference_file_base_name="test_other_create_cubit_input_files_solid_brick" @@ -82,7 +81,6 @@ def test_integration_cosserat_curve_translate_and_rotate( assert_results_close, ): """Test that a curve can be loaded, rotated and transformed.""" - if twist_type is None: curve = get_cosserat_curve() elif twist_type == "angle": @@ -140,7 +138,6 @@ def test_integration_cosserat_curve_vtk_representation( assert_results_close, ): """Test the vtk representation of the Cosserat curve.""" - reference_path = get_corresponding_reference_file_path(extension="vtu") result_path = tmp_path / reference_path.name @@ -164,7 +161,6 @@ def test_integration_cosserat_curve_pvd_series( assert_results_close, ): """Test the pvd series representation of the Cosserat curve.""" - reference_path = get_corresponding_reference_file_path( additional_identifier=reference_name, extension="pvd" ) @@ -189,7 +185,6 @@ def test_integration_cosserat_curve_mesh_transformation( assert_results_close, ): """Test that the get_mesh_transformation function works as expected.""" - curve = get_cosserat_curve() pos, rot = curve.get_centerline_position_and_rotation(0) rot = Rotation.from_quaternion(rot) @@ -222,7 +217,6 @@ def test_integration_cosserat_curve_mesh_warp( assert_results_close, ): """Warp a balloon along a centerline.""" - # Load the curve curve = get_cosserat_curve() pos, rot = curve.get_centerline_position_and_rotation(0) @@ -255,7 +249,6 @@ def test_integration_cosserat_curve_mesh_warp_transform_boundary_conditions( assert_results_close, ): """Test the transform boundary creation function.""" - # Load the curve curve = get_cosserat_curve() pos, rot = curve.get_centerline_position_and_rotation(0) diff --git a/tests/integration/test_integration_four_c.py b/tests/integration/test_integration_four_c.py index e5fe5ca6..e6f3e8f3 100644 --- a/tests/integration/test_integration_four_c.py +++ b/tests/integration/test_integration_four_c.py @@ -19,8 +19,8 @@ # 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. -"""This script is used to test general functionality of the 4C module with end- -to-end integration tests.""" +"""This script is used to test general functionality of the 4C module with end- to-end +integration tests.""" import numpy as np import pytest @@ -69,7 +69,6 @@ def test_integration_four_c_point_coupling( get_corresponding_reference_file_path, ): """Test the creation of point couplings for 4C.""" - # Create material and mesh material = get_default_test_beam_material( material_type="reissner", interaction_radius=2.0 @@ -107,7 +106,6 @@ def test_integration_four_c_point_coupling_indirect( get_corresponding_reference_file_path, ): """Test that indirect point coupling works as expected.""" - material = get_default_test_beam_material(material_type="reissner") mesh = Mesh() @@ -143,7 +141,6 @@ def test_integration_four_c_fluid_element_section( get_corresponding_reference_file_path, ): """Add beam elements to an input file containing fluid elements.""" - input_file, _ = import_four_c_model( input_file_path=get_corresponding_reference_file_path( additional_identifier="import" @@ -172,9 +169,7 @@ def test_integration_four_c_fluid_element_section( def test_integration_four_c_surface_to_surface_contact_import( assert_results_close, get_corresponding_reference_file_path ): - """Test that surface-to-surface contact problems can be imported as - expected.""" - + """Test that surface-to-surface contact problems can be imported as expected.""" input_file, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( additional_identifier="solid_mesh" @@ -209,7 +204,6 @@ def test_integration_four_c_nurbs_import( working 4C test case. So this case should be moved to the 4C tests and we should add a very basic unit test case if we can import NURBS. """ - # Create a third of the NURBS hollow cylinder base = splinepy.helpme.create.disk( outer_radius=0.3, inner_radius=0.2, angle=120, n_knot_spans=1 @@ -394,16 +388,15 @@ def test_integration_four_c_nurbs_multiple_additions_to_input_file( assert_results_close, get_corresponding_reference_file_path, ): - """In this test, we add a NURBS patch to an input file, then a beam and - then a second NURBS patch. + """In this test, we add a NURBS patch to an input file, then a beam and then a + second NURBS patch. - This checks that we can add multiple NURBS patches to the input file - and that the patch IDs are represented correctly. + This checks that we can add multiple NURBS patches to the input file and that the + patch IDs are represented correctly. """ def create_nurbs_brick(n_el_dim): - """Create a NURBS brick with the given number of elements in each - direction.""" + """Create a NURBS brick with the given number of elements in each direction.""" box_dimensions = [1.5, 3.0, 2.4] vol_obj = splinepy.helpme.create.box(*box_dimensions).nurbs vol_obj.elevate_degrees([0, 1, 2]) @@ -458,7 +451,6 @@ def test_integration_four_c_user_defined_boundary_condition( get_corresponding_reference_file_path, ): """Check if a user-defined boundary condition can be added.""" - mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") @@ -480,13 +472,11 @@ def test_integration_four_c_check_multiple_node_penalty_coupling( assert_results_close, get_corresponding_reference_file_path, ): - """For point penalty coupling constraints, we add multiple coupling - conditions. + """For point penalty coupling constraints, we add multiple coupling conditions. - This is checked in this test case. The flag reuse_nodes decides - whether equal nodes are unified to a single node. + This is checked in this test case. The flag reuse_nodes decides whether equal nodes + are unified to a single node. """ - # Create mesh object mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") diff --git a/tests/integration/test_integration_four_c_beam_interaction_conditions.py b/tests/integration/test_integration_four_c_beam_interaction_conditions.py index 381834fa..80f4fa83 100644 --- a/tests/integration/test_integration_four_c_beam_interaction_conditions.py +++ b/tests/integration/test_integration_four_c_beam_interaction_conditions.py @@ -37,7 +37,6 @@ def test_integration_four_c_beam_interaction_conditions_beam_to_beam_contact( get_corresponding_reference_file_path, ): """Test the beam-to-beam contact boundary conditions.""" - # Create the mesh. mesh = Mesh() @@ -78,9 +77,7 @@ def test_integration_four_c_beam_interaction_conditions_beam_to_solid( get_corresponding_reference_file_path, assert_results_close, ): - """Test that the automatic ID creation for beam-to-solid conditions - works.""" - + """Test that the automatic ID creation for beam-to-solid conditions works.""" # Load a solid _, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( diff --git a/tests/integration/test_integration_four_c_beam_potential.py b/tests/integration/test_integration_four_c_beam_potential.py index d40f47a1..c899b397 100644 --- a/tests/integration/test_integration_four_c_beam_potential.py +++ b/tests/integration/test_integration_four_c_beam_potential.py @@ -40,9 +40,8 @@ def test_integration_four_c_beam_potential_helix( assert_results_close, get_corresponding_reference_file_path, ): - """Test the correct creation of input files for simulations including beam - to beam potential interactions.""" - + """Test the correct creation of input files for simulations including beam to beam + potential interactions.""" mesh = Mesh() input_file = InputFile() diff --git a/tests/integration/test_integration_four_c_element_beam.py b/tests/integration/test_integration_four_c_element_beam.py index 1511f17a..387c2416 100644 --- a/tests/integration/test_integration_four_c_element_beam.py +++ b/tests/integration/test_integration_four_c_element_beam.py @@ -71,7 +71,6 @@ def test_integration_four_c_element_beam_reissner_beam( ): """Test that the input file for all types of Reissner beams is generated correctly.""" - # Create mesh mesh = Mesh() @@ -110,7 +109,6 @@ def test_integration_four_c_element_beam_kirchhoff_beam( ): """Test that the input file for all types of Kirchhoff beams is generated correctly.""" - # Create mesh mesh = Mesh() @@ -170,9 +168,8 @@ def test_integration_four_c_element_beam_kirchhoff_beam( def test_integration_four_c_element_beam_euler_bernoulli( assert_results_close, get_corresponding_reference_file_path ): - """Recreate the 4C test case beam3eb_static_endmoment_quartercircle.4C.yaml - This tests the implementation for Euler Bernoulli beams.""" - + """Recreate the 4C test case beam3eb_static_endmoment_quartercircle.4C.yaml This + tests the implementation for Euler Bernoulli beams.""" # Create the mesh and add function and material. mesh = Mesh() fun = Function([{"COMPONENT": 0, "SYMBOLIC_FUNCTION_OF_SPACE_TIME": "t"}]) diff --git a/tests/integration/test_integration_four_c_header_functions.py b/tests/integration/test_integration_four_c_header_functions.py index 8f17a4fc..0bdc28f2 100644 --- a/tests/integration/test_integration_four_c_header_functions.py +++ b/tests/integration/test_integration_four_c_header_functions.py @@ -40,7 +40,6 @@ def test_integration_four_c_header_functions_static( assert_results_close, ): """Test the default static header function.""" - # Create input file. input_file = InputFile() @@ -84,7 +83,6 @@ def test_integration_four_c_header_functions_static_time( total_time, ): """Test the time setting options in the static header functions.""" - input_file = InputFile() set_header_static( @@ -103,9 +101,7 @@ def test_integration_four_c_header_functions_static_prestress( get_corresponding_reference_file_path, assert_results_close, ): - """Test the static header function with non default prestressing - parameter.""" - + """Test the static header function with non default prestressing parameter.""" # Create input file. input_file = InputFile() @@ -141,9 +137,7 @@ def test_integration_four_c_header_functions_stress_output( get_corresponding_reference_file_path, assert_results_close, ): - """Test the static header function with non default stress output - parameter.""" - + """Test the static header function with non default stress output parameter.""" # Create input file. input_file = InputFile() @@ -166,7 +160,6 @@ def test_integration_four_c_header_functions_beam_interaction( get_corresponding_reference_file_path, assert_results_close ): """Test the beam-to-beam contact header function with default parameter.""" - # Create input file. input_file = InputFile() @@ -199,7 +192,6 @@ def test_integration_four_c_header_functions_nonlinear_solver_parameters( tmp_path, ): """Test that the NOX xml is exported correctly.""" - input_file = InputFile() set_header_static( input_file, diff --git a/tests/integration/test_integration_four_c_input_file.py b/tests/integration/test_integration_four_c_input_file.py index 9a4b24ba..e240c849 100644 --- a/tests/integration/test_integration_four_c_input_file.py +++ b/tests/integration/test_integration_four_c_input_file.py @@ -48,7 +48,6 @@ def create_beam_mesh( n_el: int = 2, ) -> GeometryName: """Utility function to create a beam mesh for the tests.""" - if beam_type == Beam3eb: # For EB beams, we create a straight line. return create_beam_mesh_line( @@ -84,7 +83,6 @@ def test_integration_four_c_input_file_vtu_element_blocks( ): """Test the grouping of elements with the same element data and material in blocks.""" - # Get materials material_1 = get_default_test_beam_material( material_type="reissner", interaction_radius=1.0 @@ -165,9 +163,8 @@ def test_integration_four_c_input_file_vtu_boundary_conditions( get_corresponding_reference_file_path, assert_results_close, ): - """Test that boundary conditions are correctly written to the input file in - vtu format.""" - + """Test that boundary conditions are correctly written to the input file in vtu + format.""" # Create mesh mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") @@ -220,9 +217,8 @@ def test_integration_four_c_input_file_vtu_boundary_conditions_user_defined_sect get_corresponding_reference_file_path, assert_results_close, ): - """Test that boundary conditions with user defined sections are correctly - written to the input file in vtu format.""" - + """Test that boundary conditions with user defined sections are correctly written to + the input file in vtu format.""" # Create mesh mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") @@ -261,9 +257,8 @@ def test_integration_four_c_input_file_vtu_boundary_conditions_named_geometry_se get_corresponding_reference_file_path, assert_results_close, ): - """Test that boundary conditions with named geometry sets are correctly - written to the input file in vtu format.""" - + """Test that boundary conditions with named geometry sets are correctly written to + the input file in vtu format.""" # Create mesh mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") diff --git a/tests/integration/test_integration_four_c_locsys_condition.py b/tests/integration/test_integration_four_c_locsys_condition.py index 5847b8ba..5b948272 100644 --- a/tests/integration/test_integration_four_c_locsys_condition.py +++ b/tests/integration/test_integration_four_c_locsys_condition.py @@ -41,11 +41,9 @@ def test_integration_four_c_locsys_condition_locsys( ): """Test case for point locsys condition for beams. - The testcase is adapted from to - beam3r_herm2line3_static_locsys.4C.yaml. However it has a simpler - material, and an additional line locsys condition. + The testcase is adapted from to beam3r_herm2line3_static_locsys.4C.yaml. However it + has a simpler material, and an additional line locsys condition. """ - locsys_rotation = Rotation([0, 0, 1], 0.1) # Create the mesh. diff --git a/tests/integration/test_integration_four_c_material.py b/tests/integration/test_integration_four_c_material.py index dd9a6b6c..0ea7b060 100644 --- a/tests/integration/test_integration_four_c_material.py +++ b/tests/integration/test_integration_four_c_material.py @@ -31,7 +31,6 @@ def test_integration_four_c_material_sub_materials( assert_results_close, ): """Check if sub-materials are handled correctly.""" - # Add a nested material to the mesh and check the result. mesh = Mesh() material = get_default_test_solid_material(material_type="solid_nested") @@ -48,10 +47,9 @@ def test_integration_four_c_material_sub_materials_material_numbering( assert_results_close, get_corresponding_reference_file_path, ): - """Test that materials can be added as structured data (dictionaries) to an - input file (as is done when importing input files) and that the numbering - with other added materials does not lead to materials with double IDs.""" - + """Test that materials can be added as structured data (dictionaries) to an input + file (as is done when importing input files) and that the numbering with other added + materials does not lead to materials with double IDs.""" input_file = InputFile() input_file.add( { diff --git a/tests/integration/test_integration_four_c_model_importer.py b/tests/integration/test_integration_four_c_model_importer.py index 4c0a4aca..10b6eb4d 100644 --- a/tests/integration/test_integration_four_c_model_importer.py +++ b/tests/integration/test_integration_four_c_model_importer.py @@ -42,7 +42,6 @@ def test_integration_four_c_model_importer_import_exodus_model( full_import, assert_results_close, get_corresponding_reference_file_path ): """Check that an input file with exodus mesh can be imported correctly.""" - input_file, mesh = import_four_c_model( get_corresponding_reference_file_path( reference_file_base_name="test_other_create_cubit_input_files_tube_exo" @@ -66,9 +65,8 @@ def test_integration_four_c_model_importer_import_exodus_model( def test_integration_four_c_model_importer_solid_element_types_from_cubitpy( full_import, assert_results_close, get_corresponding_reference_file_path ): - """Check that all supported solid element types are imported correctly from - a CubitPy instance.""" - + """Check that all supported solid element types are imported correctly from a + CubitPy instance.""" cubit = create_multiple_solid_bricks() input_file, mesh = import_cubitpy_model(cubit, convert_input_to_mesh=full_import) if full_import: @@ -84,9 +82,8 @@ def test_integration_four_c_model_importer_solid_element_types_from_cubitpy( def test_integration_four_c_model_importer_solid_element_types_from_input_file_yaml( full_import, assert_results_close, get_corresponding_reference_file_path ): - """Check that all supported solid element types are imported correctly from - a text based input file.""" - + """Check that all supported solid element types are imported correctly from a text + based input file.""" reference_file = get_corresponding_reference_file_path( reference_file_base_name="test_other_create_cubit_input_files_multiple_solid_bricks_yaml" ) @@ -103,9 +100,8 @@ def test_integration_four_c_model_importer_solid_element_types_from_input_file_y def test_integration_four_c_model_importer_solid_element_types_from_input_file_exo( full_import, assert_results_close, get_corresponding_reference_file_path ): - """Check that all supported solid element types are imported correctly from - an input file with an exodus mesh.""" - + """Check that all supported solid element types are imported correctly from an input + file with an exodus mesh.""" input_file_path = get_corresponding_reference_file_path( reference_file_base_name="test_other_create_cubit_input_files_multiple_solid_bricks_exo" ) @@ -127,7 +123,6 @@ def test_integration_four_c_model_importer_import_nested_materials( assert_results_close, ): """Check if nested materials are imported correctly.""" - # Create a minimal solid input file. mesh = Mesh() material = get_default_test_solid_material(material_type="solid_nested") @@ -157,9 +152,7 @@ def test_integration_four_c_model_importer_import_nested_materials( def test_integration_four_c_model_importer_import_nested_materials_error(): - """Check that an error is raised when importing nested materials with bad - IDs.""" - + """Check that an error is raised when importing nested materials with bad IDs.""" # Create an input file with "bad" material IDs. input_file = InputFile() input_file["MATERIALS"] = [ @@ -185,7 +178,6 @@ def test_integration_four_c_model_importer_non_consecutive_geometry_sets( assert_results_close, ): """Test that we can import non-consecutively numbered geometry sets.""" - input_file, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( additional_identifier="input" @@ -220,7 +212,6 @@ def test_integration_four_c_model_importer_user_defined_node_set_and_block_ids( full_import, get_corresponding_reference_file_path, assert_results_close ): """Test that user-defined node set and block IDs work as expected.""" - reference_file_base_name = ( "test_other_create_cubit_input_files_user_defined_node_sets_and_block_ids" ) diff --git a/tests/integration/test_integration_four_c_simulation.py b/tests/integration/test_integration_four_c_simulation.py index 7264747a..234b7d8f 100644 --- a/tests/integration/test_integration_four_c_simulation.py +++ b/tests/integration/test_integration_four_c_simulation.py @@ -95,8 +95,7 @@ @pytest.fixture def run_four_c_test(tmp_path: Path) -> Callable: - """Provides a helper function to run a 4C simulation in a temporary - directory. + """Provides a helper function to run a 4C simulation in a temporary directory. Args: tmp_path: The pytest temporary directory for the current test. @@ -104,7 +103,6 @@ def run_four_c_test(tmp_path: Path) -> Callable: Returns: Callable: A function that runs a 4C simulation. """ - # Counter that will track the number of calls to the _run_four_c_test function # for each test case (it is reset for each test case). run_four_c_counter = 0 @@ -130,7 +128,6 @@ def _run_four_c_test( run_dir: The directory where the simulation ran. run_name: The name of the 4C run. """ - # Since the counter is of a base type, we have to use nonlocal to modify it. nonlocal run_four_c_counter run_four_c_counter += 1 @@ -169,7 +166,6 @@ def create_cantilever_model(n_steps, time_step=0.5): time_step: float Time step size. """ - input_file = InputFile() set_header_static(input_file, time_step=time_step, n_steps=n_steps) input_file["IO"]["OUTPUT_BIN"] = True @@ -205,13 +201,12 @@ def test_integration_four_c_simulation_honeycomb_sphere( ): """Create the same honeycomb mesh as defined in 4C/tests/input_files/beam3r _herm2lin3_static_point_coupling_BTSPH_contact_stent_honeycomb_stretch_r01_ - circ10.4C.yaml The honeycomb beam is in contact with a rigid sphere, the - sphere is moved compared to the original test file, since there are some - problems with the contact convergence. + circ10.4C.yaml The honeycomb beam is in contact with a rigid sphere, the sphere is + moved compared to the original test file, since there are some problems with the + contact convergence. The sphere is imported as an existing mesh. """ - # Read input file with information of the sphere and simulation. input_file, mesh = import_four_c_model( input_file_path=get_corresponding_reference_file_path( @@ -339,7 +334,6 @@ def test_integration_four_c_simulation_beam_and_solid_tube( run_four_c_test, ): """Merge a solid tube with a beam tube and simulate them together.""" - # Create the input file and read solid mesh data. We use the exo mesh here, # thus we will run the simulation with referencing the solid node sets by # name. @@ -444,7 +438,6 @@ def test_integration_four_c_simulation_honeycomb_variants( run_four_c_test, ): """Create a few different honeycomb structures.""" - # Create input file. input_file = InputFile() @@ -621,7 +614,6 @@ def test_integration_four_c_simulation_rotated_beam_axis( - The third case uses two nodes at the connection between the lines, and couples them with a coupling. """ - # Create input file input_file = InputFile() @@ -742,8 +734,8 @@ def test_integration_four_c_simulation_dbc_monitor_to_input( get_corresponding_reference_file_path, run_four_c_test, ): - """Common driver to simulate a cantilever beam with Dirichlet boundary - conditions and then apply those as Neumann boundaries. + """Common driver to simulate a cantilever beam with Dirichlet boundary conditions + and then apply those as Neumann boundaries. This can be used to test the two different functions by selecting one of the appropriate initial run_names: @@ -756,7 +748,6 @@ def test_integration_four_c_simulation_dbc_monitor_to_input( the force are used. This function explicitly tests dbc_monitor_to_input_all_values. """ - # Create and run the initial simulation. initial_input_file, initial_mesh, mesh_beam_set = create_cantilever_model(n_steps=2) @@ -889,13 +880,11 @@ def test_integration_four_c_simulation_dirichlet_boundary_to_neumann_boundary_wi get_corresponding_reference_file_path, run_four_c_test, ): - """First simulate a cantilever beam with Dirichlet boundary conditions and - then apply those as Neumann boundaries. + """First simulate a cantilever beam with Dirichlet boundary conditions and then + apply those as Neumann boundaries. - For the application of the boundary conditions, all values of the - force are used. + For the application of the boundary conditions, all values of the force are used. """ - # Define Parameters. n_steps = 5 # number of simulation steps dt = 0.1 # time step size from create_cantilever_model @@ -903,7 +892,7 @@ def test_integration_four_c_simulation_dirichlet_boundary_to_neumann_boundary_wi # Create and run the initial simulation. initial_simulation, mesh, beam_set = create_cantilever_model(n_steps, dt) - # Add simple lienar interpolation function. + # Add simple linear interpolation function. mesh.add( Function( [ @@ -1051,7 +1040,6 @@ def test_integration_four_c_simulation_cantilever_convergence( def create_and_run_cantilever(n_el, mesh_format, *, n_proc=1): """Create a cantilever beam for a convergence analysis.""" - input_file = InputFile() set_header_static(input_file, time_step=0.25, n_steps=4) set_runtime_output(input_file, output_energy=True) @@ -1124,15 +1112,14 @@ def test_integration_four_c_simulation_beam_to_beam_contact_example( get_corresponding_reference_file_path, run_four_c_test, ): - """Small test example to show how a beam contact example with beam penalty - contact can be set up. + """Small test example to show how a beam contact example with beam penalty contact + can be set up. The test case consists of two beams: one beam is allocated along the x-axis and the other beam is located along the y-axis. The beam along the y-axis is placed above the other beam by an additional offset in z-Directions. Due to prescribed displacements at the tips of beam in y-axis, the two beams get in contact around the origin. """ - # Define Parameters for example l_beam = 2 r_beam = 0.1 @@ -1264,10 +1251,8 @@ def test_integration_four_c_simulation_locsys( """Create a star like structure made out of 3 beams to test complex locsys conditions. - We first rotate the star and then apply a prescribed displacemet to - its center. + We first rotate the star and then apply a prescribed displacemet to its center. """ - # Define Parameters for example l_beam = 2 r_beam = 0.05 @@ -1413,7 +1398,6 @@ def test_integration_four_c_simulation_beam_types( run_four_c_test, ): """Create an input file with many possible beam elements in 4C.""" - # Parameters for example l_beam = 2 r_beam = 0.05 diff --git a/tests/integration/test_integration_four_c_solid_shell_thickness_direction.py b/tests/integration/test_integration_four_c_solid_shell_thickness_direction.py index 07e85917..69c22379 100644 --- a/tests/integration/test_integration_four_c_solid_shell_thickness_direction.py +++ b/tests/integration/test_integration_four_c_solid_shell_thickness_direction.py @@ -37,9 +37,7 @@ def test_integration_four_c_solid_shell_thickness_direction_block( assert_results_close, get_corresponding_reference_file_path, ): - """Test the solid shell direction detection functionality for a block - geometry.""" - + """Test the solid shell direction detection functionality for a block geometry.""" # Test the plates _, mesh_block = import_four_c_model( input_file_path=get_corresponding_reference_file_path( @@ -65,9 +63,7 @@ def test_integration_four_c_solid_shell_thickness_direction_block( def test_integration_four_c_solid_shell_thickness_direction_dome( assert_results_close, get_corresponding_reference_file_path ): - """Test the solid shell direction detection functionality for a dome - geometry.""" - + """Test the solid shell direction detection functionality for a dome geometry.""" _, mesh_dome_original = import_four_c_model( input_file_path=get_corresponding_reference_file_path( reference_file_base_name="test_other_create_cubit_input_files_solid_shell_dome" @@ -120,7 +116,6 @@ def test_integration_four_c_solid_shell_thickness_direction_visualization( assert_results_close, get_corresponding_reference_file_path, tmp_path ): """Test the solid shell direction visualization functionality.""" - _, mesh_dome = import_four_c_model( input_file_path=get_corresponding_reference_file_path( reference_file_base_name="test_other_create_cubit_input_files_solid_shell_dome" diff --git a/tests/integration/test_integration_geometric_search.py b/tests/integration/test_integration_geometric_search.py index 18d21391..c666e23d 100644 --- a/tests/integration/test_integration_geometric_search.py +++ b/tests/integration/test_integration_geometric_search.py @@ -19,8 +19,7 @@ # 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. -"""This script is used to test the functionality of the geometric_search -module.""" +"""This script is used to test the functionality of the geometric_search module.""" import random @@ -65,9 +64,8 @@ def assert_unique_id_coordinates( inverse_indices_ref, assert_results_close, ): - """Test if the unique coordinates are really unique and that the inverse - indices result in the original array.""" - + """Test if the unique coordinates are really unique and that the inverse indices + result in the original array.""" # Get the array with the unique indices. unique_indices, inverse_indices = point_partners_to_unique_indices(point_partners) unique_points = coords[unique_indices] @@ -353,10 +351,9 @@ def test_integration_geometric_search_find_close_points_binning_flat( ): """Test case for coupling of points, when the nodes are all on a plane. - This is challenging for a binning based approach. However, this test - case can also be used for all find_close_point algorithms. + This is challenging for a binning based approach. However, this test case can also + be used for all find_close_point algorithms. """ - # Dummy material. material = MaterialBeamBase() @@ -452,9 +449,8 @@ def create_flat_mesh(): def test_integration_geometric_search_find_close_points_single_dimension( algorithm, assert_results_close ): - """Test that the find_close_points function works properly with a 1D - dimensional array (internally a n x 1 array is required)""" - + """Test that the find_close_points function works properly with a 1D dimensional + array (internally a n x 1 array is required)""" # Create array with coordinates eps = 1e-10 coords = np.array( @@ -492,7 +488,6 @@ def test_integration_geometric_search_find_close_points_multi_dimension( ): """Test that the find_close_points function also works properly with multidimensional points.""" - # Create array with coordinates. coords = np.array( [ @@ -550,9 +545,8 @@ def test_integration_geometric_search_find_close_points_multi_dimension( def test_integration_geometric_search_find_close_points_tolerance_precision( algorithm, assert_results_close ): - """Test that the find_close_points tolerance works with a precision of at - least 12.""" - + """Test that the find_close_points tolerance works with a precision of at least + 12.""" n_points = 4 delta = 1e-12 coords = np.ones([n_points, 3]) diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_applications.py b/tests/integration/test_integration_mesh_creation_functions_beam_applications.py index 9685ba4e..abfa41c7 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_applications.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_applications.py @@ -40,7 +40,6 @@ def test_integration_mesh_creation_functions_beam_applications_stent( get_corresponding_reference_file_path, ): """Test the stent creation function.""" - # Create mesh mesh = Mesh() @@ -73,7 +72,6 @@ def test_integration_mesh_creation_functions_beam_applications_fibers_in_rectang get_corresponding_reference_file_path, ): """Test the create_fibers_in_rectangle function.""" - # Create mesh mesh = Mesh() @@ -167,9 +165,8 @@ def test_integration_mesh_creation_functions_beam_applications_fibers_in_rectang assert_results_close, get_corresponding_reference_file_path, ): - """Test the create_fibers_in_rectangle function with using the - reference_point option.""" - + """Test the create_fibers_in_rectangle function with using the reference_point + option.""" # Create mesh mesh = Mesh() @@ -210,7 +207,6 @@ def test_integration_mesh_creation_functions_beam_applications_fibers_in_rectang get_corresponding_reference_file_path, ): """Test the set returned by the create_fibers_in_rectangle function.""" - # Create mesh mesh = Mesh() @@ -238,7 +234,6 @@ def test_integration_mesh_creation_functions_beam_applications_wire( get_corresponding_reference_file_path, ): """Test the create_wire_fibers function.""" - # Create mesh mesh = Mesh() diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_arc.py b/tests/integration/test_integration_mesh_creation_functions_beam_arc.py index d54584a0..a578ca99 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_arc.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_arc.py @@ -40,9 +40,8 @@ def test_integration_mesh_creation_functions_beam_arc_segment_via_axis( assert_results_close, get_corresponding_reference_file_path, ): - """Create a circular segment via the axis method and compare it with the - reference file.""" - + """Create a circular segment via the axis method and compare it with the reference + file.""" # Create mesh mesh = Mesh() radius = 2.0 @@ -67,13 +66,12 @@ def test_integration_mesh_creation_functions_beam_arc_segment_start_end_node( assert_results_close, get_corresponding_reference_file_path, ): - """Check that if start end nodes with non-matching positions or tangents - are provided we get an error. + """Check that if start end nodes with non-matching positions or tangents are + provided we get an error. TODO: Split this test into the arc functionality and a general unittest for the error messages. """ - angle = 1.0 radius = 2.0 start_node_pos = [0, 0, 0] @@ -82,8 +80,7 @@ def test_integration_mesh_creation_functions_beam_arc_segment_start_end_node( end_node_rot = Rotation([0, 0, 1], angle) def create_beam(*, start_node=None, end_node=None): - """This is the base function we use to generate the beam in this test - case.""" + """This is the base function we use to generate the beam in this test case.""" mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") if start_node is not None: @@ -148,9 +145,8 @@ def test_integration_mesh_creation_functions_beam_arc_segment_via_rotation( assert_results_close, get_corresponding_reference_file_path, ): - """Create a circular segment via the rotation method and compare it with - the reference file.""" - + """Create a circular segment via the rotation method and compare it with the + reference file.""" # Create mesh mesh = Mesh() @@ -182,7 +178,6 @@ def test_integration_mesh_creation_functions_beam_arc_segment_2d( get_corresponding_reference_file_path, ): """Create a circular segments in 2D.""" - # Create mesh mesh = Mesh() diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_generic.py b/tests/integration/test_integration_mesh_creation_functions_beam_generic.py index 9bdb4b6e..9b45eeb6 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_generic.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_generic.py @@ -53,9 +53,8 @@ def test_integration_mesh_creation_functions_beam_generic_close_beam_manual( assert_results_close, get_corresponding_reference_file_path, ): - """Create a circle mesh manually by creating the nodes and connecting them - to the elements.""" - + """Create a circle mesh manually by creating the nodes and connecting them to the + elements.""" # Parameters for this test case. n_el = 3 R = 1.235 @@ -125,7 +124,6 @@ def test_integration_mesh_creation_functions_beam_generic_close_beam_full_circle Close the circle such that it is connected to its beginning. """ - # Parameters for this test case. R = 1.235 n_el = 3 @@ -193,12 +191,11 @@ def test_integration_mesh_creation_functions_beam_generic_close_beam_two_circles assert_results_close, get_corresponding_reference_file_path, ): - """Create a full circle with different mesh creation methods, each creates - a half circle twice. + """Create a full circle with different mesh creation methods, each creates a half + circle twice. Close the circle such that it is connected to its beginning. """ - # Parameters for this test case. R = 1.235 n_el = 3 @@ -277,7 +274,6 @@ def test_integration_mesh_creation_functions_beam_generic_node_positions_of_elem ): """Creates a line, a circular segments in 2D and a helix by setting the node_positions_of_elements.""" - # Create a mesh mesh = Mesh() @@ -343,9 +339,7 @@ def test_integration_mesh_creation_functions_beam_generic_element_length_option( assert_results_close, get_corresponding_reference_file_path, ): - """Test that the element length can be specified in the beam creation - functions.""" - + """Test that the element length can be specified in the beam creation functions.""" mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_helix.py b/tests/integration/test_integration_mesh_creation_functions_beam_helix.py index ec4ee1ec..013873cf 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_helix.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_helix.py @@ -45,7 +45,6 @@ def test_integration_mesh_creation_functions_beam_helix_no_rotation( get_corresponding_reference_file_path, ): """Create a helix and compare it with the reference file.""" - ## Helix angle and height helix combination # Create mesh mesh = Mesh() @@ -90,7 +89,6 @@ def test_integration_mesh_creation_functions_beam_helix_rotation_offset( get_corresponding_reference_file_path, ): """Create a helix and compare it with the reference file.""" - # Create mesh mesh = Mesh() @@ -125,7 +123,6 @@ def test_integration_mesh_creation_functions_beam_helix_radius_zero( get_corresponding_reference_file_path, ): """Create a helix and compare it with the reference file.""" - # Create mesh mesh = Mesh() @@ -162,7 +159,6 @@ def test_integration_mesh_creation_functions_beam_helix_right_angle( get_corresponding_reference_file_path, ): """Create a helix and compare it with the reference file.""" - # Create mesh mesh = Mesh() diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_node_continuation.py b/tests/integration/test_integration_mesh_creation_functions_beam_node_continuation.py index 8ce13321..ade61403 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_node_continuation.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_node_continuation.py @@ -39,7 +39,6 @@ def test_integration_mesh_creation_functions_beam_node_continuation_line_and_arc get_corresponding_reference_file_path, ): """Test that the node continuation function work as expected.""" - mesh = Mesh() mat = get_default_test_beam_material(material_type="reissner") mesh.add(mat) diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_parametric_curve.py b/tests/integration/test_integration_mesh_creation_functions_beam_parametric_curve.py index c88d86e6..51e40094 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_parametric_curve.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_parametric_curve.py @@ -19,8 +19,7 @@ # 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. -"""This script is used to test the create parametric curve mesh creation -functions.""" +"""This script is used to test the create parametric curve mesh creation functions.""" import autograd.numpy as npAD import numpy as np @@ -72,10 +71,8 @@ def test_integration_mesh_creation_functions_beam_parametric_curve_3d_helix( assert_results_close, get_corresponding_reference_file_path, ): - """Create a helix from a parametric curve where the parameter is - transformed so the arc length along the beam is not proportional to the - parameter.""" - + """Create a helix from a parametric curve where the parameter is transformed so the + arc length along the beam is not proportional to the parameter.""" # Create mesh mesh = Mesh() @@ -109,9 +106,8 @@ def test_integration_mesh_creation_functions_beam_parametric_curve_3d_helix_leng get_corresponding_reference_file_path, assert_results_close, ): - """Create a helix from a parametric curve where and check that the correct - length is returned.""" - + """Create a helix from a parametric curve where and check that the correct length is + returned.""" mesh_1 = Mesh() mesh_2 = Mesh() mat = get_default_test_beam_material(material_type="reissner") @@ -162,7 +158,6 @@ def test_integration_mesh_creation_functions_beam_parametric_curve_2d_sin( get_corresponding_reference_file_path, ): """Create a sin from a parametric curve.""" - # Create mesh mesh = Mesh() @@ -199,7 +194,6 @@ def test_integration_mesh_creation_functions_beam_parametric_curve_3d_rotation( get_corresponding_reference_file_path, ): """Create a line from a parametric curve and prescribe the rotation.""" - # Create mesh mesh = Mesh() @@ -254,7 +248,6 @@ def test_integration_mesh_creation_functions_beam_parametric_curve_3d_line( get_corresponding_reference_file_path, ): """Create a line from a parametric curve.""" - # Create mesh mesh = Mesh() @@ -262,8 +255,7 @@ def test_integration_mesh_creation_functions_beam_parametric_curve_3d_line( mat = get_default_test_beam_material(material_type="reissner") def line(t): - """Create a line with a parametric curve (and a transformed - parameter).""" + """Create a line with a parametric curve (and a transformed parameter).""" factor = 2 t_trans = npAD.exp(factor * t / (2.0 * np.pi)) * t / npAD.exp(factor) return npAD.array([t_trans, 0, 0]) diff --git a/tests/integration/test_integration_mesh_creation_functions_beam_splinepy.py b/tests/integration/test_integration_mesh_creation_functions_beam_splinepy.py index affb0bd9..fe2ac2ac 100644 --- a/tests/integration/test_integration_mesh_creation_functions_beam_splinepy.py +++ b/tests/integration/test_integration_mesh_creation_functions_beam_splinepy.py @@ -48,7 +48,6 @@ def test_integration_mesh_creation_functions_beam_splinepy( ): """Test the create_beam_mesh_from_splinepy function with different splinepy curves.""" - curve = get_splinepy_object(splinepy_type) mat = get_default_test_beam_material(material_type="reissner") mesh = Mesh() diff --git a/tests/integration/test_integration_mesh_creation_functions_nurbs.py b/tests/integration/test_integration_mesh_creation_functions_nurbs.py index bbf9ed72..a86d40ba 100644 --- a/tests/integration/test_integration_mesh_creation_functions_nurbs.py +++ b/tests/integration/test_integration_mesh_creation_functions_nurbs.py @@ -52,7 +52,6 @@ def test_integration_mesh_creation_functions_nurbs_hollow_cylinder_segment_2d( get_corresponding_reference_file_path, ): """Test the creation of a two dimensional hollow cylinder segment.""" - # Create the surface of a quarter of a hollow cylinder surf_obj = create_nurbs_hollow_cylinder_segment_2d( 1.74, 2.46, np.pi * 5 / 6, n_ele_u=2, n_ele_v=3 @@ -83,7 +82,6 @@ def test_integration_mesh_creation_functions_nurbs_flat_plate_2d( get_corresponding_reference_file_path, ): """Test the creation of a two dimensional flat plate.""" - # Create the surface of a flat plate surf_obj = create_nurbs_flat_plate_2d(0.75, 0.91, n_ele_u=2, n_ele_v=5) @@ -110,7 +108,6 @@ def test_integration_mesh_creation_functions_nurbs_flat_plate_2d_splinepy( get_corresponding_reference_file_path, ): """Test the creation of a two dimensional flat plate with splinepy.""" - # Create the surface of a flat plate n_ele_u = 2 n_ele_v = 5 @@ -142,7 +139,6 @@ def test_integration_mesh_creation_functions_nurbs_flat_plate_2d_splinepy_copy( get_corresponding_reference_file_path, ): """Test that a mesh created from a splinepy NURBS can be copied.""" - # Create a flat plate surf_obj = splinepy.helpme.create.box(0.5, 1.0).nurbs surf_obj.elevate_degrees([0, 1]) @@ -169,7 +165,6 @@ def test_integration_mesh_creation_functions_nurbs_brick( get_corresponding_reference_file_path, ): """Test the creation of a brick.""" - # Create a brick vol_obj = create_nurbs_brick(1.5, 3.0, 2.4, n_ele_u=2, n_ele_v=3, n_ele_w=4) @@ -198,7 +193,6 @@ def test_integration_mesh_creation_functions_nurbs_brick_splinepy( get_corresponding_reference_file_path, ): """Test the creation of a brick with splinepy.""" - # Create a brick n_el_dim = [2, 3, 4] box_dimensions = [1.5, 3.0, 2.4] @@ -241,7 +235,6 @@ def test_integration_mesh_creation_functions_nurbs_rotation_nurbs_surface( get_corresponding_reference_file_path, ): """Test the rotation of a NURBS mesh.""" - # Create the surface surf_obj = create_nurbs_hollow_cylinder_segment_2d( 1.74, 2.46, np.pi * 3 / 4, n_ele_u=5, n_ele_v=2 @@ -274,7 +267,6 @@ def test_integration_mesh_creation_functions_nurbs_translate_nurbs_surface( get_corresponding_reference_file_path, ): """Test the translation of a NURBS surface mesh.""" - # Create the surface surf_obj = create_nurbs_flat_plate_2d(0.87, 1.35, n_ele_u=2, n_ele_v=3) @@ -305,7 +297,6 @@ def test_integration_mesh_creation_functions_nurbs_cylindrical_shell_sector( get_corresponding_reference_file_path, ): """Test the creation of a 3-dimensional cylindrical shell sector.""" - # Create the surface of a quarter of a hollow cylinder surf_obj = create_nurbs_cylindrical_shell_sector( 2.3, np.pi / 3, 1.7, n_ele_u=3, n_ele_v=5 @@ -336,7 +327,6 @@ def test_integration_mesh_creation_functions_nurbs_couple_nurbs_meshes( get_corresponding_reference_file_path, ): """Test the coupling of NURBS surface meshes.""" - # Create mesh mesh = Mesh() @@ -376,7 +366,6 @@ def test_integration_mesh_creation_functions_nurbs_sphere_surface( get_corresponding_reference_file_path, ): """Test the creating of the base patch of the surface of a sphere.""" - # Create mesh mesh = Mesh() @@ -406,10 +395,8 @@ def test_integration_mesh_creation_functions_nurbs_string_types( ): """Test the creating of a NURBS with strings for the element and material definition.""" - # Create mesh mesh = Mesh() - # Create the base of a sphere surf_obj = create_nurbs_flat_plate_2d(1, 3, n_ele_u=3, n_ele_v=2) @@ -435,10 +422,8 @@ def test_integration_mesh_creation_functions_nurbs_hemisphere_surface( get_corresponding_reference_file_path, ): """Test the creation of the surface of a hemisphere.""" - # Create mesh mesh = Mesh() - # Create the base of a sphere surfs = create_nurbs_hemisphere_surface(2.5, n_ele_uv=2) @@ -468,10 +453,8 @@ def test_integration_mesh_creation_functions_nurbs_torus_surface( get_corresponding_reference_file_path, ): """Test the creation of a torus.""" - # Create mesh mesh = Mesh() - # Create the surface of a torus surfs = create_nurbs_torus_surface(1, 0.5, n_ele_u=2, n_ele_v=3) @@ -501,7 +484,6 @@ def test_integration_mesh_creation_functions_nurbs_empty_knot_spans( get_corresponding_reference_file_path, ): """Test that NURBS patches with empty knot spans are handled correctly.""" - # Create the pipe geometry with splinepy disk = splinepy.helpme.create.disk( outer_radius=2.3, inner_radius=1.7, angle=360, n_knot_spans=1 diff --git a/tests/integration/test_integration_space_time.py b/tests/integration/test_integration_space_time.py index 1d262332..22468702 100644 --- a/tests/integration/test_integration_space_time.py +++ b/tests/integration/test_integration_space_time.py @@ -19,8 +19,8 @@ # 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. -"""This script is used to test general functionality of the BeamMe space-time -module with end-to-end integration tests.""" +"""This script is used to test general functionality of the BeamMe space-time module +with end-to-end integration tests.""" import numpy as np import pytest @@ -53,7 +53,6 @@ def test_integration_space_time_straight( n_nodes, assert_results_close, get_corresponding_reference_file_path ): """Create the straight beam for the tests.""" - # Create the beam mesh in space beam_type = generate_beam_class(n_nodes) mesh = Mesh() @@ -83,7 +82,6 @@ def test_integration_space_time_curved( n_nodes, assert_results_close, get_corresponding_reference_file_path ): """Create a curved beam for the tests.""" - # Create the beam mesh in space beam_type = generate_beam_class(n_nodes) mesh = Mesh() @@ -120,7 +118,6 @@ def test_integration_space_time_elbow( n_nodes, couple_nodes, assert_results_close, get_corresponding_reference_file_path ): """Create an elbow beam for the tests.""" - # Create the beam mesh in space beam_type = generate_beam_class(n_nodes) mesh = Mesh() @@ -162,7 +159,6 @@ def test_integration_space_time_varying_material_length( get_corresponding_reference_file_path, ): """Create an elbow beam for the tests.""" - beam_type = generate_beam_class(n_nodes) def beam_mesh_in_space_generator(time): @@ -224,9 +220,7 @@ def beam_mesh_in_space_generator(time): def test_integration_space_time_named_node_set( assert_results_close, get_corresponding_reference_file_path ): - """Create a straight beam and check that named node sets are handled - correctly.""" - + """Create a straight beam and check that named node sets are handled correctly.""" # Create the beam mesh in space mesh = Mesh() beam_type = generate_beam_class(2) @@ -257,7 +251,6 @@ def test_integration_space_time_node_sets( n_nodes, couple_nodes, assert_results_close, get_corresponding_reference_file_path ): """Check that geometry sets are correctly ported to space-time meshes.""" - mesh = Mesh() beam_type = generate_beam_class(n_nodes) beam_set_1 = create_beam_mesh_line( diff --git a/tests/other/test_other_create_cubit_input_files.py b/tests/other/test_other_create_cubit_input_files.py index 43654637..7c6663b8 100644 --- a/tests/other/test_other_create_cubit_input_files.py +++ b/tests/other/test_other_create_cubit_input_files.py @@ -42,7 +42,6 @@ def test_other_create_cubit_input_files_tube( assert_results_close, ): """Test that the solid tube reference file is up to date.""" - cubit = create_tube_cubit() for additional_identifier, mesh_in_exo in (("yaml", False), ("exo", True)): @@ -61,7 +60,6 @@ def test_other_create_cubit_input_files_block( assert_results_close, ): """Test that the solid block reference file is up to date.""" - result_path = tmp_path / get_corresponding_reference_file_path().name cubit = create_block_cubit() @@ -77,7 +75,6 @@ def test_other_create_cubit_input_files_solid_shell_blocks( assert_results_close, ): """Test that the solid shell reference files are up to date.""" - reference_path_blocks = get_corresponding_reference_file_path() result_path_blocks = tmp_path / reference_path_blocks.name @@ -96,7 +93,6 @@ def test_other_create_cubit_input_files_solid_shell_dome( assert_results_close, ): """Test that the solid shell reference files are up to date.""" - reference_path_dome = get_corresponding_reference_file_path() result_path_dome = tmp_path / reference_path_dome.name @@ -113,9 +109,7 @@ def test_other_create_cubit_input_files_single_solid_element_brick( get_default_test_solid_material, assert_results_close, ): - """Test that the single solid element brick reference files are up to - date.""" - + """Test that the single solid element brick reference files are up to date.""" reference_file = get_corresponding_reference_file_path() result_path = tmp_path / reference_file.name @@ -133,7 +127,6 @@ def test_other_create_cubit_input_files_solid_brick( assert_results_close, ): """Test that the solid brick reference files are up to date.""" - reference_file = get_corresponding_reference_file_path() result_path = tmp_path / reference_file.name @@ -147,7 +140,6 @@ def test_other_create_cubit_input_files_multiple_solid_bricks( tmp_path, get_corresponding_reference_file_path, assert_results_close ): """Test that the solid brick reference files are up to date.""" - cubit = create_multiple_solid_bricks() for additional_identifier, mesh_in_exo in (("yaml", False), ("exo", True)): @@ -164,7 +156,6 @@ def test_other_create_cubit_input_files_user_defined_node_sets_and_block_ids( tmp_path, get_corresponding_reference_file_path, assert_results_close ): """Test that the solid brick reference files are up to date.""" - reference_file = get_corresponding_reference_file_path() result_path = tmp_path / reference_file.name diff --git a/tests/other/test_other_create_input_files.py b/tests/other/test_other_create_input_files.py index d4605b9b..7ec5cce5 100644 --- a/tests/other/test_other_create_input_files.py +++ b/tests/other/test_other_create_input_files.py @@ -36,7 +36,6 @@ def test_other_create_input_files_beam_to_solid( get_corresponding_reference_file_path, ): """Create the input file for some beam-to-solid tests.""" - # Create the input file input_file, mesh = create_beam_to_solid_conditions_model( get_default_test_beam_material, diff --git a/tests/other/test_other_examples.py b/tests/other/test_other_examples.py index 1d204d27..fe7dfcf3 100644 --- a/tests/other/test_other_examples.py +++ b/tests/other/test_other_examples.py @@ -35,10 +35,9 @@ def test_other_examples_notebooks(notebook_path): """Parameterized test case for multiple Jupyter notebooks. - The notebook is run and it is checked that it runs through without - any errors/assertions. + The notebook is run and it is checked that it runs through without any + errors/assertions. """ - with testbook(notebook_path) as tb: # we do not define the examples as modules, therefore we need to add the # examples folder to the current sys path so examples/utils can be imported diff --git a/tests/performance/test_performance_beamme.py b/tests/performance/test_performance_beamme.py index 618aa016..0a452491 100644 --- a/tests/performance/test_performance_beamme.py +++ b/tests/performance/test_performance_beamme.py @@ -46,7 +46,6 @@ def shared_tmp_path(tmp_path_factory): def create_solid_block(cubit, file_path, nx, ny, nz): """Create a solid block (1 x 1 x 1) with (nx * ny * nz) elements.""" - # Create brick. brick = cubit.brick(1) @@ -133,9 +132,7 @@ def create_solid_block(cubit, file_path, nx, ny, nz): def create_beam_mesh(n_x, n_y, n_z, n_el): - """Create a beam grid on the domain (1 x 1 x 1) with (nx * ny * nz) "grid - cells".""" - + """Create a beam grid on the domain (1 x 1 x 1) with (nx * ny * nz) "grid cells".""" mesh = Mesh() material = MaterialReissner( radius=0.25 / np.max([n_x, n_y, n_z]), youngs_modulus=1.0 @@ -178,8 +175,8 @@ def create_beam_mesh(n_x, n_y, n_z, n_el): def medium_solid_block(shared_tmp_path, evaluate_execution_time): """Provide a solid mesh from cubit. - The version of Cubit we use in testing only allows for 50,000, so we - create a mesh with exactly that. + The version of Cubit we use in testing only allows for 50,000, so we create a mesh + with exactly that. """ cubit = CubitPy() input_file_path = shared_tmp_path / "performance_testing_solid_half.4C.yaml" @@ -203,16 +200,15 @@ def medium_solid_block(shared_tmp_path, evaluate_execution_time): def test_performance_beamme_cubitpy_create_solid(medium_solid_block): """Test the performance of creating a solid block using CubitPy. - The test is run in the fixture, so we don't need to do anything - here. + The test is run in the fixture, so we don't need to do anything here. """ pass @pytest.fixture(scope="module") def large_solid_block(evaluate_execution_time, medium_solid_block, shared_tmp_path): - """The version of Cubit we use in testing only allows for 50,000 elements, - our goal is 100,000 so we double the block with 50,000 elements here.""" + """The version of Cubit we use in testing only allows for 50,000 elements, our goal + is 100,000 so we double the block with 50,000 elements here.""" def double_block(): """Load the block with 50,000 elements and double the mesh.""" @@ -239,8 +235,7 @@ def double_block(): def test_performance_beamme_double_solid_block(large_solid_block): """Test the performance of doubling a solid block from an input file. - The test is run in the fixture, so we don't need to do anything - here. + The test is run in the fixture, so we don't need to do anything here. """ pass @@ -258,7 +253,6 @@ def test_performance_beamme_load_solid( evaluate_execution_time, large_solid_block, log_name, full_import, expected_time ): """Test the performance of loading a solid mesh.""" - evaluate_execution_time( log_name, import_four_c_model, @@ -273,7 +267,6 @@ def test_performance_beamme_load_solid( @pytest.fixture(scope="module") def large_beam_mesh(evaluate_execution_time): """Provide a large beam mesh.""" - return evaluate_execution_time( "BeamMe: Create large beam mesh", create_beam_mesh, @@ -291,8 +284,7 @@ def large_beam_mesh(evaluate_execution_time): def test_performance_beamme_create_beams(large_beam_mesh): """Test the performance of creating a large beam mesh. - The test is run in the fixture, so we don't need to do anything - here. + The test is run in the fixture, so we don't need to do anything here. """ pass @@ -300,7 +292,6 @@ def test_performance_beamme_create_beams(large_beam_mesh): @pytest.mark.performance def test_performance_beamme_copy_beams(large_beam_mesh, evaluate_execution_time): """Test the performance of copying a large beam mesh.""" - evaluate_execution_time( "BeamMe: Copy large beam mesh", large_beam_mesh.copy, @@ -312,7 +303,6 @@ def test_performance_beamme_copy_beams(large_beam_mesh, evaluate_execution_time) @pytest.mark.performance def test_performance_beamme_add_beams_to_mesh(large_beam_mesh, evaluate_execution_time): """Test the performance of adding a large beam mesh to another.""" - # To avoid modifying the original mesh, we make a copy and add to that. large_beam_mesh_copy = large_beam_mesh.copy() evaluate_execution_time( @@ -326,7 +316,6 @@ def test_performance_beamme_add_beams_to_mesh(large_beam_mesh, evaluate_executio @pytest.mark.performance def test_performance_beamme_rotate(large_beam_mesh, evaluate_execution_time): """Test the performance of rotating a large beam mesh.""" - # To avoid an expensive copy, we rotate the mesh back at the end of the test. rotation = Rotation([1, 1, 0], np.pi / 3) evaluate_execution_time( @@ -341,7 +330,6 @@ def test_performance_beamme_rotate(large_beam_mesh, evaluate_execution_time): @pytest.mark.performance def test_performance_beamme_translate(large_beam_mesh, evaluate_execution_time): """Test the performance of translating a large beam mesh.""" - # To avoid an expensive copy, we move the mesh back at the end of the test. distance = np.array([0.5, 0, 0]) evaluate_execution_time( @@ -356,7 +344,6 @@ def test_performance_beamme_translate(large_beam_mesh, evaluate_execution_time): @pytest.mark.performance def test_performance_beamme_reflect(large_beam_mesh, evaluate_execution_time): """Test the performance of reflecting a large beam mesh.""" - # To avoid modifying the original mesh, we make a copy and reflect that. large_beam_mesh_copy = large_beam_mesh.copy() evaluate_execution_time( @@ -372,7 +359,6 @@ def test_performance_beamme_wrap_around_cylinder( large_beam_mesh, evaluate_execution_time ): """Test the performance of wrapping a large beam mesh around a cylinder.""" - # To avoid modifying the original mesh, we make a copy and wrap that. large_beam_mesh_copy = large_beam_mesh.copy() evaluate_execution_time( @@ -387,9 +373,8 @@ def test_performance_beamme_wrap_around_cylinder( def test_performance_beamme_wrap_around_cylinder_without_check( large_beam_mesh, evaluate_execution_time ): - """Test the performance of wrapping a large beam mesh around a cylinder - without checking for advanced warnings.""" - + """Test the performance of wrapping a large beam mesh around a cylinder without + checking for advanced warnings.""" # To avoid modifying the original mesh, we make a copy and wrap that. large_beam_mesh_copy = large_beam_mesh.copy() evaluate_execution_time( @@ -403,7 +388,6 @@ def test_performance_beamme_wrap_around_cylinder_without_check( @pytest.mark.performance def test_performance_beamme_find_close_nodes(large_beam_mesh, evaluate_execution_time): """Test the performance of finding close nodes in a large beam mesh.""" - evaluate_execution_time( "BeamMe: Find close nodes in large beam mesh", find_close_nodes, @@ -418,7 +402,6 @@ def test_performance_beamme_couple_nodes(large_beam_mesh, evaluate_execution_tim We add the mesh to itself, to have matching nodes to replace. """ - # To avoid modifying the original mesh, we make a copies and add them to each # other. large_beam_mesh_copy_1 = large_beam_mesh.copy() @@ -435,7 +418,6 @@ def test_performance_beamme_couple_nodes(large_beam_mesh, evaluate_execution_tim @pytest.fixture(scope="module") def large_beam_input_file(large_beam_mesh, evaluate_execution_time): """Provide a large input file containing a beam mesh.""" - input_file = InputFile() evaluate_execution_time( "BeamMe: Add large beam mesh to input file", @@ -450,8 +432,7 @@ def large_beam_input_file(large_beam_mesh, evaluate_execution_time): def test_performance_beamme_add_mesh_to_input_file(large_beam_input_file): """Test the performance of adding a mesh to an input file. - The test is run in the fixture, so we don't need to do anything - here. + The test is run in the fixture, so we don't need to do anything here. """ pass @@ -473,7 +454,6 @@ def test_performance_beamme_dump_input_file( tmp_path, ): """Test the performance of dumping an input file with a large beam mesh.""" - evaluate_execution_time( log_name, large_beam_input_file.dump, @@ -491,7 +471,6 @@ def test_performance_beamme_write_vtu( large_beam_mesh, evaluate_execution_time, tmp_path ): """Test the performance of writing a beam mesh to VTU format.""" - evaluate_execution_time( "BeamMe: Write beam mesh to VTU", large_beam_mesh.write_vtu, diff --git a/tests/performance/test_performance_mesh_creation_functions_beam_parametric_curve.py b/tests/performance/test_performance_mesh_creation_functions_beam_parametric_curve.py index 15d3d224..ba5057fb 100644 --- a/tests/performance/test_performance_mesh_creation_functions_beam_parametric_curve.py +++ b/tests/performance/test_performance_mesh_creation_functions_beam_parametric_curve.py @@ -38,7 +38,6 @@ def test_performance_mesh_creation_functions_beam_parametric_curve( evaluate_execution_time, get_parametric_function ): """Test the performance of the parametric curve creation function.""" - mesh = Mesh() material = MaterialBeamBase() @@ -65,14 +64,13 @@ def test_performance_mesh_creation_functions_beam_parametric_curve_splinepy( get_splinepy_object, evaluate_execution_time, ): - """Test the performance of the parametric curve creation function with a - splinepy object. + """Test the performance of the parametric curve creation function with a splinepy + object. - Compared to a pure given function, this method does not have the - overhead of evaluating the Jacobian with automated differentiation, - as splinepy provides the derivatives explicitly. + Compared to a pure given function, this method does not have the overhead of + evaluating the Jacobian with automated differentiation, as splinepy provides the + derivatives explicitly. """ - mesh = Mesh() material = MaterialBeamBase() diff --git a/tests/performance/test_performance_space_time.py b/tests/performance/test_performance_space_time.py index 1e14679e..4c25f970 100644 --- a/tests/performance/test_performance_space_time.py +++ b/tests/performance/test_performance_space_time.py @@ -33,7 +33,6 @@ @pytest.fixture(scope="module") def mesh_in_space(evaluate_execution_time): """Provide mesh in space direction.""" - mesh = Mesh() beam_type = generate_beam_class(3) @@ -58,8 +57,7 @@ def mesh_in_space(evaluate_execution_time): def test_performance_space_time_create_mesh_in_space(mesh_in_space): """Test the performance of the mesh creation in space. - The test is run in the fixture, so we don't need to do anything - here. + The test is run in the fixture, so we don't need to do anything here. """ pass @@ -69,7 +67,6 @@ def test_performance_space_time_create_mesh_in_time( mesh_in_space, evaluate_execution_time ): """Test the performance of the mesh creation in time.""" - evaluate_execution_time( "BeamMe: Space-Time: Create mesh in time", beam_to_space_time, diff --git a/utils/check_python_imports.py b/utils/check_python_imports.py index 8366938b..ffe477d0 100644 --- a/utils/check_python_imports.py +++ b/utils/check_python_imports.py @@ -19,9 +19,8 @@ # 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. -"""This script checks if all Python imports within provided files align with -our coding style, as described in the section "Coding guidelines" in the -repository README.md.""" +"""This script checks if all Python imports within provided files align with our coding +style, as described in the section "Coding guidelines" in the repository README.md.""" import ast as _ast import sys as _sys @@ -48,18 +47,16 @@ def __init__(self, filename: str) -> None: Args: filename: The filename of the current file (to store for errors) """ - self.errors: list[Error] = [] self.filename = filename def visit_Import(self, node: _ast.Import) -> None: - """Visit an import statement and check if the import aligns with our - coding style. + """Visit an import statement and check if the import aligns with our coding + style. Args: node: The import node to check. """ - for alias in node.names: if alias.asname is None: self.errors.append( @@ -82,13 +79,12 @@ def visit_Import(self, node: _ast.Import) -> None: self.generic_visit(node) def visit_ImportFrom(self, node: _ast.ImportFrom) -> None: - """Visit an import from statement and check if the import aligns with - our coding style. + """Visit an import from statement and check if the import aligns with our coding + style. Args: node: The import from node to check. """ - for alias in node.names: # Check for wildcard imports if alias.name == "*": @@ -167,7 +163,6 @@ def check_file(filename: str) -> list[Error]: Returns: List of errors found in the Python file. """ - with open(filename, "r") as file: content = file.read() tree = _ast.parse(content, filename=filename) @@ -179,7 +174,6 @@ def check_file(filename: str) -> list[Error]: def main() -> None: """Check all provided Python files for import errors.""" - errors: list[Error] = [] for filename in _sys.argv[1:]: diff --git a/utils/logo.py b/utils/logo.py index 0edd739e..a257fdf6 100644 --- a/utils/logo.py +++ b/utils/logo.py @@ -964,8 +964,8 @@ def create_curve(curve, **kwargs): def create_mesh_curves(curves, l_el) -> Mesh: - """Create a BeamMe mesh for all given curves and return a single mesh - containing all curves.""" + """Create a BeamMe mesh for all given curves and return a single mesh containing all + curves.""" mesh = Mesh() for i in range(len(curves)): curve_mesh, _ = create_curve(curves[i], l_el=l_el) @@ -975,7 +975,6 @@ def create_mesh_curves(curves, l_el) -> Mesh: def add_letter_B(plotter, plot_data, lighting=True): """Add the letter B to the plotter.""" - color_letter = "#1E3A8A" color_nodes = "#FFD43B" # "#F43F5E" curves = CHARACTER_SPLINEPY["B"] @@ -1008,7 +1007,6 @@ def add_letter_B(plotter, plot_data, lighting=True): def add_letter_e(plotter, plot_data): """Add the letter e to the plotter.""" - color = "#60A5FA" mesh = Mesh() cross_section = 3.0 * np.array([[-1, -1], [1, -1], [1, 1], [-1, 1]]) @@ -1039,7 +1037,6 @@ def add_letter_e(plotter, plot_data): def add_letter_a(plotter, plot_data): """Add the letter a to the plotter.""" - color_letter = "black" color_control_polygon = "blue" color_control_points = "red" @@ -1089,7 +1086,6 @@ def add_letter_a(plotter, plot_data): def add_letter_m(plotter, plot_data): """Add the letter m to the plotter.""" - color_letter = "#FBBF24" mesh = Mesh() factor = 4.0 @@ -1152,7 +1148,6 @@ def add_letter_m(plotter, plot_data): def create_2d_mesh_cubit(plot_data): """Create the 2D mesh for the letters M and e.""" - if not cupy.is_coreform(): raise ValueError("This script requires Cubit Coreform") @@ -1202,7 +1197,6 @@ def create_2d_mesh_cubit(plot_data): def get_letter_2d_grid(plot_data): """Return the PyVista grids for the 2D letters.""" - _, solid_mesh = import_four_c_model( plot_data["input_file_name"], convert_input_to_mesh=True ) @@ -1222,7 +1216,6 @@ def get_letter_2d_grid(plot_data): def add_letter_2d_full(plotter, plot_data): """Add both 2D letters to the plotter.""" - color_letters = {0: "#10B981", 1: "#F472B6"} grids = get_letter_2d_grid(plot_data) translate_vector = np.array([294.7, -80.7, 0.0]) @@ -1237,7 +1230,6 @@ def add_letter_2d_full(plotter, plot_data): def add_letter_2d_small(plotter, plot_data, lighting=False): """Add just the M of the 2D letters to the plotter.""" - color = "#10B981" grid_M, _ = get_letter_2d_grid(plot_data) grid_M.translate([-235, 0, 0], inplace=True) @@ -1254,7 +1246,6 @@ def add_letter_2d_small(plotter, plot_data, lighting=False): def create_beamme_logo_full(plotter, plot_data): """Create the full BeamMe logo.""" - # Create the letters add_letter_B(plotter, plot_data) add_letter_e(plotter, plot_data) @@ -1282,7 +1273,6 @@ def create_beamme_logo_full(plotter, plot_data): def create_beamme_logo_small(plotter, plot_data, square=True): """Create the small BeamMe logo.""" - # Create the letters add_letter_B(plotter, plot_data, lighting=False) add_letter_2d_small(plotter, plot_data, lighting=False) @@ -1312,7 +1302,6 @@ def create_beamme_logo_small(plotter, plot_data, square=True): def create_beamme_logo(base_dir, create_cubit=True): """Create the BeamMe logo images.""" - # General parameters plot_data = { "l_el_coarse": 20.0, diff --git a/utils/validate_4C_files.py b/utils/validate_4C_files.py index 1f353a27..e71f749b 100644 --- a/utils/validate_4C_files.py +++ b/utils/validate_4C_files.py @@ -19,8 +19,7 @@ # 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. -"""This script validates all 4C input files with FourCIPP in this -repository.""" +"""This script validates all 4C input files with FourCIPP in this repository.""" import sys as _sys from dataclasses import dataclass as _dataclass @@ -46,7 +45,6 @@ def validate_file(filename: str) -> list[Error]: Returns: List of errors found in the 4C input file or None. """ - try: inputfile = FourCInput.from_4C_yaml(_Path(filename)) inputfile.validate(sections_only=True) @@ -58,7 +56,6 @@ def validate_file(filename: str) -> list[Error]: def main() -> None: """Validate all 4C input files with FourCIPP.""" - errors: list[Error] = [] for filename in _sys.argv[1:]: diff --git a/website/docs/prepare_docs.py b/website/docs/prepare_docs.py index 471bc09e..33f24eda 100644 --- a/website/docs/prepare_docs.py +++ b/website/docs/prepare_docs.py @@ -29,10 +29,8 @@ def prepare_docs(): """Prepare documentation for the website. - Currently, this only copies the README.md file to the documentation - directory. + Currently, this only copies the README.md file to the documentation directory. """ - markdown_dir = Path("website/docs/source/md") # create directory which contains all the markdown files From 5419f5f877e98db20a8c5aada36b0ecc606a319e Mon Sep 17 00:00:00 2001 From: Ivo Steinbrecher Date: Wed, 8 Jul 2026 11:52:07 +0200 Subject: [PATCH 04/10] Fix mypy errors --- src/beamme/core/mesh.py | 2 +- src/beamme/four_c/model_importer.py | 3 ++- src/beamme/space_time/beam_to_space_time.py | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/beamme/core/mesh.py b/src/beamme/core/mesh.py index b54b8658..09616eff 100644 --- a/src/beamme/core/mesh.py +++ b/src/beamme/core/mesh.py @@ -907,7 +907,7 @@ def get_mesh_representation( ) ) else: - element_set_indices.append(element.i_global) + element_set_indices.append(_cast(int, element.i_global)) element_set_flag[element_set_indices] = 1 else: diff --git a/src/beamme/four_c/model_importer.py b/src/beamme/four_c/model_importer.py index 6f32a8aa..51316848 100644 --- a/src/beamme/four_c/model_importer.py +++ b/src/beamme/four_c/model_importer.py @@ -35,6 +35,7 @@ from beamme.core.conf import Geometry as _Geometry from beamme.core.conf import bme as _bme from beamme.core.coupling import Coupling as _Coupling +from beamme.core.element import Element as _Element from beamme.core.geometry_set import GeometrySetNodes as _GeometrySetNodes from beamme.core.mesh import Mesh as _Mesh from beamme.core.mesh_representation import ( @@ -567,7 +568,7 @@ def _create_mesh_from_mesh_representation( ) # extract element types - element_type_id_to_element_type: dict[int, type] = {} + element_type_id_to_element_type: dict[int, type[_Element]] = {} for ( element_type_id, element_data, diff --git a/src/beamme/space_time/beam_to_space_time.py b/src/beamme/space_time/beam_to_space_time.py index 277e2264..1b820fe3 100644 --- a/src/beamme/space_time/beam_to_space_time.py +++ b/src/beamme/space_time/beam_to_space_time.py @@ -24,6 +24,7 @@ from typing import Callable as _Callable from typing import Tuple as _Tuple from typing import Type as _Type +from typing import cast as _cast import numpy as _np import pyvista as _pv @@ -276,7 +277,7 @@ def beam_to_space_time( for i_element_row_in_time in range(number_of_elements_in_time): raised_geometry_set_elements.append( space_time_elements[ - element.i_global + _cast(int, element.i_global) + i_element_row_in_time * number_of_elements_in_space ] ) From c6cb45c6b25ab537c79d6fc570638780cdc73815 Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 13:22:04 +0200 Subject: [PATCH 05/10] feat: change code base to use Python 3.11 features --- src/beamme/core/boundary_condition.py | 3 +-- src/beamme/core/geometry_set.py | 4 ++-- src/beamme/core/mesh.py | 8 ++++---- src/beamme/core/mesh_representation.py | 2 +- src/beamme/core/mesh_utils.py | 8 ++------ src/beamme/core/nurbs_patch.py | 2 +- src/beamme/core/rotation.py | 10 ++++++---- src/beamme/cosserat_curve/cosserat_curve.py | 7 +++---- .../cosserat_curve/warping_along_cosserat_curve.py | 6 ++---- src/beamme/four_c/function_utility.py | 10 ++++------ src/beamme/four_c/header_functions.py | 5 ++--- src/beamme/four_c/input_file.py | 5 +++-- src/beamme/four_c/input_file_dump_functions.py | 7 +++---- src/beamme/four_c/locsys_condition.py | 4 +--- src/beamme/four_c/model_importer.py | 5 ++--- src/beamme/four_c/solid_shell_thickness_direction.py | 4 +--- src/beamme/mesh_creation_functions/beam_generic.py | 5 ++--- .../mesh_creation_functions/beam_parametric_curve.py | 5 ++--- src/beamme/space_time/beam_to_space_time.py | 8 +++----- src/beamme/utils/data_structures.py | 2 +- src/beamme/utils/environment.py | 3 +-- tests/beamme/core/test_beamme_core_geometry_set.py | 2 +- tests/conftest.py | 2 +- tests/conftest_performance_tests.py | 2 +- tests/conftest_result_comparison.py | 3 ++- tests/conftest_test_object_generators.py | 4 ++-- .../integration/test_integration_four_c_simulation.py | 4 ++-- 27 files changed, 56 insertions(+), 74 deletions(-) diff --git a/src/beamme/core/boundary_condition.py b/src/beamme/core/boundary_condition.py index e4df300c..b01561f8 100644 --- a/src/beamme/core/boundary_condition.py +++ b/src/beamme/core/boundary_condition.py @@ -22,7 +22,6 @@ """This module implements a class to represent boundary conditions.""" import warnings as _warnings -from typing import Dict as _Dict import beamme.core.conf as _conf from beamme.core.base_mesh_item import BaseMeshItem as _BaseMeshItem @@ -59,7 +58,7 @@ class BoundaryCondition(BoundaryConditionBase): def __init__( self, geometry_set: _GeometrySetBase, - data: _Dict, + data: dict, bc_type: _conf.BoundaryCondition | str, *, double_nodes: _conf.DoubleNodes | None = None, diff --git a/src/beamme/core/geometry_set.py b/src/beamme/core/geometry_set.py index 207343c5..db4aa784 100644 --- a/src/beamme/core/geometry_set.py +++ b/src/beamme/core/geometry_set.py @@ -21,8 +21,8 @@ # THE SOFTWARE. """This module implements a basic class to manage geometry in the input file.""" -from typing import KeysView as _KeysView -from typing import Sequence as _Sequence +from collections.abc import KeysView as _KeysView +from collections.abc import Sequence as _Sequence from typing import cast as _cast import beamme.core.conf as _conf diff --git a/src/beamme/core/mesh.py b/src/beamme/core/mesh.py index 09616eff..ebf1eea5 100644 --- a/src/beamme/core/mesh.py +++ b/src/beamme/core/mesh.py @@ -26,7 +26,7 @@ import warnings as _warnings from pathlib import Path as _Path from typing import Any as _Any -from typing import List as _List +from typing import Self as _Self from typing import cast as _cast import numpy as _np @@ -205,7 +205,7 @@ def add_geometry_name(self, geometry_name): for key in keys: self.add(geometry_name[key]) - def add_list(self, add_list: _List, **kwargs) -> None: + def add_list(self, add_list: list, **kwargs) -> None: """Add a list of items to this mesh. Args: @@ -230,7 +230,7 @@ def add_list(self, add_list: _List, **kwargs) -> None: elif len(types) == 1: list_type = types.pop() - def extend_internal_list(self_list: _List, new_list: _List) -> None: + def extend_internal_list(self_list: list, new_list: list) -> None: """Extend an internal list with the new list. It is checked that the final list does not have duplicate entries. @@ -1141,7 +1141,7 @@ def display_pyvista( else: return plotter - def copy(self) -> "Mesh": + def copy(self) -> _Self: """Return a deep copy of this mesh. The internal mesh data (nodes, elements, boundary conditions, and diff --git a/src/beamme/core/mesh_representation.py b/src/beamme/core/mesh_representation.py index 76da9006..9d73ba4d 100644 --- a/src/beamme/core/mesh_representation.py +++ b/src/beamme/core/mesh_representation.py @@ -21,10 +21,10 @@ # THE SOFTWARE. """This module defines the mesh representation data structure.""" +from collections.abc import Iterable as _Iterable from dataclasses import dataclass as _dataclass from itertools import repeat as _repeat from typing import Any as _Any -from typing import Iterable as _Iterable import numpy as _np import pyvista as _pv diff --git a/src/beamme/core/mesh_utils.py b/src/beamme/core/mesh_utils.py index f91727eb..7237811a 100644 --- a/src/beamme/core/mesh_utils.py +++ b/src/beamme/core/mesh_utils.py @@ -21,10 +21,6 @@ # THE SOFTWARE. """This module defines utility functions for meshes.""" -from typing import Dict as _Dict -from typing import List as _List -from typing import Tuple as _Tuple - import numpy as _np from beamme.core.conf import bme as _bme @@ -40,7 +36,7 @@ def get_coupled_nodes_to_master_map( mesh: _Mesh, *, assign_i_global: bool = False -) -> _Tuple[_Dict[_Node, _Node], _List[_Node]]: +) -> tuple[dict[_Node, _Node], list[_Node]]: """Get a mapping of nodes in a mesh that should be "replaced" because they are coupled via a joint. @@ -101,7 +97,7 @@ def get_coupled_nodes_to_master_map( def apply_nodal_coupling_to_mesh_representation( mesh_representation: _MeshRepresentation, - geometry_sets_to_i_global: _Dict[_GeometrySetBase, int], + geometry_sets_to_i_global: dict[_GeometrySetBase, int], coupling_conditions: list[_Coupling], ): """Modify a mesh representation such that coupled nodes are represented by a single diff --git a/src/beamme/core/nurbs_patch.py b/src/beamme/core/nurbs_patch.py index 7dc6e087..970e1e3b 100644 --- a/src/beamme/core/nurbs_patch.py +++ b/src/beamme/core/nurbs_patch.py @@ -22,7 +22,7 @@ """This module implements NURBS patches for the mesh.""" from abc import abstractmethod as _abstractmethod -from typing import Iterator as _Iterator +from collections.abc import Iterator as _Iterator import numpy as _np import pyvista as _pv diff --git a/src/beamme/core/rotation.py b/src/beamme/core/rotation.py index b9506414..d1ef510b 100644 --- a/src/beamme/core/rotation.py +++ b/src/beamme/core/rotation.py @@ -21,6 +21,8 @@ # THE SOFTWARE. """This module defines a class that represents a rotation in 3D.""" +from typing import Self as _Self + import numpy as _np import quaternion as _quaternion from numpy.typing import NDArray as _NDArray @@ -75,7 +77,7 @@ def __init__(self, *args): raise ValueError(f"The given arguments {args} are invalid!") @classmethod - def from_quaternion(cls, q, *, normalized=False): + def from_quaternion(cls, q, *, normalized=False) -> _Self: """Create the object from a quaternion float array (4x1) Args @@ -100,7 +102,7 @@ def from_quaternion(cls, q, *, normalized=False): return rotation @classmethod - def from_rotation_matrix(cls, R): + def from_rotation_matrix(cls, R) -> _Self: """Create the object from a rotation matrix. The code is based on Spurriers algorithm: @@ -131,7 +133,7 @@ def from_rotation_matrix(cls, R): return cls.from_quaternion(q) @classmethod - def from_basis(cls, t1, t2): + def from_basis(cls, t1, t2) -> _Self: """Create the object from two basis vectors t1, t2. t2 will be orthogonalized on t1, and t3 will be calculated with the cross @@ -155,7 +157,7 @@ def from_basis(cls, t1, t2): return cls.from_rotation_matrix(R) @classmethod - def from_rotation_vector(cls, rotation_vector): + def from_rotation_vector(cls, rotation_vector) -> _Self: """Create the object from a rotation vector.""" q = _np.zeros(4) rotation_vector = _np.asarray(rotation_vector) diff --git a/src/beamme/cosserat_curve/cosserat_curve.py b/src/beamme/cosserat_curve/cosserat_curve.py index 90231c37..74ab9a8c 100644 --- a/src/beamme/cosserat_curve/cosserat_curve.py +++ b/src/beamme/cosserat_curve/cosserat_curve.py @@ -23,7 +23,6 @@ objects.""" from pathlib import Path as _Path -from typing import Tuple as _Tuple from xml.etree import ElementTree as _ET # nosec B405 import numpy as _np @@ -128,7 +127,7 @@ def basis(i): def get_relative_distance_and_rotations( coordinates: _np.ndarray, quaternions: _NDArray[_quaternion.quaternion] -) -> _Tuple[ +) -> tuple[ _np.ndarray, _NDArray[_quaternion.quaternion], _NDArray[_quaternion.quaternion] ]: """Get relative distances and rotations that can be used to evaluate @@ -294,14 +293,14 @@ def twist(self, twist_angle: float) -> None: def get_centerline_position_and_rotation( self, arc_length: float, **kwargs - ) -> _Tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: + ) -> tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: """Return the position and rotation at a given centerline arc length.""" pos, rot = self.get_centerline_positions_and_rotations([arc_length], **kwargs) return pos[0], rot[0] def get_centerline_positions_and_rotations( self, points_on_arc_length, *, factor=1.0 - ) -> _Tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: + ) -> tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: """Return the position and rotation at given centerline arc lengths. If the points are outside of the valid interval, a linear extrapolation will be diff --git a/src/beamme/cosserat_curve/warping_along_cosserat_curve.py b/src/beamme/cosserat_curve/warping_along_cosserat_curve.py index db5d26c9..2b9893b5 100644 --- a/src/beamme/cosserat_curve/warping_along_cosserat_curve.py +++ b/src/beamme/cosserat_curve/warping_along_cosserat_curve.py @@ -21,8 +21,6 @@ # THE SOFTWARE. """This file contains functionality to warp an existing mesh along a 1D curve.""" -from typing import Tuple as _Tuple - import numpy as _np import quaternion as _quaternion from numpy.typing import NDArray as _NDArray @@ -45,7 +43,7 @@ def get_arc_length_and_cross_section_coordinates( coordinates: _np.ndarray, origin: _np.ndarray, reference_rotation: _Rotation -) -> _Tuple[float, _np.ndarray]: +) -> tuple[float, _np.ndarray]: """Return the arc length and the cross section coordinates for a coordinate system defined by the reference rotation and the origin. @@ -74,7 +72,7 @@ def get_mesh_transformation( n_steps: int = 10, initial_configuration: bool = True, **kwargs, -) -> _Tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: +) -> tuple[_np.ndarray, _NDArray[_quaternion.quaternion]]: """Generate a list of positions for each node that describe the transformation of the nodes from the given configuration to the Cosserat curve. diff --git a/src/beamme/four_c/function_utility.py b/src/beamme/four_c/function_utility.py index faaf5a86..a8cd187f 100644 --- a/src/beamme/four_c/function_utility.py +++ b/src/beamme/four_c/function_utility.py @@ -21,15 +21,13 @@ # THE SOFTWARE. """This module implements utility functions to create 4C space time function.""" -from typing import List as _List - import numpy as _np from beamme.core.function import Function as _Function def create_linear_interpolation_dict( - times: _List[float], values: _List[float], *, variable_name="var", variable_index=0 + times: list[float], values: list[float], *, variable_name="var", variable_index=0 ): """Create a string that describes a variable that is linear interpolated over time. @@ -64,8 +62,8 @@ def create_linear_interpolation_dict( def create_linear_interpolation_function( - times: _List[float], - values: _List[float], + times: list[float], + values: list[float], *, function_type="SYMBOLIC_FUNCTION_OF_SPACE_TIME", ): @@ -81,7 +79,7 @@ def create_linear_interpolation_function( return _Function([{function_type: "var"}, function_dict]) -def ensure_length_of_function_array(function_array: _List, length: int = 3): +def ensure_length_of_function_array(function_array: list, length: int = 3): """Performs size check of a function array and appends the function array to the given length, if a list with only one item is provided. diff --git a/src/beamme/four_c/header_functions.py b/src/beamme/four_c/header_functions.py index ee646a22..f8ff02bc 100644 --- a/src/beamme/four_c/header_functions.py +++ b/src/beamme/four_c/header_functions.py @@ -23,7 +23,6 @@ file.""" from typing import Any as _Any -from typing import List as _List from beamme.core.conf import bme as _bme from beamme.four_c.input_file import InputFile as _InputFile @@ -553,8 +552,8 @@ def set_beam_contact_section( def add_result_description( input_file: _InputFile, - displacements: _List, - node_ids: _List[int], + displacements: list, + node_ids: list[int], *, tol: float = 1e-10, ): diff --git a/src/beamme/four_c/input_file.py b/src/beamme/four_c/input_file.py index 4ef53a65..373b2ed8 100644 --- a/src/beamme/four_c/input_file.py +++ b/src/beamme/four_c/input_file.py @@ -22,10 +22,11 @@ """This module defines the classes that are used to create an input file for 4C.""" import os as _os +from collections.abc import Callable as _Callable from datetime import datetime as _datetime from pathlib import Path as _Path from typing import Any as _Any -from typing import Callable as _Callable +from typing import Self as _Self from fourcipp.fourc_input import FourCInput as _FourCInput from fourcipp.fourc_input import sort_by_section_names as _sort_by_section_names @@ -108,7 +109,7 @@ def __getitem__(self, key: str) -> _Any: @classmethod def from_4C_yaml( cls, input_file_path: str | _Path, header_only: bool = False - ) -> "InputFile": + ) -> _Self: """Load 4C yaml file. Args: diff --git a/src/beamme/four_c/input_file_dump_functions.py b/src/beamme/four_c/input_file_dump_functions.py index 57af29a2..014175de 100644 --- a/src/beamme/four_c/input_file_dump_functions.py +++ b/src/beamme/four_c/input_file_dump_functions.py @@ -22,9 +22,8 @@ """This file defines functions to dump mesh items for 4C.""" from collections import defaultdict as _defaultdict +from collections.abc import KeysView as _KeysView from typing import Any as _Any -from typing import KeysView as _KeysView -from typing import List as _List import numpy as _np import pyvista as _pv @@ -260,7 +259,7 @@ def dump_mesh_to_input_file(input_file, mesh: _Mesh) -> None: lambda _, obj: nurbs_patch_to_i_global[obj] + 1 + start_index_nurbs_patches, ) - def _dump(section_name: str, items: _List | _KeysView) -> None: + def _dump(section_name: str, items: list | _KeysView) -> None: """Dump list of items to a section in the input file. This function ensures that the dumped items will be appended to the @@ -349,7 +348,7 @@ def dump_mesh_representation_to_input_file_yaml( for section in ("FLUID ELEMENTS", "STRUCTURE ELEMENTS") ) - def _dump(section_name: str, dictionary_list: _List): + def _dump(section_name: str, dictionary_list: list): """Append the given list of dictionaries to the section in the input file.""" if len(dictionary_list) == 0: return diff --git a/src/beamme/four_c/locsys_condition.py b/src/beamme/four_c/locsys_condition.py index d733ef18..41cc82a0 100644 --- a/src/beamme/four_c/locsys_condition.py +++ b/src/beamme/four_c/locsys_condition.py @@ -21,8 +21,6 @@ # THE SOFTWARE. """This file contains the wrapper for the LocSys condition for 4c.""" -from typing import List as _List - from beamme.core.boundary_condition import BoundaryCondition as _BoundaryCondition from beamme.core.conf import bme as _bme from beamme.core.function import Function as _Function @@ -45,7 +43,7 @@ def __init__( geometry_set: _GeometrySet, *, rotation: None | _Rotation = None, - function_array: None | _List[_Function | int] = None, + function_array: None | list[_Function | int] = None, update_node_position: bool = False, use_consistent_node_normal: bool = False, **kwargs, diff --git a/src/beamme/four_c/model_importer.py b/src/beamme/four_c/model_importer.py index 51316848..16e865c5 100644 --- a/src/beamme/four_c/model_importer.py +++ b/src/beamme/four_c/model_importer.py @@ -24,7 +24,6 @@ import tempfile as _tempfile from collections import defaultdict as _defaultdict from pathlib import Path as _Path -from typing import Tuple as _Tuple import numpy as _np @@ -109,7 +108,7 @@ def get_unique_id(self, data: _FourCElementData) -> int: def import_cubitpy_model( cubit, convert_input_to_mesh: bool = False -) -> _Tuple[_InputFile, _Mesh]: +) -> tuple[_InputFile, _Mesh]: """Convert a CubitPy instance to a BeamMe InputFile. Args: @@ -139,7 +138,7 @@ def import_cubitpy_model( def import_four_c_model( input_file_path: _Path, convert_input_to_mesh: bool = False -) -> _Tuple[_InputFile, _Mesh]: +) -> tuple[_InputFile, _Mesh]: """Import an existing 4C input file and optionally convert it into a BeamMe mesh. Args: diff --git a/src/beamme/four_c/solid_shell_thickness_direction.py b/src/beamme/four_c/solid_shell_thickness_direction.py index 3bb2cb5f..45615584 100644 --- a/src/beamme/four_c/solid_shell_thickness_direction.py +++ b/src/beamme/four_c/solid_shell_thickness_direction.py @@ -22,8 +22,6 @@ """This function allows to reorder the connectivity of solid shell elements such that the solid shell direction is correctly represented.""" -from typing import List as _List - import numpy as _np import pyvista as _pv @@ -159,7 +157,7 @@ def get_reordering_index_director_projection( def set_solid_shell_thickness_direction( - elements: _List[_Element], + elements: list[_Element], *, selection_type="thickness", director=None, diff --git a/src/beamme/mesh_creation_functions/beam_generic.py b/src/beamme/mesh_creation_functions/beam_generic.py index a62b8720..3f9a4199 100644 --- a/src/beamme/mesh_creation_functions/beam_generic.py +++ b/src/beamme/mesh_creation_functions/beam_generic.py @@ -21,9 +21,8 @@ # THE SOFTWARE. """Generic function for beam creation.""" +from collections.abc import Callable as _Callable from typing import Any as _Any -from typing import Callable as _Callable -from typing import Type as _Type import numpy as _np @@ -274,7 +273,7 @@ def _check_given_node_and_return_relative_twist( def create_beam_mesh_generic( mesh: _Mesh, *, - beam_class: _Type[_Beam], + beam_class: type[_Beam], material: _MaterialBeamBase, beam_function: _Any, interval: tuple[float, float], diff --git a/src/beamme/mesh_creation_functions/beam_parametric_curve.py b/src/beamme/mesh_creation_functions/beam_parametric_curve.py index d2394a94..aee83e29 100644 --- a/src/beamme/mesh_creation_functions/beam_parametric_curve.py +++ b/src/beamme/mesh_creation_functions/beam_parametric_curve.py @@ -21,8 +21,7 @@ # THE SOFTWARE. """This file has functions to create a beam from a parametric curve.""" -from typing import Callable as _Callable -from typing import Type as _Type +from collections.abc import Callable as _Callable import numpy as _np import scipy.integrate as _integrate @@ -279,7 +278,7 @@ def evaluate_all( def create_beam_mesh_parametric_curve( mesh: _Mesh, - beam_class: _Type[_Beam], + beam_class: type[_Beam], material: _MaterialBeamBase, function: _Callable, interval: tuple[float, float], diff --git a/src/beamme/space_time/beam_to_space_time.py b/src/beamme/space_time/beam_to_space_time.py index 1b820fe3..efae54e8 100644 --- a/src/beamme/space_time/beam_to_space_time.py +++ b/src/beamme/space_time/beam_to_space_time.py @@ -21,9 +21,7 @@ # THE SOFTWARE. """Convert a beam to a space time surface mesh.""" -from typing import Callable as _Callable -from typing import Tuple as _Tuple -from typing import Type as _Type +from collections.abc import Callable as _Callable from typing import cast as _cast import numpy as _np @@ -87,7 +85,7 @@ def beam_to_space_time( number_of_elements_in_time: int, *, time_start: float = 0.0, -) -> _Tuple[_Mesh, _GeometryName]: +) -> tuple[_Mesh, _GeometryName]: """Convert a beam mesh to a surface space-time mesh. Args: @@ -128,7 +126,7 @@ def beam_to_space_time( # Calculate global mesh properties number_of_nodes_in_space = len(mesh_space_reference.nodes) number_of_elements_in_space = len(mesh_space_reference.elements) - space_time_element_type: _Type[SpaceTimeElementQuad4] | _Type[SpaceTimeElementQuad9] + space_time_element_type: type[SpaceTimeElementQuad4] | type[SpaceTimeElementQuad9] if len(element_type.nodes_create) == 2: number_of_copies_in_time = number_of_elements_in_time + 1 diff --git a/src/beamme/utils/data_structures.py b/src/beamme/utils/data_structures.py index 01233dea..613127ee 100644 --- a/src/beamme/utils/data_structures.py +++ b/src/beamme/utils/data_structures.py @@ -21,8 +21,8 @@ # THE SOFTWARE. """Helper functions for data structure related functionality.""" +from collections.abc import Callable as _Callable from typing import Any as _Any -from typing import Callable as _Callable from fourcipp.utils.dict_utils import ( compare_nested_dicts_or_lists as _compare_nested_dicts_or_lists, diff --git a/src/beamme/utils/environment.py b/src/beamme/utils/environment.py index bed2a25d..4082c837 100644 --- a/src/beamme/utils/environment.py +++ b/src/beamme/utils/environment.py @@ -27,7 +27,6 @@ import sys as _sys from importlib.util import find_spec as _find_spec from pathlib import Path as _Path -from typing import Tuple as _Tuple def cubitpy_is_available() -> bool: @@ -70,7 +69,7 @@ def get_env_variable(name, *, default="default_not_set"): return default -def get_git_data(repo_path: _Path) -> _Tuple[str | None, str | None]: +def get_git_data(repo_path: _Path) -> tuple[str | None, str | None]: """Return the hash and date of the current git commit of a git repo for a given repo path. diff --git a/tests/beamme/core/test_beamme_core_geometry_set.py b/tests/beamme/core/test_beamme_core_geometry_set.py index e4009738..2e956cef 100644 --- a/tests/beamme/core/test_beamme_core_geometry_set.py +++ b/tests/beamme/core/test_beamme_core_geometry_set.py @@ -21,7 +21,7 @@ # THE SOFTWARE. """This script is used to unittest the functionality of the geometry sets.""" -from typing import Callable +from collections.abc import Callable import pytest diff --git a/tests/conftest.py b/tests/conftest.py index d7d06573..30377312 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,8 +22,8 @@ """Base testing framework infrastructure.""" import os +from collections.abc import Callable from pathlib import Path -from typing import Callable import pytest from _pytest.config import Config diff --git a/tests/conftest_performance_tests.py b/tests/conftest_performance_tests.py index c819a42c..5f7c86c8 100644 --- a/tests/conftest_performance_tests.py +++ b/tests/conftest_performance_tests.py @@ -23,7 +23,7 @@ import time import warnings -from typing import Callable +from collections.abc import Callable import pytest diff --git a/tests/conftest_result_comparison.py b/tests/conftest_result_comparison.py index f4bce92a..f3264989 100644 --- a/tests/conftest_result_comparison.py +++ b/tests/conftest_result_comparison.py @@ -24,8 +24,9 @@ import json import shutil import subprocess +from collections.abc import Callable from pathlib import Path -from typing import Any, Callable +from typing import Any import numpy as np import pytest diff --git a/tests/conftest_test_object_generators.py b/tests/conftest_test_object_generators.py index 94b4a892..a48b64c4 100644 --- a/tests/conftest_test_object_generators.py +++ b/tests/conftest_test_object_generators.py @@ -21,7 +21,7 @@ # THE SOFTWARE. """This file provides generators for commonly used test objects.""" -from typing import Callable, Dict +from collections.abc import Callable import autograd.numpy as npAD import numpy as np @@ -48,7 +48,7 @@ def get_bc_data() -> Callable: A function to create a dummy boundary condition definition. """ - def _get_bc_data(*, identifier=None, num_dof: int = 3) -> Dict: + def _get_bc_data(*, identifier=None, num_dof: int = 3) -> dict: """Return a dummy definition for a boundary condition in 4C that can be used for testing purposes. diff --git a/tests/integration/test_integration_four_c_simulation.py b/tests/integration/test_integration_four_c_simulation.py index 234b7d8f..e5ab6878 100644 --- a/tests/integration/test_integration_four_c_simulation.py +++ b/tests/integration/test_integration_four_c_simulation.py @@ -23,8 +23,8 @@ import os import re +from collections.abc import Callable from pathlib import Path -from typing import Callable, Tuple import numpy as np import pytest @@ -112,7 +112,7 @@ def _run_four_c_test( n_proc: int = 2, restart: list[int | str | None] = [None, None], **kwargs, - ) -> Tuple[Path, str]: + ) -> tuple[Path, str]: """Runs a 4C simulation inside a temporary test directory. The function asserts that ``run_four_c`` returns 0. From 8a5ed0733cf3a31eb17ba59c7e2b9610a922b101 Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 13:22:45 +0200 Subject: [PATCH 06/10] fix: change remaining infrastructure to Python 3.11 --- .github/workflows/testing.yml | 6 +++--- README.md | 2 +- pyproject.toml | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index b5fe2b0a..2dcf3c67 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -32,15 +32,15 @@ jobs: - name: Install BeamMe uses: ./.github/actions/install_beamme with: - # Test coverage and editable install with Python 3.10, otherwise we use a + # Test coverage and editable install with Python 3.11, otherwise we use a # non-editable installation and turn off coverage, because the coverage # only works in editable mode. install-command: >- - ${{ matrix.python-version == '3.10' && '-e .[cubitpy,dev,fourc]' || '.[cubitpy,dev,fourc]'}} + ${{ matrix.python-version == '3.11' && '-e .[cubitpy,dev,fourc]' || '.[cubitpy,dev,fourc]'}} - name: Run the test suite and upload results on failure uses: ./.github/actions/run_tests with: # The single space in the empty string is required, otherwise GitHub # evaluates the if clause wrong. additional-pytest-flags: >- - ${{ matrix.python-version == '3.10' && ' ' || '--no-cov' }} + ${{ matrix.python-version == '3.11' && ' ' || '--no-cov' }} diff --git a/README.md b/README.md index 35ceb0a3..b9adae5c 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ interaction, , (2022) ### Python environment -BeamMe is tested with, and supports Python versions 3.10-3.14. It is recommended to use a virtual Python environment such as [Conda](https://anaconda.org/anaconda/conda)/[Miniforge](https://conda-forge.org/download/) or [venv](https://docs.python.org/3/library/venv.html). +BeamMe is tested with, and supports Python versions 3.11-3.14. It is recommended to use a virtual Python environment such as [Conda](https://anaconda.org/anaconda/conda)/[Miniforge](https://conda-forge.org/download/) or [venv](https://docs.python.org/3/library/venv.html). - A [Conda](https://anaconda.org/anaconda/conda)/[Miniforge](https://conda-forge.org/download/) environment can be created and loaded with ```bash # Create the environment (this only has to be done once) diff --git a/pyproject.toml b/pyproject.toml index 94c341ff..eb3f8ec2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "BeamMe" description = "BeamMe: A general purpose 3D beam finite element input generator" +requires-python = ">=3.11" authors = [{name = "BeamMe Authors"}] maintainers = [ {name = "Ivo Steinbrecher", email = "ivo.steinbrecher@unibw.de"}, From 29d59074bdf2ff9f6730653861a592e805cfa108 Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 13:29:32 +0200 Subject: [PATCH 07/10] feat: add all tests passed check for tests and wheel builds --- .../build_sdist_build_test_wheels_PR_and_merge.yml | 11 +++++++++++ .github/workflows/testing.yml | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml b/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml index 6b72141a..c43c4163 100644 --- a/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml +++ b/.github/workflows/build_sdist_build_test_wheels_PR_and_merge.yml @@ -41,3 +41,14 @@ jobs: with: python-version: "3.14" wheel-name: wheels-${{ matrix.os }}-py3.14 + + all-build-wheels-pass: + name: All build wheels passed + runs-on: ubuntu-latest + needs: [build-src-dist, build-test-wheels] + if: always() + steps: + - name: Check build wheels result + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 2dcf3c67..abcc3115 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -42,5 +42,15 @@ jobs: with: # The single space in the empty string is required, otherwise GitHub # evaluates the if clause wrong. - additional-pytest-flags: >- - ${{ matrix.python-version == '3.11' && ' ' || '--no-cov' }} + additional-pytest-flags: "${{ matrix.python-version == '3.11' && ' ' || '--no-cov' }}" + + all-tests-pass: + name: All tests passed + runs-on: ubuntu-latest + needs: [beamme-testing-from-source-code] + if: always() + steps: + - name: Check test matrix result + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} From a9aa6b6cefda25f2a0d0ab39d53447efc3fc6257 Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 13:42:23 +0200 Subject: [PATCH 08/10] fix: python 3.11 name alias --- src/beamme/core/geometry_set.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/beamme/core/geometry_set.py b/src/beamme/core/geometry_set.py index db4aa784..a1d73e46 100644 --- a/src/beamme/core/geometry_set.py +++ b/src/beamme/core/geometry_set.py @@ -21,6 +21,8 @@ # THE SOFTWARE. """This module implements a basic class to manage geometry in the input file.""" +from __future__ import annotations as _annotations + from collections.abc import KeysView as _KeysView from collections.abc import Sequence as _Sequence from typing import cast as _cast From 43d90faca05785633fe9eabd4fc76022b0e1b99f Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 13:46:13 +0200 Subject: [PATCH 09/10] feat: update dev deps of beamme --- .binder/Dockerfile | 2 +- .github/actions/code_check/action.yml | 2 +- .github/actions/install_beamme/action.yml | 2 +- .github/actions/wheel_test/action.yml | 2 +- .github/workflows/documentation.yml | 2 +- .github/workflows/testing.yml | 2 +- .github/workflows/testing_protected.yml | 2 +- README.md | 6 +++--- pyproject.toml | 2 ++ 9 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.binder/Dockerfile b/.binder/Dockerfile index 2c5a49c6..0cfc986f 100644 --- a/.binder/Dockerfile +++ b/.binder/Dockerfile @@ -36,4 +36,4 @@ RUN chown -R 1000 ${HOME} RUN chown -R 1000 ${HOME}/.* USER jovyan WORKDIR ${HOME} -RUN pip install -e .[fourc,dev] +RUN pip install -e .[dev] diff --git a/.github/actions/code_check/action.yml b/.github/actions/code_check/action.yml index d57c4a75..236e971c 100644 --- a/.github/actions/code_check/action.yml +++ b/.github/actions/code_check/action.yml @@ -7,7 +7,7 @@ runs: shell: bash run: | cd ${GITHUB_WORKSPACE} - pip install -e .[dev,fourc] + pip install -e .[dev] pre-commit install --install-hooks if [ "${GITHUB_REF}" = "refs/heads/main" ]; then SKIP=no-commit-to-branch pre-commit run --all-files diff --git a/.github/actions/install_beamme/action.yml b/.github/actions/install_beamme/action.yml index eaf808fd..cf9e5cfe 100644 --- a/.github/actions/install_beamme/action.yml +++ b/.github/actions/install_beamme/action.yml @@ -4,7 +4,7 @@ inputs: install-command: description: Command to install BeamMe with pip required: false - default: ".[cubitpy,dev,fourc]" + default: ".[dev]" runs: using: composite steps: diff --git a/.github/actions/wheel_test/action.yml b/.github/actions/wheel_test/action.yml index ead54bf5..2f2ce25a 100644 --- a/.github/actions/wheel_test/action.yml +++ b/.github/actions/wheel_test/action.yml @@ -27,7 +27,7 @@ runs: - name: Install wheel under test shell: bash - run: pip install "$(echo wheelhouse/*cp${PYTAG}*.whl)[cubitpy,dev,fourc]" + run: pip install "$(echo wheelhouse/*cp${PYTAG}*.whl)[dev]" - name: Run test suite and upload results on failure uses: ./.github/actions/run_tests diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index e63c24a9..fd597233 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -24,7 +24,7 @@ jobs: - name: Install dependencies run: | cd ${GITHUB_WORKSPACE} - pip install -e .[dev,fourc] + pip install -e .[dev] - name: Build API documentation run: | pdoc --math --docformat google --output-dir api-documentation src/beamme/ diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index abcc3115..f05436b1 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -36,7 +36,7 @@ jobs: # non-editable installation and turn off coverage, because the coverage # only works in editable mode. install-command: >- - ${{ matrix.python-version == '3.11' && '-e .[cubitpy,dev,fourc]' || '.[cubitpy,dev,fourc]'}} + ${{ matrix.python-version == '3.11' && '-e .[dev]' || '.[dev]'}} - name: Run the test suite and upload results on failure uses: ./.github/actions/run_tests with: diff --git a/.github/workflows/testing_protected.yml b/.github/workflows/testing_protected.yml index a75a617e..6b952fae 100644 --- a/.github/workflows/testing_protected.yml +++ b/.github/workflows/testing_protected.yml @@ -48,7 +48,7 @@ jobs: - name: Install BeamMe uses: ./.github/actions/install_beamme with: - install-command: "-e .[cubitpy,dev,fourc]" + install-command: "-e .[dev]" - name: Setup cubit id: cubit uses: ./.github/actions/cubit_setup diff --git a/README.md b/README.md index b9adae5c..d56d91d9 100644 --- a/README.md +++ b/README.md @@ -243,7 +243,7 @@ You can quickly install BeamMe into your current environment using pip: pip install beamme ``` -Optional dependencies (for development and extra features) can be installed with: `pip install "beamme[cubitpy,dev,fourc]"` +Optional dependencies (for development and extra features) can be installed with: `pip install "beamme[dev]"` > **Note:** On Zsh, you may need to quote the brackets as shown to avoid shell expansion. ### Install BeamMe from GitHub (most recent version) @@ -315,9 +315,9 @@ make -j4 ## Developing BeamMe -If you want to actively develop BeamMe or run the test suite, you must install BeamMe in _editable_ (`-e`) mode and with our optional developer dependencies (`[dev,fourc]`) like +If you want to actively develop BeamMe or run the test suite, you must install BeamMe in _editable_ (`-e`) mode and with our optional developer dependencies (`[dev]`) like ```bash -pip install -e ".[dev,fourc]" # Quotation marks are required for some shells +pip install -e ".[dev]" # Quotation marks are required for some shells ``` You can now run the BeamMe test suite to check that everything worked as expected ```bash diff --git a/pyproject.toml b/pyproject.toml index eb3f8ec2..d069ab08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,8 @@ cubitpy = [ ] fourc = ["fourcipp"] dev = [ + "beamme[cubitpy]", + "beamme[fourc]", "coverage", "genbadge[coverage]", "pdoc", From e49de9c3c81899cd361d2d22a77313090e4bc704 Mon Sep 17 00:00:00 2001 From: David Rudlstorfer Date: Wed, 8 Jul 2026 14:21:59 +0200 Subject: [PATCH 10/10] fix: copilot review suggestions --- .pre-commit-config.yaml | 2 +- .typos.toml | 2 +- .../applications/beam_stent.py | 59 ++++++++++--------- tests/integration/test_integration_four_c.py | 2 +- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dccb0e51..095456f9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: rev: v6.0.0 hooks: - id: check-added-large-files - args: ['—-maxkb=1000'] + args: ['--maxkb=1000'] name: Check for added large files - id: check-ast name: Check Python files for parse errors diff --git a/.typos.toml b/.typos.toml index c83ce080..fb5a4ba0 100644 --- a/.typos.toml +++ b/.typos.toml @@ -1,4 +1,4 @@ -# exlude the following words from the typos pre-commit hook +# exclude the following words from the typos pre-commit hook [default.extend-words] DISCRET = "DISCRET" # in 4C yaml input files diff --git a/src/beamme/mesh_creation_functions/applications/beam_stent.py b/src/beamme/mesh_creation_functions/applications/beam_stent.py index 142c5924..62505115 100644 --- a/src/beamme/mesh_creation_functions/applications/beam_stent.py +++ b/src/beamme/mesh_creation_functions/applications/beam_stent.py @@ -53,35 +53,36 @@ def create_stent_cell( """Create a cell of the stent. This cell is on the x-y plane. - Args - ---- - beam_class: Beam - Class that will be used to create the beam elements. - material: Material - Material for the beam. - width: float - Width of the total cell. - height: float - Height of the total cell. - fac_bottom: the ratio of the bottom's width to the cell's width - fac_neck: the ratio of the neck's width to the cell's width - fac_radius: the ratio of the S1's radius to the cell's width - alpha: radiant - The angle between the lines and horizontal line - n_el: int - Number of elements per beam line. - S1, S2, S3: bool - This check weather the curve S1, S2 or S3 will be created. - If the cell is on bottom of the stent flat S1 and S2 won't - be created. If the cell is on top of the flat S1 and S3 - won't be created - - ( these variables are described in a file ) - - Return - ---- - mesh: Mesh - A mesh with this structure + + Args + ---- + beam_class: Beam + Class that will be used to create the beam elements. + material: Material + Material for the beam. + width: float + Width of the total cell. + height: float + Height of the total cell. + fac_bottom: the ratio of the bottom's width to the cell's width + fac_neck: the ratio of the neck's width to the cell's width + fac_radius: the ratio of the S1's radius to the cell's width + alpha: radiant + The angle between the lines and horizontal line + n_el: int + Number of elements per beam line. + S1, S2, S3: bool + This check weather the curve S1, S2 or S3 will be created. + If the cell is on bottom of the stent flat S1 and S2 won't + be created. If the cell is on top of the flat S1 and S3 + won't be created + + ( these variables are described in a file ) + + Return + ---- + mesh: Mesh + A mesh with this structure """ mesh = _Mesh() diff --git a/tests/integration/test_integration_four_c.py b/tests/integration/test_integration_four_c.py index e6f3e8f3..8607705a 100644 --- a/tests/integration/test_integration_four_c.py +++ b/tests/integration/test_integration_four_c.py @@ -19,7 +19,7 @@ # 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. -"""This script is used to test general functionality of the 4C module with end- to-end +"""This script is used to test general functionality of the 4C module with end-to-end integration tests.""" import numpy as np