Mesh10#

Simplified turbine mesh with data extraction in matlab.

Mesh10
Mesh10
============= Init GMSH interface =============
Link contours (50.154 ms)
Link contours (33.746 ms)
Link contours (42.479 ms)
Link contours (41.912 ms)
Link contours (58.277 ms)
Link contours (55.054 ms)
Link contours (58.174 ms)
Link contours (56.756 ms)
Link contours (47.306 ms)
Link contours (47.337 ms)
Meshing with gmsh (12.907 ms)
Saving .msh (5.761 ms)
Construct mesh object (2.882 ms)

Element type: PRISM6
Ne = 512, Nn = 539

 13 import matplotlib.pyplot as plt
 14 import numpy as np
 15
 16 from EasyFEA import Display, Folder, Mesher, ElemType, PyVista
 17 from EasyFEA.Geoms import Point, Points, Contour, CircleArc, Line
 18
 19 import scipy.io
 20
 21 if __name__ == "__main__":
 22     Display.Clear()
 23
 24     # ----------------------------------------------
 25     # Contour
 26     # ----------------------------------------------
 27
 28     # outputs
 29     folder = Folder.Results_Dir()
 30     addCylinder = True
 31     repeat = False
 32
 33     # geom
 34     angleRev = 2 * np.pi / 20  # rad
 35     saveToMatlab = False
 36
 37     # mesh
 38     N = 4  # elements in the blade lenght l
 39     elemType = ElemType.PRISM6
 40     mesher = Mesher(False, True, True)
 41     factory = mesher._factory
 42
 43     # ----------------------------------------------
 44     # Geom
 45     # ----------------------------------------------
 46
 47     l = 2
 48     t = 0.3
 49     H1 = 5
 50     c1 = 1
 51     H2 = 5
 52     c2 = 2
 53     H3 = 5
 54     c3 = 2
 55     R = 5
 56     e = 1
 57
 58     rot = 15
 59     coefRot = rot / (H1 + H2 + H3)  # deg
 60     rot0 = 0
 61     rot1 = H1 * coefRot
 62     rot2 = (H1 + H2) * coefRot - rot1
 63     rot3 = (H1 + H2 + H3) * coefRot - rot2
 64     assert t < R
 65
 66     mS = l / N
 67
 68     vols: list[tuple[Contour, Contour]] = []
 69
 70     def bladeSection(l: float, t: float, center: np.ndarray, angle=0.0, R: float = 0.0):
 71         """Create a blade section
 72
 73         Parameters
 74         ----------
 75         l : float
 76             blade length
 77         t : float
 78             blade thickness
 79         center : np.ndarray
 80             center of mass for the blade section
 81         angle : float, optional
 82             rotation in deg along z axis (0,0,1), by default 0.0
 83         R : float, optional
 84             radius used to project on the cylinder, by default 0.0
 85
 86         Returns
 87         -------
 88         Contour
 89             created contour
 90         """
 91
 92         # crete points coordinates
 93         n = 11
 94         y = np.linspace(0, l, n)
 95         y = np.append(y, y[::-1])
 96
 97         mat = np.array([[0, 0, 1], [(l / 2) ** 2, l / 2, 1], [l**2, l, 1]])
 98         a, b, c = tuple(np.linalg.inv(mat) @ [0, -t / 2, 0])
 99         x: np.ndarray = a * y**2 + b * y + c
