コード例 #1
0
long jacobi_preconditioned_conjugate_gradient_search(long icnt, double epsilon,  DOUBLEVECTOR *x, DOUBLEVECTOR *b, t_Matrix_element funz) {

    /*!
     *\param icnt  - (long) number of reiterations
     *\param epsilon - (double) required tollerance (2-order norm of the residuals)
     *\param x     - (DOUBLEVECTOR *) vector of the unknowns x in Ax=b
     *\param b     - (DOUBLEVECTOR *) vector of b in Ax=b
     *\param funz  - (t_Matrix_element) - (int) pointer to the application A (x and y doublevector y=A(param)x ) it return 0 in case of success, -1 otherwise.
     *
     *
     *\brief algorithm proposed by Jonathan Richard Shewckuck in http://www.cs.cmu.edu/~jrs/jrspapers.html#cg and http://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf
     *
     * \author Emanuele Cordano
     * \date June 2009
     *
     *\return the number of reitarations
     */


    double delta,delta_new,alpha,beta,delta0;
    DOUBLEVECTOR *r, *d,*q,*y,*sr,*diag;

    int sl;
    long icnt_max;
    long j;
    double p;

    r=new_doublevector(x->nh);
    d=new_doublevector(x->nh);
    q=new_doublevector(x->nh);
    y=new_doublevector(x->nh);
    sr=new_doublevector(x->nh);
    diag=new_doublevector(x->nh);

    icnt=0;
    icnt_max=x->nh;


    for (j=x->nl; j<=x->nh; j++) {
        y->element[j]=(*funz)(j,x);

    }

    get_diagonal(diag,funz);
//    print_doublevector_elements(diag,PRINT);
//    stop_execution();

    delta_new=0.0;

    for (j=y->nl; j<=y->nh; j++) {

        r->element[j]=b->element[j]-y->element[j];
        if (diag->element[j]<0.0) {
            diag->element[j]=1.0;
            printf("\n Error in jacobi_preconditioned_conjugate_gradient_search function: diagonal of the matrix (%lf) is negative at %ld \n",diag->element[j],j);
            stop_execution();
        }
        //  	diag->element[j]=fmax(diag->element[j],MAX_VALUE_DIAG*fabs(r->element[j]));

        //d->element[j]=r->element[j]/diag->element[j];
        if (diag->element[j]==0.0) {  //ec 20100315
            d->element[j]=0.0;
        } else {
            d->element[j]=r->element[j]/(diag->element[j]);
        }

        delta_new+=r->element[j]*d->element[j];
    }


    //  printf("delta0 =%le", delta0);

    //  double epsilon0=epsilon;
//    double pe=5.0;


    while ((icnt<=icnt_max) && (max_doublevector(r)>epsilon)) {

        delta=delta_new;
        //	s=(* funz)(q,d);
        p=0.0;

        for(j=q->nl; j<=q->nh; j++) {
            q->element[j]=(*funz)(j,d);
            p+=q->element[j]*d->element[j];

        }
        alpha=delta_new/p;
        for(j=x->nl; j<=x->nh; j++) {
            x->element[j]=x->element[j]+alpha*d->element[j];
        }


        delta_new=0.0;
        sl=0;
        for (j=y->nl; j<=y->nh; j++) {
            if (icnt%MAX_REITERTION==0) {
                y->element[j]=(*funz)(j,x);
                r->element[j]=b->element[j]-y->element[j];
            } else {
                r->element[j]=r->element[j]-alpha*q->element[j];
            }
            if (diag->element[j]==0.0) { // ec_20100315
                sr->element[j]=0.0;
                d->element[j]=0.0;
            } else {
                sr->element[j]=r->element[j]/diag->element[j];
            }

            delta_new+=sr->element[j]*r->element[j];
            /*    	if (((j==y->nl) && sl==0 ) || (sl==1)) {
            	    		printf("delta_new =%le (j=%ld)  ",delta_new,j);
            	//    		if (delta_new==0.0) sl=1;
            	    	}*/
        }
        beta=delta_new/delta;
        // double aa=1.0e-21;
        // ec  Initial residual:   printf("delta_new =%le p=%le alpha=%le beta=%le delta_max=%le\n",delta_new,p,alpha,beta,max_doublevector(r));

        for (j=d->nl; j<=d->nh; j++) {
            d->element[j]=sr->element[j]+beta*d->element[j];
        }

        icnt++;


    }
    free_doublevector(diag);
    free_doublevector(sr);
    free_doublevector(r);
    free_doublevector(d);
    free_doublevector(q);
    free_doublevector(y);



    return icnt;

}
コード例 #2
0
ファイル: sparse_matrix.c プロジェクト: zitan/geotop1zi
long CG(double tol_rel, double tol_min, double tol_max, DOUBLEVECTOR *x, DOUBLEVECTOR *x0, double dt, 
		DOUBLEVECTOR *b, t_Matrix_element_with_voidp function, void *data){

	/*!
	 *\param icnt  - (long) number of reiterations
	 *\param epsilon - (double) required tollerance (2-order norm of the residuals)
	 *\param x     - (DOUBLEVECTOR *) vector of the unknowns x in Ax=b
	 *\param b     - (DOUBLEVECTOR *) vector of b in Ax=b
	 *\param funz  - (t_Matrix_element_with_voidp) - (int) pointer to the application A (x and y doublevector y=A(param)x ) it return 0 in case of success, -1 otherwise.
	 *\param data - (void *) data and parameters related to the  argurment  t_Matrix_element_with_voidp funz
	 *
	 *
	 *\brief algorithm proposed by Jonathan Richard Shewckuck in http://www.cs.cmu.edu/~jrs/jrspapers.html#cg and http://www.cs.cmu.edu/~quake-papers/painless-conjugate-gradient.pdf
	 *
	 * \author Emanuele Cordano
	 * \date June 2009
	 *
	 *\return the number of reitarations
	 */


	double delta,alpha,beta,delta_new;
	DOUBLEVECTOR *r, *d,*q,*y,*sr,*diag,*udiag;

	int sl;
	long icnt_max;
	long icnt;
	long j;
	double p;
	double norm_r0;

	r=new_doublevector(x->nh);
	d=new_doublevector(x->nh);
	q=new_doublevector(x->nh);
	y=new_doublevector(x->nh);
	sr=new_doublevector(x->nh);
	diag=new_doublevector(x->nh);
	udiag=new_doublevector(x->nh-1);
	
	icnt=0;
	icnt_max=x->nh;
	//icnt_max=(long)(sqrt((double)x->nh));

	for (j=x->nl;j<=x->nh;j++){
		y->co[j]=(*function)(j,x,x0,dt,data);
	}

    get_diagonal(diag,x0,dt,function,data);
    get_upper_diagonal(udiag,x0,dt,function,data);
	
    delta_new=0.0;

    for (j=y->nl;j<=y->nh;j++) {

    	r->co[j]=b->co[j]-y->co[j];

    	if (diag->co[j]<0.0) {
    		diag->co[j]=1.0;
    		printf("\n Error in jacobi_preconditioned_conjugate_gradient_search function: diagonal of the matrix (%lf) is negative at %ld \n",diag->co[j],j);
    		stop_execution();
    	}
		
    }
	
    tridiag(0,0,0,x->nh,udiag,diag,udiag,r,d);

    for (j=y->nl;j<=y->nh;j++) {
    	//d->co[j]=r->co[j]/diag->co[j];
    	delta_new+=r->co[j]*d->co[j];
    }
	
	norm_r0 = norm_2(r, r->nh);
					
	while ( icnt<=icnt_max && norm_2(r, r->nh) > Fmax( tol_min , Fmin( tol_max , tol_rel*norm_r0) ) ) {

		delta=delta_new;
		p=0.0;

		for(j=q->nl;j<=q->nh;j++) {
			q->co[j]=(*function)(j,d,x0,dt,data);
			p+=q->co[j]*d->co[j];

		}
		alpha=delta_new/p;
		for(j=x->nl;j<=x->nh;j++) {
			x->co[j]=x->co[j]+alpha*d->co[j];
		}


	    delta_new=0.0;
	    sl=0;
	    for (j=y->nl;j<=y->nh;j++) {
	    	if (icnt%MAX_ITERATIONS==0) {
					y->co[j]=(*function)(j,x,x0,dt,data);
					r->co[j]=b->co[j]-y->co[j];
	    	} else {
					r->co[j]=r->co[j]-alpha*q->co[j];
	    	}
	    }

	    tridiag(0,0,0,x->nh,udiag,diag,udiag,r,sr);

	    for (j=y->nl;j<=y->nh;j++) {
	    	delta_new+=sr->co[j]*r->co[j];

	    }
	    beta=delta_new/delta;
		for (j=d->nl;j<=d->nh;j++) {
			 d->co[j]=sr->co[j]+beta*d->co[j];
		}

		icnt++;

		//printf("i:%ld normr0:%e normr:%e\n",icnt,norm_r0,norm_2(r,r->nh));


	}

	//printf("norm_r:%e\n",norm_2(r,r->nh));

	free_doublevector(udiag);
	free_doublevector(diag);
	free_doublevector(sr);
	free_doublevector(r);
	free_doublevector(d);
	free_doublevector(q);
	free_doublevector(y);


	return icnt;

}
コード例 #3
0
ファイル: sparse_matrix.c プロジェクト: zitan/geotop1zi
long BiCGSTAB(double tol_rel, double tol_min, double tol_max, DOUBLEVECTOR *x, DOUBLEVECTOR *x0, 
			  double dt, DOUBLEVECTOR *b, t_Matrix_element_with_voidp function, void *data){

	/* \author Stefano Endrizzi
	   \date March 2010	
	   from BI-CGSTAB: A FAST AND SMOOTHLY CONVERGING VARIANT OF BI-CG FOR THE SOLUTION OF NONSYMMETRIC LINEAR SYSTEMS
	   by H. A. VAN DER VORST - SIAM J. ScI. STAT. COMPUT. Vol. 13, No. 2, pp. 631-644, March 1992
	*/

	DOUBLEVECTOR *r0, *r, *p, *v, *s, *t, *diag, *udiag, *y, *z;
	//DOUBLEVECTOR *tt, *ss;
	double rho, rho1, alpha, omeg, beta, norm_r0;
	long i=0, j;
	
	r0 = new_doublevector(x->nh);
	r = new_doublevector(x->nh);
	p = new_doublevector(x->nh);
	v = new_doublevector(x->nh);
	s = new_doublevector(x->nh);
	t = new_doublevector(x->nh);
	diag = new_doublevector(x->nh);
	udiag = new_doublevector(x->nh-1);
	y = new_doublevector(x->nh);
	z = new_doublevector(x->nh);
	//tt = new_doublevector(x->nh);
	//ss = new_doublevector(x->nh);
	
	get_diagonal(diag,x0,dt,function,data);
    get_upper_diagonal(udiag,x0,dt,function,data);

    for (j=x->nl;j<=x->nh;j++ ) {		
    	r0->co[j] = b->co[j] - (*function)(j,x,x0,dt,data);
		r->co[j] = r0->co[j];
		p->co[j] = 0.;
		v->co[j] = 0.;
    }
	
	norm_r0 = norm_2(r0,r0->nh);
	
	rho = 1.;
	alpha = 1.;
	omeg = 1.;
	
	while ( i<=x->nh && norm_2(r,r->nh) > Fmax( tol_min , Fmin( tol_max , tol_rel*norm_r0) ) ) {
		
		rho1 = product(r0, r);
		
		beta = (rho1/rho)*(alpha/omeg);
		
		rho = rho1;
		
		for (j=x->nl;j<=x->nh;j++ ) {		
			p->co[j] = r->co[j] + beta*(p->co[j] - omeg*v->co[j]);
		}
		
		tridiag(0, 0, 0, x->nh, udiag, diag, udiag, p, y);
		
		for (j=x->nl;j<=x->nh;j++ ) {	
			v->co[j] = (*function)(j,y,x0,dt,data);
		}
		
		alpha = rho/product(r0, v);
		
		for (j=x->nl;j<=x->nh;j++ ) {		
			s->co[j] = r->co[j] - alpha*v->co[j];
		}
		
		tridiag(0, 0, 0, x->nh, udiag, diag, udiag, s, z);	
		
		for (j=x->nl;j<=x->nh;j++ ) {	
			t->co[j] = (*function)(j,z,x0,dt,data);
		}
		
		/*tridiag(0, 0, 0, x->nh, udiag, diag, udiag, t, tt);
		tridiag(0, 0, 0, x->nh, udiag, diag, udiag, s, ss);
		omeg = product(tt, ss)/product(tt, tt);*/
		
		omeg = product(t, s)/product(t, t);
		
		for (j=x->nl;j<=x->nh;j++ ) {		
			x->co[j] += (alpha*y->co[j] + omeg*z->co[j]);
			r->co[j] = s->co[j] - omeg*t->co[j];
		}
		
		i++;
		
		//printf("i:%ld normr0:%e normr:%e\n",i,norm_r0,norm_2(r,r->nh));
		
	}
	
	
	free_doublevector(r0);
	free_doublevector(r);
	free_doublevector(p);
	free_doublevector(v);
	free_doublevector(s);
	free_doublevector(t);
	free_doublevector(diag);
	free_doublevector(udiag);
	free_doublevector(y);
	free_doublevector(z);
	//free_doublevector(tt);
	//free_doublevector(ss);
	
	return i;
	
}
コード例 #4
0
ファイル: mtx.cpp プロジェクト: veverjak/SparseMatrix
/**
  \brief Resi soustavu D*y = z
  \param z - ziskano z solve_Lzb(const VTR& b, VTR& z)
*/
void MTX::solve_Dyz(const VTR& z, VTR& y)
{
    y.initialize(row_number);
    for(long i=0;i<row_number;i++)
        y.val[i]=z.val[i]/get_diagonal(i);
}