首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何加快在“移动”范围内的多个数组之间搜索数据的代码运行时

如何加快在“移动”范围内的多个数组之间搜索数据的代码运行时
EN

Stack Overflow用户
提问于 2019-01-03 18:46:36
回答 1查看 93关注 0票数 0

我试图将我的CFD数据(它以标量N数组的形式,N对应于Y,M到x,以及P到z)在时间步骤的子集上进行平均。下面我尝试简化我想要的平均过程的描述。

  1. 按指定的角度旋转网格在每个时间步骤(这是因为流动有一个连贯的结构,旋转和改变形状/大小在每个时间步骤,我想要重叠,并找到一个时间平均形式的结构,考虑到形状/尺寸随时间的变化)
  2. 绘制以原始未旋转网格为中心的球体
  3. 从所有位于球体内的旋转网格中识别网格点
  4. 识别每个旋转网格中网格点的索引
  5. 使用索引在球体内旋转网格点处查找标量数据。
  6. 取球体内值的平均值
  7. 将新的平均值放在未旋转网格上的位置。

我有一个代码,它似乎能正确地完成我想做的事情,但要完成计算需要太长时间。我想让它运行得更快,如果有必要的话,我愿意修改代码。下面是我的代码版本,它可以处理较小版本的数据。

代码语言:javascript
运行
复制
x = -5:5;       % x - position data
y = -2:.5:5;    % y - position data
z = -5:5;       % z - position data
% my grid is much bigger actually

[X,Y,Z] = meshgrid(x,y,z);    % mesh for plotting data

dX = diff(x)';   dX(end+1) = dX(end);    % x grid intervals
dY = diff(y)';   dY(end+1) = dY(end);    % y grid intervals
dZ = diff(z)';   dZ(end+1) = dZ(end);    % z grid intervals

