/* * Updates only the wolf and squirrels that belong to a specific subgeneration. * color: the color of the subgeneration to be updated. */ void iterate_subgeneration(int color) { int i, j, start_col; struct world **read_matrix = worlds[0]; struct world **write_matrix = worlds[1]; for(i = 0; i < max_size; i++) { if(get_cell_color(i, 0) == color) { start_col = 0; } else { start_col = 1; } for(j = start_col; j < max_size; j += N_COLORS) { if(read_matrix[i][j].type & WOLF) { update_wolf(read_matrix, write_matrix, i,j); } else if(read_matrix[i][j].type & SQUIRREL) { update_squirrel(read_matrix, write_matrix, i,j); } } } }
void start_world_simulation(void){ register int i, j, btm_lim = bottom, top_lim = top; for(; number_of_generations > 0; --number_of_generations){ copy_world(); if(taskid != MASTER) btm_lim = bottom - 1; if(taskid != numtasks-1) top_lim = top + 1; /* update 'red' cells, think chessboard */ #pragma omp parallel for private(j) for(i = btm_lim; i < top_lim; ++i){ for (j = 0; j < grid_size; j++){ if(get_cell_color(&world[i][j]) == RED){ update_world_cell(i, j); } } } resolve_conflicts(RED, number_of_generations); copy_world(); /* update 'black' cells, think chessboard */ #pragma omp parallel for private(j) for(i = btm_lim; i < top_lim; ++i){ for (j = 0; j < grid_size; j++){ if(get_cell_color(&world[i][j]) == BLACK){ update_world_cell(i, j); } } } resolve_conflicts(BLACK, number_of_generations); if(number_of_generations == 1) return; #pragma omp parallel for private(j) for(i = 0; i < payload; ++i){ for (j = 0; j < grid_size; ++j){ if (world[i][j].moved == UPDATED || world[i][j].moved == MOVED){ if (world[i][j].type == SQUIRREL || world[i][j].type == SQUIRREL_IN_TREE){ world[i][j].breeding_period++; } else if (world[i][j].type == WOLF){ world[i][j].starvation_period--; world[i][j].breeding_period++; /* wolf dies of starvation */ if(world[i][j].starvation_period <= 0){ cleanup_cell(&world[i][j]); } } } world[i][j].moved = 0; } } } }
void resolve_conflicts(int generation_color, int gen_number){ int i; world_cell* conf1 = malloc(grid_size*sizeof(world_cell)); world_cell* conf2 = malloc(grid_size*sizeof(world_cell)); //send to taskid-1 if(taskid != MASTER){ MPI_Request size_reqs[2]; MPI_Isend(world[0], grid_size, mpi_world_cell_type, taskid-1, CONF_TAG, MPI_COMM_WORLD, &size_reqs[0]); MPI_Isend(world[1], grid_size, mpi_world_cell_type, taskid-1, CONF_TAG+1, MPI_COMM_WORLD, &size_reqs[1]); } //receive from taskid +1 if(taskid != numtasks-1){ MPI_Status status; MPI_Recv(conf1, grid_size, mpi_world_cell_type, taskid+1, CONF_TAG, MPI_COMM_WORLD, &status); MPI_Recv(conf2, grid_size, mpi_world_cell_type, taskid+1, CONF_TAG+1, MPI_COMM_WORLD, &status); } //resolve conflicts on n+1 n+2 // Keep all moved cells from THIS generation (world), discard others for(i=0; i < grid_size; i++){ //discard unmoved cells from my world with color 'generation_color' if(((world[payload-2][i].moved != UPDATED) && (world[payload-2][i].moved != NEW_BORN)) && get_cell_color(&world[payload-2][i]) == generation_color && world[payload-2][i].type != ICE && world[payload-2][i].type != TREE && world[payload-2][i].type != EMPTY){ cleanup_cell(&world[payload-2][i]); } else if (world[payload-2][i].moved == UPDATED || world[payload-2][i].moved == NEW_BORN) { world[payload-2][i].moved = MOVED; } if(((world[payload-1][i].moved != UPDATED) && (world[payload-1][i].moved != NEW_BORN)) && get_cell_color(&world[payload-1][i]) == generation_color && world[payload-1][i].type != ICE && world[payload-1][i].type != TREE && world[payload-1][i].type != EMPTY){ cleanup_cell(&world[payload-1][i]); } else if (world[payload-1][i].moved == UPDATED || world[payload-1][i].moved == NEW_BORN){ world[payload-1][i].moved = MOVED; } if(conf1[i].moved == UPDATED || conf1[i].moved == NEW_BORN){ //move to my world if(conf1[i].type == WOLF) move_wolf(&conf1[i], &world[payload-2][i]); else move_squirrel(&conf1[i], &world[payload-2][i]); world[payload-2][i].moved = MOVED; } if(conf2[i].moved == UPDATED || conf2[i].moved == NEW_BORN){ //move to my world if(conf2[i].type == WOLF) move_wolf(&conf2[i], &world[payload-1][i]); else move_squirrel(&conf2[i], &world[payload-1][i]); world[payload-1][i].moved = MOVED; } } //send to taskid+1 if(taskid != numtasks-1){ MPI_Request size_reqs[2]; MPI_Isend(world[payload-2], grid_size, mpi_world_cell_type, taskid+1, CONF_TAG-2, MPI_COMM_WORLD, &size_reqs[0]); MPI_Isend(world[payload-1], grid_size, mpi_world_cell_type, taskid+1, CONF_TAG-1, MPI_COMM_WORLD, &size_reqs[1]); } //receive from taskid -1 if(taskid != MASTER){ MPI_Status status; MPI_Recv(world[0], grid_size, mpi_world_cell_type, taskid-1, CONF_TAG-2, MPI_COMM_WORLD, &status); MPI_Recv(world[1], grid_size, mpi_world_cell_type, taskid-1, CONF_TAG-1, MPI_COMM_WORLD, &status); } }