The following examples illustrate the use of derived datatypes.
Example
Send and receive a section of a 3D array.
REAL a(100,100,100), e(9,9,9)
INTEGER oneslice, twoslice, threeslice, sizeofreal, myrank, ierr
INTEGER status(MPI_STATUS_SIZE)
C extract the section a(1:17:2, 3:11, 2:10)
C and store it in e(:,:,:).
CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
CALL MPI_TYPE_EXTENT( MPI_REAL, sizeofreal, ierr)
C create datatype for a 1D section
CALL MPI_TYPE_VECTOR( 9, 1, 2, MPI_REAL, oneslice, ierr)
C create datatype for a 2D section
CALL MPI_TYPE_HVECTOR(9, 1, 100*sizeofreal, oneslice, twoslice, ierr)
C create datatype for the entire section
CALL MPI_TYPE_HVECTOR( 9, 1, 100*100*sizeofreal, twoslice,
threeslice, ierr)
CALL MPI_TYPE_COMMIT( threeslice, ierr)
CALL MPI_SENDRECV(a(1,3,2), 1, threeslice, myrank, 0, e, 9*9*9,
MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)
Example
Copy the (strictly) lower triangular part of a matrix.

Example
Transpose a matrix.
REAL a(100,100), b(100,100)
INTEGER row, xpose, sizeofreal, myrank, ierr
INTEGER status(MPI_STATUS_SIZE)
C transpose matrix a onto b
CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
CALL MPI_TYPE_EXTENT( MPI_REAL, sizeofreal, ierr)
C create datatype for one row
CALL MPI_TYPE_VECTOR( 100, 1, 100, MPI_REAL, row, ierr)
C create datatype for matrix in row-major order
CALL MPI_TYPE_HVECTOR( 100, 1, sizeofreal, row, xpose, ierr)
CALL MPI_TYPE_COMMIT( xpose, ierr)
C send matrix in row-major order and receive in column major order
CALL MPI_SENDRECV( a, 1, xpose, myrank, 0, b, 100*100,
MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)
Example
Another approach to the transpose problem:
REAL a(100,100), b(100,100)
INTEGER disp(2), blocklen(2), type(2), row, row1, sizeofreal
INTEGER myrank, ierr
INTEGER status(MPI_STATUS_SIZE)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
C transpose matrix a onto b
CALL MPI_TYPE_EXTENT( MPI_REAL, sizeofreal, ierr)
C create datatype for one row
CALL MPI_TYPE_VECTOR( 100, 1, 100, MPI_REAL, row, ierr)
C create datatype for one row, with the extent of one real number
disp(1) = 0
disp(2) = sizeofreal
type(1) = row
type(2) = MPI_UB
blocklen(1) = 1
blocklen(2) = 1
CALL MPI_TYPE_STRUCT( 2, blocklen, disp, type, row1, ierr)
CALL MPI_TYPE_COMMIT( row1, ierr)
C send 100 rows and receive in column major order
CALL MPI_SENDRECV( a, 100, row1, myrank, 0, b, 100*100,
MPI_REAL, myrank, 0, MPI_COMM_WORLD, status, ierr)
Example
We manipulate an array of structures.

Example
The same manipulations as in the previous example, but use absolute
addresses in datatypes.

Example
Handling of unions.

Example
This
example shows how a datatype can be decoded. The routine
printdatatype prints out the elements of the datatype. Note the use
of MPI_Type_free for datatypes that are not predefined.
/*
Example of decoding a datatype.
Returns 0 if the datatype is predefined, 1 otherwise
*/
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int printdatatype( MPI_Datatype datatype )
{
int *array_of_ints;
MPI_Aint *array_of_adds;
MPI_Datatype *array_of_dtypes;
int num_ints, num_adds, num_dtypes, combiner;
int i;
MPI_Type_get_envelope( datatype,
&num_ints, &num_adds, &num_dtypes, &combiner );
switch (combiner) {
case MPI_COMBINER_NAMED:
printf( "Datatype is named:" );
/* To print the specific type, we can match against the
predefined forms. We can NOT use a switch statement here
We could also use MPI_TYPE_GET_NAME if we prefered to use
names that the user may have changed.
*/
if (datatype == MPI_INT) printf( "MPI_INT\n" );
else if (datatype == MPI_DOUBLE) printf( "MPI_DOUBLE\n" );
... else test for other types ...
return 0;
break;
case MPI_COMBINER_STRUCT:
case MPI_COMBINER_STRUCT_INTEGER:
printf( "Datatype is struct containing" );
array_of_ints = (int *)malloc( num_ints * sizeof(int) );
array_of_adds =
(MPI_Aint *) malloc( num_adds * sizeof(MPI_Aint) );
array_of_dtypes = (MPI_Datatype *)
malloc( num_dtypes * sizeof(MPI_Datatype) );
MPI_Type_get_contents( datatype, num_ints, num_adds, num_dtypes,
array_of_ints, array_of_adds, array_of_dtypes );
printf( " %d datatypes:\n", array_of_ints[0] );
for (i=0; i<array_of_ints[0]; i++) {
printf( "blocklength %d, displacement %ld, type:\n",
array_of_ints[i+1], array_of_adds[i] );
if (printdatatype( array_of_dtypes[i] )) {
/* Note that we free the type ONLY if it
is not predefined */
MPI_Type_free( &array_of_dtypes[i] );
}
}
free( array_of_ints );
free( array_of_adds );
free( array_of_dtypes );
break;
... other combiner values ...
default:
printf( "Unrecognized combiner type\n" );
}
return 1;
}