Finish Functions

show_results()

At the end of the code, if we are choosing to show results, we print out the final counts of susceptible, infected, immune, and dead people. We also print the actual contagiousness and actual deadliness of the disease. To perform these two calculations, we use the following code (using the contagiousness as the example):

    #ifdef SHOW_RESULTS
    printf("Rank %d final counts: %d susceptible, %d infected, %d immune, %d dead \nRank %d actual contagiousness: %f \nRank %d actual deadliness: %f \n", 
        our->our_rank, our->our_num_susceptible, our->our_num_infected, 
        our->our_num_immune, our->our_num_dead, our->our_rank, 
        100.0 * (stats->our_num_infections / (stats->our_num_infection_attempts 
            == 0 ? 1 : stats->our_num_infection_attempts)),our->our_rank, 
        100.0 * (stats->our_num_deaths / (stats->our_num_recovery_attempts 
            == 0 ? 1 : stats->our_num_recovery_attempts)));
    #endif

In this code, the ternary operators (? and :) are used to return one value if something is true and another value if it isn’t. The thing we are checking for truth is our_num_infection_attempts == 0. If this is true, i.e. if we didn’t attempt any infection attempts at all, then we say there was actually 1 infection attempt (this is to avoid a divide by zero error). Otherwise, we return the actual number of infection attempts. This value becomes the dividend for our_num_infections; in other words, we divide the number of actual infections by the number of total infections. This will give us a value less than 1, so we multiply it by 100 to obtain the actual contagiousness factor of the disease. A similar procedure is performed to calculate the actual deadliness factor.

cleanup

If X display is enabled, then Rank 0 destroys the X Window and closes the display

    // if use X_DISPLAY, do close_display()
    #ifdef X_DISPLAY
    close_display(our, dpy);
    #endif

Since we allocated our arrays dynamically, we need to release them back to the heap using the free function. We do this in the reverse order than we used malloc, so environment will come first and x_locations will come last.

    // free text display environment
    #ifdef TEXT_DISPLAY 
    int our_current_location_x;
    for(our_current_location_x = constant->environment_width - 1; 
        our_current_location_x >= 0; our_current_location_x--)
    {
        free(dpy->environment[our_current_location_x]);
    }
    free(dpy->environment);
    #endif

    // free arrays allocated in our struct
    free(our->our_num_days_infected);
    free(our->our_states);
    free(our->our_infected_y_locations);
    free(our->our_infected_x_locations);
    free(our->our_y_locations);
    free(our->our_x_locations);

    // free arrays allocated in global struct
    free(global->states);
    free(global->their_infected_x_locations);
    free(global->their_infected_y_locations);
    free(global->y_locations);
    free(global->x_locations);

Just as we initialized the MPI environment with MPI_Init, we must finalize it with MPI_Finalize(). No MPI functions are allowed to occur after MPI_Finalize.

    #ifdef _MPI
        // MPI execution is finished; no MPI calls are allowed after this
        MPI_Finalize();
    #endif