Skip to content

Commit 4cf5402

Browse files
Merge pull request #320 from imcs-compsim/migrate_dat_to_yaml
Migrate MeshPy from dat to yaml
2 parents 737ef87 + fc734cc commit 4cf5402

File tree

254 files changed

+31976
-28214
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

254 files changed

+31976
-28214
lines changed

.github/workflows/testing.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
with:
9898
source-command: "source python-workflow-venv/bin/activate"
9999
install-command: "-e .[dev]"
100-
additional-pytest-flags: "--4C --ArborX --cov-fail-under=93"
100+
additional-pytest-flags: "--4C --ArborX --cov-fail-under=92"
101101
- name: Upload test results on failure
102102
if: failure()
103103
uses: actions/upload-artifact@v4

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dynamic = ["version"]
2929

3030
[project.optional-dependencies]
3131
cubitpy = ["cubitpy@git+https://github.com/imcs-compsim/cubitpy.git@main"]
32+
fourc = ["fourcipp@git+https://github.com/4c-multiphysics/fourcipp.git@main"]
3233
dev = [
3334
"coverage-badge",
3435
"coverage",
@@ -50,7 +51,7 @@ Issues = "https://github.com/imcs-compsim/meshpy/issues/"
5051

5152
[tool.pytest.ini_options]
5253
testpaths = ["tests"]
53-
addopts = "-p pytest_cov --cov-report=term --cov-report=html --cov-fail-under=90 --cov=src/meshpy/"
54+
addopts = "-p pytest_cov --cov-report=term --cov-report=html --cov-fail-under=89 --cov=src/meshpy/"
5455
markers = [
5556
"fourc: tests in combination with 4C",
5657
"arborx: tests in combination with ArborX",

src/meshpy/abaqus/beam.py

-17
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import numpy as _np
2626

2727
from meshpy.core.element_beam import Beam as _Beam
28-
from meshpy.core.material import MaterialBeam as _MaterialBeam
2928

3029

3130
def generate_abaqus_beam(beam_type: str):
@@ -69,19 +68,3 @@ def generate_abaqus_beam(beam_type: str):
6968
"n_dim": n_dim,
7069
},
7170
)
72-
73-
74-
class AbaqusBeamMaterial(_MaterialBeam):
75-
"""A class representing an Abaqus beam material."""
76-
77-
def __init__(self, name: str):
78-
"""Initialize the material. For now it is only supported to state the
79-
name of the resulting element set here. The material and cross-section
80-
lines in the input file have to be defined manually.
81-
82-
Args
83-
----
84-
name: str
85-
Name of the material, this will be the name of the resulting element set
86-
"""
87-
super().__init__(data=name)

src/meshpy/abaqus/input_file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def get_material_lines(self):
308308
# Create the element sets for the different materials.
309309
input_file_lines = []
310310
for material, elements in materials.items():
311-
material_name = material.get_dat_lines()[0]
311+
material_name = material.dump_to_list()[0]
312312
input_file_lines.extend(get_set_lines("Elset", elements, material_name))
313313
return input_file_lines
314314

src/meshpy/abaqus/material.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2018-2025 MeshPy Authors
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
"""This file provides functions to create Abaqus beam element classes to be
23+
used with MeshPy."""
24+
25+
from meshpy.core.material import MaterialBeam as _MaterialBeam
26+
27+
28+
class AbaqusBeamMaterial(_MaterialBeam):
29+
"""A class representing an Abaqus beam material."""
30+
31+
def __init__(self, name: str):
32+
"""Initialize the material. For now it is only supported to state the
33+
name of the resulting element set here. The material and cross-section
34+
lines in the input file have to be defined manually.
35+
36+
Args
37+
----
38+
name: str
39+
Name of the material, this will be the name of the resulting element set
40+
"""
41+
super().__init__(data=name)
42+
43+
def dump_to_list(self):
44+
"""Return a list with the (single) item representing this material."""
45+
return [self.data]

