Matrix with changing data and time steps

1

I have trouble writing a program that must calculate the temperature of a central point of a rectangular region after certain time steps.

For which you create a matrix of (N + 1) x (M + 1) where N = 2M and the center point of the region is (N / 2) +1 and (M / 2) +1. The upper cells have an initial temperature of 20 ºC, the rest of the cells have an initial temperature of 0 ºC, and in the cells of the contour the temperature is invariant.

The temperature in each cell and time step (Tk) is calculated with the temperature in the previous time step (Tk-1) of the adjacent cells, following the following formula:

  

(Where (i, j) is the value of a cell)

     

T = (4 * [(i + 1, j) + (i-1, j) + (i, j + 1) + (i, j-1)] + [(i-1, j- 1) + (i-1, j + 1) + (i + 1, j + 1) + (i + 1, j-1)]) / 10

So far I have everything clear and I have no major problem. The problem begins when to calculate the temperature after each step of time adds the temperature already calculated in the time jump itself instead of using the temperature of the previous time jump, ie:

To calculate the temperature of the cell (1,6), use the adjacent cells, but previously you calculated the cell (1,5), and instead of using the temperature of (1,5) before the calculation, the sum after said calculation giving the wrong result.

So far I have written the following:

int main( ) {
  int N = 20;   
  int M = 10;
  int A = 2 * N + 1;
  int B = 2 * M + 1;
  int matriz[A][B];

  for( int i = 1; i < A; i++ ) {
    for( int j = 0; j < B; j++ ) {      
      matriz[0][j] = 20;
      matriz[i][j] = 0;
    }
  }

  for( int i = 1; i < ( A - 1 ); i++ ) {
    for( int j = 1; j < ( B - 1 ); j++ ) {
      int n = i - 1;
      int e = j + 1;
      int s = i + 1;
      int o = j - 1;
      int T = ( 4 * ( matriz[n][j] + matriz[s][j] + matriz[i][o] + matriz[i][e] ) + ( matriz[n][e] + matriz[n][o] + matriz[s][e] + matriz[s][o] ) ) / 10;
      matriz[i][j] += matriz[i][j] + T;
    }
  } 
  std::cout << matriz[N + 1][M + 1];
  return 0;
}
    
asked by Kris1985 29.03.2018 в 11:52
source

1 answer

2
  

To calculate the temperature of the cell (1,6), use the adjacent cells, but previously you calculated the cell (1,5), and instead of using the temperature of (1,5) before the calculation, the sum after said calculation giving the wrong result.

Normal, in each pass you are writing the values, you can not use the values previous to the calculation if you calculate the value when you update it. You need a copy of the values before calculation. My advice is to use a multiple buffer .

To implement a double buffer I would use an update function that received two matrices: the reference (data that will not be changed) and the calculation (data that will be written):

constexpr int N = 20;   
constexpr int M = 10;
constexpr int A = 2 * N + 1;
constexpr int B = 2 * M + 1;
using Matriz = int[A][B];

void actualiza(const Matriz &origen, Matriz &destino)
{
  for( int i = 1; i < ( A - 1 ); i++ ) {
    for( int j = 1; j < ( B - 1 ); j++ ) {
      int n = i - 1;
      int e = j + 1;
      int s = i + 1;
      int o = j - 1;
      int T = ( 4 * ( origen[n][j] + origen[s][j] + origen[i][o] + origen[i][e] ) +
                    ( origen[n][e] + origen[n][o] + origen[s][e] + origen[s][o] ) ) / 10;

      destino[i][j] += T;
    }
  } 
}

I've made some changes to your code to make it work; firstly I have changed your values N , M , A and B to constant expressions to ensure that they are available at compile time and thus be able to define the type Matriz , which will be a training 1 of two dimensions AxB , this is the type that will be passed to the function actualiza that your algorithm follows.

In the second place I changed the update instruction you were using, since you used the operator += using the same data along with another value on your left and right, you probably did not want this, because if (for example) in the cell (j,i) you had the value 7 and in T the value 10 the result would be:

matriz(j,i) += 7 + 10; // matriz(j,i) es 7
matriz(j,i) += 17;     // matriz(j,i) es 7
// matriz(j,i) obtiene el valor 24

In order for the multiple buffer to work you have to exchange each matrix in each call to actualiza .

Other things to consider.

You are using variables to define the size of formations 1 , it is required that the size of the formations be a constant value. If you use a variable and compile it means you are using a compiler extension known as VLA ( Variable Lenght Array ), being a compiler extension means that if you change the compiler it is likely that the code stops compiling, read this thread to have more details about it.

With that in mind, your code could look like this:

#include <iostream>

constexpr int N = 20;   
constexpr int M = 10;
constexpr int A = 2 * N + 1;
constexpr int B = 2 * M + 1;
using Matriz = int[A][B];

void actualiza(const Matriz &origen, Matriz &destino)
{
  for( int i = 1; i < ( A - 1 ); i++ ) {
    for( int j = 1; j < ( B - 1 ); j++ ) {
      int n = i - 1;
      int e = j + 1;
      int s = i + 1;
      int o = j - 1;
      int Temperatura = ( 4 * ( origen[n][j] + origen[s][j] + origen[i][o] + origen[i][e] ) +
                              ( origen[n][e] + origen[n][o] + origen[s][e] + origen[s][o] ) ) / 10;
      destino[i][j] += Temperatura;
    }
  } 
}

int main()
{
    Matriz matriz1{}, matriz2{};

    for( int j = 0; j < B; j++ ) {      
        matriz1[0][j] = 20;
        matriz2[0][j] = 20;
    }

    constexpr int pasos = 10;
    for (int paso = 0; paso != pasos; ++paso)
    {
        if (paso % 2)
            actualiza(matriz1, matriz2);
        else
            actualiza(matriz2, matriz1);
    }

    std::cout << matriz1[N + 1][M + 1] << '\n'
              << matriz2[N + 1][M + 1];

    return 0;
}

Notice that to initialize the matrices we have used keys ( {} ), this causes all its elements to be initialized to zero ( 0 ), so that when assigning the initial values a single loop is necessary for the cells higher.

The buffers exchange loop has made it as simple as possible, but you can choose any other implementation.

  • Also known as array , or array .
  • answered by 29.03.2018 в 12:44