@@ -37,8 +37,6 @@ import Meshes
3737import GeoIO
3838import Rotations: RotX, RotY, RotZ
3939
40- # import CUDA # Uncomment this to use GPU (if available)
41-
4240
4341run_name = " cessna" # Name of this run
4442
@@ -53,20 +51,20 @@ rho = 0.71461 # (kg/m^3) air density at 17300 ft
5351
5452
5553# ----------------- GEOMETRY DESCRIPTION ---------------------------------------
56- meshfile = joinpath(read_path, " cessna.msh" ) # Gmsh file to read
54+ meshfile = " cessna.msh" # Gmsh file to read
5755
5856offset = [0 , 0 , 0 ] # Offset to center the mesh
5957rotation = RotX(0 * pi / 180 ) * RotY(0 * pi / 180 ) * RotX(0 * pi / 180 ) # Rotation to align mesh
6058scaling = 0.3048 # Factor to scale mesh dimensions (ft -> m)
6159
62- # Gmsh files with trailing edges
63- trailingedges = [ # ( Gmsh file, span direction )
64- ( " cessna-TE-leftwing.msh" , [0 , 1 , 0 ]),
65- ( " cessna-TE-rightwing.msh" , [0 , 1 , 0 ]),
66- ( " cessna-TE-leftelevator.msh" , [0 , 1 , 0 ]),
67- ( " cessna-TE-rightelevator.msh" , [0 , 1 , 0 ]),
68- ( " cessna-TE-rudder.msh " , [ 0 , 0 , 1 ] ),
69- ]
60+ trailingedges = [ # Gmsh files with trailing edges
61+ # ( Gmsh file, span sorting function, junction criterion, closed )
62+ ( " cessna-TE-leftwing.msh" , X -> dot(X, [0 , 1 , 0 ]), X -> abs(X[ 2 ]) - 0.67 , false ),
63+ ( " cessna-TE-rightwing.msh" , X -> dot(X, [0 , 1 , 0 ]), X -> abs(X[ 2 ]) - 0.67 , false ),
64+ ( " cessna-TE-leftelevator.msh" , X -> dot(X, [0 , 1 , 0 ]), X -> abs(X[ 2 ]) - 0.23 , false ),
65+ ( " cessna-TE-rightelevator.msh" , X -> dot(X, [0 , 1 , 0 ]), X -> abs(X[ 2 ]) - 0.23 , false ),
66+ ( " cessna-TE-rudder.msh " , X -> dot(X, [ 0 , 0 , 1 ]), X -> X[ 3 ] - 0.65 , false ),
67+ ]
7068
7169flip = true # Whether to flip control points against the direction of normals
7270 # NOTE: use `flip=true` if the normals
@@ -78,6 +76,12 @@ Sref = 16.2344 # (m^2) reference area
7876Xac = [2.815 , 0 , 0.4142 ] # (m) aerodynamic center for
7977 # calculation of moments
8078
79+ # Define function used for reading Gmsh files
80+ meshreader(file) = GeoIO. load(file). geometry
81+
82+ # Format input for `generate_multibody(...)`
83+ meshfiles = [ (" Airframe" , meshfile, flip) ]
84+
8185# ----------------- SOLVER SETTINGS -------------------------------------------
8286
8387# Solver: direct linear solver for open bodies
@@ -88,71 +92,11 @@ bodytype = pnl.RigidWakeBody{pnl.VortexRing, 2}
8892
8993
9094# ----------------- GENERATE BODY ----------------------------------------------
91- # Read Gmsh mesh
92- msh = GeoIO. load(meshfile)
93- msh = msh. geometry
94-
95- # Transform the original mesh: Translate, rotate, and scale
96- msh = msh |> Meshes. Translate(offset... ) |> Meshes. Rotate(rotation) |> Meshes. Scale(scaling)
97-
98- # Wrap Meshes object into a Grid object from GeometricTools
99- grid = pnl. gt. GridTriangleSurface(msh)
100-
101- # Read all trailing edges
102- sheddings = []
103-
104- for (trailingedgefile, spandir) in trailingedges
105-
106- # Read Gmsh line of trailing edge
107- TEmsh = GeoIO. load(joinpath(read_path, trailingedgefile))
108- TEmsh = TEmsh. geometry
109-
110- # Apply the same transformations of the mesh to the trailing edge
111- TEmsh = TEmsh |> Meshes. Translate(offset... ) |> Meshes. Rotate(rotation) |> Meshes. Scale(scaling)
112-
113- # Convert TE Meshes object into a matrix of points used to identify the trailing edge
114- trailingedge = pnl. gt. vertices2nodes(TEmsh. vertices)
115-
116- # Sort TE points from "left" to "right" according to span direction
117- trailingedge = sortslices(trailingedge; dims= 2 , by = X -> pnl. dot(X, spandir))
118-
119- # Function for identifying if a point is close to a junction
120- if trailingedgefile in [" cessna-TE-leftwing.msh" , " cessna-TE-rightwing.msh" ]
121-
122- criterion = X -> abs(X[2 ]) <= 0.67
123-
124- elseif trailingedgefile in [" cessna-TE-leftelevator.msh" , " cessna-TE-rightelevator.msh" ]
125-
126- criterion = X -> abs(X[2 ]) <= 0.23
127-
128- elseif trailingedgefile in [" cessna-TE-rudder.msh" ]
129-
130- criterion = X -> X[3 ] <= 0.65
131-
132- else
133-
134- criterion = X -> false
135-
136- end
137-
138- # Filter out any points that are close to junctions
139- tokeep = filter( i -> ! criterion(trailingedge[:, i]), 1 : size(trailingedge, 2 ) )
140- trailingedge = trailingedge[:, tokeep]
141-
142- # Generate TE shedding matrix
143- shedding = pnl. calc_shedding(grid, trailingedge; tolerance= 0.001 * bref)
144-
145- push!(sheddings, shedding)
146-
147- end
148-
149- # Combine all TE shedding matrices into one
150- shedding = hcat(sheddings... )
151-
152- # Generate paneled body
153- body = bodytype(grid, shedding; CPoffset= (- 1 )^ flip * 1e-14 )
154-
155- println(" Number of panels:\t $(body. ncells) " )
95+ body, elsprescribe = pnl. generate_multibody(bodytype, meshfiles, trailingedges, meshreader;
96+ tolerance= 0.001 * bref,
97+ read_path= read_path,
98+ offset= offset, rotation= rotation, scaling= scaling,
99+ )
156100
157101
158102# ----------------- CALL SOLVER ------------------------------------------------
@@ -171,10 +115,7 @@ Dbs = repeat(Vinf/magVinf, 1, body.nsheddings)
171115
172116# Solve body (panel strengths) giving `Uinfs` as boundary conditions and
173117# `Das` and `Dbs` as trailing edge rigid wake direction
174- @time pnl. solve(body, Uinfs, Das, Dbs)
175-
176- # Uncomment this to use GPU instead (if available)
177- # @time pnl.solve(body, Uinfs, Das, Dbs; GPUArray=CUDA.CuArray{Float32})
118+ @time pnl. solve(body, Uinfs, Das, Dbs; elprescribe= elsprescribe)
178119
179120# ----------------- POST PROCESSING ----------------------------------------
180121println(" Post processing..." )
0 commit comments