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,523 @@
1
+ try:
2
+ from Meshing import *
3
+ from Element_Stiffness import *
4
+ from Assemble_Stiffness import *
5
+ except:
6
+ from KIB_LAP.Scheibe.Meshing import *
7
+ from KIB_LAP.Scheibe.Element_Stiffness import *
8
+ from KIB_LAP.Scheibe.Assemble_Stiffness import *
9
+
10
+ from matplotlib.collections import PatchCollection
11
+ import numpy as np
12
+ import matplotlib.pyplot as plt
13
+ import matplotlib.patches as patches
14
+ from matplotlib.widgets import Slider
15
+
16
+
17
+ import matplotlib.cm as cm
18
+ from tabulate import *
19
+ from scipy.interpolate import griddata
20
+
21
+
22
+ class ShellCalculation:
23
+ def __init__(self, MeshingParams="Meshing_R"):
24
+ self.Meshing_Mode = MeshingParams
25
+ self.Get_Meshing_Parameters()
26
+ self.Get_Material_Parameters()
27
+ self.Get_Element_Matrices()
28
+ self.Assemble_Stiffness_Matrices()
29
+ self.SolveAssembled_Matrix()
30
+ self.StoreElementDisplacements()
31
+ self.CalculateInnerElementForces_Gauss()
32
+
33
+ def BuildMultiPatchMeshFromCSV(
34
+ self, patches_csv="Meshing_Parameters/Meshing_Patches.csv", tol=None
35
+ ):
36
+ df = pd.read_csv(patches_csv)
37
+
38
+ # minimale Plausibilitätschecks
39
+ required = {"patch_id", "d1", "d2", "num_x", "num_y", "elem_type", "dx", "dy"}
40
+ miss = required - set(df.columns)
41
+ if miss:
42
+ raise ValueError(f"Missing columns in {patches_csv}: {miss}")
43
+
44
+ meshes = []
45
+ for _, row in df.iterrows():
46
+ m = MeshingClass(
47
+ d1=float(row["d1"]),
48
+ d2=float(row["d2"]),
49
+ num_x=int(row["num_x"]),
50
+ num_y=int(row["num_y"]),
51
+ elem_type=str(row["elem_type"]),
52
+ )
53
+ # aktuell: nur rect, analog kannst du später quad-from-csv je patch machen
54
+ if str(row["elem_type"]).lower() == "rect":
55
+ m.generating_rectangular_mesh()
56
+ else:
57
+ raise ValueError("Only 'rect' supported in multipatch example for now.")
58
+
59
+ # absolute Verschiebung
60
+ m.translate(dx=float(row["dx"]), dy=float(row["dy"]))
61
+
62
+ # optional: Voids pro Patch (wenn Spalten vorhanden)
63
+ if (
64
+ "voids_csv" in df.columns
65
+ and isinstance(row.get("voids_csv"), str)
66
+ and row["voids_csv"].strip()
67
+ ):
68
+ voids_csv = row["voids_csv"].strip()
69
+ polygons_csv = None
70
+ if (
71
+ "polygons_csv" in df.columns
72
+ and isinstance(row.get("polygons_csv"), str)
73
+ and row["polygons_csv"].strip()
74
+ ):
75
+ polygons_csv = row["polygons_csv"].strip()
76
+ m.apply_voids_from_csv(voids_csv, polygons_csv=polygons_csv)
77
+
78
+ meshes.append(m)
79
+
80
+ # Merge: erstes Mesh ist Basis
81
+ base = meshes[0]
82
+ for m in meshes[1:]:
83
+ base.merge_with_mesh(m, tol=tol) # tol optional
84
+
85
+ return base
86
+
87
+ def Get_Meshing_Parameters(self):
88
+
89
+ try:
90
+ self.Meshing_Params = pd.read_csv("Meshing_Parameters/Meshing_Params.csv")
91
+ except:
92
+ self.Meshing_Params = pd.read_csv(
93
+ "../Meshing_Parameters/Meshing_Params.csv"
94
+ )
95
+
96
+ _num_x = self.Meshing_Params.loc[
97
+ self.Meshing_Params["Param"] == "num_x", "Value"
98
+ ].values[0]
99
+ _num_y = self.Meshing_Params.loc[
100
+ self.Meshing_Params["Param"] == "num_y", "Value"
101
+ ].values[0]
102
+ _d_1 = self.Meshing_Params.loc[
103
+ self.Meshing_Params["Param"] == "d1", "Value"
104
+ ].values[0]
105
+ _d_2 = self.Meshing_Params.loc[
106
+ self.Meshing_Params["Param"] == "d2", "Value"
107
+ ].values[0]
108
+
109
+ if self.Meshing_Mode == "Meshing_R":
110
+ self.Meshing = MeshingClass(
111
+ d1=_d_1, d2=_d_2, num_x=int(_num_x), num_y=int(_num_y), elem_type="rect"
112
+ )
113
+ self.Meshing.generating_rectangular_mesh()
114
+
115
+ elif self.Meshing_Mode == "Meshing_RQ":
116
+ self.Meshing = MeshingClass(
117
+ d1=0, d2=0, num_x=int(_num_x), num_y=int(_num_y), elem_type="rect"
118
+ )
119
+ self.Meshing.generating_quadrilateral_mesh_from_csv(
120
+ "Meshing_Parameters/Meshing_Params_q.csv"
121
+ )
122
+
123
+ elif self.Meshing_Mode == "Meshing_MP":
124
+ # Multi-Patch: alles aus eigener CSV
125
+ self.Meshing = self.BuildMultiPatchMeshFromCSV(
126
+ "Meshing_Parameters/Meshing_Patches.csv"
127
+ )
128
+
129
+ else:
130
+ raise ValueError(f"Unknown Meshing_Mode: {self.Meshing_Mode}")
131
+
132
+ def Get_Material_Parameters(self):
133
+ try:
134
+ self.Material_Params = pd.read_csv("Material_Parameters/Material.csv")
135
+ except:
136
+ self.Material_Params = pd.read_csv("../Material_Parameters/Material.csv")
137
+ self.E = self.Material_Params.loc[
138
+ self.Material_Params["Parameter"] == "E", "Value"
139
+ ].values[0]
140
+ self.nu = self.Material_Params.loc[
141
+ self.Material_Params["Parameter"] == "nu", "Value"
142
+ ].values[0]
143
+ self.t = self.Material_Params.loc[
144
+ self.Material_Params["Parameter"] == "t", "Value"
145
+ ].values[0]
146
+ self.gamma = self.Material_Params.loc[
147
+ self.Material_Params["Parameter"] == "gamma", "Value"
148
+ ].values[0]
149
+
150
+ def Get_Element_Matrices(self):
151
+ self.EL_Matrices = np.zeros((len(self.Meshing.EL), 8, 8))
152
+ self.EL_AreaLoads = np.zeros((8, len(self.Meshing.EL)))
153
+ self.EL_AreaLoads_Nodes = np.zeros((len(self.Meshing.EL), 4))
154
+
155
+ for i in range(0, len(self.Meshing.EL), 1):
156
+ coords = np.zeros((4, 2))
157
+ for j in range(0, len(self.Meshing.EL[0]), 1):
158
+ index = int(self.Meshing.EL[i][j])
159
+ _x = self.Meshing.NL[index - 1][0]
160
+ _y = self.Meshing.NL[index - 1][1]
161
+ coords[j][0] = _x
162
+ coords[j][1] = _y
163
+
164
+ self.stiffness_matrix = Stiffness_Matrix(
165
+ coords, self.E, self.nu, self.t, self.gamma, self.Meshing
166
+ )
167
+ self.stiffness_matrix.stiffness()
168
+
169
+ self.EL_Matrices[i] = self.stiffness_matrix.K
170
+
171
+ self.stiffness_matrix.element_load_vector()
172
+ self.EL_AreaLoads[:, i] = self.stiffness_matrix.element_loading_vec
173
+ self.EL_AreaLoads_Nodes[i, :] = self.Meshing.EL[i]
174
+
175
+ def Assemble_Stiffness_Matrices(self):
176
+ self.AssembleMatrix = Assembled_Matrices(
177
+ self.Meshing,
178
+ self.Meshing.EL,
179
+ self.Meshing.NL,
180
+ self.EL_Matrices,
181
+ self.stiffness_matrix.node_loading_vec,
182
+ self.stiffness_matrix.node_store_vec,
183
+ self.EL_AreaLoads,
184
+ self.EL_AreaLoads_Nodes,
185
+ )
186
+ self.AssembleMatrix.assemble_K()
187
+ self.AssembleMatrix.Load_BC()
188
+ self.AssembleMatrix.LoadInput()
189
+ self.AssembleMatrix.apply_BC()
190
+ self.AssembleMatrix.GenerateLoadVector()
191
+
192
+ def SolveAssembled_Matrix(self):
193
+ self.AssembleMatrix.Solve()
194
+
195
+ def StoreElementDisplacements(self):
196
+ self.AssembleMatrix.StoreElementDisplacements()
197
+
198
+ def Ns_Mat(self, xi, eta):
199
+ self.Ns_Matrix = np.zeros(
200
+ (self.stiffness_matrix._PD, self.stiffness_matrix._NPE)
201
+ )
202
+ self.Ns_Matrix_T = np.zeros(
203
+ (self.stiffness_matrix._NPE, self.stiffness_matrix._PD)
204
+ )
205
+
206
+ if self.stiffness_matrix._NPE == 3:
207
+ self.Ns_Matrix[0][0] = 1
208
+ self.Ns_Matrix[0][1] = 0
209
+ self.Ns_Matrix[0][2] = -1
210
+
211
+ self.Ns_Matrix[1][0] = 0
212
+ self.Ns_Matrix[1][1] = 1
213
+ self.Ns_Matrix[1][2] = -1
214
+
215
+ if self.stiffness_matrix._NPE == 4:
216
+ self.Ns_Matrix[0][0] = -0.25 * (1 - eta)
217
+ self.Ns_Matrix[0][1] = 0.25 * (1 - eta)
218
+ self.Ns_Matrix[0][2] = 0.25 * (1 + eta)
219
+ self.Ns_Matrix[0][3] = -0.25 * (1 + eta)
220
+
221
+ self.Ns_Matrix[1][0] = -0.25 * (1 - xi)
222
+ self.Ns_Matrix[1][1] = -0.25 * (1 + xi)
223
+ self.Ns_Matrix[1][2] = 0.25 * (1 + xi)
224
+ self.Ns_Matrix[1][3] = 0.25 * (1 - xi)
225
+
226
+ def E_Mat(self):
227
+ """
228
+ Function to calculate the material matrix for each element \n
229
+ """
230
+ self.E_el = np.zeros((3, 3))
231
+
232
+ self.E_el[0][0] = 1
233
+ self.E_el[0][1] = self.nu
234
+ self.E_el[0][2] = 0
235
+
236
+ self.E_el[1][0] = self.nu
237
+ self.E_el[1][1] = 1
238
+ self.E_el[1][2] = 0
239
+
240
+ self.E_el[2][0] = 0
241
+ self.E_el[2][1] = 0
242
+ self.E_el[2][2] = (1 - self.nu) / 2
243
+
244
+ self.E_el *= self.E / (1 - self.nu**2)
245
+
246
+ def _q4_dN_dxi_eta(xi, eta):
247
+ # Q4, Knotenreihenfolge: 1(-1,-1), 2(+1,-1), 3(+1,+1), 4(-1,+1)
248
+ dN_dxi = 0.25 * np.array(
249
+ [-(1 - eta), +(1 - eta), +(1 + eta), -(1 + eta)], dtype=float
250
+ )
251
+
252
+ dN_deta = 0.25 * np.array(
253
+ [-(1 - xi), -(1 + xi), +(1 + xi), +(1 - xi)], dtype=float
254
+ )
255
+
256
+ return dN_dxi, dN_deta
257
+
258
+ def _D_plane_stress(E, nu):
259
+ c = E / (1.0 - nu**2)
260
+ return c * np.array(
261
+ [[1.0, nu, 0.0], [nu, 1.0, 0.0], [0.0, 0.0, (1.0 - nu) / 2.0]], dtype=float
262
+ )
263
+
264
+ def CalculateInnerElementForces_Gauss(self, compute_nodal=True, compute_principal=True):
265
+ """
266
+ Rückrechnung an 2x2 Gauss-Punkten je Q4-Element (plane stress).
267
+ + optional:
268
+ - Extrapolation GP -> Elementknoten -> globale Knotenwerte
269
+ - Bestimmung globaler Knoten-Extrema
270
+ - Hauptmembrankräfte (principal membrane forces)
271
+ """
272
+
273
+ import numpy as np
274
+
275
+ # -------------------------
276
+ # Gauss-Punkte 2x2
277
+ # -------------------------
278
+ gp = 1.0 / np.sqrt(3.0)
279
+ gauss_pts = [(-gp, -gp), (+gp, -gp), (+gp, +gp), (-gp, +gp)]
280
+
281
+ def dN_dxi_eta(xi, eta):
282
+ dN_dxi = 0.25 * np.array([-(1 - eta), +(1 - eta), +(1 + eta), -(1 + eta)], dtype=float)
283
+ dN_deta = 0.25 * np.array([-(1 - xi), -(1 + xi), +(1 + xi), +(1 - xi)], dtype=float)
284
+ return dN_dxi, dN_deta
285
+
286
+ def Nvals(xi, eta):
287
+ return 0.25 * np.array([
288
+ (1 - xi) * (1 - eta),
289
+ (1 + xi) * (1 - eta),
290
+ (1 + xi) * (1 + eta),
291
+ (1 - xi) * (1 + eta),
292
+ ], dtype=float)
293
+
294
+ def D_plane_stress(E, nu):
295
+ c = E / (1.0 - nu**2)
296
+ return c * np.array([
297
+ [1.0, nu, 0.0],
298
+ [nu, 1.0, 0.0],
299
+ [0.0, 0.0, (1.0 - nu) / 2.0],
300
+ ], dtype=float)
301
+
302
+ # -------------------------
303
+ # Speicher
304
+ # -------------------------
305
+ n_elem = len(self.Meshing.EL)
306
+
307
+ self.gp_xy = np.zeros((n_elem, 4, 2), dtype=float)
308
+ self.strain_gp = np.zeros((n_elem, 4, 3), dtype=float)
309
+ self.stress_gp = np.zeros((n_elem, 4, 3), dtype=float)
310
+ self.n_gp = np.zeros((n_elem, 4, 3), dtype=float)
311
+
312
+ # -------------------------
313
+ # Material / Dicke
314
+ # -------------------------
315
+ E0 = float(getattr(self, "E", 210e9))
316
+ nu0 = float(getattr(self, "nu", 0.3))
317
+ t0 = float(getattr(self, "t", 1.0))
318
+
319
+ # -------------------------
320
+ # Loop über Elemente
321
+ # -------------------------
322
+ for e in range(n_elem):
323
+ el_nodes = self.Meshing.EL[e] # [n1,n2,n3,n4] (1-basiert)
324
+ coords = np.array([self.Meshing.NL[nid - 1] for nid in el_nodes], dtype=float) # (4,2)
325
+
326
+ ue = np.asarray(self.AssembleMatrix.disp_element_matrix[:, e], dtype=float).reshape(8)
327
+
328
+ E, nu, t = E0, nu0, t0
329
+ D = D_plane_stress(E, nu)
330
+
331
+ for k, (xi, eta) in enumerate(gauss_pts):
332
+ dN_dxi, dN_deta = dN_dxi_eta(xi, eta)
333
+
334
+ J = np.zeros((2, 2), dtype=float)
335
+ J[0, 0] = np.dot(dN_dxi, coords[:, 0])
336
+ J[0, 1] = np.dot(dN_deta, coords[:, 0])
337
+ J[1, 0] = np.dot(dN_dxi, coords[:, 1])
338
+ J[1, 1] = np.dot(dN_deta, coords[:, 1])
339
+
340
+ detJ = np.linalg.det(J)
341
+ if detJ <= 0:
342
+ raise ValueError(f"detJ <= 0 in element {e+1}. Check node ordering / mesh.")
343
+
344
+ invJ = np.linalg.inv(J)
345
+
346
+ dN_dx = invJ[0, 0] * dN_dxi + invJ[0, 1] * dN_deta
347
+ dN_dy = invJ[1, 0] * dN_dxi + invJ[1, 1] * dN_deta
348
+
349
+ B = np.zeros((3, 8), dtype=float)
350
+ for i in range(4):
351
+ B[0, 2*i + 0] = dN_dx[i]
352
+ B[1, 2*i + 1] = dN_dy[i]
353
+ B[2, 2*i + 0] = dN_dy[i]
354
+ B[2, 2*i + 1] = dN_dx[i]
355
+
356
+ eps = B @ ue
357
+ sig = D @ eps
358
+
359
+ N = Nvals(xi, eta)
360
+ x_gp = float(np.dot(N, coords[:, 0]))
361
+ y_gp = float(np.dot(N, coords[:, 1]))
362
+
363
+ self.gp_xy[e, k, :] = [x_gp, y_gp]
364
+ self.strain_gp[e, k, :] = eps
365
+ self.stress_gp[e, k, :] = sig
366
+ self.n_gp[e, k, :] = sig * t # [n_x, n_y, n_xy]
367
+
368
+ # Element-Mittelwerte
369
+ self.stress_elem_avg = np.mean(self.stress_gp, axis=1) # (n_elem,3)
370
+ self.n_elem_avg = np.mean(self.n_gp, axis=1) # (n_elem,3)
371
+
372
+ # ==========================================================
373
+ # (1) Knotenwerte (Extrapolation GP -> Elementknoten -> global)
374
+ # ==========================================================
375
+ if compute_nodal:
376
+ n_nodes = self.Meshing.NL.shape[0]
377
+
378
+ # Extrapolationsmatrix für GP-Reihenfolge:
379
+ # (-g,-g),(+g,-g),(+g,+g),(-g,+g) -> Knoten (-1,-1),(+1,-1),(+1,+1),(-1,+1)
380
+ s2 = np.sqrt(3.0) / 2.0
381
+ Mext = np.array([
382
+ [1.0 + s2, -0.5, 1.0 - s2, -0.5 ],
383
+ [-0.5, 1.0 + s2, -0.5, 1.0 - s2],
384
+ [1.0 - s2, -0.5, 1.0 + s2, -0.5 ],
385
+ [-0.5, 1.0 - s2, -0.5, 1.0 + s2],
386
+ ], dtype=float)
387
+
388
+ # element-knotenwerte
389
+ self.stress_node_elem = np.zeros((n_elem, 4, 3), dtype=float)
390
+ self.n_node_elem = np.zeros((n_elem, 4, 3), dtype=float)
391
+
392
+ for e in range(n_elem):
393
+ self.stress_node_elem[e, :, :] = Mext @ self.stress_gp[e, :, :]
394
+ self.n_node_elem[e, :, :] = Mext @ self.n_gp[e, :, :]
395
+
396
+ # globale knotenwerte via Mittelung
397
+ sum_stress = np.zeros((n_nodes, 3), dtype=float)
398
+ sum_n = np.zeros((n_nodes, 3), dtype=float)
399
+ cnt = np.zeros((n_nodes,), dtype=int)
400
+
401
+ for e in range(n_elem):
402
+ el_nodes = self.Meshing.EL[e] # 1-basiert
403
+ for a in range(4):
404
+ nid0 = int(el_nodes[a]) - 1
405
+ sum_stress[nid0, :] += self.stress_node_elem[e, a, :]
406
+ sum_n[nid0, :] += self.n_node_elem[e, a, :]
407
+ cnt[nid0] += 1
408
+
409
+ cnt_safe = np.maximum(cnt, 1)[:, None]
410
+ self.stress_node = sum_stress / cnt_safe
411
+ self.n_node = sum_n / cnt_safe
412
+ self.node_contrib_count = cnt
413
+
414
+ # ---- Knoten-Extrema (max/min pro Komponente) ----
415
+ def _extrema_dict(vec, name):
416
+ NL = np.asarray(self.Meshing.NL, float)
417
+ imax = int(np.nanargmax(vec))
418
+ imin = int(np.nanargmin(vec))
419
+ return {
420
+ "name": name,
421
+ "max": {"value": float(vec[imax]), "node": imax+1, "xy": (float(NL[imax,0]), float(NL[imax,1]))},
422
+ "min": {"value": float(vec[imin]), "node": imin+1, "xy": (float(NL[imin,0]), float(NL[imin,1]))},
423
+ }
424
+
425
+ self.extrema_nodes = {
426
+ "sigma_x": _extrema_dict(self.stress_node[:, 0], "sigma_x"),
427
+ "sigma_y": _extrema_dict(self.stress_node[:, 1], "sigma_y"),
428
+ "tau_xy": _extrema_dict(self.stress_node[:, 2], "tau_xy"),
429
+ "n_x": _extrema_dict(self.n_node[:, 0], "n_x"),
430
+ "n_y": _extrema_dict(self.n_node[:, 1], "n_y"),
431
+ "n_xy": _extrema_dict(self.n_node[:, 2], "n_xy"),
432
+ }
433
+
434
+ # ==========================================================
435
+ # (2) Hauptmembrankräfte (principal membrane forces)
436
+ # ==========================================================
437
+ if compute_principal:
438
+ def principal_2d(nx, ny, nxy):
439
+ """
440
+ Rückgabe:
441
+ n1, n2: Hauptmembrankräfte
442
+ theta: Winkel der 1. Hauptachse gegen +x (rad)
443
+ """
444
+ n_avg = 0.5 * (nx + ny)
445
+ R = np.sqrt((0.5 * (nx - ny))**2 + nxy**2)
446
+ n1 = n_avg + R
447
+ n2 = n_avg - R
448
+ theta = 0.5 * np.arctan2(2.0 * nxy, (nx - ny))
449
+ return n1, n2, theta
450
+
451
+ # GP principal
452
+ self.n_princ_gp = np.zeros((n_elem, 4, 3), dtype=float) # [n1,n2,theta]
453
+ for e in range(n_elem):
454
+ for k in range(4):
455
+ nx, ny, nxy = self.n_gp[e, k, :]
456
+ n1, n2, th = principal_2d(nx, ny, nxy)
457
+ self.n_princ_gp[e, k, :] = [n1, n2, th]
458
+
459
+ # element-avg principal (aus element-avg n)
460
+ self.n_princ_elem_avg = np.zeros((n_elem, 3), dtype=float)
461
+ for e in range(n_elem):
462
+ nx, ny, nxy = self.n_elem_avg[e, :]
463
+ n1, n2, th = principal_2d(nx, ny, nxy)
464
+ self.n_princ_elem_avg[e, :] = [n1, n2, th]
465
+
466
+ # nodal principal (wenn nodal vorhanden)
467
+ if compute_nodal:
468
+ self.n_princ_node = np.zeros((self.n_node.shape[0], 3), dtype=float)
469
+ for i in range(self.n_node.shape[0]):
470
+ nx, ny, nxy = self.n_node[i, :]
471
+ n1, n2, th = principal_2d(nx, ny, nxy)
472
+ self.n_princ_node[i, :] = [n1, n2, th]
473
+
474
+ def PlotStressAlongCut(self, cut_position, cut_direction="x", field="sigma_x"):
475
+ import numpy as np
476
+ import matplotlib.pyplot as plt
477
+ from scipy.interpolate import griddata
478
+
479
+ if not hasattr(self, "stress_elem_avg"):
480
+ self.CalculateInnerElementForces_Gauss()
481
+
482
+ field_idx = {"sigma_x": 0, "sigma_y": 1, "tau_xy": 2}
483
+ j = field_idx[field]
484
+
485
+ # Elementzentren
486
+ centroids = []
487
+ vals = []
488
+ for e, el in enumerate(self.Meshing.EL):
489
+ coords = np.array([self.Meshing.NL[nid - 1] for nid in el], dtype=float)
490
+ centroids.append(coords.mean(axis=0))
491
+ vals.append(float(self.stress_elem_avg[e, j]))
492
+ centroids = np.array(centroids, dtype=float) # (n_elem,2)
493
+ vals = np.array(vals, dtype=float) # (n_elem,)
494
+
495
+ # Grid für Interpolation
496
+ grid_x, grid_y = np.mgrid[
497
+ centroids[:, 0].min() : centroids[:, 0].max() : 200j,
498
+ centroids[:, 1].min() : centroids[:, 1].max() : 200j,
499
+ ]
500
+
501
+ grid_z = griddata(centroids, vals, (grid_x, grid_y), method="linear")
502
+
503
+ if cut_direction == "x":
504
+ cut_index = int(np.argmin(np.abs(grid_x[:, 0] - cut_position)))
505
+ cut_vals = grid_z[cut_index, :]
506
+ cut_coords = grid_y[cut_index, :]
507
+ xlabel = "y"
508
+ title = f"{field} along x={cut_position}"
509
+ else:
510
+ cut_index = int(np.argmin(np.abs(grid_y[0, :] - cut_position)))
511
+ cut_vals = grid_z[:, cut_index]
512
+ cut_coords = grid_x[:, cut_index]
513
+ xlabel = "x"
514
+ title = f"{field} along y={cut_position}"
515
+
516
+ plt.figure()
517
+ plt.plot(cut_coords, cut_vals, label=title)
518
+ plt.xlabel(xlabel)
519
+ plt.ylabel(field)
520
+ plt.grid(True)
521
+ plt.legend()
522
+ plt.title(title)
523
+ plt.show()
@@ -0,0 +1,25 @@
1
+ from Meshing import *
2
+ _num_x = 10
3
+ _num_y = 10
4
+
5
+
6
+ A = MeshingClass(d1=10, d2=10, num_x=_num_x, num_y=_num_y, elem_type="rect"); A.generating_rectangular_mesh()
7
+
8
+ B = MeshingClass(d1=10, d2=10, num_x=_num_x, num_y=_num_y, elem_type="rect"); B.generating_rectangular_mesh()
9
+ B.NL[:,1] += A.NL[:,1].max() # rechts an A
10
+
11
+ C = MeshingClass(d1=10, d2=10, num_x=_num_x, num_y=_num_y, elem_type="rect"); C.generating_rectangular_mesh()
12
+ C.NL[:,1] += A.NL[:,1].max() # oben auf A
13
+ C.NL[:,0] += B.NL[:,0].max()
14
+
15
+ A.merge_with_mesh(B)
16
+ A.merge_with_mesh(C)
17
+
18
+ BottomNodes = A.get_bottom_border_nodes()
19
+ print(BottomNodes)
20
+
21
+ A.plot_mesh()
22
+
23
+
24
+
25
+
@@ -0,0 +1,14 @@
1
+ try:
2
+ from Element_Stiffness import *
3
+ from Assemble_Stiffness import *
4
+ from Meshing import *
5
+ from Output import *
6
+ from Plotting import *
7
+ from Shell_Calculation import *
8
+ except:
9
+ from KIB_LAP.Scheibe.Element_Stiffness import *
10
+ from KIB_LAP.Scheibe.Assemble_Stiffness import *
11
+ from KIB_LAP.Scheibe.Meshing import *
12
+ from KIB_LAP.Scheibe.Output import *
13
+ from KIB_LAP.Scheibe.Plotting import *
14
+ from KIB_LAP.Scheibe.Shell_Calculation import *
@@ -0,0 +1,33 @@
1
+ from Shell_Calculation import *
2
+ from Output import Output_Class
3
+ from Plotting import ShellPlotter
4
+
5
+ Class = ShellCalculation("Meshing_MP")
6
+
7
+ Output = Output_Class()
8
+
9
+ Plotting = ShellPlotter(Class)
10
+
11
+ # Plotting.plot_mesh_with_node_ids()
12
+ # Plotting.plot_load_vector_interactive()
13
+ # Plotting.plot_deflected_interactive()
14
+ # # Displacements
15
+
16
+ # Output.report_nodal_extrema(Class)
17
+
18
+ # # Line forces n = stress * t (n_gp shape: (n_elem,4,3))
19
+ # Output.report_extrema("n_x [MN/m]", Class.n_gp[:, :, 0], Class.gp_xy)
20
+ # Output.report_extrema("n_xy [MN/m]", Class.n_gp[:, :, 2], Class.gp_xy)
21
+
22
+ # # Stresses (stress_gp shape: (n_elem,4,3))
23
+ # Output.report_extrema("sigma_x [MN/m^2]", Class.stress_gp[:, :, 0], Class.gp_xy)
24
+ # Output.report_extrema("sigma_y [MN/m^2]", Class.stress_gp[:, :, 1], Class.gp_xy)
25
+ # Output.report_extrema("tau_xy [MN/m^2]", Class.stress_gp[:, :, 2], Class.gp_xy)
26
+
27
+
28
+ # Plotting.plot_mesh()
29
+ # Plotting.plot_inner_element_forces()
30
+ # Plotting.plot_stress_along_cut(10.20, "x", "sigma_x", method="linear")
31
+
32
+ Plotting.plot_principal_membrane_forces("n1")
33
+ Plotting.plot_principal_membrane_forces("n2")