/*
 * 01-hello-mpi.c  —  Your FIRST MPI program
 * Session 11 · 2311CSC501J Parallel Processing
 *
 * WHAT THIS SHOWS
 *   OpenMP (Session 03/10) forked THREADS that shared one memory. MPI is different:
 *   `mpirun -np 4` launches 4 separate PROCESSES, each a full copy of this program,
 *   each with its OWN private memory. They are NOT threads — they cannot see each
 *   other's variables. The only way they cooperate is by passing MESSAGES.
 *
 *   Every process gets two numbers from MPI:
 *     - its RANK  : a unique id, 0 .. size-1 (like a jersey number)
 *     - the SIZE  : how many processes there are in total
 *   This is the SPMD model: Single Program, Multiple Data. One source file, run by
 *   many processes, and each behaves differently based on its rank.
 *
 *   Notice the print order is NOT fixed between runs — the processes run truly at
 *   once, on different cores/machines, and whoever reaches printf first wins.
 *
 * HOW TO COMPILE & RUN
 *   Install an MPI implementation first (Open MPI or MPICH), then:
 *       mpicc 01-hello-mpi.c -o hello
 *       mpirun -np 4 ./hello          # launch 4 processes
 *       mpirun -np 8 ./hello          # try a different process count
 *
 *   No MPI on your machine? See README.md for zero-install online options.
 *   (This CANNOT run in a browser — MPI needs real OS processes.)
 */

#include <stdio.h>
#include <mpi.h>              /* every MPI program includes this */

int main(int argc, char **argv) {
    /* MPI_Init MUST be the first MPI call. It sets up the process group and
     * hands MPI the command-line args. Nothing MPI-related works before this. */
    MPI_Init(&argc, &argv);

    int rank, size;

    /* Which process am I? Fills `rank` with 0 .. size-1.
     * MPI_COMM_WORLD is the "communicator" — the group of ALL processes. */
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    /* How many of us are there in total? Fills `size`. */
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    /* Every process runs this line, but each prints its own rank. */
    printf("Hello from rank %d of %d\n", rank, size);

    /* A common pattern: let ONE process (by convention rank 0, the "master")
     * do coordination work the others should not repeat. */
    if (rank == 0) {
        printf("[rank 0] I am the master. %d processes reported in.\n", size);
    }

    /* MPI_Finalize MUST be the last MPI call. It cleanly shuts the group down. */
    MPI_Finalize();
    return 0;
}
