2D Arrays

So we are suppose to use a 2D array to determine the temperature distribution for a two-dimensional plate with constant boundary conditions. Use a 20 X 20 two-dimensional array of numbers to represent the temperature at different places on a (square) plate.

Im having trouble with updating the elements after initializing them and then updating until it becomes stable. My numbers are off and should look like this.

0.0000, 100.0000, 100.0000, 100.0000, 0.0000
0.0000, 40.6250, 50.0000, 40.6250, 0.0000
0.0000, 25.0000, 31.2500, 25.0000, 0.0000
0.0000, 40.6250, 50.0000, 40.6250, 0.0000
0.0000, 100.0000, 100.0000, 100.0000, 0.0000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  #include <iostream>
#include <iomanip>
#include <string>
#include <cmath>

using namespace std;

//Print the numbers in the array with a fixed precision of 4 and width 10.
const int SIZE_OF_ARRAY = 20;
const double MAX_TEMPERATURE = 100.0;
const int MIN_TEMPERATURE = 0;
const double NEIGHBORS = 4.0;

int main() {
    
    double averageTemperature = 0;
    double hotPlate[SIZE_OF_ARRAY][SIZE_OF_ARRAY];
    
    cout << "Hotplate simulator" << endl << endl;
    cout << "Printing initial plate..." << endl;
    
    
    for (int row = 0; row < SIZE_OF_ARRAY; row++)
    {
        for (int column = 0; column < SIZE_OF_ARRAY; column++)
        {
            if (row == 0 || row == 19)
            {
                if (column == 0 || column == 19)
                {
                    hotPlate[row][column] = 0;
                }
                else
                {
                    hotPlate[row][column] = 100;
                }
            }
            else
            {
                hotPlate[row][column] = 0;
            }
        }
    }
    //printing first plate
    for (int row = 0; row < SIZE_OF_ARRAY; row++)
    {
        for (int column = 0; column < SIZE_OF_ARRAY; column++)
        {
            if (column == 19) {
                cout << fixed << setprecision(4) << setw(10) << hotPlate[row][column];
            }
            else {
                cout << fixed << setprecision(4) << setw(10) << hotPlate[row][column] << ",";
            }
        }
        cout << endl;
    }
    //first iteration
    cout << endl;
    cout << "Printing plate after one iteration..." << endl;
    
    for (int row = 1; row < SIZE_OF_ARRAY - 1; row++){
        for (int column = 1; column < SIZE_OF_ARRAY - 1; column++){
            
            averageTemperature = (hotPlate[row][column - 1] + hotPlate[row + 1][column] + hotPlate[row][column + 1] + hotPlate[row - 1][column]) / NEIGHBORS;
            hotPlate[row][column] = averageTemperature;
            
        }
    }
   for (int row = 0; row < SIZE_OF_ARRAY; row++)
    {
        for (int column = 0; column < SIZE_OF_ARRAY; column++)
        {
            if (column == 19) {
                cout << fixed << setprecision(4) << setw(10) << hotPlate[row][column];
            }
            else {
                cout << fixed << setprecision(4) << setw(10) << hotPlate[row][column] << ",";
            }
        }
        cout << endl;
    }
    
    return 0;
    
}
Last edited on
First of all, if you want your answers to look like that then use a 5*5 array and not 20*20.

Secondly, you are only iterating once. You need to iterate many times. During the development stage, do a fixed (fairly large) number of iterations. Then change your code to compute the temperature change over one iteration (added over all nodes, and ignoring sign). When this global change is sufficiently small then you can stop iterating.
closed account (48T7M4Gy)
NEIGHBORS as a constant is OK sort of but it should be an int, size_t, unsigned in or similar rather than a double.

Printing values in the array would be better handled with a function to avoid duplication.

Stability can possibly be determined automatically by selecting a cell (say at the center) and recording the change in value from one iteration to the next. When the temperature increment/change is less than a user selected limit value then the iterations stop.
Last edited on
closed account (48T7M4Gy)
Assuming you know about functions this is roughly what I was getting at. You'll see that the central value stabilizes well before 35 iterations.

Note also you haven't allocated the boundary values using the constants. But that's easy to do. :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <iomanip>

