1

I've defined a type called "chart":

Type :: chart
  Character(len=32) :: title
  Character(len=32) :: xAxis
  Character(len=32) :: yAxis
  Real(kind=DoubleReal) :: xMin=1.1D99
  Real(kind=DoubleReal) :: xMax=-1.1D99
  Real(kind=DoubleReal) :: yMin=1.1D99
  Real(kind=DoubleReal) :: yMax=-1.1D99
  Logical :: cleanPyFile=.true.
End Type  

I'd like to know how to send a user defined variable from one process to another using Fortran with MPI libraries.

benpalmer
  • 21
  • 3
  • Hi thanks for replying. I want to be able to to write a subroutine to distribute a variable of type chart (for example) from the 0 process to all other processes. The way I planned to do it is loop through the parts of the chart variable and send each part separately. I haven't tried anything else as yet. – benpalmer Jun 24 '15 at 15:17
  • Hi. I was interested in knowing if there was a method of looping through the elements of a defined type for other reasons, but yes I would also like to know how to send and receive defined data types in Fortran with MPI subroutines. – benpalmer Jun 24 '15 at 17:36
  • 1
    Related, but in a different language http://stackoverflow.com/questions/18992701/mpi-c-derived-types-struct-of-vectors – Vladimir F Героям слава Jun 24 '15 at 18:20
  • 1
    You'd use `mpi derived types`, which are covered extensively in Qs and As here on SO, and in several online tutorials. The only reason this question is not a duplicate of the one @VladimirF points you towards is that that is about derived types in C. – High Performance Mark Jun 24 '15 at 20:10

1 Answers1

1

Thank you for the replies and the suggested reading. I've looked at the C++ topic and I've also found information on the subroutines at open-mpi.org and how to use them computing.llnl.gov.

I've just put together a subroutine that's part of the program I'm writing, and it's a bit rough around the edges, but it works:

    Module typesM

    ! Setup Modules  
      Use kinds
    ! Force declaration of all variables
      Implicit None
    ! Include MPI header
      Include 'mpif.h'
    ! Declare global variables
    ! Privacy of functions/subroutines/variables
      Private
    ! Public subroutines  
      Public :: SetUpMPITypes

      Contains

      Subroutine SetUpMPITypes()  
        Implicit None   ! Force declaration of all variables
    ! Private variables
        Integer(kind=StandardInteger) :: error
        Integer(kind=StandardInteger) :: iExtent, rExtent, dpExtent
        Integer(kind=StandardInteger) :: elementTypes(0:1), blockCounts(0:1), blockOffset(0:1)
        Integer(kind=StandardInteger) :: rssConfigID
        Integer(kind=StandardInteger) :: mpiProcessCount, mpiProcessID
        Integer(kind=StandardInteger) :: i, processTo, processFrom, tag
        Integer, Dimension(MPI_STATUS_SIZE) :: status
    ! Define my rssConfig type in Fortran
        Type :: rssConfig
          sequence
          Real(kind=DoubleReal) :: total=0.0D0
          Real(kind=DoubleReal) :: energy=0.0D0
          Real(kind=DoubleReal) :: force=0.0D0
          Real(kind=DoubleReal) :: stress=0.0D0
          Integer(kind=StandardInteger) :: n
        End Type rssConfig
    ! Declare rssTest as rssConfig type
        Type (rssConfig) :: rssTest  
    ! Extent of data types
        Call MPI_TYPE_EXTENT(MPI_INTEGER, iExtent, error)
        Call MPI_TYPE_EXTENT(MPI_REAL, rExtent, error)
        Call MPI_TYPE_EXTENT(MPI_DOUBLE_PRECISION, dpExtent, error)    
    ! Block 1
        blockCounts(0) = 4
        blockOffset(0) = 0
        elementTypes(0) = MPI_DOUBLE_PRECISION
    ! Block 2
        blockCounts(1) = 1 
        blockOffset(1) = 4 * dpExtent
        elementTypes(1) = MPI_INTEGER
    ! Make mpi structure
        call MPI_TYPE_STRUCT(2, blockCounts, blockOffset, elementTypes, rssConfigID, error)
        call MPI_TYPE_COMMIT(rssConfigID, error)
    ! Get process ID and total mpi process count
        Call MPI_Comm_size(MPI_COMM_WORLD ,mpiProcessCount,error)
        Call MPI_Comm_rank(MPI_COMM_WORLD,mpiProcessID,error)
    ! Set values on the root process    
        If(mpiProcessID.eq.0)Then
          rssTest%total = 8.1D0
        End If
    ! wait and print out    
        call sleep(1)
        print *,mpiProcessID,rssTest%total
    ! Send from root to workers using rssConfig type
        If(mpiProcessID.eq.0)Then
          Do i=1,(mpiProcessCount-1)
            processTo = i
            tag = 114 + i
            Call MPI_SEND(rssTest,1,rssConfigID,processTo,tag,MPI_COMM_WORLD,error)
          End Do
        End If
    ! Recieve by worker processes from root process
        If(mpiProcessID.gt.0)Then
          processFrom = 0
          tag = 114 + mpiProcessID
          Call MPI_RECV(rssTest,1,rssConfigID,processFrom,tag,MPI_COMM_WORLD,status,error)
        End If  
    ! wait and printout
        call sleep(1)
        print *,mpiProcessID,rssTest%total  
      End Subroutine SetUpMPITypes

    End Module typesM

Thank you for the advice. I'm going to try to use the MPI_TYPE_CREATE_STRUCT subroutine in the future, but I haven't got it working yet.

mort
  • 12,988
  • 14
  • 52
  • 97
benpalmer
  • 21
  • 3