Skip to content

Commit e6b6680

Browse files
Merge pull request #310 from isteinbrecher/meshpy_to_yaml
Migrate main MeshPy functionality to YAML
2 parents 8ca3eff + bca3cea commit e6b6680

File tree

65 files changed

+2229
-2223
lines changed

Some content is hidden

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

65 files changed

+2229
-2223
lines changed

src/meshpy/core/boundary_condition.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,13 @@ def __init__(self, geometry_set, bc_type=None, **kwargs):
5050
self.geometry_set = geometry_set
5151

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

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()
57+
geometry_set_id = int(bc_dict["E"]) - 1
58+
geometry_set = geometry_sets[geometry_set_id]
59+
del bc_dict["E"]
6360

6461
if bc_key in (
6562
_mpy.bc.dirichlet,
@@ -74,22 +71,25 @@ def from_dat(cls, bc_key, line, **kwargs):
7471
BoundaryCondition as _BoundaryCondition,
7572
)
7673

77-
return _BoundaryCondition(
78-
int(split[1]) - 1, " ".join(split[2:]), bc_type=bc_key, **kwargs
74+
boundary_condition = _BoundaryCondition(
75+
geometry_set, bc_dict, bc_type=bc_key
7976
)
8077
elif bc_key is _mpy.bc.point_coupling:
8178
# Coupling condition.
8279
from meshpy.core.coupling import Coupling as _Coupling
8380

84-
return _Coupling(
85-
int(split[1]) - 1,
81+
boundary_condition = _Coupling(
82+
geometry_set,
8683
bc_key,
87-
" ".join(split[2:]),
84+
bc_dict,
8885
check_overlapping_nodes=False,
8986
check_at_init=False,
90-
**kwargs,
9187
)
92-
raise ValueError("Got unexpected boundary condition!")
88+
else:
89+
raise ValueError("Got unexpected boundary condition!")
90+
91+
boundary_condition.check()
92+
return boundary_condition
9393

9494

9595
class BoundaryConditionContainer(_ContainerBase):

src/meshpy/core/coupling.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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):

src/meshpy/core/element.py

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121
# THE SOFTWARE.
2222
"""This module implements the class that represents one element in the Mesh."""
2323

24+
from typing import List as _List
25+
2426
from meshpy.core.base_mesh_item import BaseMeshItemFull as _BaseMeshItemFull
27+
from meshpy.core.node import Node as _Node
28+
from meshpy.utils.environment import fourcipp_is_available as _fourcipp_is_available
2529

2630

2731
class Element(_BaseMeshItemFull):
@@ -43,12 +47,15 @@ def __init__(self, nodes=None, material=None, **kwargs):
4347
self.vtk_cell_data = {}
4448

4549
@classmethod
46-
def from_dat(cls, input_line):
47-
"""Check the string to decide which element to use.
50+
def from_legacy_string(cls, nodes: _List[_Node], input_line: str):
51+
"""Create an element from a legacy string."""
4852

49-
Nodes are linked with the 0 based index and will be connected to
50-
the Node objects after the whole input file is parsed.
51-
"""
53+
if _fourcipp_is_available():
54+
raise ValueError(
55+
"Port this functionality to create the element from the dict "
56+
"representing the element, not the legacy string."
57+
"TODO: pass the nodes array here, so we can directly link to the nodes"
58+
)
5259

5360
# Import solid element classes for creation of the element.
5461
from meshpy.core.element_volume import VolumeHEX8 as _VolumeHEX8
@@ -59,14 +66,16 @@ def from_dat(cls, input_line):
5966
from meshpy.four_c.element_volume import SolidRigidSphere as _SolidRigidSphere
6067

6168
# Split up input line and get pre node string.
62-
line_split = input_line[0].split()
63-
dat_pre_nodes = " ".join(line_split[1:3])
69+
line_split = input_line.split()
70+
string_pre_nodes = " ".join(line_split[1:3])
6471

6572
# Get a list of the element nodes.
66-
element_nodes = []
73+
# This is only here because we need the pre and post strings - can be
74+
# removed when moving on from the legacy format.
75+
dummy = []
6776
for i, item in enumerate(line_split[3:]):
6877
if item.isdigit():
69-
element_nodes.append(int(item) - 1)
78+
dummy.append(int(item) - 1)
7079
else:
7180
break
7281
else:
@@ -75,56 +84,51 @@ def from_dat(cls, input_line):
7584
)
7685