src/meshpy/core/base_mesh_item.py

+2-26
Original file line numberDiff line numberDiff line change
@@ -47,36 +47,12 @@ def __init__(self, data=None, comments=None):
4747
else:
4848
self.comments = comments
4949

50-
def get_dat_lines(self):
51-
"""Return the content of this object as a list.
52-
53-
If comments exist, also add those.
54-
"""
55-
56-
# Get data of object.
57-
data = self._get_dat()
58-
if isinstance(data, str):
59-
data = [data]
60-
61-
# Get comments if given.
62-
return_list = []
63-
if not len(self.comments) == 0:
64-
return_list.extend(self.comments)
65-
66-
# Return final list.
67-
return_list.extend(data)
68-
return return_list
69-
70-
def _get_dat(self):
71-
"""Return the content of this object as either a list or a str."""
72-
return self.data
73-
7450

7551
class BaseMeshItemFull(BaseMeshItem):
7652
"""Base class for all objects that are related to a mesh and are fully
7753
created in MeshPy."""
7854

7955

8056
class BaseMeshItemString(BaseMeshItem):
81-
"""Base class for all objects that are imported from a dat file as a plain
82-
string."""
57+
"""Base class for all objects that are imported from an input file as a
58+
plain string."""

src/meshpy/core/boundary_condition.py

+17-19
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,8 @@ def __init__(self, geometry_set, bc_type=None, **kwargs):
3737
3838
Args
3939
----
40-
geometry_set: GeometrySet, int
41-
Geometry that this boundary condition acts on. An integer can be
42-
given, in the case a dat file is imported. This integer is only
43-
temporary and will be replaced with the GeometrySet object.
40+
geometry_set: GeometrySet
41+
Geometry that this boundary condition acts on.
4442
bc_type: mpy.bc
4543
Type of the boundary condition.
4644
"""
@@ -50,16 +48,13 @@ def __init__(self, geometry_set, bc_type=None, **kwargs):
5048
self.geometry_set = geometry_set
5149

5250
@classmethod
53-
def from_dat(cls, bc_key, line, **kwargs):
51+
def from_dict(cls, geometry_sets, bc_key, bc_dict):
5452
"""This function acts as a factory and creates the correct boundary
55-
condition object from a line in the dat file.
53+
condition object from a dictionary parsed from an input file."""
5654

57-
The geometry set is passed as integer (0 based index) and will
58-
be connected after the whole input file is parsed.
59-
"""
60-
61-
# Split up the input line.
62-
split = line.split()
55+
geometry_set_id = int(bc_dict["E"]) - 1
56+
geometry_set = geometry_sets[geometry_set_id]
57+
del bc_dict["E"]
6358

6459
if bc_key in (
6560
_mpy.bc.dirichlet,
@@ -74,22 +69,25 @@ def from_dat(cls, bc_key, line, **kwargs):
7469
BoundaryCondition as _BoundaryCondition,
7570
)
7671

