嵌套trapz双重集成

时间:2013-05-06 19:33:52

标签: matlab integral quad

我想知道是否有任何方法可以通过嵌套quad2d循环绕过trapz的调用。我将用更详细的方式讨论我的问题:目前,我用这种方式执行双积分的计算:

clc, clear all, close all
load E_integral.mat

c = 1.476;
gamma = 3.0;

beta_int = (c*gamma)./(k_int.*sqrt(E_integral));

figure, loglog(k_int,beta_int,'r','LineWidth',2.0), grid on;

k1 = (.01:.1:100);
k2 = .01:.1:100;
k3 = -100:.1:100;

int_k3 = zeros(size(k2));
int_k3k2 = zeros(size(k1));

tic
for ii = 1:numel(k1)
    phi11 = @(k2,k3) PHI11(k1(ii),k2,k3,k_int,beta_int);
    int_k3(ii) = 2*quad2d(phi11,-100,100,-100,100);
end
toc

其中PHI11定义为

function phi11 = PHI11(k1,k2,k3,k_int,beta_int)
k = sqrt(k1.^2 + k2.^2 + k3.^2);
ksq = k.^2;
k1sq = k1.^2;
fourpi = 4.*pi;
beta = exp(interp1(log(k_int),log(beta_int),log(k),'linear'));
k30 = k3 + beta.*k1;
k0 = sqrt(k1.^2 + k2.^2 + k30.^2);
k0sq = k0.^2;
k04sq = k0.^4;
Ek0 = (1.453.*k04sq)./((1 + k0sq).^(17/6));

C1 = (beta.*k1sq.*(k0sq - 2.*(k30.^2) + beta.*k1.*k30))./(ksq.*(k1.^2 + k2.^2));
C2 = ((k2.*k0sq)./((k1.^2 + k2.^2).^(3/2))).*atan2((beta.*k1.*sqrt(k1.^2 + k2.^2)),(k0sq - k30.*k1.*beta));
xhsi1 = C1 - (k2./k1).*C2;
xhsi1_sq = xhsi1.^2;
phi11 = (Ek0./(fourpi.*k04sq)).*(k0sq - k1sq - 2.*k1.*k30.*xhsi1 + (k1.^2 + k2.^2).*xhsi1_sq);
end

E_integral.mat可以通过这种方式获得:

clc,clear all,close all

k_int = .001:.01:1000;

Ek = (1.453.*k_int.^4)./((1 + k_int.^2).^(17/6));


E = @(k_int) (1.453.*k_int.^4)./((1 + k_int.^2).^(17/6));

E_integral = zeros(size(k_int));

for ii = 1:numel(k_int)    
    E_integral(ii) = integral(E,k_int(ii),Inf);    
end

save('E_integral','k_int','E_integral')

现在的问题是:是否可以通过使用嵌套的quad2d函数来忽略handle functiontrapz以支持更实用的方法?

到目前为止,我已尝试过以下代码,但未达到预期效果:

int_k33 = zeros(size(k2));
S_11 = zeros(size(k1));
tic
for ii = 1:1
    for jj = 1:numel(k2)
        int_k33(jj) = trapz(k3,PHI11(k1(ii),k2(jj),k3,k_int,beta_int));        
    end
    S_11(ii) = 4*trapz(k2,int_k33);
end
toc

1 个答案:

答案 0 :(得分:2)

我不确定你为什么要避免使用quad2d函数,但是可以将2D正交分成两个1D嵌套正交(即使函数没有因子分解)。

这是一种通过与两个trapz调用集成进行处理的方法。关键是要在一个大表中生成所有值的集合,并为两个维度使用trapz

首先,我定义测试值:

f= @(x,y) sin(x.*cos(y));
N = 1000;

然后,我为x和y方向定义网格(类似于k2k3):

xpts1d = linspace(0,1,N+1);
ypts1d = linspace(0,1,N+1);

然后我在所有点对中评估函数f:

xpts = xpts1d'*ones(1,N+1);
ypts = ones(N+1,1)*ypts1d;
values = f(xpts,ypts);

然后,可以使用两个嵌套调用完成集成:

I = trapz(xpts1d,trapz(ypts1d,values,2),1);

这给出了正确答案。


在我的回答的第一个版本中,我使用了quad函数,它直接使用函数句柄。 “天真”的想法是简单地嵌套两个调用,如:

I = quad( @(y) quad( @(x)f(x,y) ,0,1),0,1)

但实际上这不起作用。关键是内部quad调用不适用于向量值函数,而外部调用需要向量值函数。

为了使其有效,我们只需要更改quadquadv的向量值版本的内部调用:

I = quad( @(y) quadv( @(x)f(x,y) ,0,1),0,1)

现在它应该可以工作,我们可以检查它实际上给出了与

相同的答案
I = quad2d( f, 0,1,0,1)

如果您真的想使用trapz函数,我建议您在trapz之上构建一个函数,该函数接受函数句柄并在其中调用trapz