7786
# Get the post node string
78-
dat_post_nodes = " ".join(line_split[3 + i :])
87+
string_post_nodes = " ".join(line_split[3 + i :])
7988

8089
# Depending on the number of nodes chose which solid element to return.
81-
n_nodes = len(element_nodes)
90+
n_nodes = len(nodes)
8291
match n_nodes:
8392
case 8:
8493
return _VolumeHEX8(
85-
nodes=element_nodes,
86-
dat_pre_nodes=dat_pre_nodes,
87-
dat_post_nodes=dat_post_nodes,
94+
nodes=nodes,
95+
string_pre_nodes=string_pre_nodes,
96+
string_post_nodes=string_post_nodes,
8897
comments=input_line[1],
8998
)
9099
case 4:
91100
return _VolumeTET4(
92-
nodes=element_nodes,
93-
dat_pre_nodes=dat_pre_nodes,
94-
dat_post_nodes=dat_post_nodes,
95-
comments=input_line[1],
101+
nodes=nodes,
102+
string_pre_nodes=string_pre_nodes,
103+
string_post_nodes=string_post_nodes,
96104
)
97105
case 10:
98106
return _VolumeTET10(
99-
nodes=element_nodes,
100-
dat_pre_nodes=dat_pre_nodes,
101-
dat_post_nodes=dat_post_nodes,
102-
comments=input_line[1],
107+
nodes=nodes,
108+
string_pre_nodes=string_pre_nodes,
109+
string_post_nodes=string_post_nodes,
103110
)
104111
case 20:
105112
return _VolumeHEX20(
106-
nodes=element_nodes,
107-
dat_pre_nodes=dat_pre_nodes,
108-
dat_post_nodes=dat_post_nodes,
109-
comments=input_line[1],
113+
nodes=nodes,
114+
string_pre_nodes=string_pre_nodes,
115+
string_post_nodes=string_post_nodes,
110116
)
111117
case 27:
112118
return _VolumeHEX27(
113-
nodes=element_nodes,
114-
dat_pre_nodes=dat_pre_nodes,
115-
dat_post_nodes=dat_post_nodes,
116-
comments=input_line[1],
119+
nodes=nodes,
120+
string_pre_nodes=string_pre_nodes,
121+
string_post_nodes=string_post_nodes,
117122
)
118123
case 1:
119124
return _SolidRigidSphere(
120-
nodes=element_nodes,
121-
dat_pre_nodes=dat_pre_nodes,
122-
dat_post_nodes=dat_post_nodes,
123-
comments=input_line[1],
125+
nodes=nodes,
126+
string_pre_nodes=string_pre_nodes,
127+
string_post_nodes=string_post_nodes,
124128
)
125129
case _:
126130
raise TypeError(
127-
f"Could not find a element type for {dat_pre_nodes}, with {n_nodes} nodes"
131+
f"Could not find a element type for {string_pre_nodes}, with {n_nodes} nodes"
128132
)
129133

130134
def flip(self):
@@ -149,9 +153,9 @@ def replace_node(self, old_node, new_node):
149153
"The node that should be replaced is not in the current element"
150154
)
151155

152-
def add_element_specific_section(self, sections):
153-
"""Add element specific section (e.g. STRUCTURE KNOTVECTORS for NURBS
154-
elements) to the sections dictionary."""
156+
def dump_element_specific_section(self, yaml_dict):
157+
"""Add information of this element to specific section (e.g. STRUCTURE
158+
KNOTVECTORS for NURBS elements)."""
155159