using namespace std;

const int SIZE_OF_ARRAY = 5;
const double MAX_TEMPERATURE = 100.0;
const int MIN_TEMPERATURE = 0;
const int NEIGHBORS = 4;

void print_array(double anArray[][SIZE_OF_ARRAY], int iteration_no)
{
    cout << endl;
    cout << "Printing plate after one iteration..." << iteration_no << endl;
    
    for (int row = 0; row < SIZE_OF_ARRAY; row++)
    {
        for (int column = 0; column < SIZE_OF_ARRAY; column++)
            cout << fixed << setprecision(4) << setw(10) << anArray[row][column];
        cout << endl;
    }
}

int main() {
    
    double averageTemperature = 0;
    double hotPlate[SIZE_OF_ARRAY][SIZE_OF_ARRAY] =
    {
        {0.0000, MAX_TEMPERATURE, 100.0000, 100.0000, 0.0000},
        {0.0000,  40.6250, 50.0000, 40.6250, 0.0000},
        {0.0000,  25.0000, 31.2500, 25.0000, 0.0000},
        {0.0000, 40.6250, 50.0000, 40.6250, 0.0000},
        {0.0000, 100.0000, 100.0000, 100.0000, 0.0000}
    };
    
    cout << "Hotplate simulator" << endl << endl;
    cout << "Printing initial plate..." << endl;
    
    double previous = 0.0;
    double current = 0.0;
    double delta = 0.0;
    
    for(int iteration = 0; iteration < 35; iteration++) // NEED TO WORK ON THE NUMBER
    {
        previous = hotPlate[2][2];
        for (int row = 1; row < SIZE_OF_ARRAY - 1; row++)
        {
            for (int column = 1; column < SIZE_OF_ARRAY - 1; column++)
            {
                averageTemperature =
                (hotPlate[row][column - 1] + hotPlate[row + 1][column]
                 + hotPlate[row][column + 1] + hotPlate[row - 1][column]) / NEIGHBORS;
                
                hotPlate[row][column] = averageTemperature;
            }
        }
        
        current = hotPlate[2][2];
        
        // TEST LIMIT (delta IS ALWAYS +VE)
        delta = current - previous;
        if (delta < 0.0001)
        {
            std::cout << "Done\\n";
            break;
        }
        else
            current = previous;
        
        print_array( hotPlate, iteration);
    }
    return 0;
}
Last edited on
So we arent suppose to use functions yet since we are just learning it so I dont neccesarily get them too much. The number i posted were an array of 5 x 5 but its just cause printing out a 20 x 20 is a lot more. So i Have to print it after the first iteration and then finally when it is stable.
closed account (48T7M4Gy)
@rantiv,

So, if you aren't supposed to use functions then just write what you want in main and remove the function call and function.

You can have whatever size array you want and the best way to change it is by only changing the value in the line where you declare the value of SIZE_OF_ARRAY.
Ok let me work on it and Ill let you know. Thanks so much for the help so far
closed account (48T7M4Gy)
PS @OP You will still need to prepare the values in the array by hand, the way you have done so far, i.e. by typing in 5x5 values. 20x20 takes a while.

However you could automate it by writing extra lines to setup the boundary conditions and use random numbers to fill in the initial state values. Maybe for a later time and just stay with 5x5 for testing/development.
Well what i have to iniallt make them zeros and 100 was fine it was just updating them once and taking the first average.
ok so now i have this: The update till stable is off

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>

using namespace std;

//Print the numbers in the array with a fixed precision of 4 and width 10.
const int SIZE_OF_ARRAY = 20;
const double MAX_TEMPERATURE = 100.0;
const int MIN_TEMPERATURE = 0;
const int NEIGHBORS = 4;
const double CHANGE = 0.1;