100
101         x[y.size // 2 :] *= -1
102
103         z = np.zeros_like(y)
104
105         coord = np.array([x, y, z]).T
106
107         # first center the surface on (0,0,0) to do the rotation
108         coord = coord - np.array([0, l / 2, 0])
109
110         # rotate along z axis
111         rot = angle * np.pi / 180
112         rotMat = np.array(
113             [[np.cos(rot), -np.sin(rot), 0], [np.sin(rot), np.cos(rot), 0], [0, 0, 1]]
114         )
115         coord = coord @ rotMat
116
117         # project on R radius the z coordinates
118         if R != 0:
119             coord[:, 2] = -(R - np.sqrt(R**2 - coord[:, 0] ** 2))
120
121         # center the surface
122         coord += center
123
124         # create points
125         points = [Point(*co) for co in coord]
126
127         # split points in 4 groups to construct 4 points list
128         split1, split2 = np.reshape(points, (2, -1))
129
130         idxM = len(split1) // 2
131         spline1 = Points(split1[: idxM + 1], mS)
132         spline2 = Points(split1[idxM:], mS)
133         spline3 = Points(split2[: idxM + 1], mS)
134         spline4 = Points(split2[idxM:], mS)
135
136         # construct contour
137         contour = Contour([spline1, spline2, spline3, spline4])
138
139         # contour.Plot()
140
141         return contour, np.asarray(coord)
142
143     def Cylinder(
144         R, angleRev: float, coord: np.ndarray, y1: float
145     ) -> tuple[Contour, Contour]:
146         s = np.sin(angleRev / 2)
147         c = np.cos(angleRev / 2)
148
149         P1 = Point(-s * R, coord[0, 1], c * R)
150         P2 = Point(*coord[0])
151         P3 = Point(s * R, P2.y, c * R)
152         P4 = Point(s * R, y1, c * R)
153         P5 = Point(P2.x, y1, P2.z)
154         P6 = Point(-s * R, y1, c * R)
155
156         C1 = Point(y=P2.y)
157         C2 = Point(y=y1)
158
159         L1_l = CircleArc(P1, P2, C1, meshSize=mS)
160         L2_l = Line(P2, P5, mS)
161         L3_l = CircleArc(P5, P6, C2, meshSize=mS)
162         L4_l = Line(P6, P1, mS)
163
164         contour_l = Contour([L1_l, L2_l, L3_l, L4_l])
165
166         L1_r = CircleArc(P2, P3, C1, meshSize=mS)
167         L2_r = Line(P3, P4, mS)
168         L3_r = CircleArc(P4, P5, C2, meshSize=mS)
169         L4_r = Line(P5, P2, mS)
170
171         contour_r = Contour([L1_r, L2_r, L3_r, L4_r])
172
173         return contour_l, contour_r
174
175     def CylinderBlade(R, angleRev: float, coord: np.ndarray) -> Contour:
176         s = np.sin(angleRev / 2)
177         c = np.cos(angleRev / 2)
178
179         y0 = coord[0, 1]
180         y1 = coord[-1, 1]
181
182         P1 = Point(-s * R, y0, c * R)
183         P2 = Point(*coord[0])
184         P3 = Point(*coord[-1])
185         P4 = Point(-s * R, y1, c * R)
186
187         C1 = Point(0, y0, 0)
188         C2 = Point(0, y1, 0)
189
190         L1 = CircleArc(P1, P2, C1, meshSize=mS)
191         L2 = Points([Point(*co) for co in coord], mS)
192         L3 = CircleArc(P3, P4, C2, meshSize=mS)
193         L4 = Line(P4, P1, mS)
194
195         contour = Contour([L1, L2, L3, L4])
196
197         return contour
198
199     def LinkEveryone(
200         vols: list[tuple[Contour, Contour, list[int]]], rot=0.0
201     ) -> list[tuple]:
202         """contour1, contour2, nLayers, numElems
203         return created entities"""
204         allEntities = []
205         for vol in vols:
206             contour1, contour2, nLayers, numElems = vol
207             contour1 = contour1.copy()
208             contour1.Rotate(rot, direction=(0, 1, 0))
209             contour2 = contour2.copy()
210             contour2.Rotate(rot, direction=(0, 1, 0))
211             ents = mesher._Link_Contours(
212                 contour1, contour2, elemType, nLayers, numElems
213             )
214
215             allEntities.extend(ents)
216
217         return allEntities
218
219     # ----------------------------------------------
220     # Mesh
221     # ----------------------------------------------
222
223     bladeInf, coordInf = bladeSection(l, t, (0, 0, R), rot0, R)  # blade in z = R
224     bladeSup, coordSup = bladeSection(
225         l, t, (0, 0, R + e), rot0, R + e
226     )  # blade in z = R+e
227
228     coordInfL, coordInfR = np.reshape(coordInf, (2, -1, 3))
229     coordSupL, coordSupR = np.reshape(coordSup, (2, -1, 3))
230
231     blade1, __ = bladeSection(l * c1, t, (0, -(c1 * l - l) / 2, R + e + H1), rot1)
232     blade2, __ = bladeSection(l * c2, t, (0, -(c2 * l - l) / 2, R + e + H1 + H2), rot2)
233     blade3, __ = bladeSection(
234         l * c3, t, (0, -(c3 * l - l) / 2, R + e + H1 + H2 + H3), rot3
235     )
236
237     elems = [N / 2] * 4  # number of elements for each lines for blades
238
239     # contour1, contour2, nLayers, numElems
240     vols.append((bladeInf, bladeSup, e / mS, elems))
241     vols.append((bladeSup, blade1, H1 / mS, elems))
242     vols.append((blade1, blade2, H2 / mS, elems))
243     vols.append((blade2, blade3, H3 / mS, elems))
244
245     if addCylinder:
246         elems = [N, l / 2 / mS] * 2
247
248         # cylinder y=-l
249         cylinInf1_l, cylinInf1_r = Cylinder(R, angleRev, coordInfL, -l)
250         cylinSup1_l, cylinSup1_r = Cylinder(R + e, angleRev, coordSupL, -l)
251
252         vols.append((cylinInf1_l, cylinSup1_l, e / mS, elems))
253         vols.append((cylinInf1_r, cylinSup1_r, e / mS, elems))
254
255         # cylinder y=l
256         cylinInf2_l, cylinInf2_r = Cylinder(R, angleRev, coordInfR, l)
257         cylinSup2_l, cylinSup2_r = Cylinder(R + e, angleRev, coordSupR, l)
258         vols.append((cylinInf2_l, cylinSup2_l, e / mS, elems))
259         vols.append((cylinInf2_r, cylinSup2_r, e / mS, elems))
260
261         elems = [N] * 4
262         # cylinder blade left
263         coordInfL = coordInf[: coordInf.shape[0] // 2]
264         coordSupfL = coordSup[: coordSup.shape[0] // 2]
265         contourInf = CylinderBlade(R, angleRev, coordInfL)
266         contourSup = CylinderBlade(R + e, angleRev, coordSupfL)
267
268         # cylinder blade right
269         coordInfR = coordInf[coordInf.shape[0] // 2 :]
270         coordSupfR = coordSup[coordSup.shape[0] // 2 :]
271         contourInf_c = CylinderBlade(R, -angleRev, coordInfR[::-1])
272         contourSup_c = CylinderBlade(R + e, -angleRev, coordSupfR[::-1])
273
274         vols.append((contourInf, contourSup, e / mS, elems))
275         vols.append((contourInf_c, contourSup_c, e / mS, elems))
276
277     # axGeom = Display.init_Axes(3)
278     # axGeom.axis('off')
279     # for v, vol in enumerate(vols):
280     #     color = 'blue'
281     #     vol[0].Plot(axGeom, color=color)
282     #     vol[1].Plot(axGeom, color=color)
283     #     # ax.legend()
284
285     firstPart = LinkEveryone(vols)
286
287     mesher._Set_mesh_algorithm(elemType)
288
289     # mesher._synchronize()
290     # parts = factory.getEntities()
291
292     if repeat:
293         na = int(np.pi * 2 / angleRev)
294
295         for i in range(na - 1):
296             print(f"{(i + 1) / (na - 1) * 100:2.0f} %")
297             LinkEveryone(vols, angleRev * (i + 1) * 180 / np.pi)
298
299             # # dont work
300             # partsC = factory.copy(parts)
301             # factory.rotate(partsC, 0,0,0,0,0,1, angleRev*(i+1))
302
303     mesher._Mesh_Generate(3, elemType, folder=folder, filename="blade")
304
305     mesh = mesher._Mesh_Get_Mesh()
306
307     nodesCircle = mesh.Nodes_Conditions(
308         lambda x, y, z: np.sqrt(x**2 + z**2) <= R + 1e-2
309     )
310     nodesUpper = mesh.Nodes_Conditions(
311         lambda x, y, z: z >= mesh.coord[:, 2].max() - 1e-2
312     )
313
314     nodesBlades = mesh.Nodes_Conditions(
315         lambda x, y, z: np.sqrt(x**2 + z**2) >= R + e + 1e-1
316     )
317     nodesCyl = mesh.Nodes_Conditions(lambda x, y, z: np.sqrt(x**2 + z**2) <= R + e)
318
319     mesh.Set_Tag(nodesCircle, "blades")
320     mesh.Set_Tag(nodesCyl, "cylindre")
321
322     if saveToMatlab:
323         matFile = Folder.Join(folder, "blade.mat")
324         msh = {
325             "connect": np.asarray(mesh.connect + 1, dtype=float),
326             "coord": mesh.coord,
327             "bladesNodes": np.asarray(nodesBlades + 1, dtype=float),
328             "bladesElems": np.asarray(
329                 mesh.Elements_Nodes(nodesBlades) + 1, dtype=float
330             ),
331             "cylindreNodes": np.asarray(nodesCyl + 1, dtype=float),
332             "cylindreElems": np.asarray(mesh.Elements_Nodes(nodesCyl) + 1, dtype=float),
333         }
334         scipy.io.savemat(matFile, msh)
335
336     # ----------------------------------------------
337     # Plot
338     # ----------------------------------------------
339
340     PyVista.Plot_Mesh(mesh).show()
341
342     qual = mesh.Get_Quality("aspect")
343     PyVista.Plot(
344         mesh,
345         qual,
346         nodeValues=False,
347         plotMesh=True,
348         cmap="viridis",
349         clim=(0, 1),
350         nColors=11,
351     ).show()
352
353     plt.show()

Total running time of the script: (0 minutes 0.890 seconds)

Gallery generated by Sphinx-Gallery