Mesh10#

Simplified turbine mesh with data extraction in matlab.

Mesh10
Mesh10
============= Init GMSH interface =============
Link contours (55.733 ms)
Link contours (36.718 ms)
Link contours (45.157 ms)
Link contours (45.753 ms)
Link contours (63.360 ms)
Link contours (59.716 ms)
Link contours (62.979 ms)
Link contours (60.912 ms)
Link contours (51.439 ms)
Link contours (51.850 ms)
Meshing with gmsh (13.261 ms)
Saving .msh (6.070 ms)
Construct mesh object (1.545 ms)

Element type: PRISM6
Ne = 512, Nn = 539

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

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

Gallery generated by Sphinx-Gallery