为什么我编的电力系统潮流计算C语言PQ分解法不收敛

这是我编的vc源文件链接(功率部分还没编完,请忽略。。)http://pan.baidu.com/s/1jGmg5jo

//PQ 分解法源程序
#include "math.h"
#include "stdio.h"
#include "stdlib.h"

#define M 14 //预计支路数
#define N 14 //预计节点数
//
struct linestr //支路信息
{
int i,j; //和该支路相连的两个节点
float r,x,g,b; //该支路的参数,kb为非标准变比
float pij,qij,pji,qji; //支路潮流—计算数据
}line[M];

struct pointstr //节点信息
{
int sign; //节点类型,0—平衡节点,1—PQ节点,2—PV节点
float voltage,cta,p,q; //节点电压幅值和相位角,节点注入有功、无功
}pointpri[N],pointaft[N]; //pointpri用于存放节点的初始数据,pointaft用于存放计算后的节点数据

float G[N][N]={0},B[N][N]={0}; //节点导纳阵
//
float B1[N][N]={0},B2[N][N]={0};//修正方程系数矩阵
float detp[N]={0},detct[N]={0},detq[N]={0},detv[N]={0};//依次放修正方程的修正量
float pn[N]={0},ctn[N]={0},qn[N]={0},vn[N]={0}; //依次放修正量对应的节点号,即变量对应的节点号

int nline,npoint; //准确的支路数和节点数
int npq,npv,nbal; //PQ节点数、PV节点数、平衡节点数

void creat()
{
int i;
npq=0;npv=0;nbal=0;

printf("\n请输入总支路数:");scanf("%d",&nline);

for(i=1;i<=nline;i++)
{
printf("请输入%d号支路数据:\n",i);
printf("和该支路相连的节点号i,j(请用逗号隔开):");scanf("%d,%d",&(line[i].i),&(line[i].j));
printf("该支路的电阻和电抗R,X(请用逗号隔开):");scanf("%f,%f",&(line[i].r),&(line[i].x));
printf("该支路的对地电导和电纳G,B(请用逗号隔开):");scanf("%f,%f",&(line[i].g),&(line[i].b));
line[i].pij=0;line[i].qij=0;line[i].pji=0;line[i].qji=0;
//形成节点导纳阵
G[line[i].i][line[i].j]=-line[i].r/((line[i].r*line[i].r+line[i].x*line[i].x));
G[line[i].j][line[i].i]=G[line[i].i][line[i].j];
B[line[i].i][line[i].j]=line[i].x/((line[i].r*line[i].r+line[i].x*line[i].x));
B[line[i].j][line[i].i]=B[line[i].i][line[i].j];
G[line[i].i][line[i].i]+=line[i].r/((line[i].r*line[i].r+line[i].x*line[i].x));
G[line[i].i][line[i].i]+=line[i].g;
B[line[i].i][line[i].i]+=(-line[i].x)/((line[i].r*line[i].r+line[i].x*line[i].x));
B[line[i].i][line[i].i]+=line[i].b;
G[line[i].j][line[i].j]+=line[i].r/(line[i].r*line[i].r+line[i].x*line[i].x);
G[line[i].j][line[i].j]+=line[i].g;
B[line[i].j][line[i].j]+=(-line[i].x)/(line[i].r*line[i].r+line[i].x*line[i].x);
B[line[i].j][line[i].j]+=line[i].b;
}

printf("\n请输入总节点数:");scanf("%d",&npoint);
for(i=1;i<=npoint;i++)
{
printf("请输入节点%d的数据\n",i);
printf("选择节点类型(1-平衡节点,2-PQ节点,3-PV节点):");
scanf("%d",&(pointpri[i].sign));

if(pointpri[i].sign==1)
{
printf("请输入该节点的电压幅值和相位角(用逗号隔开):");
scanf("%f,%f",&(pointpri[i].voltage),&(pointpri[i].cta));
pointpri[i].p=0;pointpri[i].q=0;
nbal++;
}
else if(pointpri[i].sign==2)
{
printf("请输入该节点的注入有功和无功(用逗号隔开):");
scanf("%f,%f",&(pointpri[i].p),&(pointpri[i].q));
pointpri[i].voltage=1;pointpri[i].cta=0;
npq++;
}
else if(pointpri[i].sign==3)
{
printf("请输入该节点的有功注入和电压幅值(用逗号隔开):");
scanf("%f,%f",&(pointpri[i].p),&(pointpri[i].voltage));
pointpri[i].q=0;pointpri[i].cta=0;
npv++;
}
else
{
printf("选择无效,请重新输入\n");
i--;
}
if(nbal>1)
{
printf("出现多个平衡节点,请重新输入\n");
i--;nbal--;
}
}

}

