📄 pbcg.cpp
字号:
//#include "stdafx.h"
#include "PBCG.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
PBCG::PBCG()
{
sa = NULL;
ija = NULL;
}
PBCG::~PBCG()
{
if(sa != NULL)
delete sa;
if(ija != NULL)
delete ija;
}
void PBCG::linbcg(unsigned long n, double b[], double x[], int itol, double tol, int itmax, int *iter, double *err)
{
unsigned long j;
double ak,akden,bk,bkden,bknum,bnrm,dxnrm,xnrm,zm1nrm,znrm;
double *p,*pp,*r,*rr,*z,*zz;
p=dvector(1,n);
pp=dvector(1,n);
r=dvector(1,n);
rr=dvector(1,n);
z=dvector(1,n);
zz=dvector(1,n);
*iter=0;
atimes(n,x,r,0);
for (j=1;j<=n;j++) {
r[j]=b[j]-r[j];
rr[j]=r[j];
}
znrm=1.0;
if (itol == 1) bnrm=snrm(n,b,itol);
else if (itol == 2) {
asolve(n,b,z,0);
bnrm=snrm(n,z,itol);
}
else if (itol == 3 || itol == 4) {
asolve(n,b,z,0);
bnrm=snrm(n,z,itol);
asolve(n,r,z,0);
znrm=snrm(n,z,itol);
} else nrerror("illegal itol in linbcg");
asolve(n,r,z,0);
while (*iter <= itmax) {
++(*iter);
zm1nrm=znrm;
asolve(n,rr,zz,1);
for (bknum=0.0,j=1;j<=n;j++) bknum += z[j]*rr[j];
if (*iter == 1) {
for (j=1;j<=n;j++) {
p[j]=z[j];
pp[j]=zz[j];
}
}
else {
bk=bknum/bkden;
for (j=1;j<=n;j++) {
p[j]=bk*p[j]+z[j];
pp[j]=bk*pp[j]+zz[j];
}
}
bkden=bknum;
atimes(n,p,z,0);
for (akden=0.0,j=1;j<=n;j++) akden += z[j]*pp[j];
ak=bknum/akden;
atimes(n,pp,zz,1);
for (j=1;j<=n;j++) {
x[j] += ak*p[j];
r[j] -= ak*z[j];
rr[j] -= ak*zz[j];
}
asolve(n,r,z,0);
if (itol == 1 || itol == 2) {
znrm=1.0;
*err=snrm(n,r,itol)/bnrm;
} else if (itol == 3 || itol == 4) {
znrm=snrm(n,z,itol);
if (fabs(zm1nrm-znrm) > EPS*znrm) {
dxnrm=fabs(ak)*snrm(n,p,itol);
*err=znrm/fabs(zm1nrm-znrm)*dxnrm;
} else {
*err=znrm/bnrm;
continue;
}
xnrm=snrm(n,x,itol);
if (*err <= 0.5*xnrm) *err /= xnrm;
else {
*err=znrm/bnrm;
continue;
}
}
printf("iter=%4d err=%12.6f\n",*iter,*err);
if (*err <= tol) break;
}
free_dvector(p,1,n);
free_dvector(pp,1,n);
free_dvector(r,1,n);
free_dvector(rr,1,n);
free_dvector(z,1,n);
free_dvector(zz,1,n);
}
void PBCG::asolve(unsigned long n, double b[], double x[], int itrnsp)
{
unsigned long i;
for(i=1;i<=n;i++) x[i]=(sa[i] != 0.0 ? b[i]/sa[i] : b[i]);
}
void PBCG::atimes(unsigned long n, double x[], double r[], int itrnsp)
{
if (itrnsp) dsprstx(sa,ija,x,r,n);
else dsprsax(sa,ija,x,r,n);
}
double PBCG::snrm(unsigned long n, double sx[], int itol)
{
unsigned long i,isamax;
double ans;
if (itol <= 3) {
ans = 0.0;
for (i=1;i<=n;i++) ans += sx[i]*sx[i];
return sqrt(ans);
} else {
isamax=1;
for (i=1;i<=n;i++) {
if (fabs(sx[i]) > fabs(sx[isamax])) isamax=i;
}
return fabs(sx[isamax]);
}
}
void PBCG::dsprsax(double sa[], unsigned long ija[], double x[], double b[], unsigned long n)
{
unsigned long i,k;
if (ija[1] != n+2) nrerror("dsprsax: mismatched vector and matrix");
for (i=1;i<=n;i++) {
b[i]=sa[i]*x[i];
for (k=ija[i];k<=ija[i+1]-1;k++) b[i] += sa[k]*x[ija[k]];
}
}
void PBCG::dsprstx(double sa[], unsigned long ija[], double x[], double b[], unsigned long n)
{
unsigned long i,j,k;
if (ija[1] != n+2) nrerror("mismatched vector and matrix in dsprstx");
for (i=1;i<=n;i++) b[i]=sa[i]*x[i];
for (i=1;i<=n;i++) {
for (k=ija[i];k<=ija[i+1]-1;k++) {
j=ija[k];
b[j] += sa[k]*x[i];
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -