kib-lap 0.5__cp313-cp313-win_amd64.whl → 0.7.7__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KIB_LAP/Betonbau/TEST_Rectangular.py +21 -0
- KIB_LAP/Betonbau/beam_rectangular.py +4 -0
- KIB_LAP/FACHWERKEBEN/Elements.py +209 -0
- KIB_LAP/FACHWERKEBEN/InputData.py +118 -0
- KIB_LAP/FACHWERKEBEN/Iteration.py +967 -0
- KIB_LAP/FACHWERKEBEN/Materials.py +30 -0
- KIB_LAP/FACHWERKEBEN/Plotting.py +681 -0
- KIB_LAP/FACHWERKEBEN/__init__.py +4 -0
- KIB_LAP/FACHWERKEBEN/main.py +27 -0
- KIB_LAP/Plattentragwerke/PlateBendingKirchhoff.py +36 -29
- KIB_LAP/STABRAUM/InputData.py +13 -2
- KIB_LAP/STABRAUM/Output_Data.py +61 -0
- KIB_LAP/STABRAUM/Plotting.py +1453 -0
- KIB_LAP/STABRAUM/Programm.py +518 -1026
- KIB_LAP/STABRAUM/Steifigkeitsmatrix.py +338 -117
- KIB_LAP/STABRAUM/main.py +58 -0
- KIB_LAP/STABRAUM/results.py +37 -0
- KIB_LAP/Scheibe/Assemble_Stiffness.py +246 -0
- KIB_LAP/Scheibe/Element_Stiffness.py +362 -0
- KIB_LAP/Scheibe/Meshing.py +365 -0
- KIB_LAP/Scheibe/Output.py +34 -0
- KIB_LAP/Scheibe/Plotting.py +722 -0
- KIB_LAP/Scheibe/Shell_Calculation.py +523 -0
- KIB_LAP/Scheibe/Testing_Mesh.py +25 -0
- KIB_LAP/Scheibe/__init__.py +14 -0
- KIB_LAP/Scheibe/main.py +33 -0
- KIB_LAP/StabEbenRitz/Biegedrillknicken.py +757 -0
- KIB_LAP/StabEbenRitz/Biegedrillknicken_Trigeometry.py +328 -0
- KIB_LAP/StabEbenRitz/Querschnittswerte.py +527 -0
- KIB_LAP/StabEbenRitz/Stabberechnung_Klasse.py +868 -0
- KIB_LAP/plate_bending_cpp.cp313-win_amd64.pyd +0 -0
- KIB_LAP/plate_buckling_cpp.cp313-win_amd64.pyd +0 -0
- {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/METADATA +1 -1
- {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/RECORD +37 -19
- Examples/Cross_Section_Thin.py +0 -61
- KIB_LAP/Betonbau/Bemessung_Zust_II.py +0 -648
- KIB_LAP/Betonbau/Iterative_Design.py +0 -723
- KIB_LAP/Plattentragwerke/NumInte.cpp +0 -23
- KIB_LAP/Plattentragwerke/NumericalIntegration.cpp +0 -23
- KIB_LAP/Plattentragwerke/plate_bending_cpp.cp313-win_amd64.pyd +0 -0
- KIB_LAP/main.py +0 -2
- {Examples → KIB_LAP/StabEbenRitz}/__init__.py +0 -0
- {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/WHEEL +0 -0
- {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import matplotlib.patches as patches
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MeshingClass:
|
|
8
|
+
def __init__(self, d1, d2, num_x, num_y, elem_type):
|
|
9
|
+
self._d1 = d1
|
|
10
|
+
self._d2 = d2
|
|
11
|
+
self._num_x = num_x
|
|
12
|
+
self._num_y = num_y
|
|
13
|
+
self._elem_type = elem_type
|
|
14
|
+
self.PD = 2 # Problem-Dimension
|
|
15
|
+
self.NoN = 0 # Number of Nodes NoN
|
|
16
|
+
self.NoE = 0 # Number of Elements NoE
|
|
17
|
+
self.NPE = 4 if elem_type == "rect" else 3 # Nodes per elements
|
|
18
|
+
self.q = np.zeros((4, 2))
|
|
19
|
+
self.NL = np.zeros((1, self.PD))
|
|
20
|
+
self.EL = np.zeros((1, self.NPE))
|
|
21
|
+
self.a = 0
|
|
22
|
+
self.b = 0
|
|
23
|
+
self.element_edges = {} # Dictionary to store edges by element
|
|
24
|
+
|
|
25
|
+
def get_NL(self):
|
|
26
|
+
return self.NL
|
|
27
|
+
|
|
28
|
+
def get_EL(self):
|
|
29
|
+
return self.EL
|
|
30
|
+
|
|
31
|
+
def get_NPE(self):
|
|
32
|
+
return self.NPE
|
|
33
|
+
|
|
34
|
+
def general_mesh_input(self):
|
|
35
|
+
self.q = np.array([[0, 0], [self._d1, 0], [0, self._d2], [self._d1, self._d2]])
|
|
36
|
+
self.NoN = (self._num_x + 1) * (self._num_y + 1)
|
|
37
|
+
self.NoE = self._num_x * self._num_y
|
|
38
|
+
self.NL = np.zeros((self.NoN, self.PD))
|
|
39
|
+
self.EL = np.zeros((self.NoE, self.NPE), dtype=int)
|
|
40
|
+
self.a = (self.q[1, 0] - self.q[0, 0]) / self._num_x
|
|
41
|
+
self.b = (self.q[2, 1] - self.q[0, 1]) / self._num_y
|
|
42
|
+
|
|
43
|
+
def generating_rectangular_mesh(self):
|
|
44
|
+
self.general_mesh_input()
|
|
45
|
+
n = 0
|
|
46
|
+
for i in range(1, self._num_y + 2):
|
|
47
|
+
for j in range(1, self._num_x + 2):
|
|
48
|
+
self.NL[n, 0] = self.q[0, 0] + (j - 1) * self.a
|
|
49
|
+
self.NL[n, 1] = self.q[0, 1] + (i - 1) * self.b
|
|
50
|
+
n += 1
|
|
51
|
+
|
|
52
|
+
for i in range(1, self._num_y + 1):
|
|
53
|
+
for j in range(1, self._num_x + 1):
|
|
54
|
+
if j == 1:
|
|
55
|
+
self.EL[(i - 1) * self._num_x + j - 1, 0] = (i - 1) * (
|
|
56
|
+
self._num_x + 1
|
|
57
|
+
) + j
|
|
58
|
+
self.EL[(i - 1) * self._num_x + j - 1, 1] = (
|
|
59
|
+
self.EL[(i - 1) * self._num_x + j - 1, 0] + 1
|
|
60
|
+
)
|
|
61
|
+
self.EL[(i - 1) * self._num_x + j - 1, 3] = (
|
|
62
|
+
self.EL[(i - 1) * self._num_x + j - 1, 0] + self._num_x + 1
|
|
63
|
+
)
|
|
64
|
+
self.EL[(i - 1) * self._num_x + j - 1, 2] = (
|
|
65
|
+
self.EL[(i - 1) * self._num_x + j - 1, 3] + 1
|
|
66
|
+
)
|
|
67
|
+
else:
|
|
68
|
+
self.EL[(i - 1) * self._num_x + j - 1, 0] = self.EL[
|
|
69
|
+
(i - 1) * self._num_x + j - 2, 1
|
|
70
|
+
]
|
|
71
|
+
self.EL[(i - 1) * self._num_x + j - 1, 3] = self.EL[
|
|
72
|
+
(i - 1) * self._num_x + j - 2, 2
|
|
73
|
+
]
|
|
74
|
+
self.EL[(i - 1) * self._num_x + j - 1, 1] = (
|
|
75
|
+
self.EL[(i - 1) * self._num_x + j - 1, 0] + 1
|
|
76
|
+
)
|
|
77
|
+
self.EL[(i - 1) * self._num_x + j - 1, 2] = (
|
|
78
|
+
self.EL[(i - 1) * self._num_x + j - 1, 3] + 1
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
self.generate_edges()
|
|
82
|
+
|
|
83
|
+
def generating_quadrilateral_mesh(self, q):
|
|
84
|
+
"""
|
|
85
|
+
Structured Q4 mesh on a general convex quadrilateral using bilinear mapping.
|
|
86
|
+
|
|
87
|
+
q: array-like shape (4,2) with corner points in boundary order.
|
|
88
|
+
Recommended order: [q1,q2,q3,q4] counter-clockwise (CCW).
|
|
89
|
+
Example: q1 bottom-left, q2 bottom-right, q3 top-right, q4 top-left.
|
|
90
|
+
"""
|
|
91
|
+
q = np.asarray(q, dtype=float)
|
|
92
|
+
if q.shape != (4, 2):
|
|
93
|
+
raise ValueError("q must have shape (4,2)")
|
|
94
|
+
|
|
95
|
+
# Store corners
|
|
96
|
+
self.q = q.copy()
|
|
97
|
+
|
|
98
|
+
# Setup sizes
|
|
99
|
+
self.NoN = (self._num_x + 1) * (self._num_y + 1)
|
|
100
|
+
self.NoE = self._num_x * self._num_y
|
|
101
|
+
self.NL = np.zeros((self.NoN, self.PD))
|
|
102
|
+
self.EL = np.zeros((self.NoE, self.NPE), dtype=int)
|
|
103
|
+
|
|
104
|
+
# For plotting margins: use average edge lengths / divisions
|
|
105
|
+
Lx = 0.5 * (np.linalg.norm(q[1] - q[0]) + np.linalg.norm(q[2] - q[3]))
|
|
106
|
+
Ly = 0.5 * (np.linalg.norm(q[3] - q[0]) + np.linalg.norm(q[2] - q[1]))
|
|
107
|
+
self.a = Lx / self._num_x
|
|
108
|
+
self.b = Ly / self._num_y
|
|
109
|
+
|
|
110
|
+
# Bilinear map from (s,t) in [0,1]^2
|
|
111
|
+
q1, q2, q3, q4 = q[0], q[1], q[2], q[3]
|
|
112
|
+
|
|
113
|
+
def map_st(s, t):
|
|
114
|
+
return (1 - s) * (1 - t) * q1 + s * (1 - t) * q2 + s * t * q3 + (1 - s) * t * q4
|
|
115
|
+
|
|
116
|
+
# Create nodes (same numbering scheme as your rectangular mesh)
|
|
117
|
+
n = 0
|
|
118
|
+
for i in range(0, self._num_y + 1):
|
|
119
|
+
t = i / self._num_y if self._num_y > 0 else 0.0
|
|
120
|
+
for j in range(0, self._num_x + 1):
|
|
121
|
+
s = j / self._num_x if self._num_x > 0 else 0.0
|
|
122
|
+
xy = map_st(s, t)
|
|
123
|
+
self.NL[n, 0] = xy[0]
|
|
124
|
+
self.NL[n, 1] = xy[1]
|
|
125
|
+
n += 1
|
|
126
|
+
|
|
127
|
+
# Create elements connectivity (identical pattern as rectangular case)
|
|
128
|
+
# Node numbering: row-major
|
|
129
|
+
for i in range(1, self._num_y + 1):
|
|
130
|
+
for j in range(1, self._num_x + 1):
|
|
131
|
+
# bottom-left node id in this cell
|
|
132
|
+
n1 = (i - 1) * (self._num_x + 1) + j
|
|
133
|
+
n2 = n1 + 1
|
|
134
|
+
n4 = n1 + (self._num_x + 1)
|
|
135
|
+
n3 = n4 + 1
|
|
136
|
+
|
|
137
|
+
e = (i - 1) * self._num_x + (j - 1)
|
|
138
|
+
self.EL[e, :] = [n1, n2, n3, n4]
|
|
139
|
+
|
|
140
|
+
self.generate_edges()
|
|
141
|
+
|
|
142
|
+
def read_q_from_csv(self, filepath="Meshing_Params_q.csv"):
|
|
143
|
+
"""
|
|
144
|
+
Liest 4 Eckpunkte q aus CSV mit Spalten 'x[m]' und 'y[m]'.
|
|
145
|
+
Rückgabe: np.array shape (4,2)
|
|
146
|
+
"""
|
|
147
|
+
df = pd.read_csv(filepath)
|
|
148
|
+
|
|
149
|
+
# toleranter Umgang mit Spaltennamen (falls mal ohne [m])
|
|
150
|
+
cols = [c.strip() for c in df.columns]
|
|
151
|
+
df.columns = cols
|
|
152
|
+
|
|
153
|
+
xcol = "x[m]" if "x[m]" in df.columns else ("x" if "x" in df.columns else None)
|
|
154
|
+
ycol = "y[m]" if "y[m]" in df.columns else ("y" if "y" in df.columns else None)
|
|
155
|
+
if xcol is None or ycol is None:
|
|
156
|
+
raise ValueError(f"CSV muss Spalten 'x[m]'/'y[m]' oder 'x'/'y' enthalten. Gefunden: {list(df.columns)}")
|
|
157
|
+
|
|
158
|
+
if len(df) != 4:
|
|
159
|
+
raise ValueError(f"CSV muss genau 4 Punkte enthalten, gefunden: {len(df)}")
|
|
160
|
+
|
|
161
|
+
q = df[[xcol, ycol]].to_numpy(dtype=float)
|
|
162
|
+
return q
|
|
163
|
+
|
|
164
|
+
def generating_quadrilateral_mesh_from_csv(self, filepath="Meshing_Params_q.csv"):
|
|
165
|
+
"""
|
|
166
|
+
Convenience: liest q aus CSV und erzeugt direkt das Mesh.
|
|
167
|
+
"""
|
|
168
|
+
q = self.read_q_from_csv(filepath)
|
|
169
|
+
self.generating_quadrilateral_mesh(q)
|
|
170
|
+
|
|
171
|
+
def generate_edges(self):
|
|
172
|
+
for el_index, el in enumerate(self.EL):
|
|
173
|
+
edges = {
|
|
174
|
+
"left": (el[0], el[3]),
|
|
175
|
+
"bottom": (el[0], el[1]),
|
|
176
|
+
"right": (el[1], el[2]),
|
|
177
|
+
"top": (el[2], el[3]),
|
|
178
|
+
}
|
|
179
|
+
for orientation in edges:
|
|
180
|
+
edges[orientation] = tuple(sorted(edges[orientation]))
|
|
181
|
+
self.element_edges[el_index] = edges
|
|
182
|
+
|
|
183
|
+
def _tol(self):
|
|
184
|
+
# typische Elementgröße als Toleranzmaß
|
|
185
|
+
a = float(getattr(self, "a", 0.0))
|
|
186
|
+
b = float(getattr(self, "b", 0.0))
|
|
187
|
+
h = max(a, b, 1e-12)
|
|
188
|
+
return 1e-6 * h # z.B. 1e-6 der Elementgröße
|
|
189
|
+
|
|
190
|
+
def get_left_border_nodes(self, tol=None):
|
|
191
|
+
NL = np.asarray(self.NL, dtype=float)
|
|
192
|
+
if tol is None:
|
|
193
|
+
tol = self._tol()
|
|
194
|
+
x_min = float(NL[:, 0].min())
|
|
195
|
+
return [i + 1 for i, x in enumerate(NL[:, 0]) if abs(x - x_min) <= tol]
|
|
196
|
+
|
|
197
|
+
def get_right_border_nodes(self, tol=None):
|
|
198
|
+
NL = np.asarray(self.NL, dtype=float)
|
|
199
|
+
if tol is None:
|
|
200
|
+
tol = self._tol()
|
|
201
|
+
x_max = float(NL[:, 0].max())
|
|
202
|
+
return [i + 1 for i, x in enumerate(NL[:, 0]) if abs(x - x_max) <= tol]
|
|
203
|
+
|
|
204
|
+
def get_bottom_border_nodes(self, tol=None):
|
|
205
|
+
NL = np.asarray(self.NL, dtype=float)
|
|
206
|
+
if tol is None:
|
|
207
|
+
tol = self._tol()
|
|
208
|
+
y_min = float(NL[:, 1].min())
|
|
209
|
+
return [i + 1 for i, y in enumerate(NL[:, 1]) if abs(y - y_min) <= tol]
|
|
210
|
+
|
|
211
|
+
def get_top_border_nodes(self, tol=None):
|
|
212
|
+
NL = np.asarray(self.NL, dtype=float)
|
|
213
|
+
if tol is None:
|
|
214
|
+
tol = self._tol()
|
|
215
|
+
y_max = float(NL[:, 1].max())
|
|
216
|
+
return [i + 1 for i, y in enumerate(NL[:, 1]) if abs(y - y_max) <= tol]
|
|
217
|
+
|
|
218
|
+
def get_element_edges(self):
|
|
219
|
+
return self.element_edges
|
|
220
|
+
|
|
221
|
+
def get_coordinate_x(self, node_nr):
|
|
222
|
+
for i in range(0, len(self.EL), 1):
|
|
223
|
+
for j in range(0, len(self.EL[0]), 1):
|
|
224
|
+
index = int(self.EL[i][j])
|
|
225
|
+
|
|
226
|
+
if index == node_nr:
|
|
227
|
+
return self.NL[index - 1][0]
|
|
228
|
+
|
|
229
|
+
def get_coordinate_z(self, node_nr):
|
|
230
|
+
for i in range(0, len(self.EL), 1):
|
|
231
|
+
for j in range(0, len(self.EL[0]), 1):
|
|
232
|
+
index = int(self.EL[i][j])
|
|
233
|
+
|
|
234
|
+
if index == node_nr:
|
|
235
|
+
return self.NL[index - 1][1]
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# ============================================================
|
|
239
|
+
# MERGE / STITCH SUPPORT
|
|
240
|
+
# ============================================================
|
|
241
|
+
|
|
242
|
+
def merge_with_mesh(self, other, tol=None):
|
|
243
|
+
"""
|
|
244
|
+
Vereint self-Mesh und other-Mesh, indem Knoten mit gleichen Koordinaten
|
|
245
|
+
(bis tol) zusammengeführt werden. EL bleibt 1-based.
|
|
246
|
+
"""
|
|
247
|
+
if tol is None:
|
|
248
|
+
tol = max(self._tol(), other._tol())
|
|
249
|
+
|
|
250
|
+
NL_A = np.asarray(self.NL, float)
|
|
251
|
+
EL_A = np.asarray(self.EL, int)
|
|
252
|
+
NL_B = np.asarray(other.NL, float)
|
|
253
|
+
EL_B = np.asarray(other.EL, int)
|
|
254
|
+
|
|
255
|
+
# spatial hash on A
|
|
256
|
+
def key(pt):
|
|
257
|
+
return (round(pt[0] / tol), round(pt[1] / tol))
|
|
258
|
+
|
|
259
|
+
hashA = {}
|
|
260
|
+
for i, pt in enumerate(NL_A, start=1): # 1-based ids
|
|
261
|
+
hashA[key(pt)] = i
|
|
262
|
+
|
|
263
|
+
NL = NL_A.tolist()
|
|
264
|
+
mapB = {} # old B node id -> merged node id
|
|
265
|
+
|
|
266
|
+
for j, pt in enumerate(NL_B, start=1):
|
|
267
|
+
k = key(pt)
|
|
268
|
+
if k in hashA:
|
|
269
|
+
mapB[j] = hashA[k]
|
|
270
|
+
else:
|
|
271
|
+
NL.append([pt[0], pt[1]])
|
|
272
|
+
mapB[j] = len(NL)
|
|
273
|
+
|
|
274
|
+
# remap B elements
|
|
275
|
+
EL_B_new = np.zeros_like(EL_B)
|
|
276
|
+
for e in range(EL_B.shape[0]):
|
|
277
|
+
for a in range(EL_B.shape[1]):
|
|
278
|
+
EL_B_new[e, a] = mapB[int(EL_B[e, a])]
|
|
279
|
+
|
|
280
|
+
# combine
|
|
281
|
+
self.NL = np.asarray(NL, float)
|
|
282
|
+
self.EL = np.vstack([EL_A, EL_B_new]).astype(int)
|
|
283
|
+
|
|
284
|
+
self.NoN = len(self.NL)
|
|
285
|
+
self.NoE = len(self.EL)
|
|
286
|
+
|
|
287
|
+
# edges aktualisieren
|
|
288
|
+
self.element_edges = {}
|
|
289
|
+
self.generate_edges()
|
|
290
|
+
|
|
291
|
+
# optional: mapping speichern
|
|
292
|
+
self.merge_map_other_nodes = mapB
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
# in MeshingClass ergänzen
|
|
296
|
+
def translate(self, dx=0.0, dy=0.0):
|
|
297
|
+
self.NL[:, 0] += float(dx)
|
|
298
|
+
self.NL[:, 1] += float(dy)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def plot_mesh(self,
|
|
302
|
+
show_node_numbers=True,
|
|
303
|
+
show_element_numbers=False,
|
|
304
|
+
node_fontsize=7,
|
|
305
|
+
elem_fontsize=8,
|
|
306
|
+
ax=None):
|
|
307
|
+
"""
|
|
308
|
+
Plottet das aktuelle Mesh (NL, EL) inkl. optionaler
|
|
309
|
+
Knoten- und Elementnummern.
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
NL = np.asarray(self.NL, float)
|
|
313
|
+
EL = np.asarray(self.EL, int)
|
|
314
|
+
|
|
315
|
+
if ax is None:
|
|
316
|
+
fig, ax = plt.subplots(figsize=(7, 6))
|
|
317
|
+
|
|
318
|
+
# -------------------------
|
|
319
|
+
# Elemente zeichnen
|
|
320
|
+
# -------------------------
|
|
321
|
+
for e, el in enumerate(EL):
|
|
322
|
+
node_ids = el - 1 # 0-based
|
|
323
|
+
coords = NL[node_ids, :]
|
|
324
|
+
|
|
325
|
+
poly = np.vstack([coords, coords[0]])
|
|
326
|
+
ax.plot(poly[:, 0], poly[:, 1], color="black", linewidth=0.8)
|
|
327
|
+
|
|
328
|
+
if show_element_numbers:
|
|
329
|
+
xc = coords[:, 0].mean()
|
|
330
|
+
yc = coords[:, 1].mean()
|
|
331
|
+
ax.text(
|
|
332
|
+
xc, yc, f"E{e+1}",
|
|
333
|
+
color="red",
|
|
334
|
+
fontsize=elem_fontsize,
|
|
335
|
+
ha="center", va="center",
|
|
336
|
+
bbox=dict(facecolor="white", edgecolor="none", alpha=0.6)
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
# -------------------------
|
|
340
|
+
# Knoten plotten
|
|
341
|
+
# -------------------------
|
|
342
|
+
ax.scatter(NL[:, 0], NL[:, 1], s=10, color="black", zorder=3)
|
|
343
|
+
|
|
344
|
+
if show_node_numbers:
|
|
345
|
+
for i, (x, y) in enumerate(NL):
|
|
346
|
+
ax.text(
|
|
347
|
+
x, y, f"N{i+1}",
|
|
348
|
+
color="blue",
|
|
349
|
+
fontsize=node_fontsize,
|
|
350
|
+
ha="right", va="bottom",
|
|
351
|
+
zorder=4,
|
|
352
|
+
bbox=dict(facecolor="white", edgecolor="none", alpha=0.6)
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
# -------------------------
|
|
356
|
+
# Plot-Layout
|
|
357
|
+
# -------------------------
|
|
358
|
+
ax.set_aspect("equal", adjustable="box")
|
|
359
|
+
ax.set_xlabel("x")
|
|
360
|
+
ax.set_ylabel("y")
|
|
361
|
+
ax.grid(True, linestyle="--", alpha=0.4)
|
|
362
|
+
ax.set_title("Finite-Element-Netz")
|
|
363
|
+
|
|
364
|
+
plt.tight_layout()
|
|
365
|
+
plt.show()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Output_Class:
|
|
5
|
+
def __init__(self):
|
|
6
|
+
init = None
|
|
7
|
+
def report_nodal_extrema(self,fieldname):
|
|
8
|
+
print("Max. x- Displacement: ", max(fieldname.AssembleMatrix.x_disp), "[m]")
|
|
9
|
+
print("Min. x- Displacement: ", min(fieldname.AssembleMatrix.x_disp), "[m]")
|
|
10
|
+
print("Max. z- Displacement: ", max(fieldname.AssembleMatrix.z_disp), "[m]")
|
|
11
|
+
print("Min. z- Displacement: ", min(fieldname.AssembleMatrix.z_disp), "[m]")
|
|
12
|
+
|
|
13
|
+
def report_extrema(self,field_name, arr_2d, gp_xy):
|
|
14
|
+
"""
|
|
15
|
+
arr_2d: shape (n_elem, 4) -> Werte je Element und Gauss-Punkt
|
|
16
|
+
gp_xy : shape (n_elem, 4, 2) -> phys. Koordinaten der Gauss-Punkte
|
|
17
|
+
"""
|
|
18
|
+
n_elem, n_gp = arr_2d.shape
|
|
19
|
+
|
|
20
|
+
# MAX
|
|
21
|
+
imax = np.argmax(arr_2d)
|
|
22
|
+
emax, gmax = np.unravel_index(imax, arr_2d.shape)
|
|
23
|
+
vmax = float(arr_2d[emax, gmax])
|
|
24
|
+
x_max, y_max = gp_xy[emax, gmax, :]
|
|
25
|
+
|
|
26
|
+
# MIN
|
|
27
|
+
imin = np.argmin(arr_2d)
|
|
28
|
+
emin, gmin = np.unravel_index(imin, arr_2d.shape)
|
|
29
|
+
vmin = float(arr_2d[emin, gmin])
|
|
30
|
+
x_min, y_min = gp_xy[emin, gmin, :]
|
|
31
|
+
|
|
32
|
+
print(f"\n--- {field_name} ---")
|
|
33
|
+
print(f"MAX: {vmax:.6g} in Element {emax+1}, GP {gmax+1} at (x,y)=({x_max:.6g},{y_max:.6g})")
|
|
34
|
+
print(f"MIN: {vmin:.6g} in Element {emin+1}, GP {gmin+1} at (x,y)=({x_min:.6g},{y_min:.6g})")
|