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,246 @@
1
+ import numpy as np
2
+ from scipy.sparse import csr_matrix
3
+ from scipy.sparse.linalg import cg
4
+ import matplotlib.pyplot as plt
5
+ import matplotlib.patches as patches
6
+ from matplotlib.widgets import Slider
7
+
8
+ try:
9
+ from Element_Stiffness import Stiffness_Matrix
10
+ from Meshing import MeshingClass
11
+ except:
12
+ from KIB_LAP.Scheibe.Element_Stiffness import Stiffness_Matrix
13
+ from KIB_LAP.Scheibe.Meshing import MeshingClass
14
+
15
+ import pandas as pd
16
+ from tabulate import *
17
+
18
+
19
+ class Assembled_Matrices:
20
+ def __init__(
21
+ self,
22
+ _mesh,
23
+ EL,
24
+ NL,
25
+ EL_Matrices,
26
+ _ElementLoadVector,
27
+ _ElementLoadVectorNodes,
28
+ _ElementLoadVectorAreaLoads,
29
+ _ElementLoadVectorAreaLoadsNodes,
30
+ load_input="csv",
31
+ bc_input="csv",
32
+ ):
33
+ # Meshing
34
+ self.mesh = _mesh
35
+
36
+ self.EL = EL
37
+ self.NL = NL
38
+ # Generate element stiffness matrices
39
+ self.ElementLoadVector = _ElementLoadVector
40
+ self.ElementLoadVectorNodes = _ElementLoadVectorNodes
41
+ self.ElementLoadVectorAreaLoads = _ElementLoadVectorAreaLoads
42
+ self.ElementLoadVectorAreaLoadsNodes = _ElementLoadVectorAreaLoadsNodes
43
+ # Assemble Stiffness matrices
44
+ self._EL = np.array(EL)
45
+ self._NoE = self._EL.shape[0]
46
+ self._NPE = self._EL.shape[1]
47
+ self.NoN = len(NL)
48
+ self.PD = len(NL[0])
49
+ self._EL_Matrices = np.array(EL_Matrices)
50
+ self.load_input = load_input
51
+ self.bc_input = bc_input
52
+
53
+ self.K_Assemble = np.zeros((self.NoN * self.PD, self.NoN * self.PD))
54
+ self.K_Assemble_BC = None
55
+ self.Index_Vector_BC = []
56
+
57
+ def assemble_K(self):
58
+ for i in range(self._NoE):
59
+ Index_Vector = np.zeros(self._NPE * 2, dtype=int)
60
+ for j in range(self._NPE):
61
+ Index_Vector[j] = int(self._EL[i, j] * 2 - 2)
62
+ Index_Vector[j + self._NPE] = int(self._EL[i, j] * 2 - 1)
63
+
64
+ for row in range(len(Index_Vector)):
65
+ ind_row = Index_Vector[row]
66
+ for col in range(len(Index_Vector)):
67
+ ind_col = Index_Vector[col]
68
+ self.K_Assemble[ind_row, ind_col] += self._EL_Matrices[i][row][col]
69
+
70
+ def Load_BC(self):
71
+ if self.bc_input == "console":
72
+ # Implementieren Sie hier die Konsoleneingabe
73
+ pass
74
+ else:
75
+ try:
76
+ self.BC = pd.DataFrame(
77
+ pd.read_csv("Boundary_Conditions/Spring_Elements.csv")
78
+ )
79
+ except:
80
+ """
81
+ This exception is used, if the main file is started from a subfolder (e.g. the parametric studies or testing) \n
82
+ folder \n
83
+ """
84
+ self.BC = pd.DataFrame(
85
+ pd.read_csv("../Boundary_Conditions/Spring_Elements.csv")
86
+ )
87
+
88
+ def apply_BC(self):
89
+ self.K_Assemble_BC = np.copy(self.K_Assemble)
90
+ self.Index_Vector_BC = np.zeros(0, dtype=int)
91
+ self.stiffness_spring = []
92
+
93
+ for i in range(len(self.BC["No"])):
94
+ node = self.BC["No"][i]
95
+ dof = self.BC["DOF"][i]
96
+ stiffness = self.BC["cf in [MN/m]"][i]
97
+ print("Stiffness ", stiffness)
98
+ print(node)
99
+ # Überprüfen, ob der Knoten ein numerischer Wert ist
100
+ if str(node).isdigit():
101
+ node = int(node)
102
+ if dof == "x":
103
+ self.Index_Vector_BC = np.append(self.Index_Vector_BC, (node - 1) * 2)
104
+ elif dof == "z":
105
+ self.Index_Vector_BC = np.append(self.Index_Vector_BC, (node - 1) * 2 + 1)
106
+ elif node == "left":
107
+ nodes = self.mesh.get_left_border_nodes()
108
+ print("LEFT DOF")
109
+ print(dof)
110
+ for p in nodes:
111
+ if dof == "x":
112
+ self.Index_Vector_BC = np.append(self.Index_Vector_BC, (p - 1) * 2)
113
+ elif dof == "z":
114
+ self.Index_Vector_BC = np.append(self.Index_Vector_BC, (p - 1) * 2 + 1)
115
+ else:
116
+ print("Exception. No valid coordinate input for the left boundary.")
117
+ elif node == "right":
118
+ nodes = self.mesh.get_right_border_nodes()
119
+ for p in nodes:
120
+ if dof == "x":
121
+ self.Index_Vector_BC = np.append(self.Index_Vector_BC, (p - 1) * 2)
122
+ elif dof == "z":
123
+ self.Index_Vector_BC = np.append(self.Index_Vector_BC, (p - 1) * 2 + 1)
124
+ else:
125
+ print("Exception. No valid coordinate input for the right boundary.")
126
+ else:
127
+ print("The input isn't usable! Please change the DOF of the boundary condition at Position "
128
+ + str(i + 1) + "\n")
129
+
130
+ try:
131
+ self.stiffness_spring.append(stiffness)
132
+ except:
133
+ print("Error with the spring stiffness")
134
+
135
+ self.Index_Vector_BC = sorted(self.Index_Vector_BC)
136
+
137
+ p = 0
138
+ for index in sorted(self.Index_Vector_BC, reverse=True):
139
+ self.K_Assemble_BC[index][index] += self.stiffness_spring[p]
140
+ p+=1
141
+
142
+ print(self.Index_Vector_BC)
143
+
144
+ def LoadInput(self):
145
+ self.Einzellasten = False
146
+ self.Linienlasten = False
147
+ if self.load_input == "console":
148
+ # Implementieren Sie hier die Konsoleneingabe
149
+ pass
150
+ else:
151
+ try:
152
+ self.NodalForces = pd.DataFrame(pd.read_csv("Loading/Nodal_Loads.csv"))
153
+ self.ElementLoads = pd.DataFrame(
154
+ pd.read_csv("Loading/Element_Loads.csv")
155
+ )
156
+ except:
157
+ self.NodalForces = pd.DataFrame(
158
+ pd.read_csv("../Loading/Nodal_Loads.csv")
159
+ )
160
+ self.ElementLoads = pd.DataFrame(
161
+ pd.read_csv("../Loading/Element_Loads.csv")
162
+ )
163
+
164
+ def GenerateLoadVector(self):
165
+ self.Load_Vector = np.zeros(len(self.K_Assemble_BC))
166
+
167
+ for i in range(0, len(self.NodalForces["DOF"])):
168
+ if self.NodalForces["DOF"][i] == "x":
169
+ index_load = (self.NodalForces["No"][i] - 1) * 2 # x-Direction
170
+ self.Load_Vector[index_load] = self.NodalForces["F in [MN]"][i]
171
+ elif self.NodalForces["DOF"][i] == "z":
172
+ index_load = (self.NodalForces["No"][i] - 1) * 2 + 1 # z-Direction
173
+ self.Load_Vector[index_load] = self.NodalForces["F in [MN]"][i]
174
+
175
+ else:
176
+ print(
177
+ "The input isn't usable! Please change the DOF of the boundary condition at Position "
178
+ + i
179
+ + 1
180
+ + "\n"
181
+ )
182
+
183
+ for i in range(0, len(self.ElementLoadVectorNodes)):
184
+ index_load_x = int((self.ElementLoadVectorNodes[i] - 1) * 2)
185
+ index_load_z = int((self.ElementLoadVectorNodes[i] - 1) * 2 + 1)
186
+
187
+ self.Load_Vector[index_load_x] += self.ElementLoadVector[0][i]
188
+ self.Load_Vector[index_load_z] += self.ElementLoadVector[1][i]
189
+
190
+ for i in range(0, len(self.ElementLoadVectorAreaLoadsNodes), 1):
191
+ p = 0
192
+ for j in range(0, len(self.ElementLoadVectorAreaLoadsNodes[i]), 1):
193
+ index_load_x = int((self.ElementLoadVectorAreaLoadsNodes[i][j] - 1) * 2)
194
+ index_load_z = int(
195
+ (self.ElementLoadVectorAreaLoadsNodes[i][j] - 1) * 2 + 1
196
+ )
197
+
198
+ self.Load_Vector[index_load_x] += self.ElementLoadVectorAreaLoads[
199
+ p * 2
200
+ ][i]
201
+ self.Load_Vector[index_load_z] += self.ElementLoadVectorAreaLoads[
202
+ p * 2 + 1
203
+ ][i]
204
+
205
+ p += 1
206
+
207
+ def get_assembled(self):
208
+ return self.K_Assemble
209
+
210
+ def get_assembled_BC(self):
211
+ return self.K_Assemble_BC
212
+
213
+ def Solve(self):
214
+ if len(self.K_Assemble) < 20:
215
+ self.x_reduced = np.linalg.solve(self.K_Assemble_BC, self.Load_Vector)
216
+ else:
217
+ self.x_reduced, sparse_info = cg(self.K_Assemble_BC, self.Load_Vector)
218
+ print("Information about sparse solver ")
219
+ sparse_info
220
+
221
+ self.x_disp = self.x_reduced[::2]
222
+ self.z_disp = self.x_reduced[1::2]
223
+
224
+ def StoreElementDisplacements(self):
225
+ self.disp_element_matrix = np.zeros((8, self._NoE))
226
+ for row in range(0, len(self.EL), 1):
227
+ p = 0
228
+ for col in range(0, len(self.EL[0]), 1):
229
+ index_x = int((self.EL[row][col] - 1) * 2)
230
+ index_z = int((self.EL[row][col] - 1) * 2 + 1)
231
+
232
+ disp_x = self.x_reduced[index_x]
233
+ disp_z = self.x_reduced[index_z]
234
+
235
+ self.disp_element_matrix[p * 2][row] = disp_x
236
+ self.disp_element_matrix[p * 2 + 1][row] = disp_z
237
+
238
+ p += 1
239
+
240
+
241
+ def __str__(self):
242
+ output = "Assembled stiffness matrix\n"
243
+ output += tabulate(self.K_Assemble) + "\n"
244
+ output += "Assembled stiffness matrix with boundary conditions\n"
245
+ output += tabulate(self.K_Assemble_BC)
246
+ return output
@@ -0,0 +1,362 @@
1
+ import numpy as np
2
+ import pandas as pd
3
+ from tabulate import *
4
+
5
+
6
+ class Linear_Algebra_Class:
7
+ def matrix_transpose_symmetric(self, matrix, result=None):
8
+ return np.transpose(matrix)
9
+
10
+ def matrix_multiplication(self, mat1, mat2):
11
+ return np.matmul(mat1, mat2)
12
+
13
+
14
+ class Gaucho_Method:
15
+ def __init__(self, J):
16
+ self.J = J
17
+ self.det_J = None
18
+ self.J_inv = None
19
+
20
+ def ldl_decomposition(self):
21
+ self.L = np.linalg.cholesky(self.J)
22
+ self.D = np.diag(np.diag(self.L))
23
+ self.L = self.L / np.sqrt(np.diag(self.L))[:, None]
24
+
25
+ def calculate_inverse_gaucho(self):
26
+ self.J_inv = np.linalg.inv(self.J)
27
+ return self.J_inv
28
+
29
+ def calculate_determinant_gaucho(self):
30
+ self.det_J = np.linalg.det(self.J)
31
+ return self.det_J
32
+
33
+
34
+ class Stiffness_Matrix:
35
+ def __init__(self, coords, E, nu, t, gamma, _mesh=None):
36
+ self._coords = np.array(coords)
37
+ self._E = E
38
+ self._nu = nu
39
+ self._t = t
40
+ self._gamma = gamma
41
+
42
+ self._coords_T = np.transpose(self._coords)
43
+ self.K = np.zeros((len(coords), len(coords)))
44
+ self.K_ij = np.zeros((len(coords[0]), len(coords[0])))
45
+ self.J = np.zeros((len(coords[0]), len(coords[0])))
46
+ self.J_inv = np.zeros((len(coords[0]), len(coords[0])))
47
+
48
+ self.grad = np.zeros((len(coords[0]), len(coords)))
49
+ self.result_grad = np.zeros((len(coords[0]), len(coords)))
50
+ self.result_grad_T = np.zeros((len(coords), len(coords[0])))
51
+
52
+ self._NPE = len(coords)
53
+ self._PD = len(coords[0])
54
+ self._GPE = 4 # 4 GP for rectangular, 3 for triangular
55
+
56
+ # Gaussian integration
57
+ self.xi, self.eta, self.alpha = 0, 0, 0
58
+
59
+ # Material parameters
60
+ self.delta = 0
61
+ self.C = 0
62
+ self.det_J = 0
63
+
64
+ # Friends
65
+ self.lin_al = Linear_Algebra_Class()
66
+ self.gaucho_ptr = None
67
+
68
+ self.mesh_data = _mesh
69
+
70
+ def gauss_points(self, gp):
71
+ sqrt3_inv = 1 / np.sqrt(3)
72
+ gauss_points = [
73
+ (-sqrt3_inv, -sqrt3_inv, 1),
74
+ (sqrt3_inv, -sqrt3_inv, 1),
75
+ (sqrt3_inv, sqrt3_inv, 1),
76
+ (-sqrt3_inv, sqrt3_inv, 1),
77
+ ]
78
+ if self._GPE == 4:
79
+ self.xi, self.eta, self.alpha = gauss_points[gp - 1]
80
+
81
+ def stiffness(self):
82
+ self.K = np.zeros((self._NPE * self._PD, self._NPE * self._PD))
83
+ self.det_J_store = np.zeros((2, 2))
84
+
85
+ self._coords_T = self.lin_al.matrix_transpose_symmetric(self._coords)
86
+
87
+ for i in range(self._NPE):
88
+ for j in range(self._NPE):
89
+ for gp in range(1, self._GPE + 1):
90
+ self.gauss_points(gp)
91
+ self.grad_N_nat()
92
+ self.J = self.lin_al.matrix_multiplication(
93
+ self._coords_T, self.result_grad_T
94
+ )
95
+ self.gaucho_ptr = Gaucho_Method(self.J)
96
+
97
+ self.gaucho_ptr.ldl_decomposition()
98
+ self.J_inv = self.gaucho_ptr.calculate_inverse_gaucho()
99
+ self.det_J = self.gaucho_ptr.calculate_determinant_gaucho()
100
+
101
+ self.grad = self.lin_al.matrix_multiplication( # Transformed B-Matrix (Isoparametric)
102
+ self.J_inv, self.result_grad
103
+ )
104
+
105
+ for a in range(self._PD):
106
+ for b in range(self._PD):
107
+ for c in range(self._PD):
108
+ for d in range(self._PD):
109
+ self.K[a * self._NPE + i, c * self._NPE + j] += (
110
+ self.grad[b, i]
111
+ * self.constitutive(a + 1, b + 1, c + 1, d + 1)
112
+ * self.grad[d, j]
113
+ * self.det_J
114
+ * self.alpha
115
+ * self._t
116
+ )
117
+
118
+ def grad_N_nat(self):
119
+ self.result_grad = np.zeros((self._PD, self._NPE))
120
+ self.result_grad_T = np.zeros((self._NPE, self._PD))
121
+
122
+ if self._NPE == 3:
123
+ self.result_grad[0][0] = 1
124
+ self.result_grad[0][1] = 0
125
+ self.result_grad[0][2] = -1
126
+
127
+ self.result_grad[1][0] = 0
128
+ self.result_grad[1][1] = 1
129
+ self.result_grad[1][2] = -1
130
+
131
+ if self._NPE == 4:
132
+ self.result_grad[0][0] = -0.25 * (1 - self.eta)
133
+ self.result_grad[0][1] = 0.25 * (1 - self.eta)
134
+ self.result_grad[0][2] = 0.25 * (1 + self.eta)
135
+ self.result_grad[0][3] = -0.25 * (1 + self.eta)
136
+
137
+ self.result_grad[1][0] = -0.25 * (1 - self.xi)
138
+ self.result_grad[1][1] = -0.25 * (1 + self.xi)
139
+ self.result_grad[1][2] = 0.25 * (1 + self.xi)
140
+ self.result_grad[1][3] = 0.25 * (1 - self.xi)
141
+
142
+ self.result_grad_T = self.lin_al.matrix_transpose_symmetric(self.result_grad)
143
+
144
+ def N_nat(self, xi, eta):
145
+ self.result_N = np.zeros((2, 8))
146
+ self.result_N_T = np.zeros((8, 2))
147
+
148
+ if self._NPE == 4:
149
+ self.result_N[0][0] = 0.25 * (1 - eta) * (1 - xi)
150
+ self.result_N[0][2] = 0.25 * (1 - eta) * (1 + xi)
151
+ self.result_N[0][4] = 0.25 * (1 + eta) * (1 + xi)
152
+ self.result_N[0][6] = 0.25 * (1 + eta) * (1 - xi)
153
+
154
+ self.result_N[1][1] = 0.25 * (1 - eta) * (1 - xi)
155
+ self.result_N[1][3] = 0.25 * (1 - eta) * (1 + xi)
156
+ self.result_N[1][5] = 0.25 * (1 + eta) * (1 + xi)
157
+ self.result_N[1][7] = 0.25 * (1 + eta) * (1 - xi)
158
+
159
+ self.result_N_T = self.lin_al.matrix_transpose_symmetric(self.result_N)
160
+
161
+ def delta_func(self, i, j):
162
+ return 1 if i == j else 0
163
+
164
+ def constitutive(self, i, j, k, l):
165
+ return (self._E / (2 * (1 + self._nu))) * (
166
+ self.delta_func(i, l) * self.delta_func(j, k)
167
+ + self.delta_func(i, k) * self.delta_func(j, l)
168
+ ) + (self._E * self._nu) / (1 - self._nu**2) * self.delta_func(
169
+ i, j
170
+ ) * self.delta_func(
171
+ k, l
172
+ )
173
+
174
+ def element_load_vector(self):
175
+ try:
176
+ self.loading_table = pd.DataFrame(pd.read_csv("Loading/Element_Loads.csv"))
177
+ except:
178
+ self.loading_table = pd.DataFrame(
179
+ pd.read_csv("../Loading/Element_Loads.csv")
180
+ )
181
+
182
+ self.element_loading_vec = np.zeros(8)
183
+
184
+ for i in self.loading_table["type"]:
185
+ if i == "top":
186
+ self.loading_nodes = self.mesh_data.get_top_border_nodes()
187
+ self.node_loading_vec = np.zeros(
188
+ (2, int(len(self.loading_nodes) - 1) * 2)
189
+ )
190
+ self.node_store_vec = np.zeros(int((len(self.loading_nodes) - 1) * 2))
191
+
192
+ for p in range(0, len(self.loading_nodes) - 1):
193
+ npa = self.loading_nodes[p]
194
+ npe = self.loading_nodes[p + 1]
195
+
196
+ self.node_store_vec[p * 2] = npa
197
+ self.node_store_vec[p * 2 + 1] = npe
198
+
199
+ x_npa = self.mesh_data.get_coordinate_x(npa)
200
+ z_npa = self.mesh_data.get_coordinate_z(npa)
201
+ x_npe = self.mesh_data.get_coordinate_x(npe)
202
+ z_npe = self.mesh_data.get_coordinate_z(npa)
203
+
204
+ l_x = abs(x_npe - x_npa)
205
+ l_z = abs(z_npe - z_npa)
206
+
207
+ px = self.loading_table[self.loading_table["type"] == "top"][
208
+ "px"
209
+ ].values
210
+ pz = self.loading_table[self.loading_table["type"] == "top"][
211
+ "pz"
212
+ ].values
213
+
214
+ # Numerical integration of the load vector at each node with an loadings
215
+
216
+ eta = 1 # At the top boundary, the eta value is 1 for all loops
217
+ WP = 1 # Numerical integration with 2 Gauss Points
218
+ for x in range(0, 2, 1):
219
+ xi = -1 / np.sqrt(3) + 1 / np.sqrt(3) * 2 * x
220
+ self.N_nat(xi, eta)
221
+
222
+ self.p_a_x = (
223
+ self.result_N[0][6] * px
224
+ ) # The beginning node is always form-function N4
225
+ self.p_a_z = self.result_N[1][7] * pz
226
+ self.p_e_x = self.result_N[0][4] * px
227
+ self.p_e_z = self.result_N[1][5] * pz
228
+
229
+ self.node_loading_vec[0][p * 2] += self.p_a_x * l_x / 2
230
+ self.node_loading_vec[1][p * 2] += self.p_a_z * l_x / 2
231
+
232
+ self.node_loading_vec[0][p * 2 + 1] += self.p_e_x * l_x / 2
233
+ self.node_loading_vec[1][p * 2 + 1] += self.p_e_z * l_x / 2
234
+ elif i == "bottom":
235
+ self.loading_nodes = self.mesh_data.get_bottom_border_nodes()
236
+ self.node_loading_vec = np.zeros(
237
+ (2, int(len(self.loading_nodes) - 1) * 2)
238
+ )
239
+ self.node_store_vec = np.zeros(int((len(self.loading_nodes) - 1) * 2))
240
+
241
+ for p in range(0, len(self.loading_nodes) - 1):
242
+ npa = self.loading_nodes[p]
243
+ npe = self.loading_nodes[p + 1]
244
+
245
+ self.node_store_vec[p * 2] = npa
246
+ self.node_store_vec[p * 2 + 1] = npe
247
+
248
+ x_npa = self.mesh_data.get_coordinate_x(npa)
249
+ z_npa = self.mesh_data.get_coordinate_z(npa)
250
+ x_npe = self.mesh_data.get_coordinate_x(npe)
251
+ z_npe = self.mesh_data.get_coordinate_z(npa)
252
+
253
+ l_x = abs(x_npe - x_npa)
254
+ l_z = abs(z_npe - z_npa)
255
+
256
+ px = self.loading_table[self.loading_table["type"] == "bottom"][
257
+ "px"
258
+ ].values
259
+ pz = self.loading_table[self.loading_table["type"] == "bottom"][
260
+ "pz"
261
+ ].values
262
+
263
+ # Numerical integration of the load vector at each node with an loadings
264
+
265
+ eta = 1 # At the top boundary, the eta value is 1 for all loops
266
+ WP = 1 # Numerical integration with 2 Gauss Points
267
+ for x in range(0, 2, 1):
268
+ xi = -1 / np.sqrt(3) + 1 / np.sqrt(3) * 2 * x
269
+ self.N_nat(xi, eta)
270
+
271
+ self.p_a_x = (
272
+ self.result_N[0][6] * px
273
+ ) # The beginning node is always form-function N4
274
+ self.p_a_z = self.result_N[1][7] * pz
275
+ self.p_e_x = self.result_N[0][4] * px
276
+ self.p_e_z = self.result_N[1][5] * pz
277
+
278
+ self.node_loading_vec[0][p * 2] += self.p_a_x * l_x / 2
279
+ self.node_loading_vec[1][p * 2] += self.p_a_z * l_x / 2
280
+
281
+ self.node_loading_vec[0][p * 2 + 1] += self.p_e_x * l_x / 2
282
+ self.node_loading_vec[1][p * 2 + 1] += self.p_e_z * l_x / 2
283
+
284
+
285
+
286
+ if i == "selfweight":
287
+ """_summary_
288
+
289
+ Note on the Jacobian: The Determinant is needed before the element load vector \n
290
+ from self weight can be calculated. Because it remains constant for all calculations, there is not need to calculate it \n
291
+ in each iteration \n
292
+ """
293
+ self.q_self = np.zeros(8)
294
+ self.q_self[1:9:2] = self._gamma * self._t
295
+
296
+ WP_xi = 1 # Numerical integration with 2 Gauss Points
297
+ WP_eta = 1 # Numerical integration with 2 Gauss Points
298
+
299
+ for x in range(0, 2, 1):
300
+ xi = -1 / np.sqrt(3) + 1 / np.sqrt(3) * 2 * x
301
+ for y in range(0, 2, 1):
302
+ eta = -1 / np.sqrt(3) + 1 / np.sqrt(3) * 2 * y
303
+
304
+ self.N_nat(xi, eta)
305
+
306
+ self.element_loading_vec[1] += (
307
+ self.q_self[1]
308
+ * self.result_N[0][0]
309
+ * self.det_J
310
+ * WP_xi
311
+ * WP_eta
312
+ )
313
+ self.element_loading_vec[3] += (
314
+ self.q_self[3]
315
+ * self.result_N[0][2]
316
+ * self.det_J
317
+ * WP_xi
318
+ * WP_eta
319
+ )
320
+ self.element_loading_vec[5] += (
321
+ self.q_self[5]
322
+ * self.result_N[0][4]
323
+ * self.det_J
324
+ * WP_xi
325
+ * WP_eta
326
+ )
327
+ self.element_loading_vec[7] += (
328
+ self.q_self[7]
329
+ * self.result_N[0][6]
330
+ * self.det_J
331
+ * WP_xi
332
+ * WP_eta
333
+ )
334
+
335
+ def __str__(self):
336
+ output = "NODAL COORDINATES\n"
337
+ output += "\n".join(
338
+ " ".join(str(self._coords_T[i][j]) for j in range(len(self._coords_T[0])))
339
+ for i in range(len(self._coords_T))
340
+ )
341
+
342
+ output += "\ngrad\n"
343
+ output += "\n".join(
344
+ " ".join(str(self.grad[i][j]) for j in range(len(self.grad[0])))
345
+ for i in range(len(self.grad))
346
+ )
347
+
348
+ output += "\nResult grad T\n"
349
+ output += "\n".join(
350
+ " ".join(
351
+ str(self.result_grad_T[i][j]) for j in range(len(self.result_grad_T[0]))
352
+ )
353
+ for i in range(len(self.result_grad_T))
354
+ )
355
+
356
+ output += "\nStiffness matrix K\n"
357
+ output += "\n".join(
358
+ " ".join(str(self.K[i][j]) for j in range(len(self.K[0])))
359
+ for i in range(len(self.K))
360
+ )
361
+
362
+ return output