77-
return _BoundaryCondition(
78-
int(split[1]) - 1, " ".join(split[2:]), bc_type=bc_key, **kwargs
72+
boundary_condition = _BoundaryCondition(
73+
geometry_set, bc_dict, bc_type=bc_key
7974
)
8075
elif bc_key is _mpy.bc.point_coupling:
8176
# Coupling condition.
8277
from meshpy.core.coupling import Coupling as _Coupling
8378

84-
return _Coupling(
85-
int(split[1]) - 1,
79+
boundary_condition = _Coupling(
80+
geometry_set,
8681
bc_key,
87-
" ".join(split[2:]),
82+
bc_dict,
8883
check_overlapping_nodes=False,
8984
check_at_init=False,
90-
**kwargs,
9185
)
92-
raise ValueError("Got unexpected boundary condition!")
86+
else:
87+
raise ValueError("Got unexpected boundary condition!")
88+
89+
boundary_condition.check()
90+
return boundary_condition
9391

9492

9593
class BoundaryConditionContainer(_ContainerBase):

src/meshpy/core/conf.py

+7-13
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def set_default_values(self):
151151
self.git_date = None
152152

153153
# Precision for floats in output.
154-
self.dat_precision = "{:.12g}"
154+
self.output_precision = "{:.12g}"
155155

156156
# Set the epsilons for comparison of different types of values.
157157
self.eps_quaternion = 1e-10
@@ -166,10 +166,7 @@ def set_default_values(self):
166166
self.geometric_search_max_nodes_brute_force = 1000
167167
self.geometric_search_binning_n_bin = 10
168168

169-
# Values for the formatting of the input file.
170-
self.dat_len_section = 80
171-
172-
# Import meshes as pure dat or import the geometry.
169+
# Import meshes as pure dict or import the geometry.
173170
self.import_mesh_full = False
174171

175172
# Number of digits for node set output (this will be set in the
@@ -179,19 +176,16 @@ def set_default_values(self):
179176
self.vtk_nan_int = -1
180177
self.vtk_nan_float = 0.0
181178

182-
# Check for overlapping elements when creating a dat file.
179+
# Check for overlapping elements when creating an input file.
183180
self.check_overlapping_elements = True
184181

185182
# Lines to be added to each created input file
186183
self.input_file_meshpy_header = [
187-
"-" * 77,
184+
"-" * 40,
188185
"This input file was created with MeshPy.",
189-
"Copyright (c) 2018-2025",
190-
" Ivo Steinbrecher",
191-
" Institute for Mathematics and Computer-Based Simulation",
192-
" Universitaet der Bundeswehr Muenchen",
193-
" https://www.unibw.de/imcs-en",
194-
"-" * 77,
186+
"Copyright (c) 2018-2025 MeshPy Authors",
187+
"https://imcs-compsim.github.io/meshpy/",
188+
"-" * 40,
195189
]
196190

197191

src/meshpy/core/coupling.py

+9-12
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ def __init__(
6060
physical position.
6161
check_at_init: bool
6262
If the previous check should be performed at initialization. This is required
63-
when importing a coupling from a dat file as the nodes themselves are not build
63+
when importing a coupling from an input file as the nodes themselves are not build
6464
up when the coupling is read.
6565
"""
6666

6767
if isinstance(geometry, int):
68-
# This is the case if the boundary condition is read from an existing dat file
68+
# This is the case if the boundary condition is read from an existing input file
6969
pass
7070
elif isinstance(geometry, _GeometrySetBase):
7171
pass
@@ -108,15 +108,12 @@ def check(self):
108108
"The nodes given to Coupling do not have the same position."
109109
)
110110

111-
def _get_dat(self):
112-
"""Return the dat line for this object.
111+
def dump_to_list(self):
112+
"""Return a list with a single item representing this coupling
113+
condition."""
113114

114-
If no explicit string was given, it depends on the coupling type
115-
as well as the beam type.
116-
"""
117-
118-
if isinstance(self.coupling_dof_type, str):
119-
string = self.coupling_dof_type
115+
if isinstance(self.coupling_dof_type, dict):
116+
bc_dict = self.coupling_dof_type
120117
else:
121118
# In this case we have to check which beams are connected to the node.
122119
# TODO: Coupling also makes sense for different beam types, this can
@@ -150,9 +147,9 @@ def _get_dat(self):
150147
"Coupling beams of different types is not yet possible!"
151148
)
152149

153-
string = beam_four_c_type.get_coupling_string(self.coupling_dof_type)
150+
bc_dict = beam_four_c_type.get_coupling_dict(self.coupling_dof_type)
154151

155-
return f"E {self.geometry_set.i_global} {string}"
152+
return [{"E": self.geometry_set.i_global, **bc_dict}]
156153

157154

158155
def coupling_factory(geometry, coupling_type, coupling_dof_type, **kwargs):

0 commit comments

Comments
 (0)