2011-12-20 126 views
0

早安大家,提高5D矩陣計算

我已經寫了這個代碼:

clc 
clear all 
close all 

%Box size 
Nx=4096; 
Ny=15; 
Nz=15; 

%Spatial gird resolution 
delta=6; 

%WT/turbulence condition 
UHub=11.4; 
HubHt=90; 
z0=0.03; 
IECturbC='B'; 

%%INITIALISATION 

% definition of constants 
twopi=2*pi; 
fourpi=4*pi; 
sqrt2=sqrt(2); 

%constants and derived parameters from IEC 
gamma = 3.9; %IEC, (B.12) 
alpha = 0.2; %IEC, sect. 6.3.1.2 

%set delta1 according to guidelines (chap.6) 
if HubHt<=60, 
    delta1=0.7*HubHt; 
else 
    delta1=42; 
end; 

%IEC, Table 1, p.22 
if IECturbC == 'A', 
    Iref=0.16; 
elseif IECturbC == 'B', 
    Iref=0.14; 
elseif IECturbC == 'C', 
    Iref=0.12; 
else 
    error('IECturbC can be equal to A,B or C;adjust the input value') 
end; 

%IEC, sect. 6.3.1.3 
b=6.5; 
sigma1=Iref*(0.75*UHub+b); 
%derived constants 
l=0.8*delta1; %IEC, (B.12) 
sigmaiso=0.55*sigma1; %IEC, (B.12) 

%%MAIN PROGRAM 
Cij=zeros(3,3,Nx,Ny,Nz); 
k = zeros(3,1); %current vector k 

