超松弛迭代法求解接地金属槽内电位分布.docx
《超松弛迭代法求解接地金属槽内电位分布.docx》由会员分享,可在线阅读,更多相关《超松弛迭代法求解接地金属槽内电位分布.docx(20页珍藏版)》请在冰点文库上搜索。
超松弛迭代法求解接地金属槽内电位分布
实验一用超松弛迭代法求解接地金属槽内电位分布
1、
实验内容:
试用超松弛迭代法求解接地金属槽内电位的分布。
已知:
,
给定边值如图所示。
给定初值:
误差范围:
计算迭代次数,
分布。
一.实验思路
由边界条件用泊松方程的五点差分格式求得中央点的点位。
再以所得点及边界再次利用泊松方程的五点差分格式求出另四个点,依照此方法求出其余点的电位分布。
用最佳收敛因子的经验公式计算收敛因子。
利用超松弛迭代法进行差分方程的求解,当遇到边界是采用边界值或者边界差分格式。
直到所有节点电位满足误差条件。
二.实验设计原理:
有限差分法
有限差分法(FiniteDifferentialMethod)是基于差分原理的一种数值计算法。
其基本思想:
将场域离散为许多小网格,应用差分原理,将求解连续函数ϕ的泊松方程的问题换为求解网格节点上ϕ的差分方程组的问题。
编程时将边值编入到程序中,这样可以省略输入,从而直接输入迭代因子进行求解,可以减少编程的难度。
迭代时所用公式是和书上一样,为
a[i][j]=b[i][j]+w/4*(b[i+1][j]+b[i][j+1]+a[i][j-1]+a[i-1][j]-4*b[i][j]);
其中a代表k+1,而b代表k。
三、程序运行界面及结果
四.源程序代码
#include
#include
#include
usingnamespacestd;
classoverrei//over-relaxationiterativemethod
{
private:
intm,n;
doublex,e;
double**p,**q;
public:
intk;
overrei(intm0,intn0,doublee0)
{
inti;
e=e0;
k=0;
m=m0;
n=n0;
p=newdouble*[m];
for(i=0;ip[i]=newdouble[n];
q=newdouble*[m];
//迭代因子求解
for(i=0;iq[i]=newdouble[n];
if(m==n)
x=2/(1+sin(3.141592654/(m-1)));
else
x=2-3.141592654*sqrt
(2)*sqrt(1/((m-1)*(m-1))+1/((n-1)*(n-1)));
cout<<"最佳收敛因子:
"<}
voidInitialization();//赋边界条件
voidCal();//计算
voidDiedai();//迭代函数
voidShow();//输出部分
};
voidoverrei:
:
Initialization()//赋边界条件
{
inti,j;
for(i=0;ifor(j=0;j{
if(i==0)
{
p[i][j]=100;
q[i][j]=100;
}
else
{
p[i][j]=0;
q[i][j]=0;
}
}
cout<<"初始点位:
"<Show();
}
voidoverrei:
:
Cal()//计算
{
inti,j;
intc=1;
while
(1)
{
c=1;
for(i=0;i{
for(j=0;j{
if((p[i][j]-q[i][j])>e||(q[i][j]-p[i][j])>e)//相邻两次迭代误差是否小于1e-5
{
c=0;break;
}
}
if(c==0)break;
}
if(c==1&&k!
=0)break;
Diedai();
}
}
voidoverrei:
:
Diedai()//迭代函数
{
inti,j;
doubley=x/4;
if(k%2)
{
for(i=1;ifor(j=1;j{
q[i][j]=p[i][j]+y*(q[i-1][j]+q[i][j-1]+p[i+1][j]+p[i][j+1]-4*p[i][j]);
}
}
else
{
for(i=1;ifor(j=1;j{
p[i][j]=q[i][j]+y*(p[i-1][j]+p[i][j-1]+q[i+1][j]+q[i][j+1]-4*q[i][j]);
}
}
k++;
}
voidoverrei:
:
Show()//输出部分
{
inti,j;
for(i=0;i{
for(j=0;j{
cout<}
cout<}
}
intmain()
{
cout<<"**************************************"<cout<<"超松弛迭代法求解接地金属槽内电位的分布"<cout<<"**************************************"<overreiA(5,5,1e-5);
A.Initialization();
A.Cal();
cout<<"电位分布:
"<A.Show();
cout<<"迭代次数:
"<return0;
}
实验二按对称场差分格式求解电位的分布
一.实验思路
只计算一半的区域,对另一半进行对称性计算,减小计算量。
选取二维数组,同样是两个数组a[41][41]、b[41][41],分别用于表示迭代前后的取值。
由此对第20列进行特殊处理。
即第21列是和第20列相等的,因为在第21列上标注了"∂Φ/∂x=0,即要求每次迭后都要求u1[i][20]=u1[i][19],其余则同前。
当计算出了前21列的电位值时,根据对称性可得到右半边的电位值,即要求u1[i][40-j]=u1[i][j];,直接赋值。
四周的电位值依旧保持不变,不能够参与迭代。
并且中间对称列上的电位值为零,故也不参与迭代。
由题意可知,只有第1列到第20列参与迭代。
在进行精度计算时,用数组b的值与相应数组a里的值进行比较,没迭代一次都要进行比较。
如果在误差允许的范围内,则继续迭代;当超过误差标准的时候则停止迭代。
依旧按照比较得到最少收敛次数的方法在程序中计算出最佳收敛因子。
然后对对称列右边的点进行对称赋值。
最后输出输出最佳迭代因子、迭代的次数和迭代后各相应点的电位值。
二.源程序代码
#include
#include
#include
void main()
{
double u1[41][41],u2[41][41];
int flag=10000,i,j,e,n;
double a,d; //a最佳加速收敛因子
for(j=0;j<41;j++)
{
u1[0][j]=100; u1[40][j]=0;
}
for(i=1;i<40;i++)
{
u1[i][0]=0; u1[i][40]=0;
}
for(i=1;i<40;i++) //内部点赋初值
for(j=1;j<21;j++)
{
u1[i][j]=2.5*(j-1);
}
cout<<"迭代前左半区域各电位点上的初始值:
"<for(i=0;i<41;i++)
{
for(j=0;j<21;j++)
{
cout<//输出迭代初值
}
cout<}
cout<for(d=1;d<2;d+=0.01)//取迭代次数最少的加速收敛因子
{
n=0; for(j=0;j<41;j++)
{
u1[0][j]=100; u1[40][j]=0;
}
for(i=1;i<40;i++)
{
u1[i][0]=0; u1[i][40]=0;
}
for(i=1;i<40;i++)
for(j=1;j<21;j++)
{
u1[i][j]=2.5*(j-1);
}
do//迭代x次
{
for(i=0;i<41;i++)
{
for(j=0;j<22;j++)
{
u2[i][j]=u1[i][j];
}
}
for(i=1;i<40;i++)
{
for(j=1;j<20;j++)
{
u1[i][j]=u2[i][j]+(d/4)*(u2[i+1][j]+u2[i][j+1]+u1[i-1][j]+u1[i][j-1]-4*u2[i][j]);
}
u1[i][20]=u1[i][19];
}
for(i=1;i<40;i++)//判断精度
{
{
for(j=1;j<21;j++)
{
if(fabs(u1[i][j]-u2[i][j])>1e-5)
{
e=1; break;
}
else e=0;
}
if(e==1) break;
}
}
n++;//迭代次数
}while(e);
if(n{
flag=n; a=d;
}
}
for(i=1;i<40;i++)//对其对称点赋值
for(j=1;j<21;j++)
{
u1[i][40-j]=u1[i][j];
}
cout<<"迭代后各节点上最终电位近似值:
"<for(i=0;i<41;i++)
{
for(j=0;j<41;j++)
{
cout<:
fixed)<}
cout<}
cout<cout<<"收敛因子:
"<cout<cout<<"迭代次数:
"<cout<}
三.程序运行界面及结果
附录:
程序一:
#include
#include
voidmain()
{
doublem[5][5],n[5][5];
intN=0,b=1;
inti,j;
doublee=0.00001;
doublea=2/(1+sin(3.1415926/4));
for(i=0;i<=4;i++)
for(j=0;j<=4;j++)
{
m[i][j]=0;n[i][j]=0;
}
m[1][4]=100;
m[2][4]=100;
m[3][4]=100;
n[1][4]=100;
n[2][4]=100;
n[3][4]=100;
for(j=4;j>=0;j--)
{
for(i=0;i<=4;i++)
cout<<"m["<
cout<}
while(b=1)
{
b=0;
N=N+1;
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
m[i][j]=m[i][j]+a*(m[i-1][j]+m[i][j-1]+m[i+1][j]+m[i][j+1]-4*m[i][j])/4;
for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
{
if(fabs(m[i][j]-n[i][j])>=e)
b=1;
n[i][j]=m[i][j];
}
}
for(j=4;j>=0;j--)
{
for(i=0;i<=4;;i++)
cout<<"m["<
cout<}
cunt<<"N="<程序二:
#include
#include
#include
usingnamespacestd;
classoverrei//over-relaxationiterativemethod
{
private:
intm,n;
doublex,e;
double**p,**q;
public:
intk;
overrei(intm0,intn0,doublee0)
{
inti;
e=e0;
k=0;
m=m0;
n=n0;
p=newdouble*[m];
for(i=0;ip[i]=newdouble[n];
q=newdouble*[m];
//迭代因子求解
for(i=0;iq[i]=newdouble[n];
if(m==n)
x=2/(1+sin(3.141592653/(m-1)));
else
x=2-3.141592653*sqrt
(2)*sqrt(1/((m-1)*(m-1))+1/((n-1)*(n-1)));
cout<<"最佳收敛因子:
"<}
voidInitialization();//赋边界条件
voidCal();//计算
voidDiedai();//迭代函数
voidShow();//输出部分
};
voidoverrei:
:
Initialization()
{
inti,j;
//边界条件
for(i=0;ifor(j=0;j{
if(i==0)
{
p[i][j]=100;
q[i][j]=100;
}
else
{
p[i][j]=0;
q[i][j]=0;
}
}
cout<<"初始点位:
"<Show();
}
voidoverrei:
:
Cal()
{
inti,j;
intc=1;
while
(1)
{
c=1;
for(i=0;i{
for(j=0;j{
if((p[i][j]-q[i][j])>e||(q[i][j]-p[i][j])>e)
{
c=0;break;
}
}
if(c==0)break;
}
if(c==1&&k!
=0)break;
Diedai();
}
}
voidoverrei:
:
Diedai()
{
inti,j;
doubley=x/4;
if(k%2)
{
for(i=1;ifor(j=1;j{
q[i][j]=p[i][j]+y*(q[i-1][j]+q[i][j-1]+p[i+1][j]+p[i][j+1]-4*p[i][j]);
}
}
else
{
for(i=1;ifor(j=1;j{
p[i][j]=q[i][j]+y*(p[i-1][j]+p[i][j-1]+q[i+1][j]+q[i][j+1]-4*q[i][j]);
}
}
k++;
}
voidoverrei:
:
Show()
{
inti,j;
for(i=0;i{
for(j=0;j{
cout<}
cout<}
}
intmain()
{
cout<<"**************************************"<cout<<"超松弛迭代法求解接地金属槽内电位的分布"<cout<<"**************************************"<overreiA(5,5,1e-6);
A.Initialization();
A.Cal();
cout<<"电位分布:
"<A.Show();
cout<<"迭代次数:
"<return0;
}
程序三
#include
#include
int i,j,N=0;//N为迭代次数
double u1[5][5];//定义电位
double u2[5][5];
double e=0.00001;//误差范围
double a=1.5;//加速收敛因子
int finish();//迭代结束函数
int Nresult();//求解迭代次数
void print();
void main()
{ if(i==4){
for(j=0;j<5;j++)
{ u1[i][j]=100;
}//边界值
}
else u1[i][j]=0;
N=Nresult();
print();
}
void print()
{
cout<<"迭代次数为:
"< for(j=0;j<5;j++)
{cout< }
cout<for(j=0;j<5;j++)
{cout< }
cout<for(j=0;j<5;j++)
{cout< }
cout<for(j=0;j<5;j++)
{cout< }
cout<for(j=0;j<5;j++)
{cout< }
cout<}
int finish()
{ double b;
b=u2[i][j]-u1[i][j];
if((-e
return 1;
else
return 0;
}
int Nresult()
{
do{N++;
for(i=1;i<4;i++)
{ for(j=1;j<4;j++)
{
u1[i][j]=u2[i][j];
}
}
for(j=1;j<4;j++)
{u2[1][j]=u1[1][j]+a/4*(u2[0][j]+u2[1][j-1]+u1[2][j]+u1[1][j+1]-4*u1[1][j]);
u1[i][j]=u2[i][j];
}
for(j=1;j<4;j++)
{u2[2][j]=u1[2][j]+a/4*(u2[1][j]+u2[2][j-1]+u1[3][j]+u1[2][j+1]-4*u1[2][j]);
u1[i][j]=u2[i][j];
}
for(j=1;j<4;j++)
{u2[3][j]=u1[3][j]+a/4*(u2[2][j]+u2[3][j-1]+u1[4][j]+u1[3][j+1]-4*u1[3][j]);
u1[i][j]=u2[i][j];
}
}while(finish()==0);
return N;
}
程序四
#include
#include
#include
using namespace std;
class cscdd
{
private:
int m,n;
double x,e;
double **p,**q;
public:
int k;
cscdd(int m0,int n0,double e0)
{
int i;
e=e0;
k=0;
m=m0;
n=n0;
p=new double *[m];
for( i=0;i{
p[i]=new double[n];
}
q=new double *[m];
for( i=0;i{
q[i]=new double[n];
}
if(m==n)
x=2/(1+sin(3.141592654/(m-1)));
else
x=2-3.141592654*sqrt
(2)*sqrt(1/((m-1)*(m-1))+1/((n-1)*(n-1)));
cout<<"最佳收敛因子:
"<}
void bjtj(); //赋边界条件
void jishuan(); //计算
void Diedai(); //迭代函数
void suchu(); //输出部分
};
void cscdd:
:
bjtj() //赋边界条件
{
int i,j;
for(i=0;ifor(j=0;j{
if(i==0)
{
p[i][j]=100;
q[i][j]=100;
}
else
{
p[i][j]=0;
q[i][j]=0;
}
}
cout<<"初始点位:
"<