Esempio n. 1
0
boolean DL_largematrix::conjug_gradient(DL_largevector *x, DL_largevector *b){
// Solves Ax=b using conjugate gradient
// returns if the solution was diverging |Ax-b|>|b|
  static DL_largevector p,pp, r,rr, z,zz;

  if ((rep==lud) || (rep==ludb)) {
    DL_dsystem->get_companion()->Msg("DL_largematrix::conjug_grad not implemented for LU decomposed matrices\n");
    return FALSE;
  }

  int j, iter=0, itmax=nrrows;
  DL_Scalar ak, akden, bk, bkden=0, bknum, bnrm;

  p.resize(nrrows);
  pp.resize(nrrows);
  r.assign(b);
  rr.assign(b);
  z.resize(nrrows);
  zz.resize(nrrows);

  bnrm=b->norm();
  x->makezero();
  asolve(&r,&z);
  while (iter<itmax) {
    ++iter;
    asolve(&rr,&zz);
    bknum=z.inprod(&rr);
    if (iter==1) {
      p.assign(&z);
      pp.assign(&zz);
    }
    else {
      bk=bknum/bkden;
      for (j=0;j<nrrows;j++) {
	p.set(j,bk*p.get(j)+z.get(j));
	pp.set(j,bk*pp.get(j)+zz.get(j));
      }
    }
    bkden=bknum;
    times(&p,&z);
    akden=z.inprod(&pp);
    ak=bknum/akden;
    transposetimes(&pp,&zz);
    for(j=0;j<nrrows;j++) { // not very nice to use the implementation
      // of x, r and rr here, but += and -= are faster...
      x->v[j]+=ak*p.get(j);
       r.v[j]-=ak*z.get(j);
      rr.v[j]-=ak*zz.get(j);
    }
    asolve(&r,&z);

    if (r.norm()<=(TOL*bnrm)) break;
  }
  return (r.norm()>bnrm);
}
Esempio n. 2
0
void PCBCGSolver::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=new double[n+1];
    pp=new double[n+1];
    r=new double[n+1];
    rr=new double[n+1];
    z=new double[n+1];
    zz=new double[n+1];

    *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 printf("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;
    }

    delete [] p;
    delete [] pp;
    delete [] r;
    delete [] rr;
    delete [] z;
    delete [] zz;
    p = NULL;
    pp = NULL;
    r = NULL;
    rr = NULL;
    z = NULL;
    zz = NULL;
}
Esempio n. 3
0
void linbcg(unsigned long n, double b[], double x[], int itol, double tol,
	int itmax, int *iter, double *err)
{
	void asolve(unsigned long n, double b[], double x[], int itrnsp);
	void atimes(unsigned long n, double x[], double r[], int itrnsp);
	double snrm(unsigned long n, double sx[], int itol);
	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);
}