+++ /dev/null
-/*
- Over-relaxation solution to Poisson equation
-
- Syntax
- Poisson N N_x N_y
- ( Max # iteration, grid in x, grid in y )
-
- Note: only written for equal x and y meshes -- N_x = N_y
-
- IBOUND: positions on grid corresponding to boundaries
-
- Modular code - simple main code - logical functions
-
-
- Build & use of code
-
-gcc poisson_2d.c -lm -o poisson_2d
-
-./poisson_2d N N_x N_y | plot_image.py -s N_x,N_y -t "2d Poisson"
-
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#define MAX_x 350 /* maximum dimensions */
-#define MAX_y 350
-
-#define EPS 1.0e-7 /* tolerance in solution */
-
-#define IMAGE 1 /* image - yes (1) - no (0) */
-
- /* global array & file to record solution */
-int ibound[MAX_x][MAX_y];
-double phi[MAX_x][MAX_y], ff[MAX_x][MAX_y];
-
-
-/* lattice definition & iteration number */
-void set_grid ( int argc, char *argv[], int *N_iterations,
- int *NI, int *NJ, double *h )
-{
- if ( argc != 4 )
- {
- printf( " Syntax: poisson N N_x N_y ( where N_x = N_y ) \n" );
- exit(1);
- }
- *N_iterations = atoi(argv[1]);
- *NI = atoi(argv[2]);
- *NJ = atoi(argv[3]);
-
- if ( *NI != *NJ )
- {
- fprintf( stderr, " Code only setup for N_x = N_y \n");
- exit(1);
- }
-
- if ( *NI > MAX_x || *NJ > MAX_y)
- {
- fprintf( stderr, " Grid dimensions too large \n");
- exit(1);
- }
-
- *h = 1.0/(double)(*NI-1);
-}
-
-
-/* initial phi values, source & boundary conditions */
-void initial_source_and_boundary ( int NI, int NJ )
-{
- int i, j, i_s;
- double r2;
- /* initial fields & source*/
- for ( i=0 ; i<NI ; i++ )
- {
- for ( j=0 ; j<NJ ; j++)
- {
- r2 = (i-NI/5)*(i-NI/5) + (j-3*NJ/4)*(j-3*NJ/4);
- ff[i][j] = 7000 * exp( - 0.01 * r2 );
- ibound[i][j] = 0;
- phi[i][j] = 0.0;
- }
- }
- /* Boundary Conditions */
- for ( j=0 ; j<NJ ; j++)
- {
- ibound[0][j] = 1;
- phi[0][j] = 2.0;
- ibound[NI-1][j] = 1;
- phi[NI-1][j] = 2.0;
- }
- for ( i=0 ; i<NI ; i++ )
- {
- ibound[i][0] = 1;
- phi[i][0] = 2.0;
- ibound[i][NJ-1] = 1;
- phi[i][NJ-1] = 2.0;
- }
- /* single values somewhere in square */
- i_s = 4*NI/5;
- ibound[i_s][3*NJ/4] = 1;
- phi[i_s][3*NJ/4] = -25.0;
- i_s = NI/3;
- ibound[i_s][NJ/3] = 1;
- phi[i_s][NJ/3] = -10.0;
-
-
- /* echo input */
- fprintf( stderr, " Grid size: %d x %d \n", NI, NJ );
-
-}
-
-
-/* check solution & output field data for image */
-void output_results( int NI, int NJ, double h )
-{
- int i, j;
- double aux, phi_min, phi_max, residual, largest_residual;
-
- /* check if solution is */
- /* really a solution */
- fprintf( stderr, " Check - ( LHS - RHS ) \n");
- largest_residual = 0.0;
- for ( i=0 ; i<NI ; i++ )
- {
- for ( j=0 ; j<NJ ; j++)
- {
- /* min & max of phi as an aside */
- if ( phi[i][j] < phi_min ) phi_min = phi[i][j];
- if ( phi[i][j] > phi_max ) phi_max = phi[i][j];
-
- if ( ibound[i][j] == 0 )
- {
- residual = phi[i+1][j] + phi[i-1][j] +
- phi[i][j+1] + phi[i][j-1] -
- 4.0 * phi[i][j] - h * h * ff[i][j];
- }
- else
- {
- residual = 0.0;
- }
- if( fabs( residual ) > largest_residual )
- largest_residual = fabs( residual );
- }
- }
-
- fprintf( stderr, "largest residual : %e \n", largest_residual );
-
- /* output phi for image */
- if ( IMAGE == 1 )
- {
- aux = 255.0 / ( phi_max - phi_min );
- for ( i=0 ; i<NI ; i++ )
- {
- for ( j=0 ; j<NJ ; j++)
- printf( " %f \n", aux * ( phi[i][j] - phi_min ) );
- }
- }
-}
-
-
-/* one Gauss-Siedel iteration */
-void Gauss_Siedel_step( int NI, int NJ, int iter,
- double *diff, double h )
-{
- int i, j;
- double difference, aux, chi;
-
- /* over-relaxation control */
- chi = 1.0;
- if ( iter > 30 ) chi = 1.2;
- if ( iter > 50 ) chi = 1.8;
- /* Gauss-Siedel update */
- difference = 0.0;
- for ( i=0 ; i<NI ; i++ )
- {
- for ( j=0 ; j<NJ ; j++)
- {
- if ( ibound[i][j] == 0 )
- {
- aux = phi[i][j];
- phi[i][j] = 0.25 * ( phi[i+1][j] + phi[i-1][j] +
- phi[i][j+1] +phi[i][j-1] - h * h * ff[i][j] );
- phi[i][j] = (1-chi)*aux + chi*phi[i][j];
- if ( difference < fabs( aux - phi[i][j] ) )
- difference = fabs( aux - phi[i][j] );
- }
- }
- }
- fprintf( stderr, " iter: %d - error %e \n", iter, difference );
- *diff=difference;
-}
-
-
-
-
-int main ( int argc, char *argv[] )
-{
- double h;
- int NI, NJ, i, j;
- double diff, aux, chi;
- int N_iterations, iter;
-
- /* lattice definition & */
- /* iteration number */
- set_grid ( argc, argv, &N_iterations, &NI, &NJ, &h );
- /* initial fields, source */
- /* & boundary conditions */
- initial_source_and_boundary ( NI, NJ );
- /* iterate the solution */
- for ( iter=1 ; iter<N_iterations ; iter++ )
- {
- /* Gauss-Siedel iteration */
- Gauss_Siedel_step( NI, NJ, iter, &diff, h );
- /* solution accurate enough ? */
- if ( diff < EPS ) break;
- }
- /* check & output the phi field */
- output_results ( NI, NJ, h );
-
-}
-