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,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 *
|
KIB_LAP/Scheibe/main.py
ADDED
|
@@ -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")
|