/* pde_abc_eq.c see WEB page for development, CMSC 455 supplemental */ /* The PDE to be solved is: */ /* a1(x,y)*uxx(x,y) + b1(x,y)*uxy(x,y) + c1(x,y)*uyy(x,y) + */ /* d1(x,y)*ux(x,y) + e1(x,y)*uy(x,y) + f1(x,y)*u(x,y) = c(x,y) */ /* */ /* Method is high order discretization */ /* The functions and other problem information is in the files: */ /* abc.h and abc.c */ /* compile with abc.c and deriv.c */ #include #include #include #include "abc.h" #include "deriv.h" #undef abs #define abs(a) ((a)<0.0?(-(a)):(a)) #undef min #define min(a,b) ((a)<(b)?(a):(b)) #undef max #define max(a,b) ((a)>(b)?(a):(b)) /* nx and ny are defined in abc.h */ static double us[(nx-2)*(ny-2)]; /* solution being computed */ static double uu[(nx-2)*(ny-2)]; /* solution if checking */ static double ut[(nx-2)*(ny-2)][(nx-2)*(ny-2)+1]; /* equations to be solved */ /* nx-2 by ny-2 internal, non boundary cells */ /* all elements 0..nx-1 by 0..ny-1 includes boundary elements */ /* xmin, xmax, ymin, ymax are defined in abc.h */ static double hx; /* x step = (xmax-xmin)/(nx-1) */ static double hy; /* y step = (ymax-ymin)/(ny-1) */ static double hx2, hy2, hxy; /* hx^2, hy^2, hx*hy */ static int cs; /* index of constant vector */ static double pdxx[nd][nd], pdxy[nd][nd], pdyy[nd][nd]; static double pdx[nd][nd], pdy[nd][nd], pd[nd][nd]; static int md; /* mid point correction nd/2 */ /* ifcheck defined in abc.h non zero for checking */ static double error; /* sum of absolute exact-computed */ static double avgerror; /* average error */ static double maxerror; /* maximum cell error */ static void check_soln(); static void clear() { int i, j, ii; for(i=0; i0) uu[ii] = u(xmin+(i+1)*hx,ymin+(j+1)*hy); } } } /* end clear */ static void printus() /* print the computed solution */ { int i, j, k; printf("\n computed solution\n"); printf("us[x,y] \n"); for(i=1; imaxerror) maxerror=err; } } } /* end check */ static void printexact() /* typically not known */ { int i, j; printf("\n exact solution\n"); printf("u(x,y) \n"); for(i=1; i1 , bye.\n"); exit(1);} if(nd!=5) { printf("init_matrix needs enhancement, bye.\n"); exit(1);} /* build discretization matrices */ if(ifcheck) printf("build_coef for point ix=%d, iy=%d \n", ix, iy); for(i=0; i3) printf("deriv pdxx returns bb=%d, aa=%d %d %d %d %d\n", bb, a[0], a[1], a[2], a[3], a[4]); for(i=0; i3) printf("deriv pdyy returns bb=%d, aa=%d %d %d %d %d \n", bb, a[0], a[1], a[2], a[3], a[4]); for(j=0; j3) printf("deriv pdx returns bb=%d, aa=%d %d %d %d %d \n", bb, a[0], a[1], a[2], a[3], a[4]); for(i=0; i3) printf("deriv pdy returns bb=%d, aa=%d %d %d %d %d \n", bb, a[0], a[1], a[2], a[3], a[4]); for(j=0; j2) print_coef(); } /* end build_coef */ static void check_row(int row) { int i, j, ii; double sum = 0.0; for(i=0; i0.001) printf("row=%d is bad err=%g \n", row, sum); } /* end check_row */ static void build_row(int i, int j, int bi, int bj) { /* i,j are in element coordinates, ir,jr are all element coord */ int ki, kj, ii, jj, ij, ir, jr, ia, ja; double p, a1c, b1c, c1c, d1c, e1c, f1c, cc; ir = i; jr = j; ii = (i-1)+(nx-2)*(j-1); /* row of matrix */ if(ifcheck>2) { printf("working row %d, i=%d, j=%d, bi=%d, bj=%d \n", ii, i, j, bi, bj); /* printf("x=%g, y=%g \n", xmin+ir*hx, ymin+jr*hy); */ } a1c = a1(xmin+ir*hx,ymin+jr*hy); b1c = b1(xmin+ir*hx,ymin+jr*hy); c1c = c1(xmin+ir*hx,ymin+jr*hy); d1c = d1(xmin+ir*hx,ymin+jr*hy); e1c = e1(xmin+ir*hx,ymin+jr*hy); f1c = f1(xmin+ir*hx,ymin+jr*hy); cc = c(xmin+ir*hx,ymin+jr*hy); if(ifcheck>5) { printf("a1c=%7.3f, b1c=%7.3f, c1c=%7.3f \n", a1c, b1c, c1c); printf("d1c=%7.3f, d1c=%7.3f, cc =%7.3f \n", d1c, e1c, cc); } for(ki=0; kinx-1) printf("***+error in ia=%d \n", ia); if(ja<0) printf("***-error in ja=%d \n", ja); if(ja>ny-1) printf("***+error in ja=%d \n", ja); if(ia==0) /* boundary value tests */ { ut[ii][cs] -= p * u(xmin+(ia)*hx, ymin+(ja)*hy); } else if(ia==nx-1) ut[ii][cs] -= p * u(xmin+(ia)*hx, ymin+(ja)*hy); else if(ja==0) ut[ii][cs] -= p * u(xmin+(ia)*hx, ymin+(ja)*hy); else if(ja==ny-1) ut[ii][cs] -= p * u(xmin+(ia)*hx, ymin+(ja)*hy); else /* non boundary case */ { ut[ii][ij] = p; if(ifcheck>5) printf("ij=%d, p=u[ii][ij]=%g \n", ij, ut[ii][ij]); } } } ut[ii][cs] += cc; printf("ii=%d, ut[ii][ii]=%g, ut[ii][cs]=%g \n\n", ii, ut[ii][ii], ut[ii][cs]); if(ifcheck>0) check_row(ii); } /* end build_row */ static void init_matrix() { int i, j, ii, jj; /* zero internal cells, the matrix does not include boundary cells */ for(i=1; i2) printf("working row edge i=%d, j=%d \n", i, j); build_row(i, j, -1, 0); } /* end j loop on edge */ build_coef(md+1, md, md); for(j=2; j2) printf("working row edge i=%d, j=%d \n", i, j); build_row(i, j, 1, 0); } /* end j loop on edge */ build_coef(md, md-1, md); for(i=2; i2) printf("working row edge i=%d, j=%d \n", i, j); build_row(i, j, 0 , -1); } /* end i loop on edge */ build_coef(md, md+1, md); for(i=2; i2) printf("working row edge i=%d, j=%d \n", i, j); build_row(i, j, 0 , 1); } /* end i loop on edge */ printf("four sides, one element in, special case, generated \n"); /* now do four corners */ i=1; j=1; build_coef(md-1, md-1, md); build_row(i, j, -1, -1); i=1; j=ny-2; build_coef(md-1, md+1, md); build_row(i, j, -1, 1); i=nx-2; j=1; build_coef(md+1, md-1, md); build_row(i, j, 1, -1); i=nx-2; j=ny-2; build_coef(md+1, md+1, md); build_row(i, j, 1, 1); } /* end init_matrix */ static void print_mat() { int i, j, k, ii; printf(" initial matrix \n"); for(i=0; i<(nx-2)*(ny-2); i++) { printf("i=%d, j=0 .. %d \n", i, (nx-2)*(ny-2)); for(k=0; k<=(nx-2)*(ny-2); k=k+nx-2) { for(j=0; j5) printf("check_soln setup \n"); for(i=0; i5) printf("ug[%d][%d]=%g \n", i, j, ug[i][j]); } } for(i=0; i5) { printf("cx=\n"); for(i=0; i5) { printf("numerical dxx=%g, dxy=%g,dyy=%g\n", dxx, dxy, dyy); printf("analytic dxx=%g, dxy=%g,dyy=%g\n", 6.0*x+6.0*y, 6.0*x+8.0*y+5.0, 12.0*y+8.0*x); printf("numerical dx=%g , dy=%g ,u=%g\n", dx, dy, ug[i][j]); printf("analytic dx=%g , dy=%g ,u=%g\n", 3.0*x*x+6.0*x*y+4.0*y*y+5.0*y+6.0, 6.0*y*y+3.0*x*x+8.0*x*y+5.0*x+7.0, u(x,y)); } err = a1(xg[i],yg[j])*dxx + b1(xg[i],yg[j])*dxy + c1(xg[i],yg[j])*dyy + d1(xg[i],yg[j])*dx + e1(xg[i],yg[j])*dy + f1(xg[i],yg[j])*ug[i][j] - /* PDE u term at i,j*/ c(xg[i],yg[j]); /* RHS */ err = abs(err); sumerr += err; sumsqerr += err*err; maxerr = max(err,maxerr); cnt++; } /* end j */ } /* end i */ rmserr = sqrt(sumsqerr/(double)cnt); avgerr = sumerr/(double)cnt; printf("check_soln values against PDE \n"); printf("maxerr=%g, rmserr=%g, avgerr=%g \n",maxerr,rmserr,avgerr); } /* end check_soln */ static void simeq(int n, int m, double B[(nx-2)*(ny-2)][(nx-2)*(ny-2)+1], double X[]) { /* tailored version for this problem */ int *row; /* row interchange indices */ int hold, i_pivot; /* pivot indices */ double pivot; /* pivot element value */ double abs_pivot; int i, j, k; row = (int *)calloc(n, sizeof(int)); /* set up row interchange vectors */ for(k=0; k abs_pivot) { i_pivot = i; pivot = B[row[i]][k]; abs_pivot = abs ( pivot ); } } /* have pivot, interchange row pointers */ hold = row[k]; row[k] = row[i_pivot]; row[i_pivot] = hold; /* check for near singular */ if( abs_pivot < 1.0E-10 ) { for(j=k+1; j