Skip to content
Snippets Groups Projects
main.cpp 5.44 KiB
Newer Older
  • Learn to ignore specific revisions
  • Milan Jaros's avatar
    Milan Jaros committed
    # include "poisson.h"
    
    //****************************************************************************80
    
    int main(int argc, char* argv[])
    
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    MAIN is the main program for POISSON_SERIAL.
    //
    //  Discussion:
    //
    //    POISSON_SERIAL is a program for solving the Poisson problem.
    //
    //    This program runs serially.  Its output is used as a benchmark for
    //    comparison with similar programs run in a parallel environment.
    //
    //    The Poisson equation
    //
    //      - DEL^2 U(x,y) = F(x,y)
    //
    //    is solved on the unit square [0,1] x [0,1] using a grid of NX by
    //    NX evenly spaced points.  The first and last points in each direction
    //    are boundary points.
    //
    //    The boundary conditions and F are set so that the exact solution is
    //
    //      U(x,y) = sin ( pi * x * y )
    //
    //    so that
    //
    //      - DEL^2 U(x,y) = pi^2 * ( x^2 + y^2 ) * sin ( pi * x * y )
    //
    //    The Jacobi iteration is repeatedly applied until convergence is detected.
    //
    //    For convenience in writing the discretized equations, we assume that NX = NY.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license. 
    //
    //  Modified:
    //
    //    26 October 2011
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
    	bool converged;
    	double diff;
    	double dx;
    	double dy;
    	double error;
    	double** f;
    	int i;
    	int it;
    	int it_max = 100000;
    	int j;
    	int nx = 256;
    	int ny = 128;
    	double tolerance = 0.000001;
    	double** u;
    	double u_norm;
    	double** udiff;
    	double** uexact;
    	double** unew;
    	double unew_norm;
    	double x;
    	double y;
    
    	//Check args
    	if (argc < 2) {
    
    Milan Jaros's avatar
    Milan Jaros committed
    		printf("USAGE:\tpoisson 0 (tiny)\n\tpoisson 1 (small)\n\tpoisson 2 (large)\n");
    
    Milan Jaros's avatar
    Milan Jaros committed
    		return 0;
    	}
    
    	// Read Input
    	int type = atoi(argv[1]);
    	//tiny
    	if (type == 0) {
    
    Milan Jaros's avatar
    Milan Jaros committed
    		nx = 16;
    		ny = 16;
    
    Milan Jaros's avatar
    Milan Jaros committed
    		it_max = 1000;
    	}
    
    Milan Jaros's avatar
    Milan Jaros committed
    	//small
    
    Milan Jaros's avatar
    Milan Jaros committed
    	if (type == 1) {
    
    Milan Jaros's avatar
    Milan Jaros committed
    		nx = 64;
    		ny = 64;
    		it_max = 100000;
    	}    
    	//large
    	if (type == 2) {
    
    Milan Jaros's avatar
    Milan Jaros committed
    		nx = 256;
    
    Milan Jaros's avatar
    Milan Jaros committed
    		ny = 256;
    
    Milan Jaros's avatar
    Milan Jaros committed
    		it_max = 100000;
    	}
    
    	//Alloc memory
    	f = new double* [nx];
    	u = new double* [nx];
    	udiff = new double* [nx];
    	uexact = new double* [nx];
    	unew = new double* [nx];
    	for (i = 0; i < nx; i++)
    	{
    		f[i] = new double[ny];
    		u[i] = new double[ny];
    		udiff[i] = new double[ny];
    		uexact[i] = new double[ny];
    		unew[i] = new double[ny];
    	}
    
    	dx = 1.0 / (double)(nx - 1);
    	dy = 1.0 / (double)(ny - 1);
    	//
    	//  Print a message.
    	//
    	cout << "\n";
    	cout << "POISSON_SERIAL:\n";
    	cout << "  C++ version\n";
    	cout << "  A program for solving the Poisson equation.\n";
    	cout << "\n";
    	cout << "  -DEL^2 U = F(X,Y)\n";
    	cout << "\n";
    	cout << "  on the rectangle 0 <= X <= 1, 0 <= Y <= 1.\n";
    	cout << "\n";
    	cout << "  F(X,Y) = pi^2 * ( x^2 + y^2 ) * sin ( pi * x * y )\n";
    	cout << "\n";
    	cout << "  The number of interior X grid points is " << nx << "\n";
    	cout << "  The number of interior Y grid points is " << ny << "\n";
    	cout << "  The X grid spacing is " << dx << "\n";
    	cout << "  The Y grid spacing is " << dy << "\n";
    	//
    	//  Initialize the data.
    	//
    	rhs(nx, ny, f);
    	//
    	//  Set the initial solution estimate.
    	//  We are "allowed" to pick up the boundary conditions exactly.
    	//
    	for (j = 0; j < ny; j++)
    	{
    		for (i = 0; i < nx; i++)
    		{
    			if (i == 0 || i == nx - 1 || j == 0 || j == ny - 1)
    			{
    				unew[i][j] = f[i][j];
    			}
    			else
    			{
    				unew[i][j] = 0.0;
    			}
    		}
    	}
    	unew_norm = r8mat_rms(nx, ny, unew);
    	//
    	//  Set up the exact solution.
    	//
    	for (j = 0; j < ny; j++)
    	{
    		y = (double)(j) / (double)(ny - 1);
    		for (i = 0; i < nx; i++)
    		{
    			x = (double)(i) / (double)(nx - 1);
    			uexact[i][j] = u_exact(x, y);
    		}
    	}
    	u_norm = r8mat_rms(nx, ny, uexact);
    	cout << "  RMS of exact solution = " << u_norm << "\n";
    	//
    	//  Do the iteration.
    	//
    	converged = false;
    
    	cout << "\n";
    	cout << "  Step    ||Unew||     ||Unew-U||     ||Unew-Exact||\n";
    	cout << "\n";
    
    	for (j = 0; j < ny; j++)
    	{
    		for (i = 0; i < nx; i++)
    		{
    			udiff[i][j] = unew[i][j] - uexact[i][j];
    		}
    	}
    	error = r8mat_rms(nx, ny, udiff);
    	cout << "  " << setw(4) << 0
    		<< "  " << setw(14) << unew_norm
    		<< "  " << "              "
    		<< "  " << setw(14) << error << "\n";
    
    	for (it = 1; it <= it_max; it++)
    	{
    		for (j = 0; j < ny; j++)
    		{
    			for (i = 0; i < nx; i++)
    			{
    				u[i][j] = unew[i][j];
    			}
    		}
    		//
    		//  UNEW is derived from U by one Jacobi step.
    		//
    		sweep(nx, ny, dx, dy, f, u, unew);
    		//
    		//  Check for convergence.
    		//
    		u_norm = unew_norm;
    		unew_norm = r8mat_rms(nx, ny, unew);
    
    		for (j = 0; j < ny; j++)
    		{
    			for (i = 0; i < nx; i++)
    			{
    				udiff[i][j] = unew[i][j] - u[i][j];
    			}
    		}
    		diff = r8mat_rms(nx, ny, udiff);
    
    		for (j = 0; j < ny; j++)
    		{
    			for (i = 0; i < nx; i++)
    			{
    				udiff[i][j] = unew[i][j] - uexact[i][j];
    			}
    		}
    		error = r8mat_rms(nx, ny, udiff);
    
    		if (diff <= tolerance)
    		{
    			cout << "  " << setw(4) << it
    				<< "  " << setw(14) << unew_norm
    				<< "  " << setw(14) << diff
    				<< "  " << setw(14) << error << "\n";
    
    			converged = true;
    			break;
    		}
    	}
    
    	if (converged)
    	{
    		cout << "  The iteration has converged.\n";
    	}
    	else
    	{
    		cout << "  The iteration has NOT converged.\n";
    	}
    	//
    	//  Terminate.
    	//
    	cout << "\n";
    	cout << "POISSON_SERIAL:\n";
    	cout << "  Normal end of execution.\n";
    	cout << "\n";
    
    	//Free memory
    	for (i = 0; i < nx; i++)
    	{
    		delete[] f[i];
    		delete[] u[i];
    		delete[] udiff[i];
    		delete[] uexact[i];
    		delete[] unew[i];
    	}
    
    	delete[] f;
    	delete[] u;
    	delete[] udiff;
    	delete[] uexact;
    	delete[] unew;
    
    	return 0;
    }
    //****************************************************************************80