MPI supports passing Fortran entities of BIND(C) and SEQUENCE derived types to choice dummy arguments, provided no type component has the ALLOCATABLE or POINTER attribute.
The following code fragment shows
some possible ways to send scalars or arrays of interoperable
derived type in Fortran. The example assumes that all data is passed by address.
type, BIND(C) :: mytype integer :: i real :: x double precision :: d logical :: l end type mytype type(mytype) :: foo, fooarr(5) integer :: blocklen(4), type(4) integer(KIND=MPI_ADDRESS_KIND) :: disp(4), base, lb, extent call MPI_GET_ADDRESS(foo%i, disp(1), ierr) call MPI_GET_ADDRESS(foo%x, disp(2), ierr) call MPI_GET_ADDRESS(foo%d, disp(3), ierr) call MPI_GET_ADDRESS(foo%l, disp(4), ierr) base = disp(1) disp(1) = disp(1) - base disp(2) = disp(2) - base disp(3) = disp(3) - base disp(4) = disp(4) - base blocklen(1) = 1 blocklen(2) = 1 blocklen(3) = 1 blocklen(4) = 1 type(1) = MPI_INTEGER type(2) = MPI_REAL type(3) = MPI_DOUBLE_PRECISION type(4) = MPI_LOGICAL call MPI_TYPE_CREATE_STRUCT(4, blocklen, disp, type, newtype, ierr) call MPI_TYPE_COMMIT(newtype, ierr) call MPI_SEND(foo%i, 1, newtype, dest, tag, comm, ierr) ! or call MPI_SEND(foo, 1, newtype, dest, tag, comm, ierr) ! expects that base == address(foo%i) == address(foo) call MPI_GET_ADDRESS(fooarr(1), disp(1), ierr) call MPI_GET_ADDRESS(fooarr(2), disp(2), ierr) extent = disp(2) - disp(1) lb = 0 call MPI_TYPE_CREATE_RESIZED(newtype, lb, extent, newarrtype, ierr) call MPI_TYPE_COMMIT(newarrtype, ierr) call MPI_SEND(fooarr, 5, newarrtype, dest, tag, comm, ierr)Using the derived type variable foo instead of its first basic type element foo%i may be impossible if the MPI library implements choice buffer arguments through overloading instead of using TYPE(*), DIMENSION(..), or through a non-standardized extension such as !$PRAGMA IGNORE_TKR; see Section MPI for Different Fortran Standard Versions .
To use a derived type in an array requires a correct extent of the datatype handle to take care of the alignment rules applied by the compiler. These alignment rules may imply that there are gaps between the components of a derived type, and also between the subsuquent elements of an array of a derived type. The extent of an interoperable derived type (i.e., defined with BIND(C)) and a SEQUENCE derived type with the same content may be different because C and Fortran may apply different alignment rules. As recommended in the advice to users in Section Lower-Bound and Upper-Bound Markers , one should add an additional fifth structure element with one numerical storage unit at the end of this structure to force in most cases that the array of structures is contiguous. Even with such an additional element, one should keep this resizing due to the special alignment rules that can be used by the compiler for structures, as also mentioned in this advice.
Using the extended semantics defined in TS 29113, it is also possible to use entities or derived types without either the BIND(C) or the SEQUENCE attribute as choice buffer arguments; some additional constraints must be observed, e.g., no ALLOCATABLE or POINTER type components may exist. In this case, the base address in the example must be changed to become the address of foo instead of foo%i, because the Fortran compiler may rearrange type components or add padding. Sending the structure foo should then also be performed by providing it (and not foo%i) as actual argument for MPI_Send.