高斯-勒让德数值积分Matlab代码
[code]function [ql,Ak,xk]=guasslegendre(fun,a,b,n,tol)
% 高斯-勒让德数值积分
%
% 参数说明
% fun:积分表达式,可以是函数句柄、inline函数、匿名函数、字符串表达式,但是必须可以接受矢量输入
% a,b:积分上下限,注意积分区间太大会降低精度,此时建议使用复化求积公式,默认[-1 1]
% n:积分阶数,可以任意正整数,但是不建议设置过大,大不一定能得到更好的精度,默认7
% tol:积分精度,默认1e-6
% ql:积分结果
% Ak:求积系数
% xk:求积节点,满足ql=sum(Ak.*fun(xk))
% 高斯-勒让德数值积分
%
% 参数说明
% fun:积分表达式,可以是函数句柄、inline函数、匿名函数、字符串表达式,但是必须可以接受矢量输入
% a,b:积分上下限,注意积分区间太大会降低精度,此时建议使用复化求积公式,默认[-1 1]
% n:积分阶数,可以任意正整数,但是不建议设置过大,大不一定能得到更好的精度,默认7
% tol:积分精度,默认1e-6
% ql:积分结果
% Ak:求积系数
% xk:求积节点,满足ql=sum(Ak.*fun(xk))
%
% 举例说明
% fun=@(x)exp(x).*cos(x); % 必须可以接受矢量输入
% quadl(fun,0,pi) % 调用MATLAB内部积分函数检验
% [ql,Ak,xk]=guasslegendre(fun,0,pi)
%
% 高斯积分说明
% 1.高斯积分是精度最高的插值型数值积分,具有2n+1阶精度,并且高斯积分总是稳定。一般插值型数值积分精度为至少n阶,且具有高阶不稳定性
% 2.高斯求积节点就是对应n阶正交多项式的根,构建首项系数为1的正交多项式参见www.matlabsky/thread-4798-1-1.html
% 3.高斯求积系数,可以由Lagrange多项式插值系数进行积分得到
% 4.由高斯求积节点为根构成的多项式,与任何不超过n阶的多项式正交
%
% 勒让德正交多项式说明
% 举例说明
% fun=@(x)exp(x).*cos(x); % 必须可以接受矢量输入
% quadl(fun,0,pi) % 调用MATLAB内部积分函数检验
% [ql,Ak,xk]=guasslegendre(fun,0,pi)
%
% 高斯积分说明
% 1.高斯积分是精度最高的插值型数值积分,具有2n+1阶精度,并且高斯积分总是稳定。一般插值型数值积分精度为至少n阶,且具有高阶不稳定性
% 2.高斯求积节点就是对应n阶正交多项式的根,构建首项系数为1的正交多项式参见www.matlabsky/thread-4798-1-1.html
% 3.高斯求积系数,可以由Lagrange多项式插值系数进行积分得到
% 4.由高斯求积节点为根构成的多项式,与任何不超过n阶的多项式正交
%
% 勒让德正交多项式说明
% 1.区间[-1,1]上关于权rho(x)=1的正交多项式系,满足
% |- 2/(2j+1) (i=j)
% ∫(Pi(x)*Pj(x),-1,1)= |
% |- 0 (i≠j)
% 2.勒让德正交多项式的通式为:P0=1, Pn=1/(2^n*n!) * diff((x^2-1)^n,n) (n=1,2,...)
% 3.关于高斯-勒让德的数值积分的求积系数和节点,由于表达式不便于书写,感兴趣的网友可以参考相关书籍
%
% by dynamic of Matlab技术论坛
% see also www.matlabsky
% contact me matlabsky@gmail
% 2010-01-15 23:05:33
%
% 输入参数有效性检验
if nargin==1
% |- 2/(2j+1) (i=j)
% ∫(Pi(x)*Pj(x),-1,1)= |
% |- 0 (i≠j)
% 2.勒让德正交多项式的通式为:P0=1, Pn=1/(2^n*n!) * diff((x^2-1)^n,n) (n=1,2,...)
% 3.关于高斯-勒让德的数值积分的求积系数和节点,由于表达式不便于书写,感兴趣的网友可以参考相关书籍
%
% by dynamic of Matlab技术论坛
% see also www.matlabsky
% contact me matlabsky@gmail
% 2010-01-15 23:05:33
%
% 输入参数有效性检验
if nargin==1
a=-1;b=1;n=7;tol=1e-8;
elseif nargin==3
n=7;tol=1e-8;
elseif nargin==4
tol=1e-8;
elseif nargin==2|nargin>5
error('The Number of Input Arguments Is Wrong!');
end
% 计算求积节点
syms x
p=sym2poly(diff((x^2-1)^(n+1),n+1))/(2^n*factorial(n));
tk=roots(p); % 求积节点
% 计算求积系数
Ak=zeros(n+1,1);
for i=1:n+1
elseif nargin==3
n=7;tol=1e-8;
elseif nargin==4
tol=1e-8;
elseif nargin==2|nargin>5
error('The Number of Input Arguments Is Wrong!');
end
% 计算求积节点
syms x
p=sym2poly(diff((x^2-1)^(n+1),n+1))/(2^n*factorial(n));
tk=roots(p); % 求积节点
% 计算求积系数
Ak=zeros(n+1,1);
for i=1:n+1
xkt=tk;
xkt(i)=[];
pn=poly(xkt);
fp=@(x)polyval(pn,x)/polyval(pn,tk(i));
Ak(i)=quadl(fp,-1,1,tol); % 求积系数
end
% 积分变量代换,将[a,b]变换到[-1,1]
xk=(b-a)/2*tk+(b+a)/2;
% 检验积分函数fun有效性
fun=fcnchk(fun,'vectorize');
% 计算变量代换之后积分函数的值
fx=fun(xk)*(b-a)/2;
% 计算积分值
ql=sum(Ak.*fx);[/code]
xkt(i)=[];
pn=poly(xkt);
fp=@(x)polyval(pn,x)/polyval(pn,tk(i));
Ak(i)=quadl(fp,-1,1,tol); % 求积系数
end
% 积分变量代换,将[a,b]变换到[-1,1]
xk=(b-a)/2*tk+(b+a)/2;
% 检验积分函数fun有效性
fun=fcnchk(fun,'vectorize');
% 计算变量代换之后积分函数的值
fx=fun(xk)*(b-a)/2;
% 计算积分值
ql=sum(Ak.*fx);[/code]
Matlab只能直接计算内外积分限都是已知实数的二重积分
比如 INT_(a)^(b)INT_{c}^{d}f(x,y)dxdy,其中a,b,c,d都是已知实数,则可以用Matlab指令:
dblquad(f(x,y),c,d,a,d);
但如果内积分限是外积分的积分变量函数时,Matlab不能直接运算。
比如INT_(a)^(b)INT_{g1(y)}^{g2(y)}f(x,y)dxdy, 其中外积分限a,b都是已知实数, 而内积分限g1(y), g2(y)都是外积分变量y的函数
解法: 把内积分变量x转换成y和一个新定义变量v的函数: x=(1-v)*g1(y)+v*g2(y),这样,原来的积分公式可以变为:
INT_(a)^(b)INT_{0}^{1)}f((1-v)*g1(y)+v*g2(y), y)*[g2(y)-g1(y)]dvdy
这时内积分变量是v,内积分上下限是常数0和1. 积分函数变成f((1-v)*g1(y)+v*g2(y),,y)*[g2(y)-g1(y)] ,注意这里f(x,y)中的x已经转换成(1-v)*g1(y)+v*g2(y)。
这样,这个二重积分可以用Matalb指令算出:
dblquad(f((1-v)*g1(y)+v*g2(y),y)*(g2(y)-g1(y)) ,0,1,a,b);
用matlab求定积分的三个实例代码
一、符号积分 符号积分由函数int来实现。该函数的一般调用格式为: int(s):没有指定积分变量和积分阶数时,系统按findsym函数指示的默认变量对被积函数或符号表达式s求不定积分; int(s,v):以v为自变量,对被积函数或符号表达式s求不定积分; int(s,v,a,b):求定积分运算。a,b分别表示定积分的下限和上限。该函数求被积函数在区间[a,b]上的定积分。a和b可以是两个具体的数,也可以是一个符号表达式,还可以是无穷(inf)。当函数f关于变量x在闭区间[a,b]上可积时,函数返回一个定积分结果。当a,b中有一个是inf时,函数返回一个广义积分。当a,b中有一个符号表达式时,函数返回一个符号函数。 例: 求函数x^2+y^2+z^2的三重积分。内积分上下限都是函数,对z积分下限是sqrt(x*y),积分上限是x^2*y;对y积分下限是sqrt(x),积分上限是x^2;对x的积分下限1,上限是2,求解如下: >>syms x y z %定义符号变量 >>F2=int(int(int(x^2+y^2+z^2,z,sqrt(x*y),x^2*y),y,sqrt(x),x^2),x,1,2) %注意定积分的书写格式 F2 = 1610027357/6563700-6072064/348075*2^(1/2)+14912/4641*2^(1/4)+64/225*2^(3/4) %给出有理数解 >>VF2=vpa(F2) %给出默认精度的数值解 VF2 = 224.92153573331143159790710032805 二、数值积分 1.数值积分基本原理 求解定积分的数值方法多种多样,如简单的梯形法、辛普生(Simpson)法、牛顿-柯特斯(Newton-Cotes)法等都是经常采用的方法。它们的基本思想都是将整个积分区间[a,b]分成n个子区间[xi,xi+1],i=1,2,…,n,其中x1=a,xn+1=b。这样求定积分问题就分解为求和问题。 2.数值积分的实现方法 基于变步长辛普生法,MATLAB给出了quad函数来求定积分。该函数的调用格式为: [I,n]=quad('fname',a,b,tol,trace) 基于变步长、牛顿-柯特斯(Newton-Cotes)法,MATLAB给出了quadl函数来求定积分。该函数的调用格式为: [I,n]=quadl('fname',a,b,tol,trace) 其中fname是被积函数名。a和b分别是定积分的下限和上限。tol用来控制积分精度,缺省时取tol=0.001。trace控制是否展现积分过程,若取非0则展现积分过程,取0则不展现,缺省时取trace=0。返回参数I即定积分值,n为被积函数的调用次数。 例: 求函数'exp(-x*x)的定积分,积分下限为0,积分上限为1。 >>fun=inline('exp(-x.*x)','x'); %用内联函数定义被积函数fname >>Isim=quad(fun,0,1) %辛普生法 Isim = 0.746824180726425 IL=quadl(fun,0,1) %牛顿-柯特斯法 IL = 0.746824133988447 三、梯形法求向量积分 trapz(x,y)—梯形法沿列方向求函数Y关于自变量X的积分(向量形式,数值方法)。 >>d=0.001; >>x=0:d:1; >>S=d*trapz(exp(-x.^2)) S= 0.7468 或: >>format long g >>x=0:0.001:1; %x向量,也可以是不等间距 >>y=exp(-x.^2); %y向量,也可以不是由已知函数生成的向量 >>S=trapz(x,y); %求向量积分 S = 0.746824071499185 int的积分可以是定积分,也可以是不定积分(即有没有积分上下限都可以积)可以得到解析的解,比如你对x^2积分,得到的结果是1/3*x^3,这是通过解析的方法来解的。如果int(x^2,x,1,2)得到的结果是7/3 quad是数值积分,它只能是定积分(就是有积分上下限的积分),它是通过simpson数值积分来求得的(并不是通过解析的方法得到解析解,再将上下限代入,而是用小梯形的面积求和得到的)。如果f=inline('x.^2');quad(f,1,2)得到的结果是2.333333,这个数并不是7/3 int是符号解,无任何误差,唯一问题是计算速度;quad是数值解,有计算精度限制,优点是总是能有一定的速度,即总能在一定时间内给出一个一定精度的解。 对于y=exp(-(x.^2+x+1)/(1+x)),被积函数之原函数无"封闭解析表达式",符号计算无法解题,这是符号计算有限性,结果如下: >> syms x >>y=exp(-(x.^2+x+1)/(1+x)) >>s=int(y,x,0,inf) y = exp((-x^2-x-1)/(1+x)) Warning: Explicit integral could not be found. >> In sym.int at 58 s = int(exp((-x^2-x-1)/(1+x)),x = 0 .. Inf) 只有通过数值计算解法 >> dx=0.05; %采样间隔 >>x=0:dx:1000; %数值计算适合于有限区间上,取有限个采样点,只要终值足够大,精度不受影响 >>y=exp(-(x.^2+x+1)./(1+x)); >>S=dx*cumtrapz(y); %计算区间内曲线下图形面积,为小矩形面积累加得 >>S(end) ans = 0.5641 %所求定积分值 或进行编程,积分上限人工输入,程序如下: %表达式保存为函数文件 function y=fxy(x) y=exp(-(x.^2+x+1)./(1+x)); % save fxy.m % main --------主程序 clear,clc h=.001;p=0;a=0; R=input('请输入积分上限,R=') while a<R p=p+(fxy(a)+fxy(a+h))*h/2; a=a+h; end p=vpa(p,10) 运行主程序后得到结果: 请输入积分上限,R=1000 R = 1000 p = .5641346055 其它结果如下: 0-1: int=.3067601686 0-2: int=.4599633159 0-5: int=.5583068217 0-10: int=.5640928975 0-100: int=.5641346055 0-1000: int=.5641346055 在积分函数中,sqrt(e1*e2*e3)*cos(n1*pi*x/12).*cos(n2*pi*y/11).*cos(n3*pi*z/9);已知变量e1,e2,e3,n1,n2,n3通过函数参数输入,如果直接用inline或字符串的形式,则表达式中的未知数有9个,分别是e1,e2,e3,n1,n2,n3,x,y,z。而用匿名函数时,已知变量e1,e2,e3,n1,n2,n3就会以常数看待,未知数就只有x,y,z了,可以求三重积分了。 完整函数程序: function Fn(n1,n2,n3) if n1==0 e1=1; else if n1>0 e1=2; end end if n2==0 e2=1; else if n2>0 e2=2; end end if n3==0 e3=1; else if n3>0 e3=2; end end F=@(x,y,z)sqrt(e1*e2*e3)*cos(n1*pi*x/12).*cos(n2*pi*y/11).*cos(n3*pi*z/9); S=triplequad(F,-6,6,-5.5,5.5,-4.5,4.5) %求三重数值积分 将以上代码保存为Fn.m程序文件,即m文件,然后运行: >> Fn(1,1,1) S = 866.9655 |
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论