int main() {
    
    double average_temp;
    double hotPlate[SIZE_OF_ARRAY][SIZE_OF_ARRAY];
    double largest_change = 0;
    
    cout << "Hotplate simulator" << endl << endl;
    cout << "Printing initial plate..." << endl;
    
    
    for (int row = 0; row < SIZE_OF_ARRAY; row++)
    {
        for (int column = 0; column < SIZE_OF_ARRAY; column++)
        {
            if (row == 0 || row == 19)
            {
                if (column == 0 || column == 19)
                {
                    hotPlate[row][column] = 0;
                }
                else
                {
                    hotPlate[row][column] = 100;
                }
            }
            else
            {
                hotPlate[row][column] = 0;
            }
        }
    }
    //printing first plate
    for (int row = 0; row < SIZE_OF_ARRAY; row++)
    {
        for (int column = 0; column < SIZE_OF_ARRAY; column++)
        {
            if (column == 19) {
                cout << fixed << setprecision(4) << setw(10) << hotPlate[row][column];
            }
            else {
                cout << fixed << setprecision(4) << setw(10) << hotPlate[row][column] << ",";
            }
        }
        cout << endl;
    }
    //first iteration
    cout << endl;
    cout << "Printing plate after one iteration..." << endl;
    
	for (int row = 0; row < SIZE_OF_ARRAY; row++) {
		for (int column = 0; column < SIZE_OF_ARRAY; column++) {
			if (row == 0 || row == SIZE_OF_ARRAY - 1) {
				if (column == 0 || column == SIZE_OF_ARRAY - 1) {
					hotPlate[row][column] = 0;
				}
				else {
					hotPlate[row][column] = 100.0;
				}
			}
			else if (row == 1 || row == SIZE_OF_ARRAY - 2) {
			    if (column == 0 || column == SIZE_OF_ARRAY - 1) {
					hotPlate[row][column] = 0;			        
			    }
			    else {
			       hotPlate [row][column] = 100 / 4;
			    }
			}
			else {
			    hotPlate[row][column] = 0;
			}
		}
	}   
   for (int row = 0; row < SIZE_OF_ARRAY; row++) {
      for (int column = 0; column < SIZE_OF_ARRAY; column++) {
         cout << setprecision(4) << fixed << hotPlate[row][column];
         if (column < SIZE_OF_ARRAY -1) {
              cout << ", ";
         }
      }
      cout << endl;
   }
   cout << endl;
   
	do
	{
		largest_change = 0;
		for (int row = 1; row < SIZE_OF_ARRAY - 1; row++)
		{
			for (int col = 1; col < SIZE_OF_ARRAY - 1; col++)
			{
				double old_value = hotPlate[row][col];
				average_temp = (hotPlate[row][col - 1] + hotPlate[row + 1][col] + hotPlate[row][col + 1] + hotPlate[row - 1][col]) / NEIGHBORS;
				hotPlate[row][col] = average_temp;

				double change = abs(old_value - hotPlate[row][col]);
				if (change > largest_change)
				{
					largest_change = change;
				}
			}
		}


	} while (largest_change > CHANGE);
	for (int row = 0; row < SIZE_OF_ARRAY; row++) {
      for (int column = 0; column < SIZE_OF_ARRAY; column++) {
         cout << setprecision(4) << fixed << hotPlate[row][column];
         if (column < SIZE_OF_ARRAY -1) {
              cout << ", ";
         }
      }
      cout << endl;
   }
   cout << endl;
    
    return 0;
    
}
Last edited on
closed account (48T7M4Gy)
So, does that mean it's working the way you want? It might be a good idea to add a counter variable so you can show how many iterations were required to get to the stable state.
Last edited on
It is but the end numbers arent right...

This is what i got:
43.0576, 36.9987, 29.5239, 20.6783, 10.6823, 0.0000
0.0000, 12.5412, 24.0079, 33.8095, 41.8032, 48.0877, 52.8450, 56.2550, 58.4607, 59.5571, 59.5903, 58.5574, 56.4073, 53.0401, 48.3083, 42.0284, 34.0160, 24.1706, 12.6348, 0.0000
0.0000, 15.6173, 29.2459, 40.2155, 48.6668, 55.0032, 59.6265, 62.8528, 64.9018, 65.9085, 65.9359, 64.9815, 62.9784, 59.7874, 55.1850, 48.8525, 40.3857, 29.3800, 15.6944, 0.0000
0.0000, 20.7103, 37.1875, 49.1993, 57.7180, 63.7148, 67.8962, 70.7244, 72.4843, 73.3383, 73.3592, 72.5453, 70.8204, 68.0193, 63.8539, 57.8600, 49.3295, 37.2901, 20.7693, 0.0000
0.0000, 30.0572, 49.6273, 61.7198, 69.3438, 74.3022, 77.5855, 79.7342, 81.0445, 81.6729, 81.6870, 81.0856, 79.7989, 77.6684, 74.3959, 69.4394, 61.8075, 49.6964, 30.0969, 0.0000
0.0000, 49.9042, 69.5649, 78.7356, 83.6674, 86.6016, 88.4496, 89.6249, 90.3300, 90.6652, 90.6723, 90.3506, 89.6572, 88.4910, 86.6485, 83.7153, 78.7795, 69.5995, 49.9241, 0.0000
0.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 100.0000, 0.0000

