/* abc_eq.c discretize, build linear equations, solve * solve 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) = c(x,y) * * where, for this test case * a1(x,y) = exp(x/2)*exp(y)/2 * b1(x,y) = 0.7/(x*x*y*y + 0.5) * c1(x,y) = (4 - exp(x) - exp(y/2))*2 * d1(x,y) = x*x+y * e1(x,y) = x*y*y * f1(x,y) = 3.0*x + 2.0*y * * c(x,y) = 0.5*exp(x/2.0)*exp(y)*(6.0*x+6.0*y) + * 0.7*(6.0*x + 8.0*y + 5.0)/(x*x*y*y+0.5) + * (8.0 - 2.0*exp(x) - 2.0*exp(y/2.0))*(12.0*y + 8.0*x) + * (x*x+y)*(3.0*x*x + 6.0*x*y + 4.0*y*y + 5.0*y + 6.0) + * x*y*y*(6.0*y*y + 3.0*x*x + 8.0*x*y + 5.0*x +7.0) + * 3.0*x + 2.0*y; * * The solution (normally only the boundary values are given) * u(x,y) = x^3 + 2y^3 + 3x^2 y + 4xy^2 + 5xy + 6x + 7y + 8 * * The solver uses #include "abc.h" to gain access to the users problem * Compile with abc.c to be able to call functions defined above * * replace continuous derivatives with discrete derivatives * solve for U(i,j) numerical approximation U(x_i,y_j) * A * U = F, solve simultaneous equations for U * * subscripts in code use x[i], y[ii] * derivatives are computed with b,hx,a included as in * cx[j] for first derivative of x at point j * cxx[j] for second derivative of x at point j * cx[j]*cy[jj] for d^2u/dy dx at j, jj * * The boundaries xmin..xmax, ymin..ymax are known * The number of grid points in each dimension is known nx, ny * hx=(xmax-xmin)/(nx-1), hy=(ymax-ymin)/(ny-1), * thus xg(i)=xmin+i*hx, yg(j)=ymin+j*hy for this test * non uniform grids could have non uniformly spaced values in xg, yg * then the linear system of equations is built, * nxy=(nx-2)*(ny-2) equations because the boundary value * is known on each end. * The matrix A is nxy rows by nxy columns (nxy+1) columns including F * The forcing function vector F is nxy elements adjunct to A * The solution vector U is nxy elements. * The building of the A matix requires 4 nested loops for rows * i in 1..nx-1, j in 1..ny-1, for rows of A * then each term in the differential equation fills in that row * and cs = (nx-2)*(ny-2) the RHS, fills the last column of A * subscripting functions are used to compute linear subscripts of A, U * row=(i-1)*(ny-2)+(ii-1) * row*(nxy+1)+col for A * * care must be taken to move the negative of boundary elements to * the right hand size of the equation to be solved. These are subtracted * from the computed value of the forcing function, cs, for that row. * tests are j==0 || j==nx-1 jj==0 || jj==ny-1 for boundaries */ #include #include #include #include #include "deriv.h" #include "simeq.h" #include "abc.h" #undef abs #define abs(x) ((x)<0.0?(-(x)):(x)) #undef min #define min(a,b) ((a)<(b)?(a):(b)) #undef max #define max(a,b) ((a)>(b)?(a):(b)) /* nx, ny, xmin, xmax, ymin, ymax defined in abc.h */ #define nxy (nx-2)*(ny-2) #define nn max(nx,ny) int s(int i, int ii) /* for x,y */ { return (i-1)*(ny-2) + (ii-1); } /* end s */ int sk(int k, int i, int ii) /* for x,y */ { return k*(nxy+1) + (i-1)*(ny-2) + (ii-1); } /* end sk */ int ss(int i, int ii, int j, int jj) { return s(i,ii)*(nxy+1) + s(j,jj); } /* end ss */ static double A[nxy*(nxy+1)]; /* last column is RHS */ static double U[nxy]; static double xg[nx]; static double yg[ny]; static double Ua[nxy]; static double hx, hy; void printA() { int i, ii, j, jj, cs, k; cs = (nx-2)*(ny-2); /* constant RHS column */ for(i=1; ismaxerr) smaxerr = err; } /* end ii */ } /* end i */ printf("check_soln maxerr=%g \n",smaxerr); } /* end check_soln */ int main(int argc, char *argv[]) { double x, y; int i, ii, j, jj; int k, cs; /* coeficients of terms in first equation */ double coefdxx; /* computed below if not constant */ double coefdxy; double coefdyy; double coefdx; double coefdy; double coefu; /* derivative point arrays, dynamic in this version */ double cx[nx], cy[ny]; double cxx[nx], cyy[ny]; double val, err, avgerr, maxerr; double time_start; double time_now; double time_last; printf("abc_eq.c running \n"); printf("Given a1(x,y)*uxx(x,y) + b1(x,y)*uxy(x,y) + c1(x,y)*uyy(x,y) +\n"); printf(" d1(x,y)*ux(x,y) + e1(x,y)*uy(x,y) + f1(x,y) = c(x,y) \n"); printf("where, for this test case \n"); printf(" a1(x,y) = exp(x/2)*exp(y)/2 \n"); printf(" b1(x,y) = 0.7/(x*x*y*y + 0.5) \n"); printf(" c1(x,y) = (4 - exp(x) - exp(y/2))*2 \n"); printf(" d1(x,y) = x*x+y \n"); printf(" e1(x,y) = x*y*y \n"); printf(" f1(x,y) = 3.0*x + 2.0*y \n"); printf(" \n"); printf(" c(x,y) = 0.5*exp(x/2.0)*exp(y)*(6.0*x+6.0*y) + \n"); printf(" 0.7*(6.0*x + 8.0*y + 5.0)/(x*x*y*y+0.5) + \n"); printf(" (8.0 - 2.0*exp(x) - 2.0*exp(y/2.0))*(12.0*y + 8.0*x) + \n"); printf(" (x*x+y)*(3.0*x*x + 6.0*x*y + 4.0*y*y + 5.0*y + 6.0) + \n"); printf(" x*y*y*(6.0*y*y + 3.0*x*x + 8.0*x*y + 5.0*x +7.0) + \n"); printf(" 3.0*x + 2.0*y; \n"); printf(" \n"); printf("xmin<=x<=xmax ymin<=y<=ymax zmin<=z<=zmax Boundaries \n"); printf("Analytic solution \n"); printf(" u(x,y) = x^3 + 2y^3 + 3x^2 y + 4xy^2 + 5xy + 6x + 7y + 8 \n"); printf(" \n"); printf("xmin=%g, xmax=%g, ymin=%g, ymax=%g \n", xmin, xmax, ymin, ymax); printf("nx=%d, ny=%d \n", nx, ny); time_start = (double)clock()/(double)CLOCKS_PER_SEC; printf("time start = %f seconds \n", time_start); time_last = time_start; printf("x grid and analytic solution at ymin \n"); hx = (xmax-xmin)/(double)(nx-1); for(i=0; imaxerr) maxerr = err; avgerr = avgerr + err; printf("ug[%d,%d]=%9.4f, Ua=%9.4f, err=%g \n", i, ii, U[s(i,ii)], Ua[s(i,ii)], err); } /* ii */ } /* i */ time_now = (double)clock()/(double)CLOCKS_PER_SEC; printf("total CPU time = %f seconds \n", time_now-time_start); printf("\n"); printf(" maxerr=%g, avgerr=%g \n", maxerr, avgerr/(double)(nx*ny)); printf("\n"); printf("end abc_eq.c \n"); return 0; } /* end main */ /* end abc_eq.c */