2 Over-relaxation solution to Poisson equation
6 ( Max # iteration, grid in x, grid in y )
8 Note: only written for equal x and y meshes -- N_x = N_y
10 IBOUND: positions on grid corresponding to boundaries
12 Modular code - simple main code - logical functions
17 gcc poisson_2d.c -lm -o poisson_2d
19 ./poisson_2d N N_x N_y | plot_image.py -s N_x N_y -t "2d Poisson"
28 #define MAX_x 350 /* maximum dimensions */
31 #define EPS 1.0e-7 /* tolerance in solution */
33 #define IMAGE 1 /* image - yes (1) - no (0) */
35 /* global array & file to record solution */
36 int ibound[MAX_x][MAX_y];
37 double phi[MAX_x][MAX_y], ff[MAX_x][MAX_y];
40 /* lattice definition & iteration number */
41 void set_grid ( int argc, char *argv[], int *N_iterations,
42 int *NI, int *NJ, double *h )
46 printf( " Syntax: poisson N N_x N_y ( where N_x = N_y ) \n" );
49 *N_iterations = atoi(argv[1]);
55 fprintf( stderr, " Code only setup for N_x = N_y \n");
59 if ( *NI > MAX_x || *NJ > MAX_y)
61 fprintf( stderr, " Grid dimensions too large \n");
65 *h = 1.0/(double)(*NI-1);
69 /* initial phi values, source & boundary conditions */
70 void initial_source_and_boundary ( int NI, int NJ )
74 /* initial fields & source*/
75 for ( i=0 ; i<NI ; i++ )
77 for ( j=0 ; j<NJ ; j++)
79 r2 = (i-NI/5)*(i-NI/5) + (j-3*NJ/4)*(j-3*NJ/4);
80 ff[i][j] = 7000 * exp( - 0.01 * r2 );
85 /* Boundary Conditions */
86 for ( j=0 ; j<NJ ; j++)
93 for ( i=0 ; i<NI ; i++ )
100 /* single values somewhere in square */
102 ibound[i_s][3*NJ/4] = 1;
103 phi[i_s][3*NJ/4] = -25.0;
105 ibound[i_s][NJ/3] = 1;
106 phi[i_s][NJ/3] = -10.0;
110 fprintf( stderr, " Grid size: %d x %d \n", NI, NJ );
115 /* check solution & output field data for image */
116 void output_results( int NI, int NJ, double h )
119 double aux, phi_min, phi_max, residual, largest_residual;
121 /* check if solution is */
122 /* really a solution */
123 fprintf( stderr, " Check - ( LHS - RHS ) \n");
124 largest_residual = 0.0;
125 for ( i=0 ; i<NI ; i++ )
127 for ( j=0 ; j<NJ ; j++)
129 /* min & max of phi as an aside */
130 if ( phi[i][j] < phi_min ) phi_min = phi[i][j];
131 if ( phi[i][j] > phi_max ) phi_max = phi[i][j];
133 if ( ibound[i][j] == 0 )
135 residual = phi[i+1][j] + phi[i-1][j] +
136 phi[i][j+1] + phi[i][j-1] -
137 4.0 * phi[i][j] - h * h * ff[i][j];
143 if( fabs( residual ) > largest_residual )
144 largest_residual = fabs( residual );
148 fprintf( stderr, "largest residual : %e \n", largest_residual );
150 /* output phi for image */
153 aux = 255.0 / ( phi_max - phi_min );
154 for ( i=0 ; i<NI ; i++ )
156 for ( j=0 ; j<NJ ; j++)
157 printf( " %f \n", aux * ( phi[i][j] - phi_min ) );
163 /* one Gauss-Siedel iteration */
164 void Gauss_Siedel_step( int NI, int NJ, int iter,
165 double *diff, double h )
168 double difference, aux, chi;
170 /* over-relaxation control */
172 if ( iter > 30 ) chi = 1.2;
173 if ( iter > 50 ) chi = 1.8;
174 /* Gauss-Siedel update */
176 for ( i=0 ; i<NI ; i++ )
178 for ( j=0 ; j<NJ ; j++)
180 if ( ibound[i][j] == 0 )
183 phi[i][j] = 0.25 * ( phi[i+1][j] + phi[i-1][j] +
184 phi[i][j+1] +phi[i][j-1] - h * h * ff[i][j] );
185 phi[i][j] = (1-chi)*aux + chi*phi[i][j];
186 if ( difference < fabs( aux - phi[i][j] ) )
187 difference = fabs( aux - phi[i][j] );
191 fprintf( stderr, " iter: %d - error %e \n", iter, difference );
198 int main ( int argc, char *argv[] )
202 double diff, aux, chi;
203 int N_iterations, iter;
205 /* lattice definition & */
206 /* iteration number */
207 set_grid ( argc, argv, &N_iterations, &NI, &NJ, &h );
208 /* initial fields, source */
209 /* & boundary conditions */
210 initial_source_and_boundary ( NI, NJ );
211 /* iterate the solution */
212 for ( iter=1 ; iter<N_iterations ; iter++ )
214 /* Gauss-Siedel iteration */
215 Gauss_Siedel_step( NI, NJ, iter, &diff, h );
216 /* solution accurate enough ? */
217 if ( diff < EPS ) break;
219 /* check & output the phi field */
220 output_results ( NI, NJ, h );