This is what i should end up with
62.6089 60.7125 57.6939 53.3261 47.2847 39.1587 28.5348 15.2619 0.0000
0.0000 20.4310 36.6290 48.3696 56.6332 62.3989 66.3803 69.0461 70.6868 71.4693 71.4693 70.6868 69.0461 66.3803 62.3989 56.6332 48.3696 36.6290 20.4310 0.0000
0.0000 29.8641 49.2412 61.1464 68.5944 73.3934 76.5389 78.5758 79.8042 80.3836 80.3836 79.8042 78.5758 76.5389 73.3934 68.5944 61.1464 49.2412 29.8641 0.0000
0.0000 49.8050 69.3666 78.4413 83.2828 86.1354 87.9127 89.0309 89.6942 90.0045 90.0045 89.6942 89.0309 87.9127 86.1354 83.2828 78.4413 69.3666 49.8050 0.0000
0.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 100.0000 0.0000
closed account (48T7M4Gy)
After how many iterations?
when it reaches stability
closed account (48T7M4Gy)
I've run your program on my machine and also on the cpp shell here with change = .1 and .00001 and the results are nothing like the answer you have posted.


Check, but looks OK unless you take all 8 neighbors:

average_temp = (hotPlate[row][col - 1] + hotPlate[row + 1][col] + hotPlate[row][col + 1] + hotPlate[row - 1][col]) / NEIGHBORS;

Could be your boundary conditions too.
Last edited on
Wait what?
closed account (48T7M4Gy)
@rantiv,
Perhaps if you wrote a complete sentence describing your current situation and whether you want any help would go a long way towards getting a more meaningful response to your last two words and question mark. :)
My numbers are off and should look like this.

0.0000, 100.0000, 100.0000, 100.0000, 0.0000
0.0000, 40.6250, 50.0000, 40.6250, 0.0000
0.0000, 25.0000, 31.2500, 25.0000, 0.0000
0.0000, 40.6250, 50.0000, 40.6250, 0.0000
0.0000, 100.0000, 100.0000, 100.0000, 0.0000


@Rantiv - are you absolutely sure about this?

Take the middle element (31.25). If I average its 4 neighbours (25, 25, 50, 50) I would get
37.5, not 31.25.

In fact, on symmetry grounds I would rather expect the middle value (AND ALL THE DIAGONAL ELEMENTS) to be 50.00. That is presuming you want BOTH top and bottom boundaries to be at temperature 100: check your (required) boundary conditions.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

//=====================================================================

void display( ostream &strm, double *T, int imax, int jmax )
{
   for ( int i = 0; i < imax; i++ )
   {
      for ( int j = 0; j < jmax; j++ )
      {
         int ij = i * jmax + j;
         strm << fixed << setw( 9 ) << setprecision( 4 ) << T[ij];
      }
      strm << endl;
   }
}

//=====================================================================

void boundaryConditions( double *T, int imax, int jmax, double T0, double TL, double TR, double TB, double TT )
{
   for ( int i = 0; i < imax; i++ )
   {
      for ( int j = 0; j < jmax; j++ )
      {
         int ij = i * jmax + j;
         T[ij] = T0;                             // initial condition

         if      ( i == 0        ) T[ij] = TT;   // top
         else if ( i == imax - 1 ) T[ij] = TB;   // bottom

         if      ( j == 0        ) T[ij] = TL;   // left (including corner)
         else if ( j == jmax - 1 ) T[ij] = TR;   // right (including corner)
      }
   }
}

