Я реализовал 4D интерполяцию в Matlab, где производительность действительно важна. Метод интерполяции - это интерполяция ближайшего соседа, основанная на триангуляции Делоне. Поскольку я новичок в кодировании Matlab, я хочу спросить, стоит ли мне использовать массивы или ячейки вместо таблиц из-за их низкой производительности. Также общий вопрос, если вы видите что-нибудь, где я могу ускорить мой код. Я уже сохранил файлы матов в v6, так что это не вариант. Под текстом вы видите код основной программы. После этого код для 2D-интерполяции. загруженные таблицы состоят из 7 столбцов, заполненных AeroDataId, координатой X_ C, CP (производной давления), числом Маха, коэффициентом подъема, номером Рейнольдса и переходом. Один AeroDataId принадлежит в большинстве случаев 280 x_ c координат с различными коэффициентами давления. Фильтрация всех данных выглядит быстрее, чем использование sql запросов.
clc
close
clear
%% ReynoldsNumbers and Transitions known in the database
ReynoldsNumbers=[1e6;1.5e6;2.5e6;5e6;8e6;14e6;25e6;50e6;100e6];
Transition=[0;0.1;0.2;0.3;0.4;0.5;0.6;0.7;0.8;0.9];
%% parameters
Ma=0.85;
C_l=0.345;
Tl=0.15;
Re=55e6;
AirfoilId=0;
delta=0.015;
delta_ini=0.15;
%% try to find the neighbours of the parameters, which already exist in the database
tic
Re_u=ReynoldsNumbers(ReynoldsNumbers==Re);
Tl_u=Transition(Transition==Tl);
Tl_o=[];
Re_o=[];
if isempty(Re_u)
Re_u_index=nearestpoint(Re,ReynoldsNumbers,'previous');
Re_o_index=nearestpoint(Re,ReynoldsNumbers,'next');
Re_o=ReynoldsNumbers(Re_o_index);
Re_u=ReynoldsNumbers(Re_u_index);
if Re < 1e6
Re_u=1e6;
Re_o=1.5e6;
elseif Re > 100e6
Re_u=50e6;
Re_o=100e6;
end
end
if isempty(Tl_u)
Tl_u_index=nearestpoint(Tl,Transition,'previous');
Tl_o_index=nearestpoint(Tl,Transition,'next');
Tl_u=Transition(Tl_u_index);
Tl_o=Transition(Tl_o_index);
end
toc
%% load data based on the airfoilId size of new_upper_airfoil 25000000x7 table
if AirfoilId==0
load('new_upper_airfoil_all_0');
load('new_lower_airfoil_all_0');
elseif AirfoilId==1
load('new_upper_airfoil_all_1');
load('new_lower_airfoil_all_1');
elseif AirfoilId==2
load('new_upper_airfoil_all_2');
load('new_lower_airfoil_all_2');
end
%% no need to to make all the interpolation with the whole data, only a specific delta
new_upper_airfoil=new_upper_airfoil_all(new_upper_airfoil_all.Ma < (Ma+delta_ini) & new_upper_airfoil_all.Ma > (Ma-delta_ini) & new_upper_airfoil_all.CL_res < (C_l+delta_ini) & new_upper_airfoil_all.CL_res > (C_l-delta_ini),2:7);
new_lower_airfoil=new_lower_airfoil_all(new_lower_airfoil_all.Ma < (Ma+delta_ini) & new_lower_airfoil_all.Ma > (Ma-delta_ini) & new_lower_airfoil_all.CL_res < (C_l+delta_ini) & new_lower_airfoil_all.CL_res > (C_l-delta_ini),2:7);
%% filter data for the first 2D - Interpoaltion and execute it
new_upper_airfoil1=new_upper_airfoil(new_upper_airfoil.ReynoldsNumber==Re_u & new_upper_airfoil.Transition==Tl_u,1:4);
new_lower_airfoil1=new_lower_airfoil(new_lower_airfoil.ReynoldsNumber==Re_u & new_lower_airfoil.Transition==Tl_u,1:4);
DV1=delaunay_nearest(new_upper_airfoil1, new_lower_airfoil1, Ma, C_l, delta);
DV_1=table(DV1.X_C, DV1.CP, repmat(Re_u,280,1),repmat(Tl_u,280,1),'VariableNames',{'X_C','CP','Re','Tl'});
%% secound
if ~isempty(Tl_o)
new_upper_airfoil2=new_upper_airfoil(new_upper_airfoil.ReynoldsNumber==Re_u & new_upper_airfoil.Transition==Tl_o,1:4);
new_lower_airfoil2=new_lower_airfoil(new_lower_airfoil.ReynoldsNumber==Re_u & new_lower_airfoil.Transition==Tl_o,1:4);
DV2=delaunay_nearest(new_upper_airfoil2, new_lower_airfoil2, Ma, C_l, delta);
DV_2=table(DV2.X_C, DV2.CP, repmat(Re_u,280,1), repmat(Tl_o,280,1),'VariableNames',{'X_C','CP','Re','Tl'});
else
DV_2=[];
end
%% third
if ~isempty(Re_o)
new_upper_airfoil3=new_upper_airfoil(new_upper_airfoil.ReynoldsNumber==Re_o & new_upper_airfoil.Transition==Tl_u,1:4);
new_lower_airfoil3=new_lower_airfoil(new_lower_airfoil.ReynoldsNumber==Re_o & new_lower_airfoil.Transition==Tl_u,1:4);
DV3=delaunay_nearest(new_upper_airfoil3, new_lower_airfoil3, Ma, C_l, delta);
DV_3=table(DV3.X_C, DV3.CP, repmat(Re_o,280,1),repmat(Tl_u,280,1),'VariableNames',{'X_C','CP','Re','Tl'});
else
DV_3=[];
end
%% fourth
if ~isempty(Re_o) && ~isempty(Tl_o)
new_upper_airfoil4=new_upper_airfoil(new_upper_airfoil.ReynoldsNumber==Re_o & new_upper_airfoil.Transition==Tl_o,1:4);
new_lower_airfoil4=new_lower_airfoil(new_lower_airfoil.ReynoldsNumber==Re_o & new_lower_airfoil.Transition==Tl_o,1:4);
DV4=delaunay_nearest(new_upper_airfoil4, new_lower_airfoil4, Ma, C_l, delta);
DV_4=table(DV4.X_C, DV4.CP, repmat(Re_o,280,1),repmat(Tl_o,280,1),'VariableNames',{'X_C','CP','Re','Tl'});
else
DV_4=[];
end
%% Interpolation of the 4 2D Interpolations
DV_inter=[DV_1;DV_2;DV_3;DV_4];
if size(DV_inter,1)==280
DV=DV_1(:,1:2);
% figure
% hold on
% plot(DV.X_C,-DV.CP,'bl-');
% grid on;
% xlabel('X_C');
% ylabel('Cp');
%
else
%% interpolation with inverse distance weighted interpoaltion
load('x_c0');
DV=zeros(281,2);
for x_c=1:1:280
x_c_inter=x_c0(x_c);
Find=DV_inter(DV_inter.X_C==x_c_inter,:);
cp_inter=IDW(Find.Re, Find.Tl,Find.CP,Re,Tl,-2,'ng',2);
DV(x_c,:)=[x_c_inter,cp_inter];
end
DV(281,:)=DV(1,:);
figure
hold on
plot(DV(:,1),-DV(:,2),'r-');
grid on;
xlabel('X_C');
ylabel('Cp');
end
function DV = delaunay_nearest(new_upper_airfoil,new_lower_airfoil,Ma,C_l,delta)
Error=true;
load('x_c0');
while(Error)
%% build table for the pressure distribution
DV=array2table(zeros(280,2),'VariableNames',{'X_C','CP'});
%% another smaller delta for the interpolation (if too small the exception will be catched and the interpolation is restarted with a higher delta
new_upper_airfoil_loop=new_upper_airfoil(new_upper_airfoil.Ma < (Ma+delta) & new_upper_airfoil.Ma > (Ma-delta) & new_upper_airfoil.CL_res < (C_l+delta) & new_upper_airfoil.CL_res > (C_l-delta),:);
new_lower_airfoil_loop=new_lower_airfoil(new_lower_airfoil.Ma < (Ma+delta) & new_lower_airfoil.Ma > (Ma-delta) & new_lower_airfoil.CL_res < (C_l+delta) & new_lower_airfoil.CL_res > (C_l-delta),:);
%% try to build the delaunay triangulation
try
DT=delaunayTriangulation(new_upper_airfoil_loop.Ma,new_upper_airfoil_loop.CL_res);
% figure
% hold on;
% triplot(DT);
% plot(Ma,C_l,'ro');
%% find nearest neighbor
pointindex=dsearchn(DT.Points,[Ma,C_l]);
point=DT.Points(pointindex,:);
Error=0;
catch
delta=delta+0.005;
disp('Die Deltas wurden um 0.005 erhöht, da der Bereich der Daten zu klein war.');
continue;
end
%% search for the nearest neighbor
new_upper_airfoil_loop=new_upper_airfoil_loop(new_upper_airfoil_loop.Ma==point(1,1) & new_upper_airfoil_loop.CL_res==point(1,2),1:2);
new_lower_airfoil_loop=new_lower_airfoil_loop(new_lower_airfoil_loop.Ma==point(1,1) & new_lower_airfoil_loop.CL_res==point(1,2),1:2);
%% 2D Interpolation for all 280 points of the airfoil with the same x/c coordinates
for x_c=1:1:280
x_c_inter=x_c0(x_c);
%% upper_airfoil
if x_c < 146
FIND=new_upper_airfoil_loop(abs(new_upper_airfoil_loop.X_C-x_c_inter)<0.0005,:);
if(isempty(FIND))
leftNeighborIndex=nearestpoint(x_c_inter,new_upper_airfoil_loop.X_C,'previous');
if isnan(leftNeighborIndex)
leftNeighborIndex=1;
end
rightNeighborIndex=leftNeighborIndex+1;
if rightNeighborIndex > height(new_upper_airfoil_loop)
rightNeighborIndex=leftNeighborIndex-1;
end
average=interp1([new_upper_airfoil_loop.X_C(leftNeighborIndex,:),new_upper_airfoil_loop.X_C(rightNeighborIndex,:)], [new_upper_airfoil_loop.CP(leftNeighborIndex,:),new_upper_airfoil_loop.CP(rightNeighborIndex,:)], x_c_inter, 'linear','extrap');
FIND.X_C(1,:)=x_c_inter;
FIND.CP(1,:)=average;
DV(x_c,:)=FIND;
else
FIND.X_C(1,1)=x_c_inter;
DV(x_c,:)=FIND(1,:);
end
end
%% lower airfoil
if x_c > 145
FIND=new_lower_airfoil_loop(abs(new_lower_airfoil_loop.X_C-x_c_inter)<0.00008,:);
if(isempty(FIND))
leftNeighborIndex=nearestpoint(x_c_inter,new_lower_airfoil_loop.X_C,'previous');
if isnan(leftNeighborIndex)
leftNeighborIndex=height(new_lower_airfoil_loop);
end
rightNeighborIndex=leftNeighborIndex-1;
average=interp1([new_lower_airfoil_loop.X_C(leftNeighborIndex,:),new_lower_airfoil_loop.X_C(rightNeighborIndex,:)], [new_lower_airfoil_loop.CP(leftNeighborIndex,:),new_lower_airfoil_loop.CP(rightNeighborIndex,:)], x_c_inter, 'linear','extrap');
FIND.X_C(1,:)=x_c_inter;
FIND.CP(1,:)=average;
DV(x_c,:)=FIND;
else
FIND.X_C(1,1)=x_c_inter;
DV(x_c,:)=FIND(1,:);
end
end
end
end
end