bokunda

[MPI] Cell-Cancer-Simulation

May 14th, 2021
808
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <mpi.h>
  4.  
  5. #define KANCER 0
  6. #define LEK 1
  7. #define TKIVO 2
  8.  
  9. #define KANCER_VEROVATNOCA 2
  10. #define LEK_VEROVATNOCA 18
  11. #define TKIVO_VEROVATNOCA 80
  12.  
  13. #define TOP 1
  14. #define BOTTOM 2
  15. #define LEFT 4
  16. #define RIGHT 8
  17.  
  18. typedef struct celija {
  19.     int tip;
  20.     int jacina;
  21. } CELIJA;
  22.  
  23.  
  24. CELIJA** allocateMatrix(int m, int n)
  25. {
  26.     int i;
  27.     CELIJA **matrix = (CELIJA**)malloc(m * sizeof(CELIJA*));
  28.     for(i = 0; i < m; i++) matrix[i] = (CELIJA*)malloc(n * sizeof(CELIJA));
  29.     return matrix;
  30. }
  31.  
  32. void printMatrix(CELIJA **matrix, int startM, int m, int n)
  33. {
  34.     int i, j;
  35.     for (i = 0; i < m && startM <= m; i++)
  36.     {
  37.         for (j = 0; j < n; j++)
  38.         {
  39.             printf("| %d %6d ", matrix[i][j].tip, matrix[i][j].jacina);
  40.             if (j == n - 1) printf("|");
  41.         }
  42.         printf("\n");
  43.     }
  44. }
  45.  
  46. void setMatrixData(CELIJA **matrix, int m, int n)
  47. {
  48.     int i, j;
  49.     for (i = 0; i < m; i++)
  50.     {
  51.         for (j = 0; j < n; j++)
  52.         {
  53.             int verovatnocaTipa = rand() % 100 + 1;
  54.             if (verovatnocaTipa <= KANCER_VEROVATNOCA)
  55.             {
  56.                 matrix[i][j].tip = KANCER;
  57.                 matrix[i][j].jacina = rand() % 101 + 1;
  58.             }
  59.             else if (verovatnocaTipa > KANCER_VEROVATNOCA && verovatnocaTipa <= LEK_VEROVATNOCA)
  60.             {
  61.                 matrix[i][j].tip = LEK;
  62.                 matrix[i][j].jacina = rand() % 20 + 1;
  63.             }
  64.             else if (verovatnocaTipa > LEK_VEROVATNOCA)
  65.             {
  66.                 matrix[i][j].tip = TKIVO;
  67.                 matrix[i][j].jacina = rand() % 10001;
  68.             }
  69.         }
  70.     }
  71. }
  72.  
  73. int tryApplyCancerOrMedicine(CELIJA **matrix, int i, int j, CELIJA value)
  74. {
  75.     if (matrix[i][j].tip == TKIVO && value.tip == KANCER)
  76.     {
  77.         matrix[i][j].jacina -= value.jacina;
  78.  
  79.         if (matrix[i][j].jacina <= 0)
  80.         {
  81.             matrix[i][j].tip = KANCER;
  82.             matrix[i][j].jacina = rand() % 101;
  83.         }
  84.     }
  85.  
  86.     if (matrix[i][j].tip == KANCER && value.tip == LEK)
  87.     {
  88.         matrix[i][j].jacina -= value.jacina;
  89.        
  90.         if (matrix[i][j].jacina <= 0)
  91.         {
  92.             matrix[i][j].tip = TKIVO;
  93.             matrix[i][j].jacina = rand() % 10001;
  94.         }
  95.     }
  96.  
  97.     return matrix[i][j].tip != value.tip ? 1 : 0;
  98. }
  99.  
  100. void doWork(CELIJA **matrix, int startM, int endM, int n)
  101. {
  102.     int i, j;
  103.     for (i = startM; i <= endM; i++)
  104.     {
  105.         int hasCancerNeighbour = 0;
  106.         for (j = 0; j < n; j++)
  107.         {
  108.             // check left
  109.             if (j > 0) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i][j-1]);
  110.             // check right
  111.             if (j < n) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i][j+1]);
  112.             // check top
  113.             if (i > startM) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i-1][j]);
  114.             // check bottom
  115.             if (i < endM) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i+1][j]);
  116.             // check top-left
  117.             if (j > 0 && i > startM) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i-1][j-1]);
  118.             // check top-right
  119.             if (j < n && i > startM) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i-1][j+1]);
  120.             // check bottom-left
  121.             if (j > 0 && i < endM) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i+1][j-1]);
  122.             // check bottom-right
  123.             if (j < n && i < endM) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, matrix[i+1][j+1]);
  124.  
  125.             // convert cell into a tissue if there cell is surrounded with tissues
  126.             if (hasCancerNeighbour == 0 && matrix[i][j].tip == LEK)
  127.             {
  128.                 matrix[i][j].tip = TKIVO;
  129.                 matrix[i][j].jacina = rand() % 10001;
  130.             }
  131.         }
  132.     }
  133. }
  134.  
  135. void doWorkEdge(CELIJA **matrix, CELIJA *rowToCompare, int n, int i)
  136. {
  137.     int j;
  138.     int hasCancerNeighbour = 0;
  139.     for (j = 0; j < n; j++)
  140.     {
  141.         // default check
  142.         hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, rowToCompare[j]);
  143.  
  144.         // check edge-left
  145.         if (j > 0) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, rowToCompare[j-1]);
  146.         // check edge-right
  147.         if (j < n) hasCancerNeighbour += tryApplyCancerOrMedicine(matrix, i, j, rowToCompare[j+1]);
  148.  
  149.         if (hasCancerNeighbour == 0 && matrix[i][j].tip == LEK)
  150.         {
  151.             matrix[i][j].tip = TKIVO;
  152.             matrix[i][j].jacina = rand() % 10001;
  153.         }
  154.     }
  155. }
  156.  
  157. CELIJA findLocalStrongestCancerCell(CELIJA **matrix, int startM, int endM, int n)
  158. {
  159.     int i, j;
  160.     CELIJA strongest;
  161.     strongest.tip = KANCER;
  162.     strongest.jacina = -1;
  163.  
  164.     for (i = startM; i <= endM; i++)
  165.     {
  166.         for (j = 0; j < n; j++)
  167.         {
  168.             if (matrix[i][j].tip == KANCER && matrix[i][j].jacina > strongest.jacina)
  169.             {
  170.                 strongest = matrix[i][j];
  171.             }
  172.         }
  173.     }
  174.     return strongest;
  175. }
  176.  
  177. void myMax(int *invector, int *outvector, int *len, MPI_Datatype type)
  178. {
  179.     *outvector = *outvector < *invector ? *outvector : *invector;
  180. }
  181.  
  182. int main(int argc, char **argv)
  183. {
  184.     int rank, size;
  185.     int m = 100, n = 10;
  186.     int i;
  187.     int steps = 1;
  188.  
  189.     CELIJA strongestGlobal;
  190.  
  191.     CELIJA *top_row = (CELIJA *)malloc(n * sizeof(CELIJA));
  192.     CELIJA *bottom_row = (CELIJA *)malloc(n * sizeof(CELIJA));
  193.  
  194.     CELIJA **matrix = allocateMatrix(m, n);
  195.     setMatrixData(matrix, m, n);
  196.  
  197.     MPI_Init(&argc, &argv);
  198.  
  199.     // Commit structure
  200.     MPI_Datatype mycelltype;
  201.     MPI_Aint extentINT, lb;
  202.  
  203.     int count = 2;
  204.     int lengths[2] = { 1, 1 };
  205.     MPI_Aint displacements[2] = { 0, extentINT };
  206.     MPI_Datatype types[2] = { MPI_INT, MPI_INT };
  207.  
  208.     MPI_Type_get_extent(MPI_INT, &lb, &extentINT);
  209.  
  210.     MPI_Type_create_struct(count, lengths, displacements, types, &mycelltype);
  211.     MPI_Type_commit(&mycelltype);
  212.  
  213.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  214.     MPI_Comm_size(MPI_COMM_WORLD, &size);
  215.  
  216.     // Find submatrix for process
  217.     int startM = (rank * (m / size));
  218.     int endM = startM + (m / size) - 1;
  219.  
  220.     for (i = 0; i < steps; i++)
  221.     {
  222.         doWork(matrix, startM, endM, n);
  223.  
  224.         // upper cells
  225.         if (rank != 0)
  226.         {
  227.             MPI_Send(matrix[startM], n * 2, MPI_INT, rank - 1, 40, MPI_COMM_WORLD);
  228.             MPI_Recv(bottom_row, n * 2, MPI_INT, rank - 1, 40, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  229.  
  230.             doWorkEdge(matrix, bottom_row, n, startM);
  231.         }
  232.         // lower cells
  233.         if (rank != size - 1)
  234.         {
  235.             MPI_Send(matrix[endM], n * 2, MPI_INT, rank + 1, 40, MPI_COMM_WORLD);
  236.             MPI_Recv(bottom_row, n * 2, MPI_INT, rank + 1, 40, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  237.        
  238.             doWorkEdge(matrix, bottom_row, n, startM);
  239.         }
  240.     }
  241.  
  242.     // Register reduction operation
  243.     MPI_Op MPI_MY_MAX;
  244.     MPI_Op_create( (MPI_User_function *) myMax, 1, &MPI_MY_MAX);
  245.  
  246.     // Find the strongest cancer cell
  247.     CELIJA strongest = findLocalStrongestCancerCell(matrix, startM, endM, n);
  248.  
  249.     MPI_Reduce(&strongest.jacina, &strongestGlobal.jacina, 1, MPI_INT, MPI_MY_MAX, 0, MPI_COMM_WORLD);
  250.  
  251.     printf("[%d]: Strongest local: %d_%d\n", rank, strongest.tip, strongest.jacina);
  252.  
  253.     if (rank == 0) printf("Strongest global: %d\n", strongestGlobal.jacina);
  254.  
  255.     MPI_Finalize();
  256.  
  257.     return 0;
  258. }
RAW Paste Data