for ikx=1:(Nx), 
    m = -1.*Nx/2+ikx; 
    k(1)=m*l/(Nx*delta)*twopi; 
    for iky=1:(Ny), 
     m= -1.*Ny/2+iky; 
     k(2)=m*l/(Ny*delta)*twopi; 
     for ikz=1:(Nz), 
     m= -1.*Nz/2+ikz; 
     k(3)=m*l/(Nz*delta)*twopi; 


      if k(1)==0, 
      Cij(:,:,ikx,iky,ikz)=0; 
      else 
      kabs=sqrt(k(1)^2+k(2)^2+k(3)^2); 
      beta= gamma./(kabs.^(2/3)); 
      k0(3)=k(3)+beta.*k(1); 
      k0abs=sqrt(k(1)^2+k(2)^2+k0(3)^2); 
      Ek0=1.453*k0abs^4/(1.+k0abs.^2)^(17/6); 
      C1=beta.*k(1)^2*(k0abs.^2 - 2*k0(3)^2 + beta.*k(1)*k0(3))/(kabs.^2*(k(1)^2 + k(2)^2)); 
      C2=k(2).*k0abs.^2./ (exp((3/2).*log(k(1).^2 + k(2).^2))) .* atan2(beta.*k(1).* sqrt(k(1)^2 + k(2)^2) ,(k0abs.^2 - k0(3).*k(1).*beta)); 
      xhsi1=C1 - k(2).*C2./k(1); 
      xhsi2=k(2).*C1./k(1) + C2; 

      Cij(1,1,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(k(2).*xhsi1); 
      Cij(1,2,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(k(3) - k(1).*xhsi1 + beta.*k(1)); 
      Cij(1,3,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(-k(2)); 
      Cij(2,1,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(k(2).*xhsi2 - k(3) - beta.*k(1)); 
      Cij(2,2,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(-k(1).*xhsi2); 
      Cij(2,3,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(k(1)); 
      Cij(3,1,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(k0abs.^2.*k(2) ./ (kabs.^2)); 
      Cij(3,2,ikx,iky,ikz)= sigmaiso*sqrt(twopi*pi*l^3.*Ek0/(Nx*Ny*Nz*delta^3.*k0abs.^4))*(-k0abs.^2*k(1) ./ (kabs.^2)); 
      Cij(3,3,ikx,iky,ikz)= 0; 
      end;  
     end; 
    end; 
end; 

我想問你: 1.有沒有更快的方法來獲得Cij的矩陣?當Nx,Ny,Nz增加時,Cij的計算相當慢; 2.有什麼方法可以獲得情節(kabs,beta)和情節(kabs,Ek0)嗎?

請耐心等待,我仍然是matlab世界中的新手。

提前感謝和問候, 弗朗切斯科

+0

看到這個答案:http://stackoverflow.com/a/7973945/907578。此外,您應該通過提供更少的不相關代碼來使問題更加通用。 – cyborg 2011-12-20 10:54:00

+0

問題是,如果沒有整個代碼,就不太容易理解我需要的東西。對不起,這只是2天,我是一個stackoverflow用戶:) – fpe 2011-12-20 10:59:57

+0

@cyborg:btw你有任何線索如何改變我的Cij實現根據該答案?我對matlab非常熟悉,需要很長時間才能獲得正確的編碼。我提前感謝您。 – fpe 2011-12-20 11:20:59

回答

3

如果你想在MATLAB良好performaces,你應該嘗試矢量化你的代碼儘可能。

例如,而不是做:

for x=1:n 
    A(x)=x^2 
end 

x=1:n; 
A=x.^2; 

當你有一個以上的指標,您可以使用ndgrid。因此,而不是這樣做的:

for x=1:nx 
    for y=1:ny 
    for z=1:nz 
     A(x,y,z)=x^2+y-2*z; 
    end 
    end 
end 

[x y z]=ndgrid(1:nx,1:ny,1:nz) 
A=x.^2+y-2*z 

既然你看起來就像你努力,我已經改變了你的代碼你。執行時間現在是0.33秒。該vecotrized版本是:

clc 
clear all 
close all 
tic 

%Box size 
Nx=1024; 
Ny=15; 
Nz=15; 

%Spatial gird resolution 
delta=6; 

%WT/turbulence condition 
UHub=11.4; 
HubHt=90; 
z0=0.03; 
IECturbC='B'; 

%%INITIALISATION 

% definition of constants 
twopi=2*pi; 
fourpi=4*pi; 
sqrt2=sqrt(2); 

%constants and derived parameters from IEC 
gamma = 3.9; %IEC, (B.12) 
alpha = 0.2; %IEC, sect. 6.3.1.2 

%set delta1 according to guidelines (chap.6) 
if HubHt<=60, 
    delta1=0.7*HubHt; 
else 
    delta1=42; 
end; 

%IEC, Table 1, p.22 
if IECturbC == 'A', 
    Iref=0.16; 
elseif IECturbC == 'B', 
    Iref=0.14; 
elseif IECturbC == 'C', 
    Iref=0.12; 
else 
    error('IECturbC can be equal to A,B or C;adjust the input value') 
end; 

%IEC, sect. 6.3.1.3 
b=6.5; 
sigma1=Iref*(0.75*UHub+b); 
%derived constants 
l=0.8*delta1; %IEC, (B.12) 
sigmaiso=0.55*sigma1; %IEC, (B.12) 

Cij2=zeros(3,3,Nx,Ny,Nz); 
[x y z]=ndgrid(1:Nx,1:Ny,1:Nz); 
k1=(x-Nx/2)*l/(Nx*delta)*twopi; 
k2=(y-Ny/2)*l/(Ny*delta)*twopi; 
k3=(z-Nz/2)*l/(Nz*delta)*twopi; 
kabs=sqrt(k1.^2+k2.^2+k3.^2); 
beta= gamma./(kabs.^(2/3)); 
k03=k3+beta.*k1; 
k0abs=sqrt(k1.^2+k2.^2+k03.^2); 
Ek0=1.453*k0abs.^4./(1+k0abs.^2).^(17/6); 
C1=beta.*k1.^2.*(k0abs.^2 - 2*k03.^2 + beta.*k1.*k03)./(kabs.^2.*(k1.^2 + k2.^2)); 
C2=k2.*k0abs.^2./ (exp((3/2).*log(k1.^2 + k2.^2))) .* atan2(beta.*k1.* sqrt(k1.^2 + k2.^2) ,(k0abs.^2 - k03.*k1.*beta)); 
xhsi1=C1 - k2.*C2./k1; 
xhsi2=k2.*C1./k1 + C2; 
CC=sigmaiso*sqrt(twopi*pi*l^3.*Ek0./(Nx*Ny*Nz*delta^3.*k0abs.^4)); 
Cij2(1,1,:,:,:)= CC.*(k2.*xhsi1); 
Cij2(1,2,:,:,:)= CC.*(k3 - k1.*xhsi1 + beta.*k1); 
Cij2(1,3,:,:,:)= CC.*(-k2); 
Cij2(2,1,:,:,:)= CC.*(k2.*xhsi2 - k3 - beta.*k1); 
Cij2(2,2,:,:,:)= CC.*(-k1.*xhsi2); 
Cij2(2,3,:,:,:)= CC.*(k1); 
Cij2(3,1,:,:,:)= CC.*(k0abs.^2.*k2 ./ (kabs.^2)); 
Cij2(3,2,:,:,:)= CC.*(-k0abs.^2.*k1 ./ (kabs.^2)); 
+0

:哇,這太令人吃驚了。我前幾天嘗試做類似的事情,但後來我在計算Cij2時迷路了;但現在問題再次與昨天相同,即計算H(3,Nx,Ny,Nz)= dot(Cij,n),其中n包含高斯分佈隨機數(mu = 0,sigma = 1)。 – fpe 2011-12-20 12:18:24

0

我會盡量更普遍地回答你的問題,所以其他人也可以受益。

您應該矢量化for循環以使您的代碼更快。取而代之的是這樣的:

for i=1:n 
    for j=1:m 
     M(i,j)=sqrt(i) + sqrt(j); 
    end 
end 

矢量化根據下面的代碼循環:

[xi,xj] = ndgrid(1:n,1:m); 
M = sqrt(xi)+sqrt(xj);