void view()
{
int i,j;

for(i=1;i<=npoint;i++)
{
for(j=1;j<=npoint;j++)
printf("%f+j%f ,",G[i][j],B[i][j]);
printf("\n");
}
for(i=1;i<=npoint;i++)
{
printf("节点%d参数:",i);
if(pointpri[i].sign==1)printf("平衡节点 v=%f,theta=%f\n",pointpri[i].voltage,pointpri[i].cta);
else if(pointpri[i].sign==2)printf("PQ节点 P=%f,Q=%f\n",pointpri[i].p,pointpri[i].q);
else printf("PV节点 P=%f,v=%f\n",pointpri[i].p,pointpri[i].voltage);
}
}
void modify()
{
}

void run()
{
int i,j,k,m,n;
float E,e;//E为题目所要求的迭代精度,由键盘输入,e为每一步迭代的实际计算精度,用以和E比较
int numPQ[N];//PQ节点号
int numPV[N];//PV节点号
int numBAL; //平衡节点号
int np_th[N],nq_v[N];//迭代方程中的有功-电压相位角方程、无功-电压幅值方程分别对应的节点号
float B1_fac[N][N]={0},B2_fac[N][N]={0},a;

j=1;k=1;m=1;n=1;
for(i=1;i<=npoint;i++){B1_fac[i][i]=1;B2_fac[i][i]=1;}

for(i=1;i<=npoint;i++)
{//将数据存入一个新的结构体数组,保证在迭代过程中即使数据有改变,仍能保留住原始数据
pointaft[i].sign=pointpri[i].sign;
pointaft[i].voltage=pointpri[i].voltage;
pointaft[i].cta=pointpri[i].cta;
pointaft[i].p=pointpri[i].p;
pointaft[i].q=pointpri[i].q;
//统计PV节点和PQ节点序号,并存入临时数组
if(pointpri[i].sign==1)numBAL=i;
else if(pointpri[i].sign==2){numPQ[j++]=i;np_th[m++]=i;nq_v[n++]=i;}
else {numPV[k++]=i;np_th[m++]=i;}
}
//形成有功-相位角的迭代方程系数矩阵B1
for(i=1;i<=npoint-1;i++)
for(j=1;j<=npoint-1;j++)
B1[i][j]=B[np_th[i]][np_th[j]];
//形成因子表
for(k=1;k<=npoint-1;k++)
for(i=k+1;i<=npoint-1;i++)
{ a=B1[i][k];
for(j=1;j<=npoint-1;j++)
{
B1[i][j]-=a*B1[k][j]/B1[k][k];
B1_fac[i][j]-=a*B1_fac[k][j]/B1[k][k];
}
}

//形成无功-电压幅值的迭代方程的系数矩阵B2
for(i=1;i<=npq;i++)
for(j=1;j<=npq;j++)
B2[i][j]=B[nq_v[i]][nq_v[j]];
//形成因子表
for(k=1;k<=npq;k++)
for(i=k+1;i<=npq;i++)
{ a=B2[i][k];
for(j=1;j<=npq;j++)
{
B2[i][j]-=a*B2[k][j]/B2[k][k];
B2_fac[i][j]-=a*B2_fac[k][j]/B2[k][k];
}
}

printf("请输入迭代精度:");scanf("%f",&E);

k=-1;
do
{
e=0;
k++;

//有功迭代
//首先计算有功不平衡量
for(i=1;i<=npoint-1;i++)
{
detp[i]=pointaft[np_th[i]].p/pointaft[np_th[i]].voltage;
for(j=1;j<=npoint;j++)
detp[i]-=pointaft[j].voltage*(G[np_th[i]][j]*cos(pointaft[np_th[i]].cta-pointaft[j].cta)+B[np_th[i]][j]*sin(pointaft[np_th[i]].cta-pointaft[j].cta));
printf("%f,",detp[i]);
}
for(i=1;i<=npoint-1;i++)
{
detct[i]=0;
for(j=1;j<=npoint-1;j++)
detct[i]+=B1_fac[i][j]*detp[j];
}
for(i=npoint-1;i>=1;i--)
{
for(j=npoint-1;j>i;j--)
detct[i]-=B1[i][j]*detct[j];
detct[i]/=B1[i][i];
}
for(i=1;i<=npoint-1;i++)detct[i]/=(-pointaft[np_th[i]].voltage);//求出相位角的修正量
for(i=1;i<=npoint-1;i++){pointaft[np_th[i]].cta+=detct[i];e+=detct[i]*detct[i];}//修正角度,并计算精度
printf("第%d次迭代后的相位角:",k);
for(i=1;i<=npoint;i++)printf("%f,",pointaft[i].cta);
printf("\n");

//无功迭代

//首先计算无功不平衡量
for(i=1;i<=npq;i++)
{
detq[i]=pointaft[nq_v[i]].q/pointaft[nq_v[i]].voltage;
for(j=1;j<=npoint;j++)
detq[i]-=pointaft[j].voltage*(G[nq_v[i]][j]*sin(pointaft[nq_v[i]].cta-pointaft[j].cta)-B[nq_v[i]][j]*cos(pointaft[nq_v[i]].cta-pointaft[j].cta));
printf("%f,",detq[i]);
}
for(i=1;i<=npq;i++)
{
detv[i]=0;
for(j=1;j<=npq;j++)
detv[i]+=B2_fac[i][j]*detq[j];
}
for(i=npq;i>=1;i--)
{
for(j=npq;j>i;j--)
detv[i]-=B2[i][j]*detv[j];
detv[i]/=B2[i][i];
}
for(i=1;i<=npq;i++)detv[i]/=(-1);//求出电压的修正量
for(i=1;i<=npq;i++){pointaft[nq_v[i]].voltage+=detv[i];e+=detv[i]*detv[i];}//修正电压
printf("第%d次迭代后的电压幅值为:",k);
for(i=1;i<=npoint;i++)printf("%f,",pointaft[i].voltage);
printf("\n");

}while(e>E&&k<100);

//输出结果
printf("在满足精度E=%f的情况下,计算结果为:",E);
for(i=1;i<=npoint;i++)
printf("v%d=%f,cta%d=%f\n",i,pointaft[i].voltage,i,pointaft[i].cta);

//计算平衡节点注入功率
pointaft[numBAL].p=0;pointaft[numBAL].q=0;
for(i=1;i<=npoint;i++)
{
pointaft[numBAL].p+=pointaft[i].voltage*(G[numBAL][i]*cos(pointaft[numBAL].cta-pointaft[i].cta)+B[numBAL][i]*sin(pointaft[numBAL].cta-pointaft[i].cta));
pointaft[numBAL].q+=pointaft[i].voltage*(G[numBAL][i]*sin(pointaft[numBAL].cta-pointaft[i].cta)-B[numBAL][i]*cos(pointaft[numBAL].cta-pointaft[i].cta));
}
pointaft[numBAL].p*=pointaft[numBAL].voltage;
pointaft[numBAL].q*=pointaft[numBAL].voltage;
printf("平衡节点注入功率为:%f+j%f\n",pointaft[numBAL].p,pointaft[numBAL].q);

//计算各支路潮流
for(k=1;k<=nline;k++)
{
float aa,bb,cc;
i=line[k].i;j=line[k].j;
aa=pointaft[i].voltage*cos(pointaft[i].cta)-pointaft[j].voltage*cos(pointaft[j].cta);
bb=pointaft[i].voltage*sin(pointaft[i].cta)-pointaft[j].voltage*sin(pointaft[j].cta);
cc=line[k].r*line[k].r+line[k].x*line[k].x;
line[k].pij=(line[k].r*(pointaft[i].voltage*cos(pointaft[i].cta)*aa+pointaft[i].voltage*sin(pointaft[i].cta*bb))-line[k].x*(pointaft[i].voltage*sin(pointaft[i].cta*aa-pointaft[i].voltage*cos(pointaft[i].cta)*bb)))/cc;
line[k].qij=(line[k].x*(pointaft[i].voltage*cos(pointaft[i].cta)*aa+pointaft[i].voltage*sin(pointaft[i].cta*bb))+line[k].r*(pointaft[i].voltage*sin(pointaft[i].cta*aa-pointaft[i].voltage*cos(pointaft[i].cta)*bb)))/cc;
line[k].pji=(line[k].r*(pointaft[j].voltage*cos(pointaft[j].cta)*(-aa)+pointaft[j].voltage*sin(pointaft[j].cta*(-bb)))-line[k].x*(pointaft[j].voltage*sin(pointaft[j].cta*(-aa)-pointaft[j].voltage*cos(pointaft[j].cta)*(-bb))))/cc;
line[k].qji=(line[k].x*(pointaft[j].voltage*cos(pointaft[j].cta)*(-aa)+pointaft[j].voltage*sin(pointaft[j].cta*(-bb)))+line[k].r*(pointaft[j].voltage*sin(pointaft[j].cta*(-aa)-pointaft[j].voltage*cos(pointaft[j].cta)*(-bb))))/cc;

printf("由节点%d流向节点%d的功率为:%f+j%f\n",i,j,line[k].pij,line[k].qij);
printf("由节点%d流向节点%d的功率为:%f+j%f\n",j,i,line[k].pji,line[k].qji);
}

}

