/* 2d linear elasticity */ int elasti1_2d(LSst *lsst) { pCsr A; int ier; char stim[32]; /* -- Part I: matrix assembly */ if ( lsst->info.verb != '0' ) fprintf(stdout," Matrix and right-hand side assembly\n"); /* counting P2 nodes (for dylib) */ if ( lsst->info.typ == P2 && !lsst->info.np2 ) { lsst->info.np2 = hashar_2d(lsst); if ( lsst->info.np2 == 0 ) { fprintf(stdout," # Error on P2 nodes.\n"); return(0); } } /* allocating memory (for dylib) */ if ( !lsst->sol.u ) { lsst->sol.u = (double*)calloc(lsst->info.dim*(lsst->info.npi+lsst->info.np2),sizeof(double)); assert(lsst->sol.u); } /* build matrix */ A = lsst->info.typ == P1 ? matA_P1_2d(lsst) : matA_P2_2d(lsst); lsst->sol.F = lsst->info.typ == P1 ? rhsF_P1_2d(lsst) : rhsF_P2_2d(lsst); /* free mesh structure + boundary conditions */ if ( !lsst->info.xport && lsst->info.mfree ) { free(lsst->mesh.tria); if ( !lsst->info.zip ) free(lsst->mesh.point); } /* -- Part II: solver */ if ( lsst->info.verb != '0' ) { fprintf(stdout," Solving linear system:"); fflush(stdout); ier = csrPrecondGrad(A,lsst->sol.u,lsst->sol.F,&lsst->sol.res,&lsst->sol.nit,1); if ( ier <= 0 ) fprintf(stdout,"\n # convergence problem: %d\n",ier); else fprintf(stdout," %E in %d iterations\n",lsst->sol.res,lsst->sol.nit); } else { ier = csrPrecondGrad(A,lsst->sol.u,lsst->sol.F,&lsst->sol.res,&lsst->sol.nit,1); } /* free memory */ csrFree(A); free(lsst->sol.F); return(ier > 0); }
/* solve Ax = b using preconditionned conjugate gradient method. Return code: >0 upon completion, <0 no convergence 0 memory problem -1 ill conditioned matrix -2 max it reached */ int csrPrecondGrad(pCsr A,double *x,double *b,double *er,int *ni,char tgv) { pCsr L; double *ap,*p,*q,*y; double dp,nn,rmp,rm,rm2,alpha,beta,err; int n,it,ier,nit; /* allocation */ if ( !x || !b ) return(0); assert(A->nr == A->nc); n = A->nr; y = (double*)malloc(A->nr*sizeof(double)); assert(y); /* compute R0 = y = b - A.x0 */ nn = csrXY(x,x,A->nr); if ( nn < CS_EPSD2 ) { memcpy(y,b,A->nr*sizeof(double)); } else { csrAxpy(A,x,b,y,-1.,1.); } rmp = csrXY(y,y,A->nr); if ( fabs(rmp) < CS_EPSD2 ) { free(y); return(1); } else if ( tgv ) { rmp /= CS_TGV2; } /* P_1 = P^-1.R_0 */ p = (double*)malloc(A->nr*sizeof(double)); q = (double*)malloc(A->nr*sizeof(double)); ap = (double*)malloc(A->nr*sizeof(double)); assert(p); assert(q); assert(ap); /* incomplete SSOR factorization */ L = csrTr(A); csrSSOR(A,L,p,y); err = *er; err = err * err * rmp; nit = *ni; ier = 1; it = 0; rm = rmp; while ( (err < rm) && ++it <= nit ) { /* alpha_m = <P^-1.R_m-1,R_m-1> / <AP_m,P_m> */ rm = csrXY(p,y,n); if ( fabs(rm) <= CS_EPSD2 ) break; dp = csrAxdotx(A,p,ap); if ( fabs(dp) <= CS_EPSD2 ) break; /* X_m = X_m-1 + alpha_m.P_m , R_m = R_m-1 - alpha_m AP_m */ alpha = (rm / dp); csrlXmY(p,x,x,alpha,1.0,n); csrlXmY(ap,y,y,-alpha,1.0,n); /* beta_m = <P^-1.R_m,R_m> / <P^-1.R_m-1,R_m-1> */ csrSSOR(A,L,q,y); rm2 = csrXY(q,y,n); if ( fabs(rm2) <= CS_EPSD2 ) break; /* P_m+1 = P^-1.R_m + beta_m P_m */ beta = rm2 / rm; csrlXmY(p,q,p,beta,1.0,n); //printf(" GC1: it %d err %E rm %E\n",it,err,rm2); rm = rm2; } if ( it > nit ) ier = -2; *er = sqrt(rm / rmp); *ni = it; free(p); free(q); free(y); free(ap); csrFree(L); return(ier); }