156160
def get_vtk(self, vtk_writer_beam, vtk_writer_solid, **kwargs):
157161
"""Add representation of this element to the vtk_writers for solid and

src/meshpy/core/element_beam.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,18 +155,18 @@ def check_node(node, pos, rot, arc_length, name):
155155
return created_nodes
156156

157157
@classmethod
158-
def get_coupling_string(cls, coupling_dof_type):
159-
"""Return the string to couple this beam to another beam."""
158+
def get_coupling_dict(cls, coupling_dof_type):
159+
"""Return the dict to couple this beam to another beam."""
160160

161161
match coupling_dof_type:
162162
case _mpy.coupling_dof.joint:
163-
if cls.coupling_joint_string is None:
163+
if cls.coupling_joint_dict is None:
164164
raise ValueError(f"Joint coupling is not implemented for {cls}")
165-
return cls.coupling_joint_string
165+
return cls.coupling_joint_dict
166166
case _mpy.coupling_dof.fix:
167-
if cls.coupling_fix_string is None:
167+
if cls.coupling_fix_dict is None:
168168
raise ValueError("Fix coupling is not implemented for {cls}")
169-
return cls.coupling_fix_string
169+
return cls.coupling_fix_dict
170170
case _:
171171
raise ValueError(
172172
f'Coupling_dof_type "{coupling_dof_type}" is not implemented!'

src/meshpy/core/element_volume.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,21 @@ class VolumeElement(_Element):
3636
vtk_cell_type = None
3737
vtk_topology: list = []
3838

39-
def __init__(self, nodes=None, dat_pre_nodes="", dat_post_nodes="", **kwargs):
39+
def __init__(self, nodes=None, string_pre_nodes="", string_post_nodes="", **kwargs):
4040
super().__init__(nodes=nodes, material=None, **kwargs)
41-
self.dat_pre_nodes = dat_pre_nodes
42-
self.dat_post_nodes = dat_post_nodes
41+
self.string_pre_nodes = string_pre_nodes
42+
self.string_post_nodes = string_post_nodes
4343

44-
def _get_dat(self):
45-
"""Return the dat line for this element."""
44+
def dump_to_list(self):
45+
"""Return a list with the items representing this object (usually a
46+
single item)."""
4647

4748
# String with the node ids.
48-
nodes_string = ""
49-
for node in self.nodes:
50-
nodes_string += f"{node.i_global} "
49+
nodes_string = " ".join(str(node.i_global) for node in self.nodes)
5150

52-
# Return the dat line.
53-
return (
54-
f"{self.i_global} {self.dat_pre_nodes} {nodes_string} {self.dat_post_nodes}"
55-
)
51+
return [
52+
f"{self.i_global} {self.string_pre_nodes} {nodes_string} {self.string_post_nodes}"
53+
]
5654

5755
def get_vtk(self, vtk_writer_beam, vtk_writer_solid, **kwargs):
5856
"""Add the representation of this element to the VTK writer as a

src/meshpy/core/geometry_set.py

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from meshpy.core.container import ContainerBase as _ContainerBase
3131
from meshpy.core.element_beam import Beam as _Beam
3232
from meshpy.core.node import Node as _Node
33+
from meshpy.utils.environment import fourcipp_is_available as _fourcipp_is_available
3334

3435

3536
class GeometrySetBase(_BaseMeshItemFull):
@@ -120,8 +121,13 @@ def get_all_nodes(self):
120121
'The "get_all_nodes" method has to be overwritten in the derived class'
121122
)
122123

123-
def _get_dat(self):
124-
"""Get the lines for the input file."""
124+
def dump_to_list(self):
125+
"""Return a list with the legacy strings of this geometry set."""
126+
127+
if _fourcipp_is_available():
128+
raise ValueError(
129+
"Port this functionality to dump the geometry set to a suitable data format"
130+
)
125131

126132
# Sort the nodes based on the node GID.
127133
nodes = self.get_all_nodes()
@@ -264,26 +270,6 @@ def __init__(self, geometry_type, nodes=None, **kwargs):
264270
if nodes is not None:
265271
self.add(nodes)
266272

267-
@classmethod
268-
def from_dat(cls, geometry_key, lines, comments=None):
269-
"""Get a geometry set from an input line in a dat file.
270-
271-
The geometry set is passed as integer (0 based index) and will
272-
be connected after the whole input file is parsed.
273-
"""
274-
nodes = []
275-
for line in lines:
276-
nodes.append(int(line.split()[1]) - 1)
277-
return cls(geometry_key, nodes, comments=comments)
278-
279-
def replace_indices_with_nodes(self, nodes):
280-
"""After the set is imported from a dat file, replace the node indices
281-
with the corresponding nodes objects."""
282-
node_dict = {}
283-
for node_id in self.nodes.keys():
284-
node_dict[nodes[node_id]] = None
285-
self.nodes = node_dict
286-
287273
def add(self, value):
288274
"""Add nodes to this object.
289275

0 commit comments

Comments
 (0)