/* pde3_gl.c just checking second order approximation */ /* z(x,y) = x^3 + y^3 + 2x^2y + 3xy^2 + 4x + 5y + 6 */ /* dz/dx = 3x^2 + 0 + 4xy + 3y^2 + 4 + 0 + 0 */ /* d^2z/dx^2 = 6x + 0 + 4y + 0 + 0 + 0 + 0 */ /* dz/dy = 0 + 3y^2 + 2x^2 + 6xy + 0 + 5 + 0 */ /* d^2z/dy^2 = 0 + 6y + 0 + 6x + 0 + 0 + 0 */ /* */ /* solve d^2z/dx^2 + d^2z/dy^2 = 12x + 10y = c(x,y) */ /* by second order method on square -1,-1 to 1,1 */ /* second order numerical difference */ /* d^2z/dx^2 + d^2z/dy^2 = */ /* 1/h^2(z(-1h,0)+z(1h,0)+z(0,-1h)+z(0,1h)-4z(0,0)) +O(h^2) */ /* = c(x,y) */ /* solve for new z(0,0) = */ /* ((z(-1h,0)+z(1h,0)+z(0,-1h)+z(0,1h)) - c(x,y)*h^2)/4 */ /* Mouse buttons control axis of rotation */ /* arrow keys control axis of rotation, also */ /* "f" and "s" make rotation faster or slower */ /* "W" and "w" make wireframe or solid */ #include #include #include #undef abs #define abs(a) ((a)<0.0?(-(a)):(a)) #undef min #define min(a,b) ((a)<(b)?(a):(b)) static int nx = 41; static int ny = 41; static double zs[100][100]; /* solution being interated */ static double zt[100][100]; /* temporary for partical results */ /* nx-2 by ny-2 internal, non boundary cells */ static double xmin = -2.0; static double ymin = -2.0; static double xmax = 4.0; static double ymax = 4.0; static double zmax; static double zmin; static double h; /* x and y step = (xmax-xmin)/(n-1) */ static double diff = 1.0e6; /* sum abs difference form last ineration */ static double error; /* sum of absolute exact-computed */ static double avgerror; /* average error */ static double maxerror; /* maximum cell error */ static int iter = 0; /* iteration counter */ static int max_iter = 3500; /* maximum iterations */ /* graphics values */ static GLfloat theta[] = {60.0,90.0,0.0}; static GLint axis = 1; static GLint windoww = 700; static GLint windowh = 700; static double rotation = 0.0; /* 'f' or 's' */ static int wireframe = 1; /* 'W' or 'w' */ static double scalex = 1.0; /* scale x to -1..1 */ static double scaley = 1.0; /* scale y to -1..1 */ static double scalez = 1.0; /* scale z to -1..1 */ static double offsetx = 0.0; /* offset to center */ static double offsety = 0.0; /* offset to center */ static double offsetz = 0.0; /* offset to center */ static int run = 0; /* run/pause */ static int step = 0; /* step */ static int xm, ym; /* global mouse x,y */ /* no function prototypes used here because the functions are defined */ /* before they are used */ static double z(double x, double y) /* for boundary and check */ { return x*x*x + y*y*y + 2.0*x*x*y + 3.0*x*y*y + 4.0*x + 5.0*y +6.0; } static double c(double x, double y) /* from solve */ { return 12.0*x + 10.0*y; } static double z00(int i, int j) /* new iterated value */ { return ( zs[i-1][j] + zs[i+1][j] + zs[i][j-1] + zs[i][j+1] - c(xmin+i*h,ymin+j*h)*h*h )/4.0; } static void init_boundary() { int i, j; zmin = z(xmin, ymin); /* save zmin and zmax for plotting */ zmax = zmin; /* set boundary on four sides */ for(i=0; izmax) zmax = zs[i][0]; if(zs[i][ny-1]zmax) zmax = zs[i][ny-1]; } for(j=0; jzmax) zmax = zs[0][j]; if(zs[nx-1][j]zmax) zmax = zs[nx-1][j]; } /* zero internal cells */ for(i=1; imaxerror) maxerror=err; } } } /* end check */ static void printzs() { int i, j; printf("\n computed solution\n"); for(i=0; i 360.0) theta[axis] = theta[axis] - 360.0; if(diff>0.0001 && iterx && xmy && ym2) axis=0; if(theta[axis]==0.0) theta[axis]= 0.25; } xm = x; /* global mouse coordinates */ ym = windowh-y; if(btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) { if(in_rect(windoww-100, 5, windoww-5, 30)) /* restart */ { iter = 0; init_boundary(); diff = 1.0e6; } else if(in_rect(windoww-200, 5, windoww-105, 30)) /* run */ { run = 1; } else if(in_rect(windoww-300, 5, windoww-205, 30)) /* step */ { step = 1; } else if(in_rect(windoww-400, 5, windoww-305, 30)) /* pause */ { run = 0; } } glutPostRedisplay(); } /* end mouse */ static void keyboard(unsigned char key, int x, int y) { if(key == 'f') {rotation=rotation+0.25; if(rotation>5.0) rotation=5.0;} if(key == 's') {rotation=rotation-0.25; if(rotation<0.0) rotation=0.0;} if(key == 'W') wireframe=1; if(key == 'w') wireframe=0; if(key == 'p') run = 0; if(key == 'r') run = 1; /* Use x, X, y, Y, z, Z to change angle about axis */ if(key == 'x') theta[0] -= 2.0; if(key == 'X') theta[0] += 2.0; if(key == 'y') theta[1] -= 2.0; if(key == 'Y') theta[1] += 2.0; if(key == 'z') theta[2] -= 2.0; if(key == 'Z') theta[2] += 2.0; glutPostRedisplay(); } /* end keyboard */ static void special(int k, int x, int y) { switch(k) { case GLUT_KEY_LEFT: axis = 1; break; case GLUT_KEY_RIGHT: axis = 2; break; case GLUT_KEY_DOWN: axis = 0; break; case GLUT_KEY_UP: wireframe = 1-wireframe; break; } } /* end sprcial */ static void myReshape(int w, int h) { glViewport(0, 0, w, h); windoww = w; windowh = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); if(w <= h) glOrtho(-1.5, 1.5, -1.5 * (GLfloat)h / (GLfloat)w, 1.5 * (GLfloat)h / (GLfloat)w, -10.0, 10.0); else glOrtho(-1.5 * (GLfloat)w / (GLfloat)h, 1.5 * (GLfloat)w / (GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glClearColor(1.0, 1.0, 1.0, 1.0); } /* end myReshape */ int main(int argc, char *argv[]) { printf("pde3.c running\n"); h = (xmax-xmin)/(nx-1); /* step size in x */ /*= (ymax-ymin)/(ny-1); step size in y */ printf("xmin=%g, xmax=%g, nx=%d, h=%g \n", xmin, xmax, nx, h); printf("ymin=%g, ymax=%g, ny=%d, h=%g \n", ymin, ymax, ny, h); init_boundary(); scalex = 2.0/(xmax-xmin); scaley = 2.0/(ymax-ymin); scalez = 2.0/(zmax-zmin); offsetx = -(xmax+xmin)/2.0; offsety = -(ymax+ymin)/2.0; offsetz = -(zmax+zmin)/2.0; glutInit(&argc, argv); /* need both double buffering and z buffer */ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); glutInitWindowSize(windoww, windowh); glutCreateWindow(argv[0]); glutReshapeFunc(myReshape); /* enable resize/reshape */ glutDisplayFunc(display); /* enable display */ glutIdleFunc(spin_pde); /* enable idle function */ glutMouseFunc(mouse); /* enable mouse */ glutKeyboardFunc(keyboard); /* enable keyboard */ glutSpecialFunc(special); /* enable arrow keys */ glEnable(GL_DEPTH_TEST); /* enable hidden surface removal */ glutMainLoop(); return 0; } /* end pde3_gl.c */