Preprocessor
The APM Preprocessor reads the mesh of the body and assigns a type to each element. The mesh must satisfy the following requirements:
  • The mesh must be watertight
  • The surface normals of the body must point outward i.e. into the flow
  • If the mesh includes a wake, the wake normals should point in the negative z-direction
  • The mesh must be in a body-fixed coordinate system i.e. the x-axis must point forward, the y-axis must point to the right wing and the z-axis must point down
More information about the format of the mesh file is available in the mesh file section. The image below shows an unstructured mesh of a fixed-wing UAV.
Unstructured mesh of a fixed-wing UAV
The mesh should be in a body-fixed coordinate system, should be watertight and the mesh normals should point outward i.e. into the flow.
After running the APM Preprocessor each element of the mesh is assigned a type. A list of the element types is given in the table below.
Type
Description
1
Body element
2
Upper trailing edge element (normal points in negative z-direction)
3
Lower trailing edge element (normal points in positive z-direction)
4
Upper intersection edge element (at locations where the wake elements intersect the body elements)
5
Lower intersection edge element (at locations where the wake elements intersect the body elements)
6
Element belonging to a flat surface (wing tip, tail tip, fuselage boom base, etc.)
The image below shows the element types for the fixed-wing UAV.
Element types of the fixed-wing UAV.
To find trailing edge elements the APM Preprocessor compares the angle between the normals of two adjacent elements to the trailing_edge_angle option in the .conf file. If the angle is greater than the one specified by the trailing_edge_angle option the elements are marked as trailing edge elements. Trailing edge elements are used by the APM Solver to enforce the Kutta condition. If the mesh contains a wake, as in the fixed-wing UAV example, the APM Preprocessor will find all elements which have more than 3 neighbours. Such elements exist along the trailing edges and at the location where the wake meets the body. Elements belonging to flat surfaces (e.g the wing and tail tips and the fuselage base) should be type 6. The APM Preprocessor is unable to detect type 6 elements automatically. You need to manually specify elements of type 6. For the fixed-wing UAV example, the elements at the fuselage base must be type 6. To set the type of all elements belonging to the base you need to determine the identifier (ID) of at least one element belonging to the base. You can easily determine the identifier by opening the .stl file in a data analysis and visualization application such as ParaView.
Run the APM Preprocessor without specifying identifiers for type 6 elements. Open the created .vtu or .dat files and find the identifier of at least one element belonging to a flat surface. Add the identifier to the tip_panels option in the .conf file and re-run the APM Preprocessor.
After you obtain the identifier of at least one element belonging to the base, add it to the tip_panels option in the .conf file. You can add multiple identifiers if you have multiple flat surface in your model. Make sure the identifiers are separated by a comma.
tip_panels = id1,id2,id3...
After the APM Preprocessor runs it will create a .mdl file. The format for the .mdl file is specific to the Aviumtechnologies Panel Method and contains the element vertices, types, and neighbours. The APM Solver uses the .mdl file to solve for the potential flow around the body.

clear all;
close all;
clc;
structured=0;
model=dlmread('<model>.mdl');
N_vertices=model(1,1);
N_faces=model(1,2);
model=model(2:end,:);
for i=1:N_vertices
vertices(i,1)=model(i,1);
vertices(i,2)=model(i,2);
vertices(i,3)=model(i,3);
end
model=model((N_vertices+1):end,:);
for i=1:N_faces
faces(i,1)=model(i,1)+1;
faces(i,2)=model(i,2)+1;
faces(i,3)=model(i,3)+1;
if structured == 1
faces(i,4)=model(i,4)+1;
end
r1=vertices(faces(i,1),:)';
r2=vertices(faces(i,2),:)';
r3=vertices(faces(i,3),:)';
if structured == 1
r4=vertices(faces(i,4),:)';
end
if structured == 1
r=1/4*(r1+r2+r3+r4);
n=cross(r3-r1,r4-r2);
else
r=1/3*(r1+r2+r3);
n=cross(r2-r1,r3-r1);
end
n=n/norm(n);
centres(i,1)=r(1);
centres(i,2)=r(2);
centres(i,3)=r(3);
normals(i,1)=n(1);
normals(i,2)=n(2);
normals(i,3)=n(3);
end
model=model((N_faces+1):end,:);
for i=1:N_faces
types(i,1)=model(i,1);
end
figure(1);
hold on;
patch('Faces',faces,'Vertices',vertices,'FaceVertexCdata',types,'FaceColor','flat','EdgeColor',[0,0,0]/255,'Clipping','off');
quiver3(centres(:,1),centres(:,2),centres(:,3),normals(:,1),normals(:,2),normals(:,3),1,'Color',[0 143 255]/255,'Clipping','off');
grid on;
axis equal;
axis off;
rotate3d on;
set(gca,'Zdir','reverse');
set(gca,'Ydir','reverse');
colormap(jet);
colorbar;
camproj('perspective');
view([135,25]);
drawnow;
Copy link