This example is more subtle that it appears. A very simple solution might try something like this
	MPI_Send( to up process );
	MPI_Send( to down process);
	MPI_Recv( from down process );
	MPI_Recv( from up process );
But this depends on MPI being able to buffer the data in each send before the receives take place.

Because the domain is not periodic, even if MPI_Send requires buffering, the program will complete. However, it may take longer to send the data than you might expect.

Also note the use of MPI_Reduce to collect the errors at process zero, and the output of the result before MPI_Finalize is called (the MPI standard does specify what happens after MPI_Finalize).

Different tag values are used for the two messages. While this is not necessary in this case (the MPI requirement on message ordering, combined with the source selection, is sufficient), it is good practice, and can help identify problems. Note that if MPI_ANY_SOURCE were used in the MPI_Recv calls instead of a specific source, different tag values would be necessary.