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; }
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; }
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; }
/** \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); }