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.
Files changed (44) hide show
  1. KIB_LAP/Betonbau/TEST_Rectangular.py +21 -0
  2. KIB_LAP/Betonbau/beam_rectangular.py +4 -0
  3. KIB_LAP/FACHWERKEBEN/Elements.py +209 -0
  4. KIB_LAP/FACHWERKEBEN/InputData.py +118 -0
  5. KIB_LAP/FACHWERKEBEN/Iteration.py +967 -0
  6. KIB_LAP/FACHWERKEBEN/Materials.py +30 -0
  7. KIB_LAP/FACHWERKEBEN/Plotting.py +681 -0
  8. KIB_LAP/FACHWERKEBEN/__init__.py +4 -0
  9. KIB_LAP/FACHWERKEBEN/main.py +27 -0
  10. KIB_LAP/Plattentragwerke/PlateBendingKirchhoff.py +36 -29
  11. KIB_LAP/STABRAUM/InputData.py +13 -2
  12. KIB_LAP/STABRAUM/Output_Data.py +61 -0
  13. KIB_LAP/STABRAUM/Plotting.py +1453 -0
  14. KIB_LAP/STABRAUM/Programm.py +518 -1026
  15. KIB_LAP/STABRAUM/Steifigkeitsmatrix.py +338 -117
  16. KIB_LAP/STABRAUM/main.py +58 -0
  17. KIB_LAP/STABRAUM/results.py +37 -0
  18. KIB_LAP/Scheibe/Assemble_Stiffness.py +246 -0
  19. KIB_LAP/Scheibe/Element_Stiffness.py +362 -0
  20. KIB_LAP/Scheibe/Meshing.py +365 -0
  21. KIB_LAP/Scheibe/Output.py +34 -0
  22. KIB_LAP/Scheibe/Plotting.py +722 -0
  23. KIB_LAP/Scheibe/Shell_Calculation.py +523 -0
  24. KIB_LAP/Scheibe/Testing_Mesh.py +25 -0
  25. KIB_LAP/Scheibe/__init__.py +14 -0
  26. KIB_LAP/Scheibe/main.py +33 -0
  27. KIB_LAP/StabEbenRitz/Biegedrillknicken.py +757 -0
  28. KIB_LAP/StabEbenRitz/Biegedrillknicken_Trigeometry.py +328 -0
  29. KIB_LAP/StabEbenRitz/Querschnittswerte.py +527 -0
  30. KIB_LAP/StabEbenRitz/Stabberechnung_Klasse.py +868 -0
  31. KIB_LAP/plate_bending_cpp.cp313-win_amd64.pyd +0 -0
  32. KIB_LAP/plate_buckling_cpp.cp313-win_amd64.pyd +0 -0
  33. {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/METADATA +1 -1
  34. {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/RECORD +37 -19
  35. Examples/Cross_Section_Thin.py +0 -61
  36. KIB_LAP/Betonbau/Bemessung_Zust_II.py +0 -648
  37. KIB_LAP/Betonbau/Iterative_Design.py +0 -723
  38. KIB_LAP/Plattentragwerke/NumInte.cpp +0 -23
  39. KIB_LAP/Plattentragwerke/NumericalIntegration.cpp +0 -23
  40. KIB_LAP/Plattentragwerke/plate_bending_cpp.cp313-win_amd64.pyd +0 -0
  41. KIB_LAP/main.py +0 -2
  42. {Examples → KIB_LAP/StabEbenRitz}/__init__.py +0 -0
  43. {kib_lap-0.5.dist-info → kib_lap-0.7.7.dist-info}/WHEEL +0 -0
  44. {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})")