//=====================================================================

void gaussSeidel( double *T, int imax, int jmax, double &maxChange )
{
   int i, j, ij;
   double Told;

   maxChange = 0;

   for ( int i = 1; i < imax - 1; i++ )
   {
      for ( int j = 1; j < jmax - 1; j++ )
      {
         int ij = i * jmax + j;
         double Told = T[ij];

         T[ij] = ( T[ij+1] + T[ij-1] + T[ij-jmax] + T[ij+jmax] ) / 4.0;        // update step

         double change = abs( T[ij] - Told );
         if ( change > maxChange ) maxChange = change;
      }
   }
}

//=====================================================================

int main()
{
   const int SIZE = 5;                                               // array dimensions
   const double TL = 0.0, TR = 0.0, TB = 100.0, TT = 100.0;          // boundary conditions
   const double T0 = 25.0;                                           // initial condition
   const double TOLERANCE = 1.0e-6;                                  // tolerance for convergence
   const int NMAX = 1000;                                            // maximum number of iterations
   double T[SIZE][SIZE];                                             // temperature array

   // Initialise
   cout << "Starting conditions:\n";
   boundaryConditions( &T[0][0], SIZE, SIZE, T0, TL, TR, TB, TT );
   display( cout, &T[0][0], SIZE, SIZE );                        
   cout << endl;

   // Loop
   int n = 0;                                                        // iteration counter
   double maxChange = TOLERANCE + 1;                                 // make sure it runs
   while ( maxChange > TOLERANCE && n < NMAX )                       // keep iterating until converged (or max iterations)
   {
      n++;
      gaussSeidel( &T[0][0], SIZE, SIZE, maxChange );                // update
      cout << "Iteration: " << n << "   Max change = " << scientific << maxChange << endl;
   }

   // Final output
   cout << "\n\nFinal solution:\n";
   display( cout, &T[0][0], SIZE, SIZE );                        
}


Starting conditions:
   0.0000 100.0000 100.0000 100.0000   0.0000
   0.0000  25.0000  25.0000  25.0000   0.0000
   0.0000  25.0000  25.0000  25.0000   0.0000
   0.0000  25.0000  25.0000  25.0000   0.0000
   0.0000 100.0000 100.0000 100.0000   0.0000

Iteration: 1   Max change = 2.2852e+001
Iteration: 2   Max change = 8.5938e+000
Iteration: 3   Max change = 5.8594e+000
Iteration: 4   Max change = 2.9297e+000
Iteration: 5   Max change = 1.4648e+000
Iteration: 6   Max change = 7.3242e-001
Iteration: 7   Max change = 3.6621e-001
Iteration: 8   Max change = 1.8311e-001
Iteration: 9   Max change = 9.1553e-002
Iteration: 10   Max change = 4.5776e-002
Iteration: 11   Max change = 2.2888e-002
Iteration: 12   Max change = 1.1444e-002
Iteration: 13   Max change = 5.7220e-003
Iteration: 14   Max change = 2.8610e-003
Iteration: 15   Max change = 1.4305e-003
Iteration: 16   Max change = 7.1526e-004
Iteration: 17   Max change = 3.5763e-004
Iteration: 18   Max change = 1.7881e-004
Iteration: 19   Max change = 8.9407e-005
Iteration: 20   Max change = 4.4703e-005
Iteration: 21   Max change = 2.2352e-005
Iteration: 22   Max change = 1.1176e-005
Iteration: 23   Max change = 5.5879e-006
Iteration: 24   Max change = 2.7940e-006
Iteration: 25   Max change = 1.3970e-006
Iteration: 26   Max change = 6.9849e-007


Final solution:
   0.0000 100.0000 100.0000 100.0000   0.0000
   0.0000  50.0000  62.5000  50.0000   0.0000
   0.0000  37.5000  50.0000  37.5000   0.0000
   0.0000  50.0000  62.5000  50.0000   0.0000
   0.0000 100.0000 100.0000 100.0000   0.0000

Last edited on
Topic archived. No new replies allowed.