// pde_nl22.c solve non linear second order, second degree nonlinear // solve uxx*uxx + 2*uxx*uxy + uyy*uyy = f(x,y) // f(x,y) = 4*sin(x-y)^2 // with boundary ub(x,y) = sin(x-y) 0 < x < 1.0 < y < 1.0 // set up system of equations, use specialized Jacobian, simeq_newton3 // solution u(x,y) = sin(x-y) // x at i, y at ii rderiv or nuderiv cxx, cyy with nx=5, ny=5 // xg is X grid coordinates, yg is Y grid coordinates // subscripts 0 and 4 are known on boundary, thus there are 9 unknowns // u(xg[1],yg[1]), u(xg[2],yg[1]), u(xg[3],yg[1]), // u(xg[1],yg[2]), u(xg[2],yg[2]), u(xg[3],yg[2]), // u(xg[1],yg[3]), u(xg[2],yg[3]), u(xg[3],yg[3]) // thus 1 <= i <= 3, 1 <= ii <= 3 for inside boundary, boundary at 0 and 4 // // discrete uxx(xg[i],yg[ii) = cxx[0]*ub(xg[0],yg[ii]) + // cxx[1]* u(xg[1],yg[ii]) + cxx[2]* u(xg[2],yg[ii]) + // cxx[3]* u(xg[3],yg[ii]) + cxx[4]*ub(xg[4],yg[ii]); // // ub(xg[0]) and ub(xg[4]) are known boundary conditions, at xg 1,2,3 u unknown // similarly uyy(xg[i],yg[ii) = cyy[0]*ub(xg[i],yg[0]) + // cyy[1]* u(xg[i],yg[1]) + cyy[2]* u(xg[i],yg[2]) + // cyy[3]* u(xg[i],yg[3]) + cyy[4]*ub(xg[i],yg[4]); // // the product uxx(xg[i],yg[ii])*uyy(xg[i],yg[ii]) has 25 terms // 4 terms constant cxx[0]*ub(xg[0],yg[ii]) * cyy[0]*ub(xg[i],yg[0]) // cxx[4]*ub(xg[4],yg[ii]) * cyy[0]*ub(xg[i],yg[0]) // cxx[0]*ub(xg[0],yg[ii]) * cyy[4]*ub(xg[i],yg[4]) // cxx[4]*ub(xg[4],yg[ii]) * cyy[4]*ub(xg[i],yg[4]) // 12 terms one unknown // cxx[0]*ub(xg[0],yg[ii]) * cyy[1]* u(xg[i],yg[1]) // ... // cxx[4]*ub(xg[4],yg[ii]) * cyy[3]* u(xg[i],yg[3]) // 9 terms product of two unknonws // cxx[1]* u(xg[1],yg[ii]) * cyy[1]* u(xg[i],yg[1]) // ... // cxx[3]* u(xg[3],yg[ii]) * cyy[3]* u(xg[i],yg[3]) // // similarly for uxx*uxx and uyy*uxx #include #include #include #include "deriv.h" #include "simeq_newton3.h" // solve system of non linear equations // also needs invert.h and invert.c #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)) #define nx 7 #define ny 6 // number of equations and number of linear unknowns #define neqn (nx-2)*(ny-2) // number of nonlinear terms, all pairs of unknowns #define nlin neqn*neqn // total number of terms needed for nonlinear solution #define ntot neqn+nlin static double A[neqn][ntot]; // nonlinear system of equations static double F[neqn]; // RHS of nonlinear equations static double xg[nx]; // xgrid static double yg[ny]; // ygrid static double U[ntot]; // solution being computed and initial static double Ua[neqn]; // known solution for testing static double cxx[nx][nx]; // numerical second derivative i,j static double cyy[ny][ny]; // numerical second derivative ii,jj static int var1[ntot]; // unknown variable index in U static int var2[ntot]; // unknown variable index in U second power static int var3[ntot]; // unknown variable index in U third power static double xmin = 0.0; static double xmax = 0.6; static double ymin = 0.0; static double ymax = 0.4; static double hx, hy; static int check = 0; // 1 for much printout static double f(double x, double y) // RHS, forcing function { return 4.0*sin(x-y)*sin(x-y); } // end f // boundary values, in this case, exact solution for checking static double ub(double x, double y) { return sin(x-y); } // end ub static int S(int i, int ii) // 0 <= i <= nx, 0 <= ii <= ny { return (i-1)*(ny-2) + (ii-1); // unknown zero based inside boundary } // end S index into neqn static int SS(int unk, int nlk) // unknown i * ii nonlinear term { return neqn+unk*neqn+nlk; // zero based } // end SS index into ntot static void nlterms() // build var1, var2, var3 for simeq_newton3 { int i, j, ii, jj, unk, nlk, k; // linear, then nonlinear terms neqn, nlin for(i=1; ineqn) printf("error var1=%d at nlx=%d \n", var1[nlx], nlx); if(var2[nlx]<0 || var2[nlx]>neqn) printf("error var2=%d at nlx=%d \n", var2[nlx], nlx); if(var3[nlx] != -1) printf("error var3=%d at nlx=%d \n", var3[nlx], nlx); val += A[row][nlx]*Ua[var1[nlx]]*Ua[var2[nlx]]; if(check && (row==0 || row==19)) printf("nlx=%d, A[][]=%f, val=%f \n", nlx, A[row][nlx], val); } // end jj } // end j } // end ii } // end i err = val - F[row]; printf("check row=%d, F[row]=%f, err=%e \n", row, F[row], err); fflush(stdout); } // end check_row static void buildA() // A * U = F U unknown { int i, j, k, ii, jj, kk, row, unk, unk1, unk2, nlx; double val, valj, valk, valjj, valkk, txx, txxc, tyy, tyyc; // initialize A to zero, F was initialized for(i=0; i