8
8
from typing import List , Tuple , Union
9
9
from scipy .sparse import coo_matrix
10
10
import copy
11
-
11
+ from guistatics import GUIStatics
12
12
class CalcFEM :
13
13
14
14
def __init__ (self , params_mesh , params_boundaries_materials ):
@@ -28,6 +28,7 @@ def __init__(self, params_mesh, params_boundaries_materials):
28
28
self .boundary_parameters = params_boundaries_materials [1 ]
29
29
self .node_parameters = params_boundaries_materials [2 ]
30
30
self .calculation_parameters = params_boundaries_materials [3 ]
31
+
31
32
# Instance vars created
32
33
self .all_element_matrices_steif = None
33
34
self .all_element_matrices_mass = None
@@ -38,9 +39,9 @@ def __init__(self, params_mesh, params_boundaries_materials):
38
39
self .sysmatrix_diri = None # Systemmatrix after implementing Dirichlet Cond
39
40
self .force_vector_diri = None # Force Vector after implementing Dirichlet Cond
40
41
self .solution = None
41
-
42
+ self . acoustic_source = None # sources if equation is 'HH'
42
43
# development
43
- self .file_path_dev = r'testing\output_gui_4_calcfem_' + '1 ' + '.txt'
44
+ self .file_path_dev = r'testing\output_gui_4_calcfem_' + '2 ' + '.txt'
44
45
45
46
def develop_print_input (self ):
46
47
print ("\n \n \n ------------------DEBUG--------------------" )
@@ -73,9 +74,9 @@ def calc_fem(self):
73
74
:return:
74
75
"""
75
76
76
-
77
77
# set equation
78
78
self .equation = self .calculation_parameters ['equation' ] # either HE (HeatEquation) or HH (HelmHoltz)
79
+ #self.equation = 'HH' # todo for dev!
79
80
80
81
# calculate element matrices
81
82
self .calc_elementmatrices ()
@@ -86,6 +87,11 @@ def calc_fem(self):
86
87
# create force vector
87
88
self .create_force_vector ()
88
89
90
+ # implement acoustic sources if helmholtz equation
91
+ if self .equation == 'HH' :
92
+ self .calculate_acoustic_sources ()
93
+ self .implement_acoustic_sources ()
94
+
89
95
# implement boundary conditions
90
96
self .implement_boundary_conditions ()
91
97
@@ -96,10 +102,82 @@ def calc_fem(self):
96
102
self .solve_linear_system ()
97
103
98
104
# plot solution
99
- self .plot_solution (self .solution , self .nodes_mesh_gen , self .triangulation )
105
+ # self.plot_solution(self.solution, self.nodes_mesh_gen, self.triangulation)
100
106
101
107
return self .solution
102
108
109
+ def get_region_for_node_nbr (self , node ):
110
+ """
111
+ Gets the region number for a node
112
+ :param node:
113
+ :return:
114
+ """
115
+ for key , val in self .triangulation_region_dict .items ():
116
+ if node in val :
117
+ return key
118
+
119
+ def implement_acoustic_sources (self ):
120
+ """
121
+ Implements acoustic source, if any, into force vector for calculation Helmholtz equation
122
+ :return:
123
+ """
124
+ for pos , val in self .acoustic_source :
125
+ self .force_vector [pos ] = self .force_vector [pos ] + val
126
+
127
+
128
+
129
+ def calculate_acoustic_sources (self ):
130
+ """
131
+ calculates acoustic source values
132
+ :return:
133
+ """
134
+
135
+ freq = float (self .calculation_parameters ['freq' ])
136
+ omega = freq * 2 * math .pi
137
+
138
+ self .acoustic_source = list ()
139
+ for node_nbr , vals in self .node_parameters .items ():
140
+ val_bc = vals ['bc' ]['value' ]
141
+ if val_bc :
142
+ node_pos = self .single_nodes_dict [node_nbr ]
143
+ region_nbr = self .get_region_for_node_nbr (node_pos )
144
+ rho = self .region_parameters [region_nbr ]['material' ]['rho' ]
145
+ mpsource = 4 * math .pi / rho * ((2 * rho * omega ) / ((2 * math .pi ) ** 2 )) ** 0.5
146
+ self .acoustic_source .append ([node_pos , mpsource ])
147
+
148
+
149
+
150
+ def plot_solution_dev (self ):
151
+ """
152
+ Plots the solution via matplotlib
153
+ """
154
+ solution = self .solution
155
+ all_points = self .nodes_mesh_gen
156
+ triangles = self .triangulation
157
+
158
+ dataz = np .real (solution )
159
+ values = dataz
160
+ aspectxy = 1
161
+ triang_mpl = tri .Triangulation (all_points [:, 0 ], all_points [:, 1 ], triangles )
162
+
163
+ fig , ax = plt .subplots (figsize = (12 , 8 ))
164
+
165
+ units = self .calculation_parameters ['units' ]
166
+ ax .set_title ('solution' )
167
+ ax .set_xlabel (f"x [{ units } ]" )
168
+ ax .set_ylabel (f"y [{ units } ]" )
169
+ ax .set_aspect (aspectxy )
170
+
171
+ contour = ax .tricontourf (triang_mpl , values , cmap = 'viridis' , levels = 20 )
172
+ divider = make_axes_locatable (ax )
173
+ cax = divider .append_axes ("right" , size = "5%" , pad = 0.2 )
174
+ cbar = fig .colorbar (contour , cax = cax )
175
+
176
+ ax .scatter (all_points [:, 0 ], all_points [:, 1 ], c = values , cmap = 'viridis' , marker = '.' ,
177
+ edgecolors = 'w' , s = 10 )
178
+ ax .triplot (triang_mpl , 'w-' , linewidth = 0.1 )
179
+
180
+ plt .show ()
103
181
104
182
@staticmethod
105
183
def plot_solution (solution , all_points , triangles ):
@@ -144,6 +222,7 @@ def implement_boundary_conditions(self):
144
222
145
223
# create dirichlet list for implementation of dirichlet boundary conditions
146
224
dirichlet_dict = dict ()
225
+ print (self .boundary_parameters )
147
226
for boundary_nbr , params in self .boundary_parameters .items ():
148
227
bc = params ['bc' ]
149
228
bc_type = bc ['type' ]
@@ -158,8 +237,10 @@ def implement_boundary_conditions(self):
158
237
dirichlet_dict [node ] = bc_value
159
238
dirichlet_list = np .array ([[key , val ] for key , val in dirichlet_dict .items ()])
160
239
161
- self .sysmatrix_diri , self .force_vector_diri = self .implement_dirichlet_condition (dirichlet_list , self .sysarray , self .force_vector )
162
-
240
+ if dirichlet_list :
241
+ self .sysmatrix_diri , self .force_vector_diri = self .implement_dirichlet_condition (dirichlet_list , self .sysarray , self .force_vector )
242
+ else :
243
+ self .sysmatrix_diri , self .force_vector_diri = self .sysarray , self .force_vector
163
244
164
245
@staticmethod
165
246
def implement_dirichlet_condition (dirichlet_list : np .array , system_matrix : np .array , force_vector : np .array ):
@@ -226,7 +307,9 @@ def calc_system_matrices(self):
226
307
if self .equation == 'HE' :
227
308
self .sysarray = self .syssteifarray
228
309
elif self .equation == 'HH' : # todo: include in elementmatrices
229
- ...
310
+ freq = float (self .calculation_parameters ['freq' ])
311
+ omega = freq * 2 * math .pi
312
+ self .sysarray = self .syssteifarray - omega ** 2 * self .sysmassarray
230
313
231
314
232
315
def calc_elementmatrices (self ):
@@ -314,6 +397,8 @@ def print_matrix(matrix: Union[np.array, list]):
314
397
if __name__ == '__main__' :
315
398
calcfem = CalcFEM ((0 ,0 ,0 ,0 ,0 ), (0 ,0 ,0 ,0 )) # Develop
316
399
calcfem .develop () # read date via exec(!)
400
+ calcfem .calc_fem ()
401
+ calcfem .plot_solution_dev ()
317
402
# calcfem.nodes_mesh_gen = [[0.5, 0.5], [0., 0. ], [0.5, 0. ], [1., 0. ], [1., 0.5], [1., 1. ], [0.5, 1. ], [0., 1. ], [0., 0.5], [1., 1.5], [1., 2. ], [0.5, 1.5]]
318
403
# calcfem.single_nodes_dict = {'0': 1, '1': 3, '2': 5, '3': 7, '4': 10}
319
404
# calcfem.boundary_nodes_dict = {'0': [[1, np.array([0., 0.])], [2, np.array([0.5, 0. ])], [3, np.array([1., 0.])]], '1': [[3, np.array([1., 0.])], [4, np.array([1. , 0.5])], [5, np.array([1., 1.])]], '2': [[5, np.array([1., 1.])], [6, np.array([0.5, 1. ])], [7, np.array([0., 1.])]], '3': [[7, np.array([0., 1.])], [8, np.array([0. , 0.5])], [1, np.array([0., 0.])]], '4': [[5, np.array([1., 1.])], [9, np.array([1. , 1.5])], [10, np.array([1., 2.])]], '5': [[10, np.array([1., 2.])], [11, np.array([0.5, 1.5])], [7, np.array([0., 1.])]]}
@@ -341,4 +426,3 @@ def print_matrix(matrix: Union[np.array, list]):
341
426
# '5': {'coordinates': (1.0, 2.0), 'bc': {'type': None, 'value': None}}}
342
427
# calcfem.calculation_parameters = {'mesh_density': 1, 'freq': None, 'equation': 'HE'}
343
428
344
- calcfem .calc_fem ()
0 commit comments