main ()
{
int a;

printf("\n");
printf("***************电力系统潮流计算**************\n");
printf("\n");
printf(" 设计者: 李 冰 设计:2014 年 5 月\n");
printf("\n");
printf("\n");
printf(" 注:各参数用标么值表示,角度均以弧度制表示\n");
printf("\n");

printf("\n");
do
{
printf("请选择:1-建立电网;2-查看数据;3-修改数据;4-运行计算;0-退出程序:");//由键盘输入选项
scanf("%d",&a);
if (a==0) //如果选中0,就表示退出程序
{
exit(0);
}
else if (a==1) //如果选中1,就跳去执行建立电网,即creat处
{
creat();
}
else if (a==2) //如果选中2,就跳去执行查看数据,即view处
{
view();
}
else if (a==3) //如果选中1,就跳去执行修改数据,即modify处
{
modify();
}
else if (a==4) //如果选中1,就跳去执行运行计算,即run处
{
run();
}
else //如果以上都不是,则表示无效输入,重新要求输入选择
{
printf("\n无效输入,请重新选择\n");
}
}while(1);
}
不知道能不能帮到你
温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-04-25
我最近也在做这个,不过我没有自己编,是去csdn上面下了些来读。虽然很多程序是可以编译的,但是有些算法小错误真是想破脑袋好久才发现,现在为止pq分解法的c写的我还没有看到正确的……追问

还没看到正确的。。。。不至于吧 我要哭死了T^T

追答

恩,我在csdn和pudn上面都下载了些,不过各有各的问题。或者就是那种节点已经定了,改不了的,这一类我也没有再编译,说不定也编不过呢? -.- 。你自己写的还没有研制成功?

追问

就是找不出错啊 一直不收敛 给跪了(┬_┬)

本回答被网友采纳
第2个回答  2014-04-11
大哥,你的程序一点注释也没有,也不了解PQ分解,实在是想帮也帮不上追问

我加了注释了http://pan.baidu.com/s/1qWpse1e
还有,我是照着书上这个式子编的http://pan.baidu.com/s/1dDFwW5F
我本身也不是很懂,慢慢摸索的,不好意思啊T-T
那个b是对地电容不是阻抗。k是变比不是阻抗。刚发现。。。。。。。。

相似回答