TestPoints = combvec(x,y,z)';    % you need the Matlab Neural Network Toolbox to run this
dXYZ = combvec(dX',dY',dZ')';

% TestPoints is the unrotated grid

M = length(x);   % size of grid x - direction
N = length(y);   % size of grid y - direction
P = length(z);   % size of grid z - direction

D = randi([-10,10],N,M,P,3);    % placeholder for data for 3 time steps (I have more than 3, this is a subset)
D2{3,M*N*P} = [];
PosAll{3,2} = [];

[xSph,ySph,zSph] = sphere(50);

c = 0.01;   % 1 cm
nu = 8e-6;  % 8 cSt
s = 3*c;    % span for Aspect Ratio 3
r_g = s/sqrt(3);
U_g = 110*nu/c; % velocity for Reynolds number 110
Omega = U_g/r_g;    % angular velocity
T = (2*pi)/Omega;   % period
dt = 40*T/1920;     % time interval
DeltaRotAngle = ((2*pi)/T)*dt;  % angle interval

timesteps = 121:123;   % time steps 121, 122, and 123
for ti=timesteps
    tj = find(ti==timesteps);
    Theta = ti*DeltaRotAngle;
    Rotate = [cos(Theta),0,sin(Theta);...
        0,1,0;...
        -sin(Theta),0,cos(Theta)];
    PosAll{tj,1} = (Rotate*TestPoints')';
end

for i=1:M*N*P
    aa = TestPoints(i,1);
    bb = TestPoints(i,2);
    cc = TestPoints(i,3);
    rs = 0.8*sqrt(dXYZ(i,1)^2 + dXYZ(i,2)^2 + dXYZ(i,3)^2);

    handles.H = figure;
    hs = surf(xSph*rs+aa,ySph*rs+bb,zSph*rs+cc);
    [Fs,Vs,~] = surf2patch(hs,'triangle');
    close(handles.H)

    for ti=timesteps
        tj = find(timesteps==ti);
        f = inpolyhedron(Fs,Vs,PosAll{tj,1},'FlipNormals',false);

        TestPointsR_ti = PosAll{tj,1};
        PointsInSphere = TestPointsR_ti(f,:);

        p1 = [aa,bb,cc];
        p2 = [PointsInSphere(:,1),...
            PointsInSphere(:,2),...
            PointsInSphere(:,3)];

        w = 1./sqrt(sum(...
            (p2-repmat(p1,size(PointsInSphere,1),1))...
            .^2,2));

        D_ti = reshape(D(:,:,:,tj),M*N*P,1);
        D2{tj,i} = [D_ti(f),w];
    end
end

D3{M*N*P,1} = [];
for i=1:M*N*P
    D3{i} = vertcat(D2{:,i});
end

D4 = zeros(M*N*P,1);
for i=1:M*N*P
    D4(i) = sum(D3{i}(:,1).*D3{i}(:,2))/...
                sum(D3{i}(:,2));
end
D_ta = reshape(D4,N,M,P);

我期望得到一个N,x,M,x,P数组,其中每个索引是所有点的加权平均值,包括在未旋转网格中特定位置的所有时间步长。正如你所看到的,这正是我所得到的。然而,主要的问题是,当我使用更大的“真实”数据集时,需要多长时间才能做到这一点。上面的代码只需几分钟就能运行,但是当M= 120、N= 24和P= 120时,时间步骤数为24,这可能会花费更长的时间。根据我的估计,完成整个计算大约需要25+天。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-04 01:48:40

没关系,我可以帮你学数学。你在这里要做的是在一个球体里找到东西。你有一个很好定义的球体,所以这很容易。只要找出所有点与中心点之间的距离。不需要绘制或使用多面体。注意,第66行,我根据球的中心点修改点,计算这些点的距离,并与球体的半径进行比较。

代码语言:javascript
运行
复制
% x = -5:2:5;       % x - position data
x = linspace(-5,5,120);
% y = -2:5;    % y - position data
y = linspace(-2,5,24);
% z = -5:2:5;       % z - position data
z = linspace(-5,5,120);
% my grid is much bigger actually

[X,Y,Z] = meshgrid(x,y,z);    % mesh for plotting data

dX = diff(x)';   dX(end+1) = dX(end);    % x grid intervals
dY = diff(y)';   dY(end+1) = dY(end);    % y grid intervals
dZ = diff(z)';   dZ(end+1) = dZ(end);    % z grid intervals

TestPoints = combvec(x,y,z)';    % you need the Matlab Neural Network Toolbox to run this
dXYZ = combvec(dX',dY',dZ')';

% TestPoints is the unrotated grid

M = length(x);   % size of grid x - direction
N = length(y);   % size of grid y - direction
P = length(z);   % size of grid z - direction

D = randi([-10,10],N,M,P,3);    % placeholder for data for 3 time steps (I have more than 3, this is a subset)
D2{3,M*N*P} = [];
PosAll{3,2} = [];

[xSph,ySph,zSph] = sphere(50);

c = 0.01;   % 1 cm
nu = 8e-6;  % 8 cSt
s = 3*c;    % span for Aspect Ratio 3
r_g = s/sqrt(3);
U_g = 110*nu/c; % velocity for Reynolds number 110
Omega = U_g/r_g;    % angular velocity
T = (2*pi)/Omega;   % period
dt = 40*T/1920;     % time interval
DeltaRotAngle = ((2*pi)/T)*dt;  % angle interval

timesteps = 121:123;   % time steps 121, 122, and 123
for ti=timesteps
    tj = find(ti==timesteps);
    Theta = ti*DeltaRotAngle;
    Rotate = [cos(Theta),0,sin(Theta);...
        0,1,0;...
        -sin(Theta),0,cos(Theta)];
    PosAll{tj,1} = (Rotate*TestPoints')';
end
tic
for i=1:M*N*P

    aa = TestPoints(i,1);
    bb = TestPoints(i,2);
    cc = TestPoints(i,3);
    rs = 0.8*sqrt(dXYZ(i,1)^2 + dXYZ(i,2)^2 + dXYZ(i,3)^2);

%     handles.H = figure;
%     hs = surf(xSph*rs+aa,ySph*rs+bb,zSph*rs+cc);
%     [Fs,Vs,~] = surf2patch(hs,'triangle');
%     close(handles.H)

    for ti=timesteps
        tj = find(timesteps==ti);

%         f = inpolyhedron(Fs,Vs,PosAll{tj,1},'FlipNormals',false);
        f = sqrt(sum((PosAll{tj,1}-[aa,bb,cc]).^2,2))<rs;
        TestPointsR_ti = PosAll{tj,1};
        PointsInSphere = TestPointsR_ti(f,:);

        p1 = [aa,bb,cc];
        p2 = [PointsInSphere(:,1),...
            PointsInSphere(:,2),...
            PointsInSphere(:,3)];

        w = 1./sqrt(sum(...
            (p2-repmat(p1,size(PointsInSphere,1),1))...
            .^2,2));

        D_ti = reshape(D(:,:,:,tj),M*N*P,1);
        D2{tj,i} = [D_ti(f),w];
    end
    if ~mod(i,10)
        toc
    end
end

D3{M*N*P,1} = [];
for i=1:M*N*P
    D3{i} = vertcat(D2{:,i});
end

D4 = zeros(M*N*P,1);
for i=1:M*N*P
    D4(i) = sum(D3{i}(:,1).*D3{i}(:,2))/...
                sum(D3{i}(:,2));
end
D_ta = reshape(D4,N,M,P);

就运行时而言,在我的计算机上,运行旧代码需要57个小时。新代码需要2个小时。在这一点上,主要的计算是距离,所以我怀疑你会变得